diff --git a/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php b/lib/classes/JsonApi/Routes/Courseware/ContainersCopy.php
index 087483994292b40fb291e8c01261fcf6c544309a..cbef54c762e239b10d792d567390e1fcc3481427 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 1f621e5c88343efef56dbc2a2c5dd5ce91e649b8..088f53959c44dd5a05d24b5714f80ac83d2e580d 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 ca5a7b7f281c4f9379c285558a7809f972e09ad2..3cfca284999316e289bf8353bfb02d81a53f8b8f 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();
+                }
+            }
+        }
+    }
 }