1<?php 2 3/* 4 * This file is part of the league/commonmark package. 5 * 6 * (c) Colin O'Dell <colinodell@gmail.com> 7 * 8 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js) 9 * - (c) John MacFarlane 10 * 11 * For the full copyright and license information, please view the LICENSE 12 * file that was distributed with this source code. 13 */ 14 15namespace League\CommonMark\Node; 16 17final class NodeWalker 18{ 19 /** 20 * @var Node 21 */ 22 private $root; 23 24 /** 25 * @var Node|null 26 */ 27 private $current; 28 29 /** 30 * @var bool 31 */ 32 private $entering; 33 34 public function __construct(Node $root) 35 { 36 $this->root = $root; 37 $this->current = $this->root; 38 $this->entering = true; 39 } 40 41 /** 42 * Returns an event which contains node and entering flag 43 * (entering is true when we enter a Node from a parent or sibling, 44 * and false when we reenter it from child) 45 * 46 * @return NodeWalkerEvent|null 47 */ 48 public function next(): ?NodeWalkerEvent 49 { 50 $current = $this->current; 51 $entering = $this->entering; 52 if (null === $current) { 53 return null; 54 } 55 56 if ($entering && $current->isContainer()) { 57 if ($current->firstChild()) { 58 $this->current = $current->firstChild(); 59 $this->entering = true; 60 } else { 61 $this->entering = false; 62 } 63 } elseif ($current === $this->root) { 64 $this->current = null; 65 } elseif (null === $current->next()) { 66 $this->current = $current->parent(); 67 $this->entering = false; 68 } else { 69 $this->current = $current->next(); 70 $this->entering = true; 71 } 72 73 return new NodeWalkerEvent($current, $entering); 74 } 75 76 /** 77 * Resets the iterator to resume at the specified node 78 * 79 * @param Node $node 80 * @param bool $entering 81 * 82 * @return void 83 */ 84 public function resumeAt(Node $node, bool $entering = true) 85 { 86 $this->current = $node; 87 $this->entering = $entering; 88 } 89} 90