diff --git a/src/Pecee/SimpleRouter/LoadableRoute.php b/src/Pecee/SimpleRouter/LoadableRoute.php new file mode 100644 index 0000000..0dd1d39 --- /dev/null +++ b/src/Pecee/SimpleRouter/LoadableRoute.php @@ -0,0 +1,93 @@ +url; + } + + /** + * Set url + * + * @param string $url + * @return static + */ + public function setUrl($url) { + + $this->url = '/' . trim($url, '/') . '/'; + /*$this->originalUrl = $this->url; + + if(preg_match_all('/' . static::PARAMETERS_REGEX_MATCH . '/is', $this->url, $matches)) { + $parameters = $matches[1]; + + + if (count($parameters)) { + + foreach (array_keys($parameters) as $key) { + $parameters[$key] = null; + } + + $this->settings['parameters'] = $parameters; + } + + }*/ + + return $this; + } + + /** + * Get alias for the url which can be used when getting the url route. + * @return string|array + */ + public function getAlias(){ + return $this->getSetting('alias'); + } + + /** + * Check if route has given alias. + * + * @param string $name + * @return bool + */ + public function hasAlias($name) { + if ($this->getAlias() !== null) { + if (is_array($this->getAlias())) { + foreach ($this->getAlias() as $alias) { + if (strtolower($alias) === strtolower($name)) { + return true; + } + } + } + return strtolower($this->getAlias()) === strtolower($name); + } + + return false; + } + + /** + * Set the url alias for easier getting the url route. + * @param string|array $alias + * @return static + */ + public function setAlias($alias){ + $this->settings['alias'] = $alias; + return $this; + } + + public function addSettings(array $settings) { + + // Change as to alias + if(isset($settings['as'])) { + $this->setAlias($settings['as']); + unset($settings['as']); + } + + return parent::addSettings($settings); + } + +} \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index 6c025d4..d08c962 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -24,10 +24,11 @@ class RouterBase { protected $response; /** - * Used to keep track of whether to add routes to stack or not. - * @var RouterEntry + * Used to keep track of whether or not a should should be added to + * the backstack-list for group-processing or not. + * @var bool */ - protected $currentRoute; + protected $processingRoute; /** * All added routes @@ -78,24 +79,25 @@ class RouterBase { protected $loadedRoute; /** - * List over route changes (to avoid looping) + * List over route changes (to avoid endless-looping) * @var array */ - protected $routeChanges; + protected $routeChanges = array(); public function __construct() { + $this->reset(); } public function reset() { + $this->processingRoute = false; $this->request = new Request(); $this->response = new Response($this->request); $this->routes = array(); + $this->bootManagers = array(); $this->backStack = array(); $this->controllerUrlMap = array(); - $this->bootManagers = array(); $this->exceptionHandlers = array(); - $this->routeChanges = array(); } /** @@ -104,7 +106,7 @@ class RouterBase { * @return RouterEntry */ public function addRoute(RouterEntry $route) { - if($this->currentRoute !== null) { + if($this->processingRoute) { $this->backStack[] = $route; } else { $this->routes[] = $route; @@ -113,7 +115,7 @@ class RouterBase { return $route; } - protected function processRoutes(array $routes, array $settings = array(), array $prefixes = array(), $backStack = false, RouterGroup $group = null) { + protected function processRoutes(array $routes, array $settings = array(), array $prefixes = array(), RouterEntry $parent = null) { // Loop through each route-request $mergedSettings = array(); @@ -127,11 +129,24 @@ class RouterBase { $route->addSettings($settings); } - if($backStack && $group !== null) { - $route->setGroup($group); - } else { - $prefixes = []; - $group = null; + if($parent !== null) { + + if($parent instanceof RouterGroup) { + if ($parent->getPrefix() !== null && trim($parent->getPrefix(), '/') !== '') { + $prefixes[] = trim($parent->getPrefix(), '/'); + } + + if ($route->matchRoute($this->request)) { + $mergedSettings = array_merge($settings, $parent->getMergeableSettings()); + + // Add ExceptionHandler + if (count($parent->getExceptionHandlers())) { + $this->exceptionHandlers = array_merge($this->exceptionHandlers, $parent->getExceptionHandler()); + } + } + } + + $route->setParent($parent); } if($route->getNamespace() === null && $this->defaultNamespace !== null) { @@ -143,52 +158,26 @@ class RouterBase { $route->setNamespace($namespace); } - $this->currentRoute = $route; - if($route instanceof ILoadableRoute) { - if(is_array($prefixes) && count($prefixes) && $backStack) { - $route->setUrl( '/' . join('/', $prefixes) . $route->getUrl() ); - } - + $route->setUrl( trim(join('/', $prefixes) . $route->getUrl(), '/') ); $this->controllerUrlMap[] = $route; } else { - - if($route instanceof RouterGroup) { - - if ($route->getPrefix() !== null && trim($route->getPrefix(), '/') !== '') { - $prefixes[] = trim($route->getPrefix(), '/'); - } - - if (is_callable($route->getCallback())) { - - $route->renderRoute($this->request); - - if ($route->matchRoute($this->request)) { - - /* @var $group RouterGroup */ - $group = $route; - - $mergedSettings = array_merge($settings, $group->getMergeableSettings()); - - // Add ExceptionHandler - if ($group->getExceptionHandler() !== null) { - $this->exceptionHandlers[] = $route; - } - - } - } + if ($route->getCallback() !== null && is_callable($route->getCallback())) { + $this->processingRoute = true; + $route->renderRoute($this->request); + $this->processingRoute = false; } } - $this->currentRoute = null; - if(count($this->backStack)) { $backStack = $this->backStack; $this->backStack = array(); // Route any routes added to the backstack - $this->processRoutes($backStack, $mergedSettings, $prefixes, true, $group); + $this->processRoutes($backStack, $mergedSettings, $prefixes, $route); } + + $prefixes = []; } } @@ -269,9 +258,8 @@ class RouterBase { protected function handleException(\Exception $e) { - /* @var $route RouterGroup */ - foreach ($this->exceptionHandlers as $route) { - $handler = $route->getExceptionHandler(); + /* @var $handler IExceptionHandler */ + foreach ($this->exceptionHandlers as $handler) { $handler = new $handler(); if (!($handler instanceof IExceptionHandler)) { @@ -394,12 +382,14 @@ class RouterBase { $domain = ''; - if($route->getGroup() !== null && $route->getGroup()->getDomain() !== null) { - if(is_array($route->getGroup()->getDomain())) { - $domains = $route->getGroup()->getDomain(); + $parent = $route->getParent(); + + if($parent !== null && ($parent instanceof RouterGroup) && $parent->getDomain() !== null) { + if(is_array($parent->getDomain())) { + $domains = $parent->getDomain(); $domain = array_shift($domains); } else { - $domain = $route->getGroup()->getDomain(); + $domain = $parent->getDomain(); } $domain = '//' . $domain; @@ -482,16 +472,25 @@ class RouterBase { $route = $this->controllerUrlMap[$i]; // Check an alias exist, if the matches - use it - if($route instanceof IControllerRoute) { - $c = $route->getController(); - } else { - if($route->hasAlias($controller)) { + if($route instanceof LoadableRoute) { + + // Check for alias + if ($route->hasAlias($controller)) { return $this->processUrl($route, $route->getMethod(), $parameters, $getParams); } - if(!is_callable($route->getCallback()) && stripos($route->getCallback(), '@') !== false) { - $c = $route->getCallback(); + // Use controller name + if($route instanceof RouterController) { + $c = $route->getController(); + } else { + + // Use callback if it's not a function + if (stripos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) { + $c = $route->getCallback(); + } + } + } if($c === $controller || strpos($c, $controller) === 0) { diff --git a/src/Pecee/SimpleRouter/RouterController.php b/src/Pecee/SimpleRouter/RouterController.php index 4d1723d..60a8781 100644 --- a/src/Pecee/SimpleRouter/RouterController.php +++ b/src/Pecee/SimpleRouter/RouterController.php @@ -4,11 +4,10 @@ namespace Pecee\SimpleRouter; use Pecee\Exception\RouterException; use Pecee\Http\Request; -class RouterController extends RouterEntry implements ILoadableRoute, IControllerRoute { +class RouterController extends LoadableRoute implements IControllerRoute { const DEFAULT_METHOD = 'index'; - protected $url; protected $controller; protected $method; @@ -18,7 +17,7 @@ class RouterController extends RouterEntry implements ILoadableRoute, IControlle } public function renderRoute(Request $request) { - if(is_object($this->getCallback()) && is_callable($this->getCallback())) { + if($this->getCallback() !== null && is_callable($this->getCallback())) { // When the callback is a function call_user_func_array($this->getCallback(), $this->getParameters()); @@ -69,23 +68,6 @@ class RouterController extends RouterEntry implements ILoadableRoute, IControlle return null; } - /** - * @return string - */ - public function getUrl() { - return $this->url; - } - - /** - * @param string $url - * @return static - */ - public function setUrl($url) { - $url = rtrim($url, '/') . '/'; - $this->url = $url; - return $this; - } - /** * @return string */ diff --git a/src/Pecee/SimpleRouter/RouterEntry.php b/src/Pecee/SimpleRouter/RouterEntry.php index 7e37f2b..8ed83e5 100644 --- a/src/Pecee/SimpleRouter/RouterEntry.php +++ b/src/Pecee/SimpleRouter/RouterEntry.php @@ -22,6 +22,9 @@ abstract class RouterEntry { self::REQUEST_TYPE_PATCH, ]; + protected $parent; + protected $callback; + protected $settings = [ 'requestMethods' => array(), 'where' => array(), @@ -29,8 +32,6 @@ abstract class RouterEntry { 'middleware' => array(), ]; - protected $callback; - /** * @param string $callback * @return static @@ -95,14 +96,14 @@ abstract class RouterEntry { * @return string|array */ public function getMiddleware() { - return $this->settingArray('middleware'); + return $this->getSetting('middleware'); } /** * @return string */ public function getNamespace() { - return $this->setting('namespace'); + return $this->getSetting('namespace'); } /** @@ -116,7 +117,7 @@ abstract class RouterEntry { * @return array */ public function getParameters(){ - return $this->setting('parameters', array()); + return $this->getSetting('parameters', array()); } /** @@ -209,7 +210,7 @@ abstract class RouterEntry { // Check for optional parameter // Use custom parameter regex if it exists - if(is_array($this->setting('where')) && isset($this->settings['where'][$parameter])) { + if(is_array($this->getSetting('where')) && isset($this->settings['where'][$parameter])) { $parameterRegex = $this->settings['where'][$parameter]; } @@ -284,7 +285,7 @@ abstract class RouterEntry { } public function renderRoute(Request $request) { - if(is_object($this->getCallback()) && is_callable($this->getCallback())) { + if($this->getCallback() !== null && is_callable($this->getCallback())) { // When the callback is a function call_user_func_array($this->getCallback(), $this->getParameters()); } else { @@ -328,32 +329,25 @@ abstract class RouterEntry { * @return array */ public function getRequestMethods() { - return $this->settingArray('requestMethods'); + return $this->getSetting('requestMethods'); } - public function getGroup() { - return $this->setting('group'); + /** + * @return RouterEntry + */ + public function getParent() { + return $this->parent; } - public function setGroup($group) { - $this->settings['group'] = $group; + public function setParent(RouterEntry $parent) { + $this->parent = $parent; return $this; } - protected function setting($name, $defaultValue = null) { + protected function getSetting($name, $defaultValue = null) { return isset($this->settings[$name]) ? $this->settings[$name] : $defaultValue; } - protected function settingArray($name) { - $value = $this->setting($name); - - if($value === null) { - return []; - } - - return (!is_array($value)) ? array($value) : $value; - } - abstract function matchRoute(Request $request); } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/RouterGroup.php b/src/Pecee/SimpleRouter/RouterGroup.php index 8e29572..23d149e 100644 --- a/src/Pecee/SimpleRouter/RouterGroup.php +++ b/src/Pecee/SimpleRouter/RouterGroup.php @@ -7,12 +7,18 @@ use Pecee\Http\Request; class RouterGroup extends RouterEntry { + public function __construct() { + $this->settings = array_merge($this->settings, [ + 'exceptionHandlers' => array() + ]); + } + public function matchDomain(Request $request) { - if($this->setting('domain') !== null) { + if($this->getSetting('domain') !== null) { - if(is_array($this->setting('domain'))) { + if(is_array($this->getSetting('domain'))) { - for($i = 0; $i < count($this->setting('domain')); $i++) { + for($i = 0; $i < count($this->getSetting('domain')); $i++) { $domain = $this->settings['domain'][$i]; $parameters = $this->parseParameters($domain, $request->getHost(), '[^.]*'); @@ -26,7 +32,7 @@ class RouterGroup extends RouterEntry { return false; } - $parameters = $this->parseParameters($this->setting('domain'), $request->getHost(), '[^.]*'); + $parameters = $this->parseParameters($this->getSetting('domain'), $request->getHost(), '[^.]*'); if ($parameters !== null) { $this->settings['parameters'] = $parameters; @@ -43,8 +49,8 @@ class RouterGroup extends RouterEntry { // Check if request method is allowed $hasAccess = true; - if($this->setting('method') !== null) { - if(is_array($this->setting('method'))) { + if($this->getSetting('method') !== null) { + if(is_array($this->getSetting('method'))) { $hasAccess = (in_array($request->getMethod(), $this->getRequestMethods())); } else { $hasAccess = strtolower($this->getRequestMethods()) == strtolower($request->getMethod()); @@ -69,17 +75,17 @@ class RouterGroup extends RouterEntry { return $this->matchDomain($request); } - public function setExceptionHandler($class) { - $this->settings['exceptionHandler'] = $class; + public function setExceptionHandlers($class) { + $this->settings['exceptionHandlers'][] = $class; return $this; } - public function getExceptionHandler() { - return $this->setting('exceptionHandler'); + public function getExceptionHandlers() { + return $this->getSetting('exceptionHandlers'); } public function getDomain() { - return $this->setting('domain'); + return $this->getSetting('domain'); } /** @@ -87,7 +93,7 @@ class RouterGroup extends RouterEntry { * @return static */ public function setPrefix($prefix) { - $this->settings['prefix'] = '/' . ltrim($prefix, '/'); + $this->settings['prefix'] = '/' . trim($prefix, '/'); return $this; } @@ -95,7 +101,7 @@ class RouterGroup extends RouterEntry { * @return string */ public function getPrefix() { - return $this->setting('prefix'); + return $this->getSetting('prefix'); } /** @@ -118,7 +124,11 @@ class RouterGroup extends RouterEntry { } $settings['middleware'] = array_unique(array_reverse($settings['middleware'])); + } + if(isset($settings['prefix'])) { + $this->setPrefix($settings['prefix']); + unset($settings['prefix']); } $this->settings = array_merge($this->settings, $settings); diff --git a/src/Pecee/SimpleRouter/RouterResource.php b/src/Pecee/SimpleRouter/RouterResource.php index 8fe4a18..9b2aba6 100644 --- a/src/Pecee/SimpleRouter/RouterResource.php +++ b/src/Pecee/SimpleRouter/RouterResource.php @@ -4,9 +4,8 @@ namespace Pecee\SimpleRouter; use Pecee\Exception\RouterException; use Pecee\Http\Request; -class RouterResource extends RouterEntry implements ILoadableRoute, IControllerRoute { +class RouterResource extends LoadableRoute implements IControllerRoute { - protected $url; protected $controller; public function __construct($url, $controller) { @@ -15,7 +14,7 @@ class RouterResource extends RouterEntry implements ILoadableRoute, IControllerR } public function renderRoute(Request $request) { - if(is_object($this->getCallback()) && is_callable($this->getCallback())) { + if($this->getCallback() !== null && is_callable($this->getCallback())) { // When the callback is a function call_user_func_array($this->getCallback(), $this->getParameters()); } else { @@ -97,22 +96,6 @@ class RouterResource extends RouterEntry implements ILoadableRoute, IControllerR return null; } - /** - * @return string - */ - public function getUrl() { - return $this->url; - } - - /** - * @param string $url - * @return static - */ - public function setUrl($url) { - $this->url = rtrim($url, '/') . '/'; - return $this; - } - /** * @return string */ diff --git a/src/Pecee/SimpleRouter/RouterRoute.php b/src/Pecee/SimpleRouter/RouterRoute.php index 7fdc3b3..74bf74c 100644 --- a/src/Pecee/SimpleRouter/RouterRoute.php +++ b/src/Pecee/SimpleRouter/RouterRoute.php @@ -4,11 +4,7 @@ namespace Pecee\SimpleRouter; use Pecee\Http\Request; -class RouterRoute extends RouterEntry implements ILoadableRoute { - - const PARAMETERS_REGEX_MATCH = '{([A-Za-z\-\_]*?)\?{0,1}}'; - - protected $url; +class RouterRoute extends LoadableRoute { public function __construct($url, $callback) { $this->setUrl($url); @@ -21,9 +17,9 @@ class RouterRoute extends RouterEntry implements ILoadableRoute { $url = rtrim($url, '/') . '/'; // Match on custom defined regular expression - if($this->setting('regexMatch') !== null) { + if($this->getSetting('regexMatch') !== null) { $parameters = array(); - if(preg_match('/(' . $this->setting('regexMatch') . ')/is', $request->getHost() . $url, $parameters)) { + if(preg_match('/(' . $this->getSetting('regexMatch') . ')/is', $request->getHost() . $url, $parameters)) { $this->settings['parameters'] = (!is_array($parameters[0]) ? array($parameters[0]) : $parameters[0]); return true; } @@ -36,92 +32,11 @@ class RouterRoute extends RouterEntry implements ILoadableRoute { $parameters = $this->parseParameters($route, $url); if($parameters !== null) { - $this->settings['parameters'] = array_merge($this->settingArray('parameters'), $parameters); + $this->settings['parameters'] = array_merge($this->getSetting('parameters'), $parameters); return true; } return null; } - /** - * @return string - */ - public function getUrl() { - return $this->url; - } - - /** - * @param string $url - * @return static - */ - public function setUrl($url) { - $parameters = array(); - $matches = array(); - - if(preg_match_all('/' . static::PARAMETERS_REGEX_MATCH . '/is', $url, $matches)) { - $parameters = $matches[1]; - } - - if(count($parameters)) { - - foreach(array_keys($parameters) as $key) { - $parameters[$key] = null; - } - - $this->settings['parameters'] = $parameters; - } - - $this->url = $url; - return $this; - } - - /** - * Get alias for the url which can be used when getting the url route. - * @return string|array - */ - public function getAlias(){ - return $this->setting('alias'); - } - - /** - * Check if route has given alias. - * - * @param string $name - * @return bool - */ - public function hasAlias($name) { - if ($this->getAlias() !== null) { - if (is_array($this->getAlias())) { - foreach ($this->setting('alias') as $alias) { - if (strtolower($alias) === strtolower($name)) { - return true; - } - } - } - return strtolower($this->getAlias()) === strtolower($name); - } - - return false; - } - - /** - * Set the url alias for easier getting the url route. - * @param string|array $alias - * @return static - */ - public function setAlias($alias){ - $this->settings['alias'] = $alias; - return $this; - } - - public function addSettings(array $settings) { - - // Change as to alias - if(isset($settings['as'])) { - $this->setAlias($settings['as']); - } - - return parent::addSettings($settings); - } - } \ No newline at end of file