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

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