4 require_once
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8 require_once
'./Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9 require_once
'./Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
95 $this->matchingpairs = array();
97 $this->terms = array();
98 $this->definitions = array();
108 if (strlen($this->title)
111 && count($this->matchingpairs)
142 $ilDB->manipulateF(
"DELETE FROM qpl_a_mterm WHERE question_fi = %s",
144 array( $this->
getId() )
148 $ilDB->manipulateF(
"DELETE FROM qpl_a_mdef WHERE question_fi = %s",
150 array( $this->
getId() )
155 foreach ($this->terms as $key => $term)
157 $next_id = $ilDB->nextId(
'qpl_a_mterm' );
158 $ilDB->manipulateF(
"INSERT INTO qpl_a_mterm (term_id, question_fi, picture, term) VALUES (%s, %s, %s, %s)",
159 array(
'integer',
'integer',
'text',
'text' ),
160 array( $next_id, $this->
getId(), $term->picture, $term->text )
162 $termids[$term->identifier] = $next_id;
165 $definitionids = array();
167 foreach ($this->definitions as $key => $definition)
169 $next_id = $ilDB->nextId(
'qpl_a_mdef' );
170 $ilDB->manipulateF(
"INSERT INTO qpl_a_mdef (def_id, question_fi, picture, definition, morder) VALUES (%s, %s, %s, %s, %s)",
171 array(
'integer',
'integer',
'text',
'text',
'integer' ),
172 array( $next_id, $this->
getId(
173 ), $definition->picture, $definition->text, $definition->identifier )
175 $definitionids[$definition->identifier] = $next_id;
178 $ilDB->manipulateF(
"DELETE FROM qpl_a_matching WHERE question_fi = %s",
180 array( $this->
getId() )
185 $next_id = $ilDB->nextId(
'qpl_a_matching' );
186 $ilDB->manipulateF(
"INSERT INTO qpl_a_matching (answer_id, question_fi, points, term_fi, definition_fi) VALUES (%s, %s, %s, %s, %s)",
187 array(
'integer',
'integer',
'float',
'integer',
'integer' ),
192 $termids[$pair->term->identifier],
193 $definitionids[$pair->definition->identifier]
209 array(
"integer" ), array( $this->
getId() )
213 'question_fi' => array(
'integer', $this->
getId()),
214 'shuffle' => array(
'text', $this->shuffle),
215 'matching_type' => array(
'text', $this->matching_type),
232 SELECT qpl_questions.*,
233 {$this->getAdditionalTableName()}.*
235 LEFT JOIN {$this->getAdditionalTableName()}
236 ON {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id
237 WHERE qpl_questions.question_id = %s
241 $query, array(
'integer'), array($question_id)
246 $data = $ilDB->fetchAssoc(
$result);
247 $this->
setId($question_id);
256 include_once(
"./Services/RTE/classes/class.ilRTE.php");
260 $this->
setMatchingMode($data[
'matching_mode'] === null ? self::MATCHING_MODE_1_ON_1 : $data[
'matching_mode']);
261 $this->
setEstimatedWorkingTime(substr($data[
"working_time"], 0, 2), substr($data[
"working_time"], 3, 2), substr($data[
"working_time"], 6, 2));
273 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
277 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
278 $this->terms = array();
281 while ($data = $ilDB->fetchAssoc(
$result))
284 array_push($this->terms, $term);
285 $termids[$data[
'term_id']] = $term;
289 $definitionids = array();
290 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
294 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
295 $this->definitions = array();
298 while ($data = $ilDB->fetchAssoc(
$result))
301 array_push($this->definitions, $definition);
302 $definitionids[$data[
'def_id']] = $definition;
306 $this->matchingpairs = array();
307 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
311 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
314 while ($data = $ilDB->fetchAssoc(
$result))
316 array_push($this->matchingpairs,
new assAnswerMatchingPair($termids[$data[
'term_fi']], $definitionids[$data[
'definition_fi']], $data[
'points']));
334 $this_id = $this->
getId();
338 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
342 if( (
int)$testObjId > 0 )
344 $clone->setObjId($testObjId);
369 $clone->copyPageOfQuestion($this_id);
371 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
373 $clone->duplicateImages($this_id, $thisObjId);
375 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
392 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
395 $source_questionpool_id = $this->
getObjId();
396 $clone->setObjId($target_questionpool_id);
407 $clone->copyImages(
$original_id, $source_questionpool_id);
409 $clone->onCopy($source_questionpool_id,
$original_id, $clone->getObjId(), $clone->getId());
422 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
425 $sourceParentId = $this->
getObjId();
431 $clone->setObjId($targetParentId);
433 if ($targetQuestionTitle)
435 $clone->setTitle($targetQuestionTitle);
440 $clone->copyPageOfQuestion($sourceQuestionId);
442 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
444 $clone->copyImages($sourceQuestionId, $sourceParentId);
446 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
455 $imagepath_original = str_replace(
"/$this->id/images",
"/$question_id/images", $imagepath);
457 if( (
int)$objectId > 0 )
459 $imagepath_original = str_replace(
"/$this->obj_id/",
"/$objectId/", $imagepath_original);
462 foreach ($this->terms as $term)
464 if (strlen($term->picture))
467 if (!file_exists($imagepath))
471 if (!@copy($imagepath_original .
$filename, $imagepath . $filename))
473 $ilLog->write(
"matching question image could not be duplicated: $imagepath_original$filename");
475 if (@file_exists($imagepath_original . $this->
getThumbPrefix() . $filename))
479 $ilLog->write(
"matching question image thumbnail could not be duplicated: $imagepath_original" . $this->
getThumbPrefix() . $filename);
484 foreach ($this->definitions as $definition)
486 if (strlen($definition->picture))
489 if (!file_exists($imagepath))
493 if (!@copy($imagepath_original .
$filename, $imagepath . $filename))
495 $ilLog->write(
"matching question image could not be duplicated: $imagepath_original$filename");
497 if (@file_exists($imagepath_original . $this->
getThumbPrefix() . $filename))
501 $ilLog->write(
"matching question image thumbnail could not be duplicated: $imagepath_original" . $this->
getThumbPrefix() . $filename);
508 public function copyImages($question_id, $source_questionpool)
513 $imagepath_original = str_replace(
"/$this->id/images",
"/$question_id/images", $imagepath);
514 $imagepath_original = str_replace(
"/$this->obj_id/",
"/$source_questionpool/", $imagepath_original);
515 foreach ($this->terms as $term)
517 if (strlen($term->picture))
519 if (!file_exists($imagepath))
524 if (!@copy($imagepath_original .
$filename, $imagepath . $filename))
526 $ilLog->write(
"matching question image could not be copied: $imagepath_original$filename");
530 $ilLog->write(
"matching question image thumbnail could not be copied: $imagepath_original" . $this->
getThumbPrefix() . $filename);
534 foreach ($this->definitions as $definition)
536 if (strlen($definition->picture))
539 if (!file_exists($imagepath))
543 if (!copy($imagepath_original .
$filename, $imagepath . $filename))
545 $ilLog->write(
"matching question image could not be copied: $imagepath_original$filename");
549 $ilLog->write(
"matching question image thumbnail could not be copied: $imagepath_original" . $this->
getThumbPrefix() . $filename);
567 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
568 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
569 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
573 if ($position < count($this->matchingpairs))
575 $part1 = array_slice($this->matchingpairs, 0, $position);
576 $part2 = array_slice($this->matchingpairs, $position);
577 $this->matchingpairs = array_merge($part1, array($pair), $part2);
581 array_push($this->matchingpairs, $pair);
598 require_once
'./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php';
599 require_once
'./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php';
600 require_once
'./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php';
605 if (is_null($definition))
610 array_push($this->matchingpairs, $pair);
618 foreach ($this->terms as $term)
620 if ($term->identifier == $a_identifier)
return $term;
630 foreach ($this->definitions as $definition)
632 if ($definition->identifier == $a_identifier)
return $definition;
651 if (count($this->matchingpairs) < 1)
655 if ($index >= count($this->matchingpairs))
659 return $this->matchingpairs[$index];
675 if (count($this->matchingpairs) < 1)
679 if ($index >= count($this->matchingpairs))
683 unset($this->matchingpairs[$index]);
684 $this->matchingpairs = array_values($this->matchingpairs);
693 $this->matchingpairs = array();
704 return count($this->matchingpairs);
737 return count($this->terms);
748 return count($this->definitions);
759 array_push($this->terms, $term);
770 array_push($this->definitions, $definition);
783 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
786 if ($position < count($this->terms))
788 $part1 = array_slice($this->terms, 0, $position);
789 $part2 = array_slice($this->terms, $position);
790 $this->terms = array_merge($part1, array($term), $part2);
794 array_push($this->terms, $term);
806 if (is_null($definition))
808 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
811 if ($position < count($this->definitions))
813 $part1 = array_slice($this->definitions, 0, $position);
814 $part2 = array_slice($this->definitions, $position);
815 $this->definitions = array_merge($part1, array($definition), $part2);
819 array_push($this->definitions, $definition);
829 $this->terms = array();
838 $this->definitions = array();
849 unset($this->terms[$position]);
850 $this->terms = array_values($this->terms);
861 unset($this->definitions[$position]);
862 $this->definitions = array_values($this->definitions);
874 $this->terms[$index] = $term;
891 throw new ilTestException(
'return details not implemented for '.__METHOD__);
896 $found_values = array();
901 $result = $this->getCurrentSolutionResultSet($active_id,
$pass);
902 while ($data = $ilDB->fetchAssoc(
$result))
904 if (strcmp($data[
"value1"],
"") != 0)
906 if( !isset($found_values[$data[
'value2']]) )
908 $found_values[$data[
'value2']] = array();
911 $found_values[$data[
'value2']][] = $data[
'value1'];
951 $matchingPairs = array();
953 foreach( $this->matchingpairs as $pair )
955 if( $pair->points <= 0 )
960 $matchingPairs[] = $pair;
963 return $matchingPairs;
968 $matchingPairsByDefinition = array();
970 foreach( $this->matchingpairs as $pair )
972 if( $pair->points <= 0 )
977 $defId = $pair->definition->identifier;
979 if( !isset($matchingPairsByDefinition[$defId]) )
981 $matchingPairsByDefinition[$defId] = $pair;
983 elseif( $pair->points > $matchingPairsByDefinition[$defId]->points )
985 $matchingPairsByDefinition[$defId] = $pair;
989 return $matchingPairsByDefinition;
1003 if (preg_match(
"/.*\\.(\\w+)$/",
$filename, $matches))
1005 $extension = $matches[1];
1007 return md5(
$filename) .
"." . $extension;
1012 $term = $this->terms[$index];
1013 if (is_object($term))
1016 $term->picture = null;
1022 $definition = $this->definitions[$index];
1023 if (is_object($definition))
1026 $definition->picture = null;
1053 function setImageFile($image_tempfilename, $image_filename, $previous_filename =
'')
1056 if (strlen($image_tempfilename))
1058 $image_filename = str_replace(
" ",
"_", $image_filename);
1060 if (!file_exists($imagepath))
1064 $savename = $image_filename;
1075 if (
$result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename)))
1087 $matchings = array();
1091 if( isset($postData[$definition->identifier]) )
1093 foreach( $this->
getTerms() as $term )
1095 if( isset($postData[$definition->identifier][$term->identifier]) )
1097 if( !is_array($postData[$definition->identifier]) )
1099 $postData[$definition->identifier] = array();
1102 $matchings[$definition->identifier][] = $term->identifier;
1118 $handledTerms = array();
1120 foreach( $submittedMatchings as $definition =>
$terms )
1128 foreach(
$terms as $i => $term )
1130 if( isset($handledTerms[$term]) )
1136 $handledTerms[$term] = $term;
1158 $matchingsExist =
false;
1160 if ($submittedMatchingsValid)
1164 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1170 $affectedRows = $this->removeCurrentSolution($active_id,
$pass);
1172 foreach( $submittedMatchings as $definition =>
$terms )
1174 foreach(
$terms as $i => $term )
1176 $affectedRows = $this->saveCurrentSolution($active_id,
$pass, $term, $definition);
1178 $matchingsExist =
true;
1184 $saveWorkingDataResult =
true;
1188 $saveWorkingDataResult =
false;
1191 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1194 if( $matchingsExist )
1204 return $saveWorkingDataResult;
1232 mt_srand((
double)microtime()*1000000);
1233 $random_number = mt_rand(1, 100000);
1238 foreach ($this->matchingpairs as $key => $pair)
1240 if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number))
1247 return $random_number;
1279 return "assMatchingQuestion";
1289 return "qpl_qst_matching";
1299 return array(
"qpl_a_matching",
"qpl_a_mterm");
1333 include_once (
"./Services/Excel/classes/class.ilExcelUtils.php");
1339 foreach ($solutions as $solution)
1341 $matches_written = FALSE;
1345 $matches_written = TRUE;
1346 if ($pair->definition->identifier == $solution[
"value2"])
1348 if (strlen($pair->definition->text))
1357 if ($pair->term->identifier == $solution[
"value1"])
1359 if (strlen($pair->term->text))
1371 return $startrow + $i + 1;
1401 $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1409 foreach ($this->terms as $term)
1413 foreach ($this->definitions as $definition)
1432 switch (strtoupper($path_info[
'extension']))
1464 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1465 'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1469 foreach ($this->
getTerms() as $term)
1472 "text" => $term->text,
1473 "id" =>(
int)$term->identifier
1489 "text" => (
string) $def->text,
1490 "id" => (
int) $this->getId().$def->identifier
1496 $matchings = array();
1499 $pid = $pair->definition->identifier;
1502 $pid .=
'::'.$pair->term->identifier;
1505 if( !isset($matchings[$pid]) || $matchings[$pid][
"points"] < $pair->points )
1507 $matchings[$pid] = array(
1508 "term_id" => (
int) $pair->term->identifier,
1509 "def_id" => (
int) $this->getId().$pair->definition->identifier,
1510 "points" => (int) $pair->points
1515 $result[
'matchingPairs'] = array_values($matchings);
1521 $lng->loadLanguageModule(
'assessment');
1522 $result[
'reset_button_label'] = $lng->txt(
"reset_terms");
1554 foreach($found_values as $definition =>
$terms)
1558 foreach($this->matchingpairs as $pair)
1560 if($pair->definition->identifier == $definition && $pair->term->identifier == $term)
1580 require_once
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1611 $data = $ilDB->queryF(
1612 "SELECT morder FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id",
1614 array($this->
getId())
1618 for($index=1; $index <= $ilDB->numRows($data); ++$index)
1620 $row = $ilDB->fetchAssoc($data);
1624 $data = $ilDB->queryF(
1625 "SELECT term_id FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id",
1627 array($this->
getId())
1631 for($index=1; $index <= $ilDB->numRows($data); ++$index)
1633 $row = $ilDB->fetchAssoc($data);
1637 $data = $ilDB->queryF(
1638 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = (
1639 SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s
1641 array(
"integer",
"integer",
"integer",
"integer",
"integer",
"integer"),
1645 while(
$row = $ilDB->fetchAssoc($data))
1647 if(
$row[
"value1"] > 0)