PluginProbe
FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP / trunk
FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP vtrunk
2.4.0 trunk 1.0.1 1.1.0 1.1.1 1.2.0 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.71 2.2.72 2.2.73 2.2.80 2.2.81 All 32 releases
fluent-smtp / includes / Support / Collection.php

Collection.php in FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP trunk, at includes/Support/Collection.php

856 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentMail\Includes\Support;
4
5 use Closure;
6 use Countable;
7 use ArrayAccess;
8 use ArrayIterator;
9 use CachingIterator;
10 use JsonSerializable;
11 use IteratorAggregate;
12 use FluentMail\Includes\Support\Arr;
13 use FluentMail\Includes\Support\Contracts\JsonableInterface;
14 use FluentMail\Includes\Support\Contracts\ArrayableInterface;
15
16 /**
17 * @phpstan-consistent-constructor
18 */
19 class Collection implements ArrayAccess, ArrayableInterface, Countable, IteratorAggregate, JsonableInterface, JsonSerializable {
20
21 /**
22 * The items contained in the collection.
23 *
24 * @var array
25 */
26 protected $items = array();
27
28 /**
29 * Create a new collection.
30 *
31 * @param array $items
32 * @return void
33 */
34 public function __construct(array $items = array())
35 {
36 $this->items = $items;
37 }
38
39 /**
40 * Create a new collection instance if the value isn't one already.
41 *
42 * @param mixed $items
43 * @return static
44 */
45 public static function make($items)
46 {
47 if (is_null($items)) return new static;
48
49 if ($items instanceof Collection) return $items;
50
51 return new static(is_array($items) ? $items : array($items));
52 }
53
54 /**
55 * Get all of the items in the collection.
56 *
57 * @return array
58 */
59 public function all()
60 {
61 return $this->items;
62 }
63
64 /**
65 * Collapse the collection items into a single array.
66 *
67 * @return static
68 */
69 public function collapse()
70 {
71 $results = array();
72
73 foreach ($this->items as $values)
74 {
75 if ($values instanceof Collection) $values = $values->all();
76
77 $results = array_merge($results, $values);
78 }
79
80 return new static($results);
81 }
82
83 /**
84 * Determine if an item exists in the collection.
85 *
86 * @param mixed $value
87 * @return bool
88 */
89 public function contains($value)
90 {
91 if ($value instanceof Closure)
92 {
93 return ! is_null($this->first($value));
94 }
95
96 return in_array($value, $this->items);
97 }
98
99 /**
100 * Diff the collection with the given items.
101 *
102 * @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
103 * @return static
104 */
105 public function diff($items)
106 {
107 return new static(array_diff($this->items, $this->getArrayableItems($items)));
108 }
109
110 /**
111 * Execute a callback over each item.
112 *
113 * @param \Closure $callback
114 * @return $this
115 */
116 public function each(Closure $callback)
117 {
118 array_map($callback, $this->items);
119
120 return $this;
121 }
122
123 /**
124 * Fetch a nested element of the collection.
125 *
126 * @param string $key
127 * @return static
128 */
129 public function fetch($key)
130 {
131 return new static(Arr::fetch($this->items, $key));
132 }
133
134 /**
135 * Run a filter over each of the items.
136 *
137 * @param \Closure $callback
138 * @return static
139 */
140 public function filter(Closure $callback)
141 {
142 return new static(array_filter($this->items, $callback));
143 }
144
145 /**
146 * Get the first item from the collection.
147 *
148 * @param \Closure $callback
149 * @param mixed $default
150 * @return mixed|null
151 */
152 public function first(?Closure $callback = null, $default = null)
153 {
154 if (is_null($callback))
155 {
156 return count($this->items) > 0 ? reset($this->items) : null;
157 }
158
159 return Arr::first($this->items, $callback, $default);
160 }
161
162 /**
163 * Get a flattened array of the items in the collection.
164 *
165 * @return static
166 */
167 public function flatten()
168 {
169 return new static(Arr::flatten($this->items));
170 }
171
172 /**
173 * Flip the items in the collection.
174 *
175 * @return static
176 */
177 public function flip()
178 {
179 return new static(array_flip($this->items));
180 }
181
182 /**
183 * Remove an item from the collection by key.
184 *
185 * @param mixed $key
186 * @return void
187 */
188 public function forget($key)
189 {
190 unset($this->items[$key]);
191 }
192
193 /**
194 * Get an item from the collection by key.
195 *
196 * @param mixed $key
197 * @param mixed $default
198 * @return mixed
199 */
200 public function get($key, $default = null)
201 {
202 if ($this->offsetExists($key))
203 {
204 return $this->items[$key];
205 }
206
207 return Arr::value($default);
208 }
209
210 /**
211 * Group an associative array by a field or Closure value.
212 *
213 * @param callable|string $groupBy
214 * @return static
215 */
216 public function groupBy($groupBy)
217 {
218 $results = array();
219
220 foreach ($this->items as $key => $value)
221 {
222 $results[$this->getGroupByKey($groupBy, $key, $value)][] = $value;
223 }
224
225 return new static($results);
226 }
227
228 /**
229 * Get the "group by" key value.
230 *
231 * @param callable|string $groupBy
232 * @param string $key
233 * @param mixed $value
234 * @return string
235 */
236 protected function getGroupByKey($groupBy, $key, $value)
237 {
238 if ( ! is_string($groupBy) && is_callable($groupBy))
239 {
240 return $groupBy($value, $key);
241 }
242
243 return Arr::getItem($value, $groupBy);
244 }
245
246 /**
247 * Key an associative array by a field.
248 *
249 * @param string $keyBy
250 * @return static
251 */
252 public function keyBy($keyBy)
253 {
254 $results = [];
255
256 foreach ($this->items as $item)
257 {
258 $key = Arr::getItem($item, $keyBy);
259
260 $results[$key] = $item;
261 }
262
263 return new static($results);
264 }
265
266 /**
267 * Determine if an item exists in the collection by key.
268 *
269 * @param mixed $key
270 * @return bool
271 */
272 public function has($key)
273 {
274 return $this->offsetExists($key);
275 }
276
277 /**
278 * Concatenate values of a given key as a string.
279 *
280 * @param string $value
281 * @param string $glue
282 * @return string
283 */
284 public function implode($value, $glue = null)
285 {
286 return implode($glue, $this->lists($value));
287 }
288
289 /**
290 * Intersect the collection with the given items.
291 *
292 * @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
293 * @return static
294 */
295 public function intersect($items)
296 {
297 return new static(array_intersect($this->items, $this->getArrayableItems($items)));
298 }
299
300 /**
301 * Determine if the collection is empty or not.
302 *
303 * @return bool
304 */
305 public function isEmpty()
306 {
307 return empty($this->items);
308 }
309
310 /**
311 * Get the keys of the collection items.
312 *
313 * @return array
314 */
315 public function keys()
316 {
317 return array_keys($this->items);
318 }
319
320 /**
321 * Get the last item from the collection.
322 *
323 * @return mixed|null
324 */
325 public function last()
326 {
327 return count($this->items) > 0 ? end($this->items) : null;
328 }
329
330 /**
331 * Get an array with the values of a given key.
332 *
333 * @param string $value
334 * @param string $key
335 * @return array
336 */
337 public function lists($value, $key = null)
338 {
339 return Arr::pluck($this->items, $value, $key);
340 }
341
342 /**
343 * Run a map over each of the items.
344 *
345 * @param \Closure $callback
346 * @return static
347 */
348 public function map(Closure $callback)
349 {
350 return new static(array_map($callback, $this->items, array_keys($this->items)));
351 }
352
353 /**
354 * Merge the collection with the given items.
355 *
356 * @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
357 * @return static
358 */
359 public function merge($items)
360 {
361 return new static(array_merge($this->items, $this->getArrayableItems($items)));
362 }
363
364 /**
365 * Get and remove the last item from the collection.
366 *
367 * @return mixed|null
368 */
369 public function pop()
370 {
371 return array_pop($this->items);
372 }
373
374 /**
375 * Push an item onto the beginning of the collection.
376 *
377 * @param mixed $value
378 * @return void
379 */
380 public function prepend($value)
381 {
382 array_unshift($this->items, $value);
383 }
384
385 /**
386 * Push an item onto the end of the collection.
387 *
388 * @param mixed $value
389 * @return void
390 */
391 public function push($value)
392 {
393 $this->items[] = $value;
394 }
395
396 /**
397 * Pulls an item from the collection.
398 *
399 * @param mixed $key
400 * @param mixed $default
401 * @return mixed
402 */
403 public function pull($key, $default = null)
404 {
405 return Arr::pull($this->items, $key, $default);
406 }
407
408 /**
409 * Put an item in the collection by key.
410 *
411 * @param mixed $key
412 * @param mixed $value
413 * @return void
414 */
415 public function put($key, $value)
416 {
417 $this->items[$key] = $value;
418 }
419
420 /**
421 * Get one or more items randomly from the collection.
422 *
423 * @param int $amount
424 * @return mixed
425 */
426 public function random($amount = 1)
427 {
428 if ($this->isEmpty()) return null;
429
430 $keys = array_rand($this->items, $amount);
431
432 return is_array($keys) ? array_intersect_key($this->items, array_flip($keys)) : $this->items[$keys];
433 }
434
435 /**
436 * Reduce the collection to a single value.
437 *
438 * @param callable $callback
439 * @param mixed $initial
440 * @return mixed
441 */
442 public function reduce(callable $callback, $initial = null)
443 {
444 return array_reduce($this->items, $callback, $initial);
445 }
446
447 /**
448 * Create a collection of all elements that do not pass a given truth test.
449 *
450 * @param \Closure|mixed $callback
451 * @return static
452 */
453 public function reject($callback)
454 {
455 if ($callback instanceof Closure)
456 {
457 return $this->filter(function($item) use ($callback)
458 {
459 return ! $callback($item);
460 });
461 }
462
463 return $this->filter(function($item) use ($callback)
464 {
465 return $item != $callback;
466 });
467 }
468
469 /**
470 * Reverse items order.
471 *
472 * @return static
473 */
474 public function reverse()
475 {
476 return new static(array_reverse($this->items));
477 }
478
479 /**
480 * Search the collection for a given value and return the corresponding key if successful.
481 *
482 * @param mixed $value
483 * @param bool $strict
484 * @return mixed
485 */
486 public function search($value, $strict = false)
487 {
488 return array_search($value, $this->items, $strict);
489 }
490
491 /**
492 * Get and remove the first item from the collection.
493 *
494 * @return mixed|null
495 */
496 public function shift()
497 {
498 return array_shift($this->items);
499 }
500
501 /**
502 * Shuffle the items in the collection.
503 *
504 * @return $this
505 */
506 public function shuffle()
507 {
508 shuffle($this->items);
509
510 return $this;
511 }
512
513 /**
514 * Slice the underlying collection array.
515 *
516 * @param int $offset
517 * @param int $length
518 * @param bool $preserveKeys
519 * @return static
520 */
521 public function slice($offset, $length = null, $preserveKeys = false)
522 {
523 return new static(array_slice($this->items, $offset, $length, $preserveKeys));
524 }
525
526 /**
527 * Chunk the underlying collection array.
528 *
529 * @param int $size
530 * @param bool $preserveKeys
531 * @return static
532 */
533 public function chunk($size, $preserveKeys = false)
534 {
535 $chunks = new static;
536
537 foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk)
538 {
539 $chunks->push(new static($chunk));
540 }
541
542 return $chunks;
543 }
544
545 /**
546 * Sort through each item with a callback.
547 *
548 * @param \Closure $callback
549 * @return $this
550 */
551 public function sort(Closure $callback)
552 {
553 uasort($this->items, $callback);
554
555 return $this;
556 }
557
558 /**
559 * Sort the collection using the given Closure.
560 *
561 * @param \Closure|string $callback
562 * @param int $options
563 * @param bool $descending
564 * @return $this
565 */
566 public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
567 {
568 $results = array();
569
570 if (is_string($callback)) $callback =
571 $this->valueRetriever($callback);
572
573 // First we will loop through the items and get the comparator from a callback
574 // function which we were given. Then, we will sort the returned values and
575 // and grab the corresponding values for the sorted keys from this array.
576 foreach ($this->items as $key => $value)
577 {
578 $results[$key] = $callback($value);
579 }
580
581 $descending ? arsort($results, $options)
582 : asort($results, $options);
583
584 // Once we have sorted all of the keys in the array, we will loop through them
585 // and grab the corresponding model so we can set the underlying items list
586 // to the sorted version. Then we'll just return the collection instance.
587 foreach (array_keys($results) as $key)
588 {
589 $results[$key] = $this->items[$key];
590 }
591
592 $this->items = $results;
593
594 return $this;
595 }
596
597 /**
598 * Sort the collection in descending order using the given Closure.
599 *
600 * @param \Closure|string $callback
601 * @param int $options
602 * @return $this
603 */
604 public function sortByDesc($callback, $options = SORT_REGULAR)
605 {
606 return $this->sortBy($callback, $options, true);
607 }
608
609 /**
610 * Splice portion of the underlying collection array.
611 *
612 * @param int $offset
613 * @param int $length
614 * @param mixed $replacement
615 * @return static
616 */
617 public function splice($offset, $length = 0, $replacement = array())
618 {
619 return new static(array_splice($this->items, $offset, $length, $replacement));
620 }
621
622 /**
623 * Get the sum of the given values.
624 *
625 * @param \Closure $callback
626 * @return mixed
627 */
628 public function sum($callback = null)
629 {
630 if (is_null($callback))
631 {
632 return array_sum($this->items);
633 }
634
635 if (is_string($callback))
636 {
637 $callback = $this->valueRetriever($callback);
638 }
639
640 return $this->reduce(function($result, $item) use ($callback)
641 {
642 return $result += $callback($item);
643
644 }, 0);
645 }
646
647 /**
648 * Take the first or last {$limit} items.
649 *
650 * @param int $limit
651 * @return static
652 */
653 public function take($limit = null)
654 {
655 if ($limit < 0) return $this->slice($limit, abs($limit));
656
657 return $this->slice(0, $limit);
658 }
659
660 /**
661 * Transform each item in the collection using a callback.
662 *
663 * @param \Closure $callback
664 * @return $this
665 */
666 public function transform(Closure $callback)
667 {
668 $this->items = array_map($callback, $this->items);
669
670 return $this;
671 }
672
673 /**
674 * Return only unique items from the collection array.
675 *
676 * @return static
677 */
678 public function unique()
679 {
680 return new static(array_unique($this->items));
681 }
682
683 /**
684 * Reset the keys on the underlying array.
685 *
686 * @return static
687 */
688 public function values()
689 {
690 $this->items = array_values($this->items);
691
692 return $this;
693 }
694
695 /**
696 * Get a value retrieving callback.
697 *
698 * @param string $value
699 * @return \Closure
700 */
701 protected function valueRetriever($value)
702 {
703 return function($item) use ($value)
704 {
705 return Arr::getItem($item, $value);
706 };
707 }
708
709 /**
710 * Get the collection of items as a plain array.
711 *
712 * @return array
713 */
714 public function toArray()
715 {
716 return array_map(function($value) {
717 return $value instanceof ArrayableInterface ? $value->toArray() : $value;
718 }, $this->items);
719 }
720
721 /**
722 * Convert the object into something JSON serializable.
723 *
724 * @return array
725 */
726 public function jsonSerialize(): array
727 {
728 return $this->toArray();
729 }
730
731 /**
732 * Get the collection of items as JSON.
733 *
734 * @param int $options
735 * @return string
736 */
737 public function toJson($options = 0)
738 {
739 return json_encode($this->toArray(), $options);
740 }
741
742 /**
743 * Get an iterator for the items.
744 *
745 * @return \ArrayIterator
746 */
747 public function getIterator(): ArrayIterator
748 {
749 return new ArrayIterator($this->items);
750 }
751
752 /**
753 * Get a CachingIterator instance.
754 *
755 * @param int $flags
756 * @return \CachingIterator
757 */
758 public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
759 {
760 return new CachingIterator($this->getIterator(), $flags);
761 }
762
763 /**
764 * Count the number of items in the collection.
765 *
766 * @return int
767 */
768 public function count(): int
769 {
770 return count($this->items);
771 }
772
773 /**
774 * Determine if an item exists at an offset.
775 *
776 * @param mixed $key
777 * @return bool
778 */
779 public function offsetExists($key): bool
780 {
781 return array_key_exists($key, $this->items);
782 }
783
784 /**
785 * Get an item at a given offset.
786 *
787 * @param mixed $key
788 * @return mixed
789 */
790 #[\ReturnTypeWillChange]
791 public function offsetGet($key)
792 {
793 return $this->items[$key];
794 }
795
796 /**
797 * Set the item at a given offset.
798 *
799 * @param mixed $key
800 * @param mixed $value
801 * @return void
802 */
803 public function offsetSet($key, $value): void
804 {
805 if (is_null($key))
806 {
807 $this->items[] = $value;
808 }
809 else
810 {
811 $this->items[$key] = $value;
812 }
813 }
814
815 /**
816 * Unset the item at a given offset.
817 *
818 * @param string $key
819 * @return void
820 */
821 public function offsetUnset($key): void
822 {
823 unset($this->items[$key]);
824 }
825
826 /**
827 * Convert the collection to its string representation.
828 *
829 * @return string
830 */
831 public function __toString()
832 {
833 return $this->toJson();
834 }
835
836 /**
837 * Results array of items from Collection or ArrayableInterface.
838 *
839 * @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
840 * @return array
841 */
842 protected function getArrayableItems($items)
843 {
844 if ($items instanceof Collection)
845 {
846 $items = $items->all();
847 }
848 elseif ($items instanceof ArrayableInterface)
849 {
850 $items = $items->toArray();
851 }
852
853 return $items;
854 }
855 }
856