balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

collection.php (7693B)


      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 callable|null $callback
     31 	 *
     32 	 * @return $this
     33 	 */
     34 	public function filter( callable $callback = null ) {
     35 		if ( ! $callback ) {
     36 			return new static( array_filter( $this->items ) );
     37 		}
     38 
     39 		return new static( array_filter( $this->items, $callback, ARRAY_FILTER_USE_BOTH ) );
     40 	}
     41 
     42 	/**
     43 	 * @param $items
     44 	 *
     45 	 * @return $this
     46 	 */
     47 	public function merge( $items ) {
     48 		if ( $items instanceof Collection ) {
     49 			$items = $items->all();
     50 		}
     51 
     52 		return new static( array_merge( $this->items, $items ) );
     53 	}
     54 
     55 	/**
     56 	 * Union the collection with the given items.
     57 	 *
     58 	 * @param array $items
     59 	 *
     60 	 * @return $this
     61 	 */
     62 	public function union( array $items ) {
     63 		return new static( $this->all() + $items );
     64 	}
     65 
     66 	/**
     67 	 * Merge array recursively
     68 	 *
     69 	 * @param $items
     70 	 *
     71 	 * @return $this
     72 	 */
     73 	public function merge_recursive( $items ) {
     74 		if ( $items instanceof Collection ) {
     75 			$items = $items->all();
     76 		}
     77 
     78 		return new static( array_merge_recursive( $this->items, $items ) );
     79 	}
     80 
     81 	/**
     82 	 * Replace array recursively
     83 	 *
     84 	 * @param $items
     85 	 *
     86 	 * @return $this
     87 	 */
     88 	public function replace_recursive( $items ) {
     89 		if ( $items instanceof Collection ) {
     90 			$items = $items->all();
     91 		}
     92 
     93 		return new static( array_replace_recursive( $this->items, $items ) );
     94 	}
     95 
     96 	/**
     97 	 * Implode the items
     98 	 *
     99 	 * @param $glue
    100 	 *
    101 	 * @return string
    102 	 */
    103 	public function implode( $glue ) {
    104 		return implode( $glue, $this->items );
    105 	}
    106 
    107 	/**
    108 	 * Run a map over each of the items.
    109 	 *
    110 	 * @param  callable  $callback
    111 	 * @return $this
    112 	 */
    113 	public function map( callable $callback ) {
    114 		$keys = array_keys( $this->items );
    115 
    116 		$items = array_map( $callback, $this->items, $keys );
    117 
    118 		return new static( array_combine( $keys, $items ) );
    119 	}
    120 
    121 	/**
    122 	 * @param callable $callback
    123 	 * @param null     $initial
    124 	 *
    125 	 * @return mixed|null
    126 	 */
    127 	public function reduce( callable $callback, $initial = null ) {
    128 		$result = $initial;
    129 
    130 		foreach ( $this->all() as $key => $value ) {
    131 			$result = $callback( $result, $value, $key );
    132 		}
    133 
    134 		return $result;
    135 	}
    136 
    137 	/**
    138 	 * @param callable $callback
    139 	 *
    140 	 * @return $this
    141 	 */
    142 	public function map_with_keys( callable $callback ) {
    143 		$result = [];
    144 
    145 		foreach ( $this->items as $key => $value ) {
    146 			$assoc = $callback( $value, $key );
    147 
    148 			foreach ( $assoc as $map_key => $map_value ) {
    149 				$result[ $map_key ] = $map_value;
    150 			}
    151 		}
    152 
    153 		return new static( $result );
    154 	}
    155 
    156 	/**
    157 	 * Get all items except for those with the specified keys.
    158 	 *
    159 	 * @param array $keys
    160 	 *
    161 	 * @return $this
    162 	 */
    163 	public function except( array $keys ) {
    164 		return $this->filter( function ( $value, $key ) use ( $keys ) {
    165 			return ! in_array( $key, $keys, true );
    166 		} );
    167 	}
    168 
    169 	/**
    170 	 * Get the items with the specified keys.
    171 	 *
    172 	 * @param array $keys
    173 	 *
    174 	 * @return $this
    175 	 */
    176 	public function only( array $keys ) {
    177 		return $this->filter( function ( $value, $key ) use ( $keys ) {
    178 			return in_array( $key, $keys, true );
    179 		} );
    180 	}
    181 
    182 	/**
    183 	 * Run over the collection to get specific prop from the collection item.
    184 	 *
    185 	 * @param $key
    186 	 *
    187 	 * @return $this
    188 	 */
    189 	public function pluck( $key ) {
    190 		$result = [];
    191 
    192 		foreach ( $this->items as $item ) {
    193 			$result[] = $this->get_item_value( $item, $key );
    194 		}
    195 
    196 		return new static( $result );
    197 	}
    198 
    199 	/**
    200 	 * Group the collection items by specific key in each collection item.
    201 	 *
    202 	 * @param $group_by
    203 	 *
    204 	 * @return $this
    205 	 */
    206 	public function group_by( $group_by ) {
    207 		$result = [];
    208 
    209 		foreach ( $this->items as $item ) {
    210 			$group_key = $this->get_item_value( $item, $group_by, 0 );
    211 
    212 			$result[ $group_key ][] = $item;
    213 		}
    214 
    215 		return new static( $result );
    216 	}
    217 
    218 	/**
    219 	 * Sort keys
    220 	 *
    221 	 * @param false $descending
    222 	 *
    223 	 * @return $this
    224 	 */
    225 	public function sort_keys( $descending = false ) {
    226 		$items = $this->items;
    227 
    228 		if ( $descending ) {
    229 			krsort( $items );
    230 		} else {
    231 			ksort( $items );
    232 		}
    233 
    234 		return new static( $items );
    235 	}
    236 
    237 	/**
    238 	 * Get specific item from the collection.
    239 	 *
    240 	 * @param      $key
    241 	 * @param null $default
    242 	 *
    243 	 * @return mixed|null
    244 	 */
    245 	public function get( $key, $default = null ) {
    246 		if ( ! array_key_exists( $key, $this->items ) ) {
    247 			return $default;
    248 		}
    249 
    250 		return $this->items[ $key ];
    251 	}
    252 
    253 	/**
    254 	 * Get the first item.
    255 	 *
    256 	 * @param null $default
    257 	 *
    258 	 * @return mixed|null
    259 	 */
    260 	public function first( $default = null ) {
    261 		if ( $this->is_empty() ) {
    262 			return $default;
    263 		}
    264 
    265 		foreach ( $this->items as $item ) {
    266 			return $item;
    267 		}
    268 	}
    269 
    270 	/**
    271 	 * Find an element from the items.
    272 	 *
    273 	 * @param callable $callback
    274 	 * @param null     $default
    275 	 *
    276 	 * @return mixed|null
    277 	 */
    278 	public function find( callable $callback, $default = null ) {
    279 		foreach ( $this->all() as $key => $item ) {
    280 			if ( $callback( $item, $key ) ) {
    281 				return $item;
    282 			}
    283 		}
    284 
    285 		return $default;
    286 	}
    287 
    288 	/**
    289 	 * Make sure all the values inside the array are uniques.
    290 	 *
    291 	 * @param null|string|string[] $keys
    292 	 *
    293 	 * @return $this
    294 	 */
    295 	public function unique( $keys = null ) {
    296 		if ( ! $keys ) {
    297 			return new static(
    298 				array_unique( $this->items )
    299 			);
    300 		}
    301 
    302 		if ( ! is_array( $keys ) ) {
    303 			$keys = [ $keys ];
    304 		}
    305 
    306 		$exists = [];
    307 
    308 		return $this->filter( function ( $item ) use ( $keys, &$exists ) {
    309 			$value = null;
    310 
    311 			foreach ( $keys as $key ) {
    312 				$current_value = $this->get_item_value( $item, $key );
    313 
    314 				$value .= "{$key}:{$current_value};";
    315 			}
    316 
    317 			// If no value for the specific key return the item.
    318 			if ( null === $value ) {
    319 				return true;
    320 			}
    321 
    322 			// If value is not exists, add to the exists array and return the item.
    323 			if ( ! in_array( $value, $exists, true ) ) {
    324 				$exists[] = $value;
    325 
    326 				return true;
    327 			}
    328 
    329 			return false;
    330 		} );
    331 	}
    332 
    333 	/**
    334 	 * @return array
    335 	 */
    336 	public function keys() {
    337 		return array_keys( $this->items );
    338 	}
    339 
    340 	/**
    341 	 * @return bool
    342 	 */
    343 	public function is_empty() {
    344 		return empty( $this->items );
    345 	}
    346 
    347 	/**
    348 	 * @return array
    349 	 */
    350 	public function all() {
    351 		return $this->items;
    352 	}
    353 
    354 	/**
    355 	 * @return array
    356 	 */
    357 	public function values() {
    358 		return array_values( $this->all() );
    359 	}
    360 
    361 	/**
    362 	 * @param mixed $key
    363 	 *
    364 	 * @return bool
    365 	 */
    366 	public function offsetExists( $key ) {
    367 		return isset( $this->items[ $key ] );
    368 	}
    369 
    370 	/**
    371 	 * @param mixed $key
    372 	 *
    373 	 * @return mixed
    374 	 */
    375 	public function offsetGet( $key ) {
    376 		return $this->items[ $key ];
    377 	}
    378 
    379 	/**
    380 	 * @param mixed $key
    381 	 * @param mixed $value
    382 	 */
    383 	public function offsetSet( $key, $value ) {
    384 		if ( is_null( $key ) ) {
    385 			$this->items[] = $value;
    386 		} else {
    387 			$this->items[ $key ] = $value;
    388 		}
    389 	}
    390 
    391 	/**
    392 	 * @param mixed $key
    393 	 */
    394 	public function offsetUnset( $key ) {
    395 		unset( $this->items[ $key ] );
    396 	}
    397 
    398 	/**
    399 	 * @return \ArrayIterator|\Traversable
    400 	 */
    401 	public function getIterator() {
    402 		return new \ArrayIterator( $this->items );
    403 	}
    404 
    405 	/**
    406 	 * @return int|void
    407 	 */
    408 	public function count() {
    409 		return count( $this->items );
    410 	}
    411 
    412 	/**
    413 	 * @param      $item
    414 	 * @param      $key
    415 	 * @param null $default
    416 	 *
    417 	 * @return mixed|null
    418 	 */
    419 	private function get_item_value( $item, $key, $default = null ) {
    420 		$value = $default;
    421 
    422 		if ( is_object( $item ) && isset( $item->{$key} ) ) {
    423 			$value = $item->{$key};
    424 		} elseif ( is_array( $item ) && isset( $item[ $key ] ) ) {
    425 			$value = $item[ $key ];
    426 		}
    427 
    428 		return $value;
    429 	}
    430 }