ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
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  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, $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);
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 = split($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)
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  $this->getProcessLocker()->requestUserSolutionUpdateLock();
356 
357  $affectedRows = $this->removeCurrentSolution($active_id, $pass);
358 
359  $solutionSubmit = $this->getSolutionSubmit();
360 
361  $entered_values = false;
362  if (strlen($solutionSubmit))
363  {
364  $affectedRows = $this->saveCurrentSolution($active_id, $pass, $_POST['orderresult'], null);
365  $entered_values = true;
366  }
367 
368  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
369 
370  if ($entered_values)
371  {
372  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
374  {
375  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
376  }
377  }
378  else
379  {
380  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
382  {
383  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
384  }
385  }
386 
387  return true;
388  }
389 
391  {
392  global $ilDB;
393 
394  // save additional data
395  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName()
396  . " WHERE question_fi = %s",
397  array( "integer" ),
398  array( $this->getId() )
399  );
400 
401  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName()
402  . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
403  array( "integer", "text", "float" ),
404  array(
405  $this->getId(),
406  $this->getOrderText(),
407  ($this->getTextSize() < 10) ? NULL : $this->getTextSize()
408  )
409  );
410  }
411 
420  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
421  {
422  // nothing to rework!
423  }
424 
430  public function getQuestionType()
431  {
432  return "assOrderingHorizontal";
433  }
434 
440  public function getAdditionalTableName()
441  {
442  return "qpl_qst_horder";
443  }
444 
450  public function getAnswerTableName()
451  {
452  return "";
453  }
454 
460  public function deleteAnswers($question_id)
461  {
462  }
463 
468  public function getRTETextWithMediaObjects()
469  {
470  $text = parent::getRTETextWithMediaObjects();
471  return $text;
472  }
473 
485  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
486  {
487  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
488  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
489  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
490 
491  $solutionvalue = "";
492  $solutions =& $this->getSolutionValues($active_id, $pass);
493  $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
494  $i = 1;
495  $worksheet->writeString($startrow+$i, 0, ilExcelUtils::_convert_text($solutionvalue));
496  $i++;
497  return $startrow + $i + 1;
498  }
499 
512  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
513  {
514  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
515  $import = new assOrderingHorizontalImport($this);
516  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
517  }
518 
525  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
526  {
527  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
528  $export = new assOrderingHorizontalExport($this);
529  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
530  }
531 
537  public function getBestSolution($active_id, $pass)
538  {
539  $user_solution = array();
540  return $user_solution;
541  }
542 
548  public function getOrderingElements()
549  {
550  return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
551  }
552 
558  public function getRandomOrderingElements()
559  {
560  $elements = $this->getOrderingElements();
561  shuffle($elements);
562  return $elements;
563  }
564 
570  public function getOrderText()
571  {
572  return $this->ordertext;
573  }
574 
580  public function setOrderText($a_value)
581  {
582  $this->ordertext = $a_value;
583  }
584 
590  public function getTextSize()
591  {
592  return $this->textsize;
593  }
594 
600  public function setTextSize($a_value)
601  {
602  if ($a_value >= 10)
603  {
604  $this->textsize = $a_value;
605  }
606  }
607 
613  public function getSeparator()
614  {
615  return $this->separator;
616  }
617 
623  public function setSeparator($a_value)
624  {
625  $this->separator = $a_value;
626  }
627 
631  public function __get($value)
632  {
633  switch ($value)
634  {
635  case "ordertext":
636  return $this->getOrderText();
637  break;
638  case "textsize":
639  return $this->getTextSize();
640  break;
641  case "separator":
642  return $this->getSeparator();
643  break;
644  default:
645  return parent::__get($value);
646  break;
647  }
648  }
649 
653  public function __set($key, $value)
654  {
655  switch ($key)
656  {
657  case "ordertext":
658  $this->setOrderText($value);
659  break;
660  case "textsize":
661  $this->setTextSize($value);
662  break;
663  case "separator":
664  $this->setSeparator($value);
665  break;
666  default:
667  parent::__set($key, $value);
668  break;
669  }
670  }
671 
672  public function supportsJavascriptOutput()
673  {
674  return true;
675  }
676 
677  public function supportsNonJsOutput()
678  {
679  return false;
680  }
681 
685  public function toJSON()
686  {
687  include_once("./Services/RTE/classes/class.ilRTE.php");
688  $result = array();
689  $result['id'] = (int) $this->getId();
690  $result['type'] = (string) $this->getQuestionType();
691  $result['title'] = (string) $this->getTitle();
692  $result['question'] = $this->formatSAQuestion($this->getQuestion());
693  $result['nr_of_tries'] = (int) $this->getNrOfTries();
694  $result['shuffle'] = (bool) true;
695  $result['points'] = (bool) $this->getPoints();
696  $result['textsize'] = ((int)$this->getTextSize()) // #10923
697  ? (int)$this->getTextSize()
698  : 100;
699  $result['feedback'] = array(
700  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
701  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
702  );
703 
704  $arr = array();
705  foreach ($this->getOrderingElements() as $order => $answer)
706  {
707  array_push($arr, array(
708  "answertext" => (string) $answer,
709  "order" => (int) $order+1
710  ));
711  }
712  $result['answers'] = $arr;
713 
714  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
715  $result['mobs'] = $mobs;
716 
717  return json_encode($result);
718  }
719 
728  public function getOperators($expression)
729  {
730  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
732  }
733 
738  public function getExpressionTypes()
739  {
740  return array(
745  );
746  }
747 
756  public function getUserQuestionResult($active_id, $pass)
757  {
759  global $ilDB;
760  $result = new ilUserQuestionResult($this, $active_id, $pass);
761 
762  $data = $ilDB->queryF(
763  "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = (
764  SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s
765  )",
766  array("integer", "integer", "integer","integer", "integer", "integer"),
767  array($active_id, $pass, $this->getId(), $active_id, $pass, $this->getId())
768  );
769  $row = $ilDB->fetchAssoc($data);
770 
771  $answer_elements = $this->splitAndTrimOrderElementText($row["value1"], $this->answer_separator);
772  $elements = $this->getOrderingElements();
773  $solutions = array();
774 
775  foreach($answer_elements as $answer)
776  {
777  foreach($elements as $key => $element)
778  {
779  if($element == $answer)
780  {
781  $result->addKeyValue($key+1, $answer);
782  }
783  }
784  }
785 
786  $glue = " ";
787  if($this->answer_separator = '{::}')
788  {
789  $glue = "";
790  }
791  $result->addKeyValue(null, join($glue, $answer_elements));
792 
793  $points = $this->calculateReachedPoints($active_id, $pass);
794  $max_points = $this->getMaximumPoints();
795 
796  $result->setReachedPercentage(($points/$max_points) * 100);
797 
798  return $result;
799  }
800 
809  public function getAvailableAnswerOptions($index = null)
810  {
811  $elements = $this->getOrderingElements();
812  if($index !== null)
813  {
814  if(array_key_exists($index, $elements))
815  {
816  return $elements[$index];
817  }
818  return null;
819  }
820  else
821  {
822  return $elements;
823  }
824  }
825 
830  protected function calculateReachedPointsForSolution($value)
831  {
832  $value = $this->splitAndTrimOrderElementText($value, $this->answer_separator);
833  $value = join($value, $this->answer_separator);
834  if(strcmp($value, join($this->getOrderingElements(), $this->answer_separator)) == 0)
835  {
836  $points = $this->getPoints();
837  return $points;
838  }
839  return 0;
840  }
841 }
getId()
Gets the id of the assQuestion object.
Class for horizontal ordering questions.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
Class iQuestionCondition.
$_POST['username']
Definition: cron.php:12
$result
getPoints()
Returns the maximum available points for the question.
reworkWorkingData($active_id, $pass, $obligationsAnswered)
Reworks the allready saved working data if neccessary.
& getSolutionValues($active_id, $pass=NULL)
Loads solutions of a given user from the database an returns it.
Abstract basic class which is to be extended by the concrete assessment question type classes...
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
_convert_text($a_text, $a_target="has been removed")
static strPos($a_haystack, $a_needle, $a_offset=NULL)
Definition: class.ilStr.php:32
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. ...
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)
_enabledAssessmentLogging()
check wether assessment logging is enabled or not
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.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setAuthor($author="")
Sets the authors name of the assQuestion object.
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assOrderingHorizontal constructor
$mobs
Class ilUserQuestionResult.
saveWorkingData($active_id, $pass=NULL)
Saves the learners input of the question to the database.
isComplete()
Returns true, if a single choice question is complete for use.
Class for formula question question exports.
getQuestion()
Gets the question string of the question object.
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.
_getLogLanguage()
retrieve the log language for assessment logging
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
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.
global $ilUser
Definition: imgupload.php:15
setQuestion($question="")
Sets the question string of the question object.
Interface ilObjQuestionScoringAdjustable.
getQuestionType()
Returns the question type of the question.
global $ilDB
setOriginalId($original_id)
logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
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.
calculateReachedPoints($active_id, $pass=NULL, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
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.
setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
Creates an Excel worksheet for the detailed cumulated results of this 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.