ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
8 require_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']);
126  } catch (ilTestQuestionPoolException $e) {
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 
282  $points = $this->calculateReachedPointsForSolution($data['value1']);
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 
435  public function getRTETextWithMediaObjects()
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 
516  public function getRandomOrderingElements()
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
802  public function buildTestPresentationConfig()
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 }
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getId()
Gets the id of the assQuestion object.
Class for horizontal ordering questions.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
Class iQuestionCondition.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
$data
Definition: storeScorm.php:23
static strPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:30
$result
getPoints()
Returns the maximum available points for the question.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
Abstract basic class which is to be extended by the concrete assessment question type classes...
getSeparator()
Get order text separator.
copyObject($target_questionpool_id, $title="")
Copies an assOrderingHorizontal object.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
setId($id=-1)
Sets the id of the assQuestion object.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
splitAndTrimOrderElementText($in_string, $separator)
Splits the answer string either by space(s) or the separator (eg.
setOrderText($a_value)
Set order text.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
setNrOfTries($a_nr_of_tries)
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
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...
getObjId()
Get the object id of the container object.
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
loadFromDb($question_id)
Loads a assOrderingHorizontal object from a database.
Base Exception for all Exceptions relating to Modules/Test.
$index
Definition: metadata.php:128
toJSON()
Returns a JSON representation of the question.
static _getLogLanguage()
retrieve the log language for assessment logging
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setAuthor($author="")
Sets the authors name of the assQuestion object.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assOrderingHorizontal constructor
$mobs
Class ilUserQuestionResult.
isComplete()
Returns true, if a single choice question is complete for use.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
Class for formula question question exports.
buildTestPresentationConfig()
Get the test question configuration.
getQuestion()
Gets the question string of the question object.
$ilUser
Definition: imgupload.php:18
Class for formula question imports.
setTextSize($a_value)
Set text size.
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
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...
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
getRandomOrderingElements()
Get ordering elements from order text in random sequence.
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
__set($key, $value)
Object setter.
setSeparator($a_value)
Set order text separator.
deleteAnswers($question_id)
Deletes datasets from answers tables.
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{}
setQuestion($question="")
Sets the question string of the question object.
Interface ilObjQuestionScoringAdjustable.
removeCurrentSolution($active_id, $pass, $authorized=true)
__construct(Container $dic, ilPlugin $plugin)
getQuestionType()
Returns the question type of the question.
global $ilDB
setOriginalId($original_id)
$DIC
Definition: xapitoken.php:46
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getTitle()
Gets the title string of the assQuestion object.
getExpressionTypes()
Get all available expression types for a specific question.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
saveToDb($original_id="")
Saves a assOrderingHorizontal object to a database.
setTitle($title="")
Sets the title string of the assQuestion object.
setObjId($obj_id=0)
Set the object id of the container object.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assOrderingHorizontal.
setComment($comment="")
Sets the comment string of the assQuestion object.
$_POST["username"]
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
$i
Definition: metadata.php:24
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
getAnswerTableName()
Returns the name of the answer table in the database.
getOrderingElements()
Get ordering elements from order text.
getOperators($expression)
Get all available operations for a specific question.