Skip to content

Instantly share code, notes, and snippets.

@eghojansu
Created January 5, 2024 07:00
Show Gist options
  • Save eghojansu/677a38e85d39c65ff736bb9cc295a399 to your computer and use it in GitHub Desktop.
Save eghojansu/677a38e85d39c65ff736bb9cc295a399 to your computer and use it in GitHub Desktop.
PHP Helpers
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