/**
  * @test
  */
 public function findOneByIdentifierFindsRemovedNodeInRepositoryAndRespectsWorkspaceAndDimensions()
 {
     $liveWorkspace = new Workspace('live');
     $nodeData = $this->getMockBuilder('TYPO3\\TYPO3CR\\Domain\\Model\\NodeData')->disableOriginalConstructor()->getMock();
     $nodeData->expects($this->any())->method('getIdentifier')->will($this->returnValue('abcd-efgh-ijkl-mnop'));
     $this->nodeDataRepository->remove($nodeData);
     $dimensions = array('persona' => array('everybody'), 'language' => array('de_DE', 'mul_ZZ'));
     $nodeData->expects($this->atLeastOnce())->method('matchesWorkspaceAndDimensions')->with($liveWorkspace, $dimensions)->will($this->returnValue(TRUE));
     $result = $this->nodeDataRepository->findOneByIdentifier('abcd-efgh-ijkl-mnop', $liveWorkspace, $dimensions);
     $this->assertNull($result);
 }
 /**
  * @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());
 }
 /**
  * @Flow\Around("method(TYPO3\Flow\Mvc\Routing\Router->resolve())")
  * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point
  * @return mixed
  */
 public function addTargetNodeToArguments(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint)
 {
     if (!isset($this->settings['targetNodeMappings']) || !is_array($this->settings['targetNodeMappings'])) {
         return $joinPoint->getAdviceChain()->proceed($joinPoint);
     }
     $arguments = $joinPoint->getMethodArgument('routeValues');
     foreach ($this->settings['targetNodeMappings'] as $pluginNamespace => $pluginTargetNodeMappings) {
         $pluginNamespace = '--' . $pluginNamespace;
         if (!isset($arguments[$pluginNamespace]) || !is_array($arguments[$pluginNamespace])) {
             continue;
         }
         $pluginArguments = $arguments[$pluginNamespace];
         foreach ($pluginTargetNodeMappings as $pluginTargetNodeMapping) {
             if (isset($pluginTargetNodeMapping['package']) && (!isset($pluginArguments['@package']) || strtolower($pluginArguments['@package']) !== strtolower($pluginTargetNodeMapping['package']))) {
                 continue;
             }
             if (isset($pluginTargetNodeMapping['controller']) && (!isset($pluginArguments['@controller']) || strtolower($pluginArguments['@controller']) !== strtolower($pluginTargetNodeMapping['controller']))) {
                 continue;
             }
             if (isset($pluginTargetNodeMapping['action']) && (!isset($pluginArguments['@action']) || strtolower($pluginArguments['@action']) !== strtolower($pluginTargetNodeMapping['action']))) {
                 continue;
             }
             if (isset($pluginTargetNodeMapping['targetNamespace'])) {
                 unset($arguments[$pluginNamespace]);
                 $arguments['--' . $pluginTargetNodeMapping['targetNamespace']] = $pluginArguments;
             }
             $nodeIdentifier = $pluginTargetNodeMapping['targetNode'];
             $node = $this->nodeDataRepository->findOneByIdentifier($nodeIdentifier, $this->createContext()->getWorkspace());
             if ($node === NULL) {
                 throw new \TYPO3\Flow\Exception('no node with identifier "' . $nodeIdentifier . '" found', 1334172725);
             }
             $arguments['node'] = $node->getContextPath();
             $arguments['@package'] = 'TYPO3.Neos';
             $arguments['@controller'] = 'Frontend\\Node';
             $arguments['@format'] = 'html';
             $arguments['@action'] = 'show';
             $joinPoint->setMethodArgument('routeValues', $arguments);
             return $joinPoint->getAdviceChain()->proceed($joinPoint);
         }
     }
     return $joinPoint->getAdviceChain()->proceed($joinPoint);
 }
 /**
  * Change the property on the given node.
  *
  * @param NodeData $node
  * @return NodeData
  */
 public function execute(NodeData $node)
 {
     $reference = (string) $node->getProperty('plugin');
     $workspace = $node->getWorkspace();
     do {
         if ($this->reverse === false && preg_match(NodeInterface::MATCH_PATTERN_PATH, $reference)) {
             $pluginNode = $this->nodeDataRepository->findOneByPath($reference, $node->getWorkspace());
         } else {
             $pluginNode = $this->nodeDataRepository->findOneByIdentifier($reference, $node->getWorkspace());
         }
         if (isset($pluginNode)) {
             break;
         }
         $workspace = $workspace->getBaseWorkspace();
     } while ($workspace && $workspace->getName() !== 'live');
     if (isset($pluginNode)) {
         $node->setProperty('plugin', $this->reverse === false ? $pluginNode->getIdentifier() : $pluginNode->getPath());
     }
     return $node;
 }
 /**
  * Get a node by identifier and this context
  *
  * @param string $identifier The identifier of a node
  * @return NodeInterface The node with the given identifier or NULL if no such node exists
  */
 public function getNodeByIdentifier($identifier)
 {
     $node = $this->firstLevelNodeCache->getByIdentifier($identifier);
     if ($node !== false) {
         return $node;
     }
     $nodeData = $this->nodeDataRepository->findOneByIdentifier($identifier, $this->getWorkspace(), $this->dimensions);
     if ($nodeData !== null) {
         $node = $this->nodeFactory->createFromNodeData($nodeData, $this);
     } else {
         $node = null;
     }
     $this->firstLevelNodeCache->setByIdentifier($identifier, $node);
     return $node;
 }
 /**
  * Collects all nodes with missing shadow nodes
  *
  * @param Workspace $workspace
  * @param boolean $dryRun
  * @param NodeType $nodeType
  * @return array
  */
 protected function fixShadowNodesInWorkspace(Workspace $workspace, $dryRun, NodeType $nodeType = null)
 {
     $workspaces = array_merge([$workspace], $workspace->getBaseWorkspaces());
     $fixedShadowNodes = 0;
     foreach ($workspaces as $workspace) {
         /** @var Workspace $workspace */
         if ($workspace->getBaseWorkspace() === null) {
             continue;
         }
         /** @var QueryBuilder $queryBuilder */
         $queryBuilder = $this->entityManager->createQueryBuilder();
         $queryBuilder->select('n')->from(NodeData::class, 'n')->where('n.workspace = :workspace');
         $queryBuilder->setParameter('workspace', $workspace->getName());
         if ($nodeType !== null) {
             $queryBuilder->andWhere('n.nodeType = :nodeType');
             $queryBuilder->setParameter('nodeType', $nodeType->getName());
         }
         /** @var NodeData $nodeData */
         foreach ($queryBuilder->getQuery()->getResult() as $nodeData) {
             $nodeDataSeenFromParentWorkspace = $this->nodeDataRepository->findOneByIdentifier($nodeData->getIdentifier(), $workspace->getBaseWorkspace(), $nodeData->getDimensionValues());
             // This is the good case, either the node does not exist or was shadowed
             if ($nodeDataSeenFromParentWorkspace === null) {
                 continue;
             }
             // Also good, the node was not moved at all.
             if ($nodeDataSeenFromParentWorkspace->getPath() === $nodeData->getPath()) {
                 continue;
             }
             $nodeDataOnSamePath = $this->nodeDataRepository->findOneByPath($nodeData->getPath(), $workspace->getBaseWorkspace(), $nodeData->getDimensionValues(), null);
             // We cannot just put a shadow node in the path, something exists, but that should be fine.
             if ($nodeDataOnSamePath !== null) {
                 continue;
             }
             if (!$dryRun) {
                 $nodeData->createShadow($nodeDataSeenFromParentWorkspace->getPath());
             }
             $fixedShadowNodes++;
         }
     }
     return $fixedShadowNodes;
 }
 /**
  * Returns the NodeData instance with the given identifier from the target workspace.
  * If no NodeData instance is found, NULL is returned.
  *
  * @param NodeInterface $node
  * @param Workspace $targetWorkspace
  * @return NodeData
  */
 protected function findNodeDataInTargetWorkspace(NodeInterface $node, Workspace $targetWorkspace)
 {
     $nodeData = $this->nodeDataRepository->findOneByIdentifier($node->getIdentifier(), $targetWorkspace, $node->getDimensions());
     return $nodeData === null || $nodeData->getWorkspace() === $targetWorkspace ? $nodeData : null;
 }
 /**
  * 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);
 }
 /**
  * Get array of node selection properties
  *
  *
  *
  * @param Node $node
  * @return array
  */
 public function prepareNodeSelectionFromNode(Node $node)
 {
     foreach ($this->contentContextFactory->getInstances() as $context) {
         $this->workspace = $context->getWorkspace();
         break;
     }
     $limit = false;
     $limit_param_name = false;
     $offset = false;
     $offset_param_name = false;
     $filter = array();
     $sort = array();
     $nodetype = false;
     $nodetypeisabstract = false;
     $entryNodes = array();
     $nodeParentPath = $node->getParentPath();
     if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')) {
         // calculate nodetype name
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('nodeType', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['nodeType'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $nodetype = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $nodetype = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $nodetype == false) {
                             $nodetype = addslashes($this->httpRequest->getArgument($value));
                         }
                         break;
                     case 'abstract':
                         $nodetypeisabstract = TRUE;
                         break;
                     default:
                         break;
                 }
             }
         } else {
             throw new IndexedNodesException($node->getNodeData()->getNodeType()->getName() . ' has no nodeType definition.');
         }
         // calculate limit
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('limit', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['limit'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $limit = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $limit = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $limit == false) {
                             $limit = addslashes($this->httpRequest->getArgument($value));
                         }
                         $limit_param_name = $value;
                         if (strlen($limit) == 0) {
                             $limit = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$limit) {
             // fetch default limit from internal params
             $value = "_limit-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $limit = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$limit_param_name) {
                 $limit_param_name = $value;
             }
         }
         // calculate limit offset, if limit isset
         if ($limit && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('offset', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['offset'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $offset = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $offset = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $offset == false) {
                             $offset = addslashes($this->httpRequest->getArgument($value));
                         }
                         $offset_param_name = $value;
                         if (strlen($offset) == 0) {
                             $offset = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$offset) {
             // fetch default offset from internal params
             $value = "_offset-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $offset = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$offset_param_name) {
                 $offset_param_name = $value;
             }
             if (strlen($offset) == 0) {
                 $offset = 0;
             }
         }
         // calculate filters
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter']) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter'] as $property => $arguments) {
                 foreach ($arguments as $arg => $filterValues) {
                     switch ($arg) {
                         case 'type':
                             $filter[$property]['type'] = $filterValues;
                             break;
                         case 'operand':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operand'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operand'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operand']) == false) {
                                             $filter[$property]['operand'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                         case 'operator':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operator'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operator'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operator']) == false) {
                                             $filter[$property]['operator'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                     }
                 }
                 if (isset($filter[$property]['type']) == false) {
                     $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                     // get sorting type by property definition
                     if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                         $filter[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                     } else {
                         $filter[$property]['type'] = 'string';
                     }
                 }
             }
         }
         // calculate entry nodes
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('entryNodes', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['entryNodes'] as $property => $filterValues) {
                 foreach ($filterValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $entryNodes[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $entryNodes[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($entryNodes[$property]['value']) == false) {
                                 $entryNodes[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'recursive':
                             $entryNodes[$property]['recursive'] = $value;
                             break;
                         case 'childNodePath':
                             $entryNodes[$property]['childNodePath'] = $value;
                             break;
                     }
                     if (isset($entryNodes[$property]['recursive']) == false) {
                         $entryNodes[$property]['recursive'] = TRUE;
                     }
                     if (isset($entryNodes[$property]['childNodePath']) == false) {
                         $entryNodes[$property]['childNodePath'] = FALSE;
                     }
                     if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value']) == false) {
                         $targetNode = $this->nodeDataRepository->findOneByIdentifier($entryNodes[$property]['value'], $this->workspace);
                         if ($targetNode) {
                             $entryNodes[$property]['path'] = $targetNode->getParentPath();
                         }
                     }
                 }
                 if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value'])) {
                     $t = $entryNodes[$property];
                     unset($entryNodes[$property]);
                     foreach ($t['value'] as $key => $val) {
                         $entryNodes[$property . $key] = array('path' => $val->getPath(), 'childNodePath' => $t['childNodePath'], 'parentPath' => $val->getParentPath(), 'childNodes' => $val->getNodeType()->getChildNodes(), 'recursive' => $t['recursive']);
                     }
                 }
             }
         } else {
             // set reference to self node
             $entryNodes['self'] = array('path' => '/');
         }
         // calculate sorting
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('sort', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['sort'] as $nullkey => $sortValues) {
                 foreach ($sortValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $sort[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $sort[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($sort[$property]) == false) {
                                 $sort[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'type':
                             $sort[$property]['type'] = $value;
                             break;
                         case 'direction':
                             foreach ($value as $k => $v) {
                                 switch ($k) {
                                     case 'property':
                                         if ($node->getProperty($v)) {
                                             $sort[$property]['direction'] = $node->getProperty($v);
                                         }
                                         break;
                                     case 'value':
                                         $sort[$property]['direction'] = $v;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($v) || isset($sort[$property]['direction']) == false) {
                                             $sort[$property]['direction'] = addslashes($this->httpRequest->getArgument($v));
                                         }
                                         break;
                                 }
                             }
                             break;
                         default:
                             break;
                     }
                     if (isset($sort[$property]['type']) == false) {
                         $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                         // get sorting type by property definition
                         if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                             $sort[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                         } else {
                             $sort[$property]['type'] = 'string';
                         }
                     }
                 }
             }
         }
     }
     return array('limit' => $limit, 'limit_param_name' => $limit_param_name, 'offset' => $offset, 'offset_param_name' => $offset_param_name, 'filter' => $filter, 'sort' => $sort, 'nodetype' => $nodetype, 'nodetypeisabstract' => $nodetypeisabstract, 'entryNodes' => $entryNodes, 'workspace' => $this->workspace);
 }