ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.assClozeTestImport.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assQuestionImport.php";
5 
16 {
30  function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
31  {
32  global $ilUser;
33 
34  // empty session variable for imported xhtml mobs
35  unset($_SESSION["import_mob_xhtml"]);
36  $presentation = $item->getPresentation();
37  $duration = $item->getDuration();
38 
39  $packageIliasVersion = $item->getIliasSourceVersion('ILIAS_VERSION');
40  $seperate_question_field = $item->getMetadataEntry("question");
41 
42  $questiontext = null;
43  if( !$packageIliasVersion || version_compare($packageIliasVersion, '5.0.0', '<') )
44  {
45  $questiontext = '&nbsp;';
46  }
47  elseif($seperate_question_field)
48  {
49  $questiontext = $this->processNonAbstractedImageReferences(
50  $seperate_question_field, $item->getIliasSourceNic()
51  );
52  }
53 
54  $clozetext = array();
55  $shuffle = 0;
56  $now = getdate();
57  $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
58  $gaps = array();
59  foreach ($presentation->order as $entry)
60  {
61  switch ($entry["type"])
62  {
63  case "material":
64 
65  $materialString = $this->object->QTIMaterialToString(
66  $presentation->material[$entry["index"]]
67  );
68 
69  if($questiontext === null)
70  {
71  $questiontext = $materialString;
72  }
73  else
74  {
75  array_push($clozetext, $materialString);
76  }
77 
78  break;
79  case "response":
80  $response = $presentation->response[$entry["index"]];
81  $rendertype = $response->getRenderType();
82  array_push($clozetext, "<<" . $response->getIdent() . ">>");
83 
84  switch (strtolower(get_class($response->getRenderType())))
85  {
86  case "ilqtirenderfib":
87  switch ($response->getRenderType()->getFibtype())
88  {
89  case FIBTYPE_DECIMAL:
90  case FIBTYPE_INTEGER:
91  array_push($gaps,
92  array(
93  "ident" => $response->getIdent(),
94  "type" => CLOZE_NUMERIC,
95  "answers" => array(),
96  "minnumber" => $response->getRenderType()->getMinnumber(),
97  "maxnumber" => $response->getRenderType()->getMaxnumber(),
98  'gap_size' => $response->getRenderType()->getMaxchars()
99  )
100  );
101  break;
102  default:
103  case FIBTYPE_STRING:
104  array_push($gaps,
105  array("ident" => $response->getIdent(),
106  "type" => CLOZE_TEXT,
107  "answers" => array(),
108  'gap_size' => $response->getRenderType()->getMaxchars()
109  ));
110  break;
111  }
112  break;
113  case "ilqtirenderchoice":
114  $answers = array();
115  $shuffle = $rendertype->getShuffle();
116  $answerorder = 0;
117  foreach ($rendertype->response_labels as $response_label)
118  {
119  $ident = $response_label->getIdent();
120  $answertext = "";
121  foreach ($response_label->material as $mat)
122  {
123  $answertext .= $this->object->QTIMaterialToString($mat);
124  }
125  $answers[$ident] = array(
126  "answertext" => $answertext,
127  "points" => 0,
128  "answerorder" => $answerorder++,
129  "action" => "",
130  "shuffle" => $rendertype->getShuffle()
131  );
132  }
133  array_push($gaps, array("ident" => $response->getIdent(), "type" => CLOZE_SELECT, "shuffle" => $rendertype->getShuffle(), "answers" => $answers));
134  break;
135  }
136  break;
137  }
138  }
139  $responses = array();
140  $feedbacks = array();
141  $feedbacksgeneric = array();
142  foreach ($item->resprocessing as $resprocessing)
143  {
144  foreach ($resprocessing->respcondition as $respcondition)
145  {
146  $ident = "";
147  $correctness = 1;
148  $conditionvar = $respcondition->getConditionvar();
149  foreach ($conditionvar->order as $order)
150  {
151  switch ($order["field"])
152  {
153  case "varequal":
154  $equals = $conditionvar->varequal[$order["index"]]->getContent();
155  $gapident = $conditionvar->varequal[$order["index"]]->getRespident();
156  break;
157  }
158  }
159  foreach ($respcondition->setvar as $setvar)
160  {
161  if (strcmp($gapident, "") != 0)
162  {
163  foreach ($gaps as $gi => $g)
164  {
165  if (strcmp($g["ident"], $gapident) == 0)
166  {
167  if ($g["type"] == CLOZE_SELECT)
168  {
169  foreach ($gaps[$gi]["answers"] as $ai => $answer)
170  {
171  if (strcmp($answer["answertext"], $equals) == 0)
172  {
173  $gaps[$gi]["answers"][$ai]["action"] = $setvar->getAction();
174  $gaps[$gi]["answers"][$ai]["points"] = $setvar->getContent();
175  }
176  }
177  }
178  else if ($g["type"] == CLOZE_TEXT)
179  {
180  array_push($gaps[$gi]["answers"], array(
181  "answertext" => $equals,
182  "points" => $setvar->getContent(),
183  "answerorder" => count($gaps[$gi]["answers"]),
184  "action" => $setvar->getAction()
185 
186  ));
187  }
188  else if ($g["type"] == CLOZE_NUMERIC)
189  {
190  array_push($gaps[$gi]["answers"], array(
191  "answertext" => $equals,
192  "points" => $setvar->getContent(),
193  "answerorder" => count($gaps[$gi]["answers"]),
194  "action" => $setvar->getAction()
195  ));
196  }
197  }
198  }
199  }
200  }
201 
202  if (count($respcondition->displayfeedback))
203  {
204  foreach ($respcondition->displayfeedback as $feedbackpointer)
205  {
206  if (strlen($feedbackpointer->getLinkrefid()))
207  {
208  foreach ($item->itemfeedback as $ifb)
209  {
210  if (strcmp($ifb->getIdent(), "response_allcorrect") == 0)
211  {
212  // found a feedback for the identifier
213  if (count($ifb->material))
214  {
215  foreach ($ifb->material as $material)
216  {
217  $feedbacksgeneric[1] = $material;
218  }
219  }
220  if ((count($ifb->flow_mat) > 0))
221  {
222  foreach ($ifb->flow_mat as $fmat)
223  {
224  if (count($fmat->material))
225  {
226  foreach ($fmat->material as $material)
227  {
228  $feedbacksgeneric[1] = $material;
229  }
230  }
231  }
232  }
233  }
234  else if (strcmp($ifb->getIdent(), "response_onenotcorrect") == 0)
235  {
236  // found a feedback for the identifier
237  if (count($ifb->material))
238  {
239  foreach ($ifb->material as $material)
240  {
241  $feedbacksgeneric[0] = $material;
242  }
243  }
244  if ((count($ifb->flow_mat) > 0))
245  {
246  foreach ($ifb->flow_mat as $fmat)
247  {
248  if (count($fmat->material))
249  {
250  foreach ($fmat->material as $material)
251  {
252  $feedbacksgeneric[0] = $material;
253  }
254  }
255  }
256  }
257  }
258  else
259  {
260  // found a feedback for the identifier
261  if (count($ifb->material))
262  {
263  foreach ($ifb->material as $material)
264  {
265  $feedbacks[$ifb->getIdent()] = $material;
266  }
267  }
268  if ((count($ifb->flow_mat) > 0))
269  {
270  foreach ($ifb->flow_mat as $fmat)
271  {
272  if (count($fmat->material))
273  {
274  foreach ($fmat->material as $material)
275  {
276  $feedbacks[$ifb->getIdent()] = $material;
277  }
278  }
279  }
280  }
281 
282  }
283  }
284  }
285  }
286  }
287 
288  }
289  }
290 
291  $this->addGeneralMetadata($item);
292  $this->object->setTitle($item->getTitle());
293  $this->object->setNrOfTries($item->getMaxattempts());
294  $this->object->setComment($item->getComment());
295  $this->object->setAuthor($item->getAuthor());
296  $this->object->setOwner($ilUser->getId());
297  $this->object->setObjId($questionpool_id);
298  $this->object->setEstimatedWorkingTime($duration["h"], $duration["m"], $duration["s"]);
299  $textgap_rating = $item->getMetadataEntry("textgaprating");
300  $this->object->setFixedTextLength($item->getMetadataEntry("fixedTextLength"));
301  $this->object->setIdenticalScoring($item->getMetadataEntry("identicalScoring"));
302  $combination = json_decode(base64_decode($item->getMetadataEntry("combinations")));
303  if (strlen($textgap_rating) == 0) $textgap_rating = "ci";
304  $this->object->setTextgapRating($textgap_rating);
305  $gaptext = array();
306  foreach ($gaps as $gapidx => $gap)
307  {
308  $gapcontent = array();
309  include_once "./Modules/TestQuestionPool/classes/class.assClozeGap.php";
310  $clozegap = new assClozeGap($gap["type"]);
311  foreach ($gap["answers"] as $index => $answer)
312  {
313  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
314  $gapanswer = new assAnswerCloze($answer["answertext"], $answer["points"], $answer["answerorder"]);
315  $gapanswer->setGapSize($gap["gap_size"]);
316  switch ($clozegap->getType())
317  {
318  case CLOZE_SELECT:
319  $clozegap->setShuffle($answer["shuffle"]);
320  break;
321  case CLOZE_NUMERIC:
322  $gapanswer->setLowerBound($gap["minnumber"]);
323  $gapanswer->setUpperBound($gap["maxnumber"]);
324  break;
325  }
326  $clozegap->setGapSize($gap["gap_size"]);
327  $clozegap->addItem($gapanswer);
328  array_push($gapcontent, $answer["answertext"]);
329  }
330  $this->object->addGapAtIndex($clozegap, $gapidx);
331  $gaptext[$gap["ident"]] = "[gap]" . join(",", $gapcontent). "[/gap]";
332  }
333 
334  $this->object->setQuestion($questiontext);
335  $clozetext = join("", $clozetext);
336 
337  foreach ($gaptext as $idx => $val)
338  {
339  $clozetext = str_replace("<<" . $idx . ">>", $val, $clozetext);
340  }
341  $this->object->setClozeTextValue($clozetext);
342 
343  // additional content editing mode information
344  $this->object->setAdditionalContentEditingMode(
346  );
347  $this->object->saveToDb();
348 
349  // handle the import of media objects in XHTML code
350  foreach ($feedbacks as $ident => $material)
351  {
352  $m = $this->object->QTIMaterialToString($material);
353  $feedbacks[$ident] = $m;
354  }
355  foreach ($feedbacksgeneric as $correctness => $material)
356  {
357  $m = $this->object->QTIMaterialToString($material);
358  $feedbacksgeneric[$correctness] = $m;
359  }
360  $questiontext = $this->object->getQuestion();
361  $clozetext = $this->object->getClozeText();
362  if (is_array($_SESSION["import_mob_xhtml"]))
363  {
364  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
365  include_once "./Services/RTE/classes/class.ilRTE.php";
366  foreach ($_SESSION["import_mob_xhtml"] as $mob)
367  {
368  if ($tst_id > 0)
369  {
370  $importfile = $this->getTstImportArchivDirectory() . '/' . $mob["uri"];
371  }
372  else
373  {
374  $importfile = $this->getQplImportArchivDirectory() . '/' . $mob["uri"];
375  }
376 
377  $GLOBALS['ilLog']->write(__METHOD__.': import mob from dir: '. $importfile);
378 
379  $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
380  $questiontext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $questiontext);
381  $clozetext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $clozetext);
382  foreach ($feedbacks as $ident => $material)
383  {
384  $feedbacks[$ident] = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $material);
385  }
386  foreach ($feedbacksgeneric as $correctness => $material)
387  {
388  $feedbacksgeneric[$correctness] = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $material);
389  }
390  }
391  }
392  $this->object->setQuestion(ilRTE::_replaceMediaObjectImageSrc($questiontext, 1));
393  $this->object->setClozeTextValue(ilRTE::_replaceMediaObjectImageSrc($clozetext, 1));
394  foreach ($feedbacks as $ident => $material)
395  {
396  $this->object->feedbackOBJ->importSpecificAnswerFeedback(
397  $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
398  );
399  }
400  foreach ($feedbacksgeneric as $correctness => $material)
401  {
402  $this->object->feedbackOBJ->importGenericFeedback(
403  $this->object->getId(), $correctness, ilRTE::_replaceMediaObjectImageSrc($material, 1)
404  );
405  }
406  $this->object->saveToDb();
407  if (count($item->suggested_solutions))
408  {
409  foreach ($item->suggested_solutions as $suggested_solution)
410  {
411  $this->object->setSuggestedSolution($suggested_solution["solution"]->getContent(), $suggested_solution["gap_index"], true);
412  }
413  $this->object->saveToDb();
414  }
415  if ($tst_id > 0)
416  {
417  $q_1_id = $this->object->getId();
418  $question_id = $this->object->duplicate(true, null, null, null, $tst_id);
419  $tst_object->questions[$question_counter++] = $question_id;
420  $import_mapping[$item->getIdent()] = array("pool" => $q_1_id, "test" => $question_id);
421  }
422  else
423  {
424  $import_mapping[$item->getIdent()] = array("pool" => $this->object->getId(), "test" => 0);
425  }
426  $this->object->saveToDb();
427  if(count($combination) > 0)
428  {
429  require_once './Modules/TestQuestionPool/classes/class.assClozeGapCombination.php';
431  assClozeGapCombination::importGapCombinationToDb($this->object->getId(),$combination);
432  }
433  $this->object->saveToDb();
434  }
435 }
436 
437 ?>
Class for cloze question numeric answers.
addGeneralMetadata(ilQTIItem $item)
$_SESSION["AccountId"]
static importGapCombinationToDb($question_id, $gap_combinations)
const CLOZE_TEXT
Cloze question constants.
processNonAbstractedImageReferences($text, $sourceNic)
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
fetchAdditionalContentEditingModeInformation($qtiItem)
fetches the "additional content editing mode" information from qti item and falls back to ADDITIONAL_...
getQplImportArchivDirectory()
returns the full path to extracted qpl import archiv (qpl import dir + qpl archiv subdir) ...
Class for cloze question gaps.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
$ai
Definition: langwiz.php:238
const CLOZE_SELECT
const FIBTYPE_STRING
static _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
$ilUser
Definition: imgupload.php:18
const FIBTYPE_INTEGER
static clearGapCombinationsFromDb($question_id)
Create styles array
The data for the language used.
const FIBTYPE_DECIMAL
Create new PHPExcel object
obj_idprivate
Class for cloze question imports.
getTstImportArchivDirectory()
returns the full path to extracted tst import archiv (tst import dir + tst archiv subdir) ...
const CLOZE_NUMERIC
Class for question imports.