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

HtmlQueryNode::newNode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Sulao\HtmlQuery;
4
5
use DOMNode, DOMNodeList;
6
7
/**
8
 * Class HtmlQueryNode
9
 *
10
 * @package Sulao\HtmlQuery
11
 */
12
abstract class HtmlQueryNode extends HtmlQueryAttribute
13
{
14
    /**
15
     * Insert content or node(s) before each matched node.
16
     *
17
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
18
     *
19
     * @return static
20
     */
21 3
    public function before($content)
22
    {
23 3
        $content = $this->contentResolve($content);
24
25
        return $this->each(function (HtmlNode $node, $index) use ($content) {
26
            $content->each(function (DOMNode $newNode) use ($node, $index) {
27 3
                $newNode = $this->newNode($newNode, $index);
28 3
                $node->before($newNode);
29 3
            });
30 3
        });
31
    }
32
33
    /**
34
     * Insert every matched node before the target.
35
     *
36
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $selector
37
     *
38
     * @return static
39
     */
40 1
    public function insertBefore($selector)
41
    {
42 1
        $target = $this->targetResolve($selector);
43
44 1
        return $target->before($this);
45
    }
46
47
    /**
48
     * Insert content or node(s) after each matched node.
49
     *
50
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
51
     *
52
     * @return static
53
     */
54 5
    public function after($content)
55
    {
56 5
        $content = $this->contentResolve($content);
57
58
        return $this->each(function (HtmlNode $node, $index) use ($content) {
59
            $content->each(function (DOMNode $newNode) use ($node, $index) {
60 5
                $newNode = $this->newNode($newNode, $index);
61 5
                $node->after($newNode);
62 5
            }, true);
63 5
        });
64
    }
65
66
    /**
67
     * Insert every matched node after the target.
68
     *
69
     * @param string|DOMNode|DOMNode[]DOMNodeList|static $selector
70
     *
71
     * @return static
72
     */
73 3
    public function insertAfter($selector)
74
    {
75 3
        $target = $this->targetResolve($selector);
76
77 3
        return $target->after($this);
78
    }
79
80
    /**
81
     * Insert content or node(s) to the end of every matched node.
82
     *
83
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
84
     *
85
     * @return static
86
     */
87 6
    public function append($content)
88
    {
89 6
        $content = $this->contentResolve($content);
90
91
        return $this->each(function (HtmlNode $node, $index) use ($content) {
92
            $content->each(function (DOMNode $newNode) use ($node, $index) {
93 6
                $newNode = $this->newNode($newNode, $index);
94 6
                $node->append($newNode);
95 6
            });
96 6
        });
97
    }
98
99
    /**
100
     * Insert every matched node to the end of the target.
101
     *
102
     * @param string|DOMNode|DOMNode[]DOMNodeList|static $selector
103
     *
104
     * @return static
105
     */
106 2
    public function appendTo($selector)
107
    {
108 2
        $target = $this->targetResolve($selector);
109
110 2
        return $target->append($this);
111
    }
112
113
    /**
114
     * Insert content or node(s) to the beginning of each matched node.
115
     *
116
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
117
     *
118
     * @return static
119
     */
120 3
    public function prepend($content)
121
    {
122 3
        $content = $this->contentResolve($content);
123
124
        return $this->each(function (HtmlNode $node, $index) use ($content) {
125
            $content->each(function (DOMNode $newNode) use ($node, $index) {
126 3
                $newNode = $this->newNode($newNode, $index);
127 3
                $node->prepend($newNode);
128 3
            }, true);
129 3
        });
130
    }
131
132
    /**
133
     * Insert every matched node to the beginning of the target.
134
     *
135
     * @param string|DOMNode|DOMNode[]DOMNodeList|static $selector
136
     *
137
     * @return static
138
     */
139 2
    public function prependTo($selector)
140
    {
141 2
        $target = $this->targetResolve($selector);
142
143 2
        return $target->prepend($this);
144
    }
145
146
    /**
147
     * Replace each matched node with the provided new content or node(s)
148
     *
149
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
150
     *
151
     * @return static
152
     */
153 2
    public function replaceWith($content)
154
    {
155 2
        $content = $this->contentResolve($content);
156
        return $this->each(function (DOMNode $node, $index) use ($content) {
157 2
            if (!$node->parentNode) {
158 1
                return;
159
            }
160
161 2
            $len = $content->count();
162 2
            $content->each(
163
                function (DOMNode $newNode) use ($node, $index, $len) {
164 2
                    $newNode = $this->newNode($newNode, $index);
165
166 2
                    if ($len === 1) {
167 2
                        $node->parentNode->replaceChild($newNode, $node);
168
                    } else {
169 2
                        $this->resolve($newNode)->insertAfter($node);
170
                    }
171 2
                },
172 2
                true
173
            );
174
175 2
            if ($len !== 1) {
176 2
                $node->parentNode->removeChild($node);
177
            }
178 2
        });
179
    }
180
181
    /**
182
     * Replace each target node with the matched node(s)
183
     *
184
     * @param string|DOMNode|DOMNode[]DOMNodeList|static $selector
185
     *
186
     * @return static
187
     */
188 1
    public function replaceAll($selector)
189
    {
190 1
        $target = $this->targetResolve($selector);
191
192 1
        return $target->replaceWith($this);
193
    }
194
195
    /**
196
     * Wrap an HTML structure around each matched node.
197
     *
198
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
199
     *
200
     * @return static
201
     */
202 3
    public function wrap($content)
203
    {
204 3
        $content = $this->contentResolve($content);
205 3
        $newNode = $content[0];
206
207 3
        if (empty($newNode)) {
208 1
            return $this;
209
        }
210
211
        return $this->each(function (DOMNode $node, $index) use ($newNode) {
212 3
            $newNode = $this->newNode($newNode, $index);
213
214 3
            $nodes = $this->xpathQuery('descendant::*[last()]', $newNode);
215 3
            if (!$nodes) {
216 1
                throw new Exception('Invalid wrap html format.');
217
            }
218
219 3
            $deepestNode = end($nodes);
220 3
            $node->parentNode->replaceChild($newNode, $node);
221 3
            $deepestNode->appendChild($node);
222 3
        });
223
    }
224
225
    /**
226
     * Wrap an HTML structure around the content of each matched node.
227
     *
228
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
229
     *
230
     * @return static
231
     */
232 1
    public function wrapInner($content)
233
    {
234 1
        $content = $this->contentResolve($content);
235 1
        $newNode = $content[0];
236
237 1
        if (empty($newNode)) {
238 1
            return $this;
239
        }
240
241
        return $this->each(function (DOMNode $node, $index) use ($newNode) {
242 1
            $newNode = $this->newNode($newNode, $index);
243
244 1
            $nodes = $this->xpathQuery('descendant::*[last()]', $newNode);
245 1
            if (!$nodes) {
246 1
                throw new Exception('Invalid wrap html format.');
247
            }
248
249 1
            $deepestNode = end($nodes);
250
251 1
            foreach (iterator_to_array($node->childNodes) as $childNode) {
252 1
                $deepestNode->appendChild($childNode);
253
            }
254
255 1
            $node->appendChild($newNode);
256 1
        });
257
    }
258
259
    /**
260
     * Wrap an HTML structure around all matched nodes.
261
     *
262
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
263
     *
264
     * @return static
265
     */
266 1
    public function wrapAll($content)
267
    {
268 1
        $content = $this->contentResolve($content);
269 1
        if (!$content->count()) {
270 1
            return $this;
271
        }
272
273 1
        $newNode = $content[0];
274
        $this->each(function (DOMNode $node, $index) use ($newNode) {
275 1
            if ($index === 0) {
276 1
                $this->resolve($node)->wrap($newNode);
277
            } else {
278 1
                $this->nodes[0]->parentNode->appendChild($node);
279
            }
280 1
        });
281
282 1
        return $this;
283
    }
284
285
    /**
286
     * Remove the parents of the matched nodes from the DOM.
287
     * A optional selector to check the parent node against.
288
     *
289
     * @param string|null $selector
290
     *
291
     * @return static
292
     */
293 2
    public function unwrap(?string $selector = null)
294
    {
295 2
        return $this->parent($selector)->unwrapSelf();
296
    }
297
298
    /**
299
     * Remove the HTML tag of the matched nodes from the DOM.
300
     * Leaving the child nodes in their place.
301
     *
302
     * @return static
303
     */
304 3
    public function unwrapSelf()
305
    {
306
        return $this->each(function (HtmlNode $node) {
307 3
            $node->unwrapSelf();
308 3
        });
309
    }
310
311
    /**
312
     * When the selection needs a new node, return the original one or a clone.
313
     *
314
     * @param DOMNode $newNode
315
     * @param int     $index
316
     *
317
     * @return DOMNode
318
     */
319 17
    protected function newNode(DOMNode $newNode, int $index)
320
    {
321 17
        return $index !== $this->count() - 1
322 13
            ? $newNode->cloneNode(true)
323 17
            : $newNode;
324
    }
325
}
326