Tokens¶
Tokens are a key component in ECA. They can be seen like variables, that store values and can be referenced later in the process again. That token functionality is provided by Drupal core out of the box and doesn't require any extra module or configuration.
However, there is also a Token module in contrib space, which is totally optional. Using ECA does not require that module to be available. Having said that, you may want to consider installing it as it provides a number of useful extra tokens as well as the Token browser which is a handy widget to provide you with a list of available tokens and their syntax.
Tokens vs. Token names
A token is a placeholder, like a variable in programming languages or scripts. They get replaced with their
corresponding value during run-time. A token can always be identified when it's enclosed and brackets, e.g.
[node:title]
or [myId]
. This is the syntax to be used when a configuration field contains "This property
supports tokens." in its description.
Other fields in ECA action configuration ask for a "Token name" instead, not for a token. Such a token name comes
without brackets and is the first part up to the first (if available) colon, e.g. node
or myId
from the two
token examples above.
Making tokens available¶
Tokens in the traditional Drupal context are provided by modules, e.g. all the node or user properties. An overview of all defined tokens can be given by the Token Browser. In ECA, a model can also define tokens on the fly, but there is an important distinction between the two types of tokens:
Read-only vs. read-write tokens
All tokens provided by Drupal core and contrib/custom modules are read-only and can be found in the Token Browser. ECA models can use all these tokens and all their properties, if they were made available, which is described in this chapter.
On the other hand, there are dynamically created tokens by ECA. Those can be read from and written to. They only
have a distinct token name, e.g. myNode
. If the token value is not a scalar value but an object, e.g. a list,
an entity, or other DataTransferObjects, then you can access their (nested) properties just like with the read-only
tokens desceibed above.
However, in all cases, tokens have to be made available before they can be used later in the processing chain. These are the options on how that could happen:
Tokens implicitly made available by events¶
Most events implicitly provide some tokens under pre-defined names.
Feature announcement (3348422)
There is a feature on the roadmap which will expose all the implicit tokens from events in the modeller UI and also here in the ECA Guide. This is currently not possible yet and the user needs to find such tokens either in support channels, in the code or by using the debugging techniques described in the Debugging section.
The tokens user
and current_user
are always available, they contain the current user entity of the request that
triggered the event.
When an entity related event gets triggered, e.g.
Presave content entity, then ECA automatically puts the related
entity onto the token stack with the name entity
and also under the name of the entity type, e.g. node
, user
, etc.
When a form related event gets triggered, e.g.
Build form, then ECA automatically puts the related form onto the token
stack with the names form
and current_form
.
Others will be documented as soon as the above feature got implemented.
Tokens declared by actions¶
Most action plugins make their result available as a token, and their configuration form allows you to define the token name for that. Example actions are:
@todo Tag action plugins
Let's tag action plugins that provide tokens so that we can link to that tag here.
Tokens being forwarded¶
When triggering a Custom event or an Entity-aware custom event with the Trigger custom event action or the Trigger entity-aware custom event action, a list of tokens, that are available in the triggering process, can be forwarded to the triggered event. They will then be available in the triggered event and its process under the same name as the triggering process.
In case of the entity-aware custom events, there will always be an entity being forwarded in addition to the tokens
mentioned above. That entity will always be known under the name entity
in the triggered events and its process.
A word about token names¶
No matter how a token gets made available to the ECA process, it always comes with a name. There is no naming convention and you can call tokens what ever you like. This is important for two reasons:
- A token representing e.g. a node, does not have to be called
node
. Instead, you can call itcurrentArticle
orreferencedLocation
or what else. This allows you to have multiple nodes in the token stack available at the same time. Token names need to be alpha-numeric, though. So, no spaces or other special characters are allowed. - When you're looking for token property syntax in the Token browser, you only always find the
tokens under their originally declared name. So, if you want to use the title of your current article, which can be
found as
[node:title:value]
in the token browser, just replace the token namenode
with the name of your own token, i.e.[currentArticle:title:value]
.
Scope of tokens¶
Tokens only ever exist, if they have been made available, and they get quickly forgotten automatically as soon as the process of the current event has been completed. They are never available outside of that event process. You can pass a token to a custom event though, but otherwise no token exists outside of the process where it has been made available.
This may sounds too strict, but it follows modern programming language design which keeps variables protected from being accessible from outside their declaring context.
Should you require more global or even persistent values/variables/token, then there are storage mechanisms required. In the ECA eco system there are many options available to do that:
- Read and write the key/value store
- Read and write the expirable key/value store
- Read and write the state
- Read and write the private temporary store
- Read and write the shared temporary store
- Read and write config
- Get and set parameters
Token Browser¶
While tokens are provided by Drupal core, the token browser is provided by the Token contrib module and is only available, if that module is installed and enabled. In the context of any ECA modeller, that token browser can be opened as an overlay and contains all potential tokens that are available on that Drupal site. This doesn't mean that all those tokens are available during run-time, when ECA processes you models. It rather is a "directory" of all token names and their properties. It's up to the ECA model to make sure that a required token is available to the processor prior to it being used.
What else you need to know about tokens¶
Tokens may be linked to their data source¶
There is an important difference on how field values are made available as tokens:
- Token: set value: when using e.g.
[entity:field_name]
to set a token, that keeps the reference back to the field and if the token value changes within that ECA model, this will also change the original entity field value. - Entity: get field value: a field value stored in a token this way will not keep the link to the original entity field and the token value can be modified safely without having to worry about unintentionally changing entity field values.
@todo Verify statement
Need to verify, if this is correct or if it's the other way round. Ideally we should write tests for this.
Nested tokens¶
If a token contains references to other tokens, Drupal's token replacement function does not replace those nested tokens by design.
Example: you may have a token called myText
which has a value like Some longer text containing a [site:name]
, when
you're using your token somewhere like The text containing [myText] and more.
will be replaced into
The text containing Some longer text containing a [site:name] and more.
, so the nested token [site:name]
won't be
replaced.
ECA 2.0 comes with an action Token: replace which resolves that issue such that it replaces tokens up to 5 nesting levels deep.
Entity fields: value or rendered¶
Using the token [entity:field_name]
will return the rendered field value, so the default field formatter will be
called before the field value is being replaced.
In contrast, the token [entity:field_name:value]
returns the original field value without using any rendering or
field formatter.
String values: plain text or markup¶
All string values are returned as markup rather than plain text by default. This is important for security reasons to prevent malicious data to cause cross-site scripting issues. However, that's not helpful in many case in the context of ECA processing, when you e.g. want to copy the value from one text field to another in an entity.
An example, of what's different in markup and plain text, is the Terms & conditions
string. If that's returned as
markup and afterwards stored in a string field again, you'll get Terms & conditions
as a result. Other HTML
entities will cause similar issues.
Feature announcement (3373537)
In ECA 2.0 there is an option to force token replacement to plain text only. By default, token replacement remains the same as it is implemented in Drupal core, so that your model only changes behaviour intentionally.
Replacing tokens in non-ECA actions¶
Action plugins that are not developed specifically for ECA often do not contain a token-replace function, and therefore may not automatically replace any tokens that are passed into them. Those action plugins (for example, "send mail" and "display message to user" and others listed under "Drupal core" in the task's "Choose element template" dialog) will have a "Replace tokens" field at the bottom of their configuration panes. Setting that field to "yes" may be necessary for proper token replacement. Tip: If you're having trouble with token replace in an action plugin, and the "Replace tokens" field is visible and set to "no," try changing it to "yes" as a first step in debugging.