Score:1

Class arguments not being passed

cn flag

Updating the emulsify_twig extension for D10, for some reason the class arguments aren't being passed... I'm extending Drupal\Core\Template\TwigExtension and using the same default arguments but for some reason it isn't picking up the arguments, resulting in: ArgumentCountError: Too few arguments to function Drupal\emulsify_twig\BemTwigExtension::__construct(), 0

This is the relevant code from the class:

use Drupal\Core\Template\TwigExtension;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;

class BemTwigExtension extends TwigExtension {
  protected $urlGenerator;  
  protected $renderer;  
  protected $themeManager;  
  protected $dateFormatter;  
  protected $fileUrlGenerator;

  public function __construct(RendererInterface $renderer, UrlGeneratorInterface $url_generator, ThemeManagerInterface $theme_manager, DateFormatterInterface $date_formatter, FileUrlGeneratorInterface $file_url_generator = NULL) {
    parent::__construct(
      $renderer,
      $url_generator,
      $theme_manager,
      $date_formatter,
      $file_url_generator
    );
    
    $this->renderer = $renderer;
    $this->urlGenerator = $url_generator;
    $this->themeManager = $theme_manager;
    $this->dateFormatter = $date_formatter;
    $this->fileUrlGenerator = $file_url_generator;
  }

Any insight as to why the arguments aren't being passed would be appreciated!

id flag
We would have to see the code that is instantiating the object. Is this a a service? Can we see the service definition please?
Score:4
de flag

The error message states that no arguments are being passed to the Twig filter extension. Drupal Twig filter extensions must be defined in [MODULE].services.yml, and in that service definition, the services to be injected as dependencies are defined. These are the arguments that BemTwigExtension::__construct is expecting, but not finding.

You could do something like the followingin emulsify_twig.services.yml:

services:
  emulsify_twig.bem_twig_extension:
    class: Drupal\emulsify_twig\TwigExtension\BemTwigExtension
    tags:
      - { name: twig.extension }
    arguments:
      - '@renderer'
      - '@url_generator'
      ...

Entering all the dependencies using their service definition names.

However, in the original post, as __construct is passing the arguments to the parent, the parent service definition can be referenced to determine which arguments it expects. In the original ploblem TwigExtension is being extended, and the TwigExtension API page lists one service as using it: twig.extension. Viewing the source on twig.extension API page shows the services expected by the parent class (the arguments):

class: Drupal\Core\Template\TwigExtension
arguments:
  - '@renderer'
  - '@url_generator'
  - '@theme.manager'
  - '@date.formatter'
  - '@file_url_generator'
tags:
  - { name: twig.extension, priority: 100 }

Then, instead of redefining all these arguments in the extended service definition, the parent can be set, using its arguments and tags as a base. So, back to emulsify_twig.services.yml the service would be defined as follows:

services:
  emulsify_twig.bem_twig_extension:
    class: Drupal\emulsify_twig\TwigExtension\BemTwigExtension
    parent: twig.extension
    arguments:
      - '@additional_class.1'
      ...

Where @additional_class.1 is the name of any additional services that the extended class will use, that the parent does not. Note that if the extended class does not require any additional services, the __construct() method does not need to be implemented in the extended class at all, as the parent implementation will be used when not defined in the child class. However, the service will still need to be defined in emulsify_twig.services.yml with the parent set as twig.extension.

adam_bear avatar
cn flag
Setting the `parent` key in services was the missing piece... and removing the constructor cuts the amount of code in half - thanks!
Jaypan avatar
de flag
You also don't need to declare the protected properties, as the parent defines them as well.
adam_bear avatar
cn flag
Yep- the only lines I kept were the class declaration & use TwigExtension, then added parent in services... thanks again!
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.