/** * Removes unused ImageVariants after a Node property changes to a different ImageVariant. * This is triggered via the nodePropertyChanged event. * * Note: This method it triggered by the "nodePropertyChanged" signal, @see \TYPO3\TYPO3CR\Domain\Model\Node::emitNodePropertyChanged() * * @param NodeInterface $node the affected node * @param string $propertyName name of the property that has been changed/added * @param mixed $oldValue the property value before it was changed or NULL if the property is new * @param mixed $value the new property value * @return void */ public function removeUnusedImageVariant(NodeInterface $node, $propertyName, $oldValue, $value) { if ($oldValue === $value || !$oldValue instanceof ImageVariant) { return; } $identifier = $this->persistenceManager->getIdentifierByObject($oldValue); $results = $this->nodeDataRepository->findNodesByRelatedEntities(array(ImageVariant::class => [$identifier])); // This case shouldn't happen as the query will usually find at least the node that triggered this call, still if there is no relation we can remove the ImageVariant. if ($results === []) { $this->assetRepository->remove($oldValue); return; } // If the result contains exactly the node that got a new ImageVariant assigned then we are safe to remove the asset here. if ($results === [$node->getNodeData()]) { $this->assetRepository->remove($oldValue); } }
/** * Move the given node instance to the target workspace * * If no target node variant (having the same dimension values) exists in the target workspace, the node that * is published will be used as a new node variant in the target workspace. * * @param NodeInterface $node The node to publish * @param Workspace $targetWorkspace The workspace to publish to * @return void */ protected function moveNodeVariantToTargetWorkspace(NodeInterface $node, Workspace $targetWorkspace) { $nodeData = $node->getNodeData(); $movedShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($nodeData); if ($movedShadowNodeData instanceof NodeData && $movedShadowNodeData->isRemoved()) { $this->nodeDataRepository->remove($movedShadowNodeData); } if ($targetWorkspace->getBaseWorkspace() === null && $node->isRemoved()) { $this->nodeDataRepository->remove($nodeData); } else { $nodeData->setWorkspace($targetWorkspace); $nodeData->setLastPublicationDateTime($this->now); $this->nodeService->cleanUpProperties($node); } $node->setNodeDataIsMatchingContext(null); }
/** * For internal use in createRecursiveCopy. * * @param NodeInterface $sourceNode * @return void */ public function similarize(NodeInterface $sourceNode) { $this->nodeData->similarize($sourceNode->getNodeData()); }
/** * For internal use in createRecursiveCopy. * * @param NodeInterface $sourceNode * @param boolean $isCopy * @return void */ public function similarize(NodeInterface $sourceNode, $isCopy = false) { $this->nodeData->similarize($sourceNode->getNodeData(), $isCopy); }
/** * Move the given node instance to the target workspace * * If no target node variant (having the same dimension values) exists in the target workspace, the node that * is published will be used as a new node variant in the target workspace. * * @param NodeInterface $node The node to publish * @param Workspace $targetWorkspace The workspace to publish to * @return void */ protected function moveNodeVariantToTargetWorkspace(NodeInterface $node, Workspace $targetWorkspace) { $nodeData = $node->getNodeData(); $this->handleShadowNodeData($nodeData, $targetWorkspace, $nodeData); // Technically this shouldn't be needed but due to doctrines behavior we need it. if ($nodeData->isRemoved() && $targetWorkspace->getBaseWorkspace() === null) { $this->nodeDataRepository->remove($nodeData); return; } $nodeData->setMovedTo(null); $nodeData->setWorkspace($targetWorkspace); $nodeData->setLastPublicationDateTime($this->now); $node->setNodeDataIsMatchingContext(null); $this->nodeService->cleanUpProperties($node); }
/** * Discards the given node. * * @param NodeInterface $node * @return void * @throws \TYPO3\TYPO3CR\Exception\WorkspaceException * @api */ public function discardNode(NodeInterface $node) { if ($node->getWorkspace()->getBaseWorkspace() === NULL) { throw new WorkspaceException('Nodes in a in a workspace without a base workspace cannot be discarded.', 1395841899); } $possibleShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($node->getNodeData()); if ($possibleShadowNodeData !== NULL) { $this->nodeDataRepository->remove($possibleShadowNodeData); } if ($node->getPath() !== '/') { $this->nodeDataRepository->remove($node); $this->emitNodeDiscarded($node); } }
/** * Method which does the actual work of discarding, includes a protection against endless recursions and * multiple discarding of the same node. * * @param NodeInterface $node The node to discard * @param array &$alreadyDiscardedNodeIdentifiers List of node identifiers which already have been discarded during one discardNode() run * @return void * @throws \TYPO3\TYPO3CR\Exception\WorkspaceException */ protected function doDiscardNode(NodeInterface $node, array &$alreadyDiscardedNodeIdentifiers = []) { if ($node->getWorkspace()->getBaseWorkspace() === null) { throw new WorkspaceException('Nodes in a in a workspace without a base workspace cannot be discarded.', 1395841899); } if ($node->getPath() === '/') { return; } if (array_search($node->getIdentifier(), $alreadyDiscardedNodeIdentifiers) !== false) { return; } $alreadyDiscardedNodeIdentifiers[] = $node->getIdentifier(); $possibleShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($node->getNodeData()); if ($possibleShadowNodeData instanceof NodeData) { if ($possibleShadowNodeData->getMovedTo() !== null) { $parentBasePath = $node->getPath(); $affectedChildNodeDataInSameWorkspace = $this->nodeDataRepository->findByParentAndNodeType($parentBasePath, null, $node->getWorkspace(), null, false, true); foreach ($affectedChildNodeDataInSameWorkspace as $affectedChildNodeData) { /** @var NodeData $affectedChildNodeData */ $affectedChildNode = $this->nodeFactory->createFromNodeData($affectedChildNodeData, $node->getContext()); $this->doDiscardNode($affectedChildNode, $alreadyDiscardedNodeIdentifiers); } } $this->nodeDataRepository->remove($possibleShadowNodeData); } $this->nodeDataRepository->remove($node); $this->emitNodeDiscarded($node); }
/** * Checks if the given node path can be used for the given node. * * @param string $nodePath * @param NodeInterface $node * @return boolean */ public function nodePathAvailableForNode($nodePath, NodeInterface $node) { /** @var NodeData $existingNodeData */ $existingNodeDataObjects = $this->nodeDataRepository->findByPathWithoutReduce($nodePath, $node->getWorkspace(), true); foreach ($existingNodeDataObjects as $existingNodeData) { if ($existingNodeData->getMovedTo() !== null && $existingNodeData->getMovedTo() === $node->getNodeData()) { return true; } } return !$this->nodePathExistsInAnyContext($nodePath); }
/** * Move the given node instance to the target workspace * * If no target node variant (having the same dimension values) exists in the target workspace, the node that * is published will be used as a new node variant in the target workspace. * * @param NodeInterface $node The node to publish * @param Workspace $targetWorkspace The workspace to publish to * @return void */ protected function moveNodeVariantToTargetWorkspace(NodeInterface $node, Workspace $targetWorkspace) { $nodeData = $node->getNodeData(); $nodeData->setWorkspace($targetWorkspace); $node->setNodeDataIsMatchingContext(NULL); }
/** * Write back the merged comments onto the node * * @param NodeInterface $node * @param array $mergedComments */ protected function writeComments(NodeInterface $node, $mergedComments) { // We directly write to the NodeData instead of Node here; as the Node is not fully correct after publishing - the. // node's context is still the same as before publishing. // (This is a bug in TYPO3CR which only manifests when trying to read the node after publishing in the same request) // If we would write to $node directly then we would create a copy in the user's workspace; which is not what we want effectively :) $node->getNodeData()->setProperty('comments', json_encode($mergedComments)); }
/** * Generate identifier for index entry based on node identifier and context * * @param NodeInterface $node * @return string */ protected function generateUniqueNodeIdentifier(NodeInterface $node) { $nodeDataPersistenceIdentifier = $this->persistenceManager->getIdentifierByObject($node->getNodeData()); return $nodeDataPersistenceIdentifier; }