Ver código fonte

improve DI consistency and controller resolution

michelphp 2 semanas atrás
pai
commit
1166e86e52

+ 0 - 22
src/Auth/AuthHandlerInterface.php

@@ -1,22 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth;
-
-use Michel\Framework\Core\Auth\Exception\AuthenticationException;
-use Psr\Http\Message\ResponseFactoryInterface;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-
-interface AuthHandlerInterface
-{
-    /**
-     * @throws AuthenticationException
-     */
-    public function authenticate(ServerRequestInterface $request):  ?AuthIdentity;
-
-    public function onFailure(
-        ServerRequestInterface $request,
-        ResponseFactoryInterface $responseFactory,
-        ?AuthenticationException $exception = null
-    ): ResponseInterface;
-}

+ 0 - 30
src/Auth/AuthIdentity.php

@@ -1,30 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth;
-
-final class AuthIdentity
-{
-    private UserInterface $user;
-    private bool $isNewLogin;
-
-    public function __construct(
-        UserInterface $user,
-        bool          $isNewLogin = false
-    )
-    {
-
-        $this->user = $user;
-        $this->isNewLogin = $isNewLogin;
-    }
-
-    public function getUser(): UserInterface
-    {
-        return $this->user;
-    }
-
-    public function isNewLogin(): bool
-    {
-        return $this->isNewLogin;
-    }
-
-}

+ 0 - 7
src/Auth/Exception/AuthenticationException.php

@@ -1,7 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Exception;
-
-class AuthenticationException extends \Exception
-{
-}

+ 0 - 7
src/Auth/Exception/InvalidCredentialsException.php

@@ -1,7 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Exception;
-
-final class InvalidCredentialsException extends AuthenticationException
-{
-}

+ 0 - 7
src/Auth/Exception/UserNotFoundException.php

@@ -1,7 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Exception;
-
-final class UserNotFoundException extends AuthenticationException
-{
-}

+ 0 - 90
src/Auth/Handler/FormAuthHandler.php

@@ -1,90 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Handler;
-
-use Michel\Framework\Core\Auth\AuthHandlerInterface;
-use Michel\Framework\Core\Auth\AuthIdentity;
-use Michel\Framework\Core\Auth\Exception\AuthenticationException;
-use Michel\Framework\Core\Auth\Exception\InvalidCredentialsException;
-use Michel\Framework\Core\Auth\Exception\UserNotFoundException;
-use Michel\Framework\Core\Auth\PasswordAuthenticatedUserInterface;
-use Michel\Framework\Core\Auth\UserInterface;
-use Michel\Framework\Core\Auth\UserProviderInterface;
-use Michel\Session\Storage\SessionStorageInterface;
-use Psr\Http\Message\ResponseFactoryInterface;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-
-class FormAuthHandler implements AuthHandlerInterface
-{
-    /**
-     * @var callable
-     */
-    private $onFailure;
-
-    private UserProviderInterface $userProvider;
-    private SessionStorageInterface $sessionStorage;
-
-    public function __construct(
-        UserProviderInterface   $userProvider,
-        SessionStorageInterface $sessionStorage,
-        callable                $onFailure
-    )
-    {
-        $this->userProvider = $userProvider;
-        $this->sessionStorage = $sessionStorage;
-        $this->onFailure = $onFailure;
-    }
-
-    /**
-     * @throws AuthenticationException
-     * @throws UserNotFoundException
-     * @throws InvalidCredentialsException
-     */
-    public function authenticate(ServerRequestInterface $request): ?AuthIdentity
-    {
-        if ($this->sessionStorage->has('user_identifier')) {
-            $identifier = $this->sessionStorage->get('user_identifier');
-            $user = $this->userProvider->findByIdentifier($identifier);
-            if ($user instanceof UserInterface) {
-                return new AuthIdentity($user,  false);
-            }
-        }
-
-        if ($request->getMethod() !== 'POST') {
-            return null;
-        }
-
-        $data = $request->getParsedBody();
-        $login = $data['login'] ?? '';
-        $pass = $data['password'] ?? '';
-        if (empty($login) || empty($pass)) {
-            throw new InvalidCredentialsException("Credentials cannot be empty.");
-        }
-
-        /**
-         * @var PasswordAuthenticatedUserInterface|UserInterface|null $user
-         */
-        $user = $this->userProvider->findByIdentifier($login);
-        if (!$user instanceof UserInterface) {
-            throw new UserNotFoundException("No user found with the provided identifier.");
-        }
-
-        if (!$user instanceof PasswordAuthenticatedUserInterface) {
-            throw new AuthenticationException("The resolved user does not support password authentication.");
-        }
-
-        if (!$this->userProvider->checkPassword($user, $pass)) {
-            throw new InvalidCredentialsException("Invalid username or password.");
-        }
-
-        $this->sessionStorage->put('user_identifier', $user->getUserIdentifier());
-        return new AuthIdentity($user,  true);
-    }
-
-    public function onFailure(ServerRequestInterface $request, ResponseFactoryInterface $responseFactory, ?AuthenticationException $exception = null): ResponseInterface
-    {
-        return ($this->onFailure)($request, $responseFactory, $exception);
-    }
-
-}

