diff options
author | Robin Appelman <icewind@owncloud.com> | 2014-03-10 14:04:58 +0100 |
---|---|---|
committer | Robin Appelman <icewind@owncloud.com> | 2014-03-10 14:04:58 +0100 |
commit | 8ab7d18a6a2b023527d2eef63099e2834c46ec97 (patch) | |
tree | 393f7f704655555a1892200215a46f4b741abc80 /lib/private/route | |
parent | 0ffd32a1ae8c4b9da2434a0b5623c1fe6e910467 (diff) | |
download | nextcloud-server-8ab7d18a6a2b023527d2eef63099e2834c46ec97.tar.gz nextcloud-server-8ab7d18a6a2b023527d2eef63099e2834c46ec97.zip |
Move the router classes to a namespace and expose it with a public interface
Diffstat (limited to 'lib/private/route')
-rw-r--r-- | lib/private/route/route.php | 132 | ||||
-rw-r--r-- | lib/private/route/router.php | 202 |
2 files changed, 334 insertions, 0 deletions
diff --git a/lib/private/route/route.php b/lib/private/route/route.php new file mode 100644 index 00000000000..6ade9ec15f6 --- /dev/null +++ b/lib/private/route/route.php @@ -0,0 +1,132 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Route; + +use OCP\Route\IRoute; +use Symfony\Component\Routing\Route as SymfonyRoute; + +class Route extends SymfonyRoute implements IRoute { + /** + * Specify the method when this route is to be used + * + * @param string $method HTTP method (uppercase) + * @return \OC\Route\Route + */ + public function method($method) { + $this->setRequirement('_method', strtoupper($method)); + return $this; + } + + /** + * Specify POST as the method to use with this route + */ + public function post() { + $this->method('POST'); + return $this; + } + + /** + * Specify GET as the method to use with this route + */ + public function get() { + $this->method('GET'); + return $this; + } + + /** + * Specify PUT as the method to use with this route + */ + public function put() { + $this->method('PUT'); + return $this; + } + + /** + * Specify DELETE as the method to use with this route + */ + public function delete() { + $this->method('DELETE'); + return $this; + } + + /** + * Specify PATCH as the method to use with this route + */ + public function patch() { + $this->method('PATCH'); + return $this; + } + + /** + * Defaults to use for this route + * + * @param array $defaults The defaults + * @return \OC\Route\Route + */ + public function defaults($defaults) { + $action = $this->getDefault('action'); + $this->setDefaults($defaults); + if (isset($defaults['action'])) { + $action = $defaults['action']; + } + $this->action($action); + return $this; + } + + /** + * Requirements for this route + * + * @param array $requirements The requirements + * @return \OC\Route\Route + */ + public function requirements($requirements) { + $method = $this->getRequirement('_method'); + $this->setRequirements($requirements); + if (isset($requirements['_method'])) { + $method = $requirements['_method']; + } + if ($method) { + $this->method($method); + } + return $this; + } + + /** + * The action to execute when this route matches + * + * @param string|callable $class the class or a callable + * @param string $function the function to use with the class + * @return \OC\Route\Route + * + * This function is called with $class set to a callable or + * to the class with $function + */ + public function action($class, $function = null) { + $action = array($class, $function); + if (is_null($function)) { + $action = $class; + } + $this->setDefault('action', $action); + return $this; + } + + /** + * The action to execute when this route matches, includes a file like + * it is called directly + * @param $file + */ + public function actionInclude($file) { + $function = create_function('$param', + 'unset($param["_route"]);' + .'$_GET=array_merge($_GET, $param);' + .'unset($param);' + .'require_once "'.$file.'";'); + $this->action($function); + } +} diff --git a/lib/private/route/router.php b/lib/private/route/router.php new file mode 100644 index 00000000000..60ba5878401 --- /dev/null +++ b/lib/private/route/router.php @@ -0,0 +1,202 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Route; + +use OCP\Route\IRouter; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class Router implements IRouter { + /** + * @var \Symfony\Component\Routing\RouteCollection[] + */ + protected $collections = array(); + + /** + * @var \Symfony\Component\Routing\RouteCollection + */ + protected $collection = null; + + /** + * @var \Symfony\Component\Routing\RouteCollection + */ + protected $root = null; + + /** + * @var \Symfony\Component\Routing\Generator\UrlGenerator + */ + protected $generator = null; + + /** + * @var string[] + */ + protected $routingFiles; + + /** + * @var string + */ + protected $cacheKey; + + protected $loaded = false; + + public function __construct() { + $baseUrl = \OC_Helper::linkTo('', 'index.php'); + if (!\OC::$CLI) { + $method = $_SERVER['REQUEST_METHOD']; + } else { + $method = 'GET'; + } + $host = \OC_Request::serverHost(); + $schema = \OC_Request::serverProtocol(); + $this->context = new RequestContext($baseUrl, $method, $host, $schema); + // TODO cache + $this->root = $this->getCollection('root'); + } + + /** + * Get the files to load the routes from + * + * @return string[] + */ + public function getRoutingFiles() { + if (!isset($this->routingFiles)) { + $this->routingFiles = array(); + foreach (\OC_APP::getEnabledApps() as $app) { + $file = \OC_App::getAppPath($app) . '/appinfo/routes.php'; + if (file_exists($file)) { + $this->routingFiles[$app] = $file; + } + } + } + return $this->routingFiles; + } + + public function getCacheKey() { + if (!isset($this->cacheKey)) { + $files = $this->getRoutingFiles(); + $files[] = 'settings/routes.php'; + $files[] = 'core/routes.php'; + $files[] = 'ocs/routes.php'; + $this->cacheKey = \OC_Cache::generateCacheKeyFromFiles($files); + } + return $this->cacheKey; + } + + /** + * loads the api routes + */ + public function loadRoutes() { + if ($this->loaded) { + return; + } + $this->loaded = true; + foreach ($this->getRoutingFiles() as $app => $file) { + $this->useCollection($app); + require_once $file; + $collection = $this->getCollection($app); + $collection->addPrefix('/apps/' . $app); + $this->root->addCollection($collection); + } + $this->useCollection('root'); + require_once 'settings/routes.php'; + require_once 'core/routes.php'; + + // include ocs routes + require_once 'ocs/routes.php'; + $collection = $this->getCollection('ocs'); + $collection->addPrefix('/ocs'); + $this->root->addCollection($collection); + } + + /** + * @param string $name + * @return \Symfony\Component\Routing\RouteCollection + */ + protected function getCollection($name) { + if (!isset($this->collections[$name])) { + $this->collections[$name] = new RouteCollection(); + } + return $this->collections[$name]; + } + + /** + * Sets the collection to use for adding routes + * + * @param string $name Name of the collection to use. + */ + public function useCollection($name) { + $this->collection = $this->getCollection($name); + } + + /** + * Create a \OC\Route\Route. + * + * @param string $name Name of the route to create. + * @param string $pattern The pattern to match + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + * @return \OC\Route\Route + */ + public function create($name, $pattern, array $defaults = array(), array $requirements = array()) { + $route = new Route($pattern, $defaults, $requirements); + $this->collection->add($name, $route); + return $route; + } + + /** + * Find the route matching $url. + * + * @param string $url The url to find + * @throws \Exception + */ + public function match($url) { + $matcher = new UrlMatcher($this->root, $this->context); + $parameters = $matcher->match($url); + if (isset($parameters['action'])) { + $action = $parameters['action']; + if (!is_callable($action)) { + var_dump($action); + throw new \Exception('not a callable action'); + } + unset($parameters['action']); + call_user_func($action, $parameters); + } elseif (isset($parameters['file'])) { + include $parameters['file']; + } else { + throw new \Exception('no action available'); + } + } + + /** + * Get the url generator + * + */ + public function getGenerator() { + if (null !== $this->generator) { + return $this->generator; + } + + return $this->generator = new UrlGenerator($this->root, $this->context); + } + + /** + * Generate url based on $name and $parameters + * + * @param string $name Name of the route to use. + * @param array $parameters Parameters for the route + * @param bool $absolute + * @return string + */ + public function generate($name, $parameters = array(), $absolute = false) { + return $this->getGenerator()->generate($name, $parameters, $absolute); + } + +} |