Skip to content

Instantly share code, notes, and snippets.

@Sebobo
Last active March 2, 2016 09:09
Show Gist options
  • Save Sebobo/2201c060ac04b66e814f to your computer and use it in GitHub Desktop.
Save Sebobo/2201c060ac04b66e814f to your computer and use it in GitHub Desktop.
Sort operation for a set of nodes based on their index
<?php
namespace Foo\Bar\TypoScript\FlowQueryOperations;
use TYPO3\Eel\FlowQuery\Operations\AbstractOperation;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;
use TYPO3\Eel\FlowQuery\FlowQuery;
/**
* Sort Nodes by their position in the node tree.
*
* Use it like this:
*
* ${q(node).children().sortRecursive(['ASC'|'DESC'])}
*/
class SortRecursiveOperation extends AbstractOperation
{
/**
* {@inheritdoc}
*
* @var string
*/
protected static $shortName = 'sortRecursive';
/**
* {@inheritdoc}
*
* @var int
*/
protected static $priority = 100;
/**
* {@inheritdoc}
*
* We can only handle TYPO3CR Nodes.
*
* @param mixed $context
*
* @return bool
*/
public function canEvaluate($context)
{
return (isset($context[0]) && ($context[0] instanceof NodeInterface));
}
/**
* {@inheritdoc}
*
* @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();
$sortOrder = 'ASC';
if (isset($arguments[0]) && !empty($arguments[0]) && in_array($arguments[0], array('ASC', 'DESC'))) {
$sortOrder = $arguments[0];
}
$getIndexPath = function (NodeInterface $node) {
$indexPath = array($node->getIndex());
while ($node = $node->getParent()) {
$indexPath[] = $node->getIndex();
}
return $indexPath;
};
$cmpIndex = function (NodeInterface $a, NodeInterface $b) use ($getIndexPath) {
if ($a == $b) {
return 0;
}
// Compare index path backwards until a difference is found
$aIndexPath = $getIndexPath($a);
$bIndexPath = $getIndexPath($b);
while (count($aIndexPath) > 0 && count($bIndexPath) > 0) {
$diff = (array_pop($aIndexPath) - array_pop($bIndexPath));
if ($diff !== 0) {
return $diff < 0 ? -1 : 1;
}
}
return 0;
};
usort($nodes, $cmpIndex);
if ($sortOrder === 'DESC') {
$nodes = array_reverse($nodes);
}
$flowQuery->setContext($nodes);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment