aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFarbod Zamani <zamani@elan-ev.de>2023-04-27 07:09:19 +0000
committerJan-Hendrik Willms <tleilax+studip@gmail.com>2023-04-27 07:09:19 +0000
commitba7aae6445affd96fdaddcf7799096524dc000f2 (patch)
tree964b2af9aef67e8623d58b7f678c8372ebd9834c
parentb19a47a2a198145154cb38494c779015351274cf (diff)
CW: Mapping content after copying structural element
Closes #1153 Merge request studip/studip!1611
-rw-r--r--lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php2
-rw-r--r--lib/models/Courseware/Container.php14
-rw-r--r--lib/models/Courseware/StructuralElement.php58
3 files changed, 60 insertions, 14 deletions
diff --git a/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php b/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php
index 0874839..cbef54c 100644
--- a/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php
+++ b/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php
@@ -45,7 +45,7 @@ class ContainersCopy extends NonJsonApiController
private function copyContainer(\User $user, \Courseware\Container $remote_container, \Courseware\StructuralElement $element)
{
- $container = $remote_container->copy($user, $element);
+ list($container, $blockMapObjs) = $remote_container->copy($user, $element);
return $container;
}
diff --git a/lib/models/Courseware/Container.php b/lib/models/Courseware/Container.php
index 1f621e5..088f539 100644
--- a/lib/models/Courseware/Container.php
+++ b/lib/models/Courseware/Container.php
@@ -104,9 +104,9 @@ class Container extends \SimpleORMap
* @param User $user the owner and editor of the new copy of this block
* @param StructuralElement $element the structural element this block will be copied into
*
- * @return Container the copy of this Container
+ * @return array an array containing the container object and the block maps
*/
- public function copy(User $user, StructuralElement $element): Container
+ public function copy(User $user, StructuralElement $element): array
{
$container = self::build([
'structural_element_id' => $element->id,
@@ -120,24 +120,26 @@ class Container extends \SimpleORMap
$container->store();
- $blockMap = $this->copyBlocks($user, $container);
+ list($blockMapIds, $blockMapObjs) = $this->copyBlocks($user, $container);
- $container['payload'] = $container->type->copyPayload($blockMap);
+ $container['payload'] = $container->type->copyPayload($blockMapIds);
$container->store();
- return $container;
+ return [$container, $blockMapObjs];
}
private function copyBlocks(User $user, Container $newContainer): array
{
$blockMap = [];
+ $newBlockList = [];
foreach ($this->blocks as $block) {
$newBlock = $block->copy($user, $newContainer);
$blockMap[$block->id] = $newBlock->id;
+ $newBlockList[$block->id] = $newBlock;
}
- return $blockMap;
+ return [$blockMap, $newBlockList];
}
}
diff --git a/lib/models/Courseware/StructuralElement.php b/lib/models/Courseware/StructuralElement.php
index ca5a7b7..3cfca28 100644
--- a/lib/models/Courseware/StructuralElement.php
+++ b/lib/models/Courseware/StructuralElement.php
@@ -809,16 +809,19 @@ SQL;
*
* @param User $user this user will be the owner of the copy
* @param StructuralElement $parent the target where to copy this instance
+ * @param string $purpose the purpose of copying this instance
+ * @param string $recursiveId the optional mapping id for copying child structural elements upon recursive call to this function
*
* @return StructuralElement the copy of this instance
*/
- public function copy(User $user, StructuralElement $parent, string $purpose = ''): StructuralElement
+ public function copy(User $user, StructuralElement $parent, string $purpose = '', string $recursiveId = ''): StructuralElement
{
$ancestorIds = array_column($parent->findAncestors(), 'id');
$ancestorIds[] = $parent->id;
if (in_array($this->id, $ancestorIds)) {
throw new \InvalidArgumentException('Cannot copy into descendants.');
}
+ static $mapping = [];
$file_ref_id = $this->copyImage($user, $parent);
@@ -840,9 +843,26 @@ SQL;
$element->store();
- $this->copyContainers($user, $element);
+ list($containerMap, $blockMap) = $this->copyContainers($user, $element);
- $this->copyChildren($user, $element, $purpose);
+ $mappingId = $recursiveId === '' ? $this->id . '_' . $element->id : $recursiveId;
+ if (!isset($mapping[$mappingId])) {
+ $mapping[$mappingId] = [
+ 'elements' => [],
+ 'containers' => [],
+ 'blocks' => [],
+ ];
+ }
+ $mapping[$mappingId]['elements'][$this->id] = $element->id;
+ $mapping[$mappingId]['containers'] = $mapping[$mappingId]['containers'] + $containerMap;
+ $mapping[$mappingId]['blocks'] = $mapping[$mappingId]['blocks'] + $blockMap;
+
+ $this->copyChildren($user, $element, $purpose, $mappingId);
+
+ if ($recursiveId === '') {
+ $this->performMapping($mapping[$mappingId]);
+ unset($mapping[$mappingId]);
+ }
return $element;
}
@@ -914,17 +934,22 @@ SQL;
return $this;
}
- private function copyContainers(User $user, StructuralElement $newElement): void
+ private function copyContainers(User $user, StructuralElement $newElement): array
{
+ $containerMap = [];
+ $blockMap = [];
foreach ($this->containers as $container) {
- $container->copy($user, $newElement);
+ list($newContainer, $blockMapsObjs) = $container->copy($user, $newElement);
+ $containerMap[$container->id] = $newContainer->id;
+ $blockMap = $blockMap + $blockMapsObjs;
}
+ return [$containerMap, $blockMap];
}
- private function copyChildren(User $user, StructuralElement $newElement, string $purpose = ''): void
+ private function copyChildren(User $user, StructuralElement $newElement, string $purpose = '', string $recursiveId = ''): void
{
foreach ($this->children as $child) {
- $child->copy($user, $newElement, $purpose);
+ $child->copy($user, $newElement, $purpose, $recursiveId);
}
}
@@ -1046,4 +1071,23 @@ SQL;
return $this->parent->findParentTask();
}
+
+ private function performMapping($mapping)
+ {
+ // Blocks mapping.
+ foreach ($mapping['blocks'] as $oldBlockId => $newBlockObj) {
+ if ($newBlockObj->type->getType() === \Courseware\BlockTypes\Link::getType()) {
+ $payload = $newBlockObj->type->getPayload();
+ if ($payload['type'] === 'internal' && '' != $payload['target']) {
+ if (in_array($payload['target'], array_keys($mapping['elements']))) {
+ $payload['target'] = $mapping['elements'][intval($payload['target'])];
+ } else {
+ $payload['target'] = '';
+ }
+ $newBlockObj->type->setPayload($payload);
+ $newBlockObj->store();
+ }
+ }
+ }
+ }
}