PluginProbe
Elementor Website Builder – more than just a page builder / 3.28.0-beta1
Elementor Website Builder – more than just a page builder v3.28.0-beta1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / utils / collection.php

collection.php in Elementor Website Builder – more than just a page builder 3.28.0-beta1, at core/utils/collection.php

560 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Inspired by Laravel Collection.
4 *
5 * @link https://github.com/illuminate/collections
6 * @package Elementor\Core\Utils
7 */
8
9 namespace Elementor\Core\Utils;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly.
13 }
14
15 /**
16 * Inspired by Laravel Collection.
17 *
18 * @link https://github.com/illuminate/collections
19 */
20 class Collection implements \ArrayAccess, \Countable, \IteratorAggregate {
21 /**
22 * The items contained in the collection.
23 *
24 * @var array
25 */
26 protected $items;
27
28 /**
29 * Collection constructor.
30 *
31 * @param array $items
32 */
33 public function __construct( array $items = [] ) {
34 $this->items = $items;
35 }
36
37 /**
38 * @param array $items
39 *
40 * @return static
41 */
42 public static function make( array $items = [] ) {
43 return new static( $items );
44 }
45
46 /**
47 * @param callable|null $callback
48 *
49 * @return $this
50 */
51 public function filter( callable $callback = null ) {
52 if ( ! $callback ) {
53 return new static( array_filter( $this->items ) );
54 }
55
56 return new static( array_filter( $this->items, $callback, ARRAY_FILTER_USE_BOTH ) );
57 }
58
59 /**
60 * @param $items
61 *
62 * @return $this
63 */
64 public function merge( $items ) {
65 if ( $items instanceof Collection ) {
66 $items = $items->all();
67 }
68
69 return new static( array_merge( $this->items, $items ) );
70 }
71
72 /**
73 * Union the collection with the given items.
74 *
75 * @param array $items
76 *
77 * @return $this
78 */
79 public function union( array $items ) {
80 return new static( $this->all() + $items );
81 }
82
83 /**
84 * Merge array recursively
85 *
86 * @param $items
87 *
88 * @return $this
89 */
90 public function merge_recursive( $items ) {
91 if ( $items instanceof Collection ) {
92 $items = $items->all();
93 }
94
95 return new static( array_merge_recursive( $this->items, $items ) );
96 }
97
98 /**
99 * Replace array recursively
100 *
101 * @param $items
102 *
103 * @return $this
104 */
105 public function replace_recursive( $items ) {
106 if ( $items instanceof Collection ) {
107 $items = $items->all();
108 }
109
110 return new static( array_replace_recursive( $this->items, $items ) );
111 }
112
113 /**
114 * Implode the items
115 *
116 * @param $glue
117 *
118 * @return string
119 */
120 public function implode( $glue ) {
121 return implode( $glue, $this->items );
122 }
123
124 /**
125 * Run a map over each of the items.
126 *
127 * @param callable $callback
128 * @return $this
129 */
130 public function map( callable $callback ) {
131 $keys = array_keys( $this->items );
132
133 $items = array_map( $callback, $this->items, $keys );
134
135 return new static( array_combine( $keys, $items ) );
136 }
137
138 /**
139 * Run a callback over each of the items.
140 *
141 * @param callable $callback
142 * @return $this
143 */
144 public function each( callable $callback ) {
145 foreach ( $this->items as $key => $value ) {
146 if ( false === $callback( $value, $key ) ) {
147 break;
148 }
149 }
150
151 return $this;
152 }
153
154 /**
155 * @param callable $callback
156 * @param null $initial
157 *
158 * @return mixed|null
159 */
160 public function reduce( callable $callback, $initial = null ) {
161 $result = $initial;
162
163 foreach ( $this->all() as $key => $value ) {
164 $result = $callback( $result, $value, $key );
165 }
166
167 return $result;
168 }
169
170 /**
171 * @param callable $callback
172 *
173 * @return $this
174 */
175 public function map_with_keys( callable $callback ) {
176 $result = [];
177
178 foreach ( $this->items as $key => $value ) {
179 $assoc = $callback( $value, $key );
180
181 foreach ( $assoc as $map_key => $map_value ) {
182 $result[ $map_key ] = $map_value;
183 }
184 }
185
186 return new static( $result );
187 }
188
189 /**
190 * Get all items except for those with the specified keys.
191 *
192 * @param array $keys
193 *
194 * @return $this
195 */
196 public function except( array $keys ) {
197 return $this->filter( function ( $value, $key ) use ( $keys ) {
198 return ! in_array( $key, $keys, true );
199 } );
200 }
201
202 /**
203 * Get the items with the specified keys.
204 *
205 * @param array $keys
206 *
207 * @return $this
208 */
209 public function only( array $keys ) {
210 return $this->filter( function ( $value, $key ) use ( $keys ) {
211 return in_array( $key, $keys, true );
212 } );
213 }
214
215 /**
216 * Run over the collection to get specific prop from the collection item.
217 *
218 * @param $key
219 *
220 * @return $this
221 */
222 public function pluck( $key ) {
223 $result = [];
224
225 foreach ( $this->items as $item ) {
226 $result[] = $this->get_item_value( $item, $key );
227 }
228
229 return new static( $result );
230 }
231
232 /**
233 * Group the collection items by specific key in each collection item.
234 *
235 * @param $group_by
236 *
237 * @return $this
238 */
239 public function group_by( $group_by ) {
240 $result = [];
241
242 foreach ( $this->items as $item ) {
243 $group_key = $this->get_item_value( $item, $group_by, 0 );
244
245 $result[ $group_key ][] = $item;
246 }
247
248 return new static( $result );
249 }
250
251 /**
252 * Sort keys
253 *
254 * @param false $descending
255 *
256 * @return $this
257 */
258 public function sort_keys( $descending = false ) {
259 $items = $this->items;
260
261 if ( $descending ) {
262 krsort( $items );
263 } else {
264 ksort( $items );
265 }
266
267 return new static( $items );
268 }
269
270 /**
271 * Get specific item from the collection.
272 *
273 * @param $key
274 * @param null $default
275 *
276 * @return mixed|null
277 */
278 public function get( $key, $default = null ) {
279 if ( ! array_key_exists( $key, $this->items ) ) {
280 return $default;
281 }
282
283 return $this->items[ $key ];
284 }
285
286 /**
287 * Get the first item.
288 *
289 * @param null $default
290 *
291 * @return mixed|null
292 */
293 public function first( $default = null ) {
294 if ( $this->is_empty() ) {
295 return $default;
296 }
297
298 foreach ( $this->items as $item ) {
299 return $item;
300 }
301 }
302
303 /**
304 * Find an element from the items.
305 *
306 * @param callable $callback
307 * @param null $default
308 *
309 * @return mixed|null
310 */
311 public function find( callable $callback, $default = null ) {
312 foreach ( $this->all() as $key => $item ) {
313 if ( $callback( $item, $key ) ) {
314 return $item;
315 }
316 }
317
318 return $default;
319 }
320
321 /**
322 * @param callable|string|int $value
323 *
324 * @return bool
325 */
326 public function contains( $value ) {
327 $callback = $value instanceof \Closure
328 ? $value
329 : function ( $item ) use ( $value ) {
330 return $item === $value;
331 };
332
333 foreach ( $this->all() as $key => $item ) {
334 if ( $callback( $item, $key ) ) {
335 return true;
336 }
337 }
338
339 return false;
340 }
341
342 /**
343 * Run array_diff between the collection and other array or collection.
344 *
345 * @param $filter
346 *
347 * @return $this
348 */
349 public function diff( $filter ) {
350 if ( $filter instanceof self ) {
351 $filter = $filter->all();
352 }
353
354 return new static( array_diff( $this->all(), $filter ) );
355 }
356
357 /**
358 * Make sure all the values inside the array are uniques.
359 *
360 * @param null|string|string[] $keys
361 *
362 * @return $this
363 */
364 public function unique( $keys = null ) {
365 if ( ! $keys ) {
366 return new static(
367 array_unique( $this->items )
368 );
369 }
370
371 if ( ! is_array( $keys ) ) {
372 $keys = [ $keys ];
373 }
374
375 $exists = [];
376
377 return $this->filter( function ( $item ) use ( $keys, &$exists ) {
378 $value = null;
379
380 foreach ( $keys as $key ) {
381 $current_value = $this->get_item_value( $item, $key );
382
383 $value .= "{$key}:{$current_value};";
384 }
385
386 // If no value for the specific key return the item.
387 if ( null === $value ) {
388 return true;
389 }
390
391 // If value is not exists, add to the exists array and return the item.
392 if ( ! in_array( $value, $exists, true ) ) {
393 $exists[] = $value;
394
395 return true;
396 }
397
398 return false;
399 } );
400 }
401
402 /**
403 * @return array
404 */
405 public function keys() {
406 return array_keys( $this->items );
407 }
408
409 /**
410 * @return bool
411 */
412 public function is_empty() {
413 return empty( $this->items );
414 }
415
416 /**
417 * @return array
418 */
419 public function all() {
420 return $this->items;
421 }
422
423 /**
424 * @return array
425 */
426 public function values() {
427 return array_values( $this->all() );
428 }
429
430 /**
431 * Support only one level depth.
432 *
433 * @return $this
434 */
435 public function flatten() {
436 $result = [];
437
438 foreach ( $this->all() as $item ) {
439 $item = $item instanceof Collection ? $item->all() : $item;
440
441 if ( ! is_array( $item ) ) {
442 $result[] = $item;
443 } else {
444 $values = array_values( $item );
445
446 foreach ( $values as $value ) {
447 $result[] = $value;
448 }
449 }
450 }
451
452 return new static( $result );
453 }
454
455 /**
456 * @param array ...$values
457 *
458 * @return $this
459 */
460 public function push( ...$values ) {
461 foreach ( $values as $value ) {
462 $this->items[] = $value;
463 }
464
465 return $this;
466 }
467
468 public function prepend( ...$values ) {
469 $this->items = array_merge( $values, $this->items );
470
471 return $this;
472 }
473
474 public function some( callable $callback ) {
475 foreach ( $this->items as $key => $item ) {
476 if ( $callback( $item, $key ) ) {
477 return true;
478 }
479 }
480
481 return false;
482 }
483
484 /**
485 * @param mixed $offset
486 *
487 * @return bool
488 */
489 #[\ReturnTypeWillChange]
490 public function offsetExists( $offset ) {
491 return isset( $this->items[ $offset ] );
492 }
493
494 /**
495 * @param mixed $offset
496 *
497 * @return mixed
498 */
499 #[\ReturnTypeWillChange]
500 public function offsetGet( $offset ) {
501 return $this->items[ $offset ];
502 }
503
504 /**
505 * @param mixed $offset
506 * @param mixed $value
507 */
508 #[\ReturnTypeWillChange]
509 public function offsetSet( $offset, $value ) {
510 if ( is_null( $offset ) ) {
511 $this->items[] = $value;
512 } else {
513 $this->items[ $offset ] = $value;
514 }
515 }
516
517 /**
518 * @param mixed $offset
519 */
520 #[\ReturnTypeWillChange]
521 public function offsetUnset( $offset ) {
522 unset( $this->items[ $offset ] );
523 }
524
525 /**
526 * @return \ArrayIterator|\Traversable
527 */
528 #[\ReturnTypeWillChange]
529 public function getIterator() {
530 return new \ArrayIterator( $this->items );
531 }
532
533 /**
534 * @return int|void
535 */
536 #[\ReturnTypeWillChange]
537 public function count() {
538 return count( $this->items );
539 }
540
541 /**
542 * @param $item
543 * @param $key
544 * @param null $default
545 *
546 * @return mixed|null
547 */
548 private function get_item_value( $item, $key, $default = null ) {
549 $value = $default;
550
551 if ( is_object( $item ) && isset( $item->{$key} ) ) {
552 $value = $item->{$key};
553 } elseif ( is_array( $item ) && isset( $item[ $key ] ) ) {
554 $value = $item[ $key ];
555 }
556
557 return $value;
558 }
559 }
560