Ejemplo n.º 1
0
 /**
  * Handles routing information received from the rewrite engine
  *
  *<code>
  * //Read the info from the rewrite engine
  * $router->handle();
  *
  * //Manually passing an URL
  * $router->handle('/posts/edit/1');
  *</code>
  *
  * @param string|null $uri
  * @throws Exception
  */
 public function handle($uri = null)
 {
     if (!is_string($uri) && !is_null($uri)) {
         throw new Exception('Invalid parameter type.');
     }
     if (!$uri) {
         /**
          * If 'uri' isn't passed as parameter it reads _GET['_url']
          */
         $realUri = $this->getRewriteUri();
     } else {
         $realUri = $uri;
     }
     /**
      * Remove extra slashes in the route
      */
     if ($this->_removeExtraSlashes && $realUri != '/') {
         $handledUri = rtrim($realUri, '/');
     } else {
         $handledUri = $realUri;
     }
     $request = null;
     $currentHostName = null;
     $routeFound = false;
     $parts = [];
     $params = [];
     $matches = null;
     $this->_wasMatched = false;
     $this->_matchedRoute = null;
     $eventsManager = $this->_eventsManager;
     if (is_object($eventsManager)) {
         $eventsManager->fire('router:beforeCheckRoutes', $this);
     }
     /**
      * Routes are traversed in reversed order
      */
     $routes = array_reverse($this->_routes);
     foreach ($routes as $route) {
         /**
          * Look for HTTP method constraints
          */
         $methods = $route->getHttpMethods();
         if ($methods !== null) {
             /**
              * Retrieve the request service from the container
              */
             if ($request === null) {
                 $dependencyInjector = $this->_dependencyInjector;
                 if (!is_object($dependencyInjector)) {
                     throw new Exception("A dependency injection container is required to access the 'request' service");
                 }
                 $request = $dependencyInjector->getShared('request');
             }
             /**
              * Check if the current method is allowed by the route
              */
             if ($request->isMethod($methods, true) === false) {
                 continue;
             }
         }
         /**
          * Look for hostname constraints
          */
         $hostname = $route->getHostname();
         if ($hostname !== null) {
             /**
              * Retrieve the request service from the container
              */
             if ($request === null) {
                 $dependencyInjector = $this->_dependencyInjector;
                 if (!is_object($dependencyInjector)) {
                     throw new Exception("A dependency injection container is required to access the 'request' service");
                 }
                 $request = $dependencyInjector->getShared('request');
             }
             /**
              * Check if the current hostname is the same as the route
              */
             if (!is_object($currentHostName)) {
                 $currentHostName = $request->getHttpHost();
             }
             /**
              * No HTTP_HOST, maybe in CLI mode?
              */
             if (is_null($currentHostName)) {
                 continue;
             }
             /**
              * Check if the hostname restriction is the same as the current in the route
              */
             if (strpos($hostname, '(') !== false) {
                 if (strpos($hostname, '#') === false) {
                     $regexHostName = '#^' . $hostname . '$#';
                 } else {
                     $regexHostName = $hostname;
                 }
                 $matched = preg_match($regexHostName, $currentHostName);
             } else {
                 $matched = $currentHostName == $hostname;
             }
             if (!$matched) {
                 continue;
             }
         }
         if (is_object($eventsManager)) {
             $eventsManager->fire('router:beforeCheckRoute', $this, $route);
         }
         /**
          * If the route has parentheses use preg_match
          */
         $pattern = $route->getCompiledPattern();
         if (strpos($pattern, '^') !== false) {
             $routeFound = preg_match($pattern, $handledUri, $matches);
         } else {
             $routeFound = $pattern == $handledUri;
         }
         /**
          * Check for beforeMatch conditions
          */
         if ($routeFound) {
             if (is_object($eventsManager)) {
                 $eventsManager->fire('router:matchedRoute', $this, $route);
             }
             $beforeMatch = $route->getBeforeMatch();
             if ($beforeMatch !== null) {
                 /**
                  * Check first if the callback is callable
                  */
                 if (!is_callable($beforeMatch)) {
                     throw new Exception("Before-Match callback is not callable in matched route");
                 }
                 /**
                  * Check first if the callback is callable
                  */
                 $routeFound = call_user_func_array($beforeMatch, [$handledUri, $route, $this]);
             }
         } else {
             if (is_object($eventsManager)) {
                 $routeFound = $eventsManager->fire('router:notMatchedRoute', $this, $route);
             }
         }
         if ($routeFound) {
             /**
              * Start from the default paths
              */
             $paths = $route->getPaths();
             $parts = $paths;
             /**
              * Check if the matches has variables
              */
             if (is_array($matches)) {
                 /**
                  * Get the route converters if any
                  */
                 $converters = $route->getConverters();
                 foreach ($paths as $part => $position) {
                     if (isset($matches[$position])) {
                         $matchPosition = $matches[$position];
                         /**
                          * Check if the part has a converter
                          */
                         if (is_array($converters)) {
                             if (isset($converters[$part])) {
                                 $converter = $converters[$part];
                                 $parts[$parts] = call_user_func_array($converter, [$matchPosition]);
                                 continue;
                             }
                         }
                         /**
                          * Update the parts if there is no converter
                          */
                         $parts[$part] = $matchPosition;
                     } else {
                         /**
                          * Apply the converters anyway
                          */
                         if (is_array($converters)) {
                             if (isset($converters[$part])) {
                                 $parts[$part] = call_user_func_array($converter, [$position]);
                             }
                         }
                     }
                 }
                 /**
                  * Update the matches generated by preg_match
                  */
                 $this->_matches = $matches;
             }
             $this->_matchedRoute = $route;
             break;
         }
     }
     /**
      * Update the wasMatched property indicating if the route was matched
      */
     if ($routeFound) {
         $this->_wasMatched = true;
     } else {
         $this->_wasMatched = false;
     }
     /**
      * The route wasn't found, try to use the not-found paths
      */
     if (!$routeFound) {
         $notFoundPaths = $this->_notFoundPaths;
         if ($notFoundPaths !== null) {
             $parts = Route::getRoutePaths($notFoundPaths);
             $routeFound = true;
         }
     }
     /**
      * Use default values before we overwrite them if the route is matched
      */
     $this->_namespace = $this->_defaultNamespace;
     $this->_module = $this->_defaultModule;
     $this->_controller = $this->_defaultController;
     $this->_action = $this->_defaultAction;
     $this->_params = $this->_defaultParams;
     if ($routeFound) {
         /**
          * Check for a namespace
          */
         if (isset($parts['namespace'])) {
             if (!is_numeric($parts['namespace'])) {
                 $this->_namespace = $parts['namespace'];
             }
             unset($parts['namespace']);
         }
         /**
          * Check for a module
          */
         if (isset($parts['module'])) {
             if (!is_numeric($parts['module'])) {
                 $this->_module = $parts['module'];
             }
             unset($parts['module']);
         }
         /**
          * Check for a controller
          */
         if (isset($parts['controller'])) {
             if (!is_numeric($parts['controller'])) {
                 $this->_controller = $parts['controller'];
             }
             unset($parts['controller']);
         }
         /**
          * Check for an action
          */
         if (isset($parts['action'])) {
             if (!is_numeric($parts['action'])) {
                 $this->_action = $parts['action'];
             }
             unset($parts['action']);
         }
         /**
          * Check for parameters
          */
         if (isset($parts['params'])) {
             $paramsStr = $parts['params'];
             if (is_string($paramsStr)) {
                 $strParams = trim($paramsStr, '/');
                 if ($strParams !== '') {
                     $params = explode('/', $strParams);
                 }
             }
             unset($parts['params']);
         }
         if (count($params)) {
             $this->_params = array_merge($params, $parts);
         } else {
             $this->_params = $parts;
         }
         if (is_object($eventsManager)) {
             $eventsManager->fire('router:afterCheckRoutes', $this);
         }
     }
 }
Ejemplo n.º 2
0
 /**
  * Adds a route applying the common attributes
  *
  * @param string $patten
  * @param Mixed $paths
  * @param Mixed $httpMethods
  * @return \Scene\Mvc\Router\RouteInterface
  * @throws Exception
  */
 protected function _addRoute($pattern, $paths = null, $httpMethods = null)
 {
     if (!is_string($pattern)) {
         throw new Exception('Invalid parameter type.');
     }
     /**
      * Check if the paths need to be merged with current paths
      */
     $defaultPaths = $this->_paths;
     if (is_array($defaultPaths)) {
         if (is_string($paths)) {
             $processedPaths = Route::getRoutePaths($paths);
         } else {
             $processedPaths = $paths;
         }
         if (is_array($processedPaths)) {
             /**
              * Merge the paths with the default paths
              */
             $mergedPaths = array_merge($defaultPaths, $processedPaths);
         } else {
             $mergedPaths = $defaultPaths;
         }
     } else {
         $mergedPaths = $paths;
     }
     /**
      * Every route is internally stored as a Phalcon\Mvc\Router\Route
      */
     $route = new Route($this->_prefix . $pattern, $mergedPaths, $httpMethods);
     $this->_routes[] = $route;
     $route->setGroup($this);
     return $route;
 }