diff --git a/flight/core/FilteredCallable.php b/flight/core/FilteredCallable.php new file mode 100644 index 0000000..00c99fc --- /dev/null +++ b/flight/core/FilteredCallable.php @@ -0,0 +1,90 @@ +closure = Closure::fromCallable($callable); + } + + /** + * @param mixed ...$input + * @return Output + * @throws Throwable + */ + public function __invoke(...$input) + { + foreach ($this->beforeFilters as $filter) { + $filterReturnValue = $filter($input); + + if ($filterReturnValue === false) { + break; + } + } + + $closure = $this->closure; + + $output = $closure(...$input); + + foreach ($this->afterFilters as $filter) { + $filterReturnValue = $filter($output); + + if ($filterReturnValue === false) { + break; + } + } + + return $output; + } + + /** @param callable(mixed[] &$input): (void|never|false) $filter */ + public function pushBeforeFilter(callable $filter): void + { + if (!in_array($filter, $this->beforeFilters)) { + $this->beforeFilters[] = $filter; + } + } + + /** @param callable(Output &$output): (void|never|false) $filter */ + public function pushAfterFilter(callable $filter): void + { + if (!in_array($filter, $this->afterFilters)) { + $filterReflectionFunction = new ReflectionFunction($filter); + + if ($filterReflectionFunction->getNumberOfParameters() === 2) { + $filter = static function (&$output) use ($filter) { + static $input = []; + + return $filter($input, $output); + }; + } + + $this->afterFilters[] = $filter; + } + } +}