ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assOrderingHorizontal.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
6 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
7 
20 {
21  protected $ordertext;
22  protected $textsize;
23  protected $separator = "::";
24  protected $answer_separator = '{::}';
25 
38  function __construct(
39  $title = "",
40  $comment = "",
41  $author = "",
42  $owner = -1,
43  $question = ""
44  )
45  {
47  $this->ordertext = "";
48  }
49 
55  public function isComplete()
56  {
57  if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0))
58  {
59  return true;
60  }
61  else
62  {
63  return false;
64  }
65  }
66 
71  public function saveToDb($original_id = "")
72  {
73  global $ilDB;
74 
76 
77  // save additional data
78  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
79  array("integer"),
80  array($this->getId())
81  );
82 
83  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
84  array("integer", "text", "float"),
85  array(
86  $this->getId(),
87  $this->getOrderText(),
88  ($this->getTextSize() < 10) ? NULL : $this->getTextSize()
89  )
90  );
91 
93  }
94 
101  public function loadFromDb($question_id)
102  {
103  global $ilDB;
104 
105  $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",
106  array("integer"),
107  array($question_id)
108  );
109  if ($result->numRows() == 1)
110  {
111  $data = $ilDB->fetchAssoc($result);
112  $this->setId($question_id);
113  $this->setObjId($data["obj_fi"]);
114  $this->setTitle($data["title"]);
115  $this->setComment($data["description"]);
116  $this->setOriginalId($data["original_id"]);
117  $this->setNrOfTries($data['nr_of_tries']);
118  $this->setAuthor($data["author"]);
119  $this->setPoints($data["points"]);
120  $this->setOwner($data["owner"]);
121  include_once("./Services/RTE/classes/class.ilRTE.php");
122  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
123  $this->setOrderText($data["ordertext"]);
124  $this->setTextSize($data["textsize"]);
125  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
126  }
127 
128  parent::loadFromDb($question_id);
129  }
130 
134  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
135  {
136  if ($this->id <= 0)
137  {
138  // The question has not been saved. It cannot be duplicated
139  return;
140  }
141  // duplicate the question in database
142  $this_id = $this->getId();
143 
144  if( (int)$testObjId > 0 )
145  {
146  $thisObjId = $this->getObjId();
147  }
148 
149  $clone = $this;
150  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
152  $clone->id = -1;
153 
154  if( (int)$testObjId > 0 )
155  {
156  $clone->setObjId($testObjId);
157  }
158 
159  if ($title)
160  {
161  $clone->setTitle($title);
162  }
163 
164  if ($author)
165  {
166  $clone->setAuthor($author);
167  }
168  if ($owner)
169  {
170  $clone->setOwner($owner);
171  }
172 
173  if ($for_test)
174  {
175  $clone->saveToDb($original_id);
176  }
177  else
178  {
179  $clone->saveToDb();
180  }
181 
182  // copy question page content
183  $clone->copyPageOfQuestion($this_id);
184  // copy XHTML media objects
185  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
186  // duplicate the generic feedback
187  $clone->duplicateGenericFeedback($this_id);
188 
189  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
190 
191  return $clone->id;
192  }
193 
197  public function copyObject($target_questionpool, $title = "")
198  {
199  if ($this->id <= 0)
200  {
201  // The question has not been saved. It cannot be duplicated
202  return;
203  }
204  // duplicate the question in database
205  $clone = $this;
206  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
208  $clone->id = -1;
209  $source_questionpool = $this->getObjId();
210  $clone->setObjId($target_questionpool);
211  if ($title)
212  {
213  $clone->setTitle($title);
214  }
215  $clone->saveToDb();
216 
217  // copy question page content
218  $clone->copyPageOfQuestion($original_id);
219  // copy XHTML media objects
220  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
221  // duplicate the generic feedback
222  $clone->duplicateGenericFeedback($original_id);
223 
224  $clone->onCopy($this->getObjId(), $this->getId());
225 
226  return $clone->id;
227  }
228 
234  public function getMaximumPoints()
235  {
236  return $this->getPoints();
237  }
238 
249  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
250  {
251  if( $returndetails )
252  {
253  throw new ilTestException('return details not implemented for '.__METHOD__);
254  }
255 
256  global $ilDB;
257 
258  $found_values = array();
259  if (is_null($pass))
260  {
261  $pass = $this->getSolutionMaxPass($active_id);
262  }
263  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
264  array('integer','integer','integer'),
265  array($active_id, $this->getId(), $pass)
266  );
267  $points = 0;
268  $data = $ilDB->fetchAssoc($result);
269 
270  $data["value1"] = $this->splitAndTrimOrderElementText($data["value1"], $this->answer_separator);
271 
272  $data['value1'] = join($data['value1'], $this->answer_separator);
273 
274  if (strcmp($data["value1"], join($this->getOrderingElements(), $this->answer_separator)) == 0)
275  {
276  $points = $this->getPoints();
277  }
278  return $points;
279  }
280 
290  private 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  {
297  $result = preg_split("/\\s+/", $in_string);
298  }
299  else
300  {
301  $result = split($separator, $in_string);
302  }
303 
304  foreach ($result as $key => $value)
305  {
306  $result[$key] = trim($value);
307  }
308 
309  return $result;
310  }
311 
320  public function saveWorkingData($active_id, $pass = NULL)
321  {
322  global $ilDB;
323  global $ilUser;
324 
325  if (is_null($pass))
326  {
327  include_once "./Modules/Test/classes/class.ilObjTest.php";
328  $pass = ilObjTest::_getPass($active_id);
329  }
330 
331  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
332  array('integer','integer','integer'),
333  array($active_id, $this->getId(), $pass)
334  );
335 
336  $entered_values = false;
337  if (strlen($_POST["orderresult"]))
338  {
339  $next_id = $ilDB->nextId('tst_solutions');
340  $affectedRows = $ilDB->insert("tst_solutions", array(
341  "solution_id" => array("integer", $next_id),
342  "active_fi" => array("integer", $active_id),
343  "question_fi" => array("integer", $this->getId()),
344  "value1" => array("clob", $_POST['orderresult']),
345  "value2" => array("clob", null),
346  "pass" => array("integer", $pass),
347  "tstamp" => array("integer", time())
348  ));
349  $entered_values = true;
350  }
351  if ($entered_values)
352  {
353  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
355  {
356  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
357  }
358  }
359  else
360  {
361  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
363  {
364  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
365  }
366  }
367 
368  return true;
369  }
370 
379  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
380  {
381  // nothing to rework!
382  }
383 
384  /*
385  * Move an element to the right during a test when a user selects/deselects a word without using javascript
386  */
387  public function moveRight($position, $active_id, $pass = null)
388  {
389  global $ilDB;
390  global $ilUser;
391 
392  if (is_null($pass))
393  {
394  include_once "./Modules/Test/classes/class.ilObjTest.php";
395  $pass = ilObjTest::_getPass($active_id);
396  }
397 
398  $solutions =& $this->getSolutionValues($active_id, $pass);
399  $elements = array();
400  if (count($solutions) == 1)
401  {
402  $elements = split("{::}", $solutions[0]["value1"]);
403  }
404  else
405  {
406  $elements = $_SESSION['qst_ordering_horizontal_elements'];
407  }
408  if (count($elements))
409  {
410  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
411  array('integer','integer','integer'),
412  array($active_id, $this->getId(), $pass)
413  );
414 
415  if ($position < count($elements)-1)
416  {
417  $temp = $elements[$position];
418  $elements[$position] = $elements[$position+1];
419  $elements[$position+1] = $temp;
420  }
421  $entered_values = false;
422  $next_id = $ilDB->nextId('tst_solutions');
423  $affectedRows = $ilDB->insert("tst_solutions", array(
424  "solution_id" => array("integer", $next_id),
425  "active_fi" => array("integer", $active_id),
426  "question_fi" => array("integer", $this->getId()),
427  "value1" => array("clob", join($elements, '{::}')),
428  "value2" => array("clob", null),
429  "pass" => array("integer", $pass),
430  "tstamp" => array("integer", time())
431  ));
432  $entered_values = true;
433  if ($entered_values)
434  {
435  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
437  {
438  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
439  }
440  }
441  else
442  {
443  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
445  {
446  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
447  }
448  }
449 
450  $this->calculateReachedPoints($active_id, $pass);
451  }
452  }
453 
459  public function getQuestionType()
460  {
461  return "assOrderingHorizontal";
462  }
463 
469  public function getAdditionalTableName()
470  {
471  return "qpl_qst_horder";
472  }
473 
479  public function getAnswerTableName()
480  {
481  return "";
482  }
483 
489  public function deleteAnswers($question_id)
490  {
491  }
492 
497  public function getRTETextWithMediaObjects()
498  {
500  return $text;
501  }
502 
514  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
515  {
516  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
517  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
518  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
519 
520  $solutionvalue = "";
521  $solutions =& $this->getSolutionValues($active_id, $pass);
522  $solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
523  $i = 1;
524  $worksheet->writeString($startrow+$i, 0, ilExcelUtils::_convert_text($solutionvalue));
525  $i++;
526  return $startrow + $i + 1;
527  }
528 
541  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
542  {
543  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assOrderingHorizontalImport.php";
544  $import = new assOrderingHorizontalImport($this);
545  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
546  }
547 
554  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
555  {
556  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assOrderingHorizontalExport.php";
557  $export = new assOrderingHorizontalExport($this);
558  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
559  }
560 
566  public function getBestSolution($active_id, $pass)
567  {
568  $user_solution = array();
569  return $user_solution;
570  }
571 
577  public function getOrderingElements()
578  {
579  return $this->splitAndTrimOrderElementText($this->getOrderText(), $this->separator);
580  }
581 
587  public function getRandomOrderingElements()
588  {
589  $elements = $this->getOrderingElements();
590  shuffle($elements);
591  return $elements;
592  }
593 
599  public function getOrderText()
600  {
601  return $this->ordertext;
602  }
603 
609  public function setOrderText($a_value)
610  {
611  $this->ordertext = $a_value;
612  }
613 
619  public function getTextSize()
620  {
621  return $this->textsize;
622  }
623 
629  public function setTextSize($a_value)
630  {
631  if ($a_value >= 10)
632  {
633  $this->textsize = $a_value;
634  }
635  }
636 
642  public function getSeparator()
643  {
644  return $this->separator;
645  }
646 
652  public function setSeparator($a_value)
653  {
654  $this->separator = $a_value;
655  }
656 
660  public function __get($value)
661  {
662  switch ($value)
663  {
664  case "ordertext":
665  return $this->getOrderText();
666  break;
667  case "textsize":
668  return $this->getTextSize();
669  break;
670  case "separator":
671  return $this->getSeparator();
672  break;
673  default:
674  return parent::__get($value);
675  break;
676  }
677  }
678 
682  public function __set($key, $value)
683  {
684  switch ($key)
685  {
686  case "ordertext":
687  $this->setOrderText($value);
688  break;
689  case "textsize":
690  $this->setTextSize($value);
691  break;
692  case "separator":
693  $this->setSeparator($value);
694  break;
695  default:
696  parent::__set($key, $value);
697  break;
698  }
699  }
700 
704  public function toJSON()
705  {
706  include_once("./Services/RTE/classes/class.ilRTE.php");
707  $result = array();
708  $result['id'] = (int) $this->getId();
709  $result['type'] = (string) $this->getQuestionType();
710  $result['title'] = (string) $this->getTitle();
711  $result['question'] = $this->formatSAQuestion($this->getQuestion());
712  $result['nr_of_tries'] = (int) $this->getNrOfTries();
713  $result['shuffle'] = (bool) true;
714  $result['points'] = (bool) $this->getPoints();
715  $result['feedback'] = array(
716  "onenotcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(0), 0)),
717  "allcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(1), 0))
718  );
719 
720  $arr = array();
721  foreach ($this->getOrderingElements() as $order => $answer)
722  {
723  array_push($arr, array(
724  "answertext" => (string) $answer,
725  "order" => (int) $order+1
726  ));
727  }
728  $result['answers'] = $arr;
729 
730  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
731  $result['mobs'] = $mobs;
732 
733  return json_encode($result);
734  }
735 }
736 
737 ?>