ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.assQuestionImport.php
Go to the documentation of this file.
1<?php
2
24
35{
39 public $object;
40
42
49 public function __construct($a_object)
50 {
51 $this->object = $a_object;
52
54 global $DIC;
55 $this->filesystem = $DIC['filesystem']->web();
56 }
57
58 public function getQuestionId(): int
59 {
60 return (int) $this->object->getId();
61 }
62
63 public function getFeedbackGeneric($item): array
64 {
65 $feedbacksgeneric = [];
66 foreach ($item->resprocessing as $resprocessing) {
67 foreach ($resprocessing->respcondition as $respcondition) {
68 foreach ($respcondition->displayfeedback as $feedbackpointer) {
69 if (strlen($feedbackpointer->getLinkrefid())) {
70 foreach ($item->itemfeedback as $ifb) {
71 if (strcmp($ifb->getIdent(), "response_allcorrect") == 0) {
72 // found a feedback for the identifier
73 if (count($ifb->material)) {
74 foreach ($ifb->material as $material) {
75 $feedbacksgeneric[1] = $material;
76 }
77 }
78 if ((count($ifb->flow_mat) > 0)) {
79 foreach ($ifb->flow_mat as $fmat) {
80 if (count($fmat->material)) {
81 foreach ($fmat->material as $material) {
82 $feedbacksgeneric[1] = $material;
83 }
84 }
85 }
86 }
87 } elseif (strcmp($ifb->getIdent(), "response_onenotcorrect") == 0) {
88 // found a feedback for the identifier
89 if (count($ifb->material)) {
90 foreach ($ifb->material as $material) {
91 $feedbacksgeneric[0] = $material;
92 }
93 }
94 if ((count($ifb->flow_mat) > 0)) {
95 foreach ($ifb->flow_mat as $fmat) {
96 if (count($fmat->material)) {
97 foreach ($fmat->material as $material) {
98 $feedbacksgeneric[0] = $material;
99 }
100 }
101 }
102 }
103 }
104 }
105 }
106 }
107 }
108 }
109 // handle the import of media objects in XHTML code
110 foreach ($feedbacksgeneric as $correctness => $material) {
111 $m = $this->QTIMaterialToString($material);
112 $feedbacksgeneric[$correctness] = $m;
113 }
114 return $feedbacksgeneric;
115 }
116
122 protected function fetchIndexFromFeedbackIdent($feedbackIdent, $prefix = 'response_'): int
123 {
124 return (int) str_replace($prefix, '', $feedbackIdent);
125 }
126
132 protected function getFeedbackAnswerSpecific(ilQTIItem $item, $prefix = 'response_'): array
133 {
134 $feedbacks = [];
135
136 foreach ($item->itemfeedback as $ifb) {
137 if ($ifb->getIdent() == 'response_allcorrect' || $ifb->getIdent() == 'response_onenotcorrect') {
138 continue;
139 }
140
141 if ($ifb->getIdent() == $prefix . 'allcorrect' || $ifb->getIdent() == $prefix . 'onenotcorrect') {
142 continue;
143 }
144
145 if (substr($ifb->getIdent(), 0, strlen($prefix)) != $prefix) {
146 continue;
147 }
148
149 $ident = $ifb->getIdent();
150
151 // found a feedback for the identifier
152
153 if (count($ifb->material)) {
154 foreach ($ifb->material as $material) {
155 $feedbacks[$ident] = $material;
156 }
157 }
158
159 if ((count($ifb->flow_mat) > 0)) {
160 foreach ($ifb->flow_mat as $fmat) {
161 if (count($fmat->material)) {
162 foreach ($fmat->material as $material) {
163 $feedbacks[$ident] = $material;
164 }
165 }
166 }
167 }
168 }
169
170 foreach ($feedbacks as $ident => $material) {
171 $m = $this->QTIMaterialToString($material);
172 $feedbacks[$ident] = $m;
173 }
174
175 return $feedbacks;
176 }
177
178 public function fromXML(
179 string $importdirectory,
180 int $user_id,
181 ilQTIItem $item,
182 int $questionpool_id,
183 ?int $tst_id,
184 ?ilObject &$tst_object,
185 int &$question_counter,
186 array $import_mapping
187 ): array {
188 return [];
189 }
190
194 protected function addGeneralMetadata(ilQTIItem $item): void
195 {
196 if ($item->getMetadataEntry('externalID')) {
197 $this->object->setExternalId($item->getMetadataEntry('externalID'));
198 } else {
199 $this->object->setExternalId($item->getMetadataEntry('externalId'));
200 }
201
202 $this->object->setLifecycle($this->fetchLifecycle($item));
203 }
204
210 {
211 try {
213 $item->getMetadataEntry('ilias_lifecycle')
214 );
216 try {
217 $lomLifecycle = new ilAssQuestionLomLifecycle(
218 $item->getMetadataEntry('lifecycle')
219 );
220
222 $lomLifecycle->getMappedIliasLifecycleIdentifer()
223 );
226 }
227 }
228
229 return $lifecycle;
230 }
231
232 protected function processNonAbstractedImageReferences($text, $sourceNic): string
233 {
234 $reg = '/<img.*src=".*\\/mm_(\\d+)\\/(.*?)".*>/m';
235 $matches = null;
236
237 if (preg_match_all($reg, $text, $matches)) {
238 $mobs = [];
239 for ($i = 0, $max = count($matches[1]); $i < $max; $i++) {
240 $mobSrcId = $matches[1][$i];
241 $mobSrcName = $matches[2][$i];
242 $mobSrcLabel = 'il_' . $sourceNic . '_mob_' . $mobSrcId;
243 $mobs[] = [
244 "mob" => $mobSrcLabel, "uri" => 'objects/' . $mobSrcLabel . '/' . $mobSrcName
245 ];
246 }
247 ilSession::set('import_mob_xhtml', $mobs);
248 }
249
250 return ilRTE::_replaceMediaObjectImageSrc($text, 0, $sourceNic);
251 }
252
261 final protected function fetchAdditionalContentEditingModeInformation($qtiItem): string
262 {
263 $additionalContentEditingMode = $qtiItem->getMetadataEntry('additional_cont_edit_mode');
264
265 if (!$this->object->isValidAdditionalContentEditingMode($additionalContentEditingMode ?? '')) {
266 $additionalContentEditingMode = assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_RTE;
267 }
268
269 return $additionalContentEditingMode;
270 }
271
273 int $question_id,
274 array $solution_from_import
275 ): void {
276 if (!$solution_from_import === []
277 || !isset($solution_from_import[0]['solution'])) {
278 return;
279 }
280
281 $solution_item = $solution_from_import[0]['solution'];
282 $content = $solution_item->getContent();
283 if ($solution_item->getTexttype() === 'application/json') {
284 $content = json_decode($content, true);
285 if (!isset($content['type']) || !isset($content['value'])) {
286 return;
287 }
288 $type = $content['type'];
289 } else {
290 $type = $this->findSolutionTypeByValue($solution_item->getContent());
291 if ($type === null) {
292 return;
293 }
294 }
295
296 $repo = $this->getSuggestedSolutionsRepo();
297 $solution_object = $repo->create($question_id, $type);
298
299 if ($type !== SuggestedSolution::TYPE_FILE) {
300 $link = is_string($content) ? $content : $content['value'];
301 $adapted_link = $this->object->resolveInternalLink($link);
302 if ($adapted_link === '') {
303 return;
304 }
305 $solution_object = $solution_object
306 ->withInternalLink($adapted_link)
307 ->withImportId($link);
308 } else {
309 if (!isset($content['title']) || !isset($content['filename'])) {
310 return;
311 }
312 $path = str_replace(CLIENT_WEB_DIR . DIRECTORY_SEPARATOR, '', $this->object->getSuggestedSolutionPath() . $content['filename']);
313 $this->filesystem->put($path, base64_decode($content['value']));
314 $solution_object = $solution_object->withTitle($content['title'])
315 ->withFilename($content['filename'])
316 ->withSize((int) $this->filesystem->getSize($path, DataSize::Byte)->inBytes())
317 ->withMime($this->filesystem->getMimeType($path));
318 }
319 $repo->update([$solution_object]);
320 }
321
322 protected function findSolutionTypeByValue(string $value): ?string
323 {
324 foreach (array_keys(SuggestedSolution::TYPES) as $type) {
325 $search_type = '_' . $type . '_';
326 if (strpos($value, $search_type) !== false) {
327 return $type;
328 }
329 }
330 return null;
331 }
332
333
334 protected ?SuggestedSolutionsDatabaseRepository $suggestedsolution_repo = null;
336 {
337 if (is_null($this->suggestedsolution_repo)) {
338 $dic = QuestionPoolDIC::dic();
339 $this->suggestedsolution_repo = $dic['question.repo.suggestedsolutions'];
340 }
341 return $this->suggestedsolution_repo;
342 }
343
348 public function QTIMaterialToString(ilQTIMaterial $a_material): string
349 {
350 $result = '';
351 $mobs = ilSession::get('import_mob_xhtml') ?? [];
352 for ($i = 0; $i < $a_material->getMaterialCount(); $i++) {
353 $material = $a_material->getMaterial($i);
354 switch ($material['type']) {
355 case 'mattext':
356 $result .= $material['material']->getContent();
357 break;
358 case 'matimage':
359 $matimage = $material['material'];
360 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
361 $mobs[] = ["mob" => $matimage->getLabel(),
362 "uri" => $matimage->getUri()
363 ];
364 }
365 }
366 }
367 ilSession::set('import_mob_xhtml', $mobs);
368 return $result;
369 }
370
371 protected function deduceThumbSizeFromImportValue(?int $size): int
372 {
373 if ($size === null) {
374 return $this->object->getThumbSize();
375 }
376
377 if ($size < $this->object->getMinimumThumbSize()) {
378 return $this->object->getMinimumThumbSize();
379 }
380
381 if ($size > $this->object->getMaximumThumbSize()) {
382 return $this->object->getMaximumThumbSize();
383 }
384
385 return $size;
386 }
387
389 int $questionpool_id,
390 ?int $tst_id,
391 int &$question_counter,
392 ?ilObjTest &$tst_object
393 ): array {
394 if ($tst_id !== null && $tst_id === $questionpool_id) {
395 $tst_object->questions[$question_counter++] = $this->object->getId();
396 return ['pool' => 0, 'test' => $this->object->getId()];
397 }
398
399 if ($tst_id > 0) {
400 $question_id = $this->object->duplicate(true, '', '', -1, $tst_id);
401 $tst_object->questions[$question_counter++] = $question_id;
402 return ['pool' => $this->object->getId(), 'test' => $question_id];
403 }
404 return ['pool' => $this->object->getId(), 'test' => 0];
405 }
406}
$lifecycle
This class provides the data size with additional information to remove the work to calculate the siz...
Definition: DataSize.php:31
Class for question imports.
fetchAdditionalContentEditingModeInformation($qtiItem)
fetches the "additional content editing mode" information from qti item and falls back to ADDITIONAL_...
getFeedbackAnswerSpecific(ilQTIItem $item, $prefix='response_')
fromXML(string $importdirectory, int $user_id, ilQTIItem $item, int $questionpool_id, ?int $tst_id, ?ilObject &$tst_object, int &$question_counter, array $import_mapping)
addQuestionToParentObjectAndBuildMappingEntry(int $questionpool_id, ?int $tst_id, int &$question_counter, ?ilObjTest &$tst_object)
QTIMaterialToString(ilQTIMaterial $a_material)
Reads an QTI material tag and creates a text or XHTML string.
processNonAbstractedImageReferences($text, $sourceNic)
fetchLifecycle(ilQTIItem $item)
addGeneralMetadata(ilQTIItem $item)
deduceThumbSizeFromImportValue(?int $size)
fetchIndexFromFeedbackIdent($feedbackIdent, $prefix='response_')
findSolutionTypeByValue(string $value)
importSuggestedSolutions(int $question_id, array $solution_from_import)
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
Class ilObject Basic functions for all objects.
getMetadataEntry(string $a_label)
getMaterial(int $a_index)
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)
static set(string $a_var, $a_val)
Set a value.
const CLIENT_WEB_DIR
Definition: constants.php:47
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
The filesystem interface provides the public interface for the Filesystem service API consumer.
Definition: Filesystem.php:37
$dic
Definition: ltiresult.php:33
$path
Definition: ltiservices.php:30
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26