Unverified Commit d7a61c29 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3452852 by dpi, longwave, smustgrave, mstrelan, mortona2k, dydave,...

Issue #3452852 by dpi, longwave, smustgrave, mstrelan, mortona2k, dydave, shalini_jha, danielveza, znerol, acbramley, mxh, elc: Add create() factory method with autowired parameters to PluginBase
parent 09d8cb80
Loading
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -49612,12 +49612,6 @@
	'count' => 1,
	'path' => __DIR__ . '/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTestBase.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Tests\\\\Core\\\\Menu\\\\MenuLinkMock\\:\\:create\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/tests/Drupal/Tests/Core/Menu/MenuLinkMock.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Tests\\\\Core\\\\Menu\\\\MenuTreeParametersTest\\:\\:providerTestSetMinDepth\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
+3 −25
Original line number Diff line number Diff line
@@ -2,9 +2,7 @@

namespace Drupal\Core\DependencyInjection;

use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;

/**
 * Defines a trait for automatically wiring dependencies from the container.
@@ -14,6 +12,8 @@
 */
trait AutowireTrait {

  use AutowiredInstanceTrait;

  /**
   * Instantiates a new instance of the implementing class using autowiring.
   *
@@ -23,29 +23,7 @@ trait AutowireTrait {
   * @return static
   */
  public static function create(ContainerInterface $container) {
    $args = [];

    if (method_exists(static::class, '__construct')) {
      $constructor = new \ReflectionMethod(static::class, '__construct');
      foreach ($constructor->getParameters() as $parameter) {
        $service = ltrim((string) $parameter->getType(), '?');
        foreach ($parameter->getAttributes(Autowire::class) as $attribute) {
          $service = (string) $attribute->newInstance()->value;
        }

        if (!$container->has($service)) {
          if ($parameter->allowsNull()) {
            $args[] = NULL;
            continue;
          }
          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);
    return static::createInstanceAutowired($container);
  }

}
+50 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\DependencyInjection;

use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;

/**
 * Defines a base trait for automatically wiring dependency arguments.
 */
trait AutowiredInstanceTrait {

  /**
   * Instantiates a new instance of the implementing class using autowiring.
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The service container this instance should use.
   * @param mixed ...$args
   *   Any predefined arguments to pass to the constructor.
   *
   * @return static
   */
  public static function createInstanceAutowired(ContainerInterface $container, mixed ...$args): static {
    if (method_exists(static::class, '__construct')) {
      $constructor = new \ReflectionMethod(static::class, '__construct');
      foreach (array_slice($constructor->getParameters(), count($args)) as $parameter) {
        $service = ltrim((string) $parameter->getType(), '?');
        foreach ($parameter->getAttributes(Autowire::class) as $attribute) {
          $service = (string) $attribute->newInstance()->value;
        }

        if (!$container->has($service)) {
          if ($parameter->allowsNull()) {
            $args[] = NULL;
            continue;
          }
          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);
  }

}
+15 −0
Original line number Diff line number Diff line
@@ -3,9 +3,11 @@
namespace Drupal\Core\Plugin;

use Drupal\Component\Plugin\PluginBase as ComponentPluginBase;
use Drupal\Core\DependencyInjection\AutowiredInstanceTrait;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Base class for plugins supporting metadata inspection and translation.
@@ -13,8 +15,21 @@
 * @ingroup plugin_api
 */
abstract class PluginBase extends ComponentPluginBase {

  use AutowiredInstanceTrait;
  use StringTranslationTrait;
  use DependencySerializationTrait;
  use MessengerTrait;

  /**
   * Instantiates a new instance of the implementing class using autowiring.
   *
   * @see \Drupal\Core\Plugin\ContainerFactoryPluginInterface
   *
   * @return static
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return static::createInstanceAutowired($container, $configuration, $plugin_id, $plugin_definition);
  }

}
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ services:
    arguments: ['@cache.bootstrap', '@lock', '@entity_type.manager']
    tags:
      - { name: needs_destruction }
  Drupal\block_content\BlockContentUuidLookup: '@block_content.uuid_lookup'
  block_content.bc_subscriber:
    class: Drupal\block_content\Routing\RouteSubscriber
    arguments: ['@entity_type.manager', '@module_handler']
Loading