From 64dc11e4e97bf4f46723d648f115b1ddbd8a9895 Mon Sep 17 00:00:00 2001 From: Matheus Zych Date: Fri, 16 Jan 2026 11:11:27 +0100 Subject: [PATCH] Implements partial fault handling when exporting test media objects by skipping missing resources --- .../ILIAS/Test/classes/class.ilObjTest.php | 30 +++++++++++++++++++ lang/ilias_de.lang | 1 + lang/ilias_en.lang | 1 + 3 files changed, 32 insertions(+) diff --git a/components/ILIAS/Test/classes/class.ilObjTest.php b/components/ILIAS/Test/classes/class.ilObjTest.php index 4c566f37dc2f..c6d23c1d52b7 100755 --- a/components/ILIAS/Test/classes/class.ilObjTest.php +++ b/components/ILIAS/Test/classes/class.ilObjTest.php @@ -18,6 +18,9 @@ declare(strict_types=1); +use ILIAS\MediaObjects\MediaObjectRepository; +use ILIAS\ResourceStorage\Identification\ResourceIdentification; +use ILIAS\ResourceStorage\Services as ResourceStorage; use ILIAS\Test\Participants\ParticipantRepository; use ILIAS\Test\Results\Data\Repository; use ILIAS\Test\TestDIC; @@ -49,6 +52,9 @@ use ILIAS\Refinery\Factory as Refinery; use ILIAS\Filesystem\Filesystem; use ILIAS\MetaData\Services\ServicesInterface as LOMetadata; +use ILIAS\UI\Factory as UIFactory; +use ILIAS\UI\Renderer as UIRenderer; +use ILIAS\UICore\GlobalTemplate; /** * Class ilObjTest @@ -145,6 +151,11 @@ class ilObjTest extends ilObject protected Repository $test_result_repository; protected LOMetadata $lo_metadata; + protected MediaObjectRepository $media_object_repository; + protected ResourceStorage $irss; + protected UIFactory $ui_factory; + protected UIRenderer $ui_renderer; + protected ilGlobalTemplateInterface $tpl; /** * Constructor @@ -166,6 +177,11 @@ public function __construct(int $id = 0, bool $a_call_by_reference = true) $this->component_factory = $DIC['component.factory']; $this->filesystem_web = $DIC->filesystem()->web(); $this->lo_metadata = $DIC->learningObjectMetadata(); + $this->media_object_repository = $DIC->mediaObjects()->internal()->repo()->mediaObject(); + $this->irss = $DIC->resourceStorage(); + $this->ui_factory = $DIC->ui()->factory(); + $this->ui_renderer = $DIC->ui()->renderer(); + $this->tpl = $DIC->ui()->mainTemplate(); $local_dic = $this->getLocalDIC(); $this->participant_access_filter = $local_dic['participant.access_filter.factory']; @@ -3732,6 +3748,7 @@ public function exportXMLPageObjects(&$a_xml_writer, $inst, &$expLog) */ public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog) { + $not_found_resources = []; foreach ($this->mob_ids as $mob_id) { $expLog->write(date("[y-m-d H:i:s] ") . "Media Object " . $mob_id); if (ilObjMediaObject::_exists((int) $mob_id)) { @@ -3740,7 +3757,14 @@ public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$ ilFileUtils::createDirectory($target_dir); $media_obj = new ilObjMediaObject((int) $mob_id); $media_obj->exportXML($a_xml_writer, (int) $a_inst); + /** @var ilMediaItem $item */ foreach ($media_obj->getMediaItems() as $item) { + $rid = $this->media_object_repository->getById($item->getMobId())['rid'] ?? null; + if (!is_string($rid) || !$this->irss->manage()->find($rid) instanceof ResourceIdentification) { + $expLog->write(date('[y-m-d H:i:s] ') . "The resource for Media Object {$item->getMobId()} does not exist (skipping)"); + $not_found_resources[] = "({$item->getMobId()}) {$item->getLocation()}"; + continue; + } $stream = $item->getLocationStream(); file_put_contents($target_dir . DIRECTORY_SEPARATOR . $item->getLocation(), $stream); $stream->close(); @@ -3748,6 +3772,12 @@ public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$ unset($media_obj); } } + + if ($not_found_resources !== []) { + $message = $this->lng->txt('missing_media_resources_export_skipped'); + $message .= $this->ui_renderer->render($this->ui_factory->listing()->unordered($not_found_resources)); + $this->tpl->setOnScreenMessage(GlobalTemplate::MESSAGE_TYPE_INFO, $message, true); + } } /** diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 089b3b8e9d2b..5649793fea3d 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -921,6 +921,7 @@ assessment#:#min_auto_complete#:#Autovervollständigung assessment#:#min_ip_label#:#Kleinste IP mit Zugriff assessment#:#min_percentage_ne_0#:#Das Notenschema muss mindestens eine Stufe mit einem minimalen Prozentsatz von 0 Prozent enthalten. assessment#:#misc#:#Verschiedene Optionen +assessment#:#missing_media_resources_export_skipped#:#Die Ressourcen der folgenden Medienobjekte konnten nicht gefunden werden und wurden beim Export übersprungen. assessment#:#mode_allatonce#:#Alle assessment#:#mode_onebyone#:#Nacheinander assessment#:#mode_question#:#Nach Frage diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 850a67b704dd..6ecb2b87d147 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -921,6 +921,7 @@ assessment#:#min_auto_complete#:#Autocomplete assessment#:#min_ip_label#:#Lowest IP With Access assessment#:#min_percentage_ne_0#:#One of your grade categories needs to start at the ‘Minimum Score Required (in %)’ level of 0% Your grading system hasn’t been saved. assessment#:#misc#:#Misc Options +assessment#:#missing_media_resources_export_skipped#:#The resources for the following media objects could not be found and were skipped during export. assessment#:#mode_allatonce#:#All assessment#:#mode_onebyone#:#One by One assessment#:#mode_question#:#Question oriented