Problem/Motivation

Is not possible to use two tokens of same type when replacing tokens in a string. For example:

$string = 'Node [node1:title] points to [node2:title]';
$string = token_replace($string, array('node1' => $node1, 'node2' => $node2));

Proposed resolution

All modules that implements hook_tokens() expect their tokens (declared in hook_token_info()) to have a certain type name ('node', 'user', etc) so we can't change this behavior because all modules implementing this hook should be updated.

Instead, the approach is to add an 'alias' to the type, and internally strip this alias and call token_generate with the clean type name.

For example, the first example using this approach:

$string = 'Node [node{pointer}:title] points to [node{pointed}:title]';
$string = token_replace($string, array('node{pointer}' => $node1, 'node{pointed}' => $node2));

The modified code is token_replace() function. After getting all standard tokens a new loop is added to process the token alias. For each token type a new token_generate call is made, passing the stripped token (without the alias name chunk) and the filtered data array with the object related to this alias.

For the previous example two additional token_generate() calls are made:

  • first call: $type is 'node', $tokens is first token alias tokens stripped ('title' => '[node:title]'), and $data is the filtered data ('node' => $node1).
  • second call: $type is 'node', $tokens is first token alias tokens stripped ('title' => '[node:title]'), and $data is the filtered data ('node' => $node1).

Remaining tasks

Add tests to test functionality in deep to allow start a discussion on this approach. Having test coverage would work very well as examples and basis for such a discussion.

Add documentation for this feature.

User interface changes

No UI changes.

API changes

Added new token_alias_scan() function similar to token_scan but scans for token alias.

Additional notes

CommentFileSizeAuthor
#95 192068-95.patch9.2 KBunstatu
#89 1920688-nr-bot.txt1.98 KBneeds-review-queue-bot
#88 1920688-88.patch9.16 KBunstatu
#72 drupal-multiple_same-type_tokens-1920688-72.patch13.23 KBartem_sylchuk
#69 drupal-multiple_same-type_tokens-1920688-68.png97.66 KBMunavijayalakshmi
#68 drupal-multiple_same-type_tokens-1920688-68.patch13.14 KBartem_sylchuk
#66 interdiff-63-66.txt3.26 KBtunic
#66 drupal-multiple_same-type_tokens-1920688-66.patch13.98 KBtunic
#63 interdiff-59-63.txt10.27 KBtunic
#63 drupal-multiple_same-type_tokens-1920688-63.patch14.14 KBtunic
#59 interdiff-56-59.txt1.18 KBtunic
#59 drupal-multiple_same-type_tokens-1920688-59.patch9.69 KBtunic
#56 interdiff-55-56.patch727 bytestunic
#56 drupal-multiple_same-type_tokens-1920688-56.patch9.67 KBtunic
#55 interdiff-54-55.patch763 bytestunic
#55 drupal-multiple_same-type_tokens-1920688-55.patch9.72 KBtunic
#54 interdiff-53-54.patch2.98 KBtunic
#54 drupal-multiple_same-type_tokens-1920688-54.patch9.72 KBtunic
#53 interdiff-44-53.patch8.27 KBtunic
#53 drupal-multiple_same-type_tokens-1920688-53.patch9.72 KBtunic
#44 interdiff-40-44.txt4.04 KBckaotik
#44 drupal-multiple_same-type_tokens-1920688-44.patch5.75 KBckaotik
#40 support_multiple-1920688-36.patch5.14 KBfacine
1920688-token-replace-multiple-instances-same-type.patch8.79 MBdave reid
#3 1920688-token-replace-multiple-instances-same-type.patch16.54 KBdave reid
#4 1920688-token-replace-multiple-instances-same-type.patch16.54 KBdave reid
#6 1920688-token-replace-multiple-instances-same-type.patch17.65 KBdave reid
#19 1920688-token-replace-multiple-instances-same-type-19.patch12.36 KBberdir
#21 1920688-token-replace-multiple-instances-same-type-21.patch12.35 KBberdir
#21 1920688-token-replace-multiple-instances-same-type-21-interdiff.txt560 bytesberdir
#24 drupal-multiple_token_instances_support-1920688-22.patch4.72 KBtunic
#28 support_multiple-1920688-28.patch5.36 KBtunic
#29 interdiff-1920688-28-29.txt989 bytestunic
#29 support_multiple-1920688-29.patch4.69 KBtunic
#35 interdiff-1920688-29-33.txt2.01 KBtunic
#35 support_multiple-1920688-33.patch5.05 KBtunic
#37 interdiff-1920688-33-35.txt2.55 KBfacine
#37 support_multiple-1920688-35.patch5.16 KBfacine

