983 lines
24 KiB
PHP
983 lines
24 KiB
PHP
<?php
|
|
|
|
namespace Illuminate\Support\Traits;
|
|
|
|
use CachingIterator;
|
|
use Closure;
|
|
use Exception;
|
|
use Illuminate\Contracts\Support\Arrayable;
|
|
use Illuminate\Contracts\Support\Jsonable;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Enumerable;
|
|
use Illuminate\Support\HigherOrderCollectionProxy;
|
|
use Illuminate\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 $sum
|
|
* @property-read HigherOrderCollectionProxy $unique
|
|
* @property-read HigherOrderCollectionProxy $until
|
|
*/
|
|
trait EnumeratesValues
|
|
{
|
|
/**
|
|
* The methods that can be proxied.
|
|
*
|
|
* @var array
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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 given key is not null.
|
|
*
|
|
* @param string|null $key
|
|
* @return static
|
|
*/
|
|
public function whereNull($key = null)
|
|
{
|
|
return $this->whereStrict($key, null);
|
|
}
|
|
|
|
/**
|
|
* Filter items where the given key is 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.
|
|
*
|
|
* @param string $type
|
|
* @return static
|
|
*/
|
|
public function whereInstanceOf($type)
|
|
{
|
|
return $this->filter(function ($value) use ($type) {
|
|
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 to the given callback and then return it.
|
|
*
|
|
* @param callable $callback
|
|
* @return $this
|
|
*/
|
|
public function tap(callable $callback)
|
|
{
|
|
$callback(clone $this);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* Take items in the collection until the given condition is met.
|
|
*
|
|
* This is an alias to the "takeUntil" method.
|
|
*
|
|
* @param mixed $value
|
|
* @return static
|
|
*
|
|
* @deprecated Use the "takeUntil" method directly.
|
|
*/
|
|
public function until($value)
|
|
{
|
|
return $this->takeUntil($value);
|
|
}
|
|
|
|
/**
|
|
* Collect the values into a collection.
|
|
*
|
|
* @return \Illuminate\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;
|
|
};
|
|
}
|
|
}
|