ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
assClozeTestImport Class Reference

This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V. More...

+ Inheritance diagram for assClozeTestImport:
+ Collaboration diagram for assClozeTestImport:

Public Member Functions

 fromXML (string $importdirectory, int $user_id, ilQTIItem $item, int $questionpool_id, ?int $tst_id, ?ilObject &$tst_object, int &$question_counter, array $import_mapping)
 Creates a question from a QTI file. More...
 
- Public Member Functions inherited from assQuestionImport
 getQuestionId ()
 
 getFeedbackGeneric ($item)
 
 fromXML (string $importdirectory, int $user_id, ilQTIItem $item, int $questionpool_id, ?int $tst_id, ?ilObject &$tst_object, int &$question_counter, array $import_mapping)
 
 importSuggestedSolutions (int $question_id, array $solution_from_import)
 
 QTIMaterialToString (ilQTIMaterial $a_material)
 Reads an QTI material tag and creates a text or XHTML string. More...
 

Protected Member Functions

 buildFeedbackIdentifier ($ident)
 
- Protected Member Functions inherited from assQuestionImport
 fetchIndexFromFeedbackIdent ($feedbackIdent, $prefix='response_')
 
 getFeedbackAnswerSpecific (ilQTIItem $item, $prefix='response_')
 
 addGeneralMetadata (ilQTIItem $item)
 
 fetchLifecycle (ilQTIItem $item)
 
 processNonAbstractedImageReferences ($text, $sourceNic)
 
 fetchAdditionalContentEditingModeInformation ($qtiItem)
 fetches the "additional content editing mode" information from qti item and falls back to ADDITIONAL_CONTENT_EDITING_MODE_RTE when no or invalid information is given More...
 
 findSolutionTypeByValue (string $value)
 
 getSuggestedSolutionsRepo ()
 
 deduceThumbSizeFromImportValue (?int $size)
 
 addQuestionToParentObjectAndBuildMappingEntry (int $questionpool_id, ?int $tst_id, int &$question_counter, ?ilObjTest &$tst_object)
 

Private Attributes

ilDBInterface $db
 

Additional Inherited Members

- Data Fields inherited from assQuestionImport
 $object
 
- Protected Attributes inherited from assQuestionImport
SuggestedSolutionsDatabaseRepository $suggestedsolution_repo = null
 

Detailed Description

This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V.

ILIAS is licensed with the GPL-3.0, see https://www.gnu.org/licenses/gpl-3.0.en.html You should have received a copy of said license along with the source code, too.

If this is not the case or you just want to try ILIAS, you'll find us at: https://www.ilias.de https://github.com/ILIAS-eLearning Class for cloze question imports

assClozeTestImport is a class for cloze question imports

Author
Helmut Schottmüller helmu.nosp@m.t.sc.nosp@m.hottm.nosp@m.uell.nosp@m.er@ma.nosp@m.c.co.nosp@m.m
Version
$Id$ \

Definition at line 28 of file class.assClozeTestImport.php.

Member Function Documentation

◆ buildFeedbackIdentifier()

assClozeTestImport::buildFeedbackIdentifier (   $ident)
protected
Parameters
string$ident
Returns
ilAssSpecificFeedbackIdentifier

Definition at line 366 of file class.assClozeTestImport.php.

Referenced by fromXML().

367  {
368  $fbIdentifier = new ilAssSpecificFeedbackIdentifier();
369 
370  $ident = explode('_', $ident);
371 
372  if (count($ident) > 1) {
373  $fbIdentifier->setQuestionIndex($ident[0]);
374  $fbIdentifier->setAnswerIndex($ident[1]);
375  } else {
376  $fbIdentifier->setQuestionIndex($ident[0]);
377  $fbIdentifier->setAnswerIndex(0);
378  }
379 
380  return $fbIdentifier;
381  }
+ Here is the caller graph for this function:

◆ fromXML()

assClozeTestImport::fromXML ( string  $importdirectory,
int  $user_id,
ilQTIItem  $item,
int  $questionpool_id,
?int  $tst_id,
?ilObject $tst_object,
int &  $question_counter,
array  $import_mapping 
)

Creates a question from a QTI file.

Receives parameters from a QTI parser and creates a valid ILIAS question object

Parameters
ilQTIItem$itemThe QTI item object
integer$questionpool_idThe id of the parent questionpool
integer$tst_idThe id of the parent test if the question is part of a test
object$tst_objectA reference to the parent test object
integer$question_counterA reference to a question counter to count the questions of an imported question pool
array$import_mappingAn array containing references to included ILIAS objects public

2024-11-06, sk: This is needed because the question-text is actually saved as the first entry in the material- node.

Definition at line 54 of file class.assClozeTestImport.php.

