src/Charcoal/Object/HierarchicalCollection.php
private function sortDescendantObjects(
        HierarchicalInterface $parentObj,
        array &$childObjects,
        &$count,
        $level,
        array &$sortedObjects
    ) {
        $pageNum = $this->page();
        $perPage = $this->numPerPage();

        if ($perPage < 1) {
            foreach ($childObjects[$parentObj->id()] as $object) {
                if ($count === 0 && $object->hasMaster()) {
                    $myParents = [];
                    $myParent  = $object->master();
                    while ($myParent) {
                        $myParents[] = $myParent;

                        if (!$myParent->hasMaster()) {
                            break;
                        }

                        $myParent = $myParent->master();
                    }

                    $numParents = count($myParents);
                    while ($myParent = array_pop($myParents)) {
                        $myParent->level = ($level - $numParents);
                        $sortedObjects[$myParent->id()] = $myParent;
                        $numParents--;
                    }
                }

                $object->level = $level;
                $sortedObjects[$object->id()] = $object;

                $count++;

                if (isset($childObjects[$object->id()])) {
                    $this->sortDescendantObjects(
                        $object,
                        $childObjects,
                        $count,
                        ($level + 1),
                        $sortedObjects
                    );
                }
            }
        } else {
            $start = (( $pageNum - 1 ) * $perPage);
            $end   = ($start + $perPage);

            foreach ($childObjects[$parentObj->id()] as $object) {
                if ($count >= $end) {
                    break;
                }

                // If the page starts in a subtree, print the parents.
                if ($count === $start && $object->hasMaster()) {
                    $myParents = [];
                    $myParent  = $object->master();
                    while ($myParent) {
                        $myParents[] = $myParent;

                        if (!$myParent->hasMaster()) {
                            break;
                        }

                        $myParent = $myParent->master();
                    }

                    $numParents = count($myParents);
                    while ($myParent = array_pop($myParents)) {
                        $myParent->level = ($level - $numParents);
                        $sortedObjects[$myParent->id()] = $myParent;
                        $numParents--;
                    }
                }

                if ($count >= $start) {
                    $object->level = $level;
                    $sortedObjects[$object->id()] = $object;
                }

                $count++;

                if (isset($childObjects[$object->id()])) {
                    $this->sortDescendantObjects(
                        $object,
                        $childObjects,
                        $count,
                        ($level + 1),
                        $sortedObjects
                    );
                }
            }
        }

        // Required in order to keep track of orphans
        unset($childObjects[$parentObj->id()]);
    }
private function sortDescendantObjects(
        HierarchicalInterface $parentObj,
        array &$childObjects,
        &$count,
        $level,
        array &$sortedObjects
    ) {
        $pageNum = $this->page();
        $perPage = $this->numPerPage();

        if ($perPage < 1) {
            foreach ($childObjects[$parentObj->id()] as $object) {
                if ($count === 0 && $object->hasMaster()) {
                    $myParents = [];
                    $myParent  = $object->master();
                    while ($myParent) {
                        $myParents[] = $myParent;

                        if (!$myParent->hasMaster()) {
                            break;
                        }

                        $myParent = $myParent->master();
                    }

                    $numParents = count($myParents);
                    while ($myParent = array_pop($myParents)) {
                        $myParent->level = ($level - $numParents);
                        $sortedObjects[$myParent->id()] = $myParent;
                        $numParents--;
                    }
                }

                $object->level = $level;
                $sortedObjects[$object->id()] = $object;

                $count++;

                if (isset($childObjects[$object->id()])) {
                    $this->sortDescendantObjects(
                        $object,
                        $childObjects,
                        $count,
                        ($level + 1),
                        $sortedObjects
                    );
                }
            }
        } else {
            $start = (( $pageNum - 1 ) * $perPage);
            $end   = ($start + $perPage);

            foreach ($childObjects[$parentObj->id()] as $object) {
                if ($count >= $end) {
                    break;
                }

                // If the page starts in a subtree, print the parents.
                if ($count === $start && $object->hasMaster()) {
                    $myParents = [];
                    $myParent  = $object->master();
                    while ($myParent) {
                        $myParents[] = $myParent;

                        if (!$myParent->hasMaster()) {
                            break;
                        }

                        $myParent = $myParent->master();
                    }

                    $numParents = count($myParents);
                    while ($myParent = array_pop($myParents)) {
                        $myParent->level = ($level - $numParents);
                        $sortedObjects[$myParent->id()] = $myParent;
                        $numParents--;
                    }
                }

                if ($count >= $start) {
                    $object->level = $level;
                    $sortedObjects[$object->id()] = $object;
                }

                $count++;

                if (isset($childObjects[$object->id()])) {
                    $this->sortDescendantObjects(
                        $object,
                        $childObjects,
                        $count,
                        ($level + 1),
                        $sortedObjects
                    );
                }
            }
        }

        // Required in order to keep track of orphans
        unset($childObjects[$parentObj->id()]);
    }
Given an object, display the nested hierarchy of descendants.

@param  HierarchicalInterface   $parentObj     The parent object from which to append its
descendants for display.
@param  HierarchicalInterface[] $childObjects  The list of descendants by parent object ID.
Passed by reference.
@param  integer                 $count         The current count of objects to display,
for pagination. Passed by reference.
@param  integer                 $level         The level directly below the $parentObj.
@param  HierarchicalInterface[] $sortedObjects The list of objects to be displayed.
Passed by reference.
@return void