ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assMatchingQuestion.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 {
46 
56 
62  protected $terms;
63  protected $definitions;
64 
71 
77  var $thumb_geometry = 100;
78 
85 
98  function __construct(
99  $title = "",
100  $comment = "",
101  $author = "",
102  $owner = -1,
103  $question = "",
105  )
106  {
108  $this->matchingpairs = array();
109  $this->matching_type = $matching_type;
110  $this->terms = array();
111  $this->definitions = array();
112  $this->masterTermIDs = array();
113  }
114 
121  function isComplete()
122  {
123  if (($this->title) and ($this->author) and ($this->question) and (count($this->matchingpairs)) and ($this->getMaximumPoints() > 0))
124  {
125  return true;
126  }
127  else
128  {
129  return false;
130  }
131  }
132 
138  public function saveToDb($original_id = "")
139  {
140  global $ilDB;
141 
143 
144  // save additional data
145  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
146  array("integer"),
147  array($this->getId())
148  );
149  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, shuffle, matching_type, thumb_geometry, element_height) VALUES (%s, %s, %s, %s, %s)",
150  array("integer", "text", "text","integer","integer"),
151  array(
152  $this->getId(),
153  $this->shuffle,
154  $this->matching_type,
155  $this->getThumbGeometry(),
156  ($this->getElementHeight() >= 20) ? $this->getElementHeight() : NULL
157  )
158  );
159 
160  // delete old terms
161  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_mterm WHERE question_fi = %s",
162  array('integer'),
163  array($this->getId())
164  );
165 
166  // delete old definitions
167  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_mdef WHERE question_fi = %s",
168  array('integer'),
169  array($this->getId())
170  );
171 
172  $termids = array();
173  // write terms
174  foreach ($this->terms as $key => $term)
175  {
176  $next_id = $ilDB->nextId('qpl_a_mterm');
177  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_mterm (term_id, question_fi, picture, term) VALUES (%s, %s, %s, %s)",
178  array('integer','integer','text', 'text'),
179  array($next_id, $this->getId(), $term->picture, $term->text)
180  );
181  $termids[$term->identifier] = $next_id;
182  }
183 
184 
185  $this->masterTermIDs=&$termids;
186 
187 
188 
189 
190 
191  $definitionids = array();
192  // write definitions
193  foreach ($this->definitions as $key => $definition)
194  {
195  $next_id = $ilDB->nextId('qpl_a_mdef');
196  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_mdef (def_id, question_fi, picture, definition, morder) VALUES (%s, %s, %s, %s, %s)",
197  array('integer','integer','text', 'text', 'integer'),
198  array($next_id, $this->getId(), $definition->picture, $definition->text, $definition->identifier)
199  );
200  $definitionids[$definition->identifier] = $next_id;
201  }
202 
203  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_matching WHERE question_fi = %s",
204  array('integer'),
205  array($this->getId())
206  );
207  $matchingpairs = $this->getMatchingPairs();
208  foreach ($matchingpairs as $key => $pair)
209  {
210  $next_id = $ilDB->nextId('qpl_a_matching');
211  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_matching (answer_id, question_fi, points, term_fi, definition_fi) VALUES (%s, %s, %s, %s, %s)",
212  array('integer','integer','float','integer','integer'),
213  array(
214  $next_id,
215  $this->getId(),
216  $pair->points,
217  $termids[$pair->term->identifier],
218  $definitionids[$pair->definition->identifier]
219  )
220  );
221  }
222 
223  $this->rebuildThumbnails();
224 
226  }
227 
234  public function loadFromDb($question_id)
235  {
236  global $ilDB;
237 
238  $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",
239  array("integer"),
240  array($question_id)
241  );
242  if ($result->numRows() == 1)
243  {
244  $data = $ilDB->fetchAssoc($result);
245  $this->setId($question_id);
246  $this->setObjId($data["obj_fi"]);
247  $this->setTitle($data["title"]);
248  $this->setComment($data["description"]);
249  $this->setOriginalId($data["original_id"]);
250  $this->setNrOfTries($data['nr_of_tries']);
251  $this->setAuthor($data["author"]);
252  $this->setPoints($data["points"]);
253  $this->setOwner($data["owner"]);
254  include_once("./Services/RTE/classes/class.ilRTE.php");
255  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
256  $this->setThumbGeometry($data["thumb_geometry"]);
257  $this->setElementHeight($data["element_height"]);
258  $this->setShuffle($data["shuffle"]);
259  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
260  }
261 
262  $termids = array();
263  $result = $ilDB->queryF("SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
264  array('integer'),
265  array($question_id)
266  );
267  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
268  $this->terms = array();
269  if ($result->numRows() > 0)
270  {
271  while ($data = $ilDB->fetchAssoc($result))
272  {
273  $term = new assAnswerMatchingTerm($data['term'], $data['picture'], $data['term_id']);
274  array_push($this->terms, $term);
275  $termids[$data['term_id']] = $term;
276  }
277  }
278 
279  $definitionids = array();
280  $result = $ilDB->queryF("SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
281  array('integer'),
282  array($question_id)
283  );
284  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
285  $this->definitions = array();
286  if ($result->numRows() > 0)
287  {
288  while ($data = $ilDB->fetchAssoc($result))
289  {
290  $definition = new assAnswerMatchingDefinition($data['definition'], $data['picture'], $data['morder']);
291  array_push($this->definitions, $definition);
292  $definitionids[$data['def_id']] = $definition;
293  }
294  }
295 
296  $this->matchingpairs = array();
297  $result = $ilDB->queryF("SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
298  array('integer'),
299  array($question_id)
300  );
301  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
302  if ($result->numRows() > 0)
303  {
304  while ($data = $ilDB->fetchAssoc($result))
305  {
306  array_push($this->matchingpairs, new assAnswerMatchingPair($termids[$data['term_fi']], $definitionids[$data['definition_fi']], $data['points']));
307  }
308  }
309  parent::loadFromDb($question_id);
310  }
311 
312 
316  public function duplicate($for_test = true, $title = "", $author = "", $owner = "")
317  {
318  if ($this->id <= 0)
319  {
320  // The question has not been saved. It cannot be duplicated
321  return;
322  }
323  // duplicate the question in database
324  $this_id = $this->getId();
325  $clone = $this;
326  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
328  $clone->id = -1;
329  if ($title)
330  {
331  $clone->setTitle($title);
332  }
333  if ($author)
334  {
335  $clone->setAuthor($author);
336  }
337  if ($owner)
338  {
339  $clone->setOwner($owner);
340  }
341  if ($for_test)
342  {
343  $clone->saveToDb($original_id);
344  }
345  else
346  {
347  $clone->saveToDb();
348  }
349 
350  // copy question page content
351  $clone->copyPageOfQuestion($this_id);
352  // copy XHTML media objects
353  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
354  // duplicate the generic feedback
355  $clone->duplicateFeedbackGeneric($this_id);
356 
357  // duplicate the image
358  $clone->duplicateImages($this_id);
359  $clone->onDuplicate($this_id);
360  return $clone->id;
361  }
362 
366  public function copyObject($target_questionpool, $title = "")
367  {
368  if ($this->id <= 0)
369  {
370  // The question has not been saved. It cannot be duplicated
371  return;
372  }
373  // duplicate the question in database
374  $clone = $this;
375  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
377  $clone->id = -1;
378  if ($title)
379  {
380  $clone->setTitle($title);
381  }
382  $source_questionpool = $this->getObjId();
383  $clone->setObjId($target_questionpool);
384  $clone->saveToDb();
385 
386  // copy question page content
387  $clone->copyPageOfQuestion($original_id);
388  // copy XHTML media objects
389  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
390  // duplicate the generic feedback
391  $clone->duplicateFeedbackGeneric($original_id);
392 
393  // duplicate the image
394  $clone->copyImages($original_id, $source_questionpool);
395  $clone->onCopy($this->getObjId(), $this->getId());
396  return $clone->id;
397  }
398 
399  public function duplicateImages($question_id)
400  {
401  global $ilLog;
402  $imagepath = $this->getImagePath();
403  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
404  foreach ($this->terms as $term)
405  {
406  if (strlen($term->picture))
407  {
408  $filename = $term->picture;
409  if (!file_exists($imagepath))
410  {
411  ilUtil::makeDirParents($imagepath);
412  }
413  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
414  {
415  $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
416  }
417  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename))
418  {
419  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
420  {
421  $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
422  }
423  }
424  }
425  }
426  foreach ($this->definitions as $definition)
427  {
428  if (strlen($definition->picture))
429  {
430  $filename = $definition->picture;
431  if (!file_exists($imagepath))
432  {
433  ilUtil::makeDirParents($imagepath);
434  }
435  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
436  {
437  $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
438  }
439  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename))
440  {
441  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
442  {
443  $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
444  }
445  }
446  }
447  }
448  }
449 
450  public function copyImages($question_id, $source_questionpool)
451  {
452  $imagepath = $this->getImagePath();
453  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
454  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
455  foreach ($this->terms as $term)
456  {
457  if (strlen($term->picture))
458  {
459  if (!file_exists($imagepath))
460  {
461  ilUtil::makeDirParents($imagepath);
462  }
463  $filename = $term->picture;
464  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
465  {
466  $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
467  }
468  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
469  {
470  $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
471  }
472  }
473  }
474  foreach ($this->definitions as $definition)
475  {
476  if (strlen($definition->picture))
477  {
478  $filename = $definition->picture;
479  if (!file_exists($imagepath))
480  {
481  ilUtil::makeDirParents($imagepath);
482  }
483  if (!copy($imagepath_original . $filename, $imagepath . $filename))
484  {
485  $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
486  }
487  if (!copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
488  {
489  $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
490  }
491  }
492  }
493  }
494 
505  public function insertMatchingPair($position, $term = null, $definition = null, $points = 0.0)
506  {
507  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
508  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
509  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
510  if (is_null($term)) $term = new assAnswerMatchingTerm();
511  if (is_null($definition)) $definition = new assAnswerMatchingDefinition();
512  $pair = new assAnswerMatchingPair($term, $definition, $points);
513  if ($position < count($this->matchingpairs))
514  {
515  $part1 = array_slice($this->matchingpairs, 0, $position);
516  $part2 = array_slice($this->matchingpairs, $position);
517  $this->matchingpairs = array_merge($part1, array($pair), $part2);
518  }
519  else
520  {
521  array_push($this->matchingpairs, $pair);
522  }
523  }
533  public function addMatchingPair($term = null, $definition = null, $points = 0.0)
534  {
535  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
536  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
537  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
538  if (is_null($term)) $term = new assAnswerMatchingTerm();
539  if (is_null($definition)) $definition = new assAnswerMatchingDefinition();
540  $pair = new assAnswerMatchingPair($term, $definition, $points);
541  array_push($this->matchingpairs, $pair);
542  }
543 
547  public function getTermWithIdentifier($a_identifier)
548  {
549  foreach ($this->terms as $term)
550  {
551  if ($term->identifier == $a_identifier) return $term;
552  }
553  return null;
554  }
555 
559  public function getDefinitionWithIdentifier($a_identifier)
560  {
561  foreach ($this->definitions as $definition)
562  {
563  if ($definition->identifier == $a_identifier) return $definition;
564  }
565  return null;
566  }
567 
576  public function getMatchingPair($index = 0)
577  {
578  if ($index < 0)
579  {
580  return NULL;
581  }
582  if (count($this->matchingpairs) < 1)
583  {
584  return NULL;
585  }
586  if ($index >= count($this->matchingpairs))
587  {
588  return NULL;
589  }
590  return $this->matchingpairs[$index];
591  }
592 
600  public function deleteMatchingPair($index = 0)
601  {
602  if ($index < 0)
603  {
604  return;
605  }
606  if (count($this->matchingpairs) < 1)
607  {
608  return;
609  }
610  if ($index >= count($this->matchingpairs))
611  {
612  return;
613  }
614  unset($this->matchingpairs[$index]);
615  $this->matchingpairs = array_values($this->matchingpairs);
616  }
617 
622  public function flushMatchingPairs()
623  {
624  $this->matchingpairs = array();
625  }
626 
633  public function getMatchingPairCount()
634  {
635  return count($this->matchingpairs);
636  }
637 
644  public function getTerms()
645  {
646  return $this->terms;
647  }
648 
655  public function getDefinitions()
656  {
657  return $this->definitions;
658  }
659 
666  public function getTermCount()
667  {
668  return count($this->terms);
669  }
670 
677  public function getDefinitionCount()
678  {
679  return count($this->definitions);
680  }
681 
688  public function addTerm($term)
689  {
690  array_push($this->terms, $term);
691  }
692 
699  public function addDefinition($definition)
700  {
701  array_push($this->definitions, $definition);
702  }
703 
710  public function insertTerm($position, $term = null)
711  {
712  if (is_null($term))
713  {
714  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
715  $term = new assAnswerMatchingTerm();
716  }
717  if ($position < count($this->terms))
718  {
719  $part1 = array_slice($this->terms, 0, $position);
720  $part2 = array_slice($this->terms, $position);
721  $this->terms = array_merge($part1, array($term), $part2);
722  }
723  else
724  {
725  array_push($this->terms, $term);
726  }
727  }
728 
735  public function insertDefinition($position, $definition = null)
736  {
737  if (is_null($definition))
738  {
739  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
740  $definition = new assAnswerMatchingDefinition();
741  }
742  if ($position < count($this->definitions))
743  {
744  $part1 = array_slice($this->definitions, 0, $position);
745  $part2 = array_slice($this->definitions, $position);
746  $this->definitions = array_merge($part1, array($definition), $part2);
747  }
748  else
749  {
750  array_push($this->definitions, $definition);
751  }
752  }
753 
758  public function flushTerms()
759  {
760  $this->terms = array();
761  }
762 
767  public function flushDefinitions()
768  {
769  $this->definitions = array();
770  }
771 
778  public function deleteTerm($position)
779  {
780  unset($this->terms[$position]);
781  $this->terms = array_values($this->terms);
782  }
783 
790  public function deleteDefinition($position)
791  {
792  unset($this->definitions[$position]);
793  $this->definitions = array_values($this->definitions);
794  }
795 
803  public function setTerm($term, $index)
804  {
805  $this->terms[$index] = $term;
806  }
807 
817  function calculateReachedPoints($active_id, $pass = NULL)
818  {
819  global $ilDB;
820 
821  $found_value1 = array();
822  $found_value2 = array();
823  if (is_null($pass))
824  {
825  $pass = $this->getSolutionMaxPass($active_id);
826  }
827  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
828  array('integer','integer','integer'),
829  array($active_id, $this->getId(), $pass)
830  );
831  while ($data = $ilDB->fetchAssoc($result))
832  {
833  if (strcmp($data["value1"], "") != 0)
834  {
835  array_push($found_value1, $data["value1"]);
836  array_push($found_value2, $data["value2"]);
837  }
838  }
839  $points = 0;
840  foreach ($found_value2 as $key => $value)
841  {
842  foreach ($this->matchingpairs as $pair)
843  {
844  if (($pair->definition->identifier == $value) && ($pair->term->identifier == $found_value1[$key]))
845  {
846  $points += $pair->points;
847  }
848  }
849  }
850 
851  $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
852  return $points;
853  }
854 
858  function getMaximumPoints()
859  {
860  $points = 0;
861  foreach ($this->matchingpairs as $key => $pair)
862  {
863  if ($pair->points > 0)
864  {
865  $points += $pair->points;
866  }
867  }
868  return $points;
869  }
870 
880  {
881  $extension = "";
882  if (preg_match("/.*\\.(\\w+)$/", $filename, $matches))
883  {
884  $extension = $matches[1];
885  }
886  return md5($filename) . "." . $extension;
887  }
888 
889  public function removeTermImage($index)
890  {
891  $term = $this->terms[$index];
892  if (is_object($term))
893  {
894  $this->deleteImagefile($term->picture);
895  $term->picture = null;
896  }
897  }
898 
899  public function removeDefinitionImage($index)
900  {
901  $definition = $this->definitions[$index];
902  if (is_object($definition))
903  {
904  $this->deleteImagefile($definition->picture);
905  $definition->picture = null;
906  }
907  }
908 
909 
916  public function deleteImagefile($filename)
917  {
918  $deletename = $filename;
919  $result = @unlink($this->getImagePath().$deletename);
920  $result = $result & @unlink($this->getImagePath().$this->getThumbPrefix() . $deletename);
921  return $result;
922  }
923 
932  function setImageFile($image_tempfilename, $image_filename, $previous_filename = '')
933  {
934  $result = TRUE;
935  if (strlen($image_tempfilename))
936  {
937  $image_filename = str_replace(" ", "_", $image_filename);
938  $imagepath = $this->getImagePath();
939  if (!file_exists($imagepath))
940  {
941  ilUtil::makeDirParents($imagepath);
942  }
943  $savename = $image_filename;
944  if (!ilUtil::moveUploadedFile($image_tempfilename, $savename, $imagepath.$savename))
945  {
946  $result = FALSE;
947  }
948  else
949  {
950  // create thumbnail file
951  $thumbpath = $imagepath . $this->getThumbPrefix() . $savename;
952  ilUtil::convertImage($imagepath.$savename, $thumbpath, "JPEG", $this->getThumbGeometry());
953  }
954  if ($result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename)))
955  {
956  $this->deleteImagefile($previous_filename);
957  }
958  }
959  return $result;
960  }
961 
968  function checkSaveData()
969  {
970  $result = true;
971  $matching_values = array();
972  foreach ($_POST['matching'][$this->getId()] as $definition => $term)
973  {
974  if ($term > 0)
975  {
976  array_push($matching_values, $term);
977  }
978  }
979 
980  $check_matching = array_flip($matching_values);
981  if (count($check_matching) != count($matching_values))
982  {
983  $result = false;
984  ilUtil::sendFailure($this->lng->txt("duplicate_matching_values_selected"), true);
985  }
986  return $result;
987  }
988 
995  function saveWorkingData($active_id, $pass = NULL)
996  {
997  global $ilDB;
998  global $ilUser;
999  $saveWorkingDataResult = $this->checkSaveData();
1000  $entered_values = 0;
1001  if ($saveWorkingDataResult)
1002  {
1003  if (is_null($pass))
1004  {
1005  include_once "./Modules/Test/classes/class.ilObjTest.php";
1006  $pass = ilObjTest::_getPass($active_id);
1007  }
1008 
1009  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1010  array('integer','integer','integer'),
1011  array($active_id, $this->getId(), $pass)
1012  );
1013 
1014  foreach ($_POST['matching'][$this->getId()] as $definition => $term)
1015  {
1016  $entered_values++;
1017  $next_id = $ilDB->nextId('tst_solutions');
1018  $affectedRows = $ilDB->insert("tst_solutions", array(
1019  "solution_id" => array("integer", $next_id),
1020  "active_fi" => array("integer", $active_id),
1021  "question_fi" => array("integer", $this->getId()),
1022  "value1" => array("clob", $term),
1023  "value2" => array("clob", $definition),
1024  "pass" => array("integer", $pass),
1025  "tstamp" => array("integer", time())
1026  ));
1027  }
1028  $saveWorkingDataResult = true;
1029  }
1030  if ($entered_values)
1031  {
1032  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1034  {
1035  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1036  }
1037  }
1038  else
1039  {
1040  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1042  {
1043  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1044  }
1045  }
1046  parent::saveWorkingData($active_id, $pass);
1047  return $saveWorkingDataResult;
1048  }
1049 
1050  public function getRandomId()
1051  {
1052  mt_srand((double)microtime()*1000000);
1053  $random_number = mt_rand(1, 100000);
1054  $found = FALSE;
1055  while ($found)
1056  {
1057  $found = FALSE;
1058  foreach ($this->matchingpairs as $key => $pair)
1059  {
1060  if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number))
1061  {
1062  $found = TRUE;
1063  $random_number++;
1064  }
1065  }
1066  }
1067  return $random_number;
1068  }
1069 
1076  public function setShuffle($shuffle)
1077  {
1078  switch ($shuffle)
1079  {
1080  case 0:
1081  case 1:
1082  case 2:
1083  case 3:
1084  $this->shuffle = $shuffle;
1085  break;
1086  default:
1087  $this->shuffle = 1;
1088  break;
1089  }
1090  }
1091 
1097  public function getQuestionType()
1098  {
1099  return "assMatchingQuestion";
1100  }
1101 
1107  public function getAdditionalTableName()
1108  {
1109  return "qpl_qst_matching";
1110  }
1111 
1117  public function getAnswerTableName()
1118  {
1119  return array("qpl_a_matching", "qpl_a_mterm");
1120  }
1121 
1126  public function getRTETextWithMediaObjects()
1127  {
1129  }
1130 
1134  public function &getMatchingPairs()
1135  {
1136  return $this->matchingpairs;
1137  }
1138 
1144  public function supportsJavascriptOutput()
1145  {
1146  return TRUE;
1147  }
1148 
1158  public function setExportDetailsXLS(&$adapter, $startrow, $active_id, $pass)
1159  {
1160  $solutions = $this->getSolutionValues($active_id, $pass);
1161  $adapter->setCellValue($startrow, 0, $this->lng->txt($this->getQuestionType()), CELL_FORMAT_TITLE);
1162  $adapter->setCellValue($startrow, 1, $this->getTitle(), CELL_FORMAT_TITLE);
1163  $imagepath = $this->getImagePath();
1164  $i = 1;
1165  foreach ($solutions as $solution)
1166  {
1167  $matches_written = FALSE;
1168  foreach ($this->getMatchingPairs() as $idx => $pair)
1169  {
1170  if (!$matches_written) $adapter->setCellValue($startrow + $i, 1, $this->lng->txt("matches"));
1171  $matches_written = TRUE;
1172  if ($pair->definition->identifier == $solution["value2"])
1173  {
1174  if (strlen($pair->definition->text))
1175  {
1176  $adapter->setCellValue($startrow + $i, 0, $pair->definition->text);
1177  }
1178  else
1179  {
1180  $adapter->setCellValue($startrow + $i, 0, $pair->definition->picture);
1181  }
1182  }
1183  if ($pair->term->identifier == $solution["value1"])
1184  {
1185  if (strlen($pair->term->text))
1186  {
1187  $adapter->setCellValue($startrow + $i, 2, $pair->term->text);
1188  }
1189  else
1190  {
1191  $adapter->setCellValue($startrow + $i, 2, $pair->term->picture);
1192  }
1193  }
1194  }
1195  $i++;
1196  }
1197  return $startrow + $i + 1;
1198  }
1199 
1205  public function getThumbGeometry()
1206  {
1207  return $this->thumb_geometry;
1208  }
1209 
1215  public function getThumbSize()
1216  {
1217  return $this->getThumbGeometry();
1218  }
1219 
1225  public function setThumbGeometry($a_geometry)
1226  {
1227  $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1228  }
1229 
1235  public function getElementHeight()
1236  {
1237  return $this->element_height;
1238  }
1239 
1245  public function setElementHeight($a_height)
1246  {
1247  $this->element_height = ($a_height < 20) ? "" : $a_height;
1248  }
1249 
1253  public function rebuildThumbnails()
1254  {
1255  foreach ($this->terms as $term)
1256  {
1257  if (strlen($term->picture)) $this->generateThumbForFile($this->getImagePath(), $term->picture);
1258  }
1259  foreach ($this->definitions as $definition)
1260  {
1261  if (strlen($definition->picture)) $this->generateThumbForFile($this->getImagePath(), $definition->picture);
1262  }
1263  }
1264 
1265  public function getThumbPrefix()
1266  {
1267  return "thumb.";
1268  }
1269 
1270  protected function generateThumbForFile($path, $file)
1271  {
1272  $filename = $path . $file;
1273  if (@file_exists($filename))
1274  {
1275  $thumbpath = $path . $this->getThumbPrefix() . $file;
1276  $path_info = @pathinfo($filename);
1277  $ext = "";
1278  switch (strtoupper($path_info['extension']))
1279  {
1280  case 'PNG':
1281  $ext = 'PNG';
1282  break;
1283  case 'GIF':
1284  $ext = 'GIF';
1285  break;
1286  default:
1287  $ext = 'JPEG';
1288  break;
1289  }
1290  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1291  }
1292  }
1293 
1294  public function getEstimatedElementHeight()
1295  {
1296  $hasImages = false;
1297  foreach ($this->terms as $term)
1298  {
1299  if (strlen($term->picture))
1300  {
1301  $hasImages = true;
1302  }
1303  }
1304  foreach ($this->definitions as $definition)
1305  {
1306  if (strlen($definition->picture))
1307  {
1308  $hasImages = true;
1309  }
1310  }
1311  if ($hasImages)
1312  { // 40 is approx. the height of the preview image
1313  return max($this->getElementHeight(), $this->getThumbSize() + 40);
1314  }
1315  else
1316  {
1317  return ($this->getElementHeight()) ? $this->getElementHeight() : 0;
1318  }
1319  }
1320 
1325  public function toJSON()
1326  {
1327  include_once("./Services/RTE/classes/class.ilRTE.php");
1328  $result = array();
1329  $result['id'] = (int) $this->getId();
1330  $result['type'] = (string) $this->getQuestionType();
1331  $result['title'] = (string) $this->getTitle();
1332  $result['question'] = (string) ilRTE::_replaceMediaObjectImageSrc($this->getQuestion(), 0);
1333  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1334  $result['shuffle'] = true;
1335  $result['feedback'] = array(
1336  "onenotcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(0), 0)),
1337  "allcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(1), 0))
1338  );
1339  $terms = array();
1340  foreach ($this->getMatchingPairs() as $pair)
1341  {
1342  $terms[(int)$pair->term->identifier] = array(
1343  "term" => $pair->term->text,
1344  "id" =>(int)$pair->term->identifier
1345  );
1346  }
1347 
1348  $terms = $this->pcArrayShuffle($terms);
1349  $pairs = array();
1350 
1351  // alex 9.9.2010 as a fix for bug 6513 I added the question id
1352  // to the "def_id" in the array. The $pair->definition->identifier is not
1353  // unique, since it gets it value from the morder table field
1354  // this value is not changed, when a question is copied.
1355  // thus copying the same question on a page results in problems
1356  // when the second one (the copy) is answered.
1357 
1358  foreach ($this->getMatchingPairs() as $pair)
1359  {
1360  array_push($pairs, array(
1361  "term_id" => (int) $pair->term->identifier,
1362  "points" => (float) $pair->points,
1363  "definition" => (string) $pair->definition->text,
1364  "def_id" => (int) $this->getId().$pair->definition->identifier,
1365  "terms" => $terms
1366  ));
1367  }
1368  $result['pairs'] = $pairs;
1369  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1370  $result['mobs'] = $mobs;
1371 
1372  return json_encode($result);
1373  }
1374 
1375 }
1376 
1377 ?>