Completed
Push — master ( 6fa286...edcedc )
by Banciu N. Cristian Mihai
18:39
created

DotFilteringTrait::filter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

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