Example #1
0
 /**
  * @covers Zepto\Router::run()
  * @covers Zepto\Router::match()
  * @covers Zepto\Router::parse_parameters()
  * @covers Zepto\Router::current_route()
  * @covers Zepto\Router::current_http_status()
  */
 public function testRunWithParameters()
 {
     $_SERVER['REQUEST_URL'] = '/zepto/index.php/get/666';
     $_SERVER['REQUEST_URI'] = '/zepto/index.php/get/666';
     $this->mock_request->expects($this->any())->method('getPathInfo')->will($this->returnValue('/get/666'));
     $this->router->get('/get/<:id|[6]{3}>', function ($id) {
         return 'This is ' . $id;
     });
     $this->assertTrue($this->router->run());
     $this->assertEquals('/get/<:id|[6]{3}>', $this->router->current_route()->url());
     $this->assertEquals('#^/get/(?P<id>[6]{3})/$#', $this->router->current_route()->pattern());
     $this->assertEquals(200, $this->router->current_http_status());
 }
Example #2
0
 /**
  * Instantiates the specified controller, optionally replacing $_GET and $_POST contents before calling the component constructor.
  * \note The original $_GET and $_POST array are restored as soon as the component is instantiated.
  * @param $controller The name of the controller class to be instantiated, lowercase, without the "Controller_" prefix.
  * @param $get The array that should replace $_GET.
  * @param $post The array that should replace $_POST.
  * @return A new Component object.
  */
 public static function factory($controller, $get = null, $post = null)
 {
     // Backup router state
     $old_router = array();
     $old_router['current_route'] = Router::$current_route;
     $old_router['current_uri'] = Router::$current_uri;
     $old_router['query_string'] = Router::$query_string;
     $old_router['complete_uri'] = Router::$complete_uri;
     $old_router['controller'] = Router::$controller;
     $old_router['method'] = Router::$method;
     $old_router['arguments'] = Router::$arguments;
     // The following three variables could be determined by running Router code and passing an url, but:
     // 1) The performance penalty would be high
     // 1) It's not a good idea for a controller to alter its behaviour depending on them, anyway
     //Router::$current_route = '';
     //Router::$current_uri = '';
     //Router::$complete_uri = '';
     Router::$controller = $controller;
     // We don't know these yet
     Router::$method = '';
     Router::$arguments = array();
     // If get or post parameters are passed, alter $_GET, $_POST and Router::$query_string accordingly
     // NOTE: Should we alter $_SERVER['QUERY_STRING'] too?
     if ($get !== null) {
         $old_get = $_GET;
         $_GET = $get;
         Router::$query_string = '?' . http_build_query($get);
     }
     if ($post !== null) {
         $old_post = $_POST;
         $_POST = $post;
     }
     // If class is not defined already, load controller file
     $controller_class = 'Controller_' . ucfirst($controller);
     if (!class_exists($controller_class, false)) {
         $controller_file = str_replace('_', '/', strtolower($controller_class));
         // If the component file doesn't exist, fire exception
         $filepath = Kohana::find_file('classes', $controller_file, true);
         // Include the Controller file
         require_once $filepath;
     }
     // Run system.pre_controller
     Event::run('dispatch.pre_controller');
     // Initialize the controller
     $controller_instance = new $controller_class();
     // Run system.post_controller_constructor
     Event::run('dispatch.post_controller_constructor');
     // Revert $_GET and $_POST changes
     if ($get !== null) {
         $_GET = $old_get;
     }
     if ($post !== null) {
         $_POST = $old_post;
     }
     // Revert Router state
     Router::$current_route = $old_router['current_route'];
     Router::$current_uri = $old_router['current_uri'];
     Router::$query_string = $old_router['query_string'];
     Router::$complete_uri = $old_router['complete_uri'];
     Router::$controller = $old_router['controller'];
     Router::$method = $old_router['method'];
     Router::$arguments = $old_router['arguments'];
     return new Component($controller_instance, $controller, $old_router);
 }
Example #3
0
 /**
  * Parses givven url, tries to match it against routes
  *
  * @param  string $url
  * @return array  Current route
  */
 public function parse_url($url)
 {
     $out = [];
     $ext = null;
     if (strpos($url, '/') !== 0) {
         $url = '/' . $url;
     }
     foreach ($this->routes as $route => $params) {
         if (($matches = $this->match_route($route, $url)) !== false) {
             $names = $params['names'];
             $defaults = $params['defaults'];
             array_shift($matches);
             foreach ($matches as $key => $found) {
                 if (empty($found) && $found !== '0' && $found !== 0) {
                     continue;
                 }
                 if (isset($names[$key])) {
                     $out[$names[$key]] = $found;
                 } else {
                     foreach (array_cleanup(explode('/', $found)) as $param) {
                         array_push($out, $param);
                     }
                 }
             }
             $out = array_merge($defaults, $out);
             break;
         }
     }
     self::$current_route = $out;
     return $out;
 }
Example #4
0
 private static function route($priority)
 {
     $uri = implode('/', segments());
     foreach (self::$slugs as $key => $routes) {
         $key = str_replace('%s', '([a-z0-9\\-]+)', str_replace('%d', '([0-9]+)', str_replace('/', '\\/', $key)));
         if (preg_match('/^' . $key . '(\\/|$)/is', $uri, $matches)) {
             array_pop($matches);
             array_shift($matches);
             foreach ($routes as &$route) {
                 if ($route->get_priority() == $priority) {
                     $arguments = preg_replace('/^' . $key . '(\\/|$)/is', '', $uri);
                     $arguments = explode("?", $arguments);
                     $arguments = array_filter(explode("/", array_shift($arguments)));
                     $arguments = array_merge($matches, $arguments);
                     // Check if the class that will handle the content actually contains the requested function.
                     if (!method_exists($route->get_classname(), $route->get_function())) {
                         continue;
                     }
                     // Check if we're not calling said function with too few parameters.
                     $reflector = new ReflectionClass($route->get_classname());
                     if (count($arguments) < $reflector->getMethod($route->get_function())->getNumberOfRequiredParameters()) {
                         continue;
                     }
                     // Check if this function might want variable number of parameters.
                     $collapse_parameters = false;
                     $parameters = $reflector->getMethod($route->get_function())->getParameters();
                     if (count($parameters) && end($parameters)->name == 'parameters') {
                         $collapse_parameters = true;
                     }
                     if (count($arguments) > count($parameters) && $collapse_parameters && $priority == ROUTE_DEFAULT) {
                         $route->set_priority(ROUTE_LATE);
                         continue;
                     }
                     // Check if we're not calling said function with too many parameters.
                     if (count($arguments) > count($parameters) && !$collapse_parameters) {
                         continue;
                     }
                     // Check if we're not calling a static function.
                     if ($reflector->getMethod($route->get_function())->isStatic()) {
                         continue;
                     }
                     // Save old segments should we need it again later
                     self::$urlsegments = self::$segments;
                     // Set the segments to those that matched our content
                     self::$segments = array();
                     self::$segments[0] = strtolower($route->get_contentname());
                     self::$segments[1] = strtolower($route->get_function());
                     self::$segments = array_merge(self::$segments, $arguments);
                     // Set the current route
                     self::$current_route = $route;
                     // Check database if needed (only do this when there's no admin panel)
                     if (!Config::admin_enabled()) {
                         $site = current_site();
                         if (self::is_fw4() && !$site->live) {
                             FW4_Structure::check_structure();
                         }
                     }
                     // Fire the controller
                     View_Loader::get_instance()->set_path(CONTENTPATH . self::$content_prefix . self::$segments[0]);
                     $page = self::$content_pages[strtolower($route->get_classname())];
                     if ($collapse_parameters) {
                         $non_optional = array_splice($arguments, 0, count($parameters) - 1);
                         $arguments = array_merge($non_optional, array(array_diff($arguments, array('index'))));
                     }
                     try {
                         $result = call_user_func_array(array($page, $route->get_function()), $arguments);
                     } catch (RowNotFoundException $e) {
                         $result = false;
                     }
                     // If the controller returns false, reset the segments and continue matching
                     if ($result === false) {
                         self::$segments = self::$urlsegments;
                         continue;
                     }
                     return true;
                 }
             }
         }
     }
     return false;
 }
Example #5
0
 public static function doRouting()
 {
     // Set the locale
     self::setLocale();
     // Check if we have a route and it's not empty
     if (isset($_GET[self::$trigger]) && !empty($_GET[self::$trigger])) {
         // Cleanup the route using our regex (only alphanumeric and url safe chars (.,-_/) are allowed)
         self::$current_route = preg_replace('/[^[:alnum:]\\.\\-\\_\\/]/', '', $_GET[self::$trigger]);
         // See if we have an filename ending (.html, etc.)
         if (self::$ending !== '') {
             // Calculate the offset for the length of the filename ending
             $offset = @strrpos(self::$current_route, self::$ending, -strlen(self::$ending));
             // Check if offset is present
             if ($offset !== FALSE) {
                 // So we remove the ending using the calculated offset to include the files we need
                 self::$tpl = substr_replace(self::$current_route, '', $offset, strlen(self::$ending)) . '.tpl';
                 self::$conf = substr_replace(self::$current_route, '', $offset, strlen(self::$ending)) . '.conf';
                 self::$md = substr_replace(self::$current_route, '', $offset, strlen(self::$ending)) . '.md';
             } else {
                 // Show 404
                 self::error404();
                 return;
             }
         } else {
             // We don't have a filename ending, thus we can assign the route's name to files we need
             self::$tpl = self::$current_route . '.tpl';
             self::$conf = self::$current_route . '.conf';
             self::$md = self::$current_route . '.md';
         }
         // Check for needed files we include later
         if (!file_exists('templates/' . self::$view_dir . self::$tpl) || !is_readable('templates/' . self::$view_dir . self::$tpl) || !is_file('templates/' . self::$view_dir . self::$tpl)) {
             // ...and if not show up the 404
             self::error404();
             return;
         }
     } else {
         // Set the current route to the default
         self::$current_route = self::$default_route . self::$ending;
         // Since we have no route, try to show up the default one
         self::$tpl = self::$default_route . '.tpl';
         self::$conf = self::$default_route . '.conf';
         self::$md = self::$default_route . '.md';
         // Again, check for needed files we include later
         if (!file_exists('templates/' . self::$view_dir . self::$tpl) || !is_readable('templates/' . self::$view_dir . self::$tpl) || !is_file('templates/' . self::$view_dir . self::$tpl)) {
             // ...and if not shopw up the 404 (again)
             self::error404();
             return;
         }
     }
     // Assign all needed files to our main template
     self::$smarty->assign('viewFile', self::$view_dir . self::$tpl);
     self::$smarty->assign('markdownFile', self::$md_dir . self::$md);
     self::$smarty->assign('currentRoute', self::$current_route);
     self::$smarty->assign('configFile', self::$conf);
     // Show the main template
     self::$smarty->display('main.tpl');
 }