Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace Termwind\ValueObjects;
6
 
7
use Generator;
8
 
9
/**
10
 * @internal
11
 */
12
final class Node
13
{
14
    /**
15
     * A value object with helper methods for working with DOM node.
16
     */
17
    public function __construct(private \DOMNode $node)
18
    {
19
    }
20
 
21
    /**
22
     * Gets the value of the node.
23
     */
24
    public function getValue(): string
25
    {
26
        return $this->node->nodeValue ?? '';
27
    }
28
 
29
    /**
30
     * Gets child nodes of the node.
31
     *
32
     * @return Generator<Node>
33
     */
34
    public function getChildNodes(): Generator
35
    {
36
        foreach ($this->node->childNodes as $node) {
37
            yield new static($node);
38
        }
39
    }
40
 
41
    /**
42
     * Checks if the node is a text.
43
     */
44
    public function isText(): bool
45
    {
46
        return $this->node instanceof \DOMText;
47
    }
48
 
49
    /**
50
     * Checks if the node is a comment.
51
     */
52
    public function isComment(): bool
53
    {
54
        return $this->node instanceof \DOMComment;
55
    }
56
 
57
    /**
58
     * Compares the current node name with a given name.
59
     */
60
    public function isName(string $name): bool
61
    {
62
        return $this->getName() === $name;
63
    }
64
 
65
    /**
66
     * Returns the current node type name.
67
     */
68
    public function getName(): string
69
    {
70
        return $this->node->nodeName;
71
    }
72
 
73
    /**
74
     * Returns value of [class] attribute.
75
     */
76
    public function getClassAttribute(): string
77
    {
78
        return $this->getAttribute('class');
79
    }
80
 
81
    /**
82
     * Returns value of attribute with a given name.
83
     */
84
    public function getAttribute(string $name): string
85
    {
86
        if ($this->node instanceof \DOMElement) {
87
            return $this->node->getAttribute($name);
88
        }
89
 
90
        return '';
91
    }
92
 
93
    /**
94
     * Checks if the node is empty.
95
     */
96
    public function isEmpty(): bool
97
    {
98
        return $this->isText() && preg_replace('/\s+/', '', $this->getValue()) === '';
99
    }
100
 
101
    /**
102
     * Gets the previous sibling from the node.
103
     */
104
    public function getPreviousSibling(): static|null
105
    {
106
        $node = $this->node;
107
 
108
        while ($node = $node->previousSibling) {
109
            $node = new static($node);
110
 
111
            if ($node->isEmpty()) {
112
                $node = $node->node;
113
 
114
                continue;
115
            }
116
 
117
            if (! $node->isComment()) {
118
                return $node;
119
            }
120
 
121
            $node = $node->node;
122
        }
123
 
124
        return is_null($node) ? null : new static($node);
125
    }
126
 
127
    /**
128
     * Gets the next sibling from the node.
129
     */
130
    public function getNextSibling(): static|null
131
    {
132
        $node = $this->node;
133
 
134
        while ($node = $node->nextSibling) {
135
            $node = new static($node);
136
 
137
            if ($node->isEmpty()) {
138
                $node = $node->node;
139
 
140
                continue;
141
            }
142
 
143
            if (! $node->isComment()) {
144
                return $node;
145
            }
146
 
147
            $node = $node->node;
148
        }
149
 
150
        return is_null($node) ? null : new static($node);
151
    }
152
 
153
    /**
154
     * Checks if the node is the first child.
155
     */
156
    public function isFirstChild(): bool
157
    {
158
        return is_null($this->getPreviousSibling());
159
    }
160
 
161
    /**
162
     * Gets the inner HTML representation of the node including child nodes.
163
     */
164
    public function getHtml(): string
165
    {
166
        $html = '';
167
        foreach ($this->node->childNodes as $child) {
168
            if ($child->ownerDocument instanceof \DOMDocument) {
169
                $html .= $child->ownerDocument->saveXML($child);
170
            }
171
        }
172
 
173
        return html_entity_decode($html);
174
    }
175
 
176
    /**
177
     * Converts the node to a string.
178
     */
179
    public function __toString(): string
180
    {
181
        if ($this->isComment()) {
182
            return '';
183
        }
184
 
185
        if ($this->getValue() === ' ') {
186
            return ' ';
187
        }
188
 
189
        if ($this->isEmpty()) {
190
            return '';
191
        }
192
 
193
        $text = preg_replace('/\s+/', ' ', $this->getValue()) ?? '';
194
 
195
        if (is_null($this->getPreviousSibling())) {
196
            $text = ltrim($text);
197
        }
198
 
199
        if (is_null($this->getNextSibling())) {
200
            $text = rtrim($text);
201
        }
202
 
203
        return $text;
204
    }
205
}