ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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  ) {
47  parent::__construct($title, $comment, $author, $owner, $question);
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 {
119  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
120  } catch (ilTestQuestionPoolException $e) {
121  }
122  }
123 
124  parent::loadFromDb($question_id);
125  }
126 
130  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
131  {
132  if ($this->id <= 0) {
133  // The question has not been saved. It cannot be duplicated
134  return;
135  }
136  // duplicate the question in database
137  $this_id = $this->getId();
138  $thisObjId = $this->getObjId();
139 
140  $clone = $this;
141  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
143  $clone->id = -1;
144 
145  if ((int) $testObjId > 0) {
146  $clone->setObjId($testObjId);
147  }
148 
149  if ($title) {
150  $clone->setTitle($title);
151  }
152 
153  if ($author) {
154  $clone->setAuthor($author);
155  }
156  if ($owner) {
157  $clone->setOwner($owner);
158  }
159 
160  if ($for_test) {
161  $clone->saveToDb($original_id);
162  } else {
163  $clone->saveToDb();
164  }
165 
166  // copy question page content
167  $clone->copyPageOfQuestion($this_id);
168  // copy XHTML media objects
169  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
170 
171  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
172 
173  return $clone->id;
174  }
175 
179  public function copyObject($target_questionpool_id, $title = "")
180  {
181  if ($this->id <= 0) {
182  // The question has not been saved. It cannot be duplicated
183  return;
184  }
185  // duplicate the question in database
186  $clone = $this;
187  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
189  $clone->id = -1;
190  $source_questionpool_id = $this->getObjId();
191  $clone->setObjId($target_questionpool_id);
192  if ($title) {
193  $clone->setTitle($title);
194  }
195  $clone->saveToDb();
196  // copy question page content
197  $clone->copyPageOfQuestion($original_id);
198  // copy XHTML media objects
199  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
200 
201  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
202 
203  return $clone->id;
204  }
205 
206  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
207  {
208  if ($this->id <= 0) {
209  // The question has not been saved. It cannot be duplicated
210  return;
211  }
212 
213  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
214 
215  $sourceQuestionId = $this->id;
216  $sourceParentId = $this->getObjId();
217 
218  // duplicate the question in database
219  $clone = $this;
220  $clone->id = -1;
221 
222  $clone->setObjId($targetParentId);
223 
224  if ($targetQuestionTitle) {
225  $clone->setTitle($targetQuestionTitle);
226  }
227 
228  $clone->saveToDb();
229  // copy question page content
230  $clone->copyPageOfQuestion($sourceQuestionId);
231  // copy XHTML media objects
232  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
233 
234  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
235 
236  return $clone->id;
237  }
238 
244  public function getMaximumPoints()
245  {
246  return $this->getPoints();
247  }
248 
259  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
260  {
261  if ($returndetails) {
262  throw new ilTestException('return details not implemented for ' . __METHOD__);
263  }
264 
265  global $DIC;
266  $ilDB = $DIC['ilDB'];
267 
268  $found_values = array();
269  if (is_null($pass)) {
270  $pass = $this->getSolutionMaxPass($active_id);
271  }
272  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
273  $points = 0;
274  $data = $ilDB->fetchAssoc($result);
275 
276  $points = $this->calculateReachedPointsForSolution($data['value1']);
277 
278  return $points;
279  }
280 
290  public function splitAndTrimOrderElementText($in_string, $separator)
291  {
292  $result = array();
293  include_once "./Services/Utilities/classes/class.ilStr.php";
294 
295  if (ilStr::strPos($in_string, $separator) === false) {
296  $result = preg_split("/\\s+/", $in_string);
297  } else {
298  $result = explode($separator, $in_string);
299  }
300 
301  foreach ($result as $key => $value) {
302  $result[$key] = trim($value);
303  }
304 
305  return $result;
306  }
307 
308  public function getSolutionSubmit()
309  {
310  return $_POST["orderresult"];
311  }
312 
321  public function saveWorkingData($active_id, $pass = null, $authorized = true)
322  {
323  global $DIC;
324  $ilDB = $DIC['ilDB'];
325  $ilUser = $DIC['ilUser'];
326 
327  if (is_null($pass)) {
328  include_once "./Modules/Test/classes/class.ilObjTest.php";
329  $pass = ilObjTest::_getPass($active_id);
330  }
331 
332  $entered_values = false;
333 
334  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $active_id, $pass, $authorized) {
335  $this->removeCurrentSolution($active_id, $pass, $authorized);
336 
337  $solutionSubmit = $this->getSolutionSubmit();
338 
339  $entered_values = false;
340  if (strlen($solutionSubmit)) {
341  $this->saveCurrentSolution($active_id, $pass, $_POST['orderresult'], null, $authorized);
342  $entered_values = true;
343  }
344  });
345 
346  if ($entered_values) {
347  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
349  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
350  }
351  } else {
352  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
354  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
355  }
356  }
357 
358  return true;
359  }
360 
362  {
363  global $DIC;
364  $ilDB = $DIC['ilDB'];
365 
366  // save additional data
367  $ilDB->manipulateF(
368  "DELETE FROM " . $this->getAdditionalTableName()
369  . " WHERE question_fi = %s",
370  array( "integer" ),
371  array( $this->getId() )
372  );
373 
374  $ilDB->manipulateF(
375  "INSERT INTO " . $this->getAdditionalTableName()
376  . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
377  array( "integer", "text", "float" ),
378  array(
379  $this->getId(),
380  $this->getOrderText(),
381  ($this->getTextSize() < 10) ? null : $this->getTextSize()
382  )
383  );
384  }
385 
391  public function getQuestionType()
392  {
393  return "assOrderingHorizontal";
394  }
395 
401  public function getAdditionalTableName()
402  {
403  return "qpl_qst_horder";
404  }
405 
411  public function getAnswerTableName()
412  {
413  return "";
414  }
415 
421  public function deleteAnswers($question_id)
422  {
423  }
424 
429  public function getRTETextWithMediaObjects()
430  {
431  $text = parent::getRTETextWithMediaObjects();
432  return $text;
433  }
434 
438  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
439  {
440  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
441 
442  $solutionvalue = "";
443  $solutions = &$this->getSolutionValues($active_id, $pass);
444  $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
445  $i = 1;
446  $worksheet->setCell($startrow + $i, 0, $solutionvalue);
447  $i++;
448 
449  return $startrow + $i + 1;
450  }
451 
464  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
465  {
466  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
467  $import = new assOrderingHorizontalImport($this);
468  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
469  }
470 
477  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
478  {
479  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
480  $export = new assOrderingHorizontalExport($this);
481  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
482  }
483 
489  public function getBestSolution($active_id, $pass)
490  {
491  $user_solution = array();
492  return $user_solution;
493  }
494 
500  public function getOrderingElements()
501  {
502  return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
503  }
504 
510  public function getRandomOrderingElements()
511  {
512  $elements = $this->getOrderingElements();
513  $elements = $this->getShuffler()->shuffle($elements);
514  return $elements;
515  }
516 
522  public function getOrderText()
523  {
524  return $this->ordertext;
525  }
526 
532  public function setOrderText($a_value)
533  {
534  $this->ordertext = $a_value;
535  }
536 
542  public function getTextSize()
543  {
544  return $this->textsize;
545  }
546 
552  public function setTextSize($a_value)
553  {
554  if ($a_value >= 10) {
555  $this->textsize = $a_value;
556  }
557  }
558 
564  public function getSeparator()
565  {
566  return $this->separator;
567  }
568 
574  public function setSeparator($a_value)
575  {
576  $this->separator = $a_value;
577  }
578 
582  public function __get($value)
583  {
584  switch ($value) {
585  case "ordertext":
586  return $this->getOrderText();
587  break;
588  case "textsize":
589  return $this->getTextSize();
590  break;
591  case "separator":
592  return $this->getSeparator();
593  break;
594  default:
595  return parent::__get($value);
596  break;
597  }
598  }
599 
603  public function __set($key, $value)
604  {
605  switch ($key) {
606  case "ordertext":
607  $this->setOrderText($value);
608  break;
609  case "textsize":
610  $this->setTextSize($value);
611  break;
612  case "separator":
613  $this->setSeparator($value);
614  break;
615  default:
616  parent::__set($key, $value);
617  break;
618  }
619  }
620 
621  public function supportsJavascriptOutput()
622  {
623  return true;
624  }
625 
626  public function supportsNonJsOutput()
627  {
628  return false;
629  }
630 
634  public function toJSON()
635  {
636  include_once("./Services/RTE/classes/class.ilRTE.php");
637  $result = array();
638  $result['id'] = (int) $this->getId();
639  $result['type'] = (string) $this->getQuestionType();
640  $result['title'] = (string) $this->getTitle();
641  $result['question'] = $this->formatSAQuestion($this->getQuestion());
642  $result['nr_of_tries'] = (int) $this->getNrOfTries();
643  $result['shuffle'] = (bool) true;
644  $result['points'] = (bool) $this->getPoints();
645  $result['textsize'] = ((int) $this->getTextSize()) // #10923
646  ? (int) $this->getTextSize()
647  : 100;
648  $result['feedback'] = array(
649  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
650  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
651  );
652 
653  $arr = array();
654  foreach ($this->getOrderingElements() as $order => $answer) {
655  array_push($arr, array(
656  "answertext" => (string) $answer,
657  "order" => (int) $order + 1
658  ));
659  }
660  $result['answers'] = $arr;
661 
662  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
663  $result['mobs'] = $mobs;
664 
665  return json_encode($result);
666  }
667 
676  public function getOperators($expression)
677  {
678  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
680  }
681 
686  public function getExpressionTypes()
687  {
688  return array(
693  );
694  }
695 
704  public function getUserQuestionResult($active_id, $pass)
705  {
707  global $DIC;
708  $ilDB = $DIC['ilDB'];
709  $result = new ilUserQuestionResult($this, $active_id, $pass);
710 
711  $maxStep = $this->lookupMaxStep($active_id, $pass);
712 
713  if ($maxStep !== null) {
714  $data = $ilDB->queryF(
715  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
716  array("integer", "integer", "integer","integer"),
717  array($active_id, $pass, $this->getId(), $maxStep)
718  );
719  } else {
720  $data = $ilDB->queryF(
721  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
722  array("integer", "integer", "integer"),
723  array($active_id, $pass, $this->getId())
724  );
725  }
726  $row = $ilDB->fetchAssoc($data);
727 
728  $answer_elements = $this->splitAndTrimOrderElementText($row["value1"], $this->answer_separator);
729  $elements = $this->getOrderingElements();
730  $solutions = array();
731 
732  foreach ($answer_elements as $answer) {
733  foreach ($elements as $key => $element) {
734  if ($element == $answer) {
735  $result->addKeyValue($key + 1, $answer);
736  }
737  }
738  }
739 
740  $glue = " ";
741  if ($this->answer_separator = '{::}') {
742  $glue = "";
743  }
744  $result->addKeyValue(null, join($glue, $answer_elements));
745 
746  $points = $this->calculateReachedPoints($active_id, $pass);
747  $max_points = $this->getMaximumPoints();
748 
749  $result->setReachedPercentage(($points / $max_points) * 100);
750 
751  return $result;
752  }
753 
762  public function getAvailableAnswerOptions($index = null)
763  {
764  $elements = $this->getOrderingElements();
765  if ($index !== null) {
766  if (array_key_exists($index, $elements)) {
767  return $elements[$index];
768  }
769  return null;
770  } else {
771  return $elements;
772  }
773  }
774 
779  protected function calculateReachedPointsForSolution($value)
780  {
781  $value = $this->splitAndTrimOrderElementText($value, $this->answer_separator);
782  $value = join($this->answer_separator, $value);
783  if (strcmp($value, join($this->answer_separator, $this->getOrderingElements())) == 0) {
784  $points = $this->getPoints();
785  return $points;
786  }
787  return 0;
788  }
789 
790  // fau: testNav - new function getTestQuestionConfig()
795  // hey: refactored identifiers
796  public function buildTestPresentationConfig()
797  // hey.
798  {
799  // hey: refactored identifiers
800  return parent::buildTestPresentationConfig()
801  // hey.
802  ->setIsUnchangedAnswerPossible(true)
803  ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
804  }
805  // fau.
806 }
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.
static strPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:30
$result
getPoints()
Returns the maximum available points for the question.
global $DIC
Definition: saml.php:7
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.
$index
Definition: metadata.php:60
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.
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)
$text
Definition: errorreport.php:18
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.
$row
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)
getQuestionType()
Returns the question type of the question.
global $ilDB
setOriginalId($original_id)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
$i
Definition: disco.tpl.php:19
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.
$key
Definition: croninfo.php:18
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.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
getAnswerTableName()
Returns the name of the answer table in the database.
$data
Definition: bench.php:6
getOrderingElements()
Get ordering elements from order text.
getOperators($expression)
Get all available operations for a specific question.