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

Helper::caseInsensitiveSearch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 10
ccs 5
cts 5
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Sulao\HtmlQuery;
4
5
use DOMDocument, DOMNode, DOMNodeList, DOMXPath;
6
use Symfony\Component\CssSelector\CssSelectorConverter;
7
use Traversable;
8
9
/**
10
 * Class Helper
11
 *
12
 * @package Sulao\HtmlQuery
13
 */
14
class Helper
15
{
16
    /**
17
     * Convert a css selector to xpath
18
     *
19
     * @param string $selector
20
     * @param string $prefix
21
     *
22
     * @return string
23
     */
24 80
    public static function toXpath(
25
        string $selector,
26
        string $prefix = 'descendant::'
27
    ): string {
28 80
        static $converter;
29 80
        $converter = $converter ?: new CssSelectorConverter();
30
31 80
        return $converter->toXPath($selector, $prefix);
32
    }
33
34
    /**
35
     * Strict Array Unique
36
     *
37
     * @param array|Traversable $arr
38
     *
39
     * @return array
40
     */
41 83
    public static function strictArrayUnique($arr): array
42
    {
43 83
        $uniqueArr = [];
44 83
        foreach ($arr as $value) {
45 81
            if (!in_array($value, $uniqueArr, true)) {
46 81
                $uniqueArr[] = $value;
47
            }
48
        }
49
50 83
        return $uniqueArr;
51
    }
52
53
    /**
54
     * Strict array intersect
55
     *
56
     * @param array $arr1
57
     * @param array $arr2
58
     *
59
     * @return array
60
     */
61 5
    public static function strictArrayIntersect(array $arr1, array $arr2): array
62
    {
63
        $arr = array_filter($arr1, function ($val1) use ($arr2) {
64 5
            return in_array($val1, $arr2, true);
65 5
        });
66
67 5
        return array_values($arr);
68
    }
69
70
    /**
71
     * Strict array diff
72
     *
73
     * @param array $arr1
74
     * @param array $arr2
75
     *
76
     * @return array
77
     */
78 3
    public static function strictArrayDiff(array $arr1, array $arr2): array
79
    {
80
        $arr = array_filter($arr1, function ($val1) use ($arr2) {
81 3
            return !in_array($val1, $arr2, true);
82 3
        });
83
84 3
        return array_values($arr);
85
    }
86
87
    /**
88
     * Case insensitive search
89
     *
90
     * @param string   $needle
91
     * @param string[] $haystack
92
     *
93
     * @return array
94
     */
95 2
    public static function caseInsensitiveSearch(
96
        string $needle,
97
        array $haystack
98
    ): array {
99 2
        $needle = strtolower($needle);
100
        $match = array_filter($haystack, function ($value) use ($needle) {
101 2
            return $needle === strtolower($value);
102 2
        });
103
104 2
        return array_values($match);
105
    }
106
107
    /**
108
     * Split the class attr value to a class array
109
     *
110
     * @param string $className
111
     *
112
     * @return array
113
     */
114 6
    public static function splitClass(string $className): array
115
    {
116 6
        return preg_split('/\s+/', trim($className)) ?: [];
117
    }
118
119
    /**
120
     * Split style to css array
121
     *
122
     * @param string $style
123
     *
124
     * @return array
125
     */
126 2
    public static function splitCss(string $style): array
127
    {
128 2
        $arr = explode(';', $style);
129 2
        $arr = array_map('trim', $arr);
130
131 2
        $css = [];
132 2
        foreach ($arr as $value) {
133 2
            $row = explode(':', $value, 2);
134 2
            if (count($row) !== 2) {
135 1
                continue;
136
            }
137
138 2
            $css[trim($row[0])] = trim($row[1]);
139
        }
140
141 2
        return $css;
142
    }
143
144
    /**
145
     * Implode css array to style string
146
     *
147
     * @param array $css
148
     *
149
     * @return string
150
     */
151 2
    public static function implodeCss(array $css): string
152
    {
153 2
        $arr = [];
154 2
        foreach ($css as $key => $value) {
155 2
            $arr[] = $key . ': ' . $value;
156
        }
157
158 2
        $style = $arr ? implode('; ', $arr) . ';' : '';
159
160 2
        return $style;
161
    }
162
163
    /**
164
     * Determine whether the string is raw html,
165
     * otherwise consider it as a css selector
166
     *
167
     * @param string $html
168
     *
169
     * @return bool
170
     */
171 37
    public static function isRawHtml(string $html): bool
172
    {
173 37
        if ($html[0] === '<' && $html[-1] === '>' && strlen($html) >= 3) {
174 8
            return true;
175
        }
176
177 35
        return (bool) preg_match('/^\s*(<[\w\W]+>)[^>]*$/', $html);
178
    }
179
180
    /**
181
     * Determine whether the selector is a id selector
182
     *
183
     * @param string      $selector
184
     * @param string|null $id
185
     *
186
     * @return bool
187
     */
188 79
    public static function isIdSelector(
189
        string $selector,
190
        string &$id = null
191
    ): bool {
192 79
        if (preg_match('/^#([\w-]+)$/', $selector, $match)) {
193 5
            $id = $match[1];
194
195 5
            return true;
196
        }
197
198 77
        return false;
199
    }
200
201
    /**
202
     * Query xpath to an array of DOMNode
203
     *
204
     * @param string       $xpath
205
     * @param DOMDocument  $doc
206
     * @param DOMNode|null $node
207
     *
208
     * @return DOMNode[]
209
     */
210 79
    public static function xpathQuery(
211
        string $xpath,
212
        DOMDocument $doc,
213
        ?DOMNode $node = null
214
    ): array {
215 79
        $docXpath = new DOMXpath($doc);
216 79
        $nodeList = $docXpath->query($xpath, $node);
217
218 79
        if (!($nodeList instanceof DOMNodeList)) {
219 1
            return [];
220
        }
221
222 79
        return iterator_to_array($nodeList);
223
    }
224
225
    /**
226
     * Get the node with the relationship of current node.
227
     *
228
     * @param DOMNode $node
229
     * @param string  $relation
230
     *
231
     * @return DOMNode|null
232
     */
233 4
    public static function getRelationNode(DOMNode $node, string $relation)
234
    {
235
        /** @var DOMNode $node */
236 4
        while (($node = $node->$relation)
237 4
            && $node instanceof DOMNode
238 4
            && $node->nodeType !== XML_DOCUMENT_NODE
239
        ) {
240 4
            if ($node->nodeType !== XML_ELEMENT_NODE) {
241 3
                continue;
242
            }
243
244 4
            return $node;
245
        }
246
247 3
        return null;
248
    }
249
}
250