PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.95
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.95
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
fluent-boards / vendor / wpfluent / framework / src / WPFluent / Support / EnumeratesValues.php

EnumeratesValues.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.95, at vendor/wpfluent/framework/src/WPFluent/Support/EnumeratesValues.php

1,094 lines 27.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\Framework\Support;
4
5 use Closure;
6 use Exception;
7 use Traversable;
8 use CachingIterator;
9 use JsonSerializable;
10 use UnexpectedValueException;
11
12 use FluentBoards\Framework\Support\Arr;
13 use FluentBoards\Framework\Support\Helper;
14 use FluentBoards\Framework\Support\Collection;
15 use FluentBoards\Framework\Support\Enumerable;
16 use FluentBoards\Framework\Support\JsonableInterface;
17 use FluentBoards\Framework\Support\ArrayableInterface;
18 use FluentBoards\Framework\Support\HigherOrderWhenProxy;
19 use FluentBoards\Framework\Support\HigherOrderCollectionProxy;
20
21 /**
22 * @property-read HigherOrderCollectionProxy $average
23 * @property-read HigherOrderCollectionProxy $avg
24 * @property-read HigherOrderCollectionProxy $contains
25 * @property-read HigherOrderCollectionProxy $doesntContain
26 * @property-read HigherOrderCollectionProxy $each
27 * @property-read HigherOrderCollectionProxy $every
28 * @property-read HigherOrderCollectionProxy $filter
29 * @property-read HigherOrderCollectionProxy $first
30 * @property-read HigherOrderCollectionProxy $flatMap
31 * @property-read HigherOrderCollectionProxy $groupBy
32 * @property-read HigherOrderCollectionProxy $keyBy
33 * @property-read HigherOrderCollectionProxy $map
34 * @property-read HigherOrderCollectionProxy $max
35 * @property-read HigherOrderCollectionProxy $min
36 * @property-read HigherOrderCollectionProxy $partition
37 * @property-read HigherOrderCollectionProxy $reject
38 * @property-read HigherOrderCollectionProxy $some
39 * @property-read HigherOrderCollectionProxy $sortBy
40 * @property-read HigherOrderCollectionProxy $sortByDesc
41 * @property-read HigherOrderCollectionProxy $skipUntil
42 * @property-read HigherOrderCollectionProxy $skipWhile
43 * @property-read HigherOrderCollectionProxy $sum
44 * @property-read HigherOrderCollectionProxy $takeUntil
45 * @property-read HigherOrderCollectionProxy $takeWhile
46 * @property-read HigherOrderCollectionProxy $unique
47 * @property-read HigherOrderCollectionProxy $until
48 */
49 trait EnumeratesValues
50 {
51 /**
52 * Indicates that the object's string representation should be escaped when __toString is invoked.
53 *
54 * @var bool
55 */
56 protected $escapeWhenCastingToString = false;
57
58 /**
59 * The methods that can be proxied.
60 *
61 * @var string[]
62 */
63 protected static $proxies = [
64 'average',
65 'avg',
66 'contains',
67 'doesntContain',
68 'each',
69 'every',
70 'filter',
71 'first',
72 'flatMap',
73 'groupBy',
74 'keyBy',
75 'map',
76 'max',
77 'min',
78 'partition',
79 'reject',
80 'skipUntil',
81 'skipWhile',
82 'some',
83 'sortBy',
84 'sortByDesc',
85 'sum',
86 'takeUntil',
87 'takeWhile',
88 'unique',
89 'until',
90 ];
91
92 /**
93 * Create a new collection instance if the value isn't one already.
94 *
95 * @param mixed $items
96 * @return static
97 */
98 public static function make($items = [])
99 {
100 return new static($items);
101 }
102
103 /**
104 * Wrap the given value in a collection if applicable.
105 *
106 * @param mixed $value
107 * @return static
108 */
109 public static function wrap($value)
110 {
111 return $value instanceof Enumerable
112 ? new static($value)
113 : new static(Arr::wrap($value));
114 }
115
116 /**
117 * Get the underlying items from the given collection if applicable.
118 *
119 * @param array|static $value
120 * @return array
121 */
122 public static function unwrap($value)
123 {
124 return $value instanceof Enumerable ? $value->all() : $value;
125 }
126
127 /**
128 * Create a new instance with no items.
129 *
130 * @return static
131 */
132 public static function empty()
133 {
134 return new static([]);
135 }
136
137 /**
138 * Create a new collection by invoking the callback a given amount of times.
139 *
140 * @param int $number
141 * @param callable|null $callback
142 * @return static
143 */
144 public static function times($number, ?callable $callback = null)
145 {
146 if ($number < 1) {
147 return new static;
148 }
149
150 return static::range(1, $number)
151 ->when($callback)
152 ->map($callback);
153 }
154
155 /**
156 * Alias for the "avg" method.
157 *
158 * @param callable|string|null $callback
159 * @return mixed
160 */
161 public function average($callback = null)
162 {
163 return $this->avg($callback);
164 }
165
166 /**
167 * Alias for the "contains" method.
168 *
169 * @param mixed $key
170 * @param mixed $operator
171 * @param mixed $value
172 * @return bool
173 */
174 public function some($key, $operator = null, $value = null)
175 {
176 return $this->contains(...func_get_args());
177 }
178
179 /**
180 * Determine if an item exists, using strict comparison.
181 *
182 * @param mixed $key
183 * @param mixed $value
184 * @return bool
185 */
186 public function containsStrict($key, $value = null)
187 {
188 if (func_num_args() === 2) {
189 return $this->contains(function ($item) use ($key, $value) {
190 return Helper::dataGet($item, $key) === $value;
191 });
192 }
193
194 if ($this->useAsCallable($key)) {
195 return ! is_null($this->first($key));
196 }
197
198 foreach ($this as $item) {
199 if ($item === $key) {
200 return true;
201 }
202 }
203
204 return false;
205 }
206
207
208 /**
209 * Execute a callback over each item.
210 *
211 * @param callable $callback
212 * @return $this
213 */
214 public function each(callable $callback)
215 {
216 foreach ($this as $key => $item) {
217 if ($callback($item, $key) === false) {
218 break;
219 }
220 }
221
222 return $this;
223 }
224
225 /**
226 * Execute a callback over each nested chunk of items.
227 *
228 * @param callable $callback
229 * @return static
230 */
231 public function eachSpread(callable $callback)
232 {
233 return $this->each(function ($chunk, $key) use ($callback) {
234 $chunk[] = $key;
235
236 return $callback(...$chunk);
237 });
238 }
239
240 /**
241 * Determine if all items pass the given truth test.
242 *
243 * @param string|callable $key
244 * @param mixed $operator
245 * @param mixed $value
246 * @return bool
247 */
248 public function every($key, $operator = null, $value = null)
249 {
250 if (func_num_args() === 1) {
251 $callback = $this->valueRetriever($key);
252
253 foreach ($this as $k => $v) {
254 if (! $callback($v, $k)) {
255 return false;
256 }
257 }
258
259 return true;
260 }
261
262 return $this->every($this->operatorForWhere(...func_get_args()));
263 }
264
265 /**
266 * Get the first item by the given key value pair.
267 *
268 * @param string $key
269 * @param mixed $operator
270 * @param mixed $value
271 * @return mixed
272 */
273 public function firstWhere($key, $operator = null, $value = null)
274 {
275 return $this->first($this->operatorForWhere(...func_get_args()));
276 }
277
278 /**
279 * Determine if the collection is not empty.
280 *
281 * @return bool
282 */
283 public function isNotEmpty()
284 {
285 return ! $this->isEmpty();
286 }
287
288 /**
289 * Run a map over each nested chunk of items.
290 *
291 * @param callable $callback
292 * @return static
293 */
294 public function mapSpread(callable $callback)
295 {
296 return $this->map(function ($chunk, $key) use ($callback) {
297 $chunk[] = $key;
298
299 return $callback(...$chunk);
300 });
301 }
302
303 /**
304 * Run a grouping map over the items.
305 *
306 * The callback should return an associative array with a single key/value pair.
307 *
308 * @param callable $callback
309 * @return static
310 */
311 public function mapToGroups(callable $callback)
312 {
313 $groups = $this->mapToDictionary($callback);
314
315 return $groups->map([$this, 'make']);
316 }
317
318 /**
319 * Map a collection and flatten the result by a single level.
320 *
321 * @param callable $callback
322 * @return static
323 */
324 public function flatMap(callable $callback)
325 {
326 return $this->map($callback)->collapse();
327 }
328
329 /**
330 * Map the values into a new class.
331 *
332 * @param string $class
333 * @return static
334 */
335 public function mapInto($class)
336 {
337 return $this->map(function ($value, $key) use ($class) {
338 return new $class($value, $key);
339 });
340 }
341
342 /**
343 * Get the min value of a given key.
344 *
345 * @param callable|string|null $callback
346 * @return mixed
347 */
348 public function min($callback = null)
349 {
350 $callback = $this->valueRetriever($callback);
351
352 return $this->map(function ($value) use ($callback) {
353 return $callback($value);
354 })->filter(function ($value) {
355 return ! is_null($value);
356 })->reduce(function ($result, $value) {
357 return is_null($result) || $value < $result ? $value : $result;
358 });
359 }
360
361 /**
362 * Get the max value of a given key.
363 *
364 * @param callable|string|null $callback
365 * @return mixed
366 */
367 public function max($callback = null)
368 {
369 $callback = $this->valueRetriever($callback);
370
371 return $this->filter(function ($value) {
372 return ! is_null($value);
373 })->reduce(function ($result, $item) use ($callback) {
374 $value = $callback($item);
375
376 return is_null($result) || $value > $result ? $value : $result;
377 });
378 }
379
380 /**
381 * "Paginate" the collection by slicing it into a smaller collection.
382 *
383 * @param int $page
384 * @param int $perPage
385 * @return static
386 */
387 public function forPage($page, $perPage)
388 {
389 $offset = max(0, ($page - 1) * $perPage);
390
391 return $this->slice($offset, $perPage);
392 }
393
394 /**
395 * Partition the collection into two arrays using the given callback or key.
396 *
397 * @param callable|string $key
398 * @param mixed $operator
399 * @param mixed $value
400 * @return static
401 */
402 public function partition($key, $operator = null, $value = null)
403 {
404 $passed = [];
405 $failed = [];
406
407 $callback = func_num_args() === 1
408 ? $this->valueRetriever($key)
409 : $this->operatorForWhere(...func_get_args());
410
411 foreach ($this as $key => $item) {
412 if ($callback($item, $key)) {
413 $passed[$key] = $item;
414 } else {
415 $failed[$key] = $item;
416 }
417 }
418
419 return new static([new static($passed), new static($failed)]);
420 }
421
422 /**
423 * Get the sum of the given values.
424 *
425 * @param callable|string|null $callback
426 * @return mixed
427 */
428 public function sum($callback = null)
429 {
430 $callback = is_null($callback)
431 ? $this->identity()
432 : $this->valueRetriever($callback);
433
434 return $this->reduce(function ($result, $item) use ($callback) {
435 return $result + $callback($item);
436 }, 0);
437 }
438
439 /**
440 * Apply the callback if the value is truthy.
441 *
442 * @param bool|mixed $value
443 * @param callable|null $callback
444 * @param callable|null $default
445 * @return static|mixed
446 */
447 public function when($value, ?callable $callback = null, ?callable $default = null)
448 {
449 if (! $callback) {
450 return new HigherOrderWhenProxy($value);
451 }
452
453 if ($value) {
454 return $callback($this, $value);
455 } elseif ($default) {
456 return $default($this, $value);
457 }
458
459 return $this;
460 }
461
462 /**
463 * Apply the callback if the collection is empty.
464 *
465 * @param callable $callback
466 * @param callable|null $default
467 * @return static|mixed
468 */
469 public function whenEmpty(callable $callback, ?callable $default = null)
470 {
471 return $this->when($this->isEmpty(), $callback, $default);
472 }
473
474 /**
475 * Apply the callback if the collection is not empty.
476 *
477 * @param callable $callback
478 * @param callable|null $default
479 * @return static|mixed
480 */
481 public function whenNotEmpty(callable $callback, ?callable $default = null)
482 {
483 return $this->when($this->isNotEmpty(), $callback, $default);
484 }
485
486 /**
487 * Apply the callback if the value is falsy.
488 *
489 * @param bool $value
490 * @param callable $callback
491 * @param callable|null $default
492 * @return static|mixed
493 */
494 public function unless($value, callable $callback, ?callable $default = null)
495 {
496 return $this->when(! $value, $callback, $default);
497 }
498
499 /**
500 * Apply the callback unless the collection is empty.
501 *
502 * @param callable $callback
503 * @param callable|null $default
504 * @return static|mixed
505 */
506 public function unlessEmpty(callable $callback, ?callable $default = null)
507 {
508 return $this->whenNotEmpty($callback, $default);
509 }
510
511 /**
512 * Apply the callback unless the collection is not empty.
513 *
514 * @param callable $callback
515 * @param callable|null $default
516 * @return static|mixed
517 */
518 public function unlessNotEmpty(callable $callback, ?callable $default = null)
519 {
520 return $this->whenEmpty($callback, $default);
521 }
522
523 /**
524 * Filter items by the given key value pair.
525 *
526 * @param string $key
527 * @param mixed $operator
528 * @param mixed $value
529 * @return static
530 */
531 public function where($key, $operator = null, $value = null)
532 {
533 return $this->filter($this->operatorForWhere(...func_get_args()));
534 }
535
536 /**
537 * Filter items where the value for the given key is null.
538 *
539 * @param string|null $key
540 * @return static
541 */
542 public function whereNull($key = null)
543 {
544 return $this->whereStrict($key, null);
545 }
546
547 /**
548 * Filter items where the value for the given key is not null.
549 *
550 * @param string|null $key
551 * @return static
552 */
553 public function whereNotNull($key = null)
554 {
555 return $this->where($key, '!==', null);
556 }
557
558 /**
559 * Filter items by the given key value pair using strict comparison.
560 *
561 * @param string $key
562 * @param mixed $value
563 * @return static
564 */
565 public function whereStrict($key, $value)
566 {
567 return $this->where($key, '===', $value);
568 }
569
570 /**
571 * Filter items by the given key value pair.
572 *
573 * @param string $key
574 * @param mixed $values
575 * @param bool $strict
576 * @return static
577 */
578 public function whereIn($key, $values, $strict = false)
579 {
580 $values = $this->getArrayableItems($values);
581
582 return $this->filter(function ($item) use ($key, $values, $strict) {
583 return in_array(Helper::dataGet($item, $key), $values, $strict);
584 });
585 }
586
587 /**
588 * Filter items by the given key value pair using strict comparison.
589 *
590 * @param string $key
591 * @param mixed $values
592 * @return static
593 */
594 public function whereInStrict($key, $values)
595 {
596 return $this->whereIn($key, $values, true);
597 }
598
599 /**
600 * Filter items such that the value of the given key is between the given values.
601 *
602 * @param string $key
603 * @param array $values
604 * @return static
605 */
606 public function whereBetween($key, $values)
607 {
608 return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
609 }
610
611 /**
612 * Filter items such that the value of the given key is not between the given values.
613 *
614 * @param string $key
615 * @param array $values
616 * @return static
617 */
618 public function whereNotBetween($key, $values)
619 {
620 return $this->filter(function ($item) use ($key, $values) {
621 return Helper::dataGet($item, $key) < reset($values) || Helper::dataGet($item, $key) > end($values);
622 });
623 }
624
625 /**
626 * Filter items by the given key value pair.
627 *
628 * @param string $key
629 * @param mixed $values
630 * @param bool $strict
631 * @return static
632 */
633 public function whereNotIn($key, $values, $strict = false)
634 {
635 $values = $this->getArrayableItems($values);
636
637 return $this->reject(function ($item) use ($key, $values, $strict) {
638 return in_array(Helper::dataGet($item, $key), $values, $strict);
639 });
640 }
641
642 /**
643 * Filter items by the given key value pair using strict comparison.
644 *
645 * @param string $key
646 * @param mixed $values
647 * @return static
648 */
649 public function whereNotInStrict($key, $values)
650 {
651 return $this->whereNotIn($key, $values, true);
652 }
653
654 /**
655 * Filter the items, removing any items that don't match the given type(s).
656 *
657 * @param string|string[] $type
658 * @return static
659 */
660 public function whereInstanceOf($type)
661 {
662 return $this->filter(function ($value) use ($type) {
663 if (is_array($type)) {
664 foreach ($type as $classType) {
665 if ($value instanceof $classType) {
666 return true;
667 }
668 }
669
670 return false;
671 }
672
673 return $value instanceof $type;
674 });
675 }
676
677 /**
678 * Pass the collection to the given callback and return the result.
679 *
680 * @param callable $callback
681 * @return mixed
682 */
683 public function pipe(callable $callback)
684 {
685 return $callback($this);
686 }
687
688 /**
689 * Pass the collection into a new class.
690 *
691 * @param string $class
692 * @return mixed
693 */
694 public function pipeInto($class)
695 {
696 return new $class($this);
697 }
698
699 /**
700 * Pass the collection through a series of callable pipes
701 * and return the result.
702 *
703 * @param array<callable> $pipes
704 * @return mixed
705 */
706 public function pipeThrough($pipes)
707 {
708 return static::make($pipes)->reduce(
709 function ($carry, $pipe) {
710 return $pipe($carry);
711 },
712 $this,
713 );
714 }
715
716 /**
717 * Pass the collection to the given callback and then return it.
718 *
719 * @param callable $callback
720 * @return $this
721 */
722 public function tap(callable $callback)
723 {
724 $callback(clone $this);
725
726 return $this;
727 }
728
729 /**
730 * Reduce the collection to a single value.
731 *
732 * @param callable $callback
733 * @param mixed $initial
734 * @return mixed
735 */
736 public function reduce(callable $callback, $initial = null)
737 {
738 $result = $initial;
739
740 foreach ($this as $key => $value) {
741 $result = $callback($result, $value, $key);
742 }
743
744 return $result;
745 }
746
747 /**
748 * Reduce the collection to multiple aggregate values.
749 *
750 * @param callable $callback
751 * @param mixed ...$initial
752 * @return array
753 *
754 * @deprecated Use "reduceSpread" instead
755 *
756 * @throws \UnexpectedValueException
757 */
758 public function reduceMany(callable $callback, ...$initial)
759 {
760 return $this->reduceSpread($callback, ...$initial);
761 }
762
763 /**
764 * Reduce the collection to multiple aggregate values.
765 *
766 * @param callable $callback
767 * @param mixed ...$initial
768 * @return array
769 *
770 * @throws \UnexpectedValueException
771 */
772 public function reduceSpread(callable $callback, ...$initial)
773 {
774 $result = $initial;
775
776 foreach ($this as $key => $value) {
777 $result = call_user_func_array($callback, array_merge($result, [$value, $key]));
778
779 if (! is_array($result)) {
780 throw new UnexpectedValueException(sprintf(
781 "%s::reduceMany expects reducer to return an array, but got a '%s' instead.",
782 static::classBasename(static::class), gettype($result)
783 ));
784 }
785 }
786
787 return $result;
788 }
789
790 /**
791 * Reduce an associative collection to a single value.
792 *
793 * @param callable $callback
794 * @param mixed $initial
795 * @return mixed
796 */
797 public function reduceWithKeys(callable $callback, $initial = null)
798 {
799 return $this->reduce($callback, $initial);
800 }
801
802 /**
803 * Create a collection of all elements that do not pass a given truth test.
804 *
805 * @param callable|mixed $callback
806 * @return static
807 */
808 public function reject($callback = true)
809 {
810 $useAsCallable = $this->useAsCallable($callback);
811
812 return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
813 return $useAsCallable
814 ? ! $callback($value, $key)
815 : $value != $callback;
816 });
817 }
818
819 /**
820 * Return only unique items from the collection array using strict comparison.
821 *
822 * @param string|callable|null $key
823 * @return static
824 */
825 public function uniqueStrict($key = null)
826 {
827 return $this->unique($key, true);
828 }
829
830 /**
831 * Collect the values into a collection.
832 *
833 * @return \FluentBoards\Framework\Support\Collection
834 */
835 public function collect()
836 {
837 return new Collection($this->all());
838 }
839
840 /**
841 * Get the collection of items as a plain array.
842 *
843 * @return array
844 */
845 public function toArray()
846 {
847 return $this->map(function ($value) {
848 return $value instanceof ArrayableInterface ? $value->toArray() : $value;
849 })->all();
850 }
851
852 /**
853 * Convert the object into something JSON serializable.
854 *
855 * @return array
856 */
857 #[\ReturnTypeWillChange]
858 public function jsonSerialize()
859 {
860 return array_map(function ($value) {
861 if ($value instanceof JsonSerializable) {
862 return $value->jsonSerialize();
863 } elseif ($value instanceof JsonableInterface) {
864 return json_decode($value->toJson(), true);
865 } elseif ($value instanceof ArrayableInterface) {
866 return $value->toArray();
867 }
868
869 return $value;
870 }, $this->all());
871 }
872
873 /**
874 * Get the collection of items as JSON.
875 *
876 * @param int $options
877 * @return string
878 */
879 public function toJson($options = 0)
880 {
881 return json_encode($this->jsonSerialize(), $options);
882 }
883
884 /**
885 * Get a CachingIterator instance.
886 *
887 * @param int $flags
888 * @return \CachingIterator
889 */
890 public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
891 {
892 return new CachingIterator($this->getIterator(), $flags);
893 }
894
895 /**
896 * Convert the collection to its string representation.
897 *
898 * @return string
899 */
900 public function __toString()
901 {
902 return $this->escapeWhenCastingToString
903 ? esc_html($this->toJson())
904 : $this->toJson();
905 }
906
907 /**
908 * Indicate that the model's string representation should be escaped when __toString is invoked.
909 *
910 * @param bool $escape
911 * @return $this
912 */
913 public function escapeWhenCastingToString($escape = true)
914 {
915 $this->escapeWhenCastingToString = $escape;
916
917 return $this;
918 }
919
920 /**
921 * Add a method to the list of proxied methods.
922 *
923 * @param string $method
924 * @return void
925 */
926 public static function proxy($method)
927 {
928 static::$proxies[] = $method;
929 }
930
931 /**
932 * Dynamically access collection proxies.
933 *
934 * @param string $key
935 * @return mixed
936 *
937 * @throws \Exception
938 */
939 public function __get($key)
940 {
941 if (! in_array($key, static::$proxies)) {
942 throw new Exception("Property [{$key}] does not exist on this collection instance.");
943 }
944
945 return new HigherOrderCollectionProxy($this, $key);
946 }
947
948 /**
949 * Results array of items from Collection or ArrayableInterface.
950 *
951 * @param mixed $items
952 * @return array
953 */
954 protected function getArrayableItems($items)
955 {
956 if (is_array($items)) {
957 return $items;
958 } elseif ($items instanceof Enumerable) {
959 return $items->all();
960 } elseif ($items instanceof ArrayableInterface) {
961 return $items->toArray();
962 } elseif ($items instanceof JsonableInterface) {
963 return json_decode($items->toJson(), true);
964 } elseif ($items instanceof JsonSerializable) {
965 return (array) $items->jsonSerialize();
966 } elseif ($items instanceof Traversable) {
967 return iterator_to_array($items);
968 } elseif (function_exists('enum_exists')) {
969 if (class_exists('UnitEnum')) {
970 if ($items instanceof \UnitEnum) {
971 return [$items];
972 }
973 }
974 }
975
976 return (array) $items;
977 }
978
979 /**
980 * Get an operator checker callback.
981 *
982 * @param string $key
983 * @param string|null $operator
984 * @param mixed $value
985 * @return \Closure
986 */
987 protected function operatorForWhere($key, $operator = null, $value = null)
988 {
989 if (func_num_args() === 1) {
990 $value = true;
991
992 $operator = '=';
993 }
994
995 if (func_num_args() === 2) {
996 $value = $operator;
997
998 $operator = '=';
999 }
1000
1001 return function ($item) use ($key, $operator, $value) {
1002 $retrieved = Helper::dataGet($item, $key);
1003
1004 $strings = array_filter([$retrieved, $value], function ($value) {
1005 return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
1006 });
1007
1008 if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
1009 return in_array($operator, ['!=', '<>', '!==']);
1010 }
1011
1012 switch ($operator) {
1013 default:
1014 case '=':
1015 case '==': return $retrieved == $value;
1016 case '!=':
1017 case '<>': return $retrieved != $value;
1018 case '<': return $retrieved < $value;
1019 case '>': return $retrieved > $value;
1020 case '<=': return $retrieved <= $value;
1021 case '>=': return $retrieved >= $value;
1022 case '===': return $retrieved === $value;
1023 case '!==': return $retrieved !== $value;
1024 }
1025 };
1026 }
1027
1028 /**
1029 * Determine if the given value is callable, but not a string.
1030 *
1031 * @param mixed $value
1032 * @return bool
1033 */
1034 protected function useAsCallable($value)
1035 {
1036 return ! is_string($value) && is_callable($value);
1037 }
1038
1039 /**
1040 * Get a value retrieving callback.
1041 *
1042 * @param callable|string|null $value
1043 * @return callable
1044 */
1045 protected function valueRetriever($value)
1046 {
1047 if ($this->useAsCallable($value)) {
1048 return $value;
1049 }
1050
1051 return function ($item) use ($value) {
1052 return Helper::dataGet($item, $value);
1053 };
1054 }
1055
1056 /**
1057 * Make a function to check an item's equality.
1058 *
1059 * @param mixed $value
1060 * @return \Closure
1061 */
1062 protected function equality($value)
1063 {
1064 return function ($item) use ($value) {
1065 return $item === $value;
1066 };
1067 }
1068
1069 /**
1070 * Make a function using another function, by negating its result.
1071 *
1072 * @param \Closure $callback
1073 * @return \Closure
1074 */
1075 protected function negate(Closure $callback)
1076 {
1077 return function (...$params) use ($callback) {
1078 return ! $callback(...$params);
1079 };
1080 }
1081
1082 /**
1083 * Make a function that returns what's passed to it.
1084 *
1085 * @return \Closure
1086 */
1087 protected function identity()
1088 {
1089 return function ($value) {
1090 return $value;
1091 };
1092 }
1093 }
1094