Issue fork drupal-1920688

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

dave reid’s picture

Status: Active » Needs review

Let's test this out.

dave reid’s picture

Try that again...

dave reid’s picture

Status: Needs review » Needs work

The last submitted patch, 1920688-token-replace-multiple-instances-same-type.patch, failed testing.

dave reid’s picture

Status: Needs work » Needs review
StatusFileSize
new17.65 KB

This one should pass.

Status: Needs review » Needs work

The last submitted patch, 1920688-token-replace-multiple-instances-same-type.patch, failed testing.

dave reid’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 1920688-token-replace-multiple-instances-same-type.patch, failed testing.

dave reid’s picture

I'm not able to replicate these failures locally. :/

dave reid’s picture

Looks like #350407: Anonymous should not appear in the users table at all blocks token replacement for anonymous users.

dave reid’s picture

Disregard #11. Looks like it was fixed in #1634280: drupal_anonymous_user() should return a User entity.

xano’s picture

When #1968214: 'unify' hook_token_info() gets in, we can require data that is passed on to token_replace() to have a "type" parameter which refers to any of the types exposed in hook_token_info(). This way, data names and types are separated, and with a few modifications we can easily pass on an arbitrary number of data objects of the same type to token_replace().

dave reid’s picture

No, that would not be compatible with the current approach here.

xano’s picture

My apologies for posting that. It was a quick idea I had right before I had to leave and I posted it without checking your patches, which is what I did just now.

I understand the approach you're taking here. I haven't tested the patched but I believe it should work well. I have two questions:
1) What if the type of the data cannot easily be obtained, such as when the data is not an object?
2) Does this mean that we can remove the data type from needs-data in a follow-up, as we are using a different method of determining datas' types now?

dave reid’s picture

1) What if the type of the data cannot easily be obtained, such as when the data is not an object?

This change would start to transition the token system to requiring standardized objects that we can rely on, like TypedData. In the case that the data is not an object, we should ensure there is some kind of wrapper object for the data. For example UNIX timestamps in this patch are converted to DateTime objects, which is easier to then do multiple replacement for since we can check why type of item it is.

Does this mean that we can remove the data type from needs-data in a follow-up, as we are using a different method of determining datas' types now?

Likely yes, we would change the needs-data to something more useful, like 'global' => TRUE/FALSE to indicate if the token type requires data to be provided or not.

xano’s picture

I wonder if we should not use $entity->entityType rather than instanceof to determine an entity's type.

rudiedirkx’s picture

Is this what Drupal 6 did with token_replace_multiple()? It's not possible in D7?

berdir’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new12.36 KB

Interesting re-roll ;)

Status: Needs review » Needs work

The last submitted patch, 19: 1920688-token-replace-multiple-instances-same-type-19.patch, failed testing.

berdir’s picture

Status: Needs review » Needs work

The last submitted patch, 21: 1920688-token-replace-multiple-instances-same-type-21.patch, failed testing.

tunic’s picture

Status: Needs work » Needs review
StatusFileSize
new4.72 KB

Added a new patch with the approach described in #2367105: Support token alias (multiple instances of the same token type) for multiple token instances.

In short this patch adds token alias support. An example:

$token_service = \Drupal::service('token');

// Load a nodes then replace tokens in the text.
$text = 'The first node is [node{first}:title] and the other node is [node{second}:title]';
$node1 = node_load(1);
$node2 = node_load(2);

$data = array(
  'node{first}' => $node1,
  'node{second}' => $node2,
);

$output = $token_service->replace($text, $data);

