It is specifically implemented for being used inside Eel, the Embedded Expression Language for Flow. Essentially, a FlowQuery object is a container for an *ordered set* of objects of a certain type. On this container, *operations* can be applied (like filter(), children(), ...). All of these operations work on a *set*, that is, an operation usually expands or shrinks the set of objects. An operation normally returns a new FlowQuery instance with the operation applied, but there are also some operations like is(...) or count(), which return simple types like boolean or numbers. We call these operations *final operations*. Internal Workings ================= To allow for optimization, calling operations are not immediately executed. Instead, they are appended to a *list of operations*. Only if one tries to iterate over the FlowQuery object or calls a final operation, the operations get executed and the result is computed. Implementation of Operations ---------------------------- Operations are implemented by implementing the {@link OperationInterface} or, more commonly, subclassing the {@link Operations/AbstractOperation}. An operation must be *equivalence preserving*, that is, the following equation must always hold: applyAllOperations(context) = applyRemainingOperations(applyOperation(context)) While an operation is running, it can *add new operations* to the front of the operation queue (with {@link pushOperation()}), so for example count($filter) can first apply filter($filter), followed by count(). However, when doing this, great care must be applied by the operation developer in order to still have finite runs, and to make sure the operation is *equivalence preserving*. Furthermore, an operation can *pop* its following operations from the operation stack, and *peek* what the next operation is. It is up to the operation developer to ensure equivalence preservation. An operation may *never* invoke __call() on the FlowQuery object it receives; as this might lead to an undefined state; i.e. you are not allowed to do: $flowQuery->someOtherOperation() *inside* an operation. Final Operations ---------------- If an operation is final, it should return the resulting value directly.
Inheritance: implements Neos\Eel\ProtectedContextAwareInterface, implements IteratorAggregate, implements Countable
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = array();
     $outputNodePaths = array();
     $until = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         $nextNodes = $this->getNextForNode($contextNode);
         if (isset($arguments[0]) && !empty($arguments[0])) {
             $untilQuery = new FlowQuery($nextNodes);
             $untilQuery->pushOperation('filter', array($arguments[0]));
             $until = $untilQuery->get();
         }
         if (isset($until[0]) && !empty($until[0])) {
             $nextNodes = $this->getNodesUntil($nextNodes, $until[0]);
         }
         if (is_array($nextNodes)) {
             foreach ($nextNodes as $nextNode) {
                 if ($nextNode !== null && !isset($outputNodePaths[$nextNode->getPath()])) {
                     $outputNodePaths[$nextNode->getPath()] = true;
                     $output[] = $nextNode;
                 }
             }
         }
     }
     $flowQuery->setContext($output);
     if (isset($arguments[1]) && !empty($arguments[1])) {
         $flowQuery->pushOperation('filter', array($arguments[1]));
     }
 }
 /**
  * Tests on a tree:
  *
  * a
  *   a1
  *   a2
  * b (TestingNodeType)
  *   b1 (TestingNodeType)
  *     b1a
  *   b2
  *   b3 (TestingNodeTypeWithSubnodes)
  *     b3a (TestingNodeType)
  *     b3b
  *
  * @test
  * @dataProvider closestOperationDataProvider
  */
 public function closestOperationTests($currentNodePath, $nodeTypeFilter, $expectedNodePath)
 {
     $nodeTypeManager = $this->objectManager->get(NodeTypeManager::class);
     $testNodeType1 = $nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:NodeType');
     $testNodeType2 = $nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:NodeTypeWithSubnodes');
     $rootNode = $this->node->getNode('/');
     $nodeA = $rootNode->createNode('a');
     $nodeA->createNode('a1');
     $nodeA->createNode('a2');
     $nodeB = $rootNode->createNode('b', $testNodeType1);
     $nodeB1 = $nodeB->createNode('b1', $testNodeType1);
     $nodeB1->createNode('b1a');
     $nodeB->createNode('b2');
     $nodeB3 = $nodeB->createNode('b3', $testNodeType2);
     $nodeB3->createNode('b3a', $testNodeType1);
     $nodeB3->createNode('b3b');
     $currentNode = $rootNode->getNode($currentNodePath);
     $q = new FlowQuery(array($currentNode));
     $actualNode = $q->closest($nodeTypeFilter)->get(0);
     if ($expectedNodePath === null) {
         if ($actualNode !== null) {
             $this->fail('Expected resulting node to be NULL');
         }
         $this->assertNull($actualNode);
     } else {
         $this->assertSame($expectedNodePath, $actualNode->getPath());
     }
 }
 /**
  * Tests on a tree:
  *
  * a
  *   a1
  * b
  *   b1 (TestingNodeType)
  *     b1a
  * c
  *
  * @test
  * @dataProvider hasOperationDataProvider()
  */
 public function hasOperationTests(array $currentNodePaths, $subject, array $expectedNodePaths)
 {
     $nodeTypeManager = $this->objectManager->get(NodeTypeManager::class);
     $testNodeType1 = $nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:NodeType');
     $rootNode = $this->node->getNode('/');
     $nodeA = $rootNode->createNode('a');
     $nodeA->createNode('a1');
     $nodeB = $rootNode->createNode('b');
     $nodeB1 = $nodeB->createNode('b1', $testNodeType1);
     $nodeB1->createNode('b1a');
     $rootNode->createNode('c');
     $currentNodes = array();
     foreach ($currentNodePaths as $currentNodePath) {
         $currentNodes[] = $rootNode->getNode($currentNodePath);
     }
     if (is_array($subject)) {
         $subjectNodes = array();
         foreach ($subject as $subjectNodePath) {
             $subjectNodes[] = $rootNode->getNode($subjectNodePath);
         }
         $subject = $subjectNodes;
     }
     $q = new FlowQuery($currentNodes);
     $result = $q->has($subject)->get();
     if ($expectedNodePaths === array()) {
         $this->assertEmpty($result);
     } else {
         foreach ($expectedNodePaths as $expectedNodePath) {
             $expectedNode = $rootNode->getNode($expectedNodePath);
             if (!in_array($expectedNode, $result)) {
                 $this->fail(sprintf('Expected result to contain node "%s"', $expectedNodePath));
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = array();
     $outputNodePaths = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         $siteNode = $contextNode->getContext()->getCurrentSiteNode();
         $parentNodes = $this->getParents($contextNode, $siteNode);
         if (isset($arguments[0]) && !empty($arguments[0] && isset($parentNodes[0]))) {
             $untilQuery = new FlowQuery(array($parentNodes[0]));
             $untilQuery->pushOperation('closest', array($arguments[0]));
             $until = $untilQuery->get();
         }
         if (isset($until) && is_array($until) && !empty($until) && isset($until[0])) {
             $parentNodes = $this->getNodesUntil($parentNodes, $until[0]);
         }
         if (is_array($parentNodes)) {
             foreach ($parentNodes as $parentNode) {
                 if ($parentNode !== null && !isset($outputNodePaths[$parentNode->getPath()])) {
                     $outputNodePaths[$parentNode->getPath()] = true;
                     $output[] = $parentNode;
                 }
             }
         }
     }
     $flowQuery->setContext($output);
     if (isset($arguments[1]) && !empty($arguments[1])) {
         $flowQuery->pushOperation('filter', $arguments[1]);
     }
 }
 /**
  * @test
  */
 public function parentsFollowedByFirstMatchesInnermostNodeOnRootline()
 {
     $teaserText = $this->node->getNode('teaser/dummy42');
     $q = new FlowQuery(array($teaserText));
     $actual = iterator_to_array($q->parents('[someSpecialProperty]')->first());
     $expected = array($this->node->getNode('teaser'));
     $this->assertTrue($expected === $actual);
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments Ignored for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $context = $flowQuery->getContext();
     if (count($context) > 0) {
         $flowQuery->setContext([end($context)]);
     } else {
         $flowQuery->setContext([]);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments Ignored for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $context = $flowQuery->getContext();
     if (isset($context[0])) {
         $flowQuery->setContext([$context[0]]);
     } else {
         $flowQuery->setContext([]);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the filter arguments
  * @return void|boolean
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (count($arguments) == 0) {
         return count($flowQuery->getContext()) > 0;
     } else {
         $flowQuery->pushOperation('is', []);
         $flowQuery->pushOperation('filter', $arguments);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments A mandatory start and optional end index in the context, negative indices indicate an offset from the start or end respectively
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $context = $flowQuery->getContext();
     if ($context instanceof \Iterator) {
         $context = iterator_to_array($context);
     }
     if (isset($arguments[0]) && isset($arguments[1])) {
         $context = array_slice($context, (int) $arguments[0], (int) $arguments[1] - (int) $arguments[0]);
     } elseif (isset($arguments[0])) {
         $context = array_slice($context, (int) $arguments[0]);
     }
     $flowQuery->setContext($context);
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the context index to fetch from
  * @return mixed
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $context = $flowQuery->getContext();
     if (isset($arguments[0])) {
         $index = $arguments[0];
         if (isset($context[$index])) {
             return $context[$index];
         } else {
             return null;
         }
     } else {
         return $context;
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the property path to use (in index 0)
  * @return mixed
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || empty($arguments[0])) {
         throw new FlowQueryException('property() must be given an attribute name when used on objects, fetching all attributes is not supported.', 1332492263);
     } else {
         $context = $flowQuery->getContext();
         if (!isset($context[0])) {
             return null;
         }
         $element = $context[0];
         $propertyPath = $arguments[0];
         return ObjectAccess::getPropertyPath($element, $propertyPath);
     }
 }
 /**
  * @param array $nodes
  */
 public function assignNodes(array $nodes)
 {
     $data = array();
     foreach ($nodes as $node) {
         if ($node->getPath() !== '/') {
             $q = new FlowQuery(array($node));
             $closestDocumentNode = $q->closest('[instanceof Neos.Neos:Document]')->get(0);
             if ($closestDocumentNode !== null) {
                 $data[] = array('nodeContextPath' => $node->getContextPath(), 'documentNodeContextPath' => $closestDocumentNode->getContextPath());
             } else {
                 $this->systemLogger->log('You have a node that is no longer connected to a parent. Path: ' . $node->getPath() . ' (Identifier: ' . $node->getIdentifier() . ')');
             }
         }
     }
     $this->assign('value', array('data' => $data, 'success' => true));
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = array();
     $outputNodePaths = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         $prevNode = $this->getPrevForNode($contextNode);
         if ($prevNode !== null && !isset($outputNodePaths[$prevNode->getPath()])) {
             $outputNodePaths[$prevNode->getPath()] = true;
             $output[] = $prevNode;
         }
     }
     $flowQuery->setContext($output);
     if (isset($arguments[0]) && !empty($arguments[0])) {
         $flowQuery->pushOperation('filter', $arguments);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery The FlowQuery object
  * @param array $arguments The arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || !is_array($arguments[0])) {
         throw new FlowQueryException('context() requires an array argument of context properties', 1398030427);
     }
     $output = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         $contextProperties = $contextNode->getContext()->getProperties();
         $modifiedContext = $this->contextFactory->create(array_merge($contextProperties, $arguments[0]));
         $nodeInModifiedContext = $modifiedContext->getNodeByIdentifier($contextNode->getIdentifier());
         if ($nodeInModifiedContext !== null) {
             $output[$nodeInModifiedContext->getPath()] = $nodeInModifiedContext;
         }
     }
     $flowQuery->setContext(array_values($output));
 }
 /**
  * @param NodeInterface $node A node
  * @return array of document nodes
  */
 public function render(NodeInterface $node)
 {
     $documentNodes = [];
     $flowQuery = new FlowQuery(array($node));
     $nodes = array_reverse($flowQuery->parents('[instanceof Neos.Neos:Document]')->get());
     /** @var NodeInterface $node */
     foreach ($nodes as $documentNode) {
         $documentNodes[] = $documentNode;
     }
     if ($node->getNodeType()->isOfType('Neos.Neos:Document')) {
         $documentNodes[] = $node;
     }
     $this->templateVariableContainer->add('documentNodes', $documentNodes);
     $content = $this->renderChildren();
     $this->templateVariableContainer->remove('documentNodes');
     return $content;
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the elements to add (as array in index 0)
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = [];
     foreach ($flowQuery->getContext() as $element) {
         $output[] = $element;
     }
     if (isset($arguments[0])) {
         if (is_array($arguments[0]) || $arguments[0] instanceof \Traversable) {
             foreach ($arguments[0] as $element) {
                 $output[] = $element;
             }
         } else {
             $output[] = $arguments[0];
         }
     }
     $flowQuery->setContext($output);
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || empty($arguments[0])) {
         throw new FlowQueryException('closest() requires a filter argument', 1332492263);
     }
     $output = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         $contextNodeQuery = new FlowQuery(array($contextNode));
         $contextNodeQuery->pushOperation('first', array());
         $contextNodeQuery->pushOperation('filter', $arguments);
         $parentsQuery = new FlowQuery(array($contextNode));
         $contextNodeQuery->pushOperation('add', array($parentsQuery->parents($arguments[0])->get()));
         foreach ($contextNodeQuery as $result) {
             $output[$result->getPath()] = $result;
         }
     }
     $flowQuery->setContext(array_values($output));
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return mixed
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || empty($arguments[0])) {
         throw new FlowQueryException('property() does not support returning all attributes yet', 1332492263);
     } else {
         $context = $flowQuery->getContext();
         $propertyPath = $arguments[0];
         if (!isset($context[0])) {
             return null;
         }
         $element = $context[0];
         if ($propertyPath[0] === '_') {
             return ObjectAccess::getPropertyPath($element, substr($propertyPath, 1));
         } else {
             return $element->getProperty($propertyPath);
         }
     }
 }
 /**
  * {@inheritdoc}
  *
  * First argument is the node property to sort by. Works with internal arguments (_xyz) as well.
  * Second argument is the sort direction (ASC or DESC).
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation.
  * @return mixed
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $nodes = $flowQuery->getContext();
     // Check sort property
     if (isset($arguments[0]) && !empty($arguments[0])) {
         $sortProperty = $arguments[0];
     } else {
         throw new \Neos\Eel\FlowQuery\FlowQueryException('Please provide a node property to sort by.', 1467881104);
     }
     // Check sort direction
     if (isset($arguments[1]) && !empty($arguments[1]) && in_array(strtoupper($arguments[1]), ['ASC', 'DESC'])) {
         $sortOrder = strtoupper($arguments[1]);
     } else {
         throw new \Neos\Eel\FlowQuery\FlowQueryException('Please provide a valid sort direction (ASC or DESC)', 1467881105);
     }
     $sortedNodes = [];
     $sortSequence = [];
     $nodesByIdentifier = [];
     // Determine the property value to sort by
     /** @var Node $node */
     foreach ($nodes as $node) {
         if ($sortProperty[0] === '_') {
             $propertyValue = \Neos\Utility\ObjectAccess::getPropertyPath($node, substr($sortProperty, 1));
         } else {
             $propertyValue = $node->getProperty($sortProperty);
         }
         if ($propertyValue instanceof \DateTime) {
             $propertyValue = $propertyValue->getTimestamp();
         }
         $sortSequence[$node->getIdentifier()] = $propertyValue;
         $nodesByIdentifier[$node->getIdentifier()] = $node;
     }
     // Create the sort sequence
     if ($sortOrder === 'DESC') {
         arsort($sortSequence);
     } elseif ($sortOrder === 'ASC') {
         asort($sortSequence);
     }
     // Build the sorted context that is returned
     foreach ($sortSequence as $nodeIdentifier => $value) {
         $sortedNodes[] = $nodesByIdentifier[$nodeIdentifier];
     }
     $flowQuery->setContext($sortedNodes);
 }
 /**
  * @Flow\Around("method(Neos\Flow\Mvc\Routing\UriBuilder->uriFor())")
  * @param \Neos\Flow\Aop\JoinPointInterface $joinPoint The current join point
  * @return string The result of the target method if it has not been intercepted
  */
 public function rewritePluginViewUris(JoinPointInterface $joinPoint)
 {
     /** @var ActionRequest $request */
     $request = $joinPoint->getProxy()->getRequest();
     $arguments = $joinPoint->getMethodArguments();
     $currentNode = $request->getInternalArgument('__node');
     if (!$request->getMainRequest()->hasArgument('node') || !$currentNode instanceof Node) {
         return $joinPoint->getAdviceChain()->proceed($joinPoint);
     }
     $currentNode = $request->getInternalArgument('__node');
     $controllerObjectName = $this->getControllerObjectName($request, $arguments);
     $actionName = $arguments['actionName'] !== null ? $arguments['actionName'] : $request->getControllerActionName();
     $targetNode = $this->pluginService->getPluginNodeByAction($currentNode, $controllerObjectName, $actionName);
     // TODO override namespace
     $q = new FlowQuery(array($targetNode));
     $pageNode = $q->closest('[instanceof Neos.Neos:Document]')->get(0);
     $result = $this->generateUriForNode($request, $joinPoint, $pageNode);
     return $result;
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery
  * @param array $arguments
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || empty($arguments[0])) {
         return;
     }
     if ($arguments[0] instanceof NodeInterface) {
         $filteredContext = array();
         $context = $flowQuery->getContext();
         foreach ($context as $element) {
             if ($element === $arguments[0]) {
                 $filteredContext[] = $element;
                 break;
             }
         }
         $flowQuery->setContext($filteredContext);
     } else {
         parent::evaluate($flowQuery, $arguments);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = array();
     $outputNodePaths = array();
     foreach ($flowQuery->getContext() as $contextNode) {
         /** @var NodeInterface $contextNode */
         $siteNode = $contextNode->getContext()->getCurrentSiteNode();
         while ($contextNode !== $siteNode && $contextNode->getParent() !== null) {
             $contextNode = $contextNode->getParent();
             if (!isset($outputNodePaths[$contextNode->getPath()])) {
                 $output[] = $contextNode;
                 $outputNodePaths[$contextNode->getPath()] = true;
             }
         }
     }
     $flowQuery->setContext($output);
     if (isset($arguments[0]) && !empty($arguments[0])) {
         $flowQuery->pushOperation('filter', $arguments);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery The FlowQuery object
  * @param array $arguments None
  * @return integer The cache lifetime in seconds or NULL if either no content collection was given or no child node had a "hiddenBeforeDateTime" or "hiddenAfterDateTime" property set
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $minimumDateTime = null;
     foreach ($flowQuery->getContext() as $contextNode) {
         $hiddenBeforeDateTime = $contextNode->getHiddenBeforeDateTime();
         if ($hiddenBeforeDateTime !== null && $hiddenBeforeDateTime > $this->now && ($minimumDateTime === null || $hiddenBeforeDateTime < $minimumDateTime)) {
             $minimumDateTime = $hiddenBeforeDateTime;
         }
         $hiddenAfterDateTime = $contextNode->getHiddenAfterDateTime();
         if ($hiddenAfterDateTime !== null && $hiddenAfterDateTime > $this->now && ($minimumDateTime === null || $hiddenAfterDateTime < $minimumDateTime)) {
             $minimumDateTime = $hiddenAfterDateTime;
         }
     }
     if ($minimumDateTime !== null) {
         $maximumLifetime = $minimumDateTime->getTimestamp() - $this->now->getTimestamp();
         if ($maximumLifetime > 0) {
             return $maximumLifetime;
         }
     }
     return null;
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the arguments for this operation
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $output = array();
     $outputNodePaths = array();
     /** @var NodeInterface $contextNode */
     foreach ($flowQuery->getContext() as $contextNode) {
         $outputNodePaths[$contextNode->getPath()] = true;
     }
     foreach ($flowQuery->getContext() as $contextNode) {
         $parentNode = $contextNode->getParent();
         if ($parentNode instanceof NodeInterface) {
             foreach ($parentNode->getChildNodes() as $childNode) {
                 if (!isset($outputNodePaths[$childNode->getPath()])) {
                     $output[] = $childNode;
                     $outputNodePaths[$childNode->getPath()] = true;
                 }
             }
         }
     }
     $flowQuery->setContext($output);
     if (isset($arguments[0]) && !empty($arguments[0])) {
         $flowQuery->pushOperation('filter', $arguments);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery the FlowQuery object
  * @param array $arguments the filter expression to use (in index 0)
  * @return void
  * @throws FizzleException
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     if (!isset($arguments[0]) || empty($arguments[0])) {
         return;
     }
     if (!is_string($arguments[0])) {
         throw new FizzleException('filter operation expects string argument', 1332489625);
     }
     $filter = $arguments[0];
     $parsedFilter = FizzleParser::parseFilterGroup($filter);
     $filteredContext = [];
     $context = $flowQuery->getContext();
     foreach ($context as $element) {
         if ($this->matchesFilterGroup($element, $parsedFilter)) {
             $filteredContext[] = $element;
         }
     }
     $flowQuery->setContext($filteredContext);
 }
Example #26
0
 /**
  * Takes care of creating a redirect to properly render the collection the given node is in.
  *
  * @param NodeInterface $node
  * @param string $typoScriptPath
  * @return string
  */
 protected function redirectToRenderNode(NodeInterface $node, $typoScriptPath)
 {
     $q = new FlowQuery(array($node));
     $closestContentCollection = $q->closest('[instanceof Neos.Neos:ContentCollection]')->get(0);
     $closestDocumentNode = $q->closest('[instanceof Neos.Neos:Document]')->get(0);
     $this->redirect('show', 'Frontend\\Node', 'Neos.Neos', ['node' => $closestDocumentNode, '__nodeContextPath' => $closestContentCollection->getContextPath(), '__affectedNodeContextPath' => $node->getContextPath(), '__typoScriptPath' => $typoScriptPath], 0, 303, 'html');
 }
 /**
  * Evaluate the property name filter by traversing to the child object. We only support
  * nested objects right now
  *
  * @param FlowQuery $query
  * @param string $propertyNameFilter
  * @return void
  */
 protected function evaluatePropertyNameFilter(FlowQuery $query, $propertyNameFilter)
 {
     $resultObjects = [];
     $resultObjectHashes = [];
     foreach ($query->getContext() as $element) {
         $subProperty = ObjectAccess::getPropertyPath($element, $propertyNameFilter);
         if (is_object($subProperty) || is_array($subProperty)) {
             if (is_array($subProperty) || $subProperty instanceof \Traversable) {
                 foreach ($subProperty as $childElement) {
                     if (!isset($resultObjectHashes[spl_object_hash($childElement)])) {
                         $resultObjectHashes[spl_object_hash($childElement)] = true;
                         $resultObjects[] = $childElement;
                     }
                 }
             } elseif (!isset($resultObjectHashes[spl_object_hash($subProperty)])) {
                 $resultObjectHashes[spl_object_hash($subProperty)] = true;
                 $resultObjects[] = $subProperty;
             }
         }
     }
     $query->setContext($resultObjects);
 }
 /**
  * {@inheritdoc}
  *
  * @param FlowQuery $flowQuery
  * @param array $arguments
  * @return void
  */
 public function evaluate(FlowQuery $flowQuery, array $arguments)
 {
     $subject = $arguments[0];
     if (!isset($subject) || empty($subject)) {
         $flowQuery->setContext(array());
         return;
     }
     $filteredContext = array();
     $context = $flowQuery->getContext();
     if (is_string($subject)) {
         foreach ($context as $contextElement) {
             $contextElementQuery = new FlowQuery(array($contextElement));
             $contextElementQuery->pushOperation('children', $arguments);
             if ($contextElementQuery->count() > 0) {
                 $filteredContext[] = $contextElement;
             }
         }
     } else {
         if ($subject instanceof FlowQuery) {
             $elements = $subject->get();
         } elseif ($subject instanceof \Traversable) {
             $elements = iterator_to_array($subject);
         } elseif (is_object($subject)) {
             $elements = array($subject);
         } elseif (is_array($subject)) {
             $elements = $subject;
         } else {
             throw new FizzleException('supplied argument for has operation not supported', 1332489625);
         }
         foreach ($elements as $element) {
             if ($element instanceof NodeInterface) {
                 $parentsQuery = new FlowQuery(array($element));
                 /** @var NodeInterface $parent */
                 foreach ($parentsQuery->parents(array())->get() as $parent) {
                     /** @var NodeInterface $contextElement */
                     foreach ($context as $contextElement) {
                         if ($contextElement->getIdentifier() === $parent->getIdentifier()) {
                             $filteredContext[] = $contextElement;
                         }
                     }
                 }
             }
         }
         $filteredContext = array_unique($filteredContext);
     }
     $flowQuery->setContext($filteredContext);
 }
 /**
  * Returns an array of usage reference objects.
  *
  * @param AssetInterface $asset
  * @return array<\Neos\Neos\Domain\Model\Dto\AssetUsageInNodeProperties>
  * @throws \Neos\ContentRepository\Exception\NodeConfigurationException
  */
 public function getUsageReferences(AssetInterface $asset)
 {
     $assetIdentifier = $this->persistenceManager->getIdentifierByObject($asset);
     if (isset($this->firstlevelCache[$assetIdentifier])) {
         return $this->firstlevelCache[$assetIdentifier];
     }
     $userWorkspace = $this->userService->getPersonalWorkspace();
     $relatedNodes = [];
     foreach ($this->getRelatedNodes($asset) as $relatedNodeData) {
         $accessible = $this->domainUserService->currentUserCanReadWorkspace($relatedNodeData->getWorkspace());
         if ($accessible) {
             $context = $this->createContextMatchingNodeData($relatedNodeData);
         } else {
             $context = $this->createContentContext($userWorkspace->getName());
         }
         $site = $context->getCurrentSite();
         $node = $this->nodeFactory->createFromNodeData($relatedNodeData, $context);
         $flowQuery = new FlowQuery([$node]);
         /** @var \Neos\ContentRepository\Domain\Model\NodeInterface $documentNode */
         $documentNode = $flowQuery->closest('[instanceof Neos.Neos:Document]')->get(0);
         $relatedNodes[] = new AssetUsageInNodeProperties($asset, $site, $documentNode, $node, $accessible);
     }
     $this->firstlevelCache[$assetIdentifier] = $relatedNodes;
     return $this->firstlevelCache[$assetIdentifier];
 }
 /**
  *
  * @param string $workspaceName
  * @return NodeInterface
  */
 protected function getLastVisitedNode($workspaceName)
 {
     if (!$this->session->isStarted() || !$this->session->hasKey('lastVisitedNode')) {
         return null;
     }
     try {
         $lastVisitedNode = $this->propertyMapper->convert($this->session->getData('lastVisitedNode'), NodeInterface::class);
         $q = new FlowQuery([$lastVisitedNode]);
         $lastVisitedNodeUserWorkspace = $q->context(['workspaceName' => $workspaceName])->get(0);
         return $lastVisitedNodeUserWorkspace;
     } catch (\Exception $exception) {
         return null;
     }
 }