| <?php |
| |
| namespace Tightenco\Collect\Support\Traits; |
| |
| use CachingIterator; |
| use Closure; |
| use Exception; |
| use Tightenco\Collect\Contracts\Support\Arrayable; |
| use Tightenco\Collect\Contracts\Support\Jsonable; |
| use Tightenco\Collect\Support\Arr; |
| use Tightenco\Collect\Support\Collection; |
| use Tightenco\Collect\Support\Enumerable; |
| use Tightenco\Collect\Support\HigherOrderCollectionProxy; |
| use Tightenco\Collect\Support\HigherOrderWhenProxy; |
| use JsonSerializable; |
| use Symfony\Component\VarDumper\VarDumper; |
| use Traversable; |
| |
| /** |
| * @property-read HigherOrderCollectionProxy $average |
| * @property-read HigherOrderCollectionProxy $avg |
| * @property-read HigherOrderCollectionProxy $contains |
| * @property-read HigherOrderCollectionProxy $each |
| * @property-read HigherOrderCollectionProxy $every |
| * @property-read HigherOrderCollectionProxy $filter |
| * @property-read HigherOrderCollectionProxy $first |
| * @property-read HigherOrderCollectionProxy $flatMap |
| * @property-read HigherOrderCollectionProxy $groupBy |
| * @property-read HigherOrderCollectionProxy $keyBy |
| * @property-read HigherOrderCollectionProxy $map |
| * @property-read HigherOrderCollectionProxy $max |
| * @property-read HigherOrderCollectionProxy $min |
| * @property-read HigherOrderCollectionProxy $partition |
| * @property-read HigherOrderCollectionProxy $reject |
| * @property-read HigherOrderCollectionProxy $some |
| * @property-read HigherOrderCollectionProxy $sortBy |
| * @property-read HigherOrderCollectionProxy $sortByDesc |
| * @property-read HigherOrderCollectionProxy $skipUntil |
| * @property-read HigherOrderCollectionProxy $skipWhile |
| * @property-read HigherOrderCollectionProxy $sum |
| * @property-read HigherOrderCollectionProxy $takeUntil |
| * @property-read HigherOrderCollectionProxy $takeWhile |
| * @property-read HigherOrderCollectionProxy $unique |
| * @property-read HigherOrderCollectionProxy $until |
| */ |
| trait EnumeratesValues |
| { |
| /** |
| * The methods that can be proxied. |
| * |
| * @var string[] |
| */ |
| protected static $proxies = [ |
| 'average', |
| 'avg', |
| 'contains', |
| 'each', |
| 'every', |
| 'filter', |
| 'first', |
| 'flatMap', |
| 'groupBy', |
| 'keyBy', |
| 'map', |
| 'max', |
| 'min', |
| 'partition', |
| 'reject', |
| 'skipUntil', |
| 'skipWhile', |
| 'some', |
| 'sortBy', |
| 'sortByDesc', |
| 'sum', |
| 'takeUntil', |
| 'takeWhile', |
| 'unique', |
| 'until', |
| ]; |
| |
| /** |
| * Create a new collection instance if the value isn't one already. |
| * |
| * @param mixed $items |
| * @return static |
| */ |
| public static function make($items = []) |
| { |
| return new static($items); |
| } |
| |
| /** |
| * Wrap the given value in a collection if applicable. |
| * |
| * @param mixed $value |
| * @return static |
| */ |
| public static function wrap($value) |
| { |
| return $value instanceof Enumerable |
| ? new static($value) |
| : new static(Arr::wrap($value)); |
| } |
| |
| /** |
| * Get the underlying items from the given collection if applicable. |
| * |
| * @param array|static $value |
| * @return array |
| */ |
| public static function unwrap($value) |
| { |
| return $value instanceof Enumerable ? $value->all() : $value; |
| } |
| |
| /** |
| * Create a new instance with no items. |
| * |
| * @return static |
| */ |
| public static function empty() |
| { |
| return new static([]); |
| } |
| |
| /** |
| * Create a new collection by invoking the callback a given amount of times. |
| * |
| * @param int $number |
| * @param callable|null $callback |
| * @return static |
| */ |
| public static function times($number, callable $callback = null) |
| { |
| if ($number < 1) { |
| return new static; |
| } |
| |
| return static::range(1, $number) |
| ->when($callback) |
| ->map($callback); |
| } |
| |
| /** |
| * Alias for the "avg" method. |
| * |
| * @param callable|string|null $callback |
| * @return mixed |
| */ |
| public function average($callback = null) |
| { |
| return $this->avg($callback); |
| } |
| |
| /** |
| * Alias for the "contains" method. |
| * |
| * @param mixed $key |
| * @param mixed $operator |
| * @param mixed $value |
| * @return bool |
| */ |
| public function some($key, $operator = null, $value = null) |
| { |
| return $this->contains(...func_get_args()); |
| } |
| |
| /** |
| * Determine if an item exists, using strict comparison. |
| * |
| * @param mixed $key |
| * @param mixed $value |
| * @return bool |
| */ |
| public function containsStrict($key, $value = null) |
| { |
| if (func_num_args() === 2) { |
| return $this->contains(function ($item) use ($key, $value) { |
| return data_get($item, $key) === $value; |
| }); |
| } |
| |
| if ($this->useAsCallable($key)) { |
| return ! is_null($this->first($key)); |
| } |
| |
| foreach ($this as $item) { |
| if ($item === $key) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Dump the items and end the script. |
| * |
| * @param mixed ...$args |
| * @return void |
| */ |
| public function dd(...$args) |
| { |
| $this->dump(...$args); |
| |
| exit(1); |
| } |
| |
| /** |
| * Dump the items. |
| * |
| * @return $this |
| */ |
| public function dump() |
| { |
| (new Collection(func_get_args())) |
| ->push($this->all()) |
| ->each(function ($item) { |
| VarDumper::dump($item); |
| }); |
| |
| return $this; |
| } |
| |
| /** |
| * Execute a callback over each item. |
| * |
| * @param callable $callback |
| * @return $this |
| */ |
| public function each(callable $callback) |
| { |
| foreach ($this as $key => $item) { |
| if ($callback($item, $key) === false) { |
| break; |
| } |
| } |
| |
| return $this; |
| } |
| |
| /** |
| * Execute a callback over each nested chunk of items. |
| * |
| * @param callable $callback |
| * @return static |
| */ |
| public function eachSpread(callable $callback) |
| { |
| return $this->each(function ($chunk, $key) use ($callback) { |
| $chunk[] = $key; |
| |
| return $callback(...$chunk); |
| }); |
| } |
| |
| /** |
| * Determine if all items pass the given truth test. |
| * |
| * @param string|callable $key |
| * @param mixed $operator |
| * @param mixed $value |
| * @return bool |
| */ |
| public function every($key, $operator = null, $value = null) |
| { |
| if (func_num_args() === 1) { |
| $callback = $this->valueRetriever($key); |
| |
| foreach ($this as $k => $v) { |
| if (! $callback($v, $k)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| return $this->every($this->operatorForWhere(...func_get_args())); |
| } |
| |
| /** |
| * Get the first item by the given key value pair. |
| * |
| * @param string $key |
| * @param mixed $operator |
| * @param mixed $value |
| * @return mixed |
| */ |
| public function firstWhere($key, $operator = null, $value = null) |
| { |
| return $this->first($this->operatorForWhere(...func_get_args())); |
| } |
| |
| /** |
| * Determine if the collection is not empty. |
| * |
| * @return bool |
| */ |
| public function isNotEmpty() |
| { |
| return ! $this->isEmpty(); |
| } |
| |
| /** |
| * Run a map over each nested chunk of items. |
| * |
| * @param callable $callback |
| * @return static |
| */ |
| public function mapSpread(callable $callback) |
| { |
| return $this->map(function ($chunk, $key) use ($callback) { |
| $chunk[] = $key; |
| |
| return $callback(...$chunk); |
| }); |
| } |
| |
| /** |
| * Run a grouping map over the items. |
| * |
| * The callback should return an associative array with a single key/value pair. |
| * |
| * @param callable $callback |
| * @return static |
| */ |
| public function mapToGroups(callable $callback) |
| { |
| $groups = $this->mapToDictionary($callback); |
| |
| return $groups->map([$this, 'make']); |
| } |
| |
| /** |
| * Map a collection and flatten the result by a single level. |
| * |
| * @param callable $callback |
| * @return static |
| */ |
| public function flatMap(callable $callback) |
| { |
| return $this->map($callback)->collapse(); |
| } |
| |
| /** |
| * Map the values into a new class. |
| * |
| * @param string $class |
| * @return static |
| */ |
| public function mapInto($class) |
| { |
| return $this->map(function ($value, $key) use ($class) { |
| return new $class($value, $key); |
| }); |
| } |
| |
| /** |
| * Get the min value of a given key. |
| * |
| * @param callable|string|null $callback |
| * @return mixed |
| */ |
| public function min($callback = null) |
| { |
| $callback = $this->valueRetriever($callback); |
| |
| return $this->map(function ($value) use ($callback) { |
| return $callback($value); |
| })->filter(function ($value) { |
| return ! is_null($value); |
| })->reduce(function ($result, $value) { |
| return is_null($result) || $value < $result ? $value : $result; |
| }); |
| } |
| |
| /** |
| * Get the max value of a given key. |
| * |
| * @param callable|string|null $callback |
| * @return mixed |
| */ |
| public function max($callback = null) |
| { |
| $callback = $this->valueRetriever($callback); |
| |
| return $this->filter(function ($value) { |
| return ! is_null($value); |
| })->reduce(function ($result, $item) use ($callback) { |
| $value = $callback($item); |
| |
| return is_null($result) || $value > $result ? $value : $result; |
| }); |
| } |
| |
| /** |
| * "Paginate" the collection by slicing it into a smaller collection. |
| * |
| * @param int $page |
| * @param int $perPage |
| * @return static |
| */ |
| public function forPage($page, $perPage) |
| { |
| $offset = max(0, ($page - 1) * $perPage); |
| |
| return $this->slice($offset, $perPage); |
| } |
| |
| /** |
| * Partition the collection into two arrays using the given callback or key. |
| * |
| * @param callable|string $key |
| * @param mixed $operator |
| * @param mixed $value |
| * @return static |
| */ |
| public function partition($key, $operator = null, $value = null) |
| { |
| $passed = []; |
| $failed = []; |
| |
| $callback = func_num_args() === 1 |
| ? $this->valueRetriever($key) |
| : $this->operatorForWhere(...func_get_args()); |
| |
| foreach ($this as $key => $item) { |
| if ($callback($item, $key)) { |
| $passed[$key] = $item; |
| } else { |
| $failed[$key] = $item; |
| } |
| } |
| |
| return new static([new static($passed), new static($failed)]); |
| } |
| |
| /** |
| * Get the sum of the given values. |
| * |
| * @param callable|string|null $callback |
| * @return mixed |
| */ |
| public function sum($callback = null) |
| { |
| $callback = is_null($callback) |
| ? $this->identity() |
| : $this->valueRetriever($callback); |
| |
| return $this->reduce(function ($result, $item) use ($callback) { |
| return $result + $callback($item); |
| }, 0); |
| } |
| |
| /** |
| * Apply the callback if the value is truthy. |
| * |
| * @param bool|mixed $value |
| * @param callable|null $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function when($value, callable $callback = null, callable $default = null) |
| { |
| if (! $callback) { |
| return new HigherOrderWhenProxy($this, $value); |
| } |
| |
| if ($value) { |
| return $callback($this, $value); |
| } elseif ($default) { |
| return $default($this, $value); |
| } |
| |
| return $this; |
| } |
| |
| /** |
| * Apply the callback if the collection is empty. |
| * |
| * @param callable $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function whenEmpty(callable $callback, callable $default = null) |
| { |
| return $this->when($this->isEmpty(), $callback, $default); |
| } |
| |
| /** |
| * Apply the callback if the collection is not empty. |
| * |
| * @param callable $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function whenNotEmpty(callable $callback, callable $default = null) |
| { |
| return $this->when($this->isNotEmpty(), $callback, $default); |
| } |
| |
| /** |
| * Apply the callback if the value is falsy. |
| * |
| * @param bool $value |
| * @param callable $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function unless($value, callable $callback, callable $default = null) |
| { |
| return $this->when(! $value, $callback, $default); |
| } |
| |
| /** |
| * Apply the callback unless the collection is empty. |
| * |
| * @param callable $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function unlessEmpty(callable $callback, callable $default = null) |
| { |
| return $this->whenNotEmpty($callback, $default); |
| } |
| |
| /** |
| * Apply the callback unless the collection is not empty. |
| * |
| * @param callable $callback |
| * @param callable|null $default |
| * @return static|mixed |
| */ |
| public function unlessNotEmpty(callable $callback, callable $default = null) |
| { |
| return $this->whenEmpty($callback, $default); |
| } |
| |
| /** |
| * Filter items by the given key value pair. |
| * |
| * @param string $key |
| * @param mixed $operator |
| * @param mixed $value |
| * @return static |
| */ |
| public function where($key, $operator = null, $value = null) |
| { |
| return $this->filter($this->operatorForWhere(...func_get_args())); |
| } |
| |
| /** |
| * Filter items where the value for the given key is null. |
| * |
| * @param string|null $key |
| * @return static |
| */ |
| public function whereNull($key = null) |
| { |
| return $this->whereStrict($key, null); |
| } |
| |
| /** |
| * Filter items where the value for the given key is not null. |
| * |
| * @param string|null $key |
| * @return static |
| */ |
| public function whereNotNull($key = null) |
| { |
| return $this->where($key, '!==', null); |
| } |
| |
| /** |
| * Filter items by the given key value pair using strict comparison. |
| * |
| * @param string $key |
| * @param mixed $value |
| * @return static |
| */ |
| public function whereStrict($key, $value) |
| { |
| return $this->where($key, '===', $value); |
| } |
| |
| /** |
| * Filter items by the given key value pair. |
| * |
| * @param string $key |
| * @param mixed $values |
| * @param bool $strict |
| * @return static |
| */ |
| public function whereIn($key, $values, $strict = false) |
| { |
| $values = $this->getArrayableItems($values); |
| |
| return $this->filter(function ($item) use ($key, $values, $strict) { |
| return in_array(data_get($item, $key), $values, $strict); |
| }); |
| } |
| |
| /** |
| * Filter items by the given key value pair using strict comparison. |
| * |
| * @param string $key |
| * @param mixed $values |
| * @return static |
| */ |
| public function whereInStrict($key, $values) |
| { |
| return $this->whereIn($key, $values, true); |
| } |
| |
| /** |
| * Filter items such that the value of the given key is between the given values. |
| * |
| * @param string $key |
| * @param array $values |
| * @return static |
| */ |
| public function whereBetween($key, $values) |
| { |
| return $this->where($key, '>=', reset($values))->where($key, '<=', end($values)); |
| } |
| |
| /** |
| * Filter items such that the value of the given key is not between the given values. |
| * |
| * @param string $key |
| * @param array $values |
| * @return static |
| */ |
| public function whereNotBetween($key, $values) |
| { |
| return $this->filter(function ($item) use ($key, $values) { |
| return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values); |
| }); |
| } |
| |
| /** |
| * Filter items by the given key value pair. |
| * |
| * @param string $key |
| * @param mixed $values |
| * @param bool $strict |
| * @return static |
| */ |
| public function whereNotIn($key, $values, $strict = false) |
| { |
| $values = $this->getArrayableItems($values); |
| |
| return $this->reject(function ($item) use ($key, $values, $strict) { |
| return in_array(data_get($item, $key), $values, $strict); |
| }); |
| } |
| |
| /** |
| * Filter items by the given key value pair using strict comparison. |
| * |
| * @param string $key |
| * @param mixed $values |
| * @return static |
| */ |
| public function whereNotInStrict($key, $values) |
| { |
| return $this->whereNotIn($key, $values, true); |
| } |
| |
| /** |
| * Filter the items, removing any items that don't match the given type(s). |
| * |
| * @param string|string[] $type |
| * @return static |
| */ |
| public function whereInstanceOf($type) |
| { |
| return $this->filter(function ($value) use ($type) { |
| if (is_array($type)) { |
| foreach ($type as $classType) { |
| if ($value instanceof $classType) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| return $value instanceof $type; |
| }); |
| } |
| |
| /** |
| * Pass the collection to the given callback and return the result. |
| * |
| * @param callable $callback |
| * @return mixed |
| */ |
| public function pipe(callable $callback) |
| { |
| return $callback($this); |
| } |
| |
| /** |
| * Pass the collection into a new class. |
| * |
| * @param string $class |
| * @return mixed |
| */ |
| public function pipeInto($class) |
| { |
| return new $class($this); |
| } |
| |
| /** |
| * Pass the collection to the given callback and then return it. |
| * |
| * @param callable $callback |
| * @return $this |
| */ |
| public function tap(callable $callback) |
| { |
| $callback(clone $this); |
| |
| return $this; |
| } |
| |
| /** |
| * Reduce the collection to a single value. |
| * |
| * @param callable $callback |
| * @param mixed $initial |
| * @return mixed |
| */ |
| public function reduce(callable $callback, $initial = null) |
| { |
| $result = $initial; |
| |
| foreach ($this as $key => $value) { |
| $result = $callback($result, $value, $key); |
| } |
| |
| return $result; |
| } |
| |
| /** |
| * Reduce an associative collection to a single value. |
| * |
| * @param callable $callback |
| * @param mixed $initial |
| * @return mixed |
| */ |
| public function reduceWithKeys(callable $callback, $initial = null) |
| { |
| $result = $initial; |
| |
| foreach ($this as $key => $value) { |
| $result = $callback($result, $value, $key); |
| } |
| |
| return $result; |
| } |
| |
| /** |
| * Create a collection of all elements that do not pass a given truth test. |
| * |
| * @param callable|mixed $callback |
| * @return static |
| */ |
| public function reject($callback = true) |
| { |
| $useAsCallable = $this->useAsCallable($callback); |
| |
| return $this->filter(function ($value, $key) use ($callback, $useAsCallable) { |
| return $useAsCallable |
| ? ! $callback($value, $key) |
| : $value != $callback; |
| }); |
| } |
| |
| /** |
| * Return only unique items from the collection array. |
| * |
| * @param string|callable|null $key |
| * @param bool $strict |
| * @return static |
| */ |
| public function unique($key = null, $strict = false) |
| { |
| $callback = $this->valueRetriever($key); |
| |
| $exists = []; |
| |
| return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) { |
| if (in_array($id = $callback($item, $key), $exists, $strict)) { |
| return true; |
| } |
| |
| $exists[] = $id; |
| }); |
| } |
| |
| /** |
| * Return only unique items from the collection array using strict comparison. |
| * |
| * @param string|callable|null $key |
| * @return static |
| */ |
| public function uniqueStrict($key = null) |
| { |
| return $this->unique($key, true); |
| } |
| |
| /** |
| * Collect the values into a collection. |
| * |
| * @return \Tightenco\Collect\Support\Collection |
| */ |
| public function collect() |
| { |
| return new Collection($this->all()); |
| } |
| |
| /** |
| * Get the collection of items as a plain array. |
| * |
| * @return array |
| */ |
| public function toArray() |
| { |
| return $this->map(function ($value) { |
| return $value instanceof Arrayable ? $value->toArray() : $value; |
| })->all(); |
| } |
| |
| /** |
| * Convert the object into something JSON serializable. |
| * |
| * @return array |
| */ |
| public function jsonSerialize() |
| { |
| return array_map(function ($value) { |
| if ($value instanceof JsonSerializable) { |
| return $value->jsonSerialize(); |
| } elseif ($value instanceof Jsonable) { |
| return json_decode($value->toJson(), true); |
| } elseif ($value instanceof Arrayable) { |
| return $value->toArray(); |
| } |
| |
| return $value; |
| }, $this->all()); |
| } |
| |
| /** |
| * Get the collection of items as JSON. |
| * |
| * @param int $options |
| * @return string |
| */ |
| public function toJson($options = 0) |
| { |
| return json_encode($this->jsonSerialize(), $options); |
| } |
| |
| /** |
| * Get a CachingIterator instance. |
| * |
| * @param int $flags |
| * @return \CachingIterator |
| */ |
| public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING) |
| { |
| return new CachingIterator($this->getIterator(), $flags); |
| } |
| |
| /** |
| * Convert the collection to its string representation. |
| * |
| * @return string |
| */ |
| public function __toString() |
| { |
| return $this->toJson(); |
| } |
| |
| /** |
| * Add a method to the list of proxied methods. |
| * |
| * @param string $method |
| * @return void |
| */ |
| public static function proxy($method) |
| { |
| static::$proxies[] = $method; |
| } |
| |
| /** |
| * Dynamically access collection proxies. |
| * |
| * @param string $key |
| * @return mixed |
| * |
| * @throws \Exception |
| */ |
| public function __get($key) |
| { |
| if (! in_array($key, static::$proxies)) { |
| throw new Exception("Property [{$key}] does not exist on this collection instance."); |
| } |
| |
| return new HigherOrderCollectionProxy($this, $key); |
| } |
| |
| /** |
| * Results array of items from Collection or Arrayable. |
| * |
| * @param mixed $items |
| * @return array |
| */ |
| protected function getArrayableItems($items) |
| { |
| if (is_array($items)) { |
| return $items; |
| } elseif ($items instanceof Enumerable) { |
| return $items->all(); |
| } elseif ($items instanceof Arrayable) { |
| return $items->toArray(); |
| } elseif ($items instanceof Jsonable) { |
| return json_decode($items->toJson(), true); |
| } elseif ($items instanceof JsonSerializable) { |
| return (array) $items->jsonSerialize(); |
| } elseif ($items instanceof Traversable) { |
| return iterator_to_array($items); |
| } |
| |
| return (array) $items; |
| } |
| |
| /** |
| * Get an operator checker callback. |
| * |
| * @param string $key |
| * @param string|null $operator |
| * @param mixed $value |
| * @return \Closure |
| */ |
| protected function operatorForWhere($key, $operator = null, $value = null) |
| { |
| if (func_num_args() === 1) { |
| $value = true; |
| |
| $operator = '='; |
| } |
| |
| if (func_num_args() === 2) { |
| $value = $operator; |
| |
| $operator = '='; |
| } |
| |
| return function ($item) use ($key, $operator, $value) { |
| $retrieved = data_get($item, $key); |
| |
| $strings = array_filter([$retrieved, $value], function ($value) { |
| return is_string($value) || (is_object($value) && method_exists($value, '__toString')); |
| }); |
| |
| if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) { |
| return in_array($operator, ['!=', '<>', '!==']); |
| } |
| |
| switch ($operator) { |
| default: |
| case '=': |
| case '==': return $retrieved == $value; |
| case '!=': |
| case '<>': return $retrieved != $value; |
| case '<': return $retrieved < $value; |
| case '>': return $retrieved > $value; |
| case '<=': return $retrieved <= $value; |
| case '>=': return $retrieved >= $value; |
| case '===': return $retrieved === $value; |
| case '!==': return $retrieved !== $value; |
| } |
| }; |
| } |
| |
| /** |
| * Determine if the given value is callable, but not a string. |
| * |
| * @param mixed $value |
| * @return bool |
| */ |
| protected function useAsCallable($value) |
| { |
| return ! is_string($value) && is_callable($value); |
| } |
| |
| /** |
| * Get a value retrieving callback. |
| * |
| * @param callable|string|null $value |
| * @return callable |
| */ |
| protected function valueRetriever($value) |
| { |
| if ($this->useAsCallable($value)) { |
| return $value; |
| } |
| |
| return function ($item) use ($value) { |
| return data_get($item, $value); |
| }; |
| } |
| |
| /** |
| * Make a function to check an item's equality. |
| * |
| * @param mixed $value |
| * @return \Closure |
| */ |
| protected function equality($value) |
| { |
| return function ($item) use ($value) { |
| return $item === $value; |
| }; |
| } |
| |
| /** |
| * Make a function using another function, by negating its result. |
| * |
| * @param \Closure $callback |
| * @return \Closure |
| */ |
| protected function negate(Closure $callback) |
| { |
| return function (...$params) use ($callback) { |
| return ! $callback(...$params); |
| }; |
| } |
| |
| /** |
| * Make a function that returns what's passed to it. |
| * |
| * @return \Closure |
| */ |
| protected function identity() |
| { |
| return function ($value) { |
| return $value; |
| }; |
| } |
| } |