ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.assOrderingHorizontal.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
8require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
9
22{
23 protected $ordertext;
24 protected $textsize;
25 protected $separator = "::";
26 protected $answer_separator = '{::}';
27
40 public function __construct(
41 $title = "",
42 $comment = "",
43 $author = "",
44 $owner = -1,
45 $question = ""
46 ) {
48 $this->ordertext = "";
49 }
50
56 public function isComplete()
57 {
58 if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0)) {
59 return true;
60 } else {
61 return false;
62 }
63 }
64
69 public function saveToDb($original_id = "")
70 {
73 parent::saveToDb();
74 }
75
79 public function getAnswerSeparator()
80 {
82 }
83
84
91 public function loadFromDb($question_id)
92 {
93 global $DIC;
94 $ilDB = $DIC['ilDB'];
95
96 $result = $ilDB->queryF(
97 "SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
98 array("integer"),
99 array($question_id)
100 );
101 if ($result->numRows() == 1) {
102 $data = $ilDB->fetchAssoc($result);
103 $this->setId($question_id);
104 $this->setObjId($data["obj_fi"]);
105 $this->setTitle($data["title"]);
106 $this->setComment($data["description"]);
107 $this->setOriginalId($data["original_id"]);
108 $this->setNrOfTries($data['nr_of_tries']);
109 $this->setAuthor($data["author"]);
110 $this->setPoints($data["points"]);
111 $this->setOwner($data["owner"]);
112 include_once("./Services/RTE/classes/class.ilRTE.php");
113 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
114 $this->setOrderText($data["ordertext"]);
115 $this->setTextSize($data["textsize"]);
116 $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
117
118 try {
122 }
123
124 try {
125 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
127 }
128 }
129
130 parent::loadFromDb($question_id);
131 }
132
136 public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
137 {
138 if ($this->id <= 0) {
139 // The question has not been saved. It cannot be duplicated
140 return;
141 }
142 // duplicate the question in database
143 $this_id = $this->getId();
144 $thisObjId = $this->getObjId();
145
146 $clone = $this;
147 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
149 $clone->id = -1;
150
151 if ((int) $testObjId > 0) {
152 $clone->setObjId($testObjId);
153 }
154
155 if ($title) {
156 $clone->setTitle($title);
157 }
158
159 if ($author) {
160 $clone->setAuthor($author);
161 }
162 if ($owner) {
163 $clone->setOwner($owner);
164 }
165
166 if ($for_test) {
167 $clone->saveToDb($original_id);
168 } else {
169 $clone->saveToDb();
170 }
171
172 // copy question page content
173 $clone->copyPageOfQuestion($this_id);
174 // copy XHTML media objects
175 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
176
177 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
178
179 return $clone->id;
180 }
181
185 public function copyObject($target_questionpool_id, $title = "")
186 {
187 if ($this->id <= 0) {
188 // The question has not been saved. It cannot be duplicated
189 return;
190 }
191 // duplicate the question in database
192 $clone = $this;
193 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
195 $clone->id = -1;
196 $source_questionpool_id = $this->getObjId();
197 $clone->setObjId($target_questionpool_id);
198 if ($title) {
199 $clone->setTitle($title);
200 }
201 $clone->saveToDb();
202 // copy question page content
203 $clone->copyPageOfQuestion($original_id);
204 // copy XHTML media objects
205 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
206
207 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
208
209 return $clone->id;
210 }
211
212 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
213 {
214 if ($this->id <= 0) {
215 // The question has not been saved. It cannot be duplicated
216 return;
217 }
218
219 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
220
221 $sourceQuestionId = $this->id;
222 $sourceParentId = $this->getObjId();
223
224 // duplicate the question in database
225 $clone = $this;
226 $clone->id = -1;
227
228 $clone->setObjId($targetParentId);
229
230 if ($targetQuestionTitle) {
231 $clone->setTitle($targetQuestionTitle);
232 }
233
234 $clone->saveToDb();
235 // copy question page content
236 $clone->copyPageOfQuestion($sourceQuestionId);
237 // copy XHTML media objects
238 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
239
240 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
241
242 return $clone->id;
243 }
244
250 public function getMaximumPoints()
251 {
252 return $this->getPoints();
253 }
254
265 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
266 {
267 if ($returndetails) {
268 throw new ilTestException('return details not implemented for ' . __METHOD__);
269 }
270
271 global $DIC;
272 $ilDB = $DIC['ilDB'];
273
274 $found_values = array();
275 if (is_null($pass)) {
276 $pass = $this->getSolutionMaxPass($active_id);
277 }
278 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
279 $points = 0;
280 $data = $ilDB->fetchAssoc($result);
281
283
284 return $points;
285 }
286
296 public function splitAndTrimOrderElementText($in_string, $separator)
297 {
298 $result = array();
299 include_once "./Services/Utilities/classes/class.ilStr.php";
300
301 if (ilStr::strPos($in_string, $separator) === false) {
302 $result = preg_split("/\\s+/", $in_string);
303 } else {
304 $result = explode($separator, $in_string);
305 }
306
307 foreach ($result as $key => $value) {
308 $result[$key] = trim($value);
309 }
310
311 return $result;
312 }
313
314 public function getSolutionSubmit()
315 {
316 return $_POST["orderresult"];
317 }
318
327 public function saveWorkingData($active_id, $pass = null, $authorized = true)
328 {
329 global $DIC;
330 $ilDB = $DIC['ilDB'];
331 $ilUser = $DIC['ilUser'];
332
333 if (is_null($pass)) {
334 include_once "./Modules/Test/classes/class.ilObjTest.php";
335 $pass = ilObjTest::_getPass($active_id);
336 }
337
338 $entered_values = false;
339
340 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $active_id, $pass, $authorized) {
341 $this->removeCurrentSolution($active_id, $pass, $authorized);
342
343 $solutionSubmit = $this->getSolutionSubmit();
344
345 $entered_values = false;
346 if (strlen($solutionSubmit)) {
347 $this->saveCurrentSolution($active_id, $pass, $_POST['orderresult'], null, $authorized);
348 $entered_values = true;
349 }
350 });
351
352 if ($entered_values) {
353 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
355 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
356 }
357 } else {
358 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
360 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
361 }
362 }
363
364 return true;
365 }
366
368 {
369 global $DIC;
370 $ilDB = $DIC['ilDB'];
371
372 // save additional data
373 $ilDB->manipulateF(
374 "DELETE FROM " . $this->getAdditionalTableName()
375 . " WHERE question_fi = %s",
376 array( "integer" ),
377 array( $this->getId() )
378 );
379
380 $ilDB->manipulateF(
381 "INSERT INTO " . $this->getAdditionalTableName()
382 . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
383 array( "integer", "text", "float" ),
384 array(
385 $this->getId(),
386 $this->getOrderText(),
387 ($this->getTextSize() < 10) ? null : $this->getTextSize()
388 )
389 );
390 }
391
397 public function getQuestionType()
398 {
399 return "assOrderingHorizontal";
400 }
401
407 public function getAdditionalTableName()
408 {
409 return "qpl_qst_horder";
410 }
411
417 public function getAnswerTableName()
418 {
419 return "";
420 }
421
427 public function deleteAnswers($question_id)
428 {
429 }
430
436 {
437 $text = parent::getRTETextWithMediaObjects();
438 return $text;
439 }
440
444 public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
445 {
446 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
447
448 $solutionvalue = "";
449 $solutions = &$this->getSolutionValues($active_id, $pass);
450 $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
451 $i = 1;
452 $worksheet->setCell($startrow + $i, 0, $solutionvalue);
453 $i++;
454
455 return $startrow + $i + 1;
456 }
457
470 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
471 {
472 include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
473 $import = new assOrderingHorizontalImport($this);
474 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
475 }
476
483 public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
484 {
485 include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
486 $export = new assOrderingHorizontalExport($this);
487 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
488 }
489
495 public function getBestSolution($active_id, $pass)
496 {
497 $user_solution = array();
498 return $user_solution;
499 }
500
506 public function getOrderingElements()
507 {
508 return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
509 }
510
517 {
518 $elements = $this->getOrderingElements();
519 $elements = $this->getShuffler()->shuffle($elements);
520 return $elements;
521 }
522
528 public function getOrderText()
529 {
530 return $this->ordertext;
531 }
532
538 public function setOrderText($a_value)
539 {
540 $this->ordertext = $a_value;
541 }
542
548 public function getTextSize()
549 {
550 return $this->textsize;
551 }
552
558 public function setTextSize($a_value)
559 {
560 if ($a_value >= 10) {
561 $this->textsize = $a_value;
562 }
563 }
564
570 public function getSeparator()
571 {
572 return $this->separator;
573 }
574
580 public function setSeparator($a_value)
581 {
582 $this->separator = $a_value;
583 }
584
588 public function __get($value)
589 {
590 switch ($value) {
591 case "ordertext":
592 return $this->getOrderText();
593 break;
594 case "textsize":
595 return $this->getTextSize();
596 break;
597 case "separator":
598 return $this->getSeparator();
599 break;
600 default:
601 return parent::__get($value);
602 break;
603 }
604 }
605
609 public function __set($key, $value)
610 {
611 switch ($key) {
612 case "ordertext":
613 $this->setOrderText($value);
614 break;
615 case "textsize":
616 $this->setTextSize($value);
617 break;
618 case "separator":
619 $this->setSeparator($value);
620 break;
621 default:
622 parent::__set($key, $value);
623 break;
624 }
625 }
626
627 public function supportsJavascriptOutput()
628 {
629 return true;
630 }
631
632 public function supportsNonJsOutput()
633 {
634 return false;
635 }
636
640 public function toJSON()
641 {
642 include_once("./Services/RTE/classes/class.ilRTE.php");
643 $result = array();
644 $result['id'] = (int) $this->getId();
645 $result['type'] = (string) $this->getQuestionType();
646 $result['title'] = (string) $this->getTitle();
647 $result['question'] = $this->formatSAQuestion($this->getQuestion());
648 $result['nr_of_tries'] = (int) $this->getNrOfTries();
649 $result['shuffle'] = (bool) true;
650 $result['points'] = (bool) $this->getPoints();
651 $result['textsize'] = ((int) $this->getTextSize()) // #10923
652 ? (int) $this->getTextSize()
653 : 100;
654 $result['feedback'] = array(
655 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
656 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
657 );
658
659 $arr = array();
660 foreach ($this->getOrderingElements() as $order => $answer) {
661 array_push($arr, array(
662 "answertext" => (string) $answer,
663 "order" => (int) $order + 1
664 ));
665 }
666 $result['answers'] = $arr;
667
668 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
669 $result['mobs'] = $mobs;
670
671 return json_encode($result);
672 }
673
682 public function getOperators($expression)
683 {
684 require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
686 }
687
692 public function getExpressionTypes()
693 {
694 return array(
699 );
700 }
701
710 public function getUserQuestionResult($active_id, $pass)
711 {
713 global $DIC;
714 $ilDB = $DIC['ilDB'];
715 $result = new ilUserQuestionResult($this, $active_id, $pass);
716
717 $maxStep = $this->lookupMaxStep($active_id, $pass);
718
719 if ($maxStep !== null) {
720 $data = $ilDB->queryF(
721 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
722 array("integer", "integer", "integer","integer"),
723 array($active_id, $pass, $this->getId(), $maxStep)
724 );
725 } else {
726 $data = $ilDB->queryF(
727 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
728 array("integer", "integer", "integer"),
729 array($active_id, $pass, $this->getId())
730 );
731 }
732 $row = $ilDB->fetchAssoc($data);
733
734 $answer_elements = $this->splitAndTrimOrderElementText($row["value1"], $this->answer_separator);
735 $elements = $this->getOrderingElements();
736 $solutions = array();
737
738 foreach ($answer_elements as $answer) {
739 foreach ($elements as $key => $element) {
740 if ($element == $answer) {
741 $result->addKeyValue($key + 1, $answer);
742 }
743 }
744 }
745
746 $glue = " ";
747 if ($this->answer_separator = '{::}') {
748 $glue = "";
749 }
750 $result->addKeyValue(null, join($glue, $answer_elements));
751
752 $points = $this->calculateReachedPoints($active_id, $pass);
753 $max_points = $this->getMaximumPoints();
754
755 $result->setReachedPercentage(($points / $max_points) * 100);
756
757 return $result;
758 }
759
768 public function getAvailableAnswerOptions($index = null)
769 {
770 $elements = $this->getOrderingElements();
771 if ($index !== null) {
772 if (array_key_exists($index, $elements)) {
773 return $elements[$index];
774 }
775 return null;
776 } else {
777 return $elements;
778 }
779 }
780
785 protected function calculateReachedPointsForSolution($value)
786 {
787 $value = $this->splitAndTrimOrderElementText($value, $this->answer_separator);
788 $value = join($this->answer_separator, $value);
789 if (strcmp($value, join($this->answer_separator, $this->getOrderingElements())) == 0) {
790 $points = $this->getPoints();
791 return $points;
792 }
793 return 0;
794 }
795
796 // fau: testNav - new function getTestQuestionConfig()
801 // hey: refactored identifiers
803 // hey.
804 {
805 // hey: refactored identifiers
806 return parent::buildTestPresentationConfig()
807 // hey.
808 ->setIsUnchangedAnswerPossible(true)
809 ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
810 }
811 // fau.
812}
$result
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Class for formula question question exports.
Class for formula question imports.
Class for horizontal ordering questions.
setSeparator($a_value)
Set order text separator.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
copyObject($target_questionpool_id, $title="")
Copies an assOrderingHorizontal object.
isComplete()
Returns true, if a single choice question is complete for use.
saveToDb($original_id="")
Saves a assOrderingHorizontal object to a database.
setOrderText($a_value)
Set order text.
setTextSize($a_value)
Set text size.
getOperators($expression)
Get all available operations for a specific question.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
toJSON()
Returns a JSON representation of the question.
getAnswerTableName()
Returns the name of the answer table in the database.
loadFromDb($question_id)
Loads a assOrderingHorizontal object from a database.
getRandomOrderingElements()
Get ordering elements from order text in random sequence.
getOrderingElements()
Get ordering elements from order text.
getQuestionType()
Returns the question type of the question.
toXML($a_include_header=true, $a_include_binary=true, $a_shuffle=false, $test_output=false, $force_image_references=false)
Returns a QTI xml representation of the question and sets the internal domxml variable with the DOM X...
getSeparator()
Get order text separator.
buildTestPresentationConfig()
Get the test question configuration.
getExpressionTypes()
Get all available expression types for a specific question.
deleteAnswers($question_id)
Deletes datasets from answers tables.
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assOrderingHorizontal constructor
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
__set($key, $value)
Object setter.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
splitAndTrimOrderElementText($in_string, $separator)
Splits the answer string either by space(s) or the separator (eg.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assOrderingHorizontal.
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
Abstract basic class which is to be extended by the concrete assessment question type classes.
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
setId($id=-1)
Sets the id of the assQuestion object.
setOriginalId($original_id)
setObjId($obj_id=0)
Set the object id of the container object.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
saveQuestionDataToDb($original_id="")
getId()
Gets the id of the assQuestion object.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
getObjId()
Get the object id of the container object.
setTitle($title="")
Sets the title string of the assQuestion object.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
removeCurrentSolution($active_id, $pass, $authorized=true)
setAuthor($author="")
Sets the authors name of the assQuestion object.
getPoints()
Returns the maximum available points for the question.
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getTitle()
Gets the title string of the assQuestion object.
setPoints($a_points)
Sets the maximum available points for the question.
setComment($comment="")
Sets the comment string of the assQuestion object.
setNrOfTries($a_nr_of_tries)
getQuestion()
Gets the question string of the question object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
setQuestion($question="")
Sets the question string of the question object.
static _getLogLanguage()
retrieve the log language for assessment logging
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static strPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:30
Base Exception for all Exceptions relating to Modules/Test.
Class ilUserQuestionResult.
Class iQuestionCondition.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
Interface ilObjQuestionScoringAdjustable.
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $ilDB
$data
Definition: storeScorm.php:23
$mobs
$ilUser
Definition: imgupload.php:18
$DIC
Definition: xapitoken.php:46