Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
SearchDepthFirstPreorder
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
1 / 1
 getMovementDirection
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2
3/**
4 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
5 */
6declare(strict_types=1);
7
8namespace pvc\struct\treesearch;
9
10use pvc\interfaces\struct\treesearch\VisitStatus;
11
12/**
13 * Class SearchStrategyDepthFirstPreorder
14 */
15class SearchDepthFirstPreorder extends SearchDepthFirst
16{
17    /**
18     * getMovementDirection
19     * @return Direction
20     *
21     * returns MOVE_DOWN if we should keep iterating by recursing down through child nodes,
22     * returns STOP if we should stop moving through nodes
23     * returns MOVE_UP if we should continue moving by returning up to the parent
24     *
25     * the goal is to stop every time we hit a node we have never visited.
26     *
27     * This method also changes the visit status of the current node.
28     *
29     * if node never visited, we go to partially visited and stop.
30     *
31     * if node partially visited and if all the children are fully visited, we go to fully visited and move up.
32     * if a node is partially visited and not all the children are fully visited then we move down
33     */
34    protected function getMovementDirection(): Direction
35    {
36        assert(!is_null($this->current()));
37
38        switch ($this->current()->getVisitStatus()) {
39
40            /**
41             * in preorder mode, stop when we first encounter a node.  There's an initialization condition to
42             * account for:  rewind is called in the first iteration and next for all subsequent iterations.
43             * Because current has been called before next the first time around, the start node has already been
44             * returned, so we do not want to return it again.
45             */
46            case VisitStatus::NEVER_VISITED:
47                $this->current()->setVisitStatus(VisitStatus::PARTIALLY_VISITED);
48                $direction = ($this->current() == $this->getStartNode()) ? Direction::MOVE_DOWN : Direction::DONT_MOVE;
49                break;
50
51            /**
52             * if all the children are fully visited, or we are at the max search level, then we move to full visited
53             * otherwise we move down.  The default case should never be true, which is to say that we should never
54             * be moving into a node that is fully visited.  The default case is only there to satisfy the type checker
55             * that the $direction variable will have a value in all cases.
56             */
57            case VisitStatus::PARTIALLY_VISITED:
58            default:
59                if ($this->allChildrenFullyVisited() || $this->atMaxLevels()) {
60                    $this->current()->setVisitStatus(VisitStatus::FULLY_VISITED);
61                    $direction = Direction::MOVE_UP;
62                } else {
63                    $direction = Direction::MOVE_DOWN;
64                }
65                break;
66        }
67        return $direction;
68    }
69}