router.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. use Symfony\Component\Routing\Matcher\UrlMatcher;
  9. use Symfony\Component\Routing\Generator\UrlGenerator;
  10. use Symfony\Component\Routing\RequestContext;
  11. use Symfony\Component\Routing\RouteCollection;
  12. //use Symfony\Component\Routing\Route;
  13. class OC_Router {
  14. protected $collections = array();
  15. protected $collection = null;
  16. protected $root = null;
  17. protected $generator = null;
  18. protected $routing_files;
  19. protected $cache_key;
  20. public function __construct() {
  21. $baseUrl = OC_Helper::linkTo('', 'index.php');
  22. if ( !OC::$CLI) {
  23. $method = $_SERVER['REQUEST_METHOD'];
  24. }else{
  25. $method = 'GET';
  26. }
  27. $host = OC_Request::serverHost();
  28. $schema = OC_Request::serverProtocol();
  29. $this->context = new RequestContext($baseUrl, $method, $host, $schema);
  30. // TODO cache
  31. $this->root = $this->getCollection('root');
  32. }
  33. public function getRoutingFiles() {
  34. if (!isset($this->routing_files)) {
  35. $this->routing_files = array();
  36. foreach(OC_APP::getEnabledApps() as $app) {
  37. $file = OC_App::getAppPath($app).'/appinfo/routes.php';
  38. if(file_exists($file)) {
  39. $this->routing_files[$app] = $file;
  40. }
  41. }
  42. }
  43. return $this->routing_files;
  44. }
  45. public function getCacheKey() {
  46. if (!isset($this->cache_key)) {
  47. $files = $this->getRoutingFiles();
  48. $files[] = 'settings/routes.php';
  49. $files[] = 'core/routes.php';
  50. $files[] = 'ocs/routes.php';
  51. $this->cache_key = OC_Cache::generateCacheKeyFromFiles($files);
  52. }
  53. return $this->cache_key;
  54. }
  55. /**
  56. * loads the api routes
  57. */
  58. public function loadRoutes() {
  59. foreach($this->getRoutingFiles() as $app => $file) {
  60. $this->useCollection($app);
  61. require_once $file;
  62. $collection = $this->getCollection($app);
  63. $this->root->addCollection($collection, '/apps/'.$app);
  64. }
  65. $this->useCollection('root');
  66. require_once 'settings/routes.php';
  67. require_once 'core/routes.php';
  68. // include ocs routes
  69. require_once 'ocs/routes.php';
  70. $collection = $this->getCollection('ocs');
  71. $this->root->addCollection($collection, '/ocs');
  72. }
  73. protected function getCollection($name) {
  74. if (!isset($this->collections[$name])) {
  75. $this->collections[$name] = new RouteCollection();
  76. }
  77. return $this->collections[$name];
  78. }
  79. /**
  80. * Sets the collection to use for adding routes
  81. *
  82. * @param string $name Name of the colletion to use.
  83. */
  84. public function useCollection($name) {
  85. $this->collection = $this->getCollection($name);
  86. }
  87. /**
  88. * Create a OC_Route.
  89. *
  90. * @param string $name Name of the route to create.
  91. * @param string $pattern The pattern to match
  92. * @param array $defaults An array of default parameter values
  93. * @param array $requirements An array of requirements for parameters (regexes)
  94. */
  95. public function create($name, $pattern, array $defaults = array(), array $requirements = array()) {
  96. $route = new OC_Route($pattern, $defaults, $requirements);
  97. $this->collection->add($name, $route);
  98. return $route;
  99. }
  100. /**
  101. * Find the route matching $url.
  102. *
  103. * @param string $url The url to find
  104. */
  105. public function match($url) {
  106. $matcher = new UrlMatcher($this->root, $this->context);
  107. $parameters = $matcher->match($url);
  108. if (isset($parameters['action'])) {
  109. $action = $parameters['action'];
  110. if (!is_callable($action)) {
  111. var_dump($action);
  112. throw new Exception('not a callable action');
  113. }
  114. unset($parameters['action']);
  115. call_user_func($action, $parameters);
  116. } elseif (isset($parameters['file'])) {
  117. include $parameters['file'];
  118. } else {
  119. throw new Exception('no action available');
  120. }
  121. }
  122. /**
  123. * Get the url generator
  124. *
  125. */
  126. public function getGenerator()
  127. {
  128. if (null !== $this->generator) {
  129. return $this->generator;
  130. }
  131. return $this->generator = new UrlGenerator($this->root, $this->context);
  132. }
  133. /**
  134. * Generate url based on $name and $parameters
  135. *
  136. * @param string $name Name of the route to use.
  137. * @param array $parameters Parameters for the route
  138. */
  139. public function generate($name, $parameters = array(), $absolute = false)
  140. {
  141. return $this->getGenerator()->generate($name, $parameters, $absolute);
  142. }
  143. /**
  144. * Generate JSON response for routing in javascript
  145. */
  146. public static function JSRoutes()
  147. {
  148. $router = OC::getRouter();
  149. $etag = $router->getCacheKey();
  150. OC_Response::enableCaching();
  151. OC_Response::setETagHeader($etag);
  152. $root = $router->getCollection('root');
  153. $routes = array();
  154. foreach($root->all() as $name => $route) {
  155. $compiled_route = $route->compile();
  156. $defaults = $route->getDefaults();
  157. unset($defaults['action']);
  158. $routes[$name] = array(
  159. 'tokens' => $compiled_route->getTokens(),
  160. 'defaults' => $defaults,
  161. );
  162. }
  163. OCP\JSON::success ( array( 'data' => $routes ) );
  164. }
  165. }