Problem/Motivation
Drupal 11.5 deprecates drupal_static() and drupal_static_reset() (removed in 13.0.0, see the change record). Token still keeps three caches in drupal_static(), so every project that tests against Drupal 12 with Token installed gets these deprecations:
token_menu_link_load_all_parents(),token.moduleline 279token_taxonomy_term_load_all_parents(),token.moduleline 339token_book_load_all_parents(),token.moduleline 408
Two more calls reset them: token_clear_cache() (token.module lines 105-106) and TokenEntityHooks::menuLinkContentPresave() (line 101).
The messages look like this:
Calling drupal_static() with "token_menu_link_load_all_parents" as argument is deprecated in drupal:11.5.0 and is removed from drupal:13.0.0. Use \Drupal::cache('memory')->set() and \Drupal::cache('memory')->get() instead.A dependent module cannot work around this. In 11.5, drupal_static() still keeps its values in a PHP static array, so \Drupal::cache('memory')->delete() does not clear Token's caches. A module that needs to reset one of them in a test has no choice but to call the deprecated drupal_static_reset() itself.
Two problems in the same code, found while reading it:
token_clear_cache()resets'token_book_link_load', but no function has that name. The book cache belongs totoken_book_load_all_parents(), so that reset clears nothing.- Nothing ever resets
token_taxonomy_term_load_all_parents(). Menu links get a reset on presave, but terms do not. If a parent term is renamed in a request that has already read its children's parent names,[term:parents]still returns the old name for the rest of that request.
Proposed resolution
Move the three caches to the memory cache bin: get()/set() in the loaders, delete() in the resets. Use each function's name as the cache ID, so the existing names keep their meaning.
Token supports ^10.3 || ^11 || ^12, and the cache.memory service does not exist on Drupal 10 (it is not in 10.6's core.services.yml). So keep drupal_static() below 11.5 and use the memory cache from 11.5 on, for example with DeprecationHelper::backwardsCompatibleCall() in one small helper per operation, rather than repeating the version check at each call site.
While there:
- Make
token_clear_cache()reset the book cache under its real name. - Reset the term parents cache when a taxonomy term is saved, the same way menu link content is handled.
Remaining tasks
- Write the patch or MR.
- Add a test that a term rename is reflected in
[term:parents]within the same request.
Found while raising Domain Path to PHPStan level 5 (#3620533), whose Drupal 12 lane now ignores these deprecations until Token is fixed.
AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code and test on the merge request. I reviewed and ran the work myself before posting it.)
Issue fork token-3627991
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
Comment #3
mably commentedComment #4
mably commentedComment #5
mably commentedThe red pipeline comes from
phpunit (next major), which fails on existing Drupal 12 problems outside this MR:TokenFieldUiTest,EntityTestandCommentTestdo not enablefilter, whichtextneeds from Drupal 12 on, andTreeTest::testUserTokensgets an emptyX-Drupal-Dynamic-Cacheheader on Drupal 12. They had not shown up before because the last 8.x-1.x run of that job stopped before any test ran. The classes this MR touches pass on Drupal 10, 11 and 12, and nodrupal_static()deprecation is left.AI-Generated: Yes (Claude Code was used to help draft this comment. I reviewed it before posting.)
Comment #6
berdirYes, the D12 fails are because of changes in core, should be fixed in a separate issue. was too optimistic/early about the compatibility.
All of those functions need to go as .module files are deprecated for D13, instead of new functions that we have to remove again later, a service should be used or possibly put them directly on hook classes, but the invalidation calls across services/hooks might be bit awkward, so separate utility service is possibly better.
I'd put the version on 11.3, because that's when the memory service was added, then the new code path can be used earlier.
the book integration is already conditional per #3588324: Remove book tests and only define book tokens if there is no book_token_info(), so no need to convert, just mark it as deprecated.
Comment #7
mably commentedThanks @berdir, done in the latest commit:
token.parents_loaderservice, used directly by the hook classes. It keeps the titles in its own properties, which last for the request likedrupal_static()did, so no memory cache and no version check are needed: one code path from 10.3 to 12.token_menu_link_load_all_parents()andtoken_taxonomy_term_load_all_parents()are now deprecated wrappers around the service.token_book_load_all_parents()is only marked deprecated, as you suggested.I left the D12 failures for a separate issue.
AI-Generated: Yes (Claude Code was used to write the code and to draft this comment. I reviewed both.)
Comment #8
berdirComment #10
berdirMerged.