Completed
Push — master ( 6e010a...c5b995 )
by Thomas
04:09
created

HtmlQuery::convertNodes()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 7
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 11
ccs 8
cts 8
cp 1
crap 5
rs 9.6111
1
<?php
2
3
namespace Sulao\HtmlQuery;
4
5
use DOMDocument, DOMNode, DOMNodeList;
6
use Traversable;
7
8
/**
9
 * Class HtmlQuery
10
 *
11
 * @package Sulao\HtmlQuery
12
 */
13
class HtmlQuery extends HtmlQueryNode
14
{
15
    const VERSION = '1.0.1';
16
17
    /**
18
     * @var DOMDocument
19
     */
20
    protected $doc;
21
22
    /**
23
     * @var DOMNode[]
24
     */
25
    protected $nodes;
26
27
    /**
28
     * HtmlQuery constructor.
29
     *
30
     * @param DOMDocument                   $doc
31
     * @param DOMNode|DOMNode[]|DOMNodeList $nodes
32
     *
33
     * @throws Exception
34
     */
35 82
    public function __construct(DOMDocument $doc, $nodes)
36
    {
37 82
        $this->doc = $doc;
38 82
        $this->nodes = $this->validateNodes($nodes);
39 82
    }
40
41
    /**
42
     * Get the outer HTML contents of the first matched node.
43
     *
44
     * @return string|null
45
     */
46 29
    public function outerHtml()
47
    {
48
        return $this->mapFirst(function (HtmlNode $node) {
49 29
            return $node->outerHtml();
50 29
        });
51
    }
52
53
    /**
54
     * Get the inner HTML contents of the first matched node or
55
     * set the inner HTML contents of every matched node.
56
     *
57
     * @param string|null $html
58
     *
59
     * @return string|null|static
60
     */
61 26
    public function html(?string $html = null)
62
    {
63 26
        if (!is_null($html)) {
64 2
            return $this->setHtml($html);
65
        }
66
67 26
        return $this->getHtml();
68
    }
69
70
    /**
71
     * Get the inner HTML contents of the first matched node.
72
     *
73
     * @return string|null
74
     */
75 26
    public function getHtml()
76
    {
77
        return $this->mapFirst(function (HtmlNode $node) {
78 26
            return $node->getHtml();
79 26
        });
80
    }
81
82
    /**
83
     * Set the inner HTML contents of every matched node.
84
     *
85
     * @param string $html
86
     *
87
     * @return static
88
     */
89 2
    public function setHtml(string $html)
90
    {
91 2
        $this->empty();
92
93 2
        if ($html !== '') {
94 2
            $this->append($html);
95
        }
96
97 2
        return $this;
98
    }
99
100
    /**
101
     * Get the combined text contents of the first matched node, including
102
     * it's descendants, or set the text contents of every matched node.
103
     *
104
     * @param string|null $text
105
     *
106
     * @return string|null|static
107
     */
108 5
    public function text(?string $text = null)
109
    {
110 5
        if (!is_null($text)) {
111 2
            return $this->setText($text);
112
        }
113
114 4
        return $this->getText();
115
    }
116
117
    /**
118
     * Get the combined text contents of the first matched node,
119
     * including it's descendants.
120
     *
121
     * @return string|null
122
     */
123 4
    public function getText()
124
    {
125
        return $this->mapFirst(function (HtmlNode $node) {
126 4
            return $node->getText();
127 4
        });
128
    }
129
130
    /**
131
     * set the text contents of every matched node.
132
     *
133
     * @param string $text
134
     *
135
     * @return static
136
     */
137 2
    public function setText(string $text)
138
    {
139
        return $this->each(function (HtmlNode $node) use ($text) {
140 2
            $node->setText($text);
141 2
        });
142
    }
143
144
    /**
145
     * Remove all child nodes of all matched nodes from the DOM.
146
     *
147
     * @return static
148
     */
149 3
    public function empty()
150
    {
151
        return $this->each(function (HtmlNode $node) {
152 3
            $node->empty();
153 3
        });
154
    }
155
156
    /**
157
     * Remove the matched nodes from the DOM.
158
     * optionally filtered by a selector.
159
     *
160
     * @param string|null $selector
161
     *
162
     * @return static
163
     */
164 2
    public function remove(?string $selector = null)
165
    {
166 2
        if (!is_null($selector)) {
167 1
            $this->filter($selector)->remove();
168
        } else {
169
            $this->each(function (HtmlNode $node) {
170 2
                $node->remove();
171 2
            });
172
        }
173
174 2
        return $this;
175
    }
176
177
    /**
178
     * Get the current value of the first matched node
179
     * or set the value of every matched node.
180
     *
181
     * @param string|null $value
182
     *
183
     * @return string|null|static
184
     */
185 1
    public function val(?string $value = null)
186
    {
187 1
        if (is_null($value)) {
188 1
            return $this->getVal();
189
        }
190
191 1
        return $this->setVal($value);
192
    }
193
194
    /**
195
     * Get the current value of the first matched node
196
     *
197
     * @return string|null
198
     */
199 1
    public function getVal()
200
    {
201
        return $this->mapFirst(function (HtmlElement $node) {
202 1
            return $node->getVal();
203 1
        });
204
    }
205
206
    /**
207
     * Set the value of every matched node.
208
     *
209
     * @param string $value
210
     *
211
     * @return static
212
     */
213 1
    public function setVal(string $value)
214
    {
215
        return $this->each(function (HtmlElement $node) use ($value) {
216 1
            $node->setVal($value);
217 1
        });
218
    }
219
220
    /**
221
     * Adds the specified class(es) to each node in the matched nodes.
222
     *
223
     * @param string $className
224
     *
225
     * @return static
226
     */
227 4
    public function addClass(string $className)
228
    {
229
        return $this->each(function (HtmlElement $node) use ($className) {
230 4
            $node->addClass($className);
231 4
        });
232
    }
233
234
    /**
235
     * Determine whether any of the matched nodes are assigned the given class.
236
     *
237
     * @param string $className
238
     *
239
     * @return bool
240
     */
241 2
    public function hasClass(string $className)
242
    {
243 2
        return $this->mapAnyTrue(
244
            function (HtmlElement $node) use ($className) {
245 2
                return $node->hasClass($className);
246 2
            }
247
        );
248
    }
249
250
    /**
251
     * Remove a single class, multiple classes, or all classes
252
     * from each matched node.
253
     *
254
     * @param string|null $className
255
     *
256
     * @return static
257
     */
258 2
    public function removeClass(?string $className = null)
259
    {
260
        return $this->each(function (HtmlElement $node) use ($className) {
261 2
            $node->removeClass($className);
262 2
        });
263
    }
264
265
    /**
266
     * Add or remove class(es) from each matched node, depending on
267
     * either the class's presence or the value of the state argument.
268
     *
269
     * @param string $className
270
     * @param bool|null   $state
271
     *
272
     * @return static
273
     */
274 1
    public function toggleClass(string $className, ?bool $state = null)
275
    {
276
        return $this->each(function (HtmlElement $node) use ($className, $state) {
277 1
            $node->toggleClass($className, $state);
278 1
        });
279
    }
280
281
    /**
282
     * Get the value of a computed style property for the first matched node
283
     * or set one or more CSS properties for every matched node.
284
     *
285
     * @param string|array $name
286
     * @param string|null  $value
287
     *
288
     * @return static|string|null
289
     */
290 1
    public function css($name, $value = null)
291
    {
292 1
        if (is_null($value) && !is_array($name)) {
293 1
            return $this->getCss($name);
294
        }
295
296 1
        if (is_array($name)) {
297 1
            foreach ($name as $key => $val) {
298 1
                $this->setCss($key, $val);
299
            }
300
        } else {
301 1
            $this->setCss($name, $value);
302
        }
303
304 1
        return $this;
305
    }
306
307
    /**
308
     * Get the value of a computed style property for the first matched node
309
     *
310
     * @param string $name
311
     *
312
     * @return string|null
313
     */
314 1
    public function getCss(string $name)
315
    {
316
        return $this->mapFirst(function (HtmlElement $node) use ($name) {
317 1
            return $node->getCss($name);
318 1
        });
319
    }
320
321
    /**
322
     * Set or Remove one CSS property for every matched node.
323
     *
324
     * @param string      $name
325
     * @param string|null $value
326
     *
327
     * @return static
328
     */
329 1
    public function setCss(string $name, ?string $value)
330
    {
331
        return $this->each(function (HtmlElement $node) use ($name, $value) {
332 1
            $node->setCss($name, $value);
333 1
        });
334
    }
335
336
    /**
337
     * Remove one CSS property for every matched node.
338
     *
339
     * @param string $name
340
     *
341
     * @return static
342
     */
343 1
    public function removeCss(string $name)
344
    {
345
        return $this->each(function (HtmlElement $node) use ($name) {
346 1
            $node->removeCss($name);
347 1
        });
348
    }
349
350
    /**
351
     * Validate the nodes
352
     *
353
     * @param DOMNode|DOMNode[]|DOMNodeList|static $nodes
354
     *
355
     * @return DOMNode[]
356
     */
357 82
    protected function validateNodes($nodes)
358
    {
359 82
        $nodes = $this->convertNodes($nodes);
360
361
        array_map(function ($node) {
362 80
            if (!($node instanceof DOMNode)) {
363 2
                throw new Exception(
364
                    'Expect an instance of DOMNode, '
365 2
                        . gettype($node) . ' given.'
366
                );
367
            }
368
369 80
            $document = $node->ownerDocument ?: $node;
370
371 80
            if ($document !== $this->doc) {
372 1
                throw new Exception(
373 1
                    'The DOMNode does not belong to the DOMDocument.'
374
                );
375
            }
376 82
        }, $nodes);
377
378 82
        return $nodes;
379
    }
380
381
    /**
382
     * Convert nodes to array
383
     *
384
     * @param DOMNode|DOMNode[]|DOMNodeList|static $nodes
385
     *
386
     * @return array
387
     */
388 82
    protected function convertNodes($nodes): array
389
    {
390 82
        if (empty($nodes)) {
391 21
            $nodes = [];
392 80
        } elseif ($nodes instanceof Traversable) {
393 1
            $nodes = iterator_to_array($nodes);
394 80
        } elseif ($nodes instanceof DOMNode || !is_array($nodes)) {
395 57
            $nodes = [$nodes];
396
        }
397
398 82
        return Helper::strictArrayUnique($nodes);
399
    }
400
}
401