router.php 4.5 KB

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