Template Token Plugin Manager¶
The Template Token plugin manager discovers YAML-based plugins that provide hierarchical token trees for use in model templates. Template tokens allow model templates to contain placeholder values that are replaced when the template is instantiated.
Plugin manager details¶
| Property | Value |
|---|---|
| Service ID | plugin.manager.modeler_api.template_token |
| Class | Drupal\modeler_api\Plugin\TemplateTokenPluginManager |
| Discovery | YAML file (MODULE.modeler_api.template_tokens.yml) |
| Value object | Drupal\modeler_api\TemplateToken |
| Alter hook | hook_modeler_api_template_token_info_alter() |
| Cache tag | modeler_api_template_token_plugins |
YAML file structure¶
Create a file named my_module.modeler_api.template_tokens.yml in your
module's root directory:
my_tokens:
model_owner: my_owner_plugin_id
tokens:
my-token-group:
name: 'My Token Group'
token: my-token-group
children:
sub-token:
name: 'Sub Token'
token: 'my-token-group:sub-token'
value: 'Default value'
children:
leaf:
name: 'Leaf Token'
token: 'my-token-group:sub-token:leaf'
value: 'Leaf value'
Top-level keys¶
Each top-level key defines a token set. Multiple sets can be defined in a single file and will be merged by the list builder.
| Key | Type | Required | Description |
|---|---|---|---|
model_owner |
string |
Yes | Plugin ID of the Model Owner |
tokens |
object |
Yes | Token tree definition |
Token entry structure¶
Each token entry has the following properties:
| Key | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Human-readable name (translatable) |
token |
string |
Yes | Token identifier used in expressions |
value |
string |
No | Sample or default value |
purpose |
string |
Conditional | Required on first-level children under each indicator. Either select or config. |
selector |
string |
No | CSS selector string for select-purpose tokens. Collected into a selector chain. |
target |
string |
No | CSS selector for identifying target elements within the matched context. |
children |
object |
No | Nested child tokens (same structure, recursive) |
Token purposes¶
First-level children under each top-level indicator (e.g. eca-template)
must declare a purpose:
| Purpose | Description |
|---|---|
select |
Defines a CSS selector chain for DOM element selection. The Preact frontend highlights matching elements. |
config |
Provides configuration values passed through without DOM interaction. |
The purpose is inherited by all descendants. The TemplateToken::resolvePurpose()
method determines the purpose for any given token path.
Tokens use a colon-separated path convention. For example, a token at
eca-template:config:global:value:VALUE represents a leaf in the tree:
Token resolution¶
The TemplateToken::findToken() method navigates the token tree using a
colon-separated path:
$templateToken = $tokenManager->getTemplateToken('eca');
$found = $templateToken->findToken('eca-template:config:global:value:VALUE');
// Returns the token entry array with 'name', 'token', 'value', etc.
The hasToken() method checks for existence without returning the full entry.
TemplateToken value object¶
The Drupal\modeler_api\TemplateToken class is a readonly value object:
| Method | Return | Description |
|---|---|---|
getId() |
string |
Token set ID |
getModelOwner() |
string |
Model Owner plugin ID |
getTokens() |
array |
Full token tree |
getProvider() |
string |
Module that defined these tokens |
hasToken($path) |
bool |
Check if a token exists at the path |
findToken($path) |
?array |
Find a token entry by colon-separated path |
resolvePurpose($path) |
?string |
Resolve the purpose (select or config) for a given token path |
collectSelectors($path) |
string[] |
Collect CSS selector keys from the purpose node down to the target path |
TemplateTokenResolver¶
The modeler_api.template_token_resolver service resolves template token
references found in strings during a page request. It is the bridge between
server-side model data and the frontend template token selector UI.
| Method | Return | Description |
|---|---|---|
enabled() |
bool |
Whether the resolver is active |
addToken($value, $modelOwnerId, $modelId, $componentId) |
$this |
Parse a string for token references and resolve them |
addConfig($key, $value, $modelOwnerId, $modelId, $componentId) |
$this |
Attach hidden config key/value to an object |
addLabel($label, $modelOwnerId, $modelId, $componentId) |
$this |
Attach a human-readable label to an object |
addAppliedTemplate($modelOwnerId, $componentId, $target, $hiddenConfig, $config) |
$this |
Record a previously applied template |
hasTokens() |
bool |
Whether any tokens were resolved |
getEntries() |
array |
Raw resolved entries keyed by composite key |
resolve() |
array |
Final output with hidden config and labels merged |
reset() |
$this |
Clear all state |
getAttachments(&$attachments) |
void |
Attach library and resolved data to a render array |
Token label support¶
Token paths can include trailing segments beyond the deepest matching node.
These extra segments are captured as a token_label. For example:
Resolves to the text node with token_label set to First name.
TemplateTokenPluginManager API¶
| Method | Return | Description |
|---|---|---|
getAllTemplateTokens($reload) |
TemplateToken[] |
All discovered token sets |
getTemplateToken($id) |
?TemplateToken |
A single token set by ID |
getTemplateTokensByModelOwner($modelOwnerId) |
TemplateToken[] |
All tokens for a Model Owner |
TemplateTokenListBuilder¶
The modeler_api.template_token_list_builder service merges all token trees
for a given Model Owner into a single unified tree. The output conforms to
template_token_list.schema.json.
/** @var \Drupal\modeler_api\TemplateTokenListBuilder $listBuilder */
$listBuilder = \Drupal::service('modeler_api.template_token_list_builder');
$mergedTree = $listBuilder->build('eca');
JSON schema¶
The merged output follows config/schema/template_token_list.schema.json:
{
"eca-template": {
"name": "ECA Templates",
"token": "eca-template",
"raw token": "[template:eca-template]",
"children": {
"config": {
"name": "Configuration",
"token": "eca-template:config",
"raw token": "[template:eca-template:config]",
"children": {
"global": {
"name": "Global",
"token": "eca-template:config:global",
"raw token": "[template:eca-template:config:global]",
"children": {
"value": {
"name": "Value",
"token": "eca-template:config:global:value",
"raw token": "[template:eca-template:config:global:value]",
"children": {
"VALUE": {
"name": "Value",
"token": "eca-template:config:global:value:VALUE",
"raw token": "[template:eca-template:config:global:value:VALUE]",
"value": "Configurable value"
}
}
}
}
}
}
}
}
}
}
When multiple modules define tokens for the same Model Owner, trees are deep
merged. For example, if eca_ng defines both eca and eca_form token sets,
the builder merges them into a single tree under their shared root paths.
Complete example¶
From the eca_ng module (eca_ng.modeler_api.template_tokens.yml):
eca:
model_owner: eca
tokens:
eca-template:
name: 'ECA Templates'
token: eca-template
children:
config:
name: 'Configuration'
token: 'eca-template:config'
children:
global:
name: 'Global'
token: 'eca-template:config:global'
children:
value:
name: 'Value'
token: 'eca-template:config:global:value'
children:
VALUE:
name: 'Value'
token: 'eca-template:config:global:value:VALUE'
value: 'Configurable value'
eca_form:
model_owner: eca
tokens:
eca-template:
name: 'ECA Templates'
token: eca-template
children:
config:
name: 'Configuration'
token: 'eca-template:config'
children:
form:
name: 'Form'
token: 'eca-template:config:form'
children:
field:
name: 'Field'
token: 'eca-template:config:form:field'
children:
LABEL:
name: 'Label'
token: 'eca-template:config:form:field:LABEL'
value: 'Select 1 field'
select:
name: 'Select where template applies'
token: 'eca-template:select'
children:
form:
name: 'Forms'
token: 'eca-template:select:form'
children:
field:
name: 'Field'
token: 'eca-template:select:form:field'
children:
all:
name: 'All form fields'
token: 'eca-template:select:form:field:all'
value: 'All form fields'
This defines two token sets that the list builder merges into a single tree for
the eca Model Owner. The first set provides global configuration tokens; the
second adds form-specific configuration and selection tokens.