References $DIC, $response, ilRTE\_replaceMediaObjectImageSrc(), ilObjMediaObject\_saveTempFileAsMediaObject(), assQuestionImport\addGeneralMetadata(), assQuestionImport\addQuestionToParentObjectAndBuildMappingEntry(), buildFeedbackIdentifier(), ilSession\clear(), ilAssClozeTestFeedback\FB_MODE_GAP_QUESTION, assQuestionImport\fetchAdditionalContentEditingModeInformation(), ilQTIRenderFib\FIBTYPE_DECIMAL, ilQTIRenderFib\FIBTYPE_INTEGER, ilSession\get(), ilQTIItem\getAuthor(), ilQTIItem\getComment(), ilQTIItem\getIdent(), ilQTIItem\getIliasSourceNic(), ilQTIItem\getMaxattempts(), ilQTIItem\getMetadataEntry(), ilQTIItem\getPresentation(), ilQTIItem\getTitle(), IL_INST_ID, assQuestionImport\importSuggestedSolutions(), ILIAS\Repository\object(), assQuestionImport\processNonAbstractedImageReferences(), assQuestionImport\QTIMaterialToString(), assClozeGap\TYPE_NUMERIC, assClozeGap\TYPE_SELECT, and assClozeGap\TYPE_TEXT.

