/** * Tests addPathConstraintToQueryBuilder, see https://jira.neos.io/browse/NEOS-1849 * * @test */ public function findByPathWithoutReduceLimitsToRootNodeCorrectly() { $this->setUpNodes(); $workspace = $this->context->getWorkspace(); $foundNodes = $this->nodeDataRepository->findByPathWithoutReduce('/', $workspace, false, true); $this->assertCount(7, $foundNodes); }
/** * The NodeData matches the context if the workspace matches exactly. * Needs to be adjusted for further context dimensions. * * @return boolean */ protected function isNodeDataMatchingContext() { if ($this->nodeDataIsMatchingContext === NULL) { $workspacesMatch = $this->nodeData->getWorkspace() !== NULL && $this->context->getWorkspace() !== NULL && $this->nodeData->getWorkspace()->getName() === $this->context->getWorkspace()->getName(); $this->nodeDataIsMatchingContext = $workspacesMatch && $this->dimensionsAreMatchingTargetDimensionValues(); } return $this->nodeDataIsMatchingContext; }
/** * @test */ public function sortByDateTimeDescending() { $nodesToSort = [$this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115addd', $this->context->getWorkspace(true), array()), $this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115adde', $this->context->getWorkspace(true), array()), $this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115addf', $this->context->getWorkspace(true), array())]; $correctOrder = [$this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115addd', $this->context->getWorkspace(true), array()), $this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115addf', $this->context->getWorkspace(true), array()), $this->nodeDataRepository->findOneByIdentifier('c381f64d-4269-429a-9c21-6d846115adde', $this->context->getWorkspace(true), array())]; $flowQuery = new \TYPO3\Eel\FlowQuery\FlowQuery($nodesToSort); $operation = new SortOperation(); $operation->evaluate($flowQuery, ['_lastPublicationDateTime', 'DESC']); $this->assertEquals($correctOrder, $flowQuery->getContext()); }
/** * @test */ public function nodeFactoryCachesCreatedNodesBasedOnIdentifierAndDimensions() { /** @var \TYPO3\TYPO3CR\Domain\Factory\NodeFactory $nodeFactory */ $nodeFactory = $this->objectManager->get('TYPO3\\TYPO3CR\\Domain\\Factory\\NodeFactory'); $nodeDataA = new NodeData('/', $this->context->getWorkspace(), '30e893c1-caef-0ca5-b53d-e5699bb8e506', ['test' => [1]]); $variantNodeA1 = $nodeFactory->createFromNodeData($nodeDataA, $this->context); $variantNodeA2 = $nodeFactory->createFromNodeData($nodeDataA, $this->context); $nodeDataB = new NodeData('/', $this->context->getWorkspace(), '30e893c1-caef-0ca5-b53d-e5699bb8e506', ['test' => [2]]); $variantNodeB = $nodeFactory->createFromNodeData($nodeDataB, $this->context); $this->assertSame($variantNodeA1, $variantNodeA2); $this->assertSame($variantNodeA1, $variantNodeB); }
/** * @param Asset $asset * @param MetaDataCollection $metaDataCollection * @throws NodeTypeNotFoundException * @throws \TYPO3\Flow\Persistence\Exception\IllegalObjectTypeException * @return void */ public function mapMetaData(Asset $asset, MetaDataCollection $metaDataCollection) { $nodeType = $this->nodeTypeManager->getNodeType('Neos.MetaData:Image'); $asset = $metaDataCollection->get('asset'); $assetNodeData = $this->metaDataRepository->findOneByAssetIdentifier($asset->getIdentifier(), $this->context->getWorkspace()); if ($assetNodeData === null) { $assetNodeDataTemplate = $this->createAssetNodeTemplate($asset, $nodeType); $this->mapMetaDataToNodeData($assetNodeDataTemplate, $nodeType, $metaDataCollection); $this->nodeService->findOrCreateMetaDataRootNode($this->context)->createNodeFromTemplate($assetNodeDataTemplate); } else { $this->mapMetaDataToNodeData($assetNodeData, $nodeType, $metaDataCollection); $this->metaDataRepository->update($assetNodeData); } }
/** * Search all properties for given $term * * TODO: Implement a better search when Flow offer the possibility * * @param string $term * @param array $searchNodeTypes * @param Context $context * @param NodeInterface $startingPoint * @return array <\TYPO3\TYPO3CR\Domain\Model\NodeInterface> */ public function findByProperties($term, array $searchNodeTypes, Context $context, NodeInterface $startingPoint = null) { if (strlen($term) === 0) { throw new \InvalidArgumentException('"term" cannot be empty: provide a term to search for.', 1421329285); } $searchResult = array(); $nodeTypeFilter = implode(',', $searchNodeTypes); $nodeDataRecords = $this->nodeDataRepository->findByProperties($term, $nodeTypeFilter, $context->getWorkspace(), $context->getDimensions(), $startingPoint ? $startingPoint->getPath() : null); foreach ($nodeDataRecords as $nodeData) { $node = $this->nodeFactory->createFromNodeData($nodeData, $context); if ($node !== null) { $searchResult[$node->getPath()] = $node; } } return $searchResult; }
/** * @param Context $context * @return NodeInterface * @throws NodeTypeNotFoundException * @throws NodeConfigurationException */ public function findOrCreateMetaDataRootNode(Context $context) { if ($this->metaDataRootNode instanceof NodeInterface) { return $this->metaDataRootNode; } $metaDataRootNodeData = $this->metaDataRepository->findOneByPath('/' . MetaDataRepository::METADATA_ROOT_NODE_NAME, $context->getWorkspace()); if ($metaDataRootNodeData !== null) { $metaDataRootNode = $this->nodeFactory->createFromNodeData($metaDataRootNodeData, $context); return $metaDataRootNode; } $nodeTemplate = new NodeTemplate(); $nodeTemplate->setNodeType($this->nodeTypeManager->getNodeType('unstructured')); $nodeTemplate->setName(MetaDataRepository::METADATA_ROOT_NODE_NAME); $context = $this->contextFactory->create(['workspaceName' => 'live']); $rootNode = $context->getRootNode(); $this->metaDataRootNode = $rootNode->createNodeFromTemplate($nodeTemplate); $this->persistenceManager->persistAll(); return $this->metaDataRootNode; }
/** * Returns the specified property. * * If the node has a content object attached, the property will be fetched * there if it is gettable. * * @param string $propertyName Name of the property * @param boolean $returnNodesAsIdentifiers If enabled, references to nodes are returned as node identifiers instead of NodeData objects * @param \TYPO3\TYPO3CR\Domain\Service\Context $context An optional Context if $returnNodesAsIdentifiers === TRUE * @return mixed value of the property * @throws \TYPO3\TYPO3CR\Exception\NodeException if the content object exists but does not contain the specified property. */ public function getProperty($propertyName, $returnNodesAsIdentifiers = FALSE, \TYPO3\TYPO3CR\Domain\Service\Context $context = NULL) { if (!is_object($this->contentObjectProxy)) { $value = isset($this->properties[$propertyName]) ? $this->properties[$propertyName] : NULL; if (!empty($value)) { // TODO: The next two lines are workarounds, actually a NodeData cannot correctly return references but should always return identifier. Node should then apply the context and return the real Node objects. $dimensions = $context !== NULL ? $context->getDimensions() : array(); $workspace = $context !== NULL ? $context->getWorkspace() : $this->getWorkspace(); switch ($this->getNodeType()->getPropertyType($propertyName)) { case 'references': $nodeDatas = array(); if (!is_array($value)) { $value = array(); } $valueNeedsToBeFixed = FALSE; foreach ($value as $nodeIdentifier) { // in cases where a reference is a NodeData instance, fix this if ($nodeIdentifier instanceof NodeData) { $nodeIdentifier = $nodeIdentifier->getIdentifier(); $valueNeedsToBeFixed = TRUE; } if ($returnNodesAsIdentifiers === FALSE) { $nodeData = $this->nodeDataRepository->findOneByIdentifier($nodeIdentifier, $workspace, $dimensions); if ($nodeData instanceof NodeData) { $nodeDatas[] = $nodeData; } } else { $nodeDatas[] = $nodeIdentifier; } } if ($valueNeedsToBeFixed === TRUE) { $fixedValue = array(); foreach ($value as $nodeIdentifier) { if ($nodeIdentifier instanceof NodeData) { $fixedValue[] = $nodeIdentifier->getIdentifier(); } else { $fixedValue[] = $nodeIdentifier; } } $this->properties[$propertyName] = $fixedValue; $this->update(); } $value = $nodeDatas; break; case 'reference': // in cases where a reference is a NodeData instance, fix this if ($value instanceof NodeData) { $value = $value->getIdentifier(); $this->properties[$propertyName] = $value; $this->update(); } if ($returnNodesAsIdentifiers === FALSE) { $nodeData = $this->nodeDataRepository->findOneByIdentifier($value, $workspace, $dimensions); if ($nodeData instanceof NodeData) { $value = $nodeData; } else { $value = NULL; } } break; } } return $value; } elseif (ObjectAccess::isPropertyGettable($this->contentObjectProxy->getObject(), $propertyName)) { return ObjectAccess::getProperty($this->contentObjectProxy->getObject(), $propertyName); } throw new \TYPO3\TYPO3CR\Exception\NodeException(sprintf('Property "%s" does not exist in content object of type %s.', $propertyName, get_class($this->contentObjectProxy->getObject())), 1291286995); }
/** * 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; }
/** * Finds a single node by its parent and (optionally) by its node type * * @param string $parentPath Absolute path of the parent node * @param string $nodeTypeFilter Filter the node type of the nodes, allows complex expressions (e.g. "TYPO3.Neos:Page", "!TYPO3.Neos:Page,TYPO3.Neos:Text" or NULL) * @param Context $context The containing context * @return NodeData The node found or NULL */ public function findFirstByParentAndNodeTypeInContext($parentPath, $nodeTypeFilter, Context $context) { $firstNode = $this->findFirstByParentAndNodeType($parentPath, $nodeTypeFilter, $context->getWorkspace(), $context->getDimensions(), $context->isRemovedContentShown() ? null : false); if ($firstNode !== null) { $firstNode = $this->nodeFactory->createFromNodeData($firstNode, $context); } return $firstNode; }
/** * Adjust this instance to the given context. * * Internal use only! * * @param Context $context * @throws \TYPO3\TYPO3CR\Exception\InvalidNodeContextException */ public function adjustToContext(Context $context) { $this->setWorkspace($context->getWorkspace()); $nodeDimensions = new \Doctrine\Common\Collections\ArrayCollection(); $targetDimensionValues = $context->getTargetDimensions(); foreach ($context->getDimensions() as $dimensionName => $dimensionValues) { if (!isset($targetDimensionValues[$dimensionName])) { throw new \TYPO3\TYPO3CR\Exception\InvalidNodeContextException(sprintf('Missing target value for dimension "%"', $dimensionName), 1391686089); } $dimensionValueToSet = $targetDimensionValues[$dimensionName]; $nodeDimensions->add(new NodeDimension($this, $dimensionName, $dimensionValueToSet)); } $this->setDimensions($nodeDimensions); }