ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assOrderingQuestion.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
25 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
26 
37 {
45  var $answers;
46 
56 
70  $title = "",
71  $comment = "",
72  $author = "",
73  $owner = -1,
74  $question = "",
76  )
77  {
79  $this->answers = array();
80  $this->ordering_type = $ordering_type;
81  }
82 
91  function isComplete()
92  {
93  if (($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0))
94  {
95  return true;
96  }
97  else
98  {
99  return false;
100  }
101  }
102 
111  function saveToDb($original_id = "")
112  {
113  global $ilDB;
114 
115  $complete = 0;
116  if ($this->isComplete())
117  {
118  $complete = 1;
119  }
120 
121  $estw_time = $this->getEstimatedWorkingTime();
122  $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
123 
124  if ($original_id)
125  {
126  $original_id = $ilDB->quote($original_id);
127  }
128  else
129  {
130  $original_id = "NULL";
131  }
132 
133  include_once("./Services/RTE/classes/class.ilRTE.php");
134  if ($this->id == -1)
135  {
136  // Neuen Datensatz schreiben
137  $now = getdate();
138  $question_type = $this->getQuestionTypeID();
139  $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
140  $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, points, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
141  $ilDB->quote($question_type . ""),
142  $ilDB->quote($this->obj_id . ""),
143  $ilDB->quote($this->title . ""),
144  $ilDB->quote($this->comment . ""),
145  $ilDB->quote($this->author . ""),
146  $ilDB->quote($this->owner . ""),
147  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
148  $ilDB->quote($estw_time . ""),
149  $ilDB->quote($this->getMaximumPoints() . ""),
150  $ilDB->quote($complete . ""),
151  $ilDB->quote($created . ""),
153  );
154  $result = $ilDB->query($query);
155  if (PEAR::isError($result))
156  {
157  global $ilias;
158  $ilias->raiseError($result->getMessage());
159  }
160  else
161  {
162  $this->id = $ilDB->getLastInsertId();
163  $query = sprintf("INSERT INTO qpl_question_ordering (question_fi, ordering_type) VALUES (%s, %s)",
164  $ilDB->quote($this->id . ""),
165  $ilDB->quote($this->ordering_type . "")
166  );
167  $ilDB->query($query);
168 
169  // create page object of question
170  $this->createPageObject();
171 
172  if ($this->getTestId() > 0)
173  {
174  $this->insertIntoTest($this->getTestId());
175  }
176  }
177  }
178  else
179  {
180  // Vorhandenen Datensatz aktualisieren
181  $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, points = %s, complete = %s WHERE question_id = %s",
182  $ilDB->quote($this->obj_id. ""),
183  $ilDB->quote($this->title . ""),
184  $ilDB->quote($this->comment . ""),
185  $ilDB->quote($this->author . ""),
186  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
187  $ilDB->quote($estw_time . ""),
188  $ilDB->quote($this->getMaximumPoints() . ""),
189  $ilDB->quote($complete . ""),
190  $ilDB->quote($this->id . "")
191  );
192  $result = $ilDB->query($query);
193  $query = sprintf("UPDATE qpl_question_ordering SET ordering_type = %s WHERE question_fi = %s",
194  $ilDB->quote($this->ordering_type . ""),
195  $ilDB->quote($this->id . "")
196  );
197  $result = $ilDB->query($query);
198  }
199  if (PEAR::isError($result))
200  {
201  global $ilias;
202  $ilias->raiseError($result->getMessage());
203  }
204  else
205  {
206  // Antworten schreiben
207  // alte Antworten löschen
208  $query = sprintf("DELETE FROM qpl_answer_ordering WHERE question_fi = %s",
209  $ilDB->quote($this->id)
210  );
211  $result = $ilDB->query($query);
212 
213  // Anworten wegschreiben
214  foreach ($this->answers as $key => $value)
215  {
216  $answer_obj = $this->answers[$key];
217  $query = sprintf("INSERT INTO qpl_answer_ordering (answer_id, question_fi, answertext, points, aorder, solution_order) VALUES (NULL, %s, %s, %s, %s, %s)",
218  $ilDB->quote($this->id),
219  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 0)),
220  $ilDB->quote($answer_obj->getPoints() . ""),
221  $ilDB->quote($answer_obj->getOrder() . ""),
222  $ilDB->quote($answer_obj->getSolutionOrder() . "")
223  );
224  $answer_result = $ilDB->query($query);
225  }
226  }
228  }
229 
239  function loadFromDb($question_id)
240  {
241  global $ilDB;
242 
243  $query = sprintf("SELECT qpl_questions.*, qpl_question_ordering.* FROM qpl_questions, qpl_question_ordering WHERE question_id = %s AND qpl_questions.question_id = qpl_question_ordering.question_fi",
244  $ilDB->quote($question_id)
245  );
246  $result = $ilDB->query($query);
247  if ($result->numRows() == 1)
248  {
249  $data = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
250  $this->id = $question_id;
251  $this->title = $data->title;
252  $this->obj_id = $data->obj_fi;
253  $this->comment = $data->comment;
254  $this->original_id = $data->original_id;
255  $this->author = $data->author;
256  $this->owner = $data->owner;
257  include_once("./Services/RTE/classes/class.ilRTE.php");
258  $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
259  $this->solution_hint = $data->solution_hint;
260  $this->ordering_type = $data->ordering_type;
261  $this->points = $data->points;
262  $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
263 
264  $query = sprintf("SELECT * FROM qpl_answer_ordering WHERE question_fi = %s ORDER BY aorder ASC",
265  $ilDB->quote($question_id)
266  );
267  $result = $ilDB->query($query);
268  include_once "./Modules/TestQuestionPool/classes/class.assAnswerOrdering.php";
269  if ($result->numRows() > 0)
270  {
271  while ($data = $result->fetchRow(MDB2_FETCHMODE_OBJECT))
272  {
273  include_once("./Services/RTE/classes/class.ilRTE.php");
274  $data->answertext = ilRTE::_replaceMediaObjectImageSrc($data->answertext, 1);
275  array_push($this->answers, new ASS_AnswerOrdering($data->answertext, $data->points, $data->aorder, $data->solution_order));
276  }
277  }
278  }
279  parent::loadFromDb($question_id);
280  }
281 
289  function duplicate($for_test = true, $title = "", $author = "", $owner = "")
290  {
291  if ($this->id <= 0)
292  {
293  // The question has not been saved. It cannot be duplicated
294  return;
295  }
296  // duplicate the question in database
297  $this_id = $this->getId();
298  $clone = $this;
299  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
301  $clone->id = -1;
302  if ($title)
303  {
304  $clone->setTitle($title);
305  }
306  if ($author)
307  {
308  $clone->setAuthor($author);
309  }
310  if ($owner)
311  {
312  $clone->setOwner($owner);
313  }
314  if ($for_test)
315  {
316  $clone->saveToDb($original_id);
317  }
318  else
319  {
320  $clone->saveToDb();
321  }
322 
323  // copy question page content
324  $clone->copyPageOfQuestion($this_id);
325  // copy XHTML media objects
326  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
327  // duplicate the generic feedback
328  $clone->duplicateFeedbackGeneric($this_id);
329 
330  // duplicate the image
331  $clone->duplicateImages($this_id);
332  return $clone->id;
333  }
334 
342  function copyObject($target_questionpool, $title = "")
343  {
344  if ($this->id <= 0)
345  {
346  // The question has not been saved. It cannot be duplicated
347  return;
348  }
349  // duplicate the question in database
350  $clone = $this;
351  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
353  $clone->id = -1;
354  $source_questionpool = $this->getObjId();
355  $clone->setObjId($target_questionpool);
356  if ($title)
357  {
358  $clone->setTitle($title);
359  }
360 
361  $clone->saveToDb();
362 
363  // copy question page content
364  $clone->copyPageOfQuestion($original_id);
365  // copy XHTML media objects
366  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
367  // duplicate the generic feedback
368  $clone->duplicateFeedbackGeneric($original_id);
369 
370  // duplicate the image
371  $clone->copyImages($original_id, $source_questionpool);
372  return $clone->id;
373  }
374 
375  function duplicateImages($question_id)
376  {
377  if ($this->getOrderingType() == OQ_PICTURES)
378  {
379  $imagepath = $this->getImagePath();
380  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
381  if (!file_exists($imagepath)) {
382  ilUtil::makeDirParents($imagepath);
383  }
384  foreach ($this->answers as $answer)
385  {
386  $filename = $answer->getAnswertext();
387  if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
388  print "image could not be duplicated!!!! ";
389  }
390  if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg")) {
391  print "image thumbnail could not be duplicated!!!! ";
392  }
393  }
394  }
395  }
396 
397  function copyImages($question_id, $source_questionpool)
398  {
399  if ($this->getOrderingType() == OQ_PICTURES)
400  {
401  $imagepath = $this->getImagePath();
402  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
403  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
404  if (!file_exists($imagepath)) {
405  ilUtil::makeDirParents($imagepath);
406  }
407  foreach ($this->answers as $answer)
408  {
409  $filename = $answer->getAnswertext();
410  if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
411  print "image could not be copied!!!! ";
412  }
413  if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg")) {
414  print "image thumbnail could not be copied!!!! ";
415  }
416  }
417  }
418  }
419 
430  {
431  $this->ordering_type = $ordering_type;
432  }
433 
443  function getOrderingType()
444  {
445  return $this->ordering_type;
446  }
447 
463  function addAnswer(
464  $answertext = "",
465  $points = 0.0,
466  $order = 0,
467  $solution_order = 0
468  )
469  {
470  $found = -1;
471  foreach ($this->answers as $key => $value)
472  {
473  if ($value->getOrder() == $order)
474  {
475  $found = $order;
476  }
477  }
478  include_once "./Modules/TestQuestionPool/classes/class.assAnswerOrdering.php";
479  if ($found >= 0)
480  {
481  // Antwort einfĂĽgen
482  $answer = new ASS_AnswerOrdering($answertext, $points, $found, $solution_order);
483  array_push($this->answers, $answer);
484  for ($i = $found + 1; $i < count($this->answers); $i++)
485  {
486  $this->answers[$i] = $this->answers[$i-1];
487  }
488  $this->answers[$found] = $answer;
489  }
490  else
491  {
492  // Anwort anhängen
493  $answer = new ASS_AnswerOrdering($answertext, $points,
494  count($this->answers), $solution_order);
495  array_push($this->answers, $answer);
496  }
497  }
498 
510  function getAnswer($index = 0)
511  {
512  if ($index < 0) return NULL;
513  if (count($this->answers) < 1) return NULL;
514  if ($index >= count($this->answers)) return NULL;
515  return $this->answers[$index];
516  }
517 
528  function deleteAnswer($index = 0)
529  {
530  if ($index < 0)
531  {
532  return;
533  }
534  if (count($this->answers) < 1)
535  {
536  return;
537  }
538  if ($index >= count($this->answers))
539  {
540  return;
541  }
542  unset($this->answers[$index]);
543  $this->answers = array_values($this->answers);
544  for ($i = 0; $i < count($this->answers); $i++)
545  {
546  if ($this->answers[$i]->getOrder() > $index)
547  {
548  $this->answers[$i]->setOrder($i);
549  }
550  }
551  }
552 
561  function flushAnswers()
562  {
563  $this->answers = array();
564  }
565 
575  function getAnswerCount()
576  {
577  return count($this->answers);
578  }
579 
589  {
590  if (count($this->answers) == 0)
591  {
592  $max = 0;
593  }
594  else
595  {
596  $max = $this->answers[0]->getSolutionOrder();
597  }
598  foreach ($this->answers as $key => $value)
599  {
600  if ($value->getSolutionOrder() > $max)
601  {
602  $max = $value->getSolutionOrder();
603  }
604  }
605  return $max;
606  }
607 
619  function calculateReachedPoints($active_id, $pass = NULL)
620  {
621  global $ilDB;
622 
623  $found_value1 = array();
624  $found_value2 = array();
625  if (is_null($pass))
626  {
627  $pass = $this->getSolutionMaxPass($active_id);
628  }
629  $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
630  $ilDB->quote($active_id . ""),
631  $ilDB->quote($this->getId() . ""),
632  $ilDB->quote($pass . "")
633  );
634  $result = $ilDB->query($query);
635  $user_order = array();
636  while ($data = $result->fetchRow(MDB2_FETCHMODE_OBJECT))
637  {
638  if ((strcmp($data->value1, "") != 0) && (strcmp($data->value2, "") != 0))
639  {
640  $user_order[$data->value2] = $data->value1;
641  }
642  }
643  ksort($user_order);
644  $user_order = array_values($user_order);
645  $answer_order = array();
646  foreach ($this->answers as $key => $answer)
647  {
648  $answer_order[$answer->getSolutionOrder()] = $key;
649  }
650  ksort($answer_order);
651  $answer_order = array_values($answer_order);
652  $points = 0;
653  foreach ($answer_order as $index => $answer_id)
654  {
655  if (strcmp($user_order[$index], "") != 0)
656  {
657  if ($answer_id == $user_order[$index])
658  {
659  $points += $this->answers[$answer_id]->getPoints();
660  }
661  }
662  }
663 
664  $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
665  return $points;
666  }
667 
676  function getMaximumPoints()
677  {
678  $points = 0;
679  foreach ($this->answers as $key => $value)
680  {
681  $points += $value->getPoints();
682  }
683  return $points;
684  }
685 
696  function setImageFile($image_filename, $image_tempfilename = "")
697  {
698  $result = 0;
699  if (!empty($image_tempfilename))
700  {
701  $imagepath = $this->getImagePath();
702  if (!file_exists($imagepath))
703  {
704  ilUtil::makeDirParents($imagepath);
705  }
706  if (!ilUtil::moveUploadedFile($image_tempfilename,$image_filename, $imagepath.$image_filename))
707  {
708  $result = 2;
709  }
710  else
711  {
712  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
713  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
714  if (!preg_match("/^image/", $mimetype))
715  {
716  unlink($imagepath . $image_filename);
717  $result = 1;
718  }
719  else
720  {
721  // create thumbnail file
722  $thumbpath = $imagepath . $image_filename . "." . "thumb.jpg";
723  ilUtil::convertImage($imagepath.$image_filename, $thumbpath, strtoupper($extension), 100);
724  }
725  }
726  }
727  return $result;
728  }
729 
739  function checkSaveData()
740  {
741  $result = true;
742  if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
743  {
744  if (strlen($_POST["orderresult"]))
745  {
746  return $result;
747  }
748  }
749  $order_values = array();
750  foreach ($_POST as $key => $value)
751  {
752  if (preg_match("/^order_(\d+)/", $key, $matches))
753  {
754  if (strcmp($value, "") != 0)
755  {
756  array_push($order_values, $value);
757  }
758  }
759  }
760  $check_order = array_flip($order_values);
761  if (count($check_order) != count($order_values))
762  {
763  // duplicate order values!!!
764  $result = false;
765  ilUtil::sendInfo($this->lng->txt("duplicate_order_values_entered"), TRUE);
766  }
767  return $result;
768  }
769 
780  function saveWorkingData($active_id, $pass = NULL)
781  {
782  global $ilDB;
783  global $ilUser;
784 
785  $saveWorkingDataResult = $this->checkSaveData();
786  $entered_values = 0;
787  if ($saveWorkingDataResult)
788  {
789  if (is_null($pass))
790  {
791  include_once "./Modules/Test/classes/class.ilObjTest.php";
792  $pass = ilObjTest::_getPass($active_id);
793  }
794 
795  $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
796  $ilDB->quote($active_id . ""),
797  $ilDB->quote($this->getId() . ""),
798  $ilDB->quote($pass . "")
799  );
800  $result = $ilDB->query($query);
801  if (array_key_exists("orderresult", $_POST))
802  {
803  $orderresult = $_POST["orderresult"];
804  if (strlen($orderresult))
805  {
806  $orderarray = explode(":", $orderresult);
807  $ordervalue = 1;
808  foreach ($orderarray as $index)
809  {
810  $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
811  $ilDB->quote($active_id . ""),
812  $ilDB->quote($this->getId() . ""),
813  $ilDB->quote(trim($index) . ""),
814  $ilDB->quote(trim($ordervalue) . ""),
815  $ilDB->quote($pass . "")
816  );
817  $result = $ilDB->query($query);
818  $ordervalue++;
819  $entered_values++;
820  }
821  }
822  }
823  else
824  {
825  foreach ($_POST as $key => $value)
826  {
827  if (preg_match("/^order_(\d+)/", $key, $matches))
828  {
829  if (!(preg_match("/initial_value_\d+/", $value)))
830  {
831  if (strlen($value))
832  {
833  $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
834  $ilDB->quote($active_id . ""),
835  $ilDB->quote($this->getId() . ""),
836  $ilDB->quote($matches[1] . ""),
837  $ilDB->quote($value . ""),
838  $ilDB->quote($pass . "")
839  );
840  $result = $ilDB->query($query);
841  $entered_values++;
842  }
843  }
844  }
845  }
846  }
847  }
848  if ($entered_values)
849  {
850  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
852  {
853  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
854  }
855  }
856  else
857  {
858  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
860  {
861  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
862  }
863  }
864  parent::saveWorkingData($active_id, $pass);
865  return $saveWorkingDataResult;
866  }
867 
868  function pc_array_shuffle($array) {
869  mt_srand((double)microtime()*1000000);
870  $i = count($array);
871  while(--$i)
872  {
873  $j = mt_rand(0, $i);
874  if ($i != $j)
875  {
876  // swap elements
877  $tmp = $array[$j];
878  $array[$j] = $array[$i];
879  $array[$i] = $tmp;
880  }
881  }
882  return $array;
883  }
884 
893  function getQuestionType()
894  {
895  return "assOrderingQuestion";
896  }
897 
907  {
908  return "qpl_question_ordering";
909  }
910 
920  {
921  return "qpl_answer_ordering";
922  }
923 
929  {
931  foreach ($this->answers as $index => $answer)
932  {
933  $answer_obj = $this->answers[$index];
934  $text .= $answer_obj->getAnswertext();
935  }
936  return $text;
937  }
938 
942  function &getAnswers()
943  {
944  return $this->answers;
945  }
946 
956  {
957  return TRUE;
958  }
959 
972  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
973  {
974  include_once ("./classes/class.ilExcelUtils.php");
975  $solutions = $this->getSolutionValues($active_id, $pass);
976  $sol = array();
977  foreach ($solutions as $solution)
978  {
979  $sol[$solution["value1"]] = $solution["value2"];
980  }
981  asort($sol);
982  $sol = array_keys($sol);
983  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
984  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
985  $i = 1;
986  $answers = $this->getAnswers();
987  foreach ($sol as $idx)
988  {
989  foreach ($solutions as $solution)
990  {
991  if ($solution["value1"] == $idx) $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($solution["value2"]));
992  }
993  $worksheet->writeString($startrow + $i, 1, ilExcelUtils::_convert_text($answers[$idx]->getAnswertext()));
994  $i++;
995  }
996  return $startrow + $i + 1;
997  }
998 }
999 
1000 ?>