ILIAS  Release_4_2_x_branch Revision 61807
 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 
70  var $thumb_geometry = 100;
71 
78 
91  function __construct(
92  $title = "",
93  $comment = "",
94  $author = "",
95  $owner = -1,
96  $question = "",
98  )
99  {
101  $this->matchingpairs = array();
102  $this->matching_type = $matching_type;
103  $this->terms = array();
104  $this->definitions = array();
105  }
106 
113  function isComplete()
114  {
115  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->matchingpairs)) and ($this->getMaximumPoints() > 0))
116  {
117  return true;
118  }
119  else
120  {
121  return false;
122  }
123  }
124 
130  public function saveToDb($original_id = "")
131  {
132  global $ilDB;
133 
135 
136  // save additional data
137  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
138  array("integer"),
139  array($this->getId())
140  );
141  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, shuffle, matching_type, thumb_geometry, element_height) VALUES (%s, %s, %s, %s, %s)",
142  array("integer", "text", "text","integer","integer"),
143  array(
144  $this->getId(),
145  $this->shuffle,
146  $this->matching_type,
147  $this->getThumbGeometry(),
148  ($this->getElementHeight() >= 20) ? $this->getElementHeight() : NULL
149  )
150  );
151 
152  // delete old terms
153  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_mterm WHERE question_fi = %s",
154  array('integer'),
155  array($this->getId())
156  );
157 
158  // delete old definitions
159  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_mdef WHERE question_fi = %s",
160  array('integer'),
161  array($this->getId())
162  );
163 
164  $termids = array();
165  // write terms
166  foreach ($this->terms as $key => $term)
167  {
168  $next_id = $ilDB->nextId('qpl_a_mterm');
169  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_mterm (term_id, question_fi, picture, term) VALUES (%s, %s, %s, %s)",
170  array('integer','integer','text', 'text'),
171  array($next_id, $this->getId(), $term->picture, $term->text)
172  );
173  $termids[$term->identifier] = $next_id;
174  }
175 
176  $definitionids = array();
177  // write definitions
178  foreach ($this->definitions as $key => $definition)
179  {
180  $next_id = $ilDB->nextId('qpl_a_mdef');
181  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_mdef (def_id, question_fi, picture, definition, morder) VALUES (%s, %s, %s, %s, %s)",
182  array('integer','integer','text', 'text', 'integer'),
183  array($next_id, $this->getId(), $definition->picture, $definition->text, $definition->identifier)
184  );
185  $definitionids[$definition->identifier] = $next_id;
186  }
187 
188  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_matching WHERE question_fi = %s",
189  array('integer'),
190  array($this->getId())
191  );
192  $matchingpairs = $this->getMatchingPairs();
193  foreach ($matchingpairs as $key => $pair)
194  {
195  $next_id = $ilDB->nextId('qpl_a_matching');
196  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_matching (answer_id, question_fi, points, term_fi, definition_fi) VALUES (%s, %s, %s, %s, %s)",
197  array('integer','integer','float','integer','integer'),
198  array(
199  $next_id,
200  $this->getId(),
201  $pair->points,
202  $termids[$pair->term->identifier],
203  $definitionids[$pair->definition->identifier]
204  )
205  );
206  }
207 
208  $this->rebuildThumbnails();
209 
211  }
212 
219  public function loadFromDb($question_id)
220  {
221  global $ilDB;
222 
223  $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",
224  array("integer"),
225  array($question_id)
226  );
227  if ($result->numRows() == 1)
228  {
229  $data = $ilDB->fetchAssoc($result);
230  $this->setId($question_id);
231  $this->setObjId($data["obj_fi"]);
232  $this->setTitle($data["title"]);
233  $this->setComment($data["description"]);
234  $this->setOriginalId($data["original_id"]);
235  $this->setNrOfTries($data['nr_of_tries']);
236  $this->setAuthor($data["author"]);
237  $this->setPoints($data["points"]);
238  $this->setOwner($data["owner"]);
239  include_once("./Services/RTE/classes/class.ilRTE.php");
240  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
241  $this->setThumbGeometry($data["thumb_geometry"]);
242  $this->setElementHeight($data["element_height"]);
243  $this->setShuffle($data["shuffle"]);
244  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
245  }
246 
247  $termids = array();
248  $result = $ilDB->queryF("SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
249  array('integer'),
250  array($question_id)
251  );
252  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
253  $this->terms = array();
254  if ($result->numRows() > 0)
255  {
256  while ($data = $ilDB->fetchAssoc($result))
257  {
258  $term = new assAnswerMatchingTerm($data['term'], $data['picture'], $data['term_id']);
259  array_push($this->terms, $term);
260  $termids[$data['term_id']] = $term;
261  }
262  }
263 
264  $definitionids = array();
265  $result = $ilDB->queryF("SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
266  array('integer'),
267  array($question_id)
268  );
269  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
270  $this->definitions = array();
271  if ($result->numRows() > 0)
272  {
273  while ($data = $ilDB->fetchAssoc($result))
274  {
275  $definition = new assAnswerMatchingDefinition($data['definition'], $data['picture'], $data['morder']);
276  array_push($this->definitions, $definition);
277  $definitionids[$data['def_id']] = $definition;
278  }
279  }
280 
281  $this->matchingpairs = array();
282  $result = $ilDB->queryF("SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
283  array('integer'),
284  array($question_id)
285  );
286  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
287  if ($result->numRows() > 0)
288  {
289  while ($data = $ilDB->fetchAssoc($result))
290  {
291  array_push($this->matchingpairs, new assAnswerMatchingPair($termids[$data['term_fi']], $definitionids[$data['definition_fi']], $data['points']));
292  }
293  }
294  parent::loadFromDb($question_id);
295  }
296 
297 
301  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
302  {
303  if ($this->id <= 0)
304  {
305  // The question has not been saved. It cannot be duplicated
306  return;
307  }
308  // duplicate the question in database
309  $this_id = $this->getId();
310 
311  if( (int)$testObjId > 0 )
312  {
313  $thisObjId = $this->getObjId();
314  }
315 
316  $clone = $this;
317  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
319  $clone->id = -1;
320 
321  if( (int)$testObjId > 0 )
322  {
323  $clone->setObjId($testObjId);
324  }
325 
326  if ($title)
327  {
328  $clone->setTitle($title);
329  }
330  if ($author)
331  {
332  $clone->setAuthor($author);
333  }
334  if ($owner)
335  {
336  $clone->setOwner($owner);
337  }
338  if ($for_test)
339  {
340  $clone->saveToDb($original_id);
341  }
342  else
343  {
344  $clone->saveToDb();
345  }
346 
347  // copy question page content
348  $clone->copyPageOfQuestion($this_id);
349  // copy XHTML media objects
350  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
351  // duplicate the generic feedback
352  $clone->duplicateFeedbackGeneric($this_id);
353 
354  // duplicate the image
355  $clone->duplicateImages($this_id, $thisObjId);
356 
357  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
358 
359  return $clone->id;
360  }
361 
365  public function copyObject($target_questionpool, $title = "")
366  {
367  if ($this->id <= 0)
368  {
369  // The question has not been saved. It cannot be duplicated
370  return;
371  }
372  // duplicate the question in database
373  $clone = $this;
374  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
376  $clone->id = -1;
377  if ($title)
378  {
379  $clone->setTitle($title);
380  }
381  $source_questionpool = $this->getObjId();
382  $clone->setObjId($target_questionpool);
383  $clone->saveToDb();
384 
385  // copy question page content
386  $clone->copyPageOfQuestion($original_id);
387  // copy XHTML media objects
388  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
389  // duplicate the generic feedback
390  $clone->duplicateFeedbackGeneric($original_id);
391 
392  // duplicate the image
393  $clone->copyImages($original_id, $source_questionpool);
394  $clone->onCopy($this->getObjId(), $this->getId());
395  return $clone->id;
396  }
397 
398  public function duplicateImages($question_id, $objectId = null)
399  {
400  global $ilLog;
401  $imagepath = $this->getImagePath();
402  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
403 
404  if( (int)$objectId > 0 )
405  {
406  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
407  }
408 
409  foreach ($this->terms as $term)
410  {
411  if (strlen($term->picture))
412  {
413  $filename = $term->picture;
414  if (!file_exists($imagepath))
415  {
416  ilUtil::makeDirParents($imagepath);
417  }
418  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
419  {
420  $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
421  }
422  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename))
423  {
424  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
425  {
426  $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
427  }
428  }
429  }
430  }
431  foreach ($this->definitions as $definition)
432  {
433  if (strlen($definition->picture))
434  {
435  $filename = $definition->picture;
436  if (!file_exists($imagepath))
437  {
438  ilUtil::makeDirParents($imagepath);
439  }
440  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
441  {
442  $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
443  }
444  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename))
445  {
446  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
447  {
448  $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
449  }
450  }
451  }
452  }
453  }
454 
455  public function copyImages($question_id, $source_questionpool)
456  {
457  global $ilLog;
458 
459  $imagepath = $this->getImagePath();
460  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
461  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
462  foreach ($this->terms as $term)
463  {
464  if (strlen($term->picture))
465  {
466  if (!file_exists($imagepath))
467  {
468  ilUtil::makeDirParents($imagepath);
469  }
470  $filename = $term->picture;
471  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
472  {
473  $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
474  }
475  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
476  {
477  $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
478  }
479  }
480  }
481  foreach ($this->definitions as $definition)
482  {
483  if (strlen($definition->picture))
484  {
485  $filename = $definition->picture;
486  if (!file_exists($imagepath))
487  {
488  ilUtil::makeDirParents($imagepath);
489  }
490  if (!copy($imagepath_original . $filename, $imagepath . $filename))
491  {
492  $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
493  }
494  if (!copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
495  {
496  $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
497  }
498  }
499  }
500  }
501 
512  public function insertMatchingPair($position, $term = null, $definition = null, $points = 0.0)
513  {
514  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
515  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
516  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
517  if (is_null($term)) $term = new assAnswerMatchingTerm();
518  if (is_null($definition)) $definition = new assAnswerMatchingDefinition();
519  $pair = new assAnswerMatchingPair($term, $definition, $points);
520  if ($position < count($this->matchingpairs))
521  {
522  $part1 = array_slice($this->matchingpairs, 0, $position);
523  $part2 = array_slice($this->matchingpairs, $position);
524  $this->matchingpairs = array_merge($part1, array($pair), $part2);
525  }
526  else
527  {
528  array_push($this->matchingpairs, $pair);
529  }
530  }
540  public function addMatchingPair($term = null, $definition = null, $points = 0.0)
541  {
542  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
543  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
544  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
545  if (is_null($term)) $term = new assAnswerMatchingTerm();
546  if (is_null($definition)) $definition = new assAnswerMatchingDefinition();
547  $pair = new assAnswerMatchingPair($term, $definition, $points);
548  array_push($this->matchingpairs, $pair);
549  }
550 
554  public function getTermWithIdentifier($a_identifier)
555  {
556  foreach ($this->terms as $term)
557  {
558  if ($term->identifier == $a_identifier) return $term;
559  }
560  return null;
561  }
562 
566  public function getDefinitionWithIdentifier($a_identifier)
567  {
568  foreach ($this->definitions as $definition)
569  {
570  if ($definition->identifier == $a_identifier) return $definition;
571  }
572  return null;
573  }
574 
583  public function getMatchingPair($index = 0)
584  {
585  if ($index < 0)
586  {
587  return NULL;
588  }
589  if (count($this->matchingpairs) < 1)
590  {
591  return NULL;
592  }
593  if ($index >= count($this->matchingpairs))
594  {
595  return NULL;
596  }
597  return $this->matchingpairs[$index];
598  }
599 
607  public function deleteMatchingPair($index = 0)
608  {
609  if ($index < 0)
610  {
611  return;
612  }
613  if (count($this->matchingpairs) < 1)
614  {
615  return;
616  }
617  if ($index >= count($this->matchingpairs))
618  {
619  return;
620  }
621  unset($this->matchingpairs[$index]);
622  $this->matchingpairs = array_values($this->matchingpairs);
623  }
624 
629  public function flushMatchingPairs()
630  {
631  $this->matchingpairs = array();
632  }
633 
640  public function getMatchingPairCount()
641  {
642  return count($this->matchingpairs);
643  }
644 
651  public function getTerms()
652  {
653  return $this->terms;
654  }
655 
662  public function getDefinitions()
663  {
664  return $this->definitions;
665  }
666 
673  public function getTermCount()
674  {
675  return count($this->terms);
676  }
677 
684  public function getDefinitionCount()
685  {
686  return count($this->definitions);
687  }
688 
695  public function addTerm($term)
696  {
697  array_push($this->terms, $term);
698  }
699 
706  public function addDefinition($definition)
707  {
708  array_push($this->definitions, $definition);
709  }
710 
717  public function insertTerm($position, $term = null)
718  {
719  if (is_null($term))
720  {
721  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
722  $term = new assAnswerMatchingTerm();
723  }
724  if ($position < count($this->terms))
725  {
726  $part1 = array_slice($this->terms, 0, $position);
727  $part2 = array_slice($this->terms, $position);
728  $this->terms = array_merge($part1, array($term), $part2);
729  }
730  else
731  {
732  array_push($this->terms, $term);
733  }
734  }
735 
742  public function insertDefinition($position, $definition = null)
743  {
744  if (is_null($definition))
745  {
746  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
747  $definition = new assAnswerMatchingDefinition();
748  }
749  if ($position < count($this->definitions))
750  {
751  $part1 = array_slice($this->definitions, 0, $position);
752  $part2 = array_slice($this->definitions, $position);
753  $this->definitions = array_merge($part1, array($definition), $part2);
754  }
755  else
756  {
757  array_push($this->definitions, $definition);
758  }
759  }
760 
765  public function flushTerms()
766  {
767  $this->terms = array();
768  }
769 
774  public function flushDefinitions()
775  {
776  $this->definitions = array();
777  }
778 
785  public function deleteTerm($position)
786  {
787  unset($this->terms[$position]);
788  $this->terms = array_values($this->terms);
789  }
790 
797  public function deleteDefinition($position)
798  {
799  unset($this->definitions[$position]);
800  $this->definitions = array_values($this->definitions);
801  }
802 
810  public function setTerm($term, $index)
811  {
812  $this->terms[$index] = $term;
813  }
814 
824  function calculateReachedPoints($active_id, $pass = NULL)
825  {
826  global $ilDB;
827 
828  $found_value1 = array();
829  $found_value2 = array();
830  if (is_null($pass))
831  {
832  $pass = $this->getSolutionMaxPass($active_id);
833  }
834  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
835  array('integer','integer','integer'),
836  array($active_id, $this->getId(), $pass)
837  );
838  while ($data = $ilDB->fetchAssoc($result))
839  {
840  if (strcmp($data["value1"], "") != 0)
841  {
842  array_push($found_value1, $data["value1"]);
843  array_push($found_value2, $data["value2"]);
844  }
845  }
846  $points = 0;
847  foreach ($found_value2 as $key => $value)
848  {
849  foreach ($this->matchingpairs as $pair)
850  {
851  if (($pair->definition->identifier == $value) && ($pair->term->identifier == $found_value1[$key]))
852  {
853  $points += $pair->points;
854  }
855  }
856  }
857 
858  $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
859  return $points;
860  }
861 
865  function getMaximumPoints()
866  {
867  $points = 0;
868  foreach ($this->matchingpairs as $key => $pair)
869  {
870  if ($pair->points > 0)
871  {
872  $points += $pair->points;
873  }
874  }
875  return $points;
876  }
877 
887  {
888  $extension = "";
889  if (preg_match("/.*\\.(\\w+)$/", $filename, $matches))
890  {
891  $extension = $matches[1];
892  }
893  return md5($filename) . "." . $extension;
894  }
895 
896  public function removeTermImage($index)
897  {
898  $term = $this->terms[$index];
899  if (is_object($term))
900  {
901  $this->deleteImagefile($term->picture);
902  $term->picture = null;
903  }
904  }
905 
906  public function removeDefinitionImage($index)
907  {
908  $definition = $this->definitions[$index];
909  if (is_object($definition))
910  {
911  $this->deleteImagefile($definition->picture);
912  $definition->picture = null;
913  }
914  }
915 
916 
923  public function deleteImagefile($filename)
924  {
925  $deletename = $filename;
926  $result = @unlink($this->getImagePath().$deletename);
927  $result = $result & @unlink($this->getImagePath().$this->getThumbPrefix() . $deletename);
928  return $result;
929  }
930 
939  function setImageFile($image_tempfilename, $image_filename, $previous_filename = '')
940  {
941  $result = TRUE;
942  if (strlen($image_tempfilename))
943  {
944  $image_filename = str_replace(" ", "_", $image_filename);
945  $imagepath = $this->getImagePath();
946  if (!file_exists($imagepath))
947  {
948  ilUtil::makeDirParents($imagepath);
949  }
950  $savename = $image_filename;
951  if (!ilUtil::moveUploadedFile($image_tempfilename, $savename, $imagepath.$savename))
952  {
953  $result = FALSE;
954  }
955  else
956  {
957  // create thumbnail file
958  $thumbpath = $imagepath . $this->getThumbPrefix() . $savename;
959  ilUtil::convertImage($imagepath.$savename, $thumbpath, "JPEG", $this->getThumbGeometry());
960  }
961  if ($result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename)))
962  {
963  $this->deleteImagefile($previous_filename);
964  }
965  }
966  return $result;
967  }
968 
975  function checkSaveData()
976  {
977  $result = true;
978  $matching_values = array();
979  foreach ($_POST['matching'][$this->getId()] as $definition => $term)
980  {
981  if ($term > 0)
982  {
983  array_push($matching_values, $term);
984  }
985  }
986 
987  $check_matching = array_flip($matching_values);
988  if (count($check_matching) != count($matching_values))
989  {
990  $result = false;
991  ilUtil::sendFailure($this->lng->txt("duplicate_matching_values_selected"), true);
992  }
993  return $result;
994  }
995 
1002  function saveWorkingData($active_id, $pass = NULL)
1003  {
1004  global $ilDB;
1005  global $ilUser;
1006  $saveWorkingDataResult = $this->checkSaveData();
1007  $entered_values = 0;
1008  if ($saveWorkingDataResult)
1009  {
1010  if (is_null($pass))
1011  {
1012  include_once "./Modules/Test/classes/class.ilObjTest.php";
1013  $pass = ilObjTest::_getPass($active_id);
1014  }
1015 
1016  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1017  array('integer','integer','integer'),
1018  array($active_id, $this->getId(), $pass)
1019  );
1020 
1021  foreach ($_POST['matching'][$this->getId()] as $definition => $term)
1022  {
1023  $entered_values++;
1024  $next_id = $ilDB->nextId('tst_solutions');
1025  $affectedRows = $ilDB->insert("tst_solutions", array(
1026  "solution_id" => array("integer", $next_id),
1027  "active_fi" => array("integer", $active_id),
1028  "question_fi" => array("integer", $this->getId()),
1029  "value1" => array("clob", $term),
1030  "value2" => array("clob", $definition),
1031  "pass" => array("integer", $pass),
1032  "tstamp" => array("integer", time())
1033  ));
1034  }
1035  $saveWorkingDataResult = true;
1036  }
1037  if ($entered_values)
1038  {
1039  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1041  {
1042  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1043  }
1044  }
1045  else
1046  {
1047  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1049  {
1050  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1051  }
1052  }
1053  parent::saveWorkingData($active_id, $pass);
1054  return $saveWorkingDataResult;
1055  }
1056 
1057  public function getRandomId()
1058  {
1059  mt_srand((double)microtime()*1000000);
1060  $random_number = mt_rand(1, 100000);
1061  $found = FALSE;
1062  while ($found)
1063  {
1064  $found = FALSE;
1065  foreach ($this->matchingpairs as $key => $pair)
1066  {
1067  if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number))
1068  {
1069  $found = TRUE;
1070  $random_number++;
1071  }
1072  }
1073  }
1074  return $random_number;
1075  }
1076 
1083  public function setShuffle($shuffle)
1084  {
1085  switch ($shuffle)
1086  {
1087  case 0:
1088  case 1:
1089  case 2:
1090  case 3:
1091  $this->shuffle = $shuffle;
1092  break;
1093  default:
1094  $this->shuffle = 1;
1095  break;
1096  }
1097  }
1098 
1104  public function getQuestionType()
1105  {
1106  return "assMatchingQuestion";
1107  }
1108 
1114  public function getAdditionalTableName()
1115  {
1116  return "qpl_qst_matching";
1117  }
1118 
1124  public function getAnswerTableName()
1125  {
1126  return array("qpl_a_matching", "qpl_a_mterm");
1127  }
1128 
1133  public function getRTETextWithMediaObjects()
1134  {
1136  }
1137 
1141  public function &getMatchingPairs()
1142  {
1143  return $this->matchingpairs;
1144  }
1145 
1151  public function supportsJavascriptOutput()
1152  {
1153  return TRUE;
1154  }
1155 
1168  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
1169  {
1170  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
1171  $solutions = $this->getSolutionValues($active_id, $pass);
1172  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
1173  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
1174  $imagepath = $this->getImagePath();
1175  $i = 1;
1176  foreach ($solutions as $solution)
1177  {
1178  $matches_written = FALSE;
1179  foreach ($this->getMatchingPairs() as $idx => $pair)
1180  {
1181  if (!$matches_written) $worksheet->writeString($startrow + $i, 1, ilExcelUtils::_convert_text($this->lng->txt("matches")));
1182  $matches_written = TRUE;
1183  if ($pair->definition->identifier == $solution["value2"])
1184  {
1185  if (strlen($pair->definition->text))
1186  {
1187  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($pair->definition->text));
1188  }
1189  else
1190  {
1191  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($pair->definition->picture));
1192  }
1193  }
1194  if ($pair->term->identifier == $solution["value1"])
1195  {
1196  if (strlen($pair->term->text))
1197  {
1198  $worksheet->writeString($startrow + $i, 2, ilExcelUtils::_convert_text($pair->term->text));
1199  }
1200  else
1201  {
1202  $worksheet->writeString($startrow + $i, 2, ilExcelUtils::_convert_text($pair->term->picture));
1203  }
1204  }
1205  }
1206  $i++;
1207  }
1208  return $startrow + $i + 1;
1209  }
1210 
1216  public function getThumbGeometry()
1217  {
1218  return $this->thumb_geometry;
1219  }
1220 
1226  public function getThumbSize()
1227  {
1228  return $this->getThumbGeometry();
1229  }
1230 
1236  public function setThumbGeometry($a_geometry)
1237  {
1238  $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1239  }
1240 
1246  public function getElementHeight()
1247  {
1248  return $this->element_height;
1249  }
1250 
1256  public function setElementHeight($a_height)
1257  {
1258  $this->element_height = ($a_height < 20) ? "" : $a_height;
1259  }
1260 
1264  public function rebuildThumbnails()
1265  {
1266  foreach ($this->terms as $term)
1267  {
1268  if (strlen($term->picture)) $this->generateThumbForFile($this->getImagePath(), $term->picture);
1269  }
1270  foreach ($this->definitions as $definition)
1271  {
1272  if (strlen($definition->picture)) $this->generateThumbForFile($this->getImagePath(), $definition->picture);
1273  }
1274  }
1275 
1276  public function getThumbPrefix()
1277  {
1278  return "thumb.";
1279  }
1280 
1281  protected function generateThumbForFile($path, $file)
1282  {
1283  $filename = $path . $file;
1284  if (@file_exists($filename))
1285  {
1286  $thumbpath = $path . $this->getThumbPrefix() . $file;
1287  $path_info = @pathinfo($filename);
1288  $ext = "";
1289  switch (strtoupper($path_info['extension']))
1290  {
1291  case 'PNG':
1292  $ext = 'PNG';
1293  break;
1294  case 'GIF':
1295  $ext = 'GIF';
1296  break;
1297  default:
1298  $ext = 'JPEG';
1299  break;
1300  }
1301  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1302  }
1303  }
1304 
1305  public function getEstimatedElementHeight()
1306  {
1307  $hasImages = false;
1308  foreach ($this->terms as $term)
1309  {
1310  if (strlen($term->picture))
1311  {
1312  $hasImages = true;
1313  }
1314  }
1315  foreach ($this->definitions as $definition)
1316  {
1317  if (strlen($definition->picture))
1318  {
1319  $hasImages = true;
1320  }
1321  }
1322  if ($hasImages)
1323  { // 40 is approx. the height of the preview image
1324  return max($this->getElementHeight(), $this->getThumbSize() + 40);
1325  }
1326  else
1327  {
1328  return ($this->getElementHeight()) ? $this->getElementHeight() : 0;
1329  }
1330  }
1331 
1336  public function toJSON()
1337  {
1338  include_once("./Services/RTE/classes/class.ilRTE.php");
1339  $result = array();
1340  $result['id'] = (int) $this->getId();
1341  $result['type'] = (string) $this->getQuestionType();
1342  $result['title'] = (string) $this->getTitle();
1343  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1344  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1345  $result['shuffle'] = true;
1346  $result['feedback'] = array(
1347  "onenotcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(0), 0)),
1348  "allcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(1), 0))
1349  );
1350  $terms = array();
1351  foreach ($this->getMatchingPairs() as $pair)
1352  {
1353  $terms[(int)$pair->term->identifier] = array(
1354  "term" => $pair->term->text,
1355  "id" =>(int)$pair->term->identifier
1356  );
1357  }
1358  $terms = $this->pcArrayShuffle($terms);
1359  $pairs = array();
1360 
1361  // alex 9.9.2010 as a fix for bug 6513 I added the question id
1362  // to the "def_id" in the array. The $pair->definition->identifier is not
1363  // unique, since it gets it value from the morder table field
1364  // this value is not changed, when a question is copied.
1365  // thus copying the same question on a page results in problems
1366  // when the second one (the copy) is answered.
1367 
1368  foreach ($this->getMatchingPairs() as $pair)
1369  {
1370  array_push($pairs, array(
1371  "term_id" => (int) $pair->term->identifier,
1372  "points" => (float) $pair->points,
1373  "definition" => (string) $pair->definition->text,
1374  "def_id" => (int) $this->getId().$pair->definition->identifier,
1375  "terms" => $terms
1376  ));
1377  }
1378  $result['pairs'] = $pairs;
1379  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1380  $result['mobs'] = $mobs;
1381 
1382  return json_encode($result);
1383  }
1384 
1385 }
1386 
1387 ?>