63  : array {
64  // empty session variable for imported xhtml mobs
65  ilSession::clear('import_mob_xhtml');
66  $presentation = $item->getPresentation();
67 
68  $questiontext = $this->processNonAbstractedImageReferences(
69  $item->getMetadataEntry('question') ?? ' ',
70  $item->getIliasSourceNic()
71  );
72 
73  $clozetext_array = [];
74  $gaps = [];
75  foreach ($presentation->order as $entry) {
76  if ($entry['type'] === 'material') {
77  $material_string = $this->QTIMaterialToString(
78  $presentation->material[$entry['index']]
79  );
80 
81  if ($questiontext === ' ') {
87  $questiontext = $material_string;
88  continue;
89  }
90 
91  $clozetext_array[] = $material_string;
92  continue;
93  }
94 
95  if ($entry['type'] === 'response') {
96  $response = $presentation->response[$entry['index']];
97  $clozetext_array[] = "<<{$response->getIdent()}>>";
98 
99  if ($response->getRenderType() instanceof ilQTIRenderFib) {
100  $fibtype = $response->getRenderType()->getFibtype();
101  if ($fibtype === ilQTIRenderFib::FIBTYPE_DECIMAL
102  || $fibtype === ilQTIRenderFib::FIBTYPE_INTEGER) {
103  $gaps[] = [
104  'ident' => $response->getIdent(),
105  'type' => assClozeGap::TYPE_NUMERIC,
106  'answers' => [],
107  'minnumber' => $response->getRenderType()->getMinnumber(),
108  'maxnumber' => $response->getRenderType()->getMaxnumber(),
109  'gap_size' => $response->getRenderType()->getMaxchars()
110  ];
111  continue;
112  }
113 
114  $gaps[] = [
115  'ident' => $response->getIdent(),
116  'type' => assClozeGap::TYPE_TEXT,
117  'answers' => [],
118  'gap_size' => $response->getRenderType()->getMaxchars()
119  ];
120  continue;
121  }
122 
123  if ($response->getRenderType() instanceof ilQTIRenderChoice) {
124  $answers = [];
125  $answerorder = 0;
126  foreach ($response->getRenderType()->response_labels as $response_label) {
127  $ident = $response_label->getIdent();
128  $answertext = '';
129  foreach ($response_label->material as $mat) {
130  $answertext .= $this->QTIMaterialToString($mat);
131  }
132  $answers[$ident] = [
133  'answertext' => $answertext,
134  'points' => 0,
135  'answerorder' => $answerorder++,
136  'action' => '',
137  'shuffle' => $response->getRenderType()->getShuffle()
138  ];
139  }
140  $gaps[] = [
141  'ident' => $response->getIdent(),
142  'type' => assClozeGap::TYPE_SELECT,
143  'shuffle' => $response->getRenderType()->getShuffle(),
144  'answers' => $answers
145  ];
146  }
147  }
148  }
149  $feedbacks = [];
150  $feedbacksgeneric = [];
151  foreach ($item->resprocessing as $resprocessing) {
152  foreach ($resprocessing->respcondition as $respcondition) {
153  $ident = '';
154  $correctness = 1;
155  $conditionvar = $respcondition->getConditionvar();
156  $equals = '';
157  $gapident = '';
158  foreach ($conditionvar->order as $order) {
159  if ($order['field'] === 'varequal') {
160  $equals = $conditionvar->varequal[$order['index']]->getContent();
161  $gapident = $conditionvar->varequal[$order['index']]->getRespident();
162  }
163  }
164  if ($gapident === '') {
165  continue;
166  }
167  foreach ($respcondition->setvar as $setvar) {
168  foreach ($gaps as $gi => $g) {
169  if ($g['ident'] !== $gapident) {
170  continue;
171  }
172  switch ($g['type']) {
174  foreach ($gaps[$gi]['answers'] as $ai => $answer) {
175  if ($answer['answertext'] === $equals) {
176  $gaps[$gi]['answers'][$ai]['action'] = $setvar->getAction();
177  $gaps[$gi]['answers'][$ai]['points'] = $setvar->getContent();
178  }
179  }
180  break;
183  $gaps[$gi]['answers'][] = [
184  'answertext' => $equals,
185  'points' => $setvar->getContent(),
186  'answerorder' => count($gaps[$gi]['answers']),
187  'action' => $setvar->getAction()
188 
189  ];
190  break;
191  }
192  }
193  }
194 
195  if ($respcondition->displayfeedback === []) {
196  continue;
197  }
198 
199  foreach ($respcondition->displayfeedback as $feedbackpointer) {
200  if ($feedbackpointer->getLinkrefid() === '') {
201  continue;
202  }
203  foreach ($item->itemfeedback as $ifb) {
204  switch ($ifb->getIdent()) {
205  case 'response_allcorrect':
206  foreach ($ifb->material as $material) {
207  $feedbacksgeneric[1] = $material;
208  }
209  foreach ($ifb->flow_mat as $fmat) {
210  foreach ($fmat->material as $material) {
211  $feedbacksgeneric[1] = $material;
212  }
213  }
214  break;
215  case 'response_onenotcorrect':
216  foreach ($ifb->material as $material) {
217  $feedbacksgeneric[0] = $material;
218  }
219  foreach ($ifb->flow_mat as $fmat) {
220  foreach ($fmat->material as $material) {
221  $feedbacksgeneric[0] = $material;
222  }
223  }
224  break;
225  default:
226  foreach ($ifb->material as $material) {
227  $feedbacks[$ifb->getIdent()] = $material;
228  }
229  foreach ($ifb->flow_mat as $fmat) {
230  foreach ($fmat->material as $material) {
231  $feedbacks[$ifb->getIdent()] = $material;
232  }
233  }
234  }
235  }
236  }
237  }
238  }
239 
240  $this->addGeneralMetadata($item);
241  $this->object->setTitle($item->getTitle());
242  $this->object->setNrOfTries((int) $item->getMaxattempts());
243  $this->object->setComment($item->getComment());
244  $this->object->setAuthor($item->getAuthor());
245  $this->object->setOwner($user_id);
246  $this->object->setObjId($questionpool_id);
247  $textgap_rating = $item->getMetadataEntry('textgaprating') ?? '';
248  $this->object->setFixedTextLength((int) $item->getMetadataEntry('fixedTextLength'));
249  $this->object->setIdenticalScoring((bool) $item->getMetadataEntry('identicalScoring'));
250  $this->object->setFeedbackMode(
251  ($item->getMetadataEntry('feedback_mode') ?? '') !== '' ?
253  );
254  $combinations = json_decode(base64_decode($item->getMetadataEntry('combinations') ?? ''));
255  if ($textgap_rating === '') {
256  $textgap_rating = 'ci';
257  }
258  $this->object->setTextgapRating($textgap_rating);
259  $gaptext = [];
260  foreach ($gaps as $gapidx => $gap) {
261  $gapcontent = [];
262  $clozegap = new assClozeGap($gap['type']);
263  foreach ($gap['answers'] as $answer) {
264  $gapanswer = new assAnswerCloze($answer['answertext'], $answer['points'], $answer['answerorder']);
265  $gapanswer->setGapSize((int) ($gap['gap_size'] ?? 0));
266  switch ($clozegap->getType()) {
268  $clozegap->setShuffle($answer['shuffle']);
269  break;
271  $gapanswer->setLowerBound($gap['minnumber']);
272  $gapanswer->setUpperBound($gap['maxnumber']);
273  break;
274  }
275  $clozegap->setGapSize((int) ($gap['gap_size'] ?? 0));
276  $clozegap->addItem($gapanswer);
277  array_push($gapcontent, $answer['answertext']);
278  }
279  $this->object->addGapAtIndex($clozegap, $gapidx);
280  $gaptext[$gap['ident']] = '[gap]' . join(',', $gapcontent) . '[/gap]';
281  }
282 
283  $this->object->setQuestion($questiontext);
284  $clozetext = join('', $clozetext_array);
285 
286  foreach ($gaptext as $idx => $val) {
287  $clozetext = str_replace('<<' . $idx . '>>', $val, $clozetext);
288  }
289  $this->object->setClozeTextValue($clozetext);
290 
291  // additional content editing mode information
292  $this->object->setAdditionalContentEditingMode(
294  );
295  $this->object->saveToDb();
296 
297  if (is_array($combinations) && count($combinations) > 0) {
298  $gap_combinations = new assClozeGapCombination($this->db);
299  $gap_combinations->clearGapCombinationsFromDb($this->object->getId());
300  $gap_combinations->importGapCombinationToDb($this->object->getId(), $combinations);
301  $gap_combinations->loadFromDb($this->object->getId());
302  $this->object->setGapCombinations($gap_combinations);
303  $this->object->setGapCombinationsExists(true);
304  }
305 
306  // handle the import of media objects in XHTML code
307  foreach ($feedbacks as $ident => $material) {
308  $m = $this->QTIMaterialToString($material);
309  $feedbacks[$ident] = $m;
310  }
311  foreach ($feedbacksgeneric as $correctness => $material) {
312  $m = $this->QTIMaterialToString($material);
313  $feedbacksgeneric[$correctness] = $m;
314  }
315  if (is_array(ilSession::get('import_mob_xhtml'))) {
316  foreach (ilSession::get('import_mob_xhtml') as $mob) {
317  $importfile = $importdirectory . DIRECTORY_SEPARATOR . $mob['uri'];
318  global $DIC;
319  $DIC['ilLog']->write(__METHOD__ . ': import mob from dir: ' . $importfile);
320 
321  $media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
322  $questiontext = str_replace('src="' . $mob['mob'] . '"', 'src="' . 'il_' . IL_INST_ID . '_mob_' . $media_object->getId() . '"', $questiontext);
323  $clozetext = str_replace('src="' . $mob['mob'] . '"', 'src="' . 'il_' . IL_INST_ID . '_mob_' . $media_object->getId() . '"', $clozetext);
324  foreach ($feedbacks as $ident => $material) {
325  $feedbacks[$ident] = str_replace('src="' . $mob['mob'] . '"', 'src="' . 'il_' . IL_INST_ID . '_mob_' . $media_object->getId() . '"', $material);
326  }
327  foreach ($feedbacksgeneric as $correctness => $material) {
328  $feedbacksgeneric[$correctness] = str_replace('src="' . $mob['mob'] . '"', 'src="' . 'il_' . IL_INST_ID . '_mob_' . $media_object->getId() . '"', $material);
329  }
330  }
331  }
332  $this->object->setQuestion(ilRTE::_replaceMediaObjectImageSrc($questiontext, 1));
333  $this->object->setClozeTextValue(ilRTE::_replaceMediaObjectImageSrc($clozetext, 1));
334  foreach ($feedbacks as $ident => $material) {
335  $fbIdentifier = $this->buildFeedbackIdentifier($ident);
336  $this->object->feedbackOBJ->importSpecificAnswerFeedback(
337  $this->object->getId(),
338  $fbIdentifier->getQuestionIndex(),
339  $fbIdentifier->getAnswerIndex(),
341  );
342  }
343  foreach ($feedbacksgeneric as $correctness => $material) {
344  $this->object->feedbackOBJ->importGenericFeedback(
345  $this->object->getId(),
346  $correctness,
348  );
349  }
350  $this->object->saveToDb();
351 
352  $this->importSuggestedSolutions($this->object->getId(), $item->suggested_solutions);
353  $import_mapping[$item->getIdent()] = $this->addQuestionToParentObjectAndBuildMappingEntry(
354  $questionpool_id,
355  $tst_id,
356  $question_counter,
357  $tst_object
358  );
359  return $import_mapping;
360  }
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static get(string $a_var)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addGeneralMetadata(ilQTIItem $item)
const IL_INST_ID
Definition: constants.php:40
QTIMaterialToString(ilQTIMaterial $a_material)
Reads an QTI material tag and creates a text or XHTML string.
addQuestionToParentObjectAndBuildMappingEntry(int $questionpool_id, ?int $tst_id, int &$question_counter, ?ilObjTest &$tst_object)
getMetadataEntry(string $a_label)
processNonAbstractedImageReferences($text, $sourceNic)
fetchAdditionalContentEditingModeInformation($qtiItem)
fetches the "additional content editing mode" information from qti item and falls back to ADDITIONAL_...
$response
Definition: xapitoken.php:90
Class for cloze question gaps.
global $DIC
Definition: shib_login.php:25
importSuggestedSolutions(int $question_id, array $solution_from_import)
static _saveTempFileAsMediaObject(string $name, string $tmp_name, bool $upload=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static clear(string $a_var)
const FB_MODE_GAP_QUESTION
constants for different feedback modes (per gap or per gap-answers/options)
+ Here is the call graph for this function:

Field Documentation

◆ $db

ilDBInterface assClozeTestImport::$db
private

Definition at line 30 of file class.assClozeTestImport.php.


The documentation for this class was generated from the following file: