Created
January 5, 2024 07:00
-
-
Save eghojansu/677a38e85d39c65ff736bb9cc295a399 to your computer and use it in GitHub Desktop.
PHP Helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function arr($value, string $delimiter = null) { | |
return new class($value, $delimiter) implements IteratorAggregate { | |
/** @var iterable */ | |
private $iterates; | |
/** @var array */ | |
private $items; | |
/** @var iterable */ | |
private $origins; | |
/** @var array */ | |
private $parameters = array(); | |
public function __construct($items, string $delimiter = null) { | |
if (is_iterable($items)) { | |
$this->origins = $items; | |
} elseif (is_string($items)) { | |
$this->origins = preg_split('/[' . preg_quote($delimiter ?? ',;|', '/') . ']/', $items, 0, PREG_SPLIT_NO_EMPTY); | |
} else { | |
$this->origins = (array) $items; | |
} | |
$this->update($this->origins); | |
} | |
function update(iterable $items) { | |
if (is_iterable($items)) { | |
$this->iterates = $items; | |
$this->items = null; | |
} else { | |
$this->iterates = null; | |
$this->items = $items; | |
} | |
return $this; | |
} | |
function getIterator(): Traversable { | |
return $this->iterates ?? new ArrayIterator($this->items); | |
} | |
function cast(): array { | |
return $this->items ?? ((array) $this->iterates); | |
} | |
function value(): iterable { | |
return $this->iterates ?? $this->items; | |
} | |
function origins() { | |
return $this->origins; | |
} | |
function addParameter($value) { | |
if ($value instanceof Closure) { | |
$this->parameters[] = $value($this->items ?? $this->iterates); | |
} else { | |
$this->parameters[] = $value; | |
} | |
return $this; | |
} | |
function clearParameters() { | |
$this->parameters = array(); | |
return $this; | |
} | |
function when($satisfied, callable $fn) { | |
return $this; | |
} | |
function each(callable $fn, ...$args) { | |
foreach ($this as $key => $value) { | |
$fn($value, $key, ...$this->parameters, ...$args); | |
} | |
return $this; | |
} | |
function map(callable $fn, ...$args) { | |
$result = array(); | |
$call = $this->internal($fn) ? fn($value) => $fn($value, ...$args) : $fn; | |
foreach ($this as $key => $value) { | |
$result[$key] = $call($value, $key, ...$this->parameters, ...$args); | |
} | |
return $this->update($result); | |
} | |
function coalesce(callable $fn = null) { | |
$call = $fn ?? fn($value) => $value; | |
foreach ($this as $key => $value) { | |
if (null !== $result = $call($value, $key, ...$this->parameters)) { | |
return $result; | |
} | |
} | |
return null; | |
} | |
function reduce(callable $fn, $carry = null) { | |
$result = $carry; | |
foreach ($this as $key => $value) { | |
$result = $fn($result, $value, $key, ...$this->parameters); | |
} | |
return $result; | |
} | |
function some(callable $fn, bool $match = null, array &$found = null): bool { | |
$found = array(null, null); | |
$call = $this->caller($fn); | |
foreach ($this as $key => $value) { | |
if (($match ?? true) === $call($value, $key, ...$this->parameters)) { | |
$found = array($value, $key); | |
return true; | |
} | |
} | |
return false; | |
} | |
function every(callable $fn, bool $match = null): bool { | |
$call = $this->caller($fn); | |
foreach ($this as $key => $value) { | |
if (($match ?? true) !== $call($value, $key, ...$this->parameters)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function filter(callable $fn, bool $match = null, bool $assoc = true) { | |
$result = array(); | |
$call = item_caller($fn); | |
$check = $match ?? true; | |
foreach ($this as $key => $value) { | |
if ($check === $call($value, $key, ...$this->parameters)) { | |
if ($assoc) { | |
$result[$key] = $value; | |
} else { | |
$result[] = $value; | |
} | |
} | |
} | |
return $this->update($result); | |
} | |
function contains($value): bool { | |
return null === $this->items ? $this->find($value) : in_array($value, $this->items); | |
} | |
function only(array|string $keys, bool $match = null) { | |
$checks = arr($keys)->cast(); | |
return $this->filter(fn(...$args) => in_array($args[1], $checks), $match); | |
} | |
function except(array|string $keys) { | |
return $this->only($keys, false); | |
} | |
function find($fn, bool $match = null, bool $exact = true) { | |
return $this->findSome($fn, $match, $exact); | |
} | |
function findIndex($fn, bool $match = null, bool $exact = true) { | |
return $this->findSome($fn, $match, $exact, 1); | |
} | |
function indexed(): bool { | |
return null !== $this->items && (!$this->items || ctype_digit(implode('', array_keys($this->items)))); | |
} | |
function slice(int $offset, int $length = null, bool $preserve = false) { | |
return $this->update(array_slice($this->items ?? array(), $offset, $length, $preserve)); | |
} | |
function splice(int $offset, int $length = null, $replacement = null) { | |
$items = $this->cast(); | |
$result = array_splice($items, $offset, $length, $replacement ?? array()); | |
$this->update($items); | |
return $result; | |
} | |
private function findSome($fn, bool $match = null, bool $exact = true, int $key = 0): mixed { | |
$call = is_callable($fn) ? $fn : fn($value) => $exact ? $value === $fn : $value == $fn; | |
return $this->some($call, $match, $found) ? ($found[$key] ?? null) : null; | |
} | |
private function caller(callable $fn): callable { | |
if ($fn instanceof Closure || is_array($fn) || !is_internal($fn)) { | |
return $fn; | |
} | |
return fn($value) => $fn($value); | |
} | |
private function internal(callable $fn): bool { | |
return (new ReflectionFunction($fn))->isInternal(); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment