HummingBirdAnimeClient/src/Aviat/AnimeClient/Dispatcher.php

267 lines
5.9 KiB
PHP
Raw Normal View History

2015-05-22 12:36:26 -04:00
<?php
/**
* Routing logic
*/
2015-09-15 13:19:29 -04:00
namespace Aviat\AnimeClient;
2015-05-22 12:36:26 -04:00
2015-09-14 19:54:34 -04:00
use Aura\Web\Request;
use Aura\Web\Response;
2015-06-26 16:39:10 -04:00
2015-09-17 23:11:18 -04:00
use Aviat\Ion\Di\ContainerInterface;
/**
* Basic routing/ dispatch
*/
2015-10-09 14:34:55 -04:00
class Dispatcher extends RoutingBase {
2015-05-22 12:36:26 -04:00
/**
* The route-matching object
* @var object $router
*/
protected $router;
/**
* Class wrapper for input superglobals
* @var object
*/
protected $request;
/**
* Routes added to router
* @var array $output_routes
*/
protected $output_routes;
/**
* Constructor
2015-06-29 09:46:49 -04:00
*
* @param ContainerInterface $container
*/
2015-09-17 23:11:18 -04:00
public function __construct(ContainerInterface $container)
2015-05-22 12:36:26 -04:00
{
2015-09-14 15:49:20 -04:00
parent::__construct($container);
$this->router = $container->get('aura-router');
$this->request = $container->get('request');
2015-05-22 12:36:26 -04:00
$this->output_routes = $this->_setup_routes();
2015-10-01 16:30:46 -04:00
$this->generate_convention_routes();
}
/**
* Generate routes based on controller methods
*
2015-10-06 12:15:19 -04:00
* @return void
2015-10-01 16:30:46 -04:00
*/
protected function generate_convention_routes()
{
$this->output_routes[] = $this->router->add('list', '/{controller}/{type}{/view}')
->setValues([
'controller' => $this->routes['convention']['default_controller'],
'action' => $this->routes['convention']['default_method'],
])->setTokens([
'type' => '[a-z_]+',
'view' => '[a-z_]+'
]);
$this->output_routes[] = $this->router->add('generic', '{/controller,action,view}')
->setValues([
'controller' => $this->routes['convention']['default_controller'],
'action' => $this->routes['convention']['default_method'],
'view' => '',
]);
2015-05-22 12:36:26 -04:00
}
/**
* Get the current route object, if one matches
*
* @return object
*/
public function get_route()
{
$error_handler = $this->container->get('error-handler');
$raw_route = $this->request->server->get('PATH_INFO');
$route_path = "/" . trim($raw_route, '/');
$error_handler->addDataTable('Route Info', [
'route_path' => $route_path
]);
$route = $this->router->match($route_path, $_SERVER);
2015-05-22 12:36:26 -04:00
return $route;
}
/**
* Get list of routes applied
*
* @return array
*/
public function get_output_routes()
{
return $this->output_routes;
}
2015-05-22 12:36:26 -04:00
/**
* Handle the current route
*
* @codeCoverageIgnore
2015-10-12 14:27:20 -04:00
* @param object|null $route
2015-05-22 12:36:26 -04:00
* @return void
*/
2015-10-09 14:34:55 -04:00
public function __invoke($route = NULL)
2015-05-22 12:36:26 -04:00
{
$error_handler = $this->container->get('error-handler');
2015-05-27 09:03:42 -04:00
2015-05-22 12:36:26 -04:00
if (is_null($route))
{
$route = $this->get_route();
$error_handler->addDataTable('route_args', (array)$route);
2015-05-22 12:36:26 -04:00
}
if ( ! $route)
{
2015-05-27 09:03:42 -04:00
$failure = $this->router->getFailedRoute();
$error_handler->addDataTable('failed_route', (array)$failure);
2015-05-22 12:36:26 -04:00
}
else
{
2015-10-01 16:30:46 -04:00
$controller_name = $route->params['controller'];
$action_method = $route->params['action'];
2015-09-17 23:11:18 -04:00
if (is_null($controller_name))
{
throw new \LogicException("Missing controller");
}
2015-10-01 16:30:46 -04:00
if (strpos($controller_name, '\\') === FALSE)
{
$map = $this->get_controller_list();
$controller_name = $map[$controller_name];
}
2015-05-22 12:36:26 -04:00
$params = (isset($route->params['params'])) ? $route->params['params'] : [];
if ( ! empty($route->tokens))
{
foreach ($route->tokens as $key => $v)
{
if (array_key_exists($key, $route->params))
{
$params[$key] = $route->params[$key];
}
}
}
2015-05-22 12:36:26 -04:00
}
$controller = new $controller_name($this->container);
2015-05-22 12:36:26 -04:00
// Run the appropriate controller method
$error_handler->addDataTable('controller_args', $params);
2015-05-22 12:36:26 -04:00
call_user_func_array([$controller, $action_method], $params);
}
/**
* Get the type of route, to select the current controller
*
* @return string
*/
public function get_controller()
{
2015-09-14 15:49:20 -04:00
$route_type = $this->__get('default_list');
$request_uri = $this->request->server->get('PATH_INFO');
$path = trim($request_uri, '/');
$segments = explode('/', $path);
2015-09-14 15:49:20 -04:00
$controller = reset($segments);
if (empty($controller))
{
$controller = $route_type;
}
2015-09-14 15:49:20 -04:00
return $controller;
}
/**
* Get the list of controllers in the default namespace
*
* @return array
*/
public function get_controller_list()
{
$convention_routing = $this->routes['convention'];
$default_namespace = $convention_routing['default_namespace'];
$path = str_replace('\\', '/', $default_namespace);
$path = trim($path, '/');
$actual_path = \_dir(SRC_DIR, $path);
$class_files = glob("{$actual_path}/*.php");
$controllers = [];
foreach ($class_files as $file)
{
$raw_class_name = basename(str_replace(".php", "", $file));
$path = strtolower(basename($raw_class_name));
$class_name = trim($default_namespace . '\\' . $raw_class_name, '\\');
$controllers[$path] = $class_name;
}
return $controllers;
}
/**
* Select controller based on the current url, and apply its relevent routes
*
* @return array
*/
public function _setup_routes()
2015-05-22 12:36:26 -04:00
{
$output_routes = [];
$route_type = $this->get_controller();
// Return early if invalid route array
2015-09-14 15:49:20 -04:00
if ( ! array_key_exists($route_type, $this->routes)) return [];
2015-05-22 12:36:26 -04:00
2015-09-14 15:49:20 -04:00
$applied_routes = array_merge($this->routes[$route_type], $this->routes['common']);
2015-05-22 12:36:26 -04:00
// Add routes
foreach ($applied_routes as $name => &$route)
2015-05-22 12:36:26 -04:00
{
$path = $route['path'];
unset($route['path']);
$controller_map = $this->get_controller_list();
$controller_class = $controller_map[$route_type];
// Prepend the controller to the route parameters
2015-10-01 16:30:46 -04:00
$route['controller'] = $controller_class;
2015-06-17 08:50:01 -04:00
// Select the appropriate router method based on the http verb
2015-09-17 23:11:18 -04:00
$add = (array_key_exists('verb', $route))
? "add" . ucfirst(strtolower($route['verb'])) : "addGet";
2015-06-17 08:50:01 -04:00
// Add the route to the router object
if ( ! array_key_exists('tokens', $route))
{
$output_routes[] = $this->router->$add($name, $path)->addValues($route);
}
else
{
$tokens = $route['tokens'];
unset($route['tokens']);
2015-06-17 08:50:01 -04:00
$output_routes[] = $this->router->$add($name, $path)
->addValues($route)
->addTokens($tokens);
2015-06-17 08:50:01 -04:00
}
}
return $output_routes;
2015-05-22 12:36:26 -04:00
}
}
2015-10-09 14:34:55 -04:00
// End of Dispatcher.php