Internally the code extracts the different alias and call Token::generate using a certain context that includes:

  • The token alias stripped so modules implementing token_info don't need to know about token alias. In the previous example the first context includes the type 'node' (instead of node{first}).
  • The $data filtered so only the data related to current alias is passed. In previous example only $node1 is passed under the 'node' key.

The patch is not complete because it doesn't handle the hook_tokens_alter(), but the appoach can be easily extended to cover this case. It can be optimized also. But first let's see if this is a good approach or there are issues that I'm not aware of.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

marvil07’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

This is a good idea, but after a while (a couple of years!), the last patch is not applying anymore, so marking as NW.

tunic’s picture

Version: 8.2.x-dev » 8.3.x-dev
Assigned: dave reid » Unassigned
Status: Needs work » Needs review
StatusFileSize
new5.36 KB

Rerolled!

Not including interfiff because file have been moved.

The patch is just porting the previouspatch code to the new Token.php file but adding the new BubbleableMetadata parameter when calling replace.

Again, this is just a proof of concept, there's much room for improvement.

BTW, now that token system is a service, I suppose a module could implement this idea and provide a modified token service, right? It'd have to extend the Token class.

tunic’s picture

It seems is not needed to modify the regexp, in fact TokenScanTest fails if yes.

With original regexps multiple token support works ok.

tunic’s picture

An example of how to use it:

$token_service = \Drupal::token();
$string_with_tokens = 'First node: [node{one}:title]........ another node: [node{two}:title]';

$node1 = node_load(1);
$node2 = node_load(2);

$string_with_tokens_replaced = $token_service->replace($string_with_tokens, array('node{one}' => $node1, 'node{two}' => $node2));
dpm($string_with_tokens_replaced);

The last submitted patch, 28: support_multiple-1920688-28.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 29: support_multiple-1920688-29.patch, failed testing.

rudiedirkx’s picture

The type{name} syntax seems very clunky. Why is it even necessary? Every entity contains its metadata, right? So Token would know $data['client'] is a User, and $data['node2'] is a Node. Why not parse all tokens and look for their types in $data?

berdir’s picture

Token supports more than entities but also things like dates and any other data structure.

The patch contains a ksm(), that's why everything explodes.

tunic’s picture

Status: Needs work » Needs review
StatusFileSize
new5.05 KB
new2.01 KB

Ok, big fail with last patch.

Let's rework the regexps. Standard scan should not match the aliased tokens, and alias scan should not match empty type tokens (for example: [:empty type token])

manuel garcia’s picture

Issue tags: -Needs reroll
facine’s picture

Notice: Undefined index: user{my_alias} in Drupal\Core\Utility\Token->replace()

Hi, I get this error if add an explication of how to use this in a field description.

I attach a new patch with a solution that works for me.

The last submitted patch, 37: support_multiple-1920688-35.patch, failed testing.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

facine’s picture

StatusFileSize
new5.14 KB

Rerolled for 8.3.x-dev

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ckaotik’s picture

The type{name} syntax seems very clunky.
-- @rudiedirkx

Token supports more than entities but also things like dates and any other data structure.
-- @berdir

Could we get away with just aliasing in the token string, and passing the data with arbitrary names?

