PluginProbe
Elementor Website Builder – more than just a page builder / 4.2.1
Elementor Website Builder – more than just a page builder v4.2.1
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 4.2.1, at core/utils/collection.php

575 lines 10.1 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 public function reverse() {
171 return new static( array_reverse( $this->items ) );
172 }
173
174 /**
175 * @param callable $callback
176 *
177 * @return $this
178 */
179 public function map_with_keys( callable $callback ) {
180 $result = [];
181
182 foreach ( $this->items as $key => $value ) {
183 $assoc = $callback( $value, $key );
184
185 foreach ( $assoc as $map_key => $map_value ) {
186 $result[ $map_key ] = $map_value;
187 }
188 }
189
190 return new static( $result );
191 }
192
193 /**
194 * Get all items except for those with the specified keys.
195 *
196 * @param array $keys
197 *
198 * @return $this
199 */
200 public function except( array $keys ) {
201 return $this->filter( function ( $value, $key ) use ( $keys ) {
202 return ! in_array( $key, $keys, true );
203 } );
204 }
205
206 /**
207 * Get the items with the specified keys.
208 *
209 * @param array $keys
210 *
211 * @return $this
212 */
213 public function only( array $keys ) {
214 return $this->filter( function ( $value, $key ) use ( $keys ) {
215 return in_array( $key, $keys, true );
216 } );
217 }
218
219 /**
220 * Run over the collection to get specific prop from the collection item.
221 *
222 * @param $key
223 *
224 * @return $this
225 */
226 public function pluck( $key ) {
227 $result = [];
228
229 foreach ( $this->items as $item ) {
230 $result[] = $this->get_item_value( $item, $key );
231 }
232
233 return new static( $result );
234 }
235
236 /**
237 * Group the collection items by specific key in each collection item.
238 *
239 * @param $group_by
240 *
241 * @return $this
242 */
243 public function group_by( $group_by ) {
244 $result = [];
245
246 foreach ( $this->items as $item ) {
247 $group_key = $this->get_item_value( $item, $group_by, 0 );
248
249 $result[ $group_key ][] = $item;
250 }
251
252 return new static( $result );
253 }
254
255 /**
256 * Sort keys
257 *
258 * @param false $descending
259 *
260 * @return $this
261 */
262 public function sort_keys( $descending = false ) {
263 $items = $this->items;
264
265 if ( $descending ) {
266 krsort( $items );
267 } else {
268 ksort( $items );
269 }
270
271 return new static( $items );
272 }
273
274 /**
275 * Get specific item from the collection.
276 *
277 * @param $key
278 * @param null $fallback
279 *
280 * @return mixed|null
281 */
282 public function get( $key, $fallback = null ) {
283 if ( ! array_key_exists( $key, $this->items ) ) {
284 return $fallback;
285 }
286
287 return $this->items[ $key ];
288 }
289
290 /**
291 * Get the first item.
292 *
293 * @param null $fallback
294 *
295 * @return mixed|null
296 */
297 public function first( $fallback = null ) {
298 if ( $this->is_empty() ) {
299 return $fallback;
300 }
301
302 foreach ( $this->items as $item ) {
303 return $item;
304 }
305 }
306
307 /**
308 * Find an element from the items.
309 *
310 * @param callable $callback
311 * @param null $fallback
312 *
313 * @return mixed|null
314 */
315 public function find( callable $callback, $fallback = null ) {
316 foreach ( $this->all() as $key => $item ) {
317 if ( $callback( $item, $key ) ) {
318 return $item;
319 }
320 }
321
322 return $fallback;
323 }
324
325 /**
326 * @param callable|string|int $value
327 *
328 * @return bool
329 */
330 public function contains( $value ) {
331 $callback = $value instanceof \Closure
332 ? $value
333 : function ( $item ) use ( $value ) {
334 return $item === $value;
335 };
336
337 foreach ( $this->all() as $key => $item ) {
338 if ( $callback( $item, $key ) ) {
339 return true;
340 }
341 }
342
343 return false;
344 }
345
346 /**
347 * Run array_diff between the collection and other array or collection.
348 *
349 * @param $filter
350 *
351 * @return $this
352 */
353 public function diff( $filter ) {
354 if ( $filter instanceof self ) {
355 $filter = $filter->all();
356 }
357
358 return new static( array_diff( $this->all(), $filter ) );
359 }
360
361 /**
362 * Make sure all the values inside the array are uniques.
363 *
364 * @param null|string|string[] $keys
365 *
366 * @return $this
367 */
368 public function unique( $keys = null ) {
369 if ( ! $keys ) {
370 return new static(
371 array_unique( $this->items )
372 );
373 }
374
375 if ( ! is_array( $keys ) ) {
376 $keys = [ $keys ];
377 }
378
379 $exists = [];
380
381 return $this->filter( function ( $item ) use ( $keys, &$exists ) {
382 $value = null;
383
384 foreach ( $keys as $key ) {
385 $current_value = $this->get_item_value( $item, $key );
386
387 $value .= "{$key}:{$current_value};";
388 }
389
390 // If no value for the specific key return the item.
391 if ( null === $value ) {
392 return true;
393 }
394
395 // If value is not exists, add to the exists array and return the item.
396 if ( ! in_array( $value, $exists, true ) ) {
397 $exists[] = $value;
398
399 return true;
400 }
401
402 return false;
403 } );
404 }
405
406 public function keys() {
407 return new static( array_keys( $this->items ) );
408 }
409
410 /**
411 * @return bool
412 */
413 public function is_empty() {
414 return empty( $this->items );
415 }
416
417 /**
418 * @return array
419 */
420 public function all() {
421 return $this->items;
422 }
423
424 /**
425 * @return array
426 */
427 public function values() {
428 return array_values( $this->all() );
429 }
430
431 /**
432 * Support only one level depth.
433 *
434 * @return $this
435 */
436 public function flatten() {
437 $result = [];
438
439 foreach ( $this->all() as $item ) {
440 $item = $item instanceof Collection ? $item->all() : $item;
441
442 if ( ! is_array( $item ) ) {
443 $result[] = $item;
444 } else {
445 $values = array_values( $item );
446
447 foreach ( $values as $value ) {
448 $result[] = $value;
449 }
450 }
451 }
452
453 return new static( $result );
454 }
455
456 public function flip() {
457 return new static( array_flip( $this->items ) );
458 }
459
460 /**
461 * @param array ...$values
462 *
463 * @return $this
464 */
465 public function push( ...$values ) {
466 foreach ( $values as $value ) {
467 $this->items[] = $value;
468 }
469
470 return $this;
471 }
472
473 public function prepend( ...$values ) {
474 $this->items = array_merge( $values, $this->items );
475
476 return $this;
477 }
478
479 public function some( callable $callback ) {
480 foreach ( $this->items as $key => $item ) {
481 if ( $callback( $item, $key ) ) {
482 return true;
483 }
484 }
485
486 return false;
487 }
488
489 public function every( callable $callback ) {
490 foreach ( $this->items as $key => $item ) {
491 if ( ! $callback( $item, $key ) ) {
492 return false;
493 }
494 }
495
496 return true;
497 }
498
499 /**
500 * @param mixed $offset
501 *
502 * @return bool
503 */
504 #[\ReturnTypeWillChange]
505 public function offsetExists( $offset ) {
506 return isset( $this->items[ $offset ] );
507 }
508
509 /**
510 * @param mixed $offset
511 *
512 * @return mixed
513 */
514 #[\ReturnTypeWillChange]
515 public function offsetGet( $offset ) {
516 return $this->items[ $offset ];
517 }
518
519 /**
520 * @param mixed $offset
521 * @param mixed $value
522 */
523 #[\ReturnTypeWillChange]
524 public function offsetSet( $offset, $value ) {
525 if ( is_null( $offset ) ) {
526 $this->items[] = $value;
527 } else {
528 $this->items[ $offset ] = $value;
529 }
530 }
531
532 /**
533 * @param mixed $offset
534 */
535 #[\ReturnTypeWillChange]
536 public function offsetUnset( $offset ) {
537 unset( $this->items[ $offset ] );
538 }
539
540 /**
541 * @return \ArrayIterator|\Traversable
542 */
543 #[\ReturnTypeWillChange]
544 public function getIterator() {
545 return new \ArrayIterator( $this->items );
546 }
547
548 /**
549 * @return int|void
550 */
551 #[\ReturnTypeWillChange]
552 public function count() {
553 return count( $this->items );
554 }
555
556 /**
557 * @param $item
558 * @param $key
559 * @param null $fallback
560 *
561 * @return mixed|null
562 */
563 private function get_item_value( $item, $key, $fallback = null ) {
564 $value = $fallback;
565
566 if ( is_object( $item ) && isset( $item->{$key} ) ) {
567 $value = $item->{$key};
568 } elseif ( is_array( $item ) && isset( $item[ $key ] ) ) {
569 $value = $item[ $key ];
570 }
571
572 return $value;
573 }
574 }
575