diff --git a/config/route_arguments.php b/config/route_arguments.php new file mode 100644 index 0000000..88b0198 --- /dev/null +++ b/config/route_arguments.php @@ -0,0 +1,6 @@ + '([0-9]+)', + '{chars}' => '([A-Za-z]+)', + '{string}' => '([0-9A-Za-z]+)', +]; \ No newline at end of file diff --git a/config/views.php b/config/views.php new file mode 100644 index 0000000..28e6f05 --- /dev/null +++ b/config/views.php @@ -0,0 +1,4 @@ + 'base' +]; \ No newline at end of file diff --git a/src/Domain/Pages/PagesController.php b/src/Domain/Pages/PagesController.php index b8da0c1..33e47db 100644 --- a/src/Domain/Pages/PagesController.php +++ b/src/Domain/Pages/PagesController.php @@ -3,6 +3,7 @@ namespace App\Domain\Pages; use App\Domain\Controller; +use App\Infrastructure\View; /** * Controller pour les pages sans lien avec un contenu spécifique. @@ -14,7 +15,7 @@ class PagesController extends Controller { { return [ self::Route( routeUrl: '/', routeName: 'Homepage', routeAction: 'index' ), - self::ROute( routeUrl: '/test/{int}', routeName: 'test', routeAction: 'test' ), + self::Route( routeUrl: '/test/{string}/baba', routeName: 'test', routeAction: 'test' ), ]; } @@ -23,11 +24,11 @@ class PagesController extends Controller { * Route de la page d'accueil. * @return void */ - public function index(): void { - echo "Coucou"; + public function index(): View { + return new View( 'home', [ 'ok' => 'bla' ] ); } - public function test( int $id ): void { + public function test( string $id ): void { echo "Coucou" . $id; } diff --git a/src/Exceptions/InvalidViewException.php b/src/Exceptions/InvalidViewException.php new file mode 100644 index 0000000..9447cde --- /dev/null +++ b/src/Exceptions/InvalidViewException.php @@ -0,0 +1,13 @@ +routeUrl === self::$clientRouteString ){ + $routeName = self::getRegexRoute( $route ); + if( preg_match( $routeName, $clientRouteName, $matches ) ){ + array_shift( $matches ); + self::$clientRouteArguments = $matches; return $route; } - */ } return false; @@ -139,20 +143,22 @@ final class Router { } private static function getRegexRoute( Route $route ): string { - $routeUrl = $route->routeUrl; - $routeUrl = str_replace( "{int}", "([0-9]+)", $routeUrl ); - return $routeUrl; + $routeUrl = trim( $route->routeUrl, '/' ); + foreach ( Kernel::$configs['route_arguments'] as $key => $value ){ + $routeUrl = str_replace( $key, $value, $routeUrl ); + } + return "#^{$routeUrl}$#"; } /** - * Va permettre d'exécuter la méthode du Controller->action() en parsant les arguments si existants. + * Va permettre d'exécuter la méthode du Controller→action() en parsant les arguments si existants. * @return void */ private static function executeRouteAction(): void { $controller = self::$clientRoute->routeController; $method = self::$clientRoute->routeAction; - new $controller()->$method(); + new $controller()->$method( ...self::$clientRouteArguments); } } \ No newline at end of file diff --git a/src/Infrastructure/View.php b/src/Infrastructure/View.php new file mode 100644 index 0000000..2edf666 --- /dev/null +++ b/src/Infrastructure/View.php @@ -0,0 +1,194 @@ + + */ + public private(set) array $integratedContent; + + /** + * Garde la dernière instance de vue. + * Si il y a un squelette, ce sera l'instance du squelette. + * + * @var View + */ + private static self $lastInstance; + + /** + * Permet de construire les informations de la vue. + * + * @param string $viewName Le nom du fichier de vue. + * @param array $viewArgs Les arguments de la vue. + * @param bool $autoRender Si la méthode $this->render() est automatiquement exécuté. + * @param string|null $skeleton Le squelette du fichier, null correspond à aucun squelette, default correspond au + * squelette défini dans la configuration des vues. + * @param array $integratedContent Le contenu intégré dans le nouveau squelette. + */ + public function __construct( + string $viewName, + array $viewArgs = [], + bool $autoRender = true, + ?string $skeleton = 'default', + array $integratedContent = [] + ) { + + if( !str_ends_with( $viewName, '.php' ) ) { + $viewName .= '.php'; + } + + $this->viewName = $viewName; + $this->viewArgs = $viewArgs; + + $this->skeleton = $skeleton; + if( $this->skeleton === "default" ){ + $this->skeleton = Kernel::$configs['views']['base_view_skeleton']; + } + + $this->integratedContent = $integratedContent; + + try { + if (!file_exists(self::VIEW_PATH . $this->viewName)) { + throw new InvalidViewException($this->viewName); + } + + if ($autoRender) { + $this->render(); + } + } catch (InvalidViewException $e) { + die( $e->getMessage() ); + } + + } + + /** + * Permet de démarrer le rendu d'une vue. + * @return void + */ + public function startView(): void { + ob_start(); + } + + /** + * Permet de finir le rendu d'une vue. + * @return void + */ + public function endView(): void { + echo ob_get_clean(); + } + + /** + * Permet de faire le rendu proprement de la vue. + * @return void + */ + public function render(): void { + + self::$lastInstance = $this; + + if( $this->skeleton === null ){ + + // Si on a pas de squelette, on inclut la vue. + // pour accéder aux éléments de la vue, on utilise les méthodes statiques de cette classe. + $this->startView(); + require self::VIEW_PATH . $this->viewName; + $this->endView(); + + } else { + + // Si on a un squelette, on charge tout le contenu de la vue enfante. + $content = file_get_contents( self::VIEW_PATH . $this->viewName ); + + // On démarre la vue du squelette. + $base = new View( $this->skeleton, $this->viewArgs, skeleton: null, integratedContent: [ 'content' => $content ] ); + + } + + + } + + /* + * VIEW TOOLS + */ + + /** + * Permet d'injecter un contenu sauvegardé dans $this->integratedContent. + * + * @param string $integratedContentName + * @return void N'affiche rien si le contenu n'existe pas. + */ + public static function inject( string $integratedContentName ): void { + if( isset( self::$lastInstance->integratedContent[ $integratedContentName ] ) ) + echo self::$lastInstance->integratedContent[ $integratedContentName ]; + } + + /** + * Permet de récupérer un argument passé à la vue. + * + * @param string $argumentName + * @return mixed null si l'argument n'existe pas. + */ + public static function arg( string $argumentName ): mixed { + if( isset( self::$lastInstance->viewArgs[ $argumentName ] ) ) + return self::$lastInstance->viewArgs[ $argumentName ]; + return null; + } + + /** + * Permet d'intégrer un bloc à la vue. + * + * @param string $partialName + * @return void N'affiche rien si le bloc n'existe pas. + */ + public static function partial( string $partialName ): void { + + if( !str_ends_with( $partialName, '.php' ) ) { + $partialName .= '.php'; + } + + if( file_exists( self::VIEW_PATH . 'partials/' . $partialName ) ) { + require self::VIEW_PATH . 'partials/' . $partialName; + } + } + + public static function getHeadTitle(): string { + $siteUrl = Kernel::$configs['general']['website_name']; + return Router::$clientRoute->routeName . ' - ' . $siteUrl; + } + +} \ No newline at end of file diff --git a/src/Kernel.php b/src/Kernel.php index 163d0cb..01a8013 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -84,7 +84,11 @@ final class Kernel { */ private function loadConfig(): void { try { + self::$configs['general'] = ConfigFactory::loadConfigFile('general'); + self::$configs['route_arguments'] = ConfigFactory::loadConfigFile('route_arguments'); + self::$configs['views'] = ConfigFactory::loadConfigFile('views'); + } catch( ConfigFailedLoadingException $e ){ die( $e->getMessage() ); } diff --git a/views/base.php b/views/base.php new file mode 100644 index 0000000..c7aef16 --- /dev/null +++ b/views/base.php @@ -0,0 +1,7 @@ + + + + + + + diff --git a/views/home.php b/views/home.php new file mode 100644 index 0000000..eda17ba --- /dev/null +++ b/views/home.php @@ -0,0 +1 @@ +

Coucou

\ No newline at end of file diff --git a/views/partials/footer.php b/views/partials/footer.php new file mode 100644 index 0000000..da78eac --- /dev/null +++ b/views/partials/footer.php @@ -0,0 +1,4 @@ + + + + diff --git a/views/partials/header.php b/views/partials/header.php new file mode 100644 index 0000000..150db74 --- /dev/null +++ b/views/partials/header.php @@ -0,0 +1,9 @@ + + + + + + <?php echo V::getHeadTitle(); ?> + + +