/** * Sends a subtree starting to $locationId to the trash * and returns a Trashed object corresponding to $locationId. * * Moves all locations in the subtree to the Trash. The associated content * objects are left untouched. * * @param mixed $locationId * * @todo Handle field types actions * * @return null|\eZ\Publish\SPI\Persistence\Content\Location\Trashed null if location was deleted, otherwise Trashed object */ public function trashSubtree($locationId) { $locationRows = $this->locationGateway->getSubtreeContent($locationId); $isLocationRemoved = false; $parentLocationId = null; foreach ($locationRows as $locationRow) { if ($locationRow["node_id"] == $locationId) { $parentLocationId = $locationRow["parent_node_id"]; } if ($this->locationGateway->countLocationsByContentId($locationRow["contentobject_id"]) == 1) { $this->locationGateway->trashLocation($locationRow["node_id"]); } else { if ($locationRow["node_id"] == $locationId) { $isLocationRemoved = true; } $this->locationGateway->removeLocation($locationRow["node_id"]); if ($locationRow["node_id"] == $locationRow["main_node_id"]) { $newMainLocationRow = $this->locationGateway->getFallbackMainNodeData($locationRow["contentobject_id"], $locationRow["node_id"]); $this->locationHandler->changeMainLocation($locationRow["contentobject_id"], $newMainLocationRow["node_id"], $newMainLocationRow["contentobject_version"], $newMainLocationRow["parent_node_id"]); } } } if (isset($parentLocationId)) { $this->locationHandler->markSubtreeModified($parentLocationId, time()); } return $isLocationRemoved ? null : $this->loadTrashItem($locationId); }
/** * 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; }
/** * Find all content in the given subtree * * @param mixed $sourceId * @param bool $onlyIds * * @return array */ public function getSubtreeContent($sourceId, $onlyIds = false) { try { return $this->innerGateway->getSubtreeContent($sourceId, $onlyIds); } catch (DBALException $e) { throw new RuntimeException('Database error', 0, $e); } catch (PDOException $e) { throw new RuntimeException('Database error', 0, $e); } }
/** * @param mixed $oldParentId * @param mixed $newParentId * * @return array */ protected function getCopiedLocationsMap($oldParentId, $newParentId) { $originalLocations = $this->locationGateway->getSubtreeContent($oldParentId); $copiedLocations = $this->locationGateway->getSubtreeContent($newParentId); $map = array(); foreach ($originalLocations as $index => $originalLocation) { $map['eznode:' . $originalLocation['node_id']] = 'eznode:' . $copiedLocations[$index]['node_id']; } return $map; }