summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Gilliland2012-02-13 14:47:00 (GMT)
committerJames Gilliland2012-02-13 15:00:50 (GMT)
commit3ef99f9000cd0f88cc802421e82e49e454387376 (patch)
treeefc4eee2981a7e8af8f8d6f1b56b9a17453a0f97
parent5ae2b93226fddcd0b86b7cb6c660a049ba038311 (diff)
Convert to our own UrlMatcher
This is a transitional implementation but by using the UrlMatcherInterface we can embed our matching logic directly into Symfony's routing logic.
-rw-r--r--core/includes/router.inc91
-rw-r--r--core/lib/Drupal/Core/UrlMatcher.php85
2 files changed, 88 insertions, 88 deletions
diff --git a/core/includes/router.inc b/core/includes/router.inc
index b8a08f8..8c3973c 100644
--- a/core/includes/router.inc
+++ b/core/includes/router.inc
@@ -5,7 +5,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;
use Symfony\Component\HttpKernel;
use Symfony\Component\EventDispatcher\EventDispatcher;
-use Symfony\Component\Routing\Matcher\UrlMatcher as SymfonyUrlMatcher;
+use Drupal\Core\UrlMatcher;
/**
@@ -20,17 +20,13 @@ use Symfony\Component\Routing\Matcher\UrlMatcher as SymfonyUrlMatcher;
* the result to the caller (FALSE).
*/
function router_execute_active_handler($request) {
- // Do some hand waving to setup the routing.
- $routes = router_get_routes($request);
try {
// Resolve a routing context(path, etc) using the routes object to a
- // Set a /routing/ context to translate
- // @todo probably write our own route object and UrlMatcher to handle
- // converting Drupal's db driven backend.
+ // Set a routing context to translate.
$context = new Routing\RequestContext();
$context->fromRequest($request);
- $matcher = new SymfonyUrlMatcher($routes, $context);
+ $matcher = new UrlMatcher($context);
// Push path paramaters into attributes.
$request->attributes->add($matcher->match($request->getPathInfo()));
@@ -53,84 +49,3 @@ function router_execute_active_handler($request) {
return $response;
}
-
-/**
- * Get a RouteCollection for resolving a request.
- *
- * Ok, so... we need a routing collection that's not this "dumb". Symfony's just
- * is just a trivial implementation. It probably means we need our own
- * DrupalRouteCollection which would actually wrap this logic, our menu router
- * table, translating between it, and caching.
- */
-function router_get_routes($request) {
-
- // Rebuild if we know it's needed, or if the menu masks are missing which
- // occurs rarely, likely due to a race condition of multiple rebuilds.
- if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {
- menu_rebuild();
- }
-
-
- $routes = new Routing\RouteCollection();
- $foo = db_query('SELECT path, page_callback, page_arguments FROM {menu_router}');
- while ($router_item = $foo->fetchAssoc()) {
- $route = array(
- 'path' => $router_item['path'],
- '_controller' => $router_item['page_callback'],
- );
- if (0 !== strpos($route['path'], '/')) {
- $route['path'] = '/' . $route['path'];
- }
-
- // Place argument defaults on the route.
- foreach (unserialize($router_item['page_arguments']) as $k => $v) {
- $route[$k] = $v;
- }
-
- $routes->add(hash('sha256', $route['path']), new Routing\Route($route['path'], $route));
- }
-
- return $routes;
-
- // Since there is no limit to the length of $path, use a hash to keep it
- // short yet unique.
- $cid = 'menu_item:' . hash('sha256', $path);
- if ($cached = cache('menu')->get($cid)) {
- $router_item = $cached->data;
- }
- else {
- $parts = array_slice($original_map, 0, MENU_MAX_PARTS);
- $ancestors = menu_get_ancestors($parts);
- $router_item = db_query_range('SELECT * FROM {menu_router} WHERE path IN (:ancestors) ORDER BY fit DESC', 0, 1, array(':ancestors' => $ancestors))->fetchAssoc();
- cache('menu')->set($cid, $router_item);
- }
-
- $routes = new Routing\RouteCollection();
- foreach (module_list() as $module) {
- $items = module_invoke($module, 'menu');
-
- foreach ($items as $path => $item) {
- // Drupal doesn't prefix but if someone did we wouldn't want to double up.
- if (0 !== strpos($path, '/')) {
- $path = '/' . $path;
- }
-
- // Set base route array.
- $route = array(
- // A page callback could be a router. I'm not sure if the controller
- // should actually be a thin layer on top or work like this yet.
- '_controller' => $item['page callback'],
- );
-
- // Place argument defaults on the route.
- foreach ($item['page arguments'] as $k => $v) {
- $route[$k] = $v;
- }
- // @todo put other "menu" information somewhere.
-
- $routes->add(hash('sha256', $path), new Routing\Route($path, $route));
- }
- }
-
- return $routes;
-}
diff --git a/core/lib/Drupal/Core/UrlMatcher.php b/core/lib/Drupal/Core/UrlMatcher.php
new file mode 100644
index 0000000..f56b13a
--- /dev/null
+++ b/core/lib/Drupal/Core/UrlMatcher.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Drupal\Core;
+
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Matcher\UrlMatcher as SymfonyUrlMatcher;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * UrlMatcher matches URL based on a set of routes.
+ */
+class UrlMatcher extends SymfonyUrlMatcher {
+
+ protected $context;
+
+ /**
+ * Constructor.
+ *
+ * @param RouteCollection $routes A RouteCollection instance
+ * @param RequestContext $context The context
+ */
+ public function __construct(RequestContext $context) {
+ $this->context = $context;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @api
+ */
+ public function match($pathinfo) {
+
+ $this->allow = array();
+
+ // Symfony uses a prefixing / but we don't yet.
+ $dpathinfo = ltrim($pathinfo, '/');
+
+ // Do our fancy frontpage logic.
+ if (empty($dpathinfo)) {
+ $dpathinfo = variable_get('site_frontpage', 'user');
+ }
+
+ if ($router_item = $this->matchDrupalItem($dpathinfo)) {
+
+ $routes = new RouteCollection();
+ $routes->add(hash('sha256', $router_item['path']), $this->convertDrupalItem($router_item));
+
+ if ($ret = $this->matchCollection($pathinfo, $routes)) {
+ return $ret;
+ }
+ }
+
+ throw 0 < count($this->allow)
+ ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow)))
+ : new ResourceNotFoundException();
+ }
+
+ /**
+ * Get a drupal menu item.
+ *
+ * @param string $path
+ * The path being looked up by
+ */
+ protected function matchDrupalItem($path) {
+ // For now we can just proxy our procedural method. At some point this will
+ // become more complicated because we'll need to get back candidates for a
+ // path and them resolve them based on things like method and scheme which
+ // we currently can't do.
+ return menu_get_item($path);
+ }
+
+ protected function convertDrupalItem($router_item) {
+ $route = array(
+ '_controller' => $router_item['page_callback']
+ );
+ // Place argument defaults on the route.
+ foreach ($router_item['page_arguments'] as $k => $v) {
+ $route[$k] = $v;
+ }
+ return new Route($router_item['path'], $route);
+ }
+}