242 lines
5.5 KiB
PHP
242 lines
5.5 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace Modules\Core\Option;
|
||
|
|
|
||
|
|
use ArrayAccess;
|
||
|
|
use IteratorAggregate;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template T
|
||
|
|
*
|
||
|
|
* @implements IteratorAggregate<T>
|
||
|
|
*/
|
||
|
|
abstract class Option implements IteratorAggregate
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
*
|
||
|
|
* @param S $value
|
||
|
|
* @param S $noneValue
|
||
|
|
*
|
||
|
|
* @return Option<S>
|
||
|
|
*/
|
||
|
|
public static function fromValue($value, $noneValue = null)
|
||
|
|
{
|
||
|
|
if ($value === $noneValue) {
|
||
|
|
return None::create();
|
||
|
|
}
|
||
|
|
|
||
|
|
return new Some($value);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
*
|
||
|
|
* @param array<string|int,S>|ArrayAccess<string|int,S>|null $array
|
||
|
|
* @param string|int|null $key
|
||
|
|
*
|
||
|
|
* @return Option<S>
|
||
|
|
*/
|
||
|
|
public static function fromArraysValue($array, $key)
|
||
|
|
{
|
||
|
|
if (
|
||
|
|
$key === null ||
|
||
|
|
!(is_array($array) || $array instanceof ArrayAccess) ||
|
||
|
|
!isset($array[$key])
|
||
|
|
) {
|
||
|
|
return None::create();
|
||
|
|
}
|
||
|
|
|
||
|
|
return new Some($array[$key]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
*
|
||
|
|
* @param callable $callback
|
||
|
|
* @param array $arguments
|
||
|
|
* @param S $noneValue
|
||
|
|
*
|
||
|
|
* @return LazyOption<S>
|
||
|
|
*/
|
||
|
|
public static function fromReturn(
|
||
|
|
$callback,
|
||
|
|
array $arguments = [],
|
||
|
|
$noneValue = null,
|
||
|
|
) {
|
||
|
|
return new LazyOption(static function () use (
|
||
|
|
$callback,
|
||
|
|
$arguments,
|
||
|
|
$noneValue,
|
||
|
|
) {
|
||
|
|
/** @var mixed */
|
||
|
|
$return = call_user_func_array($callback, $arguments);
|
||
|
|
|
||
|
|
if ($return === $noneValue) {
|
||
|
|
return None::create();
|
||
|
|
}
|
||
|
|
|
||
|
|
return new Some($return);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
*
|
||
|
|
* @param Option<S>|callable|S $value
|
||
|
|
* @param S $noneValue
|
||
|
|
*
|
||
|
|
* @return Option<S>|LazyOption<S>
|
||
|
|
*/
|
||
|
|
public static function ensure($value, $noneValue = null)
|
||
|
|
{
|
||
|
|
if ($value instanceof self) {
|
||
|
|
return $value;
|
||
|
|
} elseif (is_callable($value)) {
|
||
|
|
return new LazyOption(static function () use ($value, $noneValue) {
|
||
|
|
/** @var mixed */
|
||
|
|
$return = $value();
|
||
|
|
|
||
|
|
if ($return instanceof self) {
|
||
|
|
return $return;
|
||
|
|
} else {
|
||
|
|
return self::fromValue($return, $noneValue);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
return self::fromValue($value, $noneValue);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
*
|
||
|
|
* @param callable $callback
|
||
|
|
* @param mixed $noneValue
|
||
|
|
*
|
||
|
|
* @return callable
|
||
|
|
*/
|
||
|
|
public static function lift($callback, $noneValue = null)
|
||
|
|
{
|
||
|
|
return static function () use ($callback, $noneValue) {
|
||
|
|
/** @var array<int, mixed> */
|
||
|
|
$args = func_get_args();
|
||
|
|
|
||
|
|
$reduced_args = array_reduce(
|
||
|
|
$args,
|
||
|
|
/** @param bool $status */
|
||
|
|
static function ($status, self $o) {
|
||
|
|
return $o->isEmpty() ? true : $status;
|
||
|
|
},
|
||
|
|
false,
|
||
|
|
);
|
||
|
|
|
||
|
|
if ($reduced_args) {
|
||
|
|
return None::create();
|
||
|
|
}
|
||
|
|
|
||
|
|
$args = array_map(static function (self $o) {
|
||
|
|
return $o->get();
|
||
|
|
}, $args);
|
||
|
|
|
||
|
|
return self::ensure(
|
||
|
|
call_user_func_array($callback, $args),
|
||
|
|
$noneValue,
|
||
|
|
);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @return T */
|
||
|
|
abstract public function get();
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param S $default
|
||
|
|
* @return T|S
|
||
|
|
*/
|
||
|
|
abstract public function getOrElse($default);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param callable():S $callable
|
||
|
|
* @return T|S
|
||
|
|
*/
|
||
|
|
abstract public function getOrCall($callable);
|
||
|
|
|
||
|
|
/** @return T */
|
||
|
|
abstract public function getOrThrow(\Exception $ex);
|
||
|
|
|
||
|
|
abstract public function isEmpty(): bool;
|
||
|
|
|
||
|
|
abstract public function isDefined(): bool;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param Option<T> $else
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function orElse(self $else);
|
||
|
|
|
||
|
|
/** @deprecated Use forAll() instead. */
|
||
|
|
abstract public function ifDefined($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param callable(T):mixed $callable
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function forAll($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param callable(T):S $callable
|
||
|
|
* @return Option<S>
|
||
|
|
*/
|
||
|
|
abstract public function map($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param callable(T):Option<S> $callable
|
||
|
|
* @return Option<S>
|
||
|
|
*/
|
||
|
|
abstract public function flatMap($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param callable(T):bool $callable
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function filter($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param callable(T):bool $callable
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function filterNot($callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param T $value
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function select($value);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param T $value
|
||
|
|
* @return Option<T>
|
||
|
|
*/
|
||
|
|
abstract public function reject($value);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param S $initialValue
|
||
|
|
* @param callable(S, T):S $callable
|
||
|
|
* @return S
|
||
|
|
*/
|
||
|
|
abstract public function foldLeft($initialValue, $callable);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @template S
|
||
|
|
* @param S $initialValue
|
||
|
|
* @param callable(T, S):S $callable
|
||
|
|
* @return S
|
||
|
|
*/
|
||
|
|
abstract public function foldRight($initialValue, $callable);
|
||
|
|
}
|