Skip to content

Instantly share code, notes, and snippets.

@Sumurai8
Created February 3, 2018 12:29
Show Gist options
  • Save Sumurai8/a0491a3a585dd8908196c2d4868d61d6 to your computer and use it in GitHub Desktop.
Save Sumurai8/a0491a3a585dd8908196c2d4868d61d6 to your computer and use it in GitHub Desktop.
Add "descendants" property to collection of nodes in nested set format with a generator
<?php
/**
* Simply returns the titles of the nodes passed to it
*
* @param array $nodes Collection of nodes we want to have the titles of
*/
function titles(array $nodes) {
return array_map(
function ($node) {
return $node['title'];
},
$nodes
);
}
/**
* Generator that adds the descendants property to each node in a collection
*
* @param array $nodes pre-order walk of nodes in nested set format
*/
function with_descendants(array $nodes) {
// This method of determining descendants only works if we have a continuous
// list of bounds. The first node should be the root node of this subtree,
// so if it fits "snugly" around the other nodes and we assume the nodes are
// in pre-order, all should be fine
assert(
(($nodes[0]['right'] - $nodes[0]['left'] - 1) / 2) === count($nodes) - 1,
"Cannot determine descendants when tree is not normalised"
);
// Just so we only have to process each node once to get their title
// we cache the titles first
$titles = titles($nodes);
// Then we run through ordered nodes
for ($i = 0; $i < count($nodes); $i++) {
// We sometimes need to access the node
$node = $nodes[$i];
// We want to access the subtree of this node, so we calculate which
// node would be the first node in the subtree, and how many nodes
// would be in that subtree
$first_node = $i + 1;
$number_of_nodes = ($node['right'] - $node['left'] - 1) / 2;
// Now we take the relevant slice out of titles
$node['descendants'] = array_slice($titles, $first_node, $number_of_nodes);
// We have added our property, so we can yield the node
yield $node;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment