/** * Copy location object identified by $sourceId, into destination identified by $destinationParentId. * * Performs a deep copy of the location identified by $sourceId and all of * its child locations, copying the most recent published content object * for each location to a new content object without any additional version * information. Relations are not copied. URLs are not touched at all. * * @todo update subtree modification time, optionally retain dates and set creator * * @param mixed $sourceId * @param mixed $destinationParentId * * @return Location the newly created Location. */ public function copySubtree($sourceId, $destinationParentId) { $children = $this->locationGateway->getSubtreeContent($sourceId); $destinationParentData = $this->locationGateway->getBasicNodeData($destinationParentId); $defaultObjectStates = $this->getDefaultContentStates(); $contentMap = array(); $locationMap = array($children[0]["parent_node_id"] => array("id" => $destinationParentId, "hidden" => (bool) $destinationParentData["is_hidden"], "invisible" => (bool) $destinationParentData["is_invisible"], "path_identification_string" => $destinationParentData["path_identification_string"])); $locations = array(); foreach ($children as $child) { $locations[$child["contentobject_id"]][$child["node_id"]] = true; } $time = time(); $mainLocations = array(); $mainLocationsUpdate = array(); foreach ($children as $index => $child) { // Copy content if (!isset($contentMap[$child["contentobject_id"]])) { $content = $this->contentHandler->copy($child["contentobject_id"], $child["contentobject_version"]); $this->setContentStates($content, $defaultObjectStates); $content = $this->contentHandler->publish($content->versionInfo->contentInfo->id, $content->versionInfo->contentInfo->currentVersionNo, new MetadataUpdateStruct(array("publicationDate" => $time, "modificationDate" => $time))); $contentMap[$child["contentobject_id"]] = $content->versionInfo->contentInfo->id; } $createStruct = $this->locationMapper->getLocationCreateStruct($child); $createStruct->contentId = $contentMap[$child["contentobject_id"]]; $parentData = $locationMap[$child["parent_node_id"]]; $createStruct->parentId = $parentData["id"]; $createStruct->invisible = $createStruct->hidden || $parentData["hidden"] || $parentData["invisible"]; $pathString = explode("/", $child["path_identification_string"]); $pathString = end($pathString); $createStruct->pathIdentificationString = strlen($pathString) > 0 ? $parentData["path_identification_string"] . "/" . $pathString : null; // Use content main location if already set, otherwise create location as main if (isset($mainLocations[$child["contentobject_id"]])) { $createStruct->mainLocationId = $locationMap[$mainLocations[$child["contentobject_id"]]]["id"]; } else { $createStruct->mainLocationId = true; $mainLocations[$child["contentobject_id"]] = $child["node_id"]; // If needed mark for update if (isset($locations[$child["contentobject_id"]][$child["main_node_id"]]) && count($locations[$child["contentobject_id"]]) > 1 && $child["node_id"] !== $child["main_node_id"]) { $mainLocationsUpdate[$child["contentobject_id"]] = $child["main_node_id"]; } } $newLocation = $this->create($createStruct); $locationMap[$child["node_id"]] = array("id" => $newLocation->id, "hidden" => $newLocation->hidden, "invisible" => $newLocation->invisible, "path_identification_string" => $newLocation->pathIdentificationString); if ($index === 0) { $copiedSubtreeRootLocation = $newLocation; } } // Update main locations foreach ($mainLocationsUpdate as $contentId => $mainLocationId) { $this->changeMainLocation($contentMap[$contentId], $locationMap[$mainLocationId]["id"]); } // If subtree root is main location for its content, update subtree section to the one of the // parent location content $subtreeRootContentInfo = $this->contentHandler->loadContentInfo($copiedSubtreeRootLocation->contentId); if ($subtreeRootContentInfo->mainLocationId === $copiedSubtreeRootLocation->id) { $this->setSectionForSubtree($copiedSubtreeRootLocation->id, $this->contentHandler->loadContentInfo($this->load($destinationParentId)->contentId)->sectionId); } return $copiedSubtreeRootLocation; }