+ 0 - 83
src/Auth/Handler/TokenAuthHandler.php

@@ -1,83 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Handler;
-
-use Michel\Framework\Core\Auth\AuthHandlerInterface;
-use Michel\Framework\Core\Auth\AuthIdentity;
-use Michel\Framework\Core\Auth\Exception\AuthenticationException;
-use Michel\Framework\Core\Auth\Exception\InvalidCredentialsException;
-use Michel\Framework\Core\Auth\Exception\UserNotFoundException;
-use Michel\Framework\Core\Auth\UserInterface;
-use Michel\Framework\Core\Auth\UserProviderInterface;
-use Psr\Http\Message\ResponseFactoryInterface;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-
-class TokenAuthHandler implements AuthHandlerInterface
-{
-
-    private UserProviderInterface $userProvider;
-
-    private string $headerName;
-
-    /**
-     * @var callable|null
-     */
-    private $onFailure;
-    public function __construct(
-        UserProviderInterface $userProvider,
-        string                $headerName,
-        callable              $onFailure = null
-    )
-    {
-        $this->userProvider = $userProvider;
-        $this->headerName = $headerName;
-        $this->onFailure = $onFailure;
-    }
-
-    public function isAuthenticated(): bool
-    {
-        return false;
-    }
-
-
-    /**
-     * @throws AuthenticationException
-     * @throws UserNotFoundException
-     * @throws InvalidCredentialsException
-     */
-    public function authenticate(ServerRequestInterface $request): ?AuthIdentity
-    {
-        $token = $request->getHeaderLine($this->headerName);
-        if (empty($token)) {
-            throw new AuthenticationException("Token is required.");
-        }
-        $user = $this->userProvider->findByToken($token);
-        if (!$user instanceof UserInterface) {
-            throw new InvalidCredentialsException("The provided API key is invalid.");
-        }
-        return new AuthIdentity($user,  false);
-    }
-
-    public function onFailure(ServerRequestInterface $request, ResponseFactoryInterface $responseFactory, ?AuthenticationException $exception = null): ResponseInterface
-    {
-        if (!is_callable($this->onFailure)) {
-            $status = 401;
-            $message = $exception ? $exception->getMessage() : "Unauthorized access.";
-            $payload = [
-                'status' => $status,
-                'title'  => 'Authentication Failed',
-                'detail' => $message,
-            ];
-
-            $response = $responseFactory->createResponse($status);
-            $response->getBody()->write(json_encode($payload, JSON_UNESCAPED_SLASHES ));
-            return $response
-                ->withHeader('Content-Type', 'application/json')
-                ->withHeader('Cache-Control', 'no-store');
-
-        }
-        return ($this->onFailure)($request, $responseFactory, $exception);
-    }
-
-}

+ 0 - 70
src/Auth/Middlewares/AuthMiddleware.php

