From 44ba75c8d20323533d2098d7b3a924684101bbf8 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 18:49:44 +0200 Subject: [PATCH 1/6] Added coverage report in a Gitlab CI compatible format --- build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build.xml b/build.xml index e72a768..cbdc866 100644 --- a/build.xml +++ b/build.xml @@ -14,6 +14,7 @@ From 18f95e250cef2a89b086a81596b43799444545d3 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 18:53:32 +0200 Subject: [PATCH 2/6] Retry with care --- build.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/build.xml b/build.xml index cbdc866..e72a768 100644 --- a/build.xml +++ b/build.xml @@ -14,7 +14,6 @@ From 98f2daca4203adbaf6b22e9c2f40053da7c025f7 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 18:57:44 +0200 Subject: [PATCH 3/6] Finalized regular coverage --- build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build.xml b/build.xml index e72a768..8501bd0 100644 --- a/build.xml +++ b/build.xml @@ -15,6 +15,7 @@ From 884c421a464f85aed868c2bf96335aa198b800c1 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 19:32:22 +0200 Subject: [PATCH 4/6] Added regular coverage report --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index 8501bd0..95d4a47 100644 --- a/build.xml +++ b/build.xml @@ -15,7 +15,7 @@ From b4a574dadf7c3b65b12ff374251ff768ef20ffde Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 20:42:50 +0200 Subject: [PATCH 5/6] Removed files that are not important to the core --- Application/Config/config.mailer.php | 12 ------ Application/Config/config.sessions.php | 4 -- Application/Events/put_events_here | 0 Application/Views/view.default.tpl | 52 ------------------------- Application/Views/view.email_verify.tpl | 29 -------------- 5 files changed, 97 deletions(-) delete mode 100644 Application/Config/config.mailer.php delete mode 100644 Application/Config/config.sessions.php delete mode 100644 Application/Events/put_events_here delete mode 100644 Application/Views/view.default.tpl delete mode 100644 Application/Views/view.email_verify.tpl diff --git a/Application/Config/config.mailer.php b/Application/Config/config.mailer.php deleted file mode 100644 index ae1a0c7..0000000 --- a/Application/Config/config.mailer.php +++ /dev/null @@ -1,12 +0,0 @@ - true, - 'smtp_enabled' => false, - 'smtp_host' => '', - 'smtp_port' => 25, - 'smtp_auth' => false, - 'smtp_username' => '', - 'smtp_password' => '', - 'smtp_debug_level' => 0, - 'sender_name' => '', - 'sender_mail' => '', -) ; \ No newline at end of file diff --git a/Application/Config/config.sessions.php b/Application/Config/config.sessions.php deleted file mode 100644 index c9e15b1..0000000 --- a/Application/Config/config.sessions.php +++ /dev/null @@ -1,4 +0,0 @@ - '', - 'urlSelector' => '', -) ; \ No newline at end of file diff --git a/Application/Events/put_events_here b/Application/Events/put_events_here deleted file mode 100644 index e69de29..0000000 diff --git a/Application/Views/view.default.tpl b/Application/Views/view.default.tpl deleted file mode 100644 index 4ea6301..0000000 --- a/Application/Views/view.default.tpl +++ /dev/null @@ -1,52 +0,0 @@ - - - {$title} - - - - -
-
- -
- - - -
-
-
-
- - - - -
- - \ No newline at end of file diff --git a/Application/Views/view.email_verify.tpl b/Application/Views/view.email_verify.tpl deleted file mode 100644 index 9d1b741..0000000 --- a/Application/Views/view.email_verify.tpl +++ /dev/null @@ -1,29 +0,0 @@ - - -
Fuze Netwerk Logo
- - -
- -

Welcome to {$siteName}!

-

Please verify your account by clicking the button below:

- - - -

If the button does not work, please copy the following link into your browser:

-{$verifyURL}?code={$code} - -

Thank you for registering to {$siteName}, have a nice day!

