diff --git a/core/core.services.yml b/core/core.services.yml index 951bebb..8fbe3ea 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -242,7 +242,7 @@ services: - [setFinalMatcher, ['@router.matcher.final_matcher']] url_generator: class: Drupal\Core\Routing\UrlGenerator - arguments: ['@router.route_provider', '@path_processor_manager', '@route_processor_manager', '@config.factory', '@settings'] + arguments: ['@router.route_provider', '@path_processor_manager', '@config.factory', '@settings'] calls: - [setRequest, ['@?request']] - [setContext, ['@?router.request_context']] @@ -475,8 +475,6 @@ services: tags: - { name: event_subscriber } arguments: [['@exception_controller', execute]] - route_processor_manager: - class: Drupal\Core\RouteProcessor\RouteProcessorManager path_processor_manager: class: Drupal\Core\PathProcessor\PathProcessorManager path_processor_decode: diff --git a/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php b/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php index e9633a7..b12da28 100644 --- a/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php +++ b/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php @@ -37,7 +37,7 @@ function __construct(CsrfTokenGenerator $csrf_token) { /** * {@inheritdoc} */ - public function processOutbound(Route $route, array &$parameters) { + public function processOutboundRoute(Route $route, array &$parameters) { if ($route->hasRequirement('_csrf')) { // Adding this to the parameters means it will get merged into the query // string when the route is compiled. diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index 8a525c9..acd2a36 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -64,7 +64,6 @@ public function register(ContainerBuilder $container) { $container->addCompilerPass(new RegisterServicesForDestructionPass()); // Add the compiler pass that will process the tagged services. $container->addCompilerPass(new RegisterPathProcessorsPass()); - $container->addCompilerPass(new RegisterRouteProcessorsPass()); $container->addCompilerPass(new ListCacheBinsPass()); // Add the compiler pass for appending string translators. $container->addCompilerPass(new RegisterStringTranslatorsPass()); diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php index 70de42d..ee9034c 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php @@ -37,5 +37,10 @@ public function process(ContainerBuilder $container) { $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; $manager->addMethodCall('addOutbound', array(new Reference($id), $priority)); } + // Add outbound route processors. + foreach ($container->findTaggedServiceIds('route_processor_outbound') as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $manager->addMethodCall('addOutboundRoute', array(new Reference($id), $priority)); + } } } diff --git a/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php b/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php index db8b799..4eda1d0 100644 --- a/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php +++ b/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php @@ -8,6 +8,8 @@ namespace Drupal\Core\PathProcessor; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; +use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface; /** * Path processor manager. @@ -15,7 +17,7 @@ * Holds an array of path processor objects and uses them to sequentially process * a path, in order of processor priority. */ -class PathProcessorManager implements InboundPathProcessorInterface, OutboundPathProcessorInterface { +class PathProcessorManager implements InboundPathProcessorInterface, OutboundPathProcessorInterface, OutboundRouteProcessorInterface { /** * Holds the array of inbound processors to cycle through. @@ -53,6 +55,23 @@ class PathProcessorManager implements InboundPathProcessorInterface, OutboundPat protected $sortedOutbound = array(); /** + * Holds the array of outbound route processors to cycle through. + * + * @var array + * An array whose keys are priorities and whose values are arrays of path + * processor objects. + */ + protected $outboundRouteProcessors = array(); + + /** + * Holds the array of outbound route processors, sorted by priority. + * + * @var array + * An array of path processor objects. + */ + protected $sortedOutboundRoute = array(); + + /** * Adds an inbound processor object to the $inboundProcessors property. * * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $processor @@ -118,6 +137,30 @@ public function processOutbound($path, &$options = array(), Request $request = N } /** + * Adds an outbound route processor object to $outboundRouteProcessors. + * + * @param \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface $processor + * The processor object to add. + * + * @param int $priority + * The priority of the processor being added. + */ + public function addOutboundRoute(OutboundRouteProcessorInterface $processor, $priority = 0) { + $this->outboundRouteProcessors[$priority][] = $processor; + $this->sortedOutboundRoute = array(); + } + + /** + * {inheritdoc} + */ + public function processOutboundRoute(Route $route, array &$parameters) { + $processors = $this->getOutboundRoute(); + foreach ($processors as $processor) { + $processor->processOutboundRoute($route, $parameters); + } + } + + /** * Returns the sorted array of outbound processors. * * @return array @@ -132,6 +175,20 @@ protected function getOutbound() { } /** + * Returns the sorted array of outbound route processors. + * + * @return array + * An array of processor objects. + */ + protected function getOutboundRoute() { + if (empty($this->sortedOutboundRoute)) { + $this->sortedOutboundRoute = $this->sortProcessors('outboundRouteProcessors'); + } + + return $this->sortedOutboundRoute; + } + + /** * Sorts the processors according to priority. * * @param string $type diff --git a/core/lib/Drupal/Core/RouteProcessor/OutboundRouteProcessorInterface.php b/core/lib/Drupal/Core/RouteProcessor/OutboundRouteProcessorInterface.php index c9bda24..e4d52bc 100644 --- a/core/lib/Drupal/Core/RouteProcessor/OutboundRouteProcessorInterface.php +++ b/core/lib/Drupal/Core/RouteProcessor/OutboundRouteProcessorInterface.php @@ -27,6 +27,6 @@ * @return * The processed path. */ - public function processOutbound(Route $route, array &$parameters); + public function processOutboundRoute(Route $route, array &$parameters); } diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php index 1bb4b53..8540d2b 100644 --- a/core/lib/Drupal/Core/Routing/UrlGenerator.php +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -41,13 +41,6 @@ class UrlGenerator extends ProviderBasedGenerator implements UrlGeneratorInterfa protected $pathProcessor; /** - * The route processor. - * - * @var \Drupal\Tests\Core\RouteProcessor\OutboundRouteProcessorInterface - */ - protected $routeProcessor; - - /** * The base path to use for urls. * * @var string @@ -85,11 +78,10 @@ class UrlGenerator extends ProviderBasedGenerator implements UrlGeneratorInterfa * @param \Symfony\Component\HttpKernel\Log\LoggerInterface $logger * An optional logger for recording errors. */ - public function __construct(RouteProviderInterface $provider, OutboundPathProcessorInterface $path_processor, OutboundRouteProcessorInterface $route_processor, ConfigFactory $config, Settings $settings, LoggerInterface $logger = NULL) { + public function __construct(RouteProviderInterface $provider, OutboundPathProcessorInterface $path_processor, ConfigFactory $config, Settings $settings, LoggerInterface $logger = NULL) { parent::__construct($provider, $logger); $this->pathProcessor = $path_processor; - $this->routeProcessor = $route_processor; $this->mixedModeSessions = $settings->get('mixed_mode_sessions', FALSE); $allowed_protocols = $config->get('system.filter')->get('protocols') ?: array('http', 'https'); Url::setAllowedProtocols($allowed_protocols); @@ -176,7 +168,7 @@ public function generate($name, $parameters = array(), $absolute = FALSE) { public function generateFromRoute($name, $parameters = array(), $options = array()) { $absolute = !empty($options['absolute']); $route = $this->getRoute($name); - $this->processRoute($route, $parameters); + $this->pathProcessor->processOutboundRoute($route, $parameters); // Symfony adds any parameters that are not path slugs as query strings. if (isset($options['query']) && is_array($options['query'])) { @@ -349,19 +341,6 @@ protected function processPath($path, &$options = array()) { } /** - * Passes the route to the processor manager for altering before complation. - * - * @param \Symfony\Component\Routing\Route $route - * The route object to process. - * - * @param array $parameters - * An array of parameters to be passed to the route compiler. - */ - protected function processRoute(SymfonyRoute $route, array &$parameters) { - $this->routeProcessor->processOutbound($route, $parameters); - } - - /** * Returns whether or not the url generator has been initialized. * * @return bool diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php index c889adc..2b42df5 100644 --- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php +++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php @@ -90,6 +90,28 @@ public function revisionOverview(NodeInterface $node) { * An array suitable for drupal_render(). */ public function page(NodeInterface $node) { + + $url_gen = \Drupal::urlGenerator(); + + \Drupal::request()->attributes->set('_controller_request', TRUE); + + xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); + + // shortcut.link_add_inline + + $url_gen->generateFromRoute('shortcut.link_add_inline', array('shortcut_set' => 'default')); + + $xhprof_data = xhprof_disable(); + + $XHPROF_ROOT = "/usr/local/Cellar/xhprof/0.9.2"; + include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php"; + include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php"; + + $xhprof_runs = new \XHProfRuns_Default(); + $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testing"); + + dpm("http://localhost/xhprof/index.php?run={$run_id}&source=xhprof_testing"); + $build = $this->buildPage($node); foreach ($node->uriRelationships() as $rel) { diff --git a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php index f75cd5f..33bbd70 100644 --- a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php +++ b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php @@ -61,7 +61,7 @@ public function testProcessOutboundNoRequirement() { $route = new Route(''); $parameters = array(); - $this->processor->processOutbound($route, $parameters); + $this->processor->processOutboundRoute($route, $parameters); // No parameters should be added to the parameters array. $this->assertEmpty($parameters); } @@ -69,7 +69,7 @@ public function testProcessOutboundNoRequirement() { /** * Tests the processOutbound() method with a _csrf route requirement. */ - public function testProcessOutbound() { + public function testProcessOutboundRoute() { $this->csrfToken->expects($this->once()) ->method('get') ->with('test') @@ -78,7 +78,7 @@ public function testProcessOutbound() { $route = new Route('', array(), array('_csrf' => 'test')); $parameters = array(); - $this->processor->processOutbound($route, $parameters); + $this->processor->processOutboundRoute($route, $parameters); // 'token' should be added to the parameters array. $this->assertArrayHasKey('token', $parameters); $this->assertSame($parameters['token'], 'test_token'); diff --git a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php index f49184f..d48cdf6 100644 --- a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php +++ b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php @@ -14,6 +14,7 @@ use Drupal\Core\PathProcessor\PathProcessorManager; use Drupal\language\HttpKernel\PathProcessorLanguage; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; use Drupal\Tests\UnitTestCase; @@ -150,4 +151,46 @@ function testProcessInbound() { $processed = $processor_manager->processInbound($test_path, $request); $this->assertEquals('user/1', $processed, 'Processing in the correct order resolves the system path from an alias.'); } + + /** + * Tests the Route process manager functionality. + */ + public function testProcessOutboundRoute() { + $route = new Route(''); + $parameters = array('test' => 'test'); + + $processors = array( + 10 => $this->getMockRouteProcessor($route, $parameters), + 5 => $this->getMockRouteProcessor($route, $parameters), + 0 => $this->getMockRouteProcessor($route, $parameters), + ); + + $path_processor_manager = new PathProcessorManager(); + + // Add the processors in reverse order. + foreach ($processors as $priority => $processor) { + $path_processor_manager->addOutboundRoute($processor, $priority); + } + + $path_processor_manager->processOutboundRoute($route, $parameters); + } + + /** + * Returns a mock Route processor object. + * + * @param \Symfony\Component\Routing\Route $route + * The Route to use in mock with() expectation. + * @param array $parameters + * The parameters to use in mock with() expectation. + * + * @return \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected function getMockRouteProcessor($route, $parameters) { + $processor = $this->getMock('Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface'); + $processor->expects($this->once()) + ->method('processOutboundRoute') + ->with($route, $parameters); + + return $processor; + } }