I recently had to work with entity tokens when i worked with Profile2 module which is based on entities / entity_tokens. After I added a field to my profile entity type and went to the webform component form where i wanted to select the token for this fresh added field it doesn't get listed there. After a global cache clear it does.

This can be fixed by adding a cache clear on hook_field_update_field / hook_field_delete_field . I already wrote a patch for that, please review:

Comments

miro_dietiker’s picture

Sounds right, confirming the issue and the solution to work.
However, why now only clearing the entity_token cache?

I think that's much more atomic and clean.

miro_dietiker’s picture

Status: Active » Needs work
s_leu’s picture

StatusFileSize
new941 bytes

corrected, flush now only on token cache. pls review:

miro_dietiker’s picture

Status: Needs work » Reviewed & tested by the community

Perfect, thank you.
Switching to reviewed to push to maintainer.

fago’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

cache_token? From where stems this cache table? That's not in core.

If it is the token module's table, then probably the token module should care about clearing its cache itself.

miro_dietiker’s picture

Status: Postponed (maintainer needs more info) » Needs review

fago, isn't the entity token module providing the tokens for (fieldable) entities?
So it's up to the entity_token module to make the caches' content consistent.

Who else populates the values to that cache?

fago’s picture

>Who else populates the values to that cache?
That's the question, whose cache is it? ;) entity-tokens just implements the token API from core to provide tokens. But I'm not aware of any caching there.

s_leu’s picture

StatusFileSize
new1.17 KB

It's the token module/API cache. see the install file or this function within token.module. By the way a dependency to the token module is missing.

function token_clear_cache() {
  cache_clear_all('*', 'cache_token', TRUE);
  drupal_static_reset('token_get_info');
  drupal_static_reset('token_get_global_token_types');
  drupal_static_reset('token_build_tree');
  drupal_static_reset('_token_profile_fields');
}

a new patch is attached:

fago’s picture

Project: Entity API » Token
Component: Entity tokens » Code
Status: Needs review » Needs work

>By the way a dependency to the token module is missing.
Nothing from the module depends on the token module, so no - it is not missing.

Well, as it is the token module's cache I think it should deal itself about clearing it. Entity tokens just implements the core token API, which does not have any caches and so does not force any cache clears. However, I fail to see how the token caching strategy is supposed to work? From where does it know when new tokens appear and should clear its cache?

miro_dietiker’s picture

Actually it doesn't know. It's the job of the hook implementors to notify the token module that a token info rebuild is needed.
That's why you need to clear the cache in any case the set of tokens you provide might change.

fago, if you look at the node module: it implements the hook_menu and adds a callback per content type to add new content.
If a user adds a new content type, the menu cache is also getting cleared by the node module. In this case, the menu system offers an api menu_rebuild();
As of my understanding this is one of the caveats we need to deal with, by using the hook system with caching.

http://drupalcode.org/project/drupal.git/blob_plain/refs/heads/7.x:/modu...

function node_menu() {
...
  node_type_cache_reset();
  foreach (node_type_get_types() as $type) {
    $type_url_str = str_replace('_', '-', $type->type);
    $items['node/add/' . $type_url_str] = array(
      'title' => $type->name,
      'title callback' => 'check_plain',
      'page callback' => 'node_add',
      'page arguments' => array($type->type),
      'access callback' => 'node_access',
      'access arguments' => array('create', $type->type),
      'description' => $type->description,
      'file' => 'node.pages.inc',
    );
  }
...
function node_type_form_submit($form, &$form_state) {
...
  node_types_rebuild();
  menu_rebuild();

Now, core provides token APIs. However the core token module doesn't introduce a cache.
The contrib token module, providing the UI, introduces the cache.
Its API function to clear the cache is as s_leu referred: token_clear_cache();
Without calling it, new tokens will not show up.

Actually, the token contrib module has a very hard limitation for dynamic tokens.
In webform we have the same issue, where context specific tokens (every webform offers one token per form component) whereas the contrib token module doesn't support real token context.
While the missing context would be a real feature request, we still should find a solution to provide up-to-date tokens for entity tokens.

Token (UI) cannot know that entity_token implements a token per field. Thus it cannot clear the cache itself.

We possibly end up with the need of explicit token contrib module support by the entity_token module as initially suggested. Without dependency, this is:

function entity_token_field_update_field($field) {
  if (module_exists('token')) {
    token_clear_cache();
  }
}
didel_fr’s picture

Hi everybody

I'm a rooky!

I want to use token create by entity in my webform!

I tried to apply the patch but it doesn't work!
The message of putty is:

[root@ns16 entity]# patch -p1 < add_flush_caches_v1.2.patch
patching file entity_token.info
Hunk #1 FAILED at 4.
1 out of 1 hunk FAILED -- saving rejects to file entity_token.info.rej
patching file entity_token.module

If somebody can explain to me the right way to apply this patch, that was great.

Thanks by advance.

fago’s picture

Title: Add cache clear on field update and field delete » Caching requires modules to implement token.module API
Priority: Normal » Critical

>It's the job of the hook implementors to notify the token module that a token info rebuild is needed.
Entity tokens integrates with core, not the token module.

@token:
I don't think it is good idea to extend the core API in a way people *have to* deal with token module specialities, like clearing the cache.
I think token.module could minimize the effects in clearing the token cache at least on every entity info cache and field info cache clears, what would fix this issue too. Still token.module cannot reliable detect new tokens, so it 'd remain problematic.

dave reid’s picture

Title: Caching requires modules to implement token.module API » Add cache clear on field update and field delete
Priority: Critical » Normal

Don't abuse the critical priority status.

fago’s picture

Well, I just wanted to highlight an imo important issue. But as you wish...
I've created #1211608: Caching requires modules to implement token.module API for the general issue.

dave reid’s picture

Assigned: Unassigned » dave reid
Category: bug » feature

Yes but you still know better than to abuse the critical priority status. This caching *should* have been built into core as token_info() is a moderately expensive hook that can be called quite often. We absolutely had to add caching in order to make building the token trees work at all. We definitely should add some token cache clearing in token.module when fields are changed. It was going to happen anyway with proper Field tokens.

dave reid’s picture

Patch in #3 needs to be re-rolled to use the proper cache clear function, and use hook_create/update/delete_field_instance() and not the field-level hooks. Also don't worry about adding a big long comment in the function's docblock - it's unnecessary.

s_leu’s picture

Project: Token » Entity API
Component: Code » Entity tokens
Assigned: dave reid » Unassigned

It seems we cannot solve this issue on token project level (as long as we state a cache is needed)..
The issue finally addresses token.module core limitation, which is subject to change only long term.
So we need a short term solution anyways.

Fago,
Are you willing to add the token project cache clear solution as suggested in #16 after this discussion?
We'll provide you a patch then.

How can we find a solution that fits all needs?

fago’s picture

Project: Entity API » Token
Component: Entity tokens » Code

Dave Reid has already outlined how to fix in token.module for now, so let's follow that.

miro_dietiker’s picture

So you want to add the cache clearing to token ui module?

Dave Reid, can you please clarify for me... You're willing to add cache clears in token project on the field_x_instance hooks?
At least it will work this way...

dave reid’s picture

That's what I said in #16.

dave reid’s picture

Status: Needs work » Needs review
StatusFileSize
new1.06 KB
dave reid’s picture

Status: Needs review » Fixed
miro_dietiker’s picture

Thank you dave for fixing this! :-)

Status: Fixed » Closed (fixed)

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