- -
- -
- - \ No newline at end of file From dd93772704b47a84c40849be061eae92ed7d8558 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 3 May 2015 22:50:36 +0200 Subject: [PATCH 6/6] Router and Logger merge with GF, and many more CI Tests --- Application/Config/config.routes.php | 8 + .../Controller/controller.standard.php | 7 - Core/Events/event.routerLoadCallableEvent.php | 41 ++ Core/Events/event.routerRouteEvent.php | 36 +- Core/Events/event.routerSetPathEvent.php | 25 ++ Core/System/class.abstract.bus.php | 3 +- Core/System/class.config.php | 1 - Core/System/class.core.php | 7 +- Core/System/class.events.php | 1 - Core/System/class.exceptions.php | 45 ++ Core/System/class.layout.php | 5 +- Core/System/class.logger.php | 23 +- Core/System/class.router.php | 397 ++++++++++++++++++ Modules/databasemodel/class.model.php | 1 - Modules/router/class.router.php | 156 ------- Modules/sections/moduleInfo.php | 2 +- index.php | 2 - tests/core_routerTest.php | 126 ++++++ tests/event_routerLoadCallableEventTest.php | 82 ++++ tests/event_routerRouteEventTest.php | 45 ++ tests/event_routerRouterSetPathEventTest.php | 83 ++++ 21 files changed, 906 insertions(+), 190 deletions(-) create mode 100644 Application/Config/config.routes.php create mode 100644 Core/Events/event.routerLoadCallableEvent.php create mode 100644 Core/Events/event.routerSetPathEvent.php create mode 100644 Core/System/class.exceptions.php create mode 100644 Core/System/class.router.php delete mode 100644 Modules/router/class.router.php create mode 100644 tests/core_routerTest.php create mode 100644 tests/event_routerLoadCallableEventTest.php create mode 100644 tests/event_routerRouteEventTest.php create mode 100644 tests/event_routerRouterSetPathEventTest.php diff --git a/Application/Config/config.routes.php b/Application/Config/config.routes.php new file mode 100644 index 0000000..dd2353a --- /dev/null +++ b/Application/Config/config.routes.php @@ -0,0 +1,8 @@ +.*?))$/' => array( +// 'controller' => 'home' +// ), + '/^(?P.*?)(|\/(?P.*?)(|\/(?P.*?)))$/', +); \ No newline at end of file diff --git a/Application/Controller/controller.standard.php b/Application/Controller/controller.standard.php index 90ebfc5..ce5eaae 100644 --- a/Application/Controller/controller.standard.php +++ b/Application/Controller/controller.standard.php @@ -11,13 +11,6 @@ class Standard extends Controller { public function index($path = null) { $this->layout->view('maintenance'); } - - public function not_found($path = null) { - $this->logger->http_error(404); - $this->layout->assign('page', $_SERVER['REQUEST_URI']); - $this->layout->assign('mail', $this->config->main->administrator_mail); - $this->layout->view('404'); - } } diff --git a/Core/Events/event.routerLoadCallableEvent.php b/Core/Events/event.routerLoadCallableEvent.php new file mode 100644 index 0000000..40a4907 --- /dev/null +++ b/Core/Events/event.routerLoadCallableEvent.php @@ -0,0 +1,41 @@ +callable = $callable; + $this->controller = $controller; + $this->function = $function; + $this->parameters = $parameters; + } +} \ No newline at end of file diff --git a/Core/Events/event.routerRouteEvent.php b/Core/Events/event.routerRouteEvent.php index 4441290..adaf352 100644 --- a/Core/Events/event.routerRouteEvent.php +++ b/Core/Events/event.routerRouteEvent.php @@ -2,18 +2,28 @@ use \FuzeWorks\Event; -class RouterRouteEvent extends Event { - - public $controller; - public $function; - public $parameters; - public $directory; +/** + * Class routerRouteEvent + * + * Fired after the router has extracted the path + * + * @package System\Events + */ +class routerRouteEvent extends Event{ - public function init($controller, $function, $parameters){ - $this->controller = $controller; - $this->function = $function; - $this->parameters = $parameters; + /** + * @var array The routing table + */ + public $routes; + + /** + * @var boolean Whether the callable will be loaded directly after or not + */ + public $loadCallable; + + public function init($routes, $loadCallable){ + + $this->routes = $routes; + $this->loadCallable = $loadCallable; } -} - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/Core/Events/event.routerSetPathEvent.php b/Core/Events/event.routerSetPathEvent.php new file mode 100644 index 0000000..59e43ab --- /dev/null +++ b/Core/Events/event.routerSetPathEvent.php @@ -0,0 +1,25 @@ +path = $path; + } +} + +?> \ No newline at end of file diff --git a/Core/System/class.abstract.bus.php b/Core/System/class.abstract.bus.php index 2be7358..bfa7397 100644 --- a/Core/System/class.abstract.bus.php +++ b/Core/System/class.abstract.bus.php @@ -6,7 +6,7 @@ abstract class Bus { protected $core; protected $mods; - protected $library; + protected $router; protected $config; protected $logger; protected $models; @@ -22,6 +22,7 @@ abstract class Bus { $this->models = &$core->mods->models; $this->layout = &$core->mods->layout; $this->events = &$core->mods->events; + $this->router = &$core->mods->router; } } diff --git a/Core/System/class.config.php b/Core/System/class.config.php index 856c149..4d8b9ce 100644 --- a/Core/System/class.config.php +++ b/Core/System/class.config.php @@ -1,7 +1,6 @@ buildRegister(); $this->mods->events->buildEventRegister(); + // And initialize the router paths + $this->mods->router->init(); + $event = $this->mods->events->fireEvent('coreStartEvent'); if ($event->isCancelled()) { return true; @@ -55,6 +57,7 @@ class Core { require_once("Core/System/class.abstract.model.php"); require_once("Core/System/class.abstract.controller.php"); require_once("Core/System/class.abstract.eventPriority.php"); + require_once("Core/System/class.exceptions.php"); // Load the core classes require_once("Core/System/class.config.php"); @@ -62,6 +65,7 @@ class Core { require_once("Core/System/class.models.php"); require_once("Core/System/class.layout.php"); require_once("Core/System/class.events.php"); + require_once("Core/System/class.router.php"); // Load them $this->mods->events = new Events ($this); @@ -69,6 +73,7 @@ class Core { $this->mods->logger = new Logger ($this); $this->mods->models = new Models ($this); $this->mods->layout = new Layout ($this); + $this->mods->router = new Router ($this); $this->loaded = true; } diff --git a/Core/System/class.events.php b/Core/System/class.events.php index b12d8ec..0c11efb 100644 --- a/Core/System/class.events.php +++ b/Core/System/class.events.php @@ -5,7 +5,6 @@ */ namespace FuzeWorks; -use \Exception; /** * Event Class diff --git a/Core/System/class.exceptions.php b/Core/System/class.exceptions.php new file mode 100644 index 0000000..c539c1a --- /dev/null +++ b/Core/System/class.exceptions.php @@ -0,0 +1,45 @@ +logger->logError('Could not load view '.$directory.'/'.$vw.' :: ' . $e->getMessage(), 'Layout', __FILE__, __LINE__); - throw new Exception\Layout('Could not load view '.$directory.'/'.$vw); + throw new LayoutException('Could not load view '.$directory.'/'.$vw); } } @@ -160,7 +159,7 @@ class Layout extends Bus { // Throw error on failure $this->logger->logError('Could not load view '.$directory.'/view.'.$view.'.tpl :: ' . $e->getMessage(), 'Layout', __FILE__, __LINE__); - throw new Exception\Layout('Could not load view '.$directory.'/view.'.$view.'.tpl'); + throw new LayoutException('Could not load view '.$directory.'/view.'.$view.'.tpl'); } } } \ No newline at end of file diff --git a/Core/System/class.logger.php b/Core/System/class.logger.php index 7f5f126..c6e02c7 100644 --- a/Core/System/class.logger.php +++ b/Core/System/class.logger.php @@ -1,7 +1,6 @@ events->addListener(array($this, 'shutdown'), 'coreShutdownEvent', EventPriority::LOWEST); + $this->debug = $this->config->error->debug; $this->newLevel("Logger Initiated"); } @@ -49,7 +50,7 @@ class Logger extends Bus{ $this->logInfo($this->backtrace()); } - if ($this->mods->config->error->debug == true || $this->print_to_screen) { + if ($this->debug == true || $this->print_to_screen) { $this->log("Parsing debug log", "Logger"); $this->logToScreen(); } @@ -263,7 +264,7 @@ class Logger extends Bus{ return $type = 'Unknown error: '.$type; } - public function http_error($errno){ + public function http_error($errno = 500, $view = true){ $http_codes = array( @@ -305,6 +306,22 @@ class Logger extends Bus{ $this->logError('HTTP-error '.$errno.' called', 'Logger'); $this->logInfo('Sending header HTTP/1.1 '.$errno.' '.$http_codes[$errno], 'Logger', __FILE__, __LINE__); header('HTTP/1.1 '.$errno.' '.$http_codes[$errno]); + + // Do we want the error-view with it? + if($view == false) + return; + + $view = 'errors/'.$errno; + $this->logger->log('Loading view '.$view); + + try{ + + $this->layout->view($view); + }catch(LayoutException $exception){ + + // No error page could be found, just echo the result + echo "

