1<?php
2
3namespace dokuwiki\plugin\prosemirror\schema;
4
5class NodeStack
6{
7
8    /** @var Node[] */
9    protected $stack = [];
10
11    /** @var int index to the top of the stack */
12    protected $stacklength = -1;
13
14    /** @var Node the root node */
15    protected $doc;
16
17    /**
18     * NodeStack constructor.
19     */
20    public function __construct()
21    {
22        $node = new Node('doc');
23        $this->doc = $node;
24        $this->top($node);
25    }
26
27    /**
28     * @return Node
29     */
30    public function getDocNode()
31    {
32        return $this->stack[0];
33    }
34
35    /**
36     * Get the current node (the one at the top of the stack)
37     *
38     * @return Node
39     */
40    public function current()
41    {
42        return $this->stack[$this->stacklength];
43    }
44
45    /**
46     * Get the document (top most level) node
47     *
48     * @return Node
49     */
50    public function doc()
51    {
52        return $this->doc;
53    }
54
55    /**
56     * Make the given node the current one
57     *
58     * @param Node $node
59     */
60    protected function top(Node $node)
61    {
62        $this->stack[] = $node;
63        $this->stacklength++;
64    }
65
66    /**
67     * Add a new child node to the current node and make it the new current node
68     *
69     * @param Node $node
70     */
71    public function addTop(Node $node)
72    {
73        $this->add($node);
74        $this->top($node);
75    }
76
77    /**
78     * Pop the current node off the stack
79     *
80     * @param string $type The type of node that is expected. A RuntimeException is thrown if the current nod does not
81     *                     match
82     *
83     * @return Node
84     */
85    public function drop($type)
86    {
87        /** @var Node $node */
88        $node = array_pop($this->stack);
89        $this->stacklength--;
90        if ($node->getType() != $type) {
91            throw new \RuntimeException("Expected the current node to be of type $type found " . $node->getType() . " instead.");
92        }
93        return $node;
94    }
95
96    /**
97     * Add a new child node to the current node
98     *
99     * @param Node $node
100     */
101    public function add(Node $node)
102    {
103        $this->current()->addChild($node);
104    }
105
106    /**
107     * Check if there have been any nodes added to the document
108     */
109    public function isEmpty()
110    {
111        return !$this->doc->hasContent();
112    }
113}
114