|
- <?php
-
- declare(strict_types=1);
-
- namespace Core;
-
- use Exception;
- use ReflectionFunction;
- use ReflectionMethod;
-
- class App
- {
- protected array $bindings = [];
-
- public function bind(string $name, mixed $value): void
- {
- $this->bindings[$name] = $value;
- }
-
- public function get(string $name): mixed
- {
- return $this->bindings[$name] ?? null;
- }
-
- public function call(callable|array|string $handler, array $parameters = []): mixed
- {
- if (is_array($handler)) {
- return $this->callMethod($handler, $parameters);
- }
-
- if (is_callable($handler)) {
- return $this->callFunction($handler, $parameters);
- }
-
- throw new Exception('Invalid handler.');
- }
-
- protected function callFunction(callable $handler, array $parameters): mixed
- {
- $reflection = new ReflectionFunction($handler);
-
- return $reflection->invokeArgs($this->resolveArgs($reflection, $parameters));
- }
-
- protected function callMethod(array $handler, array $parameters): mixed
- {
- [$class, $method] = $handler;
-
- if (is_string($class)) {
- $class = new $class();
- }
-
- $reflection = new ReflectionMethod($class, $method);
-
- return $reflection->invokeArgs($class, $this->resolveArgs($reflection, $parameters));
- }
-
- protected function resolveArgs(\ReflectionFunctionAbstract $reflection, array $parameters): array
- {
- $args = [];
-
- foreach ($reflection->getParameters() as $param) {
- $name = $param->getName();
-
- if (array_key_exists($name, $parameters)) {
- $args[] = $parameters[$name];
- continue;
- }
-
- $type = $param->getType();
-
- if ($type instanceof \ReflectionNamedType && !$type->isBuiltin()) {
- $typeName = $type->getName();
-
- if (array_key_exists($typeName, $this->bindings)) {
- $args[] = $this->bindings[$typeName];
- continue;
- }
- }
-
- $args[] = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
- }
-
- return $args;
- }
- }
|