ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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  function __construct(
41  $title = "",
42  $comment = "",
43  $author = "",
44  $owner = -1,
45  $question = ""
46  )
47  {
48  parent::__construct($title, $comment, $author, $owner, $question);
49  $this->ordertext = "";
50  }
51 
57  public function isComplete()
58  {
59  if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0))
60  {
61  return true;
62  }
63  else
64  {
65  return false;
66  }
67  }
68 
73  public function saveToDb($original_id = "")
74  {
77  parent::saveToDb();
78  }
79 
83  public function getAnswerSeparator()
84  {
86  }
87 
88 
95  public function loadFromDb($question_id)
96  {
97  global $ilDB;
98 
99  $result = $ilDB->queryF("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",
100  array("integer"),
101  array($question_id)
102  );
103  if ($result->numRows() == 1)
104  {
105  $data = $ilDB->fetchAssoc($result);
106  $this->setId($question_id);
107  $this->setObjId($data["obj_fi"]);
108  $this->setTitle($data["title"]);
109  $this->setComment($data["description"]);
110  $this->setOriginalId($data["original_id"]);
111  $this->setNrOfTries($data['nr_of_tries']);
112  $this->setAuthor($data["author"]);
113  $this->setPoints($data["points"]);
114  $this->setOwner($data["owner"]);
115  include_once("./Services/RTE/classes/class.ilRTE.php");
116  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
117  $this->setOrderText($data["ordertext"]);
118  $this->setTextSize($data["textsize"]);
119  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
120 
121  try
122  {
123  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
124  }
126  {
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  {
140  // The question has not been saved. It cannot be duplicated
141  return;
142  }
143  // duplicate the question in database
144  $this_id = $this->getId();
145  $thisObjId = $this->getObjId();
146 
147  $clone = $this;
148  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
150  $clone->id = -1;
151 
152  if( (int)$testObjId > 0 )
153  {
154  $clone->setObjId($testObjId);
155  }
156 
157  if ($title)
158  {
159  $clone->setTitle($title);
160  }
161 
162  if ($author)
163  {
164  $clone->setAuthor($author);
165  }
166  if ($owner)
167  {
168  $clone->setOwner($owner);
169  }
170 
171  if ($for_test)
172  {
173  $clone->saveToDb($original_id);
174  }
175  else
176  {
177  $clone->saveToDb();
178  }
179 
180  // copy question page content
181  $clone->copyPageOfQuestion($this_id);
182  // copy XHTML media objects
183  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
184 
185  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
186 
187  return $clone->id;
188  }
189 
193  public function copyObject($target_questionpool_id, $title = "")
194  {
195  if ($this->id <= 0)
196  {
197  // The question has not been saved. It cannot be duplicated
198  return;
199  }
200  // duplicate the question in database
201  $clone = $this;
202  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
204  $clone->id = -1;
205  $source_questionpool_id = $this->getObjId();
206  $clone->setObjId($target_questionpool_id);
207  if ($title)
208  {
209  $clone->setTitle($title);
210  }
211  $clone->saveToDb();
212  // copy question page content
213  $clone->copyPageOfQuestion($original_id);
214  // copy XHTML media objects
215  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
216 
217  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
218 
219  return $clone->id;
220  }
221 
222  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
223  {
224  if ($this->id <= 0)
225  {
226  // The question has not been saved. It cannot be duplicated
227  return;
228  }
229 
230  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
231 
232  $sourceQuestionId = $this->id;
233  $sourceParentId = $this->getObjId();
234 
235  // duplicate the question in database
236  $clone = $this;
237  $clone->id = -1;
238 
239  $clone->setObjId($targetParentId);
240 
241  if ($targetQuestionTitle)
242  {
243  $clone->setTitle($targetQuestionTitle);
244  }
245 
246  $clone->saveToDb();
247  // copy question page content
248  $clone->copyPageOfQuestion($sourceQuestionId);
249  // copy XHTML media objects
250  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
251 
252  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
253 
254  return $clone->id;
255  }
256 
262  public function getMaximumPoints()
263  {
264  return $this->getPoints();
265  }
266 
277  public function calculateReachedPoints($active_id, $pass = NULL, $authorizedSolution = true, $returndetails = FALSE)
278  {
279  if( $returndetails )
280  {
281  throw new ilTestException('return details not implemented for '.__METHOD__);
282  }
283 
284  global $ilDB;
285 
286  $found_values = array();
287  if (is_null($pass))
288  {
289  $pass = $this->getSolutionMaxPass($active_id);
290  }
291  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
292  $points = 0;
293  $data = $ilDB->fetchAssoc($result);
294 
295  $points = $this->calculateReachedPointsForSolution($data['value1']);
296 
297  return $points;
298  }
299 
309  public function splitAndTrimOrderElementText($in_string, $separator)
310  {
311  $result = array();
312  include_once "./Services/Utilities/classes/class.ilStr.php";
313 
314  if (ilStr::strPos($in_string, $separator) === false)
315  {
316  $result = preg_split("/\\s+/", $in_string);
317  }
318  else
319  {
320  $result = explode($separator, $in_string);
321  }
322 
323  foreach ($result as $key => $value)
324  {
325  $result[$key] = trim($value);
326  }
327 
328  return $result;
329  }
330 
331  public function getSolutionSubmit()
332  {
333  return $_POST["orderresult"];
334  }
335 
344  public function saveWorkingData($active_id, $pass = NULL, $authorized = true)
345  {
346  global $ilDB;
347  global $ilUser;
348 
349  if (is_null($pass))
350  {
351  include_once "./Modules/Test/classes/class.ilObjTest.php";
352  $pass = ilObjTest::_getPass($active_id);
353  }
354 
355  $entered_values = false;
356 
357  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function() use (&$entered_values, $active_id, $pass, $authorized) {
358 
359  $this->removeCurrentSolution($active_id, $pass, $authorized);
360 
361  $solutionSubmit = $this->getSolutionSubmit();
362 
363  $entered_values = false;
364  if (strlen($solutionSubmit))
365  {
366  $this->saveCurrentSolution($active_id, $pass, $_POST['orderresult'], null, $authorized);
367  $entered_values = true;
368  }
369 
370  });
371 
372  if ($entered_values)
373  {
374  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
376  {
377  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
378  }
379  }
380  else
381  {
382  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
384  {
385  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
386  }
387  }
388 
389  return true;
390  }
391 
393  {
394  global $ilDB;
395 
396  // save additional data
397  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName()
398  . " WHERE question_fi = %s",
399  array( "integer" ),
400  array( $this->getId() )
401  );
402 
403  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName()
404  . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
405  array( "integer", "text", "float" ),
406  array(
407  $this->getId(),
408  $this->getOrderText(),
409  ($this->getTextSize() < 10) ? NULL : $this->getTextSize()
410  )
411  );
412  }
413 
417  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
418  {
419  // nothing to rework!
420  }
421 
427  public function getQuestionType()
428  {
429  return "assOrderingHorizontal";
430  }
431 
437  public function getAdditionalTableName()
438  {
439  return "qpl_qst_horder";
440  }
441 
447  public function getAnswerTableName()
448  {
449  return "";
450  }
451 
457  public function deleteAnswers($question_id)
458  {
459  }
460 
465  public function getRTETextWithMediaObjects()
466  {
467  $text = parent::getRTETextWithMediaObjects();
468  return $text;
469  }
470 
474  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
475  {
476  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
477 
478  $solutionvalue = "";
479  $solutions =& $this->getSolutionValues($active_id, $pass);
480  $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
481  $i = 1;
482  $worksheet->setCell($startrow+$i, 0, $solutionvalue);
483  $i++;
484 
485  return $startrow + $i + 1;
486  }
487 
500  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
501  {
502  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
503  $import = new assOrderingHorizontalImport($this);
504  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
505  }
506 
513  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
514  {
515  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
516  $export = new assOrderingHorizontalExport($this);
517  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
518  }
519 
525  public function getBestSolution($active_id, $pass)
526  {
527  $user_solution = array();
528  return $user_solution;
529  }
530 
536  public function getOrderingElements()
537  {
538  return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
539  }
540 
546  public function getRandomOrderingElements()
547  {
548  $elements = $this->getOrderingElements();
549  $elements = $this->getShuffler()->shuffle($elements);
550  return $elements;
551  }
552 
558  public function getOrderText()
559  {
560  return $this->ordertext;
561  }
562 
568  public function setOrderText($a_value)
569  {
570  $this->ordertext = $a_value;
571  }
572 
578  public function getTextSize()
579  {
580  return $this->textsize;
581  }
582 
588  public function setTextSize($a_value)
589  {
590  if ($a_value >= 10)
591  {
592  $this->textsize = $a_value;
593  }
594  }
595 
601  public function getSeparator()
602  {
603  return $this->separator;
604  }
605 
611  public function setSeparator($a_value)
612  {
613  $this->separator = $a_value;
614  }
615 
619  public function __get($value)
620  {
621  switch ($value)
622  {
623  case "ordertext":
624  return $this->getOrderText();
625  break;
626  case "textsize":
627  return $this->getTextSize();
628  break;
629  case "separator":
630  return $this->getSeparator();
631  break;
632  default:
633  return parent::__get($value);
634  break;
635  }
636  }
637 
641  public function __set($key, $value)
642  {
643  switch ($key)
644  {
645  case "ordertext":
646  $this->setOrderText($value);
647  break;
648  case "textsize":
649  $this->setTextSize($value);
650  break;
651  case "separator":
652  $this->setSeparator($value);
653  break;
654  default:
655  parent::__set($key, $value);
656  break;
657  }
658  }
659 
660  public function supportsJavascriptOutput()
661  {
662  return true;
663  }
664 
665  public function supportsNonJsOutput()
666  {
667  return false;
668  }
669 
673  public function toJSON()
674  {
675  include_once("./Services/RTE/classes/class.ilRTE.php");
676  $result = array();
677  $result['id'] = (int) $this->getId();
678  $result['type'] = (string) $this->getQuestionType();
679  $result['title'] = (string) $this->getTitle();
680  $result['question'] = $this->formatSAQuestion($this->getQuestion());
681  $result['nr_of_tries'] = (int) $this->getNrOfTries();
682  $result['shuffle'] = (bool) true;
683  $result['points'] = (bool) $this->getPoints();
684  $result['textsize'] = ((int)$this->getTextSize()) // #10923
685  ? (int)$this->getTextSize()
686  : 100;
687  $result['feedback'] = array(
688  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
689  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
690  );
691 
692  $arr = array();
693  foreach ($this->getOrderingElements() as $order => $answer)
694  {
695  array_push($arr, array(
696  "answertext" => (string) $answer,
697  "order" => (int) $order+1
698  ));
699  }
700  $result['answers'] = $arr;
701 
702  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
703  $result['mobs'] = $mobs;
704 
705  return json_encode($result);
706  }
707 
716  public function getOperators($expression)
717  {
718  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
720  }
721 
726  public function getExpressionTypes()
727  {
728  return array(
733  );
734  }
735 
744  public function getUserQuestionResult($active_id, $pass)
745  {
747  global $ilDB;
748  $result = new ilUserQuestionResult($this, $active_id, $pass);
749 
750  $maxStep = $this->lookupMaxStep($active_id, $pass);
751 
752  if( $maxStep !== null )
753  {
754  $data = $ilDB->queryF(
755  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
756  array("integer", "integer", "integer","integer"),
757  array($active_id, $pass, $this->getId(), $maxStep)
758  );
759  }
760  else
761  {
762  $data = $ilDB->queryF(
763  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
764  array("integer", "integer", "integer"),
765  array($active_id, $pass, $this->getId())
766  );
767  }
768  $row = $ilDB->fetchAssoc($data);
769 
770  $answer_elements = $this->splitAndTrimOrderElementText($row["value1"], $this->answer_separator);
771  $elements = $this->getOrderingElements();
772  $solutions = array();
773 
774  foreach($answer_elements as $answer)
775  {
776  foreach($elements as $key => $element)
777  {
778  if($element == $answer)
779  {
780  $result->addKeyValue($key+1, $answer);
781  }
782  }
783  }
784 
785  $glue = " ";
786  if($this->answer_separator = '{::}')
787  {
788  $glue = "";
789  }
790  $result->addKeyValue(null, join($glue, $answer_elements));
791 
792  $points = $this->calculateReachedPoints($active_id, $pass);
793  $max_points = $this->getMaximumPoints();
794 
795  $result->setReachedPercentage(($points/$max_points) * 100);
796 
797  return $result;
798  }
799 
808  public function getAvailableAnswerOptions($index = null)
809  {
810  $elements = $this->getOrderingElements();
811  if($index !== null)
812  {
813  if(array_key_exists($index, $elements))
814  {
815  return $elements[$index];
816  }
817  return null;
818  }
819  else
820  {
821  return $elements;
822  }
823  }
824 
829  protected function calculateReachedPointsForSolution($value)
830  {
831  $value = $this->splitAndTrimOrderElementText($value, $this->answer_separator);
832  $value = join($value, $this->answer_separator);
833  if(strcmp($value, join($this->getOrderingElements(), $this->answer_separator)) == 0)
834  {
835  $points = $this->getPoints();
836  return $points;
837  }
838  return 0;
839  }
840 
841 // fau: testNav - new function getTestQuestionConfig()
846  // hey: refactored identifiers
847  public function buildTestPresentationConfig()
848  // hey.
849  {
850  // hey: refactored identifiers
851  return parent::buildTestPresentationConfig()
852  // hey.
853  ->setIsUnchangedAnswerPossible(true)
854  ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
855  }
856 // fau.
857 }
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.
$worksheet
Class iQuestionCondition.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
$result
calculateReachedPoints($active_id, $pass=NULL, $authorizedSolution=true, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
getPoints()
Returns the maximum available points for the question.
Abstract basic class which is to be extended by the concrete assessment question type classes...
static strPos($a_haystack, $a_needle, $a_offset=NULL)
Definition: class.ilStr.php:34
getSeparator()
Get order text separator.
copyObject($target_questionpool_id, $title="")
Copies an assOrderingHorizontal object.
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. ...
Add rich text string
The name of the decorator.
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.
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)
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)
saveWorkingData($active_id, $pass=NULL, $authorized=true)
Saves the learners input of the question to the database.
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...
$text
getSolutionValues($active_id, $pass=NULL, $authorized=true)
Loads solutions of a given user from the database an returns it.
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"]
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.