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