/** * Given a context a new node is returned that is like this node, but * lives in the new context. * * @param Context $context * @return NodeInterface */ public function createVariantForContext($context) { $autoCreatedChildNodes = array(); $nodeType = $this->getNodeType(); foreach ($nodeType->getAutoCreatedChildNodes() as $childNodeName => $childNodeConfiguration) { $childNode = $this->getNode($childNodeName); if ($childNode !== null) { $autoCreatedChildNodes[$childNodeName] = $childNode; } } $nodeData = new NodeData($this->nodeData->getPath(), $context->getWorkspace(), $this->nodeData->getIdentifier(), $context->getTargetDimensionValues()); $nodeData->similarize($this->nodeData); if ($this->context !== $context) { $node = $this->nodeFactory->createFromNodeData($nodeData, $context); } else { $this->setNodeData($nodeData); $node = $this; } $this->context->getFirstLevelNodeCache()->flush(); $this->emitNodeAdded($node); /** * @var $autoCreatedChildNode NodeInterface */ foreach ($autoCreatedChildNodes as $autoCreatedChildNode) { $autoCreatedChildNode->createVariantForContext($context); } return $node; }
/** * @test */ public function constructorSetsPathWorkspaceAndIdentifier() { $node = new NodeData('/foo/bar', $this->mockWorkspace, '12345abcde'); $this->assertSame('/foo/bar', $node->getPath()); $this->assertSame('bar', $node->getName()); $this->assertSame($this->mockWorkspace, $node->getWorkspace()); $this->assertSame('12345abcde', $node->getIdentifier()); }
/** * Creates a node from the given NodeData container. * * If this factory has previously created a Node for the given $node and $context, * it will return the same Node again. * * @param NodeData $nodeData * @param Context $context * @return \TYPO3\TYPO3CR\Domain\Model\Node */ public function createFromNodeData(NodeData $nodeData, Context $context) { $internalNodeIdentifier = $nodeData->getIdentifier() . spl_object_hash($context); if (!isset($this->nodes[$internalNodeIdentifier])) { $this->nodes[$internalNodeIdentifier] = new Node($nodeData, $context); } $node = $this->nodes[$internalNodeIdentifier]; return $this->filterNodeByContext($node, $context); }
/** * Materializes the original node data (of a different workspace) into the current * workspace. * * @return void */ protected function materializeNodeData() { $dimensions = array_map(function ($value) { return array($value); }, $this->context->getTargetDimensions()); $newNodeData = new NodeData($this->nodeData->getPath(), $this->context->getWorkspace(), $this->nodeData->getIdentifier(), $dimensions); $this->nodeDataRepository->add($newNodeData); $newNodeData->similarize($this->nodeData); $this->nodeData = $newNodeData; $this->nodeDataIsMatchingContext = TRUE; }
/** * Generates cache tags to be flushed for a node which is flushed on shutdown. * * Code duplicated from Neos' ContentCacheFlusher class * * @param NodeInterface|NodeData $node The node which has changed in some way * @return void */ protected function generateCacheTags($node) { $this->tagsToFlush[ContentCache::TAG_EVERYTHING] = 'which were tagged with "Everything".'; $nodeTypesToFlush = $this->getAllImplementedNodeTypes($node->getNodeType()); foreach ($nodeTypesToFlush as $nodeType) { /** @var NodeType $nodeType */ $nodeTypeName = $nodeType->getName(); $this->tagsToFlush['NodeType_' . $nodeTypeName] = sprintf('which were tagged with "NodeType_%s" because node "%s" has changed and was of type "%s".', $nodeTypeName, $node->getPath(), $node->getNodeType()->getName()); } $this->tagsToFlush['Node_' . $node->getIdentifier()] = sprintf('which were tagged with "Node_%s" because node "%s" has changed.', $node->getIdentifier(), $node->getPath()); while ($node->getDepth() > 1) { $node = $node->getParent(); if ($node === NULL) { break; } $this->tagsToFlush['DescendantOf_' . $node->getIdentifier()] = sprintf('which were tagged with "DescendantOf_%s" because node "%s" has changed.', $node->getIdentifier(), $node->getPath()); } if ($node instanceof NodeInterface && $node->getContext() instanceof ContentContext) { $firstActiveDomain = $node->getContext()->getCurrentSite()->getFirstActiveDomain(); if ($firstActiveDomain) { $this->domainsToFlush[] = $firstActiveDomain->getHostPattern(); } } }
/** * Creates a node from the given NodeData container. * * If this factory has previously created a Node for the given $node and it's dimensions, * it will return the same node again. * * @param NodeData $nodeData * @param Context $context * @return \TYPO3\TYPO3CR\Domain\Model\NodeInterface * @throws \TYPO3\TYPO3CR\Exception\NodeConfigurationException if a configured 'class' for a Node does not exist or does not inherit NodeInterface */ public function createFromNodeData(NodeData $nodeData, Context $context) { if ($nodeData->isInternal()) { return null; } $internalNodeIdentifier = $nodeData->getIdentifier() . spl_object_hash($context); // In case there is a Node with an internal NodeData (because the NodeData was changed in the meantime) we need to flush it. if (isset($this->nodes[$internalNodeIdentifier]) && $this->nodes[$internalNodeIdentifier]->getNodeData()->isInternal()) { unset($this->nodes[$internalNodeIdentifier]); } if (!isset($this->nodes[$internalNodeIdentifier])) { // Warning: Alternative node implementations are considered internal for now, feature can change or be removed anytime. We want to be sure it works well and makes sense before declaring it public. $class = $nodeData->getNodeType()->getConfiguration('class') ?: $this->objectManager->getClassNameByObjectName('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface'); if (!in_array($class, static::getNodeInterfaceImplementations($this->objectManager))) { throw new NodeConfigurationException('The configured implementation class name "' . $class . '" for NodeType "' . $nodeData->getNodeType() . '" does not inherit from TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface.', 1406884014); } $this->nodes[$internalNodeIdentifier] = new $class($nodeData, $context); } $node = $this->nodes[$internalNodeIdentifier]; return $this->filterNodeByContext($node, $context); }
/** * Adjust the given $shadowNodeData by removing it or moving it to the $targetWorkspace, as needed. * * @param NodeData $shadowNodeData * @param NodeData $publishedNodeData * @param Workspace $targetWorkspace * @param NodeData $targetNodeData * @return void */ protected function adjustShadowNodeData(NodeData $shadowNodeData, NodeData $publishedNodeData, Workspace $targetWorkspace, NodeData $targetNodeData) { $nodeOnSamePathInTargetWorkspace = $this->nodeDataRepository->findOneByPath($shadowNodeData->getPath(), $targetWorkspace, $publishedNodeData->getDimensionValues()); if ($nodeOnSamePathInTargetWorkspace !== null && $nodeOnSamePathInTargetWorkspace->getWorkspace() === $targetWorkspace) { $this->nodeDataRepository->remove($shadowNodeData); return; } $shadowNodeData->setMovedTo($targetNodeData); $shadowNodeData->setWorkspace($targetWorkspace); $targetWorkspaceBase = $targetWorkspace->getBaseWorkspace(); $nodeInTargetWorkspaceBase = $this->nodeDataRepository->findOneByIdentifier($publishedNodeData->getIdentifier(), $targetWorkspaceBase, $publishedNodeData->getDimensionValues()); if ($nodeInTargetWorkspaceBase !== null && $nodeInTargetWorkspaceBase->getPath() !== $shadowNodeData->getPath()) { $this->adjustShadowNodePath($shadowNodeData, $nodeInTargetWorkspaceBase->getPath(), $targetWorkspace, $publishedNodeData->getDimensionValues()); } }