Add a Autowire trait for plugins

Created on 6 June 2024, 6 months ago

Problem/Motivation

We already have a \Drupal\Core\DependencyInjection\AutowireTrait class, suitable for wiring dependencies into classes extending \Drupal\Core\DependencyInjection\ContainerInjectionInterface, implemented in šŸ“Œ Allow controller service wiring via constructor parameter attributes Fixed

I think we should have a similar thing for \Drupal\Core\Plugin\ContainerFactoryPluginInterface, so we can easily skip adding a create() method for plugins.

I acknowledge we also have something similar šŸ“Œ Allow plugin service wiring via constructor parameter attributes Needs work , but this is useful in the short term for improving DX, before removing the requirement for ContainerFactoryPluginInterface. I guess the proposed new autowire trait would be removed from drupal alongside ContainerFactoryPluginInterface, if ever that happens. So I dont see this as redundant code.

Proposed resolution

Add a AutowireTrait for plugins, so they dont need to implement create().

Remaining tasks

  • Tests.
  • Should we switch any non-tests core usages now? My suggestion is not, because I imagine there will be a huge LOC change here (many LOC removals, for the better!). But create methods could also be doing other things, or not all dependencies autowirable yet.

User interface changes

Nil.

API changes

New trait

Data model changes

Nil

Release notes snippet

āœØ Feature request
Status

Active

Version

11.0 šŸ”„

Component
BaseĀ  ā†’

Last updated 38 minutes ago

Created by

šŸ‡¦šŸ‡ŗAustralia dpi Perth, Australia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @dpi
  • šŸ‡¦šŸ‡ŗAustralia dpi Perth, Australia
  • Merge request !8306Add an Autowire trait for plugins ā†’ (Open) created by dpi
  • Pipeline finished with Success
    6 months ago
    Total: 812s
    #192309
  • Issue was unassigned.
  • šŸ‡¦šŸ‡ŗAustralia dpi Perth, Australia

    Drive by code drop. Not working on this for now.

  • šŸ‡©šŸ‡°Denmark arnested

    Nice. I was looking for exactly this today!

    I have tested the code together with Drupal 10.3 and can confirm it works.

    Since I wanted to have the benefit of this right away, I took the liberty and made it a small module: https://www.drupal.org/project/autowire_plugin_trait ā†’

  • šŸ‡³šŸ‡æNew Zealand quietone
  • šŸ‡®šŸ‡¹Italy mondrake šŸ‡®šŸ‡¹

    Also see āœØ Add a trait for autowiring properties in tests Needs work .

    There Iā€™m suggesting to add symfony/expression-language as a dependency.

    That would nicely allow using expressions and enable autowiring of constructs like

    #[AutowireProperty(expression: "service('entity_type.manager').getStorage('node')")]

  • Status changed to Needs review 3 months ago
  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Can we just extend the existing AutowireTrait to work here?

      public static function create(ContainerInterface $container) {
        $args = [];
    

    becomes

      public static function create(ContainerInterface $container, ...$args) {
    

    ie. additional arguments passed to create() become the initial set of arguments?

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    No, #8 doesn't work because ContainerFactoryPluginInterface::create() doesn't match.

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Added AutowirePluginTrait to PluginBase to enable autowiring by default (simply omit the create() method) and autowired some Views plugins to test that it all works.

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Does this even need to be a trait? Should it just be included directly in PluginBase?

    Not sure we need explicit tests, given we are exercising it in Views tests now, so removing the tag.

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Adding the trait to \Drupal\Core\Plugin\PluginBase (not Component) seems to work, I autowired the BlockContentBlock plugin to prove it.

  • Pipeline finished with Failed
    3 months ago
    Total: 128s
    #261694
  • Pipeline finished with Failed
    3 months ago
    Total: 437s
    #261698
  • Pipeline finished with Success
    3 months ago
    Total: 7407s
    #261719
  • šŸ‡ŗšŸ‡øUnited States smustgrave

    Shouldn't there be a test coverage for the new exception being thrown?

     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));
    
  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Added coverage for success and failure of autowiring a block plugin.

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    In fact let's do the refactor in #14 now to avoid copy-pasting the code here.

  • šŸ‡¦šŸ‡ŗAustralia mstrelan

    Regarding the phpstan baseline, it turns out that phpstan will accept @return annotations, and we already have that in ContainerFactoryPluginInterface, but PluginBase does not yet implement that interface. Have pushed a commit to implement that interface and update the baseline.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 709s
    #308740
  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Unfortunately implementing ContainerFactoryPluginInterface in PluginBase breaks a bunch of tests, I don't think Migrate plugins can cope with this as they have a slightly different constructor.

  • Pipeline finished with Success
    about 2 months ago
    #309218
  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    Rebased.

Production build 0.71.5 2024