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

Resolver::resolve()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
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 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Sulao\HtmlQuery;
4
5
use DOMDocument, DOMNode, DOMNodeList;
6
7
/**
8
 * Trait Selector
9
 *
10
 * @package Sulao\HtmlQuery
11
 */
12
trait Resolver
13
{
14
    /**
15
     * @var DOMDocument
16
     */
17
    protected $doc;
18
19
    /**
20
     * @var DOMNode[]
21
     */
22
    protected $nodes;
23
24
    /**
25
     * Selector constructor.
26
     *
27
     * @param DOMDocument                          $doc
28
     * @param DOMNode|DOMNode[]|DOMNodeList|static $nodes
29
     *
30
     * @return static
31
     */
32
    abstract public function __construct(DOMDocument $doc, $nodes);
33
34
    /**
35
     * Get the descendants of each matched node, filtered by a selector.
36
     *
37
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $selector
38
     *
39
     * @return static
40
     */
41
    abstract public function find($selector);
42
43
    /**
44
     * Resolve DOMNode(s) to a static instance.
45
     *
46
     * @param DOMNode|DOMNode[]|DOMNodeList|static $nodes
47
     *
48
     * @return static
49
     */
50 62
    protected function resolve($nodes)
51
    {
52 62
        if ($nodes instanceof static) {
53 21
            return $nodes;
54
        }
55
56 62
        return new static($this->doc, $nodes);
57
    }
58
59
    /**
60
     * If the parameter is a css selector, get the descendants
61
     * of dom document filtered by the css selector.
62
     * If the parameter is selection, resolve that selection to static object.
63
     *
64
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $selector
65
     *
66
     * @return static
67
     */
68 19
    protected function targetResolve($selector)
69
    {
70 19
        if (is_string($selector)) {
71 16
            return $this->resolve($this->doc)->find($selector);
72
        }
73
74 8
        return $this->resolve($selector);
75
    }
76
77
    /**
78
     * If the parameter is string, consider it as raw html,
79
     * then create document fragment for it.
80
     * If the parameter is selection, resolve that selection to static instance.
81
     *
82
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $content
83
     *
84
     * @return static
85
     */
86 17
    protected function contentResolve($content)
87
    {
88 17
        if (is_string($content)) {
89 12
            return $this->htmlResolve($content);
90
        }
91
92 15
        return $this->resolve($content);
93
    }
94
95
    /**
96
     * Resolve the html content to static instance.
97
     *
98
     * @param string $html
99
     *
100
     * @return static
101
     */
102 14
    protected function htmlResolve(string $html)
103
    {
104 14
        $frag = $this->doc->createDocumentFragment();
105 14
        $frag->appendXML($html);
106
107 14
        return $this->resolve($frag);
108
    }
109
110
    /**
111
     * Resolve the nodes under the relation to static instance.
112
     * up to but not including the node matched by the $until selector.
113
     *
114
     * @param string $relation
115
     * @param string|DOMNode|DOMNode[]|DOMNodeList|static $until
116
     *
117
     * @return static
118
     */
119 4
    protected function relationResolve(string $relation, ?string $until = null)
120
    {
121 4
        $untilNodes = !is_null($until)
122 4
            ? $this->targetResolve($until)->nodes
123 4
            : [];
124
125 4
        $nodes = [];
126 4
        foreach ($this->nodes as $node) {
127 4
            while ($node = Helper::getRelationNode($node, $relation)) {
128 4
                if (in_array($node, $untilNodes, true)) {
129 4
                    break;
130
                }
131
132 4
                if (!in_array($node, $nodes, true)) {
133 4
                    $nodes[] = $node;
134
                }
135
            }
136
        }
137
138 4
        return $this->resolve($nodes);
139
    }
140
141
    /**
142
     * Resolve the xpath to static instance.
143
     *
144
     * @param string $xpath
145
     *
146
     * @return static
147
     */
148 31
    protected function xpathResolve(string $xpath)
149
    {
150 31
        $nodes = [];
151 31
        foreach ($this->nodes as $node) {
152 30
            $nodes = array_merge($nodes, $this->xpathQuery($xpath, $node));
153
        }
154
155 31
        $nodes = Helper::strictArrayUnique($nodes);
156
157 31
        return $this->resolve($nodes);
158
    }
159
160
    /**
161
     * Query xpath to an array of DOMNode
162
     *
163
     * @param string       $xpath
164
     * @param DOMNode|null $node
165
     *
166
     * @return DOMNode[]
167
     */
168 35
    protected function xpathQuery(
169
        string $xpath,
170
        ?DOMNode $node = null
171
    ): array {
172 35
        return Helper::xpathQuery($xpath, $this->doc, $node);
173
    }
174
}
175