Problem/Motivation

In the WebformHandlerBase class and all subclasses, the initialization of the instance properties is happening.

The purpose of ContainerInjectionInterface::create() (or similar methods like ContainerFactoryPluginInterface::create()) is passing the injected dependencies to the class constructor, non initializing the instance properties.

Steps to reproduce

See: WebformHandlerBase, EmailWebformHandler, Example Handler

Proposed resolution

Rewrite all affected places.
First, replace:

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);

    $instance->loggerFactory = $container->get('logger.factory');
    $instance->configFactory = $container->get('config.factory');
    $instance->renderer = $container->get('renderer');
    $instance->entityTypeManager = $container->get('entity_type.manager');
    $instance->conditionsValidator = $container->get('webform_submission.conditions_validator');
    $instance->tokenManager = $container->get('webform.token_manager');

    $instance->setConfiguration($configuration);

    return $instance;
  }

with

    public function __construct(array $configuration, $plugin_id, $plugin_definition, 
              LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config, 
              RendererInterface $renderer, EntityTypeManagerInterface $entity_type_manager, 
              WebformSubmissionConditionsValidator $webform_submission_conditions_validator, 
              WebformTokenManagerInterface $webform_token_manager) {

    $this->configFactory = $config;
    parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition);
    
    $this->loggerFactory = $logger_factory;
    $this->renderer = $renderer;
    $this->entityTypeManager = $entity_type_manager;
    $this->conditionsValidator = $webform_submission_conditions_validator;
    $this->tokenManager = $webform_token_manager);
    
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
     return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.factory'),
      $container->get('config.factory'),
      $container->get('renderer'),
      $container->get('entity_type.manager'),
      $container->get('webform_submission.conditions_validator'),
      $container->get('webform.token_manager')
    );
  }

For example for EmailWebformHandler replace this

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->currentUser = $container->get('current_user');
    $instance->moduleHandler = $container->get('module_handler');
    $instance->languageManager = $container->get('language_manager');
    $instance->mailManager = $container->get('plugin.manager.mail');
    $instance->themeManager = $container->get('webform.theme_manager');
    $instance->tokenManager = $container->get('webform.token_manager');
    $instance->elementManager = $container->get('plugin.manager.webform.element');
    return $instance;
  }

with

    public function __construct(array $configuration, $plugin_id, $plugin_definition, 
              ....arguments here....) {

   // construct body here.
    
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
     return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('current_user'),
      $container->get('module_handler'),
      $container->get('language_manager'),
      $container->get('plugin.manager.mail'),
      $container->get('webform.theme_manager'),
      $container->get('webform.token_manager'),
      $container->get('plugin.manager.webform.element')
    );
  }

Remaining tasks

  • Do refactoring and create patch

And thanks to @apaderno for pointing to this issue. See here: https://www.drupal.org/project/projectapplications/issues/3261372#commen...

Comments

le72 created an issue. See original summary.

le72’s picture

Issue summary: View changes
juancec’s picture

Status: Needs work » Needs review
StatusFileSize
new12.09 KB

Hi, I worked on WebformHandlerBase, EmailWebformHandler and ExampleWebformHandler files in 6.x-dev.
I'm providing a patch, please review it. I hope this patch works =)

jrockowitz’s picture

Status: Needs review » Closed (won't fix)

This "unconventional" but documented approach to dependency injection allows handlers to be extended while allowing the parent class to add dependencies without breaking anything.

@see https://www.jrockowitz.com/blog/webform-road-to-drupal-9