From 36a6840061e4c58d02548c85912121a298660f3e Mon Sep 17 00:00:00 2001 From: maxonfjvipon Date: Tue, 9 May 2023 20:11:18 +0300 Subject: [PATCH] #74 - added functions.php --- src/functions.php | 582 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 582 insertions(+) create mode 100644 src/functions.php diff --git a/src/functions.php b/src/functions.php new file mode 100644 index 0000000..1b228ea --- /dev/null +++ b/src/functions.php @@ -0,0 +1,582 @@ +value(); + } +} + +if (!function_exists('ensured_array')) { + /** + * Ensured array. + * + * @param array|Arr $arr + * @return array + * @throws Exception + */ + function ensured_array(array|Arr $arr): array + { + return is_array($arr) ? $arr : $arr->asArray(); + } +} + +if (!function_exists('ensured_bool')) { + function ensured_bool(bool|Logic $boolOrLogic): bool + { + return is_bool($boolOrLogic) ? $boolOrLogic : $boolOrLogic->asBool(); + } +} + +if (!function_exists('ensured_string')) { + /** + * Ensured string. + * + * @param string|Txt $stringOrTxt Text to be ensured + * @return string Ensured string + * @throws Exception If fails + */ + function ensured_string(string|Txt $stringOrTxt): string + { + return is_string($stringOrTxt) ? $stringOrTxt : $stringOrTxt->asString(); + } +} + +// ANY +if (!function_exists('any_cond')) { + /** + * Conditional Any. + * + * @param bool|Logic $condition Condition + * @param mixed $first First value + * @param mixed $second Alternative value + * + * @see AnyCond + */ + function any_cond(bool|Logic $condition, mixed $first, mixed $second): mixed + { + return any_fork($condition, $first, $second); + } +} + +if (!function_exists('any_fork')) { + /** + * Conditional Any. + * + * @param bool|Logic $condition Condition + * @param mixed $first First value + * @param mixed $second Alternative value + * + * @see AnyFork + */ + function any_fork(bool|Logic $condition, mixed $first, mixed $second): mixed + { + return ensured_bool($condition) ? ensured_any($first) : ensured_any($second); + } +} + +if (!function_exists('at_key')) { + /** + * At key. + * + * @param string|int|float|Num|Txt $key Key to get value by + * @param Arr|array $arr Array to get value from + * + * @see AtKey + */ + function at_key(string|int|float|Num|Txt $key, array|Arr $arr): mixed + { + return ensured_array($arr)[ensured_any($key)]; + } +} + +if (!function_exists('at_value')) { + /** + * Key from array by element. + * + * @param string|int|Txt|Num|Any $value + * @param array|Arr $arr + * + * @see AtValue + */ + function at_value(mixed $value, array|Arr $arr): string|int + { + $key = array_search( + needle: ensured_any($value), + haystack: ensured_array($arr), + strict: true + ); + + if ($key === false) { + throw new Exception("Key by given value not found!"); + } + + return $key; + } +} + +if (!function_exists('first_of')) { + /** + * First item. + * + * @param string|Any|Arr|array|Txt $container Container to get first element from + * + * @see FirstOf + */ + function first_of(string|Any|Arr|array|Txt $container): mixed + { + $value = ensured_any($container); + + if (!is_string($value) && !is_array($value)) { + throw new Exception("The element to get the first element from must be an array or string"); + } + + if (empty($value)) { + throw new Exception("Can't get the first element of an empty value"); + } + + return $value[0]; + } +} + +if (!function_exists('last_of')) { + /** + * Last of. + * + * @param string|array|Txt|Arr|Any $container Container to get last element from + * + * @see LastOf + */ + function last_of(string|Any|Arr|array|Txt $container): mixed + { + $value = ensured_any($container); + + if (is_string($value)) { + if (empty($value)) { + throw new Exception(message: "Can't get the last element of an empty string"); + } + + $res = substr($value, -1); + } elseif (is_array($value)) { + if (empty($value)) { + throw new Exception(message: "Can't get the last element of an empty array"); + } + + $res = $value[count($value) - 1]; + } else { + throw new Exception(message: "The element to get the last element from must be an array or string"); + } + + return $res; + } +} + +// ARRAY +if (!function_exists('array_combined')) { + /** + * Ctor. + * + * @param array|Arr $keys + * @param array|Arr $values + * @param bool $ensure + * @return array + * + * @see ArrCombined + */ + function array_combined(array|Arr $keys, array|Arr $values, bool $ensure = false): array + { + $callback = fn (mixed $any) => ensured_any($any); + + /** @var array $keys */ + $keys = array_map($callback, ensured_array($keys)); + + /** @var array $values */ + $values = ensured_array($values); + + if ($ensure) { + /** @var array $values */ + $values = array_map($callback, $values); + } + + if (count($keys) !== count($values)) { + throw new Exception("Keys and values arrays must have the same length"); + } + + return array_combine($keys, $values); + } +} + +if (!function_exists('array_cond')) { + /** + * Conditional array. + * Alias of @see array_fork + * + * @param bool|Logic $condition + * @param Arr|array $first + * @param array|Arr $second + * + * @return array + * + * @see ArrCond + */ + function array_cond(bool|Logic $condition, array|Arr $first, array|Arr $second): array + { + return array_fork($condition, $first, $second); + } +} + +if (!function_exists('array_exploded')) { + /** + * Array exploded. + * + * @param non-empty-string|Txt $separator + * @param string|Txt $text + * + * @return array + * + * @see ArrExploded + */ + function array_exploded(string|Txt $separator, string|Txt $text): array + { + /** @var non-empty-string $separator */ + $separator = ensured_string($separator); + + return explode($separator, ensured_string($text)); + } +} + +if (!function_exists('array_filtered')) { + /** + * Array filtered. + * + * @param array|Arr $arr + * @param callable $callback + * + * @return array + * @see ArrFiltered + */ + function array_filtered(array|Arr $arr, callable $callback): array + { + return array_filter( + ensured_array($arr), + $callback, + ARRAY_FILTER_USE_BOTH + ); + } +} + +if (!function_exists('array_flatten')) { + /** + * Flatten array. + * + * @param array|Arr $arr + * @param int $deep + * + * @return array + * + * @see ArrFlatten + */ + function array_flatten(array|Arr $arr, int $deep = 1): array + { + /** + * @param array $array + * @param array $new + * @param int $currentDeep + * @param int $deep + * + * @return array + */ + $flat = function (array $array, array $new, int $currentDeep, int $deep, callable $self) { + foreach ($array as $item) { + if ($deep !== $currentDeep && (is_array($item) || $item instanceof Arr)) { + $new = $self(ensured_array($item), $new, $currentDeep + 1, $deep, $self); + } else { + $new[] = $item; + } + } + + return $new; + }; + + return $flat(ensured_array($arr), [], 0, $deep, $flat); + } +} + +if (!function_exists('array_fork')) { + /** + * Conditional array. + * + * @param bool|Logic $condition + * @param Arr|array $first + * @param array|Arr $second + * + * @return array + * + * @see ArrFork + */ + function array_fork(bool|Logic $condition, array|Arr $first, array|Arr $second): array + { + return (array) any_fork($condition, AnyOf::arr($first), AnyOf::arr($second)); + } +} + +if (!function_exists('array_if')) { + /** + * Conditional array. + * + * @param bool|Logic $condition + * @param Arr|array $arr + * + * @return array + * + * @see ArrIf + */ + function array_if(bool|Logic $condition, array|Arr $arr): array + { + return array_fork($condition, $arr, []); + } +} + +if (!function_exists('array_mapped')) { + /** + * Array mapped. + * + * @param array|Arr $arr + * @return array + * + * @return array + * + * @see ArrMapped + */ + function array_mapped(array|Arr $arr, callable $callback, bool $ensure = true): array + { + $count = (new ReflectionFunction(Closure::fromCallable($callback)))->getNumberOfParameters(); + + if ($count < 1 || $count > 2) { + throw new Exception("Invalid amount of arguments"); + } + + $array = ensured_array($arr); + + $arrays = ($isTwo = $count === 2) ? [array_keys($array), $array] : [$array]; + + if ($ensure) { + $callback = $isTwo + ? fn ($key, $value) => ensured_any(call_user_func($callback, $key, $value)) + : fn ($value) => ensured_any(call_user_func($callback, $value)); + } + + return array_map( + $callback, + ...$arrays + ); + } +} + +if (!function_exists('array_merged')) { + /** + * Array merged. + * + * @param array|Arr ...$items Items to be merged + * + * @return array + * + * @see ArrMerged + */ + function array_merged(array|Arr ...$items): array + { + return array_merge( + ...array_map( + fn ($arr) => ensured_array($arr), + $items + ) + ); + } +} + +if (!function_exists('array_single')) { + /** + * Single element array. + * + * @param string|int|float|Txt|Num|Any $key + * @param mixed $value + * + * @return array + * + * @see ArrSingle + */ + function array_single(string|int|float|Txt|Num|Any $key, mixed $value): array + { + return [ensured_any($key) => ensured_any($value)]; + } +} + +if (!function_exists('array_sorted')) { + /** + * Sorted array. + * + * @param array|Arr $arr + * @param callable|string|null $compare + * + * @return array + * + * @see ArrSorted + */ + function array_sorted(array|Arr $arr, callable|string|null $compare = null): array + { + $arr = ensured_array($arr); + + if ($compare !== null) { + usort( + $arr, + is_string($compare) + ? fn ($a, $b) => $a[$compare] <=> $b[$compare] + : $compare + ); + } else { + sort($arr); + } + + return $arr; + } +} + +if (!function_exists('array_split')) { + /** + * Split array. + * Alias of @see array_exploded + * + * @param non-empty-string|Txt $separator + * @param string|Txt $text + * + * @return array + * + * @see ArrSplit + */ + function array_split(string|Txt $separator, string|Txt $text): array + { + return array_exploded($separator, $text); + } +} + +if (!function_exists('array_with')) { + /** + * Array with an element. + * + * @param array|Arr $arr + * @param mixed $keyOrValue + * @param mixed $value + * + * @return array + * + * @see ArrWith + */ + function array_with(array|Arr $arr, mixed $keyOrValue, mixed $value = null): array + { + $array = ensured_array($arr); + + if ($value === null) { + $array[] = ensured_any($keyOrValue); + } else { + $array[ensured_any($keyOrValue)] = ensured_any($value); + } + + return $array; + } +} + +if (!function_exists('array_without')) { + /** + * Array without an element. + * + * @param array|Arr $arr + * @param string|int|Txt|Num ...$keys + * + * @return array + * + * @see ArrWithout + */ + function array_without(array|Arr $arr, string|int|Txt|Num ...$keys): array + { + $array = ensured_array($arr); + + foreach ($keys as $key) { + /** @var string|int $key */ + $key = ensured_any($key); + + if (array_key_exists($key, $array)) { + unset($array[$key]); + } + } + + return $array; + } +}