From 2053bac62690e40bfb6f1e58e7763349dbe7ee16 Mon Sep 17 00:00:00 2001 From: Fabian Borghoff Date: Thu, 6 Aug 2026 12:08:45 +0200 Subject: [PATCH] [FIX] HTMLLearningModule #48169: Copy files when copying an HTML learning module https://mantis.ilias.de/view.php?id=48169 Since ILIAS 10 the files of an HTML learning module are no longer stored in data//lm_data/lm_ but in an IRSS container resource referenced by file_based_lm.rid. ilHTLMMigration moves the files there and removes the legacy directory. ilObjFileBasedLM::cloneObject() was not adapted and still copied the legacy directory only. For migrated modules that directory is gone, so the copy kept the empty container resource created by ilObjFileBasedLM::create() and ended up without any files. Changes in ilObjFileBasedLM: - Add cloneContainerResource(), which removes the empty container resource of the target object and replaces its RID with a clone of the source container (ContainerManager::clone()). This mirrors the way MediaObjects and content styles already clone their containers. - Call it from cloneObject(); the subsequent update() persists the new RID together with the start file. - Keep the legacy populateByDirectoy() call, but only when the data directory actually exists, so installations that have not run the migration yet still copy their content. --- .../classes/class.ilObjFileBasedLM.php | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/components/ILIAS/HTMLLearningModule/classes/class.ilObjFileBasedLM.php b/components/ILIAS/HTMLLearningModule/classes/class.ilObjFileBasedLM.php index eddaac649046..f5919b73a371 100755 --- a/components/ILIAS/HTMLLearningModule/classes/class.ilObjFileBasedLM.php +++ b/components/ILIAS/HTMLLearningModule/classes/class.ilObjFileBasedLM.php @@ -231,7 +231,12 @@ public function cloneObject(int $target_id, int $copy_id = 0, bool $omit_tree = } // copy content - $new_obj->populateByDirectoy($this->getDataDirectory()); + $this->cloneContainerResource($new_obj); + + // copy legacy content (only relevant for not yet migrated modules) + if (is_dir($this->getDataDirectory())) { + $new_obj->populateByDirectoy($this->getDataDirectory()); + } $new_obj->setStartFile((string) $this->getStartFile()); $new_obj->update(); @@ -239,6 +244,31 @@ public function cloneObject(int $target_id, int $copy_id = 0, bool $omit_tree = return $new_obj; } + /** + * Replace the empty container resource of the target object (created in + * ilObjFileBasedLM::create()) by a clone of this object's container. + */ + protected function cloneContainerResource(ilObjFileBasedLM $new_obj): void + { + $source = $this->getResource(); + if ($source === null) { + return; + } + + $target = $new_obj->getResource(); + if ($target !== null) { + $this->irss->manageContainer()->remove( + $target->getIdentification(), + new ilHTLMStakeholder() + ); + } + + $cloned_rid = $this->irss->manageContainer()->clone( + $source->getIdentification() + ); + $new_obj->setRID($cloned_rid->serialize()); + } + public function isInfoEnabled(): bool { return ilObjContentObjectAccess::isInfoEnabled($this->getId());