Skip to content

Commit

Permalink
feat: add middleware attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
dewanakl committed Dec 6, 2023
1 parent 4f16ef7 commit 16e7462
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 57 deletions.
25 changes: 22 additions & 3 deletions src/Core/Facades/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ public function __construct()
private function build(string $name, array $default = []): object
{
try {
$ref = new ReflectionClass($name);

return new $name(...$this->getDependencies(
(new ReflectionClass($name))->getConstructor()?->getParameters() ?? [],
$ref->getConstructor()?->getParameters() ?? [],
$default
));
} catch (ReflectionException $e) {
Expand Down Expand Up @@ -138,8 +140,10 @@ public function invoke(string|object $name, string $method, array $default = [])
}

try {
$ref = new ReflectionClass($name);

return $name->{$method}(...$this->getDependencies(
(new ReflectionClass($name))->getMethod($method)->getParameters(),
$ref->getMethod($method)->getParameters(),
$default
));
} catch (ReflectionException $e) {
Expand Down Expand Up @@ -195,8 +199,10 @@ public function has(string $abstract): bool
public function resolve(Closure $name, array $default = []): mixed
{
try {
$ref = new ReflectionFunction($name);

return $name(...$this->getDependencies(
(new ReflectionFunction($name))->getParameters(),
$ref->getParameters(),
$default
));
} catch (ReflectionException $e) {
Expand Down Expand Up @@ -227,4 +233,17 @@ public function bind(string $abstract, Closure|string $bind): void

$this->objectPool[$abstract] = $bind;
}

/**
* Get attribute on function of object.
*
* @param object $abstract
* @param string $function
* @return array<int, \ReflectionAttribute>
*/
public function getAttribute(object $abstract, string $function): array
{
$ref = new ReflectionClass($abstract);
return $ref->getMethod($function)->getAttributes();
}
}
108 changes: 61 additions & 47 deletions src/Core/Facades/Web.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Core\Http\Session;
use Core\Http\Stream;
use Core\Middleware\Middleware;
use Core\Middleware\MiddlewareInterface;
use Core\Routing\Controller;
use Core\Routing\Route;
use Core\Support\Error;
Expand All @@ -36,65 +37,40 @@ public function __construct(Application $application)
}

/**
* Eksekusi core middleware.
* Eksekusi controller.
*
* @param array<string, mixed> $route
* @param array<int, mixed> $variables
* @param object $controller
* @param string|null $function
* @return Closure
*/
private function coreMiddleware(array $route, array $variables): Closure
private function coreMiddleware(object $controller, string|null $function = null): Closure
{
return function () use ($route, $variables): mixed {
$this->registerProvider();
return $this->invokeController($route, $variables);
return function () use ($controller, $function): mixed {
if ($function === null) {
return null;
}

return $this->app->invoke(
$controller,
$function,
array_values($this->request->route())
);
};
}

/**
* Process middleware, provider, and controller.
* Process middleware and controller.
*
* @param array<string, mixed> $route
* @param array<int, mixed> $variables
* @return Respond|Stream
*
* @throws ErrorException
*/
private function process(array $route, array $variables): Respond|Stream
{
$middleware = new Middleware([
...$this->kernel->middlewares(),
...$route['middleware']
]);

$result = $middleware->handle($this->request, $this->coreMiddleware($route, $variables));

$error = error_get_last();
if ($error !== null) {
error_clear_last();
throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
}

return $result;
}

/**
* Eksekusi controllernya.
*
* @param array<string, mixed> $route
* @param array<int, mixed> $variables
* @return mixed
*
* @throws Exception
*/
private function invokeController(array $route, array $variables): mixed
private function process(array $route): Respond|Stream
{
$controller = $route['controller'];
$function = $route['function'];

if ($function === null) {
return null;
}

if ($controller === null) {
$controller = $function;
$function = '__invoke';
Expand All @@ -105,12 +81,41 @@ private function invokeController(array $route, array $variables): mixed
throw new Exception(sprintf('Class "%s" is not extends BaseController.', get_class($controller)));
}

$parameters = [];
for ($i = 1; $i < count($variables); $i++) {
$parameters[] = $variables[$i];
$attributeMiddleware = [];
if ($function) {
foreach ($this->app->getAttribute($controller, $function) as $value) {
if ($this->app->make($value->getName()) instanceof MiddlewareInterface) {
$attributeMiddleware[] = $value->getName();
}

$this->app->clean($value->getName());
}
}

return $this->app->invoke($controller, $function, $parameters);
$middleware = new Middleware([
...$this->kernel->middlewares(),
...$route['middleware'],
...$attributeMiddleware
]);

$result = $middleware->handle(
$this->request,
$this->coreMiddleware($controller, $function)
);

$error = error_get_last();
if ($error !== null) {
error_clear_last();
throw new ErrorException(
$error['message'],
0,
$error['type'],
$error['file'],
$error['line']
);
}

return $result;
}

/**
Expand All @@ -128,14 +133,23 @@ private function runRoute(): Respond|Stream
$routeMatch = false;

foreach (Route::router()->routes() as $route) {
$pattern = '#^' . $route['path'] . '$#';

$params = [];
$variables = [];

preg_match_all('/{(\w+)}/', $route['path'], $params);
$pattern = '#^' . preg_replace('/{(\w+)}/', '([\w-]*)', $route['path']) . '$#';

if (preg_match($pattern, $path, $variables)) {
$routeMatch = true;

if ($route['method'] == $method) {
return $this->process($route, $variables);
array_shift($variables);
$route['params'] = array_combine($params[1], $variables);

Route::$route = $route;
$this->registerProvider();
return $this->process($route);
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/Core/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Core\Facades\App;
use Core\File\UploadedFile;
use Core\Routing\Route;
use Core\Valid\Exception\ValidationException;
use Core\Valid\Validator;
use Exception;
Expand Down Expand Up @@ -100,6 +101,28 @@ public function __destruct()
$this->stream = null;
}

/**
* Set or get route params.
*
* @param string|null $key
* @param mixed $val
* @return mixed
*/
public function route(string|null $key = null, mixed $val = null): mixed
{
$params = Route::route()['params'];
if (!$key) {
return $params;
}

if (!$val) {
return @$params[$key] ?? null;
}

$params[$key] = $val;
return $val;
}

/**
* Get bearer token from header.
*
Expand Down
8 changes: 7 additions & 1 deletion src/Core/Routing/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ private function ensureNoError()
$error = error_get_last();
if ($error !== null) {
error_clear_last();
throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
throw new ErrorException(
$error['message'],
0,
$error['type'],
$error['file'],
$error['line']
);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/Core/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@
*/
final class Route
{
/**
* Indicate current route.
*
* @var array $route
*/
public static $route;

/**
* Get current route.
*
* @return array
*/
public static function &route(): array
{
return static::$route;
}

/**
* Simpan url route get.
*
Expand Down
4 changes: 1 addition & 3 deletions src/Core/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ private function add(string $method, string $path, array|string|null $action = n
$function = $action;
}

$path = preg_replace('/{(\w+)}/', '([\w-]*)', $path);
$middleware = is_null($middleware) ? [] : (is_string($middleware) ? array($middleware) : $middleware);

$idroute = count($this->routes);
Expand Down Expand Up @@ -268,8 +267,7 @@ public function group(Closure $group): void

if (!is_null($tempPrefix)) {
$old = $this->routes[$id]['path'];
$prefix = preg_replace('/{(\w+)}/', '([\w-]*)', $tempPrefix);
$this->routes[$id]['path'] = ($old != '/') ? $prefix . $old : $prefix;
$this->routes[$id]['path'] = ($old != '/') ? $tempPrefix . $old : $tempPrefix;
}

if (!empty($tempMiddleware)) {
Expand Down
8 changes: 7 additions & 1 deletion src/Core/View/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ public function including(string $name): Render
$error = error_get_last();
if ($error !== null) {
error_clear_last();
throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
throw new ErrorException(
$error['message'],
0,
$error['type'],
$error['file'],
$error['line']
);
}

return $template;
Expand Down
10 changes: 8 additions & 2 deletions src/helpers/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,13 @@ function e(mixed $var): string|null
$error = error_get_last();
if ($error !== null) {
error_clear_last();
throw new \Core\View\Exception\CastToStringException($error['message'], 0, $error['type'], $error['file'], $error['line']);
throw new \Core\View\Exception\CastToStringException(
$error['message'],
0,
$error['type'],
$error['file'],
$error['line']
);
}

return htmlspecialchars($str);
Expand Down Expand Up @@ -440,7 +446,7 @@ function route(string $param, mixed ...$keys): string
$found = false;
foreach (\Core\Routing\Route::router()->routes() as $route) {
if ($route['name'] == $param) {
$param = $route['path'];
$param = preg_replace('/{(\w+)}/', '([\w-]*)', $route['path']);
$found = true;
break;
}
Expand Down

0 comments on commit 16e7462

Please sign in to comment.