Call to non-existent token.entity_mapper service when Token is not installed

Created on 24 April 2024, 7 months ago
Updated 13 May 2024, 6 months ago

Problem/Motivation

After installing scheduler on a site without the token contributed module, trying to create a new node fails and generates the server error:

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "token.entity_mapper". in Drupal\Component\DependencyInjection\Container->get() (line 157 of SITEROOT/web/core/lib/Drupal/Component/DependencyInjection/Container.php).

Steps to reproduce

Install Drupal 10; I use drush :

  • composer create-project drupal/recommended-project:^10 SITEROOT
  • composer require drush/drush
  • ./vendor/bin/drush site:install etc etc

Then add scheduler but no other modules

  • composer require scheduler:^2.0
  • drush pm-install scheduler

Then, log in and visit /node/add/article

Proposed resolution

The issue seems to be due to scheduler assuming that hook_tokens is only invoked by the contributed "token" module, given the comments in _scheduler_token_types() as implemented in scheduler.tokens.inc:

  // This function should only get executed if the Token module is enabled,
  // therefore we can assume the token.entity_mapper service exists without
  // having to check for it.

That function is in turn called from scheduler_tokens() which is an implementation of hook_tokens().

However, the call trace shows that this hook is being invoked on a site even without the Token module, via

  • SITEROOT/web/core/lib/Drupal/Core/Utility/Token.php line 364

Checking that Token.php provided by core, it is indeed invoking hook_tokens():

$replacements = $this->moduleHandler->invokeAll('tokens', [$type, $tokens, $data, $options, $bubbleable_metadata]);

One approach would be to stop making the assumption in the comment from _scheduler_token_types() and check to see if the Token module is enable before using the token.entity_mapper service, but I've not followed through the possible implications of that change.

🐛 Bug report
Status

Fixed

Version

2.0

Component

Code

Created by

🇬🇧United Kingdom alt36

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

Merge Requests

Comments & Activities

  • Issue created by @alt36
  • 🇩🇪Germany sense-design Münster

    Issue confirmed, same here for me.

  • First commit to issue fork.
  • 🇬🇧United Kingdom jonathan1055

    Thanks for raising this issue and giving the details. It is a problem and I'll work on the fix right now.

  • Merge request !135#3443183 Token entity mapper may not exist → (Merged) created by jonathan1055
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • 🇬🇧United Kingdom jonathan1055

    Test fail on drupal.org simply because I am writing out debug. They pass on gitlab.

  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    224 pass, 2 fail
  • Status changed to Needs review 7 months ago
  • 🇬🇧United Kingdom jonathan1055

    The module is loaded due to it being required by commerce_product, so testing the token module is going to take a bit more work. The commerce_product module is enabled at the start, and then test products are created, so uninstalling the module (a pre-requisite to uninstalling token) is difficult to do within the executing test.

    I have tested the change to _scheduler_token_types() locally when the token module is not installed, and it works. If others can test and confirm this change, I may commit that fix and release Scheduler 2.0.3, then work on the test coverage later.

  • Status changed to RTBC 7 months ago
  • 🇩🇪Germany sense-design Münster

    Patch works for me in project.

  • 🇬🇧United Kingdom alt36

    The MR works for me - specifically I've checked with commit bd16830, which I can see now checks if the token.entity_mapper service is available. Thanks!

  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    230 pass
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    230 pass
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    230 pass
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    230 pass
  • 🇬🇧United Kingdom jonathan1055

    Thank you both for confirming the fix. I have also now added test coverage, checking that the url to add a node, media item or taxonomy term still works and give 200 when the token module is uninstalled. Without the fixed code (using the new "test-only changes" phpunit job, which incidentally I worked on adding into gitlab templates) we only get a failure for media/add/{media_type}, there is no failure for node/add/{nodetype} or admin/structure/taxonomy/manage/{vocab}/add. Same thing happens when I run the phpunit tests locally. The hook_token_info() is not called for nodes and taxonomy terms in the test environment, I guess it must be something to do with which input filters are active in the tests? or something else, any ideas?

    At least the test does fail for 'media' so we have proof that we are now covering that part of the functionality with the extra test.

  • Pipeline finished with Skipped
    7 months ago
    #158958
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    230 pass
  • Status changed to Fixed 7 months ago
  • 🇬🇧United Kingdom jonathan1055

    Merged and fixed.

  • 🇬🇧United Kingdom jonathan1055

    I have now released Scheduler 2.0.3

  • 🇬🇧United Kingdom jonathan1055

    I have done some more investigation. The content type does not need to be enabled for Scheduling to get the original error. It is caused when hook_tokens is invoked, as shown in the backtrace

    Drupal::service('token.entity_mapper') (Line: 30)
    _scheduler_token_types() (Line: 71)
    scheduler_tokens('date', Array, Array, Array, Object)
    call_user_func_array(Object, Array) (Line: 409)
    Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}(Object, 'scheduler') (Line: 388)
    Drupal\Core\Extension\ModuleHandler->invokeAllWith('tokens', Object) (Line: 416)
    Drupal\Core\Extension\ModuleHandler->invokeAll('tokens', Array) (Line: 364)
    Drupal\Core\Utility\Token->generate('date', Array, Array, Array, Object) (Line: 241)
    Drupal\Core\Utility\Token->doReplace(1, '[date:custom:Y]-[date:custom:m]', Array, Array, Object) (Line: 191)
    Drupal\Core\Utility\Token->replace('[date:custom:Y]-[date:custom:m]', Array) (Line: 318)
    Drupal\file\Plugin\Field\FieldType\FileItem::doGetUploadLocation(Array, Array) (Line: 296)
    Drupal\file\Plugin\Field\FieldType\FileItem->getUploadLocation() (Line: 236)
    ...
    

    This is done when the entity has a file upload field defined, because the upload directory location uses the year and month template, defined with [ ] for formatting the date. If the entity does not have a file upload field then there it no call to ->invokeAll('tokens') and no error. That's why the phpunit tests for node and taxonomy term did not fail. Addind a node fails in my UI because it an image field attached. Taxonomy term does not fail in the UI because there is no file upload.

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024