From 0672cf7aaa11fd95797103ac6c8f9315cd9d115f Mon Sep 17 00:00:00 2001 From: bim-g Date: Sun, 22 Sep 2024 12:13:01 +0200 Subject: [PATCH 1/5] [UPD] refactoring to accesse root directory via getter method --- index.php | 2 +- src/Core/Application.php | 79 +++++++------------ src/Core/Bundles.php | 4 +- .../Views/Provider/ViewBuilderProvider.php | 2 +- src/Core/Views/View.php | 2 +- 5 files changed, 32 insertions(+), 57 deletions(-) diff --git a/index.php b/index.php index 581ee30..350e249 100644 --- a/index.php +++ b/index.php @@ -31,6 +31,6 @@ $app = new Application($ROOT_DIR, $configuration); -require_once $app::$ROOT_DIR . '/router/route.php'; +require_once $app::getRootDir() . '/router/route.php'; $app->run(); diff --git a/src/Core/Application.php b/src/Core/Application.php index 51b5a25..9832787 100644 --- a/src/Core/Application.php +++ b/src/Core/Application.php @@ -12,39 +12,40 @@ */ class Application { + /** + * @var array + */ + private static array $config_params = []; /** * define application global configuration * @var string */ - public static string $ROOT_DIR; + private static string $root_dir; /** * @var string */ public static string $APP_DOMAIN; /** - * @var string|mixed + * @var string */ public static string $APP_LANG; - /** - * @var string|mixed|null - */ - public static ?string $APP_TEMPLATE; /** * @var string */ - private static string $LAYOUT_CONTENT = 'layout_content'; + public static string $APP_TEMPLATE; /** * @var string */ - private static string $LAYOUT = ''; + public static string $LAYOUT_CONTENT; /** - * @var string + * @var string|null */ - private static string $VIEW_FOLDER = ''; + public static string $LAYOUT; + /** - * @var array + * @var string */ - private static array $params = []; + private static string $VIEW_FOLDER; /** * @var Router */ @@ -52,59 +53,33 @@ class Application /** * Application constructor. - * @param string $path path root directory of the application + * @param string $path root path directory of the application * @param AppConfiguration $config */ public function __construct(string $path, AppConfiguration $config) { - - self::$ROOT_DIR = str_replace("\\", '/', $path); - self::$APP_DOMAIN = $this->domainSetup()->app_domain; - self::$params = $config->generate(); - self::$APP_TEMPLATE = self::$params['app_template'] ?? null; - self::$APP_LANG = self::$params['lang'] ?? 'fr'; - $this->router = new Router(); + self::$config_params = $config->generate(); + self::$root_dir = str_replace("\\", '/', $path); + self::$APP_DOMAIN = serverDomain()->domain; + self::$APP_LANG = self::$config_params['lang'] ?? 'fr'; + self::$APP_TEMPLATE = self::$config_params['app_template'] ?? ''; self::$LAYOUT_CONTENT = 'layout_content'; + self::$LAYOUT = ''; + self::$VIEW_FOLDER = ''; + $this->router = new Router(); } - /** - * @return object - */ - private function domainSetup(): object + public static function getRootDir(): string { - $server_name = $_SERVER['SERVER_NAME']; - $protocol = strtolower(explode('/', $_SERVER['SERVER_PROTOCOL'])[0]); - $domain = self::getDomainIp() === '127.0.0.1' ? "$protocol://$server_name" : $server_name; - return (object)[ - 'server_name' => $server_name, - 'protocol' => $protocol, - 'app_domain' => $domain, - ]; + return self::$root_dir; } - /** - * use method to get domain ip - * @return string - */ - public static function getDomainIp() : string - { - $ip = $_SERVER['REMOTE_ADDR']; - - if (! empty($_SERVER['HTTP_CLIENT_IP'])) { - $ip = $_SERVER['HTTP_CLIENT_IP']; - } elseif (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; - } elseif ($ip == '::1') { - $ip = gethostbyname(getHostName()); - } - return $ip; - } /** * simple builtin dumper for dump data * @param $ex - * @return void + * */ - public static function dumper($ex) + public static function dumper($ex): void { print('
');
         var_dump($ex);
@@ -119,7 +94,7 @@ public static function dumper($ex)
      */
     public static function setLayout(string $layout)
     {
-        self::$LAYOUT = self::$ROOT_DIR.'/views/'.$layout;
+        self::$LAYOUT = self::getRootDir().'/views/'.$layout;
     }
     public static function setLayoutContent(string $layout_name)
     {
diff --git a/src/Core/Bundles.php b/src/Core/Bundles.php
index ef920e9..f8f1673 100644
--- a/src/Core/Bundles.php
+++ b/src/Core/Bundles.php
@@ -10,12 +10,12 @@ class Bundles
     private static array $header_link = [];
 
     /**
-     * manage to add a javascript script on the page
+     * manage to add a JavaScript script on the page
      * @param string $file
      */
     static function insertCSS(string $file)
     {
-        if (is_file(Application::$ROOT_DIR . '/assets/css/' . $file . '.css')) {
+        if (is_file(Application::getRootDir() . '/assets/css/' . $file . '.css')) {
             $href = WEB_ROOT . "assets/css/$file.css";
             $link = <<
diff --git a/src/Core/Views/Provider/ViewBuilderProvider.php b/src/Core/Views/Provider/ViewBuilderProvider.php
index 03923c8..620ed9e 100644
--- a/src/Core/Views/Provider/ViewBuilderProvider.php
+++ b/src/Core/Views/Provider/ViewBuilderProvider.php
@@ -87,7 +87,7 @@ public function renderHTML(string $html): void
      */
     public function setLayout(string $template): void
     {
-        $this->layout = Application::$ROOT_DIR . '/views' . $template;
+        $this->layout = Application::getRootDir() . '/views' . $template;
     }
 
     /**
diff --git a/src/Core/Views/View.php b/src/Core/Views/View.php
index 92a7763..97db5f8 100644
--- a/src/Core/Views/View.php
+++ b/src/Core/Views/View.php
@@ -96,7 +96,7 @@ private function buildFilePath(string $file_name): ?string
         $folder = strlen(trim($this->folder_name)) > 0 ? $this->folder_name : Application::getViewFolder();;
         $view_file = Escape::checkFileExtension($file_name);
         $file_source = $folder . Escape::addSlashes($view_file);
-        return Application::$ROOT_DIR . '/views' . $file_source;
+        return Application::getRootDir() . '/views' . $file_source;
     }
 
     /**

From d02c459379d4e782721e2a0094b4311d267452a8 Mon Sep 17 00:00:00 2001
From: bim-g 
Date: Sun, 22 Sep 2024 13:45:17 +0200
Subject: [PATCH 2/5] [UPD] refactoring to accesse layout path via getter
 method

---
 src/Core/Application.php | 38 +++++++++++++++++++++++++++++++-------
 src/Core/Views/View.php  | 11 +++++++++--
 2 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/src/Core/Application.php b/src/Core/Application.php
index 9832787..1f8907b 100644
--- a/src/Core/Application.php
+++ b/src/Core/Application.php
@@ -38,9 +38,9 @@ class Application
      */
     public static string $LAYOUT_CONTENT;
     /**
-     * @var string|null
+     * @var string
      */
-    public static string $LAYOUT;
+    private static string $layout;
 
     /**
      * @var string
@@ -64,11 +64,14 @@ public function __construct(string $path, AppConfiguration $config)
         self::$APP_LANG = self::$config_params['lang'] ?? 'fr';
         self::$APP_TEMPLATE = self::$config_params['app_template'] ?? '';
         self::$LAYOUT_CONTENT = 'layout_content';
-        self::$LAYOUT = '';
+        self::$layout = '';
         self::$VIEW_FOLDER = '';
         $this->router = new Router();
     }
 
+    /**
+     * @return string
+     */
     public static function getRootDir(): string
     {
         return self::$root_dir;
@@ -88,32 +91,53 @@ public static function dumper($ex): void
     }
 
     /**
-     * Set the layout at the top of your application to be available everywhere.
+     * Define a layout to be used by all pages in the application.
+     * can be set at the top of your application to be available everywhere.
      * @param string $layout
      * @return void
      */
     public static function setLayout(string $layout)
     {
-        self::$LAYOUT = self::getRootDir().'/views/'.$layout;
+        self::$layout = self::getRootDir() . '/views/' . trim($layout, '/');
     }
+
+    /**
+     * @param string $layout_name
+     * @return void
+     */
     public static function setLayoutContent(string $layout_name)
     {
         self::$LAYOUT_CONTENT = $layout_name;
     }
 
+    /**
+     * @param string $folder_name
+     * @return void
+     */
     public static function setViewFolder(string $folder_name)
     {
         self::$VIEW_FOLDER = $folder_name;
     }
-    public static function getLayout()
+
+    /**
+     * @return string|null
+     */
+    public static function getLayout(): ?string
     {
-        return self::$LAYOUT ;
+        return strlen(trim(self::$layout )) > 0 ? self::$layout : null;
     }
+
+    /**
+     * @return string
+     */
     public static function getLayoutContent()
     {
         return self::$LAYOUT_CONTENT ;
     }
 
+    /**
+     * @return string
+     */
     public static function getViewFolder()
     {
         return self::$VIEW_FOLDER ;
diff --git a/src/Core/Views/View.php b/src/Core/Views/View.php
index 97db5f8..0953356 100644
--- a/src/Core/Views/View.php
+++ b/src/Core/Views/View.php
@@ -77,15 +77,22 @@ public function display(string $view): void
     {
         $view_file = $this->buildFilePath($view);
         $render = $this->renderView($view_file);
-        if ($this->layout === '' && !$this->reset) {
+        if (! $this->getLayout() && !$this->reset) {
             $this->layout = Application::getLayout();
         }
-        if ($this->layout !== '') {
+        if ($this->getLayout()) {
             $render = $this->renderLayout($render);
         }
         $this->buildAssetHead($render);
     }
 
+    /**
+     * @return string|null
+     */
+    public function getLayout(): ?string
+    {
+        return strlen(trim($this->layout)) > 0 ? $this->layout : null;
+    }
     /**
      * @param class-string $file_name
      *

From 9a2f35af2bd08c4eabeb6f891bf4992d40a51923 Mon Sep 17 00:00:00 2001
From: bim-g 
Date: Sun, 22 Sep 2024 13:53:17 +0200
Subject: [PATCH 3/5] [UPD] refactoring to accesse layout param via getter
 method

---
 router/route.php         |  2 +-
 src/Core/Application.php | 12 ++++++------
 src/Core/Views/View.php  |  3 +--
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/router/route.php b/router/route.php
index 396b5c6..fc00b35 100644
--- a/router/route.php
+++ b/router/route.php
@@ -18,4 +18,4 @@
 $router->post('/changelang', [indexController::class, 'changeLang'])
     ->middleware([exampleValidation::class, 'changeLang']);
 
-include \Wepesi\Core\Application::$ROOT_DIR . './router/api.php';
\ No newline at end of file
+include \Wepesi\Core\Application::getRootDir() . './router/api.php';
\ No newline at end of file
diff --git a/src/Core/Application.php b/src/Core/Application.php
index 1f8907b..41b2bb7 100644
--- a/src/Core/Application.php
+++ b/src/Core/Application.php
@@ -36,7 +36,7 @@ class Application
     /**
      * @var string
      */
-    public static string $LAYOUT_CONTENT;
+    public static string $layout_content_param;
     /**
      * @var string
      */
@@ -63,7 +63,7 @@ public function __construct(string $path, AppConfiguration $config)
         self::$APP_DOMAIN = serverDomain()->domain;
         self::$APP_LANG = self::$config_params['lang'] ?? 'fr';
         self::$APP_TEMPLATE = self::$config_params['app_template'] ?? '';
-        self::$LAYOUT_CONTENT = 'layout_content';
+        self::$layout_content_param = 'layout_content';
         self::$layout = '';
         self::$VIEW_FOLDER = '';
         $this->router = new Router();
@@ -105,9 +105,9 @@ public static function setLayout(string $layout)
      * @param string $layout_name
      * @return void
      */
-    public static function setLayoutContent(string $layout_name)
+    public static function setLayoutcontentparam(string $layout_name)
     {
-        self::$LAYOUT_CONTENT = $layout_name;
+        self::$layout_content_param = $layout_name;
     }
 
     /**
@@ -130,9 +130,9 @@ public static function getLayout(): ?string
     /**
      * @return string
      */
-    public static function getLayoutContent()
+    public static function getLayoutContentParam(): string
     {
-        return self::$LAYOUT_CONTENT ;
+        return self::$layout_content_param ;
     }
 
     /**
diff --git a/src/Core/Views/View.php b/src/Core/Views/View.php
index 0953356..4819273 100644
--- a/src/Core/Views/View.php
+++ b/src/Core/Views/View.php
@@ -144,7 +144,7 @@ private function renderNotDefined(string $file_name): void
     protected function renderLayout(string $view)
     {
         if ($this->layout_content === '') {
-            $this->layout_content = Application::getLayoutContent();
+            $this->layout_content = Application::getLayoutContentParam();
         }
         if ($this->layout && is_file($this->layout)) {
             $layout_data = $this->data;
@@ -228,5 +228,4 @@ private function generateJSLink(string $path): string
     private function generateStyleLink(string $path): string {
         return '';
     }
-
 }

From 2ed0ea9829cd4c42858cfefe4f2c5920addc89c3 Mon Sep 17 00:00:00 2001
From: bim-g 
Date: Sun, 22 Sep 2024 15:50:22 +0200
Subject: [PATCH 4/5] [ENH] refactoring routing system to be more flexiblea and
 manageable via application

---
 .../Providers/Contracts/RouteContract.php     | 14 ++++
 .../Providers/Contracts/RouterContract.php    | 48 +++++++++++++
 .../Providers/Contracts/RouterProviders.php   | 18 +++++
 src/Core/Routing/Route.php                    | 23 ++++---
 src/Core/Routing/RouteFileRegistrar.php       | 46 +++++++++++++
 src/Core/Routing/Router.php                   | 69 +++++++++----------
 src/Core/Routing/Traits/routeBuilder.php      | 52 +++++++++-----
 7 files changed, 207 insertions(+), 63 deletions(-)
 create mode 100644 src/Core/Routing/Providers/Contracts/RouteContract.php
 create mode 100644 src/Core/Routing/Providers/Contracts/RouterContract.php
 create mode 100644 src/Core/Routing/Providers/Contracts/RouterProviders.php
 create mode 100644 src/Core/Routing/RouteFileRegistrar.php

diff --git a/src/Core/Routing/Providers/Contracts/RouteContract.php b/src/Core/Routing/Providers/Contracts/RouteContract.php
new file mode 100644
index 0000000..6438ad8
--- /dev/null
+++ b/src/Core/Routing/Providers/Contracts/RouteContract.php
@@ -0,0 +1,14 @@
+
  */
-class Route
+class Route implements RouteContract
 {
     /**
      * @var string
@@ -42,10 +44,11 @@ class Route
     use routeBuilder;
 
     /**
-     * @param $path
+     * @param class-string $path
      * @param $callable
+     * @param array $middleware
      */
-    function __construct($path, $callable, array $middleware = [])
+    function __construct(string $path, $callable, array $middleware = [])
     {
         $this->pattern = trim($path, '/');
         $this->callable = $callable;
@@ -56,10 +59,10 @@ function __construct($path, $callable, array $middleware = [])
     }
 
     /**
-     * @param $url
+     * @param class-string $url
      * @return bool
      */
-    function match($url): bool
+    function match(string $url): bool
     {
         $url = trim($url, '/');
         $path = preg_replace_callback('#:([\w]+)#', [$this, 'paramMatch'], $this->pattern);
@@ -80,16 +83,16 @@ function match($url): bool
     /**
      *
      */
-    public function call()
+    public function call(): void
     {
         try {
             if (count($this->middleware_tab) > 0) {
                 foreach ($this->middleware_tab as $middleware) {
-                    $this->routeFunctionCall($middleware, true, $this->_matches);
+                    $this->executeMiddleware($middleware, $this->_matches);
                 }
                 $this->middleware_tab = [];
             }
-            $this->routeFunctionCall($this->callable, false, $this->_matches);
+            $this->executeController($this->callable, $this->_matches);
         } catch (\Exception $ex) {
             echo $ex->getMessage();
         }
@@ -126,7 +129,7 @@ public function getPattern(): string
      * @param $params
      * @return array|string|string[]
      */
-    public function getUrl($params)
+    public function getUrl($params): array|string
     {
         $path = $this->pattern;
         foreach ($params as $k => $v) {
diff --git a/src/Core/Routing/RouteFileRegistrar.php b/src/Core/Routing/RouteFileRegistrar.php
new file mode 100644
index 0000000..ab97e15
--- /dev/null
+++ b/src/Core/Routing/RouteFileRegistrar.php
@@ -0,0 +1,46 @@
+
+ */
+final class RouteFileRegistrar implements RouterProviders
+{
+    /**
+     * @var RouterContract
+     */
+    protected RouterContract $router;
+
+    /**
+     * Create a new route file registrar instance.
+     *
+     * @param Router $router
+     */
+    public function __construct(RouterContract $router)
+    {
+        $this->router = $router;
+    }
+
+    /**
+     * Require the given routes file.
+     *
+     * @param class-string $routes
+     * @return void
+     */
+    public function register(string $routes): void
+    {
+        $router = $this->router;
+        if (is_file($routes)) {
+            require $routes;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Core/Routing/Router.php b/src/Core/Routing/Router.php
index 1b348e6..c90d51c 100644
--- a/src/Core/Routing/Router.php
+++ b/src/Core/Routing/Router.php
@@ -5,18 +5,23 @@
 
 namespace Wepesi\Core\Routing;
 
+use Closure;
 use Wepesi\Core\Application;
+use Wepesi\Core\Escape;
 use Wepesi\Core\Exceptions\RoutingException;
 use Wepesi\Core\Http\Response;
+use Wepesi\Core\Routing\Providers\Contracts\RouteContract;
+use Wepesi\Core\Routing\Providers\Contracts\RouterContract;
 use Wepesi\Core\Routing\Traits\routeBuilder;
 
 /**
- *  Wepesi API Router provider
+ * @template T
+ * @template-implements RouterContract
  */
-class  Router
+class  Router implements RouterContract
 {
     /**
-     * @var array|null
+     * @var array
      */
     protected array $baseMiddleware;
     /**
@@ -56,7 +61,7 @@ public function __construct()
     }
 
     /**
-     * @param $path
+     * @param string $path
      * @param $callable
      * @param null $name
      * @return Route
@@ -73,9 +78,9 @@ public function get(string $path, $callable, $name = null): Route
      * @param string $methode
      * @return Route
      */
-    private function add(string $pattern, $callable, ?string $name, string $methode): Route
+    private function add(string $pattern, $callable, ?string $name, string $methode): RouteContract
     {
-        $pattern = $this->baseRoute . '/' . trim($pattern, '/');
+        $pattern = $this->baseRoute . Escape::addSlashes(trim($pattern, '/'));
         $pattern = $this->baseRoute ? rtrim($pattern, '/') : $pattern;
         $route = new Route($pattern, $callable, $this->baseMiddleware);
         $this->routes[$methode][] = $route;
@@ -91,7 +96,7 @@ private function add(string $pattern, $callable, ?string $name, string $methode)
     }
 
     /**
-     * @param $path
+     * @param string $path
      * @param $callable
      * @param null $name
      * @return Route
@@ -117,24 +122,6 @@ public function delete(string $path, $callable, $name = null): Route
         return $this->add($path, $callable, $name, 'DELETE');
     }
 
-    /**
-     * API base group routing
-     * @param string|array $base_route it can be defined as we did for group routing, but you don't need to specify api, it will be added automatically
-     * @param callable $callable
-     * @return null
-     */
-    public function api($base_route, callable $callable)
-    {
-        $api_pattern = '/api';
-        if (is_array($base_route)) {
-            $base_route['pattern'] = $api_pattern . (isset($base_route['pattern']) ? $this->trimPath($base_route['pattern']) : '');
-        } else {
-
-            $base_route = $api_pattern . $this->trimPath($base_route);
-        }
-        return $this->group($base_route, $callable);
-    }
-
     /**
      * @param string $path
      * @return string
@@ -142,7 +129,7 @@ public function api($base_route, callable $callable)
     private function trimPath(string $path): string
     {
         $trim_path = trim($path, '/');
-        return strlen($trim_path) > 0 ? '/' . $trim_path : '';
+        return strlen($trim_path) > 0 ? Escape::addSlashes($trim_path) : '';
     }
 
     /**
@@ -151,7 +138,7 @@ private function trimPath(string $path): string
      * @param array|string $base_route can be a string or an array to defined middleware for the group routing
      * @param callable $callable a callable method can be a controller method or an anonymous callable method
      */
-    public function group($base_route, callable $callable)
+    public function group(array|string $base_route, $callable): void
     {
         $pattern = $base_route;
         if (is_array($base_route)) {
@@ -162,7 +149,12 @@ public function group($base_route, callable $callable)
         }
         $cur_base_route = $this->baseRoute;
         $this->baseRoute .= $pattern;
-        call_user_func($callable);
+
+        if ($callable instanceof Closure) {
+            call_user_func($callable, $this);
+        } else {
+            (new RouteFileRegistrar($this))->register($callable);
+        }
         $this->baseRoute = $cur_base_route;
     }
 
@@ -206,12 +198,12 @@ protected function getUrl()
     }
 
     /**
-     * Set the 404 handling function.
+     * Set the 404 handling functions.
      *
-     * @param object|callable|string $match_fn The function to be executed
+     * @param callable|object|string $match_fn The function to be executed
      * @param $callable
      */
-    public function set404($match_fn, $callable = null)
+    public function set404(callable|object|string $match_fn, $callable = null): void
     {
         if (!$callable) {
             $this->notFoundCallback = $match_fn;
@@ -221,7 +213,15 @@ public function set404($match_fn, $callable = null)
     }
 
     /**
-     * @return void
+     * list all routes elements
+     * @return array
+     */
+    public function getRoutes(): array
+    {
+        return $this->routes;
+    }
+    /**
+     * Execute the route request
      */
     public function run()
     {
@@ -240,7 +240,6 @@ public function run()
             }
             if (count($routesRequestMethod) === $i) {
                 $this->trigger404($this->notFoundCallback);
-                Response::setStatusCode(404);
             }
         } catch (RoutingException $ex) {
             Application::dumper($ex);
@@ -250,9 +249,9 @@ public function run()
     }
 
     /**
-     * @return void
+     * trigger 404 error while no route match
      */
-    protected function trigger404($match = null)
+    protected function trigger404($match = null): void
     {
         if ($match) {
             $this->routeFunctionCall($match);
diff --git a/src/Core/Routing/Traits/routeBuilder.php b/src/Core/Routing/Traits/routeBuilder.php
index cfd7315..f2db849 100644
--- a/src/Core/Routing/Traits/routeBuilder.php
+++ b/src/Core/Routing/Traits/routeBuilder.php
@@ -7,39 +7,45 @@
 
 use Wepesi\Core\Application;
 
+/**
+ *
+ */
 trait routeBuilder
 {
-    protected function routeFunctionCall($callable, bool $is_middleware = false, array $matches = []): void
+    /**
+     * @param $callable
+     * @param array $matches
+     * @param bool $is_middleware
+     * @return void
+     */
+    protected function routeFunctionCall($callable, array $matches = [], bool $is_middleware = false): void
     {
-        $controller = !$is_middleware ? 'controller' : 'middleware';
+        $class_element = !$is_middleware ? 'controller' : 'middleware';
         try {
             if (is_string($callable) || is_array($callable)) {
-                $params = is_string($callable) ? explode('#', $callable) : $callable;
-                if (count($params) != 2) {
-                    throw new \InvalidArgumentException("Error : on `$controller` class/method is not well defined");
+                $callable_params = is_string($callable) ? explode('#', $callable) : $callable;
+                if (count($callable_params) != 2) {
+                    throw new \InvalidArgumentException("Error : on `$class_element` class/method is not well defined");
                 }
 
-                $classCallable = $params[0];
-                $class_method = $params[1];
-                if (!class_exists($classCallable, true)) {
-                    throw new \InvalidArgumentException("$classCallable class not defined, not a valid $controller", 500);
+                $class_name = $callable_params[0];
+                $class_method_name = $callable_params[1];
+                if (!class_exists($class_name, true)) {
+                    throw new \InvalidArgumentException("$class_name class not defined, not a valid $class_element", 500);
                 }
 
-                $reflection = new \ReflectionClass($classCallable);
+                $reflection = new \ReflectionClass($class_name);
                 $class_instance = $reflection->newInstance();
 
                 if (!$reflection->isInstance($class_instance)) {
                     throw new \ReflectionException('Only instantiable class can be used. Not abstract,interface, or trait can be used.');
                 }
-                if (!method_exists($class_instance, $class_method)) {
-                    throw new \BadMethodCallException("method : $class_method does not belong the class : $classCallable.", 500);
-                }
-                call_user_func_array([$class_instance, $class_method], $matches);
-            } else {
-                $closure = $callable;
-                if (isset($closure) && is_callable($closure, true)) {
-                    call_user_func_array($closure, $matches);
+                if (!method_exists($class_instance, $class_method_name)) {
+                    throw new \BadMethodCallException("method : $class_method_name does not belong the class : $class_name.", 500);
                 }
+                call_user_func_array([$class_instance, $class_method_name], $matches);
+            } else if (isset($callable) && is_callable($callable, true)) {
+                call_user_func_array($callable, $matches);
             }
             return;
         } catch (\Exception $ex) {
@@ -47,4 +53,14 @@ protected function routeFunctionCall($callable, bool $is_middleware = false, arr
         }
     }
 
+    protected function executeController($controller, array $matches = []): void
+    {
+        $this->routeFunctionCall($controller, $matches);
+    }
+
+    protected function executeMiddleware($controller, array $matches = []): void
+    {
+        $this->routeFunctionCall($controller, $matches, true);
+    }
+
 }
\ No newline at end of file

From 16b122bfbfc70a2be706ccf44c4451201749d2fc Mon Sep 17 00:00:00 2001
From: bim-g 
Date: Sun, 22 Sep 2024 15:51:21 +0200
Subject: [PATCH 5/5] [ENH] refactoring routes path based on new structure

---
 ...exController.php => exampleController.php} |  2 +-
 index.php                                     |  4 +-
 router/api.php                                |  6 --
 routes/api.php                                | 10 +++
 router/route.php => routes/web.php            | 17 +++--
 src/Core/Application.php                      | 68 +++++++++++++++++--
 6 files changed, 89 insertions(+), 18 deletions(-)
 rename controller/{indexController.php => exampleController.php} (92%)
 delete mode 100644 router/api.php
 create mode 100644 routes/api.php
 rename router/route.php => routes/web.php (52%)

diff --git a/controller/indexController.php b/controller/exampleController.php
similarity index 92%
rename from controller/indexController.php
rename to controller/exampleController.php
index 3e4566c..6dceb06 100644
--- a/controller/indexController.php
+++ b/controller/exampleController.php
@@ -16,7 +16,7 @@
 use Wepesi\Core\Http\Redirect;
 use Wepesi\Core\Session;
 
-class indexController extends Controller
+class exampleController extends Controller
 {
     public function __construct()
     {
diff --git a/index.php b/index.php
index 350e249..7413128 100644
--- a/index.php
+++ b/index.php
@@ -17,7 +17,7 @@
 (new DotEnv($ROOT_DIR . '/.env'))->load();
 
 /**
- *  Generate and index file for redirection (protection) while APP_DEV in production
+ *  Generate and index a file for redirection (protection) while APP_DEV in production
  */
 if (getenv('APP_ENV') === 'prod') {
     autoIndexFolder(['assets']);
@@ -31,6 +31,4 @@
 
 $app = new Application($ROOT_DIR, $configuration);
 
-require_once $app::getRootDir() . '/router/route.php';
-
 $app->run();
diff --git a/router/api.php b/router/api.php
deleted file mode 100644
index 9be1e80..0000000
--- a/router/api.php
+++ /dev/null
@@ -1,6 +0,0 @@
-api('/', function () use ($router) {
-    $router->get('/home', function () {
-        \Wepesi\Core\Http\Response::send(['message' => 'Welcom to api routing']);
-    });
-});
diff --git a/routes/api.php b/routes/api.php
new file mode 100644
index 0000000..1406985
--- /dev/null
+++ b/routes/api.php
@@ -0,0 +1,10 @@
+router();
+$router->get('/', function () {
+    Response::send('Welcome to Wepesi API');
+});
\ No newline at end of file
diff --git a/router/route.php b/routes/web.php
similarity index 52%
rename from router/route.php
rename to routes/web.php
index fc00b35..6197dc0 100644
--- a/router/route.php
+++ b/routes/web.php
@@ -1,10 +1,16 @@
 router();
+
 // setup get started pages index
 $router->get('/', function () {
     (new View)->display('/home');
@@ -13,9 +19,12 @@
 $router->get('/helloworld', function () {
     (new View)->renderHTML('

Hello World!

'); }); -$router->get('/home', [\Wepesi\Controller\indexController::class,'home']); + +$router->get('/home', [exampleController::class,'home']); // -$router->post('/changelang', [indexController::class, 'changeLang']) +$router->post('/changelang', [exampleController::class, 'changeLang']) ->middleware([exampleValidation::class, 'changeLang']); -include \Wepesi\Core\Application::getRootDir() . './router/api.php'; \ No newline at end of file +$router->set404(function(){ + Response::send('route not defined', 404); +}); diff --git a/src/Core/Application.php b/src/Core/Application.php index 41b2bb7..4dedffd 100644 --- a/src/Core/Application.php +++ b/src/Core/Application.php @@ -120,11 +120,11 @@ public static function setViewFolder(string $folder_name) } /** - * @return string|null + * @return string */ - public static function getLayout(): ?string + public static function getLayout(): string { - return strlen(trim(self::$layout )) > 0 ? self::$layout : null; + return trim(self::$layout ); } /** @@ -153,9 +153,69 @@ public function router(): Router /** * @return void + * @throws \Exception + */ + protected function routeProvider(): void + { + $base_route_path = self::getRootDir() . '/routes'; + $api_route_path = $base_route_path . '/api.php'; + if (file_exists($api_route_path)) { + $this->router->group([ + 'pattern' => '/api' + ], function (Router $router) { + if (isset($_SERVER['HTTP_ORIGIN'])) { + // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one + // you want to allow, and if so: + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Max-Age: 86400'); // cache for 1 day + } + header('Access-Control-Allow-Methods: GET, POST,PUT, PATCH, HEAD, OPTIONS'); + // Access-Control headers are received during OPTIONS requests + if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + // may also be using PUT, PATCH, HEAD etc. + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) + header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); + + exit(0); + } + $router->group([], $this->registerRoute('/api.php')); + }); + } + $web_route_path = $base_route_path . '/web.php'; + if (file_exists($web_route_path)) { + $this->router->group([], $this->registerRoute('/web.php')); + } + if (!file_exists($web_route_path) && !file_exists($api_route_path)) { + throw new \Exception('No Route file not found.'); + } + } + + /** + * route path + * @param string $path + * @return string + */ + public function registerRoute(string $path): string + { + return $this->basePath('/routes' . '/' . trim($path,'/')); + } + /** + * @param string $path + * @return string + */ + public function basePath(string $path): string + { + return self::$root_dir . '/' . trim($path,'/'); + } + + /** + * @return void + * @throws \Exception */ - public function run() + public function run(): void { + $this->routeProvider(); $this->router->run(); } } \ No newline at end of file