It would be nice if there was a way to alter/override token values.
For example, Ubercart defines an [order_id] token, and sets the value to whatever the order_id is. But I want to replace the value of this token with a prefixed order_id, so anything including the [order_id] token would show the prefixed order_id.
As it stands now you can't just do your own implementation of hook_token_values and set your own value. The $values arrays returned from the hook_token_values functions are merged using array_merge_recursive, so instead of the newer value overwriting the old, you end up with an array containing both values. Because token just does a str_replace with the $tokens and $values arrays, when the token replacement is done you end up with "[order_id]" being replaced with "Array", which is really not helpful.
One idea is to create a "token_prepare_values" function and in the _token_replace_tokens function run the $values array through that before doing the str_replace. The token_prepare_values function would run through the values array and for any value that is an array it would replace that value with the last element in the array.
The function might look something like this:
function token_prepare_values(&$values) {
for ($i = 0; $i < count($values); $i++) {
if (is_array($values[$i])) {
$values[$i] = end($values[$i]);
}
}
return $values;
}
And the altered _token_replace_tokens function would look like this:
function _token_replace_tokens($original, $tokens, $values, $leading, $trailing) {
$tokens = token_prepare_tokens($tokens, $leading, $trailing);
$values = token_prepare_values($values);
return str_replace($tokens, $values, $original);
}
If this can't be done for some reason, maybe there could be a hook_token_value_alter() or something like that, but this seems like a pretty simple way to make it work.
Thanks. :)
Comment | File | Size | Author |
---|---|---|---|
#28 | 731518-token-hook-group-D7.patch | 911 bytes | Dave Reid |
#14 | 731518-hook-tokens-alter-D7.patch | 5.34 KB | Dave Reid |
#9 | 731518-token-alter.patch | 2.65 KB | Damien Tournoud |
Comments
Comment #1
Dave ReidI'm not sure if this would be possible. Token is already in core and feature locked without any kind of alter hook, so I don't think it would make much sense to add that feature here, just to have it removed in Drupal 7. :/
Maybe just leave this postponed for now?
Comment #2
adamo CreditAttribution: adamo commentedOK. Would be a nice feature to have. ;)
Comment #3
TonyK CreditAttribution: TonyK commented+1 to hook_token_value_alter(). This would be a great feature. Why would inclusion of this module into the core of the next Drupal version affect 6.x version of contributed module? IMO the decision to move several modules to the core is rather questionable because it obviously suppresses Drupal development. :(
Comment #4
Dave ReidBecause if we added a new api in the module for D6 but it's not supported in D7, it wouldn't make sense to do since we'd lose functionality.
Comment #5
Damien Tournoud CreditAttribution: Damien Tournoud commentedThis is brain-dead. We definitely need an alter hook here.
Comment #6
Dave ReidThis is possible in D7. Just ensure your module runs after (module weights)? Or do we need an explicit alter hook?
Comment #7
Damien Tournoud CreditAttribution: Damien Tournoud commentedNo, this not possible neither on D6 nor on D7. For the same reason: if two implementations return the same key, we end-up with an array (see #791860: array_merge_recursive() is never what we want in Drupal: add a drupal_array_merge_recursive() function instead.).
Comment #8
Dave ReidI just committed a patch to token module to prevent this in D6 so yes, it is very possible: #587148: Handle tokens correctly when more than one module defines a given token. I do see we have a problem in D7 though and it should be a proper alter hook.
Comment #9
Damien Tournoud CreditAttribution: Damien Tournoud commentedSomething like this?
This is an untested patch.
Comment #10
Dave ReidWill review this week, although looking good.
Comment #11
ohnobinki CreditAttribution: ohnobinki commented.
Comment #12
Dave ReidI like it, although the docs between hook_tokens and hook_tokens_alter should probably add @see lines to each other.
Comment #13
Dave ReidAssigning myself to re-roll tomorrow.
Comment #14
Dave ReidRe-rolled with additional linking @see comments and small move in system.api.php to keep all the token api functions together.
Comment #15
Dave ReidAdding tag...
Comment #16
Dave ReidDamZ? Look good?
Comment #17
Damien Tournoud CreditAttribution: Damien Tournoud commentedYep, looks really good to me.
Comment #18
Dave ReidAnother reasoning for this patch will easily allow any tokens to be translated via a i18n_tokens_alter(). Currenly the token_replace() function only allows one $options['callback'] function, so if tokens that want to translate pathauto tokens do not get a chance since pathauto claims the callback function.
Comment #19
Dries CreditAttribution: Dries commentedI think this waits for Drupal 8.
Comment #20
Dave ReidFair enough, I'd like to make a case for this to go into 7.1 since there is no way for this to happen in contrib. I will bump this down to needs review for now.
Comment #21
Dave ReidAdding tags...
Comment #22
Damien Tournoud CreditAttribution: Damien Tournoud commentedThis is a major regression from D6, and a very minor API addition.
Please reconsider.
Comment #23
Dave ReidI would point out that it's actually not a regression. We don't have an hook_token_values_alter() in the Token module/API for D6 at all...
Comment #24
Damien Tournoud CreditAttribution: Damien Tournoud commentedTrue, but in recent version it's at least possible for a higher-weight module to modify the tokens exposed by lower-weight modules... and that turned out to be *pretty useful* in a few recent projects of mine.
Comment #25
Dave ReidGah, I just came across a couple use cases in contrib for this. For example, we provide a [current-page:title] token in Token.module. The Page Titles module should be able to alter that token rather than having to provide its own.
Comment #26
Dries CreditAttribution: Dries commentedWell, I decided to commit this. It is a minor change and had been RTBC for a long time. And I trust Dave's judgment that it is important for contrib.
Comment #27
Dave ReidI had just noticed this yesterday but I forgot to include hook_tokens_alter() in system_hook_info() so that the hooks can be included in modulename.tokens.inc just like the rest of the token functions.
Comment #28
Dave ReidComment #29
Dave ReidComment #30
moshe weitzman CreditAttribution: moshe weitzman commentedmakes sense
Comment #31
webchickCommitted to HEAD, minus the coding standards changes. If we want to do that (I'd argue that we don't) it can be a separate follow-up issue that changes it both here and in the API docs for consistency.
Comment #32
Dave ReidSounds good Angie, leaving the coding style is fine with me.
Comment #33
jhedstromNow that this has been fixed in 7, any chance of a back-port to the 6.x token module?
Comment #35
TonyK CreditAttribution: TonyK commentedJust a note: Drupal 6 backport is discussed here: #1157058: Add hook_token_values_alter() to allow altering of tokens.