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;
}