Skip to content
Snippets Groups Projects
Commit dff5d065 authored by Dave Long's avatar Dave Long
Browse files

Merge branch '3394870-allow-controller-service' into '11.x'

Resolve #3394870 "Allow controller service"

See merge request !5034
parents 53beb854 a0d80a5d
No related branches found
No related tags found
No related merge requests found
Pipeline #35396 failed
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url; use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Messenger\MessengerTrait; use Drupal\Core\Messenger\MessengerTrait;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
/** /**
...@@ -106,7 +108,25 @@ abstract class ControllerBase implements ContainerInjectionInterface { ...@@ -106,7 +108,25 @@ abstract class ControllerBase implements ContainerInjectionInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static(); $args = [];
if (method_exists(static::class, '__construct')) {
$constructor = new \ReflectionMethod(static::class, '__construct');
foreach ($constructor->getParameters() as $parameter) {
$service = (string) $parameter->getType();
foreach ($parameter->getAttributes(Autowire::class) as $attribute) {
$service = (string) $attribute->newInstance()->value;
}
if (!$container->has($service)) {
throw new AutowiringFailedException($service, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s::_construct()", you should configure its value explicitly.', $service, $parameter->getName(), static::class));
}
$args[] = $container->get($service);
}
}
return new static(...$args);
} }
/** /**
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
use Drupal\node\NodeStorageInterface; use Drupal\node\NodeStorageInterface;
use Drupal\node\NodeTypeInterface; use Drupal\node\NodeTypeInterface;
use Drupal\node\NodeInterface; use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* Returns responses for Node routes. * Returns responses for Node routes.
...@@ -57,17 +56,6 @@ public function __construct(DateFormatterInterface $date_formatter, RendererInte ...@@ -57,17 +56,6 @@ public function __construct(DateFormatterInterface $date_formatter, RendererInte
$this->entityRepository = $entity_repository; $this->entityRepository = $entity_repository;
} }
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('date.formatter'),
$container->get('renderer'),
$container->get('entity.repository')
);
}
/** /**
* Displays add content links for available content types. * Displays add content links for available content types.
* *
......
<?php
namespace Drupal\system_test\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Lock\LockBackendInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
/**
* A controller that does not specify its autowired dependencies correctly.
*/
class BrokenSystemTestController extends ControllerBase {
/**
* Constructs the BrokenSystemTestController.
*
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock service.
*/
public function __construct(
protected LockBackendInterface $lock,
) {}
}
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
use Drupal\Core\Render\Markup; use Drupal\Core\Render\Markup;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* Controller routines for system_test routes. * Controller routines for system_test routes.
...@@ -71,7 +71,15 @@ class SystemTestController extends ControllerBase implements TrustedCallbackInte ...@@ -71,7 +71,15 @@ class SystemTestController extends ControllerBase implements TrustedCallbackInte
* @param \Drupal\Core\Messenger\MessengerInterface $messenger * @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service. * The messenger service.
*/ */
public function __construct(LockBackendInterface $lock, LockBackendInterface $persistent_lock, AccountInterface $current_user, RendererInterface $renderer, MessengerInterface $messenger) { public function __construct(
#[Autowire(service: 'lock')]
LockBackendInterface $lock,
#[Autowire(service: 'lock.persistent')]
LockBackendInterface $persistent_lock,
AccountInterface $current_user,
RendererInterface $renderer,
MessengerInterface $messenger,
) {
$this->lock = $lock; $this->lock = $lock;
$this->persistentLock = $persistent_lock; $this->persistentLock = $persistent_lock;
$this->currentUser = $current_user; $this->currentUser = $current_user;
...@@ -79,19 +87,6 @@ public function __construct(LockBackendInterface $lock, LockBackendInterface $pe ...@@ -79,19 +87,6 @@ public function __construct(LockBackendInterface $lock, LockBackendInterface $pe
$this->messenger = $messenger; $this->messenger = $messenger;
} }
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('lock'),
$container->get('lock.persistent'),
$container->get('current_user'),
$container->get('renderer'),
$container->get('messenger')
);
}
/** /**
* Tests main content fallback. * Tests main content fallback.
* *
......
<?php
namespace Drupal\KernelTests\Core\Controller;
use Drupal\KernelTests\KernelTestBase;
use Drupal\system_test\Controller\BrokenSystemTestController;
use Drupal\system_test\Controller\SystemTestController;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
/**
* Tests \Drupal\Core\Controller\ControllerBase.
*
* @coversDefaultClass \Drupal\Core\Controller\ControllerBase
* @group Controller
*/
class ControllerBaseTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
protected static $modules = ['system_test', 'system'];
/**
* @covers ::create
*/
public function testCreate() {
$controller = $this->container->get('class_resolver')->getInstanceFromDefinition(SystemTestController::class);
$property = new \ReflectionProperty(SystemTestController::class, 'persistentLock');
$this->assertSame($this->container->get('lock.persistent'), $property->getValue($controller));
}
/**
* @covers ::create
*/
public function testCreateException() {
$this->expectException(AutowiringFailedException::class);
$this->expectExceptionMessage('Cannot autowire service "Drupal\Core\Lock\LockBackendInterface": argument "$lock" of method "Drupal\system_test\Controller\BrokenSystemTestController::_construct()", you should configure its value explicitly.');
$this->container->get('class_resolver')->getInstanceFromDefinition(BrokenSystemTestController::class);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment