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.

Issue fork scheduler-3443183

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

alt36 created an issue. See original summary.

sense-design’s picture

Issue confirmed, same here for me.

jonathan1055 made their first commit to this issue’s fork.

jonathan1055’s picture

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

jonathan1055’s picture

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

jonathan1055’s picture

Status: Active » Needs review

The token module is loaded due to it being required by commerce_product, so testing without 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.

sense-design’s picture

Status: Needs review » Reviewed & tested by the community

Patch works for me in project.

alt36’s picture

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!

jonathan1055’s picture

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. We can verify the extended test coverage using the new "test-only changes" phpunit job (which incidentally I worked on adding into gitlab templates). This runs phpunit after reverting all non-test changes. So the test should fail, which shows that the changed code is now covered by a test.

Oddly 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.

  • jonathan1055 committed b3b4ab7e on 2.x
    Issue #3443183 by jonathan1055, alt36, sense-design: Call to non-...
jonathan1055’s picture

Status: Reviewed & tested by the community » Fixed

Merged and fixed.

jonathan1055’s picture

I have now released Scheduler 2.0.3

jonathan1055’s picture

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.

  • jonathan1055 committed ba93361d on 2.x
    Issue #3443183 by jonathan1055: Tidy up new token test and improve...

Status: Fixed » Closed (fixed)

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