/** * Sets the absolute path of this node. * * This method is only for internal use by the content repository or node methods. Changing * the path of a node manually may lead to unexpected behavior. * * To achieve a correct behavior when changing the path (moving the node) in a workspace, a shadow node data that will * hide the node data in the base workspace will be created. Thus queries do not need to worry about moved nodes. * Through a movedTo reference the shadow node data will be removed when publishing the moved node. * * @param string $path * @param boolean $checkForExistence Checks for existence at target path, internally used for recursions and shadow nodes. * @throws NodeException * @internal This method is purely internal and Node objects can call this on other Node objects */ public function setPath($path, $checkForExistence = true) { $originalPath = $this->nodeData->getPath(); if ($originalPath === $path) { return; } if ($checkForExistence) { $existingNodeDataArray = $this->nodeDataRepository->findByPathWithoutReduce($path, $this->context->getWorkspace()); /** @var NodeData $existingNodeData */ foreach ($existingNodeDataArray as $existingNodeData) { if ($existingNodeData->getIdentifier() !== $this->getIdentifier()) { throw new NodeException(sprintf('Can not rename the node "%s" as a node already exists on path "%s"', $this->getPath(), $path), 1414436551); } } } $changedNodePathsCollection = array(); if ($this->getNodeType()->isAggregate()) { $nodeDataVariantsAndChildren = $this->nodeDataRepository->findByPathWithoutReduce($originalPath, $this->context->getWorkspace(), true, true); /** @var NodeData $nodeData */ foreach ($nodeDataVariantsAndChildren as $nodeData) { // $nodeDataVariants at this point also contains *our own NodeData reference* ($this->nodeData), as we find all NodeData objects // (across all dimensions) with the same path. // // We need to ensure that our own Node object's nodeData reference ($this->nodeData) is also updated correctly if a new NodeData object // is returned; as we rely on the fact that $this->getPath() will return the new node path in all circumstances. // // However, $this->createNodeForVariant() only returns $this if the Context object is the same as $this->context; which is not // the case if $this->context contains dimension fallbacks such as "Language: EN, DE". // // The "if" statement below is actually a workaround to ensure that if the NodeData object is our own one, we update *ourselves* correctly, // and thus return the correct (new) Node Path when calling $this->getPath() afterwards. if ($this->nodeData === $nodeData) { $nodeVariant = $this; } else { $nodeVariant = $this->createNodeForVariant($nodeData); } if ($nodeVariant !== null) { $relativePathSegment = NodePaths::getRelativePathBetween($originalPath, $nodeVariant->getPath()); $newNodeVariantPath = NodePaths::addNodePathSegment($path, $relativePathSegment); $possibleShadowedNodeData = $nodeData->move($newNodeVariantPath, $this->context->getWorkspace()); $nodeVariant->setNodeData($possibleShadowedNodeData); $changedNodePathsCollection[] = array($nodeVariant, $originalPath, $nodeVariant->getNodeData()->getPath(), !$checkForExistence); } } } else { /** @var Node $childNode */ foreach ($this->getChildNodes() as $childNode) { $childNode->setPath(NodePaths::addNodePathSegment($path, $childNode->getName()), false); } $possibleShadowedNodeData = $this->nodeData->move($path, $this->context->getWorkspace()); $this->setNodeData($possibleShadowedNodeData); $changedNodePathsCollection[] = array($this, $originalPath, $this->getNodeData()->getPath(), $checkForExistence); } $this->nodeDataRepository->persistEntities(); foreach ($changedNodePathsCollection as $nodePathChangedArguments) { call_user_func_array(array($this, 'emitNodePathChanged'), $nodePathChangedArguments); } }
/** * Sets the absolute path of this node. * * This method is only for internal use by the content repository or node methods. Changing * the path of a node manually may lead to unexpected behavior. * * To achieve a correct behavior when changing the path (moving the node) in a workspace, a shadow node data that will * hide the node data in the base workspace will be created. Thus queries do not need to worry about moved nodes. * Through a movedTo reference the shadow node data will be removed when publishing the moved node. * * @param string $path * @param boolean $checkForExistence Checks for existence at target path, internally used for recursions and shadow nodes. * @throws NodeException * @internal This method is purely internal and Node objects can call this on other Node objects */ public function setPath($path, $checkForExistence = true) { $originalPath = $this->nodeData->getPath(); if ($originalPath === $path) { return; } if ($checkForExistence) { $existingNodeDataArray = $this->nodeDataRepository->findByPathWithoutReduce($path, $this->context->getWorkspace()); /** @var NodeData $existingNodeData */ foreach ($existingNodeDataArray as $existingNodeData) { if ($existingNodeData->getIdentifier() !== $this->getIdentifier()) { throw new NodeException(sprintf('Can not rename the node "%s" as a node already exists on path "%s"', $this->getPath(), $path), 1414436551); } } } $changedNodePathsCollection = array(); if ($this->getNodeType()->isAggregate()) { $nodeDataVariantsAndChildren = $this->nodeDataRepository->findByPathWithoutReduce($originalPath, $this->context->getWorkspace(), true, true); /** @var NodeData $nodeData */ foreach ($nodeDataVariantsAndChildren as $nodeData) { $nodeVariant = $this->createNodeForVariant($nodeData); if ($nodeVariant !== null) { $relativePathSegment = NodePaths::getRelativePathBetween($originalPath, $nodeVariant->getPath()); $newNodeVariantPath = NodePaths::addNodePathSegment($path, $relativePathSegment); $possibleShadowedNodeData = $nodeData->move($newNodeVariantPath, $this->context->getWorkspace()); $nodeVariant->setNodeData($possibleShadowedNodeData); $changedNodePathsCollection[] = array($nodeVariant, $originalPath, $nodeVariant->getNodeData()->getPath(), !$checkForExistence); } } } else { /** @var Node $childNode */ foreach ($this->getChildNodes() as $childNode) { $childNode->setPath(NodePaths::addNodePathSegment($path, $childNode->getName()), false); } $possibleShadowedNodeData = $this->nodeData->move($path, $this->context->getWorkspace()); $this->setNodeData($possibleShadowedNodeData); $changedNodePathsCollection[] = array($this, $originalPath, $this->getNodeData()->getPath(), $checkForExistence); } $this->nodeDataRepository->persistEntities(); foreach ($changedNodePathsCollection as $nodePathChangedArguments) { call_user_func_array(array($this, 'emitNodePathChanged'), $nodePathChangedArguments); } }