@@ -1,70 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth\Middlewares;
-
-use Michel\Framework\Core\Auth\AuthHandlerInterface;
-use Michel\Framework\Core\Auth\AuthIdentity;
-use Michel\Framework\Core\Auth\Exception\AuthenticationException;
-use Michel\Framework\Core\Helper\IpHelper;
-use Psr\Http\Message\ResponseFactoryInterface;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Server\RequestHandlerInterface;
-use Psr\Log\LoggerInterface;
-
-final class AuthMiddleware
-{
-    private AuthHandlerInterface $authHandler;
-    private ResponseFactoryInterface $responseFactory;
-
-    private ?LoggerInterface $logger;
-
-    public function __construct(
-        AuthHandlerInterface $authHandler,
-        ResponseFactoryInterface $responseFactory,
-        LoggerInterface $logger = null
-    )
-    {
-        $this->authHandler = $authHandler;
-        $this->responseFactory = $responseFactory;
-        $this->logger = $logger;
-    }
-
-    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
-    {
-        $handlerName = get_class($this->authHandler);
-
-        try {
-            $authIdentity = $this->authHandler->authenticate($request);
-            if ($authIdentity instanceof AuthIdentity) {
-                $user = $authIdentity->getUser();
-                $request = $request->withAttribute("user", $user);
-                if ($authIdentity->isNewLogin()) {
-                    $this->log('info', "[{handler}] Authentication successful : {id}.", [
-                        'handler' => $handlerName,
-                        'id'      => $user->getUserIdentifier()
-                    ]);
-                }
-                return $handler->handle($request);
-            }
-        }catch (AuthenticationException $exception) {
-            $this->log('warning', "[{handler}] Authentication failed: {ip} - {message}", [
-                'handler' => $handlerName,
-                'message' => $exception->getMessage(),
-                'ip'      => IpHelper::getIpFromRequest($request),
-            ]);
-            return $this->authHandler->onFailure($request, $this->responseFactory, $exception);
-        }
-
-        return $this->authHandler->onFailure($request, $this->responseFactory);
-    }
-
-
-    private function log(string $level, string $message, array $context = []): void
-    {
-        if ($this->logger === null) {
-            return;
-        }
-        $this->logger->log($level, $message, $context);
-    }
-}

+ 0 - 10
src/Auth/PasswordAuthenticatedUserInterface.php

@@ -1,10 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth;
-
-interface PasswordAuthenticatedUserInterface
-{
-    public function getPassword(): string;
-
-    public function setPassword(?string $password);
-}

+ 0 - 8
src/Auth/UserInterface.php

@@ -1,8 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth;
-
-interface UserInterface
-{
-    public function getUserIdentifier(): string;
-}

+ 0 - 11
src/Auth/UserProviderInterface.php

@@ -1,11 +0,0 @@
-<?php
-
-namespace Michel\Framework\Core\Auth;
-
-interface UserProviderInterface
-{
-    public function findByIdentifier(string $identifier): ?UserInterface;
-    public function findByToken(string $token): ?UserInterface;
-    public function checkPassword(PasswordAuthenticatedUserInterface $user, string $plainPassword): bool;
-    public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newPlainPassword): void;
-}

+ 2 - 2
src/Debug/ExecutionProfiler.php

@@ -50,8 +50,8 @@ final class ExecutionProfiler
                 'log.level' => 'debug',
                 'event.duration' => $duration,
                 'metrics' => [
-                    'memory.usage' => _m_convert($memoryUsage),
-                    'peak_memory.usage' => _m_convert(memory_get_peak_usage(true)),
+                    'memory.usage' => human_readable_bytes($memoryUsage),
+                    'peak_memory.usage' => human_readable_bytes(memory_get_peak_usage(true)),
                     'load_time.ms' => $duration * 1000,
                     'load_time.s' => number_format($duration, 3),
                 ],

+ 2 - 2
src/Debug/RequestProfiler.php

@@ -65,9 +65,9 @@ final class RequestProfiler
             'event.duration' => $duration,
             'metrics' => [
                 'memory.usage' => $memoryUsage,
-                'memory.usage.human' => _m_convert($memoryUsage),
+                'memory.usage.human' => human_readable_bytes($memoryUsage),
                 'memory.peak' => $memoryPeak,
-                'memory.peak.human' => _m_convert(memory_get_peak_usage(true)),
+                'memory.peak.human' => human_readable_bytes(memory_get_peak_usage(true)),
                 'load_time.ms' => ceil($duration * 1000),
                 'load_time.s' => number_format($duration, 3),
             ],

+ 1 - 1
src/ErrorHandler/ExceptionHandler.php

@@ -41,7 +41,7 @@ class ExceptionHandler
     public function renderByMimetype(string $mimeType, Throwable $exception): ResponseInterface
     {
         if (!$exception instanceof HttpExceptionInterface) {
-            $exception = new HttpException(500, $exception->getMessage(), $exception->getCode(), $exception);
+            $exception = new HttpException(500, $exception->getMessage(), (int)$exception->getCode(), $exception);
         }
 
         $mimeType = strtolower($mimeType);

+ 9 - 3
src/Middlewares/ControllerMiddleware.php

@@ -40,14 +40,20 @@ final class ControllerMiddleware implements MiddlewareInterface
         $this->container = $container;
     }
 
+
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         $controller = $this->resolveController($request);
-        if ($controller instanceof Controller) {
-            $controller->setContainer($this->container);
+        $controllerObject = $controller;
+        if (!$controllerObject instanceof Controller) {
+            $controllerObject = $controller[0] ?? null;
+        }
+
+        if ($controllerObject instanceof Controller) {
+            $controllerObject->setContainer($this->container);
             $requestHandler = new RequestHandler(
                 $this->container,
-                $controller->getMiddlewares(),
+                $controllerObject->getMiddlewares(),
                 static function (ServerRequestInterface $request) use ($controller) {
                     return self::callController($request, $controller);
                 }

+ 10 - 6
src/Package/MichelCorePackage.php

@@ -30,6 +30,7 @@ use Michel\RouterInterface;
 use Michel\RouterMiddleware;
 use Psr\Container\ContainerInterface;
 use Psr\EventDispatcher\EventDispatcherInterface;
+use Psr\Http\Message\ResponseFactoryInterface;
 use function getenv;
 
 final class MichelCorePackage implements PackageInterface
@@ -37,6 +38,9 @@ final class MichelCorePackage implements PackageInterface
     public function getDefinitions(): array
     {
         return [
+            ResponseFactoryInterface::class => static function (ContainerInterface $container): ResponseFactoryInterface {
+                return response_factory();
+            },
             RequestContext::class => static function (ContainerInterface $container): RequestContext {
                 return new RequestContext();
             },
@@ -106,21 +110,21 @@ final class MichelCorePackage implements PackageInterface
                 ]);
             },
             RouterMiddleware::class => static function (ContainerInterface $container) {
-                return new RouterMiddleware($container->get(RouterInterface::class), response_factory());
+                return new RouterMiddleware($container->get(RouterInterface::class), $container->get(ResponseFactoryInterface::class));
             },
             ForceHttpsMiddleware::class => static function (ContainerInterface $container) {
                 /**
                  * @var ConfigProvider $configProvider
                  */
                 $configProvider = $container->get(ConfigProvider::class);
-                return new ForceHttpsMiddleware($configProvider->isForceHttps(), response_factory());
+                return new ForceHttpsMiddleware($configProvider->isForceHttps(),$container->get(ResponseFactoryInterface::class));
             },
             IpRestrictionMiddleware::class => static function (ContainerInterface $container) {
                 /**
                  * @var ConfigProvider $configProvider
                  */
                 $configProvider = $container->get(ConfigProvider::class);
-                return new IpRestrictionMiddleware($configProvider->getAllowedIps(), response_factory());
+                return new IpRestrictionMiddleware($configProvider->getAllowedIps(), $container->get(ResponseFactoryInterface::class));
             },
             MaintenanceMiddleware::class => static function (ContainerInterface $container) {
                 /**
@@ -129,7 +133,7 @@ final class MichelCorePackage implements PackageInterface
                 $configProvider = $container->get(ConfigProvider::class);
                 return new MaintenanceMiddleware(
                     $configProvider->isMaintenance(),
-                    response_factory(),
+                    $container->get(ResponseFactoryInterface::class),
                     $configProvider->getAllowedIps()
                 );
             },
@@ -139,10 +143,10 @@ final class MichelCorePackage implements PackageInterface
                  */
                 $configProvider = $container->get(ConfigProvider::class);
 
-                return new ExceptionHandler(response_factory(), [
+                return new ExceptionHandler($container->get(ResponseFactoryInterface::class), [
                         'debug' => $container->get('michel.debug'),
                         'html_response' => new HtmlErrorRenderer(
-                            response_factory(),
+                            $container->get(ResponseFactoryInterface::class),
                             $container->get('michel.debug'),
                             filepath_join($configProvider->getTemplateDir(), '_exception')
                         )