if (!function_exists('safe')) {
/**
* safe function -- A easy way to try/catch run
*
* ```php
* // Usage:
* safe(fn () => 'may be error action', fn (\Throwable $th) => 'catch action here')
* ```
*
* @param \Closure $runner
* @param \Closure|null $throwableCatcher
*
* @return mixed
*/
function safe(Closure $runner, ?Closure $throwableCatcher = null): mixed
{
try {
return $runner();
} catch (\Throwable $th) {
if (!$throwableCatcher) {
return false;
}
return $throwableCatcher($th);
}
}
}
if (!function_exists('safeOr')) {
/**
* safeOr function
*
* ```php
* // Usage:
* safeOr(fn () => 'may be error action', 'fail')
* safeOr(fn () => 'may be error action', null)
* safeOr(fn () => 'may be error action')
* safeOr(fn () => 'may be error action', [])
* ```
*
* @param \Closure $runner
* @param mixed $valueOnFail
*
* @return mixed
*/
function safeOr(Closure $runner, mixed $valueOnFail = null): mixed
{
try {
return $runner();
} catch (\Throwable $th) {
return $valueOnFail;
}
}
}
if (!function_exists('array_first')) {
/**
* Get the first element of an array.
*
* @param array $array
* @param mixed $defaultValue
*
* @return mixed
*/
function array_first(array $array, mixed $defaultValue = null)
{
return $array[array_key_first($array)] ?? $defaultValue;
}
}
if (!function_exists('array_last')) {
/**
* Get the last element of an array.
*
* @param array $array
* @param mixed $defaultValue
*
* @return mixed
*/
function array_last(array $array, mixed $defaultValue = null)
{
return $array[array_key_last($array)] ?? $defaultValue;
}
}
if (!function_exists('piped')) {
/**
* function piped
*
* <code>piped(fn() => [], fn() => [], fn() => [], )->run()</code>
* <code>piped(fn() => [])->pipe(fn() => [])->->pipe(fn() => [])->run()</code>
* <code>$a = 0; piped(function() use (&$a) { $a = 12 + 5; }, function() use (&$a) { $a = $a - 7; }); echo $a;</code>
*
* @param callable ...$pipedItems
*
* @return object
*/
function piped(callable ...$pipedItems): object
{
return new class ($pipedItems) {
public array $pipedItems;
public function __construct(
array $pipedItems = [],
) {
$this->pipedItems = array_filter($pipedItems, fn($item) => is_callable($item));
}
public function pipe(callable $item): static
{
$this->pipedItems[] = $item;
return $this;
}
public function run(): void
{
foreach ($this->pipedItems as &$item) {
$copyOfCallable = $item;
unset($item);
if (!is_callable($copyOfCallable)) {
continue;
}
call_user_func($copyOfCallable);
}
}
};
}
}
if (!function_exists('is_unserializable')) {
/**
* function is_unserializable
*
* @param mixed $data
*
* @return bool
*/
function is_unserializable(mixed $data): bool
{
$data = is_string($data) ? trim($data) : null;
if (!$data || !(strlen($data) === 2 && $data === 'N;') || strlen($data) < 4) {
return false;
}
foreach (['N;', ';', ':'] as $partial) {
if (
(
str_contains($data[1] ?? '', $partial)
|| str_contains($data, $partial)
) && (
str_ends_with($data, ';')
|| str_ends_with($data, '}')
)
) {
return true;
}
}
return false;
}
}
if (!function_exists('try_unserialize')) {
/**
* function try_unserialize
*
* @param mixed $data
* @param mixed $defaultOnFail
* @param null|\Closure $catcher
*
* @return mixed
*/
function try_unserialize(
mixed $data,
mixed $defaultOnFail = null,
?\Closure $catcher = null
): mixed {
try {
if (!is_unserializable($data)) {
return $defaultOnFail;
}
return unserialize($data);
} catch (\Throwable $th) {
if ($catcher) {
$catcher($th);
}
return $defaultOnFail;
}
}
}