When I use a custom token for taxonomy 'needs term' I get the following errors from pathauto:
Warning: Illegal offset type in isset or empty in pathauto_cleanstring() (line 180 of /var/www/wet/profiles/wetkit/modules/contrib/pathauto/pathauto.inc).
Warning: html_entity_decode() expects parameter 1 to be string, array given in decode_entities() (line 429 of /var/www/wet/includes/unicode.inc).
Warning: Illegal offset type in pathauto_cleanstring() (line 223 of /var/www/wet/profiles/wetkit/modules/contrib/pathauto/pathauto.inc).
I have been able to recreate this issue with a minimal set of modules and the following test case:
1. Define a custom token simply called "Testing" of type 'term' which prints the text 'testing'.
2. Create a test vocabulary with one term
3. In pathauto define a pattern for the vocabulary which is [term:testing]/[term:name]
4. Now edit your term and the error message should appear
To recreate the error messages programatically, you can run the following in devel/php:
$op = 'return';
module_load_include('inc', 'pathauto');
$term = taxonomy_term_load(1);
$uri['path'] = 'taxonomy/term/1';
$pathalias = pathauto_create_alias('taxonomy_term', $op, $uri['path'], array('taxonomy_term' => $term), $term->vocabulary_machine_name, 'en');
One thing I noticed is that hook_tokens in token_custom gets run twice, once with $options['recursive'] = TRUE and another time without. If I add the following to token_custom.module the error goes away and everything still seems to work:
175 if (isset($options['recursive'])) {
176 return $return;
177 }
I don't think this is the real fix, but I thought it may help debug the issue further.
Comments
Comment #1
joel_osc CreditAttribution: joel_osc commentedFixed title.
Comment #2
gaspaio CreditAttribution: gaspaio commentedThis seems to me a Token module issue causing the custom token to be resolved twice, its value becoming an array in the process and causing the errors.
I opened an issue in the Token issue queue (#1792728: token_tokens() returns token replacements managed by other modules) for this.
In the meantime, you can probably achieve the same result if you use some other non-entity token type for your custom token, like site information for example, or a custom type with no entity dependencies;
Comment #3
Dave ReidI think the problem here is the following:
This token should not return anything if $data['term'] is empty. Does this actually happen?
Comment #4
gaspaio CreditAttribution: gaspaio commentedWhen the token value is given by :
return !empty($data['term']) ? "testing" : NULL;
the error is still there.
I think this is because, as i indicated in #1792728: token_tokens() returns token replacements managed by other modules, the same custom token is resolved twice.
Comment #5
joel_osc CreditAttribution: joel_osc commentedPlease keep in mind that the use of 'Testing' was simply to create the most basic of test cases. In my actual configuration I am using a php_field and doing operations on $data to return my token. I just wanted to remove some variables from the equation while troubleshooting to provide the simplest situation under which the problem will occur. Thanks!
Comment #6
Dave ReidWhat kind of operations are you performing on $data?
Comment #7
joel_osc CreditAttribution: joel_osc commentedHmm, maybe my grammar threw things off here - I meant to say with $data. Just returning the tid out of it will generate the same error or simply return "testing" with no other php code. I was just trying to clarify that not using "needs term" was not a viable workaround. Thx.
Comment #8
mahmost CreditAttribution: mahmost commentedSomething goes wrong with 'term' tokens .. even with gaspaio's code in #4 it passes each token in $replacements as an array
$replacements = array("[term:token-name]"=>array("good data","");
to the$options['callback']
instead of$replacements = array("[term:token-name]"=>"good data");
This seems to result from an extra call of
module_invoke_all('tokens',...)
in token.tokens.inc (which is referenced in this patch #1792728: token_tokens() returns token replacements managed by other modules, bypassing this call makes things work for this specific case.the edit in the issue summary also fixes the bug for my use case.
Comment #9
jeremylichtman CreditAttribution: jeremylichtman commentedThe simplest fix is likely in pathauto_clean_token_values (approximately line 605 in pathauto.inc).
i.e. inside the foreach loop, before the preg_match, add this:
if(is_array($value)) {
$value = array_shift($value);
}
This allows pathauto to work with custom tokens, without attempting to resolve the larger issue with tokens.
Comment #10
Cracu CreditAttribution: Cracu commentedI got into same problem, by updating location module to 7.x-3.3 which contains a line similar to:
$replacements[$original] = (isset($node->{$field}[LANGUAGE_NONE][$position][$item]) ? $node->{$field}[LANGUAGE_NONE][$position][$item] : '');
in location_cck_tokens function.
I think some modules are doing it wrong, by setting empty value for token. I ended up with an array similar to:
I've fixed temporary by adding an if right before:
Comment #11
1kenthomas CreditAttribution: 1kenthomas commentedHmm. #9 and #10 are both rather blunt solutions which involve patching external modules (it's not clear to me whether the patches to these modules have merit, that is, are a better way to solve than a change to this module).
Is is possible to move towards a solution that has the potential of being committed / won't require patch management?
Thanks, best, Ken