$source_string = 'First node: [node:title]........ another node: [node{other_node}:title]';
$replaced_string = \Drupal::token()->replace($source_string, [
  'node' => node_load(1), 
  'other_node' =>node_load(2),
];
dpm($replaced_string);

That way, the code offering multiple same-type parameters can just "dump" them into the token service. Example scenario: Passing both the current and specific node revision straight from \Drupal::routeMatch()->getParameters()->all() on /node/{node}/revisions/{node_revision}/view (Route: entity.node.revision).
The user would still need to know that [node:*] and [node_revision:*] tokens are available, and what data type they are (so the correct token type is used). But code wouldn't need to change if additional data is already passed in.

I've also made some updates for code style.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

dunebl’s picture

Status: Needs review » Reviewed & tested by the community

I confirm #44 is working nicely and apply cleanly

berdir’s picture

Version: 8.9.x-dev » 9.3.x-dev
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

#44 is a two-year old patch for Drupal 8 without tests, there really is no point in RTBC'ing that as there is no way that will get committed like that. This just generates work for maintainers :)

tunic’s picture

Berdir, if the functionality is ok for maintainers I'll be happy to work on this. Currently, I don't know if is interesting, mainly because it got little attention. I'll try to address any comments (like adding tests).

However, the first thing to do is confirm the approach is ok and optimize the code. Given that it changes (or extends) how tokens are shaped I think we need some discussion here.

berdir’s picture

Yeah, it's though to bring any token related changes in core.

FWIW, it's a bit of a chicken/egg situation in regards to test and documentation versus discussion. IMHO, having test coverage would work very well as examples and basis for such a discussion. If we end up changing the syntax then it will take a few minutes to update examples in a test string. And it will help to verify that the regular expressions are working correctly.

So if you do want to bring this forward, then I'd strongly suggest to work on tests.

tunic’s picture

Ok, thank you very much for your comments Berdir, I'll focus on tests.

tunic’s picture

Issue summary: View changes
tunic’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new9.72 KB
new8.27 KB

Changed implementation to a simpler one (approach is the same but I don't why the previous implementation was so complex).

Tests added!

tunic’s picture

StatusFileSize
new9.72 KB
new2.98 KB

Fix coding standards.

tunic’s picture

StatusFileSize
new9.72 KB
new763 bytes

A missing comma that triggered a coding standards error.

tunic’s picture

StatusFileSize
new9.67 KB
new727 bytes

Fixing wrong function name in @cover clause.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

dunebl’s picture

@tunic There is a bug in #56... it can't work without the 2 following changes

    foreach ($text_token_aliases as $type => $text_token_alias) {
      $data_for_current_token = [];
      $unaliased_tokens = [];
      foreach ($text_token_alias as $tokens) {
        foreach ($tokens as $token => $aliased_token_name) {
          $unaliased_token_name = "[$type:$token]";
          $data_for_current_token[$unaliased_token_name] = $data[$aliased_token_name];
          $alias_tokens_mapping[$unaliased_token_name] = $aliased_token_name;
          $unaliased_tokens[$token] = $unaliased_token_name;
        }

        $replacements_unaliased = $this->generate($type, $unaliased_tokens, $data_for_current_token, $options, $bubbleable_metadata);

        foreach ($replacements_unaliased as $unaliased_token_name => $value) {
          $aliased_token_name = $alias_tokens_mapping[$unaliased_token_name];
          $replacements[$aliased_token_name] = $value;
        }
      }
    }

should be

    foreach ($text_token_aliases as $type => $text_token_alias) {
      $data_for_current_token = [];
      $unaliased_tokens = [];
      foreach ($text_token_alias as $alias => $tokens) { // ADDING $alias as the key
        foreach ($tokens as $token => $aliased_token_name) {
          $unaliased_token_name = "[$type:$token]";
          $data_for_current_token[$type] = $data[$alias]; // HERE IS THE MAIN CHANGE
          $alias_tokens_mapping[$unaliased_token_name] = $aliased_token_name;
          $unaliased_tokens[$token] = $unaliased_token_name;
        }

        $replacements_unaliased = $this->generate($type, $unaliased_tokens, $data_for_current_token, $options, $bubbleable_metadata);

        foreach ($replacements_unaliased as $unaliased_token_name => $value) {
          $aliased_token_name = $alias_tokens_mapping[$unaliased_token_name];
          $replacements[$aliased_token_name] = $value;
        }
      }
    }
tunic’s picture

StatusFileSize
new9.69 KB
new1.18 KB

#58, the original token is stored in the $text_token_aliases and it is part of the return value of the alias_scan function.

I guess you were confused by the alias_scan documentation because it was wrong. I've updated the patch fixing the documentation.

dunebl’s picture

#59: No, when using the code without correction I got a warning at this line:
$data_for_current_token[$unaliased_token_name] = $data[$aliased_token_name];
And the aliased replacement didn't occurs.
After the 2 proposed corrections in #58, the code runs fine and the (aliased) replacements occurs.
Maybe you can use a debugger and you will see that the index doesn't exists in this part of the mentioned lined $data[$aliased_token_name];

tunic’s picture

#60, can you provide the test case you are using?

dunebl’s picture

Something like this:

    $source_text="<p>Title1: [node:title]<p>Title2: [node{pc}:title]";
    $data=[
      'node' =>Drupal\node\Entity\Node::load(1),
      'pc'=>Drupal\node\Entity\Node::load(2)
    ];
    $options = [
      'clear' => FALSE,
      'langcode' => 'fr',
    ];
    $replaced_text = Drupal::token()->replace($source_text, $data, $options);
    dpm($replaced_text);

You can paste this code in the devel "Execute PHP code" page after having replaced the 2 IDs of the nodes by your existing ids.

tunic’s picture

StatusFileSize
new14.14 KB
new10.27 KB

Thanks, DuneBL, indeed it was wrong. In fact, everything was wrong, even the tests.

I've refactorized the code to fix it, including proper tests. Thi include a change on the format of alias_scan to allow a small simplifcation on the replace function.

DuneBL, keep in mind that when you use an aliased token you need to provide the type and the alias in the data array. So, instead
'pc'=>Drupal\node\Entity\Node::load(2) it should be 'node{pc}'=>Drupal\node\Entity\Node::load(2) .

Your test case would be:

    $source_text="<p>Title1: [node:title]<p>Title2: [node{pc}:title]";
    $data=[
      'node' =>Drupal\node\Entity\Node::load(1),
      'node{pc}'=>Drupal\node\Entity\Node::load(2)
    ];
    $options = [
      'clear' => FALSE,
      'langcode' => 'fr',
    ];
    $replaced_text = Drupal::token()->replace($source_text, $data, $options);
    dpm($replaced_text);

With the last patch, this test case runs ok!

dunebl’s picture

Status: Needs review » Reviewed & tested by the community

Thank you!
Looks like it is working well.

berdir’s picture

Status: Reviewed & tested by the community » Needs work

This can't be RTBC when tests are failing or more specific, not running due to coding standards.

tunic’s picture

Status: Needs work » Needs review
StatusFileSize
new13.98 KB
new3.26 KB

Sorry Berdir, I totally forgot about coding standards, shame on me.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

artem_sylchuk’s picture

Quick re-roll attempt as it no longer applies to 9.4

Munavijayalakshmi’s picture

Assigned: Unassigned » Munavijayalakshmi
StatusFileSize
new97.66 KB

Re-rolled patch applied successfully and cleanly.

Munavijayalakshmi’s picture

Assigned: Munavijayalakshmi » Unassigned
Status: Needs review » Reviewed & tested by the community
artem_sylchuk’s picture

Status: Reviewed & tested by the community » Needs work

Tests didn't pass.

artem_sylchuk’s picture

Status: Needs work » Needs review
StatusFileSize
new13.23 KB

One more attempt

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

smustgrave’s picture

Status: Needs review » Needs work

Open thread in the MR.

Also why in the MR did you add phpstan-baseline update? Don't see that in the patch before.

bhanu951’s picture

@smustgrave

Updated baseline due to this PHPStan error https://www.drupal.org/pift-ci-job/2558692


Running PHPStan on *all* files.
 ------ ---------------------------------------------------------------------- 
  Line   core/lib/Drupal/Core/Utility/Token.php                                
 ------ ---------------------------------------------------------------------- 
         Ignored error pattern #^Variable \$aliased_token_name might not be    
         defined\.$# in path                                                   
         /var/www/html/core/lib/Drupal/Core/Utility/Token.php was not matched  
         in reported errors.                                                   
  269    Variable $alias_tokens_mapping might not be defined.                  
 ------ ---------------------------------------------------------------------- 

smustgrave’s picture

That seems like a valid warning that may need to be addressed vs ignored.

Would have to compare to previous patch though and see what’s different in the MR.

berdir’s picture

Agreed, new problems should not be ignored but fixed.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

ro-no-lo’s picture

Hi, for everyone coming to this issue after 10+ years, I have created a small Token extension module, were aliased tokens can be used in a programmatically way. It is a different approach, in syntax, but if you are desperate you might give it a try.

https://www.drupal.org/project/token_aliases

(You may have to use it from the git directly.)

Usage:

  $token_service = \Drupal::service('token_aliases');
  $string = 'Hello [user1:username], we have news from [user2:username] see [node:title] and [my_node:title] for more info.';
  // Fully loaded Drupal entities which are keys with the aliases used in the string.
  $data = [
    'user1' => $user1,
    'user2' => $user2,
    'node' => $node,
    'my_node' => $my_node,
  ];
  $result = $token_service->plainReplace($string, $data);
grayle’s picture

There's a bug with the latest MR. The variables should be reset a loop deeper.

I do not have time to make a patch or MR, but the main block should look like this:

    foreach ($text_token_aliases as $type => $text_token_alias) {
      foreach ($text_token_alias as $alias => $tokens) {
        // Reset the variables in this loop.
        $alias_tokens_mapping = [];
        $data_for_current_token = [];
        $unaliased_tokens = [];
        foreach ($tokens as $token => $unaliased_token_name) {
          $unaliased_tokens[$token] = "[{$unaliased_token_name}]";
          $alias_tokens_mapping["[{$unaliased_token_name}]"] = "{$type}{{$alias}}:$token";
        }
        // @todo Check if need to add else condition ?
        if (isset($data["{$type}{{$alias}}"])) {
          $data_for_current_token[$type] = $data["{$type}{{$alias}}"];
          $replacements_unaliased = $this->generate($type, $unaliased_tokens, $data_for_current_token, $options, $bubbleable_metadata);

          foreach ($replacements_unaliased as $unaliased_token_name => $value) {
            $aliased_token_name = $alias_tokens_mapping[$unaliased_token_name];
            $replacements["[{$aliased_token_name}]"] = $value;
          }
        }
      }
    }

Otherwise you get very weird issues. Easy way to test:


function test_token_reps() {
  $data = [
    'user{target}' => User::load(1),
    'user{source}' => User::load(0),
    'user{thirdy}' => User::load(6),
  ];

  $text = "
  Target UID: [user{target}:uid]
  Target Name: [user{target}:name]
  Source Name: [user{source}:name]
  Thirdy UID: [user{thirdy}:uid]
  Source Name: [user{source}:name]
  Target Mail: [user{target}:mail]
  Thirdy Mail: [user{thirdy}:mail]
  ";

  $text = Drupal::token()->replace($text, $data);

  echo $text;
}

The thing is that you can't use the same fields for all the aliases, gotta have some diffs. Then it goes haywire.

unstatu changed the visibility of the branch 1920688-support-multiple-instances to hidden.

unstatu’s picture

Version: 11.x-dev » 10.4.x-dev
Status: Needs work » Needs review

I have created a new MR (https://git.drupalcode.org/project/drupal/-/merge_requests/8706) with the following changes:

- Changed the test to return different tokens depending on the passed entity so we don't rely on the onConsecutiveCalls() approach. IMO the new approach is more consistent.

- Reseted the $alias_tokens_mapping array on the inner loop as suggested in #82

unstatu’s picture

StatusFileSize
new9.16 KB
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.98 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

smustgrave’s picture

Hiding patches from bot.

MR should be updated to 11.x also as current development branch.

unstatu’s picture

Version: 10.4.x-dev » 11.x-dev
Status: Needs work » Needs review

Thanks for the feedback, smustgrave. On it.

unstatu’s picture

Status: Needs review » Needs work

I have changed the base branch from the issue. I'm going to change the base dev branch from the MR as well

unstatu’s picture

Status: Needs work » Needs review

Created a new MR based on 11.x and fixed the bot reported problems: https://git.drupalcode.org/project/drupal/-/merge_requests/8707

unstatu’s picture

StatusFileSize
new9.2 KB

The pipeline finally passed. This patch matches the latest state of the MR https://git.drupalcode.org/project/drupal/-/merge_requests/8707 with the pipeline in green.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

Ran the test-only feature https://git.drupalcode.org/issue/drupal-1920688/-/jobs/2066476 which shows the coverage.

Think instead of updating the baseline though should fix the error around alias_tokens_mapping, maybe setting a default like

$data_for_current_token = [];
$unaliased_tokens = [];

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.