Issue #2343677 by damiankloip, znerol, Fabianx: Fixed Stack middleware suffers from incomplete service construction.
parent
7ed6ebe8f4
commit
c033857b11
|
@ -393,12 +393,7 @@ services:
|
|||
class: Drupal\Core\Controller\TitleResolver
|
||||
arguments: ['@controller_resolver', '@string_translation']
|
||||
http_kernel:
|
||||
class: Symfony\Component\HttpKernel\HttpKernel
|
||||
factory_method: resolve
|
||||
factory_service: http_kernel_factory
|
||||
arguments: ['@http_kernel.basic']
|
||||
http_kernel_factory:
|
||||
class: Stack\Builder
|
||||
class: Stack\StackedHttpKernel
|
||||
http_kernel.basic:
|
||||
class: Symfony\Component\HttpKernel\HttpKernel
|
||||
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\Core\DependencyInjection\Compiler;
|
|||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Provides a compiler pass for stacked HTTP kernels.
|
||||
|
@ -21,25 +22,44 @@ class StackedKernelPass implements CompilerPassInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container) {
|
||||
if (!$container->hasDefinition('http_kernel_factory')) {
|
||||
|
||||
if (!$container->hasDefinition('http_kernel')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$http_kernel_factory = $container->getDefinition('http_kernel_factory');
|
||||
$middleware_priorities = array();
|
||||
$middleware_arguments = array();
|
||||
foreach ($container->findTaggedServiceIds('http_middleware') as $id => $attributes) {
|
||||
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
|
||||
$middleware_priorities[$id] = $priority;
|
||||
$definition = $container->getDefinition($id);
|
||||
$middleware_arguments[$id] = $definition->getArguments();
|
||||
array_unshift($middleware_arguments[$id], $definition->getClass());
|
||||
}
|
||||
array_multisort($middleware_priorities, SORT_DESC, $middleware_arguments, SORT_DESC);
|
||||
$stacked_kernel = $container->getDefinition('http_kernel');
|
||||
|
||||
foreach ($middleware_arguments as $id => $push_arguments) {
|
||||
$http_kernel_factory->addMethodCall('push', $push_arguments);
|
||||
// Return now if this is not a stacked kernel.
|
||||
if ($stacked_kernel->getClass() !== 'Stack\StackedHttpKernel') {
|
||||
return;
|
||||
}
|
||||
|
||||
$middlewares = [];
|
||||
$priorities = [];
|
||||
|
||||
foreach ($container->findTaggedServiceIds('http_middleware') as $id => $attributes) {
|
||||
$priorities[$id] = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
|
||||
$middlewares[$id] = $container->getDefinition($id);
|
||||
}
|
||||
|
||||
array_multisort($priorities, SORT_ASC, $middlewares);
|
||||
|
||||
$decorated_id = 'http_kernel.basic';
|
||||
$middlewares_param = [new Reference($decorated_id)];
|
||||
foreach ($middlewares as $id => $decorator) {
|
||||
// Prepend a reference to the middlewares container parameter.
|
||||
array_unshift($middlewares_param, new Reference($id));
|
||||
|
||||
// Prepend the inner kernel as first constructor argument.
|
||||
$arguments = $decorator->getArguments();
|
||||
array_unshift($arguments, new Reference($decorated_id));
|
||||
$decorator->setArguments($arguments);
|
||||
|
||||
$decorated_id = $id;
|
||||
}
|
||||
|
||||
$arguments = [$middlewares_param[0], $middlewares_param];
|
||||
$stacked_kernel->setArguments($arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\DependencyInjection\Compiler\StackedKernelPassTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\DependencyInjection\Compiler;
|
||||
|
||||
use Drupal\Core\DependencyInjection\Compiler\StackedKernelPass;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass
|
||||
* @group DependencyInjection
|
||||
*/
|
||||
class StackedKernelPassTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The stacked kernel pass.
|
||||
*
|
||||
* @var \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass
|
||||
*/
|
||||
protected $stackedKernelPass;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\DependencyInjection\Container
|
||||
*/
|
||||
protected $containerBuilder;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->stackedKernelPass = new StackedKernelPass();
|
||||
$this->containerBuilder = new ContainerBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::process
|
||||
*/
|
||||
public function testProcessWithStackedKernel() {
|
||||
$stacked_kernel = new Definition('Stack\StackedHttpKernel');
|
||||
|
||||
$this->containerBuilder->setDefinition('http_kernel', $stacked_kernel);
|
||||
$this->containerBuilder->setDefinition('http_kernel.basic', $this->createMiddlewareServiceDefinition(FALSE, 0));
|
||||
|
||||
$this->containerBuilder->setDefinition('http_kernel.three', $this->createMiddlewareServiceDefinition());
|
||||
$this->containerBuilder->setDefinition('http_kernel.one', $this->createMiddlewareServiceDefinition(TRUE, 10));
|
||||
$this->containerBuilder->setDefinition('http_kernel.two', $this->createMiddlewareServiceDefinition(TRUE, 5));
|
||||
|
||||
$this->stackedKernelPass->process($this->containerBuilder);
|
||||
|
||||
$stacked_kernel_args = $this->containerBuilder->getDefinition('http_kernel')->getArguments();
|
||||
|
||||
// Check the stacked kernel args.
|
||||
$this->assertSame((string) $stacked_kernel_args[0], 'http_kernel.one');
|
||||
$this->assertCount(4, $stacked_kernel_args[1]);
|
||||
$this->assertSame((string) $stacked_kernel_args[1][0], 'http_kernel.one');
|
||||
$this->assertSame((string) $stacked_kernel_args[1][1], 'http_kernel.two');
|
||||
$this->assertSame((string) $stacked_kernel_args[1][2], 'http_kernel.three');
|
||||
$this->assertSame((string) $stacked_kernel_args[1][3], 'http_kernel.basic');
|
||||
|
||||
// Check the modified definitions.
|
||||
$definition = $this->containerBuilder->getDefinition('http_kernel.one');
|
||||
$args = $definition->getArguments();
|
||||
$this->assertSame('http_kernel.two', (string) $args[0]);
|
||||
$this->assertSame('test', $args[1]);
|
||||
|
||||
$definition = $this->containerBuilder->getDefinition('http_kernel.two');
|
||||
$args = $definition->getArguments();
|
||||
$this->assertSame('http_kernel.three', (string) $args[0]);
|
||||
$this->assertSame('test', $args[1]);
|
||||
|
||||
$definition = $this->containerBuilder->getDefinition('http_kernel.three');
|
||||
$args = $definition->getArguments();
|
||||
$this->assertSame('http_kernel.basic', (string) $args[0]);
|
||||
$this->assertSame('test', $args[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::process
|
||||
*/
|
||||
public function testProcessWithHttpKernel() {
|
||||
$kernel = new Definition('Symfony\Component\HttpKernel\HttpKernelInterface');
|
||||
$this->containerBuilder->setDefinition('http_kernel', $kernel);
|
||||
$this->stackedKernelPass->process($this->containerBuilder);
|
||||
|
||||
$unprocessed_kernel = $this->containerBuilder->getDefinition('http_kernel');
|
||||
|
||||
$this->assertSame($kernel, $unprocessed_kernel);
|
||||
$this->assertSame($kernel->getArguments(), $unprocessed_kernel->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a middleware definition.
|
||||
*
|
||||
* @param bool $tag
|
||||
* Whether ot not to set the http_middleware tag.
|
||||
* @param int $priority
|
||||
* The priority to be used for the tag.
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\Definition
|
||||
*/
|
||||
protected function createMiddlewareServiceDefinition($tag = TRUE, $priority = 0) {
|
||||
$definition = new Definition('Symfony\Component\HttpKernel\HttpKernelInterface', ['test']);
|
||||
|
||||
if ($tag) {
|
||||
$definition->addTag('http_middleware', ['priority' => $priority]);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue