DotFilteringTrait   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
eloc 80
dl 0
loc 251
ccs 72
cts 72
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A filterBy() 0 29 6
A filter() 0 14 2
A where() 0 23 5
A find() 0 13 4
A operators() 0 84 3
1
<?php
2
3
namespace BinaryCube\DotArray;
4
5
/**
6
 * DotFilteringTrait
7
 *
8
 * @package BinaryCube\DotArray
9
 * @author  Banciu N. Cristian Mihai <[email protected]>
10
 * @license https://github.com/binary-cube/dot-array/blob/master/LICENSE <MIT License>
11
 * @link    https://github.com/binary-cube/dot-array
12
 */
13
trait DotFilteringTrait
14
{
15
16
    /**
17
     * List with internal operators and the associated callbacks.
18
     *
19
     * @return array
20
     */
21 2
    protected static function operators()
22
    {
23
        return [
24
            [
25 2
                'tokens' => ['=', '==', 'eq'],
26
                'closure' => function ($item, $property, $value) {
27 2
                    return $item[$property] == $value[0];
28 2
                },
29
            ],
30
31
            [
32
                'tokens' => ['===', 'i'],
33
                'closure' => function ($item, $property, $value) {
34 2
                    return $item[$property] === $value[0];
35 2
                },
36
            ],
37
38
            [
39
                'tokens' => ['!=', 'ne'],
40
                'closure' => function ($item, $property, $value) {
41 1
                    return $item[$property] != $value[0];
42 2
                },
43
            ],
44
45
            [
46
                'tokens' => ['!==', 'ni'],
47
                'closure' => function ($item, $property, $value) {
48 1
                    return $item[$property] !== $value[0];
49 2
                },
50
            ],
51
52
            [
53
                'tokens' => ['<', 'lt'],
54
                'closure' => function ($item, $property, $value) {
55 2
                    return $item[$property] < $value[0];
56 2
                },
57
            ],
58
59
            [
60
                'tokens' => ['>', 'gt'],
61
                'closure' => function ($item, $property, $value) {
62 1
                    return $item[$property] > $value[0];
63 2
                },
64
            ],
65
66
            [
67
                'tokens' => ['<=', 'lte'],
68
                'closure' => function ($item, $property, $value) {
69 2
                    return $item[$property] <= $value[0];
70 2
                },
71
            ],
72
73
            [
74
                'tokens' => ['>=', 'gte'],
75
                'closure' => function ($item, $property, $value) {
76 1
                    return $item[$property] >= $value[0];
77 2
                },
78
            ],
79
80
            [
81
                'tokens' => ['in', 'contains'],
82
                'closure' => function ($item, $property, $value) {
83 2
                    return \in_array($item[$property], (array) $value, true);
84 2
                },
85
            ],
86
87
            [
88
                'tokens' => ['not-in', 'not-contains'],
89
                'closure' => function ($item, $property, $value) {
90 1
                    return !\in_array($item[$property], (array) $value, true);
91 2
                },
92
            ],
93
94
            [
95
                'tokens' => ['between'],
96
                'closure' => function ($item, $property, $value) {
97 2
                    return ($item[$property] >= $value[0] && $item[$property] <= $value[1]);
98 2
                },
99
            ],
100
101
            [
102
                'tokens' => ['not-between'],
103
                'closure' => function ($item, $property, $value) {
104 2
                    return ($item[$property] < $value[0] || $item[$property] > $value[1]);
105 2
                },
106
            ],
107
        ];
108
    }
109
110
    /**
111
     * Find the first item in an array that passes the truth test, otherwise return false.
112
     * The signature of the callable must be: `function ($value, $key)`
113
     *
114
     * @param \Closure $closure
115
     *
116
     * @return false|mixed
117
     */
118 1
    public function find(\Closure $closure)
119
    {
120 1
        foreach ($this->items as $key => $value) {
121 1
            if ($closure($value, $key)) {
122 1
                if (\is_array($value)) {
123 1
                    $value = static::create($value);
124
                }
125
126 1
                return $value;
127
            }
128
        }
129
130 1
        return false;
131
    }
132
133
    /**
134
     * Use a callable function to filter through items.
135
     * The signature of the callable must be: `function ($value, $key)`
136
     *
137
     * @param \Closure|null $closure
138
     * @param int           $flag    Flag determining what arguments are sent to callback.
139
     *                               ARRAY_FILTER_USE_KEY :: pass key as the only argument
140
     *                               to callback. ARRAY_FILTER_USE_BOTH :: pass both value
141
     *                               and key as arguments to callback.
142
     *
143
     * @return static
144
     */
145 3
    public function filter(\Closure $closure = null, $flag = ARRAY_FILTER_USE_BOTH)
146
    {
147 3
        $items = $this->items;
148
149 3
        if (!isset($closure)) {
150 2
            return static::create($items);
151
        }
152
153 3
        return static::create(
154 3
            \array_values(
155 3
                \array_filter(
156 3
                    $items,
157 3
                    $closure,
158 3
                    $flag
159
                )
160
            )
161
        );
162
    }
163
164
    /**
165
     * Allow to filter an array using one of the following comparison operators:
166
     *  - [ =, ==, eq (equal) ]
167
     *  - [ ===, i (identical) ]
168
     *  - [ !=, ne (not equal) ]
169
     *  - [ !==, ni (not identical) ]
170
     *  - [ <, lt (less than) ]
171
     *  - [ >, gr (greater than) ]
172
     *  - [ <=, lte (less than or equal to) ]
173
     *  - [ =>, gte (greater than or equal to) ]
174
     *  - [ in, contains ]
175
     *  - [ not-in, not-contains ]
176
     *  - [ between ]
177
     *  - [ not-between ]
178
     *
179
     * @param string $property
180
     * @param string $comparisonOperator
181
     * @param mixed  $value
182
     *
183
     * @return static
184
     */
185 2
    public function filterBy($property, $comparisonOperator, $value)
186
    {
187 2
        $args  = \func_get_args();
188 2
        $value = \array_slice($args, 2, \count($args));
189
190 2
        $closure   = null;
191 2
        $operators = static::operators();
192
193 2
        if (isset($value[0]) && \is_array($value[0])) {
194 2
            $value = $value[0];
195
        }
196
197 2
        foreach ($operators as $entry) {
198 2
            if (\in_array($comparisonOperator, $entry['tokens'])) {
199
                $closure = function ($item) use ($entry, $property, $value) {
200 2
                    $item = (array) $item;
201
202 2
                    if (!\array_key_exists($property, $item)) {
203 1
                        return false;
204
                    }
205
206 2
                    return $entry['closure']($item, $property, $value);
207 2
                };
208
209 2
                break;
210
            }
211
        }
212
213 2
        return $this->filter($closure);
214
    }
215
216
    /**
217
     * Filtering through array.
218
     * The signature of the call can be:
219
     * - where([property, comparisonOperator, ...value])
220
     * - where(\Closure) :: The signature of the callable must be: `function ($value, $key)`
221
     * - where([\Closure]) :: The signature of the callable must be: `function ($value, $key)`
222
     *
223
     * Allowed comparison operators:
224
     *  - [ =, ==, eq (equal) ]
225
     *  - [ ===, i (identical) ]
226
     *  - [ !=, ne (not equal) ]
227
     *  - [ !==, ni (not identical) ]
228
     *  - [ <, lt (less than) ]
229
     *  - [ >, gr (greater than) ]
230
     *  - [ <=, lte (less than or equal to) ]
231
     *  - [ =>, gte (greater than or equal to) ]
232
     *  - [ in, contains ]
233
     *  - [ not-in, not-contains ]
234
     *  - [ between ]
235
     *  - [ not-between ]
236
     *
237
     * @param array|callable $criteria
238
     *
239
     * @return static
240
     */
241 1
    public function where($criteria)
242
    {
243 1
        $criteria = (array) $criteria;
244
245 1
        if (empty($criteria)) {
246 1
            return $this->filter();
247
        }
248
249 1
        $closure = \array_shift($criteria);
250
251 1
        if ($closure instanceof \Closure) {
252 1
            return $this->filter($closure);
253
        }
254
255 1
        $property           = $closure;
256 1
        $comparisonOperator = \array_shift($criteria);
257 1
        $value              = $criteria;
258
259 1
        if (isset($value[0]) && \is_array($value[0])) {
260 1
            $value = $value[0];
261
        }
262
263 1
        return $this->filterBy($property, $comparisonOperator, $value);
264
    }
265
266
}
267