ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 $ilDB;
94 
95  $result = $ilDB->queryF(
96  "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",
97  array("integer"),
98  array($question_id)
99  );
100  if ($result->numRows() == 1) {
101  $data = $ilDB->fetchAssoc($result);
102  $this->setId($question_id);
103  $this->setObjId($data["obj_fi"]);
104  $this->setTitle($data["title"]);
105  $this->setComment($data["description"]);
106  $this->setOriginalId($data["original_id"]);
107  $this->setNrOfTries($data['nr_of_tries']);
108  $this->setAuthor($data["author"]);
109  $this->setPoints($data["points"]);
110  $this->setOwner($data["owner"]);
111  include_once("./Services/RTE/classes/class.ilRTE.php");
112  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
113  $this->setOrderText($data["ordertext"]);
114  $this->setTextSize($data["textsize"]);
115  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
116 
117  try {
118  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
119  } catch (ilTestQuestionPoolException $e) {
120  }
121  }
122 
123  parent::loadFromDb($question_id);
124  }
125 
129  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
130  {
131  if ($this->id <= 0) {
132  // The question has not been saved. It cannot be duplicated
133  return;
134  }
135  // duplicate the question in database
136  $this_id = $this->getId();
137  $thisObjId = $this->getObjId();
138 
139  $clone = $this;
140  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
142  $clone->id = -1;
143 
144  if ((int) $testObjId > 0) {
145  $clone->setObjId($testObjId);
146  }
147 
148  if ($title) {
149  $clone->setTitle($title);
150  }
151 
152  if ($author) {
153  $clone->setAuthor($author);
154  }
155  if ($owner) {
156  $clone->setOwner($owner);
157  }
158 
159  if ($for_test) {
160  $clone->saveToDb($original_id);
161  } else {
162  $clone->saveToDb();
163  }
164 
165  // copy question page content
166  $clone->copyPageOfQuestion($this_id);
167  // copy XHTML media objects
168  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
169 
170  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
171 
172  return $clone->id;
173  }
174 
178  public function copyObject($target_questionpool_id, $title = "")
179  {
180  if ($this->id <= 0) {
181  // The question has not been saved. It cannot be duplicated
182  return;
183  }
184  // duplicate the question in database
185  $clone = $this;
186  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
188  $clone->id = -1;
189  $source_questionpool_id = $this->getObjId();
190  $clone->setObjId($target_questionpool_id);
191  if ($title) {
192  $clone->setTitle($title);
193  }
194  $clone->saveToDb();
195  // copy question page content
196  $clone->copyPageOfQuestion($original_id);
197  // copy XHTML media objects
198  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
199 
200  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
201 
202  return $clone->id;
203  }
204 
205  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
206  {
207  if ($this->id <= 0) {
208  // The question has not been saved. It cannot be duplicated
209  return;
210  }
211 
212  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
213 
214  $sourceQuestionId = $this->id;
215  $sourceParentId = $this->getObjId();
216 
217  // duplicate the question in database
218  $clone = $this;
219  $clone->id = -1;
220 
221  $clone->setObjId($targetParentId);
222 
223  if ($targetQuestionTitle) {
224  $clone->setTitle($targetQuestionTitle);
225  }
226 
227  $clone->saveToDb();
228  // copy question page content
229  $clone->copyPageOfQuestion($sourceQuestionId);
230  // copy XHTML media objects
231  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
232 
233  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
234 
235  return $clone->id;
236  }
237 
243  public function getMaximumPoints()
244  {
245  return $this->getPoints();
246  }
247 
258  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
259  {
260  if ($returndetails) {
261  throw new ilTestException('return details not implemented for ' . __METHOD__);
262  }
263 
264  global $ilDB;
265 
266  $found_values = array();
267  if (is_null($pass)) {
268  $pass = $this->getSolutionMaxPass($active_id);
269  }
270  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
271  $points = 0;
272  $data = $ilDB->fetchAssoc($result);
273 
274  $points = $this->calculateReachedPointsForSolution($data['value1']);
275 
276  return $points;
277  }
278 
288  public function splitAndTrimOrderElementText($in_string, $separator)
289  {
290  $result = array();
291  include_once "./Services/Utilities/classes/class.ilStr.php";
292 
293  if (ilStr::strPos($in_string, $separator) === false) {
294  $result = preg_split("/\\s+/", $in_string);
295  } else {
296  $result = explode($separator, $in_string);
297  }
298 
299  foreach ($result as $key => $value) {
300  $result[$key] = trim($value);
301  }
302 
303  return $result;
304  }
305 
306  public function getSolutionSubmit()
307  {
308  return $_POST["orderresult"];
309  }
310 
319  public function saveWorkingData($active_id, $pass = null, $authorized = true)
320  {
321  global $ilDB;
322  global $ilUser;
323 
324  if (is_null($pass)) {
325  include_once "./Modules/Test/classes/class.ilObjTest.php";
326  $pass = ilObjTest::_getPass($active_id);
327  }
328 
329  $entered_values = false;
330 
331  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $active_id, $pass, $authorized) {
332  $this->removeCurrentSolution($active_id, $pass, $authorized);
333 
334  $solutionSubmit = $this->getSolutionSubmit();
335 
336  $entered_values = false;
337  if (strlen($solutionSubmit)) {
338  $this->saveCurrentSolution($active_id, $pass, $_POST['orderresult'], null, $authorized);
339  $entered_values = true;
340  }
341  });
342 
343  if ($entered_values) {
344  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
346  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
347  }
348  } else {
349  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
351  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
352  }
353  }
354 
355  return true;
356  }
357 
359  {
360  global $ilDB;
361 
362  // save additional data
363  $ilDB->manipulateF(
364  "DELETE FROM " . $this->getAdditionalTableName()
365  . " WHERE question_fi = %s",
366  array( "integer" ),
367  array( $this->getId() )
368  );
369 
370  $ilDB->manipulateF(
371  "INSERT INTO " . $this->getAdditionalTableName()
372  . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
373  array( "integer", "text", "float" ),
374  array(
375  $this->getId(),
376  $this->getOrderText(),
377  ($this->getTextSize() < 10) ? null : $this->getTextSize()
378  )
379  );
380  }
381 
385  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
386  {
387  // nothing to rework!
388  }
389 
395  public function getQuestionType()
396  {
397  return "assOrderingHorizontal";
398  }
399 
405  public function getAdditionalTableName()
406  {
407  return "qpl_qst_horder";
408  }
409 
415  public function getAnswerTableName()
416  {
417  return "";
418  }
419 
425  public function deleteAnswers($question_id)
426  {
427  }
428 
433  public function getRTETextWithMediaObjects()
434  {
435  $text = parent::getRTETextWithMediaObjects();
436  return $text;
437  }
438 
442  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
443  {
444  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
445 
446  $solutionvalue = "";
447  $solutions =&$this->getSolutionValues($active_id, $pass);
448  $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
449  $i = 1;
450  $worksheet->setCell($startrow+$i, 0, $solutionvalue);
451  $i++;
452 
453  return $startrow + $i + 1;
454  }
455 
468  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
469  {
470  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
471  $import = new assOrderingHorizontalImport($this);
472  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
473  }
474 
481  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
482  {
483  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
484  $export = new assOrderingHorizontalExport($this);
485  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
486  }
487 
493  public function getBestSolution($active_id, $pass)
494  {
495  $user_solution = array();
496  return $user_solution;
497  }
498 
504  public function getOrderingElements()
505  {
506  return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
507  }
508 
514  public function getRandomOrderingElements()
515  {
516  $elements = $this->getOrderingElements();
517  $elements = $this->getShuffler()->shuffle($elements);
518  return $elements;
519  }
520 
526  public function getOrderText()
527  {
528  return $this->ordertext;
529  }
530 
536  public function setOrderText($a_value)
537  {
538  $this->ordertext = $a_value;
539  }
540 
546  public function getTextSize()
547  {
548  return $this->textsize;
549  }
550 
556  public function setTextSize($a_value)
557  {
558  if ($a_value >= 10) {
559  $this->textsize = $a_value;
560  }
561  }
562 
568  public function getSeparator()
569  {
570  return $this->separator;
571  }
572 
578  public function setSeparator($a_value)
579  {
580  $this->separator = $a_value;
581  }
582 
586  public function __get($value)
587  {
588  switch ($value) {
589  case "ordertext":
590  return $this->getOrderText();
591  break;
592  case "textsize":
593  return $this->getTextSize();
594  break;
595  case "separator":
596  return $this->getSeparator();
597  break;
598  default:
599  return parent::__get($value);
600  break;
601  }
602  }
603 
607  public function __set($key, $value)
608  {
609  switch ($key) {
610  case "ordertext":
611  $this->setOrderText($value);
612  break;
613  case "textsize":
614  $this->setTextSize($value);
615  break;
616  case "separator":
617  $this->setSeparator($value);
618  break;
619  default:
620  parent::__set($key, $value);
621  break;
622  }
623  }
624 
625  public function supportsJavascriptOutput()
626  {
627  return true;
628  }
629 
630  public function supportsNonJsOutput()
631  {
632  return false;
633  }
634 
638  public function toJSON()
639  {
640  include_once("./Services/RTE/classes/class.ilRTE.php");
641  $result = array();
642  $result['id'] = (int) $this->getId();
643  $result['type'] = (string) $this->getQuestionType();
644  $result['title'] = (string) $this->getTitle();
645  $result['question'] = $this->formatSAQuestion($this->getQuestion());
646  $result['nr_of_tries'] = (int) $this->getNrOfTries();
647  $result['shuffle'] = (bool) true;
648  $result['points'] = (bool) $this->getPoints();
649  $result['textsize'] = ((int) $this->getTextSize()) // #10923
650  ? (int) $this->getTextSize()
651  : 100;
652  $result['feedback'] = array(
653  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
654  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
655  );
656 
657  $arr = array();
658  foreach ($this->getOrderingElements() as $order => $answer) {
659  array_push($arr, array(
660  "answertext" => (string) $answer,
661  "order" => (int) $order+1
662  ));
663  }
664  $result['answers'] = $arr;
665 
666  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
667  $result['mobs'] = $mobs;
668 
669  return json_encode($result);
670  }
671 
680  public function getOperators($expression)
681  {
682  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
684  }
685 
690  public function getExpressionTypes()
691  {
692  return array(
697  );
698  }
699 
708  public function getUserQuestionResult($active_id, $pass)
709  {
711  global $ilDB;
712  $result = new ilUserQuestionResult($this, $active_id, $pass);
713 
714  $maxStep = $this->lookupMaxStep($active_id, $pass);
715 
716  if ($maxStep !== null) {
717  $data = $ilDB->queryF(
718  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
719  array("integer", "integer", "integer","integer"),
720  array($active_id, $pass, $this->getId(), $maxStep)
721  );
722  } else {
723  $data = $ilDB->queryF(
724  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
725  array("integer", "integer", "integer"),
726  array($active_id, $pass, $this->getId())
727  );
728  }
729  $row = $ilDB->fetchAssoc($data);
730 
731  $answer_elements = $this->splitAndTrimOrderElementText($row["value1"], $this->answer_separator);
732  $elements = $this->getOrderingElements();
733  $solutions = array();
734 
735  foreach ($answer_elements as $answer) {
736  foreach ($elements as $key => $element) {
737  if ($element == $answer) {
738  $result->addKeyValue($key+1, $answer);
739  }
740  }
741  }
742 
743  $glue = " ";
744  if ($this->answer_separator = '{::}') {
745  $glue = "";
746  }
747  $result->addKeyValue(null, join($glue, $answer_elements));
748 
749  $points = $this->calculateReachedPoints($active_id, $pass);
750  $max_points = $this->getMaximumPoints();
751 
752  $result->setReachedPercentage(($points/$max_points) * 100);
753 
754  return $result;
755  }
756 
765  public function getAvailableAnswerOptions($index = null)
766  {
767  $elements = $this->getOrderingElements();
768  if ($index !== null) {
769  if (array_key_exists($index, $elements)) {
770  return $elements[$index];
771  }
772  return null;
773  } else {
774  return $elements;
775  }
776  }
777 
782  protected function calculateReachedPointsForSolution($value)
783  {
784  $value = $this->splitAndTrimOrderElementText($value, $this->answer_separator);
785  $value = join($value, $this->answer_separator);
786  if (strcmp($value, join($this->getOrderingElements(), $this->answer_separator)) == 0) {
787  $points = $this->getPoints();
788  return $points;
789  }
790  return 0;
791  }
792 
793  // fau: testNav - new function getTestQuestionConfig()
798  // hey: refactored identifiers
799  public function buildTestPresentationConfig()
800  // hey.
801  {
802  // hey: refactored identifiers
803  return parent::buildTestPresentationConfig()
804  // hey.
805  ->setIsUnchangedAnswerPossible(true)
806  ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
807  }
808  // fau.
809 }
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getId()
Gets the id of the assQuestion object.
Add rich text string
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.
$worksheet
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.
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.
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
{}
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.
Create styles array
The data for the language used.
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.
getOrderingElements()
Get ordering elements from order text.
getOperators($expression)
Get all available operations for a specific question.