$errno

".$http_codes[$errno]."

"; + } } /** diff --git a/Core/System/class.router.php b/Core/System/class.router.php new file mode 100644 index 0000000..006280e --- /dev/null +++ b/Core/System/class.router.php @@ -0,0 +1,397 @@ +config->routes as $route => $callable){ + + if(is_int($route)) { + + $route = $callable; + $callable = array($this, 'defaultCallable'); + } + + $this->addRoute($route, $callable, false); + } + } + + /** + * Returns the current routing path + * + * @return bool|string + */ + public function getPath(){ + + return $this->path; + } + + /** + * Returns an array with all the routes + * @return array + */ + public function getRoutes(){ + + return $this->routes; + } + + /** + * Returns the currently loaded callable + * @return null|callable + */ + public function getCallable(){ + + return $this->callable; + } + + /** + * Returns the active controller + * + * @return null|Controller The controller object + */ + public function getController() { + + return $this->controller; + } + + /** + * Returns the name of the function + * + * @return null|string The name of the function + */ + public function getFunction() { + + return $this->function; + } + + /** + * Returns the routing parameters + * + * @return array + */ + public function getParameters(){ + + return $this->parameters; + } + + /** + * Returns the routing parameter at given index + * + * @param int $index + * @return array + */ + public function getParameter($index = 0){ + + $parameters = $this->parameters; + $index = ($index >= 0 ? $index : count($parameters)+$index); + + if(isset($parameters[$index])) + return $parameters[$index]; + + return null; + } + + /** + * Set the current routing path + * + * @param string $path The routing path (e.g. a/b/c/d/e) + * @return bool|string + */ + public function setPath($path){ + // Fire the event to notify our modules + $event = $this->events->fireEvent('routerSetPathEvent', $path); + + // The event has been cancelled + if($event->isCancelled()){ + + return false; + } + + // Remove double slashes + $event->path = preg_replace('@[/]+@', '/', $event->path); + + // Remove first slash + if(substr($event->path, 0, 1) == '/') + $event->path = substr($event->path, 1); + + // Remove trailing slash + if(substr($event->path, -1, 1) == '/') + $event->path = substr($event->path, 0, strlen($event->path)-1); + + return $this->path = $event->path; + } + + /** + * Add a route + * + * The path will be checked before custom routes before the default route(/controller/function/param1/param2/etc) + * When the given RegEx matches the current routing-path, the callable will be called. + * + * The callable will be called with three arguments: + * + * Callable($controller, $function, $parameters) + * + * These three variables will be extracted from the named groups of your RegEx. When one or more named groups are + * not matched, they will be set to NULL. The default RegEx is: + * + * /^(?P.*?)(|\/(?P.*?)(|\/(?P.*?)))$/ + * + * ^ Named group 1 ^ Named group 2 ^ Named group 3 + * + * Named group 1 is named 'controller' and thus will become $controller + * Named group 2 is named 'function' and thus will become $function + * Named group 3 is named 'parameters' and thus will become $parameters + * + * You can also add aliases with the following: + * + * '/^this-is-an-alias$/' => array( + * 'controller' => 'home', + * 'function' => 'index', + * 'parameters' => array() + * ), + * + * This will link '/this-is-an-alias/ to /home/index. It is also possible to use the three named capture groups + * for the function, parameters or controllers. Like this: + * + * '/^alias(|\-(?P.*?))$/' => array( + * 'controller' => 'home' + * ), + * + * This will mask '/alias' to '/home' and '/alias-test' to 'home/test'. + * + * You do not *have* to use named groups, but when you don't the arguments will be left NULL; and you will need to + * extract the information from the routing-path yourself. + * + * @param string $route This is a RegEx of the route, Every capture group will be a parameter + * @param callable $callable The callable to execute + * @param bool $prepend Whether or not to insert at the beginning of the routing table + */ + public function addRoute($route, $callable, $prepend = true){ + + if($prepend) + $this->routes = array($route => $callable) + $this->routes; + else + $this->routes[$route] = $callable; + + $this->logger->log('Route added at '.($prepend ? 'top' : 'bottom').': "'.$route.'"'); + } + + /** + * Removes a route from the array based on the given route + * + * @param $route string The route to remove + */ + public function removeRoute($route){ + + unset($this->routes[$route]); + + $this->logger->log('Route removed: '.$route); + } + + /** + * Extracts the routing path to controller, function and parameters + * + * @param boolean $loadCallable Immediate load the callable after routing + */ + public function route($loadCallable = true) + { + // Default values + $callable = null; + $args = array(); + + $controller = null; + $function = null; + $parameters = null; + + // Fire the event to notify our modules + $event = $this->events->fireEvent('routerRouteEvent', $this->routes, $loadCallable); + + // The event has been cancelled + if($event->isCancelled()){ + + return; + } + + // Assign everything to the object to make it accessible, but let modules check it first + $this->routes = $event->routes; + $loadCallable = $event->loadCallable; + + //Check the custom routes + foreach ($this->routes as $r => $c) { + + //A custom route is found + if(preg_match($r, $this->path, $matches)) { + + $controller = !empty($matches['controller']) ? $matches['controller'] : null; + $function = !empty($matches['function']) ? $matches['function'] : null; + $parameters = !empty($matches['parameters']) ? explode('/', $matches['parameters']) : null; + + $this->logger->log('Route matched: '.$r); + + $callable = $c; + break; + } + } + + $this->callable = $callable; + $this->controller = $controller; + $this->function = $function; + $this->parameters = $parameters; + + // Check if we found a callable anyway + if($this->callable === null){ + + $this->logger->logWarning('No routes found for given path: "'.$this->path.'"', 'Router'); + $this->logger->http_error(404); + return; + } + + if($loadCallable) + $this->loadCallable(); + } + + /** + * Load and execute the callable + */ + public function loadCallable(){ + + $this->logger->newLevel('Loading callable'); + + // Fire the event to notify our modules + $event = $this->events->fireEvent('routerLoadCallableEvent', $this->callable, $this->controller, $this->function, $this->parameters); + + // The event has been cancelled + if($event->isCancelled()){ + + return; + } + + // Assign everything to the object to make it accessible, but let modules check it first + $this->callable = $event->callable; + $this->controller = $event->controller; + $this->function = $event->function; + $this->parameters = $event->parameters; + + if(!is_callable($this->callable)) + if(isset($this->callable['controller'])) { + + $this->controller = isset($this->callable['controller']) ? $this->callable['controller'] : $this->controller; + $this->function = isset($this->callable['function']) ? $this->callable['function'] : $this->function; + $this->parameters = isset($this->callable['parameters']) ? $this->callable['parameters'] : $this->parameters; + + $this->callable = array($this, 'defaultCallable'); + }else{ + + $this->logger->log('The given callable is not callable!', E_ERROR); + $this->error->http_error(500); + $this->logger->stopLevel(); + return; + } + + $args = array( + $this->controller, + $this->function, + $this->parameters, + ); + + $this->logger->newLevel('Calling Callable'); + $this->logger->log('Controller: '. ($args[0] === null ? 'null' : $args[0])); + $this->logger->log('Function: '. ($args[1] === null ? 'null' : $args[1])); + $this->logger->log('Parameters: '. (empty($args[2]) ? '[]' : implode(', ',$args[2]))); + $this->logger->stopLevel(); + + call_user_func_array($this->callable, $args); + + $this->logger->stopLevel(); + } + + /** + * The default callable + * + * This callable will do the 'old skool' routing. It will load the controllers from the controller-directory + * in the application-directory. + */ + public function defaultCallable(){ + + $this->logger->log('Default callable called!'); + + $this->controller = $this->controller === null ? $this->config->main->default_controller : $this->controller; + $this->function = $this->function === null ? $this->config->main->default_function : $this->function; + + // Construct file paths and classes + $class = '\Controller\\'.ucfirst($this->controller); + $file = 'Application/Controller/controller.'.$this->controller.'.php'; + + $this->logger->log('Loading controller '.$class.' from file: '.$file); + + // Check if the file exists + if(file_exists($file)){ + + if(!class_exists($class)) + require $file; + + $this->callable = new $class($this->core); + + // Check if method exists or if there is a caller function + if(method_exists($this->callable, $this->function) || method_exists($this->callable, '__call')){ + + // Execute the function on the controller + $this->callable->{$this->function}($this->parameters); + }else{ + + // Function could not be found + $this->logger->log('Could not find function '.$this->function.' on controller '.$class); + $this->error->http_error(404); + } + }else{ + + // Controller could not be found + $this->logger->log('Could not find controller '.$class); + $this->logger->http_error(404); + } + } +} +?> \ No newline at end of file diff --git a/Modules/databasemodel/class.model.php b/Modules/databasemodel/class.model.php index 90d72a5..d58941d 100644 --- a/Modules/databasemodel/class.model.php +++ b/Modules/databasemodel/class.model.php @@ -3,7 +3,6 @@ namespace Module; use \FuzeWorks\Module; use \FuzeWorks\ModelServer; -use \Exception; class DatabaseModel extends Module implements ModelServer { diff --git a/Modules/router/class.router.php b/Modules/router/class.router.php deleted file mode 100644 index cf30d71..0000000 --- a/Modules/router/class.router.php +++ /dev/null @@ -1,156 +0,0 @@ -path = $path; - } - - public function getPath() { - return $this->path; - } - - public function getRoute($index = null) { - if ($index === null) - return $this->route; - return $this->route[$index]; - } - - public function getParameters() { - return $this->parameters; - } - - public function getParameter($index = 0) { - $parameters = $this->getParameters(); - return ($index >= 0 ? $parameters[$index] : $parameters[count($parameters)+$index]); - } - - /** - * Extracts the routing path to controller, function and parameters - * - * Path structure: /controller/function/par1/par2... - */ - public function route(){ - // Retrieve the path and convert it to a proper format - $path = (!empty($this->getPath()) ? explode('/', preg_replace('#/+#','/',$this->getPath())) : array()); - $path_size = count($path); - - // If trailing slash was given or the last element was empty: remove it - if(end($path) == ''){ - array_pop($path); - } - - // Perform a routing check - // Prepare CONTROLLER, FUNCTION and PARAMS variables - $CONTROLLER = ""; - $FUNCTION = ""; - $PARAMS = array(); - - // First check if anything is given - if ($path_size >= 1) { - $CONTROLLER = $path[0]; - if ($path_size >= 2) { - $FUNCTION = $path[1]; - if ($path_size >= 3) { - $PARAMS = array_slice($path, 2); - } - } - } else { - // Default controller, default function, no arguments - $CONTROLLER = 'standard'; - } - - // Fire the event to notify our modules - $event = $this->events->fireEvent('routerRouteEvent', $CONTROLLER, $FUNCTION, $PARAMS); - - // The event has been cancelled - if($event->isCancelled()){ - return; - } - - // Assign everything to the object to make it accessible, but let modules check it first - $this->route = $path; - $this->controllerName = ($event->controller === null || empty($event->controller) ? $this->config->main->default_controller : $event->controller); - $this->function = ($event->function === null || empty($event->function) ? $this->config->main->default_function : $event->function); - $this->parameters = $event->parameters; - $this->directory = ($event->directory === null || empty($event->directory) ? "Application/Controller/" : $event->directory); - } - - /** - * Load a controller - * @access public - */ - public function loadController() { - // Initate the controllerLoadEvent - $event = $this->events->fireEvent('controllerLoadEvent', - $this->route, - $this->controllerName, - $this->function, - $this->parameters, - $this->directory - ); - - $this->route = ($event->route === null ? $this->route : $event->route); - $this->controllerName = ($event->controllerName === null ? $this->controllerName : $event->controllerName); - $this->function = ($event->function === null ? $this->function : $event->function); - $this->parameters = ($event->parameters === null ? $this->parameters : $event->parameters); - $this->directory = ($event->directory === null ? $this->directory : $event->directory); - - $file = $this->directory . "controller.".strtolower($this->controllerName).".php"; - $this->logger->log("Loading controller from file: '".$file."'"); - - if (file_exists($file)) { - if (!class_exists(ucfirst($this->controllerName))) - require_once($file); - - $this->controllerClass = "\Controller\\" . ucfirst($this->controllerName); - $this->controller = new $this->controllerClass($this->core); - - if (method_exists($this->controller, $this->function) || method_exists($this->controller, '__call')) { - $this->controller->{$this->function}($this->parameters); - } elseif (method_exists($this->controller, 'not_found')) { - // Trying last resort - $this->logger->log("Function was not found, trying Controllers not_found function"); - - // Add the function to the parameters just because it's usefull - array_unshift($this->parameters, $this->function); - $this->controller->not_found($this->parameters); - } else { - $this->logger->logError("Could not load not_found function. Aborting"); - // totally not found - } - } else { - $this->logger->logError("Could not find class. Reverting to default controller not_found"); - $file = $this->directory . "controller.".strtolower($this->config->main->default_controller).".php"; - if (file_exists($file)) - require_once($file); - $this->controllerClass = ucfirst($this->config->main->default_controller); - $this->controller = new $this->controllerClass($this->core); - - // Add the function to the parameters just because it's usefull - array_unshift($this->parameters, $this->function); - $this->controller->not_found($this->parameters); - } - } -} - -?> \ No newline at end of file diff --git a/Modules/sections/moduleInfo.php b/Modules/sections/moduleInfo.php index 2441594..895b25e 100644 --- a/Modules/sections/moduleInfo.php +++ b/Modules/sections/moduleInfo.php @@ -18,5 +18,5 @@ return array( 'date_created' => '29-04-2015', 'date_updated' => '29-04-2015', - 'enabled' => true, + 'enabled' => false, ); diff --git a/index.php b/index.php index 89e32ed..8ed525e 100644 --- a/index.php +++ b/index.php @@ -5,9 +5,7 @@ require_once( dirname(__FILE__) . "/Core/System/class.core.php"); // Load it $core = new \FuzeWorks\Core(); $core->init(); -$core->loadMod('router'); $core->mods->router->setPath( (isset($_GET['path']) ? $_GET['path'] : null) ); $core->mods->router->route(); -$core->mods->router->loadController(); ?> \ No newline at end of file diff --git a/tests/core_routerTest.php b/tests/core_routerTest.php new file mode 100644 index 0000000..c858a43 --- /dev/null +++ b/tests/core_routerTest.php @@ -0,0 +1,126 @@ +createCore(); + + // Act and assert + $core->mods->router->setPath('a/b/c/d/'); + $this->assertEquals('a/b/c/d', $core->mods->router->getPath()); + + $core->mods->router->setPath('//a//b//c'); + $this->assertEquals('a/b/c', $core->mods->router->getPath()); + + $core->mods->router->setPath('/'); + $this->assertEquals('', $core->mods->router->getPath()); + + $core->mods->router->setPath(''); + $this->assertEquals('', $core->mods->router->getPath()); + + $core->mods->router->setPath(false); + $this->assertEquals('', $core->mods->router->getPath()); + + $core->mods->router->setPath(null); + $this->assertEquals('', $core->mods->router->getPath()); + } + + /** + * @depends testParsePath + */ + public function testDoRoute(){ + + $core = $this->createCore(); + + // Act + $core->mods->router->setPath('a/b/c/d/'); + $core->mods->router->route(false); + + // Assert + // Whole route + $this->assertEquals(array('a','b',array('c','d')), array($core->mods->router->getController(), $core->mods->router->getFunction(), $core->mods->router->getParameters())); + $this->assertEquals('a', $core->mods->router->getController()); + $this->assertEquals('d', $core->mods->router->getParameter(-1)); + $this->assertEquals(null, $core->mods->router->getParameter(5)); + + // Parameters + $this->assertEquals(array('c','d'), $core->mods->router->getParameters()); + $this->assertEquals('c', $core->mods->router->getParameter(0)); + $this->assertEquals('d', $core->mods->router->getParameter(-1)); + + // Function and controller + $this->assertEquals('a', $core->mods->router->getController()); + $this->assertEquals('b', $core->mods->router->getFunction()); + } + + /** + * @depends testDoRoute + */ + public function testOddRoutes(){ + + $core = $this->createCore(); + + // Empty path + $core->mods->router->setPath(null); + $core->mods->router->route(false); + $this->assertEquals(null, $core->mods->router->getController()); + + // Double slashes + $core->mods->router->setPath('a///b'); + $core->mods->router->route(false); + $this->assertEquals(array('a','b'), array($core->mods->router->getController(), $core->mods->router->getFunction())); + + // Escaped path path + $core->mods->router->setPath('/a\/b\/c/'); + $core->mods->router->route(false); + $this->assertEquals(array('a\\','b\\','c'), array($core->mods->router->getController(), $core->mods->router->getFunction(), $core->mods->router->getParameter(0))); + $this->assertNotEquals('a', $core->mods->router->getController()); + } + + public function testCustomRoute(){ + + $core = $this->createCore(); + + $core->mods->router->addRoute('/test1/test2/', 'callable'); + $this->assertArraySubset(array('/test1/test2/' => 'callable'), $core->mods->router->getRoutes()); + + $core->mods->router->setPath('test1/test2'); + $core->mods->router->route(false); + $this->assertEquals(array('test1', 'test2'), array($core->mods->router->getController(), $core->mods->router->getFunction())); + + } + + public function testCustomRouteWithParameters(){ + + $core = $this->createCore(); + + $core->mods->router->addRoute('/^b\/(?P[^\/]+)\/?(?P.+?)$/', 'callable'); + $core->mods->router->addRoute('/e\/(?P[^\/]+)/', 'callable'); + $core->mods->router->addRoute('/b\/b$/', 'callable'); + + $core->mods->router->setPath('b/controller_a/function_a'); + $core->mods->router->route(false); + $this->assertEquals('controller_a', $core->mods->router->getController()); + $this->assertEquals('function_a', $core->mods->router->getFunction()); + + $core->mods->router->setPath('e/function_b/c'); + $core->mods->router->route(false); + $this->assertEquals(null, $core->mods->router->getController()); + $this->assertEquals('function_b', $core->mods->router->getFunction()); + + $core->mods->router->setPath('b/b'); + $core->mods->router->route(false); + $this->assertEquals(null, $core->mods->router->getController()); + $this->assertEquals(null, $core->mods->router->getFunction()); + + $core->mods->router->setPath('a/b'); + $core->mods->router->route(false); + $this->assertEquals('a', $core->mods->router->getController()); + $this->assertEquals('b', $core->mods->router->getFunction()); + } +} \ No newline at end of file diff --git a/tests/event_routerLoadCallableEventTest.php b/tests/event_routerLoadCallableEventTest.php new file mode 100644 index 0000000..15d97eb --- /dev/null +++ b/tests/event_routerLoadCallableEventTest.php @@ -0,0 +1,82 @@ +createCore(); + + $mock = $this->getMock('MockEvent', array('mockMethod')); + $mock->expects($this->once())->method('mockMethod')->with( + $this->isInstanceOf('\routerLoadCallableEvent') + ); + + $core->mods->events->addListener(array($mock, 'mockMethod'), 'routerLoadCallableEvent', \FuzeWorks\EventPriority::NORMAL); + //Prevent ouputting HTML + ob_start(); + $core->mods->router->route(); + ob_end_clean(); + } + + /** + * Intercept and change + * @todo Make this test correct + */ + public function test_change(){ + + $core = $this->createCore(); + + $core->mods->events->addListener(array($this, 'listener_change'), 'routerLoadCallableEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('x/y/z'); + ob_start(); + $core->mods->router->route(true); + ob_end_clean(); + + $this->assertNotNull($core->mods->router->getCallable()); + $this->assertInstanceOf('\FuzeWorks\Router', $core->mods->router->getCallable()[0]); + } + + // Change title from new to other + public function listener_change(\routerLoadCallableEvent $event){ + + // This controller should not exist + $this->assertEquals('x', $event->controller); + $this->assertEquals('y', $event->function); + + // It should exist now + $event->controller = 'home'; + $event->function = 'index'; + } + + /** + * Cancel events + */ + public function test_cancel(){ + + // When the callable may execute, the callable will change to the controller + // (because '' will trigger the default callable') + $core = $this->createCore(); + $core->mods->router->setPath(''); + + $core->mods->events->addListener(array($this, 'listener_cancel'), 'routerLoadCallableEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->route(); + $this->assertTrue(is_callable($core->mods->router->getCallable())); + + // When disabled, the default controller will be loaded and the callable will be overwritten + $core = $this->createCore(); + $core->mods->router->setPath(''); + $core->mods->router->route(); + $this->assertFalse(is_callable($core->mods->router->getCallable())); + } + + // Cancel all calls + public function listener_cancel(\routerLoadCallableEvent $event){ + + $event->setCancelled(true); + } +} \ No newline at end of file diff --git a/tests/event_routerRouteEventTest.php b/tests/event_routerRouteEventTest.php new file mode 100644 index 0000000..4e747b2 --- /dev/null +++ b/tests/event_routerRouteEventTest.php @@ -0,0 +1,45 @@ +createCore(); + + $mock = $this->getMock('MockEvent', array('mockMethod')); + $mock->expects($this->once())->method('mockMethod')->with( + $this->isInstanceOf('\routerRouteEvent') + ); + + $core->mods->events->addListener(array($mock, 'mockMethod'), 'routerRouteEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('a/b/c'); + $core->mods->router->route(false); + } + + /** + * Cancel events + */ + public function test_cancel(){ + + $core = $this->createCore(); + $core->mods->router->setPath('a/b/c'); + + $core->mods->events->addListener(array($this, 'listener_cancel'), 'routerRouteEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->route(false); + + $this->assertNotEquals('a', $core->mods->router->getController()); + $this->assertNotEquals('b', $core->mods->router->getFunction()); + $this->assertNotEquals(array('c'), $core->mods->router->getParameters()); + } + + // Cancel all calls + public function listener_cancel(\System\Events\routerRouteEvent $event){ + + $event->setCancelled(true); + } +} \ No newline at end of file diff --git a/tests/event_routerRouterSetPathEventTest.php b/tests/event_routerRouterSetPathEventTest.php new file mode 100644 index 0000000..f107182 --- /dev/null +++ b/tests/event_routerRouterSetPathEventTest.php @@ -0,0 +1,83 @@ +createCore(); + + $mock = $this->getMock('MockEvent', array('mockMethod')); + $mock->expects($this->once())->method('mockMethod')->with( + $this->isInstanceOf('\routerSetPathEvent') + ); + + $core->mods->events->addListener(array($mock, 'mockMethod'), 'routerSetPathEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('a/b/c'); + } + + /** + * Intercept and change + */ + public function testRouterSetPathEvent_change(){ + + $core = $this->createCore(); + + $core->mods->events->addListener(array($this, 'listener_change'), 'routerSetPathEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('a/b/c'); + + $this->assertEquals('x/y/z', $core->mods->router->getPath()); + } + + // Change title from new to other + public function listener_change(\routerSetPathEvent $event){ + + $this->assertEquals('a/b/c', $event->path); + $event->path = 'x/y/z'; + } + + /** + * Cancel events + */ + public function testLayoutFunctionCallEvent_cancel(){ + + $core = $this->createCore(); + $core->mods->router->setPath('a/b/c'); + + $core->mods->events->addListener(array($this, 'listener_cancel'), 'routerSetPathEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('x/y/z'); + + $this->assertEquals('a/b/c', $core->mods->router->getPath()); + } + + // Cancel all calls + public function listener_cancel(\routerSetPathEvent $event){ + + $event->setCancelled(true); + } + + + /** + * Do not cancel events + */ + public function testLayoutFunctionCallEvent_dontcancel(){ + + $core = $this->createCore(); + $core->mods->router->setPath('a/b/c'); + + $core->mods->events->addListener(array($this, 'listener_dontcancel'), 'routerSetPathEvent', \FuzeWorks\EventPriority::NORMAL); + $core->mods->router->setPath('x/y/z'); + + $this->assertEquals('x/y/z', $core->mods->router->getPath()); + } + + // Cancel all calls + public function listener_dontcancel(\routerSetPathEvent $event){ + + $event->setCancelled(false); + } +} \ No newline at end of file