# ECA - Drupal Events, Conditions, Actions > Documentation, tutorials and resources for Drupal's ECA module and its eco-system. Documentation for Drupal's ECA (Events-Conditions-Actions) module, the recommended rules engine for Drupal 10/11+. Covers core concepts, plugin reference, visual modelers, example models, and developer guides. # ECA Guide # Welcome to Drupal ECA This document explains how to use the Events - Conditions - Actions (ECA) module for Drupal. ## What is ECA? ECA (Events - Conditions - Actions) is a Drupal module that processes business process models based on Drupal events. The module integrates with Drupal core components and provides plugin management for: - [Events](https://ecaguide.org/eca/concepts/events/index.md) - [Conditions](https://ecaguide.org/eca/concepts/conditions/index.md) - [Actions](https://ecaguide.org/eca/concepts/actions/index.md) Note ECA does not include a built-in user interface. Instead, it provides a modeler plugin manager that integrates with existing tools. If a modeler supports templates, ECA provides them for all plugins available on your Drupal site. ## Contents - [Installation guide](https://ecaguide.org/eca/install/index.md) - [Key concepts](https://ecaguide.org/eca/concepts/index.md) - [Extension guide](https://ecaguide.org/eca/extend/index.md) - [Plugin documentation](https://ecaguide.org/plugins/index.md) - [Available modelers](https://ecaguide.org/modeler/index.md) - [Example models](https://ecaguide.org/library/index.md) - [Additional resources](#additional-resources) ## Additional resources You can find articles, tutorials, videos, and other learning materials in the Resources section. ## Get support Contact the ECA maintainers through: - Their Drupal.org user profiles - The [ECA Slack channel](https://drupal.slack.com/archives/C0287U62CSG) ## Contribute We welcome contributions including: - Bug reports and feature requests - Documentation improvements - Example models - Custom plugins - General feedback To contribute: 1. Request an account on the [ECA Guide GitLab](https://gitlab.lakedrops.com). Contact the ECA maintainers on the [ECA Slack channel](https://drupal.slack.com/archives/C0287U62CSG), and provide an email address for the account. 1. Visit the [ECA Guide Project](https://gitlab.lakedrops.com/drupal/documentation/eca) 1. Open an issue or create a merge request When writing documentation, please follow the [documentation styleguide](https://ecaguide.org/eca/styleguide/index.md). For more information about ECA, visit the [project page](https://www.drupal.org/project/eca). # Installation ECA can be installed in two ways: using the recommended Starterkit recipe or manually installing the modules. ## Starterkit (Recommended) The [ECA Starterkit](https://www.drupal.org/project/eca_starterkit) provides a complete setup for ECA. It installs a recommended set of modules, configures the Workflow Modeler, and includes a demo model to get you started immediately. ### What gets installed - **Core ECA components**: A comprehensive set of 20 sub-modules covering access control, caching, content entities, forms, logging, users, views, and more. - **Workflow Modeler**: The recommended visual editor with drag-and-drop capabilities. - **Demo Model**: A "User Registration Form" model that demonstrates field customization and validation. ### Installation steps 1. **Require the recipe**: ``` composer require drupal/eca_starterkit ``` 1. **Apply the recipe**: ``` # Using Drush (version 13 or later) drush recipe ../recipes/eca_starterkit # Or without Drush cd web && php core/scripts/drupal recipe ../recipes/eca_starterkit ``` After applying the recipe, navigate to **Administration > Configuration > Workflow > ECA** to see the installed demo model and start building your own. ## Manual Installation If you prefer to install only specific components, you can install the modules manually. Download the ECA module and Workflow Modeler module: ``` composer require drupal/eca drupal/modeler ``` Install the ECA and Workflow Modeler module and their dependencies via the GUI at `/admin/modules` or with Drush: ``` drush -y pm:install eca eca_ui modeler ``` The list of additional ECA sub-modules you may want to install depends on your specific use-case (e.g., `eca_content`, `eca_user`, `eca_views`). # Usage Actually, ECA is processing all enabled models in the background and there is nothing a user needs to do, when everything has been set up. In fact, there isn't anything a user could do to prevent ECA from processing all these models Attention Should there ever be a problem, that ECA breaks your site, please refer to the [troubleshooting](https://ecaguide.org/eca/troubleshooting/index.md) section which explains how to fix that. ## How it works ECA is a processor that works in the background by subscribing to all events on a Drupal site and executing ECA models that define processes for any of those events. There is no UI required for that, ECA just operates based on the available and enabled models. Recommended setup for production sites Creating and maintaining ECA models might be a task for your development environment. On the production site, there is often no access to either view or edit those models. If that applies to your Drupal site, you only need to enable ECA and all the sub-modules that are required by the configured ECA models. There won't be any UI and no modeler available for any user on the live site, ECA just operates on the configured models. Subscribing to all events on a Drupal site may sound worrisome in regard to site performance. We've taken much care to avoid unnecessary overhead and ECA is able to decide very quickly, whether an event is relevant for any of the configured models or not. All information, that's required to make those decisions are stored in cache separately and will only be loaded once for each request, so that the extra processing for each event on top of Symfony's event dispatching is in fact negligible, and we haven't been able to even measure any impact. ### ECA model config files The ECA models have been mentioned a lot, and this chapter explains how those models are stored and describe the structure of their config files. This should help you plan the maintenance and deployment of your own models on all your different Drupal sites. Each ECA model is a set of 2 config entities, each of which being exported by Drupal's configuration management into a separate file. The config entities (and files) for a single model are named with the following pattern: - `eca.eca.[MODEL-ID]`: contains all events, conditions and actions that ECA operates upon - `eca.model.[MODEL-ID]`: contains the proprietary model data of the modeler that has been used to create and edit this model In other words, the config entity `eca.eca.[MODEL-ID]` is being used by ECA to operate on the Drupal site. The other one is not needed for that at any time. That second config entity is only required by the modeler, when the model gets edited. When editing a model with a modeler, ECA will recreate its `eca.eca.[MODEL.ID]` config entity by converting the modeler data when the model gets saved by the modeler. Danger Always keep the 2 config entities together - ECA always keeps them in sync. And never edit them manually, the eca.eca entity will always be recreated from the eca.model entity. Having said that, the `eca.model` config entity contains everything needed to recreate the `eca.eca` config entity, should you ever loose that. That implies that you could send the `eca.model` config entity to someone else only, and they could load that into their Drupal site which would then recreate the companion `eca.eca` config entity, if they had the same modeler available to interpret the proprietary data. More about that below in [Import and export models](#import-and-export-models). ## Admin UI As mentioned above, to let ECA do its work by processing available ECA models, no UI is required whatsoever. Only if you need to maintain your ECA models, the ECA UI is required. Very much like Drupal core has implemented this for the fields and views modules, where the UIs can also be disabled when not required. When the ECA UI is being required, you can enable it separately: ``` drush en eca_ui ``` This enables the admin UI which can be found in the admin menu under Administration / Configuration / Workflow / ECA with the path `/admin/config/workflow/eca`: On this ECA admin page you can manage all aspects of ECA: Changing the order of the models by re-arranging them, importing new models and performing operations on each of the available models. That's all described in the chapters below. Creating and editing models The ECA admin UI does not provide you access to create new models or to edit existing ones. Those actions are only available, when at least one modeler is enabled which provides support for integrated editing, like e.g. the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md). ### Settings `Log level` : *Default: Error* ``` Determines, which ECA log messages will be logged to which ever logging backend is enabled on your site. By default, ECA only logs errors or more severe log messages. You can change that to e.g. `Debug` to also get much more detailed logs, see also [Logs](#logs) and [Debugging](https://ecaguide.org/eca/debugging/index.md). ``` `Documentation domain` : *Default: https://ecaguide.org* ``` This domain is being used to provide links to the documentation when working with a modeler, and it points to this official ECA guide by default. You can change this to any other domain, if you provide your own documentation, or make this field empty, so that ECA won't display any links to documentation. ``` ### Logs This is only available, if you've also enabled the `Database Logging` module. It will display all the logged ECA messages depending on the log level you've configured in the [settings](#settings). You can filter the messages by content and/or time range and the list is sorted in exactly that order how the messages got produced. Each log message for a condition or an action will also contain a list of tokens, that have been available at the time when that component has been evaluated or executed. For more details about token, see [Concepts: Token](https://ecaguide.org/eca/concepts/tokens/index.md). ### ECA model operations In the list of models, the operations column contains a list of operations for each model, that's available on that Drupal site: #### Creating and editing models These actions are only available, if you have a modeler enabled that supports integrated editing, like e.g. the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md). #### Import and export models Models can be imported by clicking on the `Import` button in the top right corner. This will open a form where you can select a file to import. There are actually 2 different file types supported for import: - an `eca.model.[MODEL-ID].yml` config file, see [ECA model config files](#eca-model-config-files) - an archive file (e.g. `[MODELLER-TYPE]-[MODEL-ID].tar.gz`) which has been previously exported (see below) or downloaded from the [Library](https://ecaguide.org/library/index.md) Once you've selected the file and click on the `Import` button, ECA will validate the file and if all dependencies are available, import the model and show it on the list of models for further operations. For a comprehensive guide on all import methods, common issues and troubleshooting, see [Importing Models](https://ecaguide.org/eca/importing/index.md). To export a model from your Drupal site, e.g. because you want to use it on a different Drupal site, or you need to attach it to an issue on drupal.org, select the `Export` operation in the list of models for that model, that you want to export. This will create an archive with a filename `[MODELLER-TYPE]-[MODEL-ID].tar.gz` which contains the id of the used modeler and the ID of the model itself. Note It's important to keep that filename as it is part of the validation when later importing that model again. The exported archive contains 3 or more files: - `dependencies.yml`: a metadata file containing the names of ECA config entities and a list of required modules - `eca.eca.[MODEL.ID].yml`: the ECA config entity for processing - `eca.model.[MODEL.ID].yml`: the ECA config entity with proprietary model data - optionally more config entities, if the exported ECA model depends on other config entities #### Clone This will clone an existing ECA model and create a random ID for the new model. #### Enable / disable Only one of those 2 operations is available, depending on the state of each model. Enabled model can be disabled and vice versa. Disabled models will not be processed by ECA, but they remain available on the Drupal site for editing or other operations. Only if you re-enable a disabled model will it be processed by ECA again. ### Delete This will delete an ECA model entirely from the Drupal site. # Importing Models ECA models can be imported into your Drupal site in several ways. This guide covers all available import methods, explains common issues that may arise during import, and provides solutions for resolving them. ## Import methods ### Using recipes (recommended) Since Drupal 10.3, the recommended way to import models from the [ECA Library](https://ecaguide.org/library/index.md) is via recipes. Each library model is available as a Composer package that can be applied as a Drupal recipe. ``` # Require the recipe package composer require drupal-eca-recipe/eca_lib_XXXX # Apply the recipe with Drush (version 13 or later): drush recipe ../recipes/eca_lib_XXXX # Or apply the recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_XXXX # Rebuilding caches is optional, sometimes required: drush cr ``` Replace `XXXX` with the library model number. Each library model page shows the exact commands to use. Tip Recipes handle dependencies automatically. If the model requires additional configuration entities (e.g. content types, fields, or vocabularies), the recipe will create them for you. ### Using the ECA admin UI Models can also be imported manually through the ECA admin interface at `/admin/config/workflow/eca`: 1. Click the **Import** button in the top right corner. 1. Select the file to import. 1. Click **Import** to validate and import the model. Two file types are supported: `eca.model.[MODEL-ID].yml` : A single YAML config file containing the proprietary model data. ECA will recreate the companion `eca.eca.[MODEL-ID]` config entity automatically, provided the appropriate modeler is enabled. See [ECA model config files](https://ecaguide.org/eca/usage/#eca-model-config-files) for details. `[MODELER-TYPE]-[MODEL-ID].tar.gz` : An archive file previously exported from another Drupal site or downloaded from the [ECA Library](https://ecaguide.org/library/index.md). The archive contains: ``` - `dependencies.yml` — metadata listing required config entities and modules - `eca.eca.[MODEL-ID].yml` — the ECA processing config entity - `eca.model.[MODEL-ID].yml` — the modeler-specific model data - optionally, additional config entities that the model depends on ``` Note When importing an archive, do not rename the file. The filename is validated during import and must match the pattern `[MODELER-TYPE]-[MODEL-ID].tar.gz`. ### Using Drupal's configuration management ECA models are standard Drupal configuration. You can also deploy them through Drupal's configuration synchronization system by placing the two config files (`eca.eca.[MODEL-ID].yml` and `eca.model.[MODEL-ID].yml`) into your configuration sync directory and running a config import: ``` drush config:import ``` This is particularly useful for deploying models from a development environment to production. See also the [recommended setup for production sites](https://ecaguide.org/eca/usage/#how-it-works). ## Troubleshooting import failures Sometimes, importing a model may fail. Below are the most common causes and their solutions. ### Existing entities prevent import **Symptom:** The import fails with a message similar to: > The import failed due to the following reason: There were errors validating the config synchronization. Entities exist of type *Content* and *Content type* *Basic page*. These entities need to be deleted before importing. **Cause:** The model archive includes configuration for entities such as content types, vocabularies or fields. If those entities already exist on your site with content attached to them, Drupal's configuration validation rejects the import because it would overwrite existing configuration that has dependent data. **Solutions:** 1. **Check for conflicting entities.** Compare the configuration in the archive with what already exists on your site. If the existing configuration matches what the model expects, the import may succeed after removing the conflicting config entities from the archive. Extract the archive, remove the unnecessary files, update `dependencies.yml` accordingly, and repackage it. 1. **Delete conflicting content first.** If the existing entities contain test data or content you do not need, delete the content and then the configuration entities before retrying the import. 1. **Import only the ECA model files.** Instead of importing the full archive, import just the `eca.model.[MODEL-ID].yml` file through the admin UI. This skips the dependency configuration but requires that all dependencies already exist on your site with a compatible setup. 1. **Use the recipe method.** Recipes handle existing configuration more gracefully. If the configuration already exists and is compatible, the recipe will skip creating it and only add the ECA model. Tip For more context on this issue, see [drupal.org issue #3381483](https://www.drupal.org/project/eca/issues/3381483). ### Missing required modules **Symptom:** The import fails because one or more required modules are not enabled. **Cause:** The model uses plugins provided by modules that are not installed on your site. The `dependencies.yml` file in the archive lists all required modules. **Solution:** Enable the required modules before importing: ``` # Check which modules are required by extracting the archive # and reading the dependencies.yml file, then enable them: drush en module_name_1 module_name_2 ``` When using the recipe method, missing modules are listed as Composer dependencies. Running `composer require` for the recipe package will automatically install the required modules. ### Modeler not available **Symptom:** The model imports but cannot be edited, or the import of a `.yml` file fails to recreate the `eca.eca` config entity. **Cause:** The model was created with a specific modeler (e.g. the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) or BPMN.iO), and that modeler is not enabled on your site. **Solution:** Enable the modeler that was used to create the model. All [ECA Library](https://ecaguide.org/library/index.md) models are built with the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md), so enabling `eca_ui` and `eca_modeller_bpmn` is sufficient for library models: ``` drush en eca_ui eca_modeller_bpmn ``` ### Archive filename has been changed **Symptom:** The import fails during file validation. **Cause:** The archive file was renamed after export. ECA validates the filename to extract the modeler type and model ID. **Solution:** Restore the original filename matching the pattern `[MODELER-TYPE]-[MODEL-ID].tar.gz`. If you do not know the original name, extract the archive and check the config filenames inside — the model ID is part of the `eca.model.[MODEL-ID].yml` filename. ### Configuration validation errors **Symptom:** The import fails with generic configuration validation errors. **Cause:** This can happen when the model was created on a different version of Drupal or ECA, and there are schema differences between versions. **Solution:** 1. Ensure you are running a compatible version of ECA. Check the model's documentation or the library page for version requirements. 1. Update ECA to the latest version: `composer update drupal/eca` 1. If the issue persists, try importing just the `eca.model.[MODEL-ID].yml` file instead of the full archive. ## Best practices for importing - **Back up your site** before importing models, especially on production environments. - **Review the model** before importing. Each library model page includes a visual representation of the model and a list of its dependencies. - **Use a development environment** to test imported models before deploying them to production. - **Prefer recipes** when importing library models — they handle dependencies automatically and are more resilient to existing configuration. - **Keep your ECA installation up to date** to ensure compatibility with the latest library models. # Understanding ECA concepts ECA (Events - Conditions - Actions) models help you automate business processes in Drupal by responding to events that happen on your site. Think of ECA as a watchful assistant that can detect when something happens, check if certain conditions apply, and then take appropriate actions. ## Core components ### Events Events are triggers that start an ECA process. These could be things like: - A user logging in - Content being created or updated - A form being submitted - A scheduled time arriving - A custom event you define When an event occurs, ECA checks if any models are listening for that event and runs them if so. For a detailed guide on event types, token availability, and how to add events to models in each modeler, see the dedicated [Events](https://ecaguide.org/eca/concepts/events/index.md) page. ### Conditions Conditions are checks that determine whether actions should run. They act as filters or guards, ensuring actions only happen when appropriate. For example, you might want to: - Check if a user has a specific role - Verify content has certain field values - Ensure a threshold has been met - Compare dates or times - Combine multiple conditions with AND/OR logic Conditions go on connections A common point of confusion for newcomers: conditions are not standalone elements on the canvas. Instead, they are attached to the **connections** (edges) between components. See the [Conditions](https://ecaguide.org/eca/concepts/conditions/index.md) page for details on how to add them in each modeler. ### Actions Actions are the tasks ECA performs when an event occurs and conditions are met. Actions can: - Create or update content - Send notifications - Modify user accounts - Interact with external systems - Trigger other events - Perform custom operations For a detailed guide on action categories, chaining, token interaction, and how to add actions in each modeler, see the dedicated [Actions](https://ecaguide.org/eca/concepts/actions/index.md) page. ## How components work together Let's look at a common example: sending a welcome email to new users in a specific role. 1. **Event**: User account is created 1. **Condition**: User has the "member" role 1. **Action**: Send customized welcome email ECA processes this flow by: 1. Detecting the account creation event 1. Checking the user's roles 1. Sending the email if the condition is met ## Next steps Learn more about specific concepts: - [Events](https://ecaguide.org/eca/concepts/events/index.md) -- types of events, tokens they provide, and how to add them - [Conditions](https://ecaguide.org/eca/concepts/conditions/index.md) -- condition types, negation, AND/OR logic, and how to add them - [Actions](https://ecaguide.org/eca/concepts/actions/index.md) -- action categories, chaining, token interaction, and how to add them - [Managing permissions](https://ecaguide.org/eca/concepts/permissions/index.md) - [Understanding tokens](https://ecaguide.org/eca/concepts/tokens/index.md) - [Using loops](https://ecaguide.org/eca/concepts/loops/index.md) - [Working with custom events](https://ecaguide.org/eca/concepts/custom_events/index.md) - [Entity events](https://ecaguide.org/eca/concepts/entity_events/index.md) - [Using gateways](https://ecaguide.org/eca/concepts/gateways/index.md) For practical examples, visit our [model library](https://ecaguide.org/library/index.md). # Actions Actions are the tasks that ECA performs when an event occurs and any associated conditions are met. They are the "do" part of the Events-Conditions-Actions pattern -- the components that actually make changes to your site. ## What is an action? An action is an operation that ECA executes as part of a model's processing flow. Unlike conditions (which only evaluate and never modify), actions carry out real work: creating content, sending emails, modifying entities, setting token values, and more. Actions can be chained together. The output of one action (often stored as a [token](https://ecaguide.org/eca/concepts/tokens/index.md)) can be used as input for the next, allowing you to build complex automated workflows step by step. ## Common action categories ECA provides a large number of actions. Here are some of the most frequently used categories: Content actions : Create, update, save, or delete content entities. Examples include [Save entity](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) and [Entity: set field value](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md). Token actions : Set, modify, or manipulate token values for use later in the process. The most common is [Token: set value](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md). User actions : Manage user accounts -- assign roles, switch the current user context, block or unblock accounts. See also [Permissions](https://ecaguide.org/eca/concepts/permissions/index.md) for how user context affects processing. Notification actions : Send emails, display messages to the user, or write to the log. Trigger actions : Trigger other ECA events, including [custom events](https://ecaguide.org/eca/concepts/custom_events/index.md), to create modular, reusable workflows. Form actions : Modify forms by setting field values, adding validation errors, or altering form elements. External actions : Interact with external systems via HTTP requests, webhooks, or queue processing. Browsing available actions The full list of actions depends on which modules are installed. See the [Plugins section](https://ecaguide.org/plugins/index.md) for a complete reference, organised by module. ## How actions work in ECA When ECA reaches an action during processing, it: 1. Evaluates any [conditions](https://ecaguide.org/eca/concepts/conditions/index.md) on the incoming connection. If a condition returns FALSE, the action (and all its successors) is skipped. 1. Executes the action with the configured parameters, replacing any [token](https://ecaguide.org/eca/concepts/tokens/index.md) references with their current values. 1. If the action produces a result (e.g. a loaded entity, a computed value), it stores that result as a token under the name you specify. 1. Proceeds to any successor actions connected from this action. Actions are processed sequentially in the order their connections were created. ## Successors and chaining An action can have one or more successor connections, each optionally guarded by conditions. This allows you to: - **Chain actions**: Connect actions in sequence to build multi-step workflows. - **Branch based on outcome**: Use conditions on outgoing connections to create conditional paths after an action. - **Trigger sub-processes**: Use the trigger custom event action to delegate work to another model. ## Adding an action to a model ### Workflow Modeler 1. Open your model at **Configuration > Workflow > ECA**. 1. From the toolbar or canvas, add an **Action** node. 1. Select the action type from the categorized list. 1. Configure the action's settings in the side panel (e.g. field values, token names, email recipients). 1. Connect the action to its predecessor (event, gateway, or another action) using an edge. 1. Optionally add conditions to the incoming edge. You can also use the **Quick-Add** feature: click the `+` on any existing node to add a connected successor action directly. ### BPMN.iO 1. On the canvas, add a **Task** element (the rounded rectangle). 1. Use the wrench icon to configure the task type as an ECA action. 1. In the configuration panel on the right, select the action from the dropdown. 1. Configure the action's settings. 1. Draw sequence flows to connect the action to its predecessor and any successors. ### Classic Modeler 1. Use the form interface to add an action by selecting from the available action types. 1. Fill in the configuration fields. 1. Connect the action to its predecessor and any successors using the form-based interface. ## Tokens and actions Many actions interact with the token system: - **Consuming tokens**: Actions can use tokens in their configuration fields. Any field marked with "This property supports tokens." accepts token references like `[node:title]` or `[myToken]`. - **Producing tokens**: Actions that produce a result (e.g. loading an entity, performing a calculation) typically offer a "Token name" field where you specify the name under which the result is stored. - **Token replacement in non-ECA actions**: Actions from Drupal core or other modules (not specifically developed for ECA) may have a "Replace tokens" setting at the bottom of their configuration. Set this to "yes" if tokens are not being replaced automatically. See [Tokens](https://ecaguide.org/eca/concepts/tokens/index.md) for details. ## Tips for working with actions - **Order matters**: Actions execute in the order they are connected. Ensure that any tokens or entities needed by an action have been made available by a preceding event or action. - **Check the "Token name" field**: When an action loads or creates something, always provide a meaningful token name so you can reference the result later. - **Use "Switch account" for elevated permissions**: Actions execute under the current user's permissions. If an action requires higher privileges, use [User: switch current account](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) before it. See [Permissions](https://ecaguide.org/eca/concepts/permissions/index.md). - **Save entities explicitly**: Modifying an entity's fields does not automatically save it. You typically need a separate [Save entity](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) action afterwards. - **Debug with logging**: Use the [debugging tools](https://ecaguide.org/eca/debugging/index.md) to trace which actions executed, which were skipped, and what token values were available at each step. # Conditions Conditions act as guards or filters in an ECA model. They determine whether a particular path of actions should be executed. If a condition evaluates to TRUE, the connected actions proceed; if FALSE, that branch is skipped. ## What is a condition? A condition is a yes-or-no check applied to a connection between components in your model. It answers the question: **"Should this path be followed?"** Conditions do not perform any changes themselves -- they only evaluate a situation and return TRUE or FALSE. This makes them safe to use: a condition never modifies data. ## Common condition types ECA offers a wide range of conditions. Some of the most frequently used include: Scalar comparison : Compare two values (equal, not equal, greater than, less than, contains, etc.). Useful for checking field values, token contents, or any text/number comparison. Entity type and bundle : Check whether an entity is of a specific type (e.g. node, user) or bundle (e.g. article, page). Essential when an event applies to multiple content types but you only want to act on one. User role : Verify whether the current user has a specific role. Commonly used to restrict actions to administrators or specific user groups. Entity field value : Check whether a specific field on an entity has a particular value, is empty, or matches a pattern. Route match : Evaluate the current Drupal route or path, useful for request/response event models. Browsing available conditions The full list of conditions depends on which modules are installed. See the [Plugins section](https://ecaguide.org/plugins/index.md) for a complete reference, organised by module. ## Negating conditions Every condition in ECA can be negated. When you negate a condition, the logic is inverted: a condition that would normally return TRUE returns FALSE instead, and vice versa. This is useful when you want to express "if NOT this condition" without needing a separate condition plugin. For example, negating a "user has role" condition effectively becomes "user does NOT have role". ## Combining conditions (AND / OR logic) You can combine multiple conditions on different connections leading from the same component: - **AND logic**: Attach multiple conditions to the same connection (or chain conditions in sequence). All must be TRUE for the path to proceed. - **OR logic**: Create separate connections from the same source to the same target, each with a different condition. If any one connection's condition is TRUE, the target action executes. For more complex conditional branching, consider using [gateways](https://ecaguide.org/eca/concepts/gateways/index.md). ## Adding conditions to a model Conditions are not standalone components that sit on the canvas on their own. Instead, they are attached to the **connections** (edges) between events, actions, and gateways. This is an important distinction that newcomers often find surprising. ### Workflow Modeler 1. First, ensure you have an event and at least one action connected by an edge. 1. Click on the **edge** (the line connecting two components). 1. In the side panel, add a condition by selecting from the available condition types. 1. Configure the condition's settings (comparison values, fields to check, etc.). 1. Optionally enable **Negate** to invert the condition logic. You can also use the **Quick-Add** feature: when adding a successor from a node, the popup allows you to insert a condition on the new edge directly. ### BPMN.iO 1. Draw a **sequence flow** (arrow) from an event or action to the next element. 1. Click on the sequence flow arrow. 1. In the configuration panel on the right, select a condition from the dropdown. 1. Configure the condition's settings. 1. Optionally enable negation. Note In BPMN terminology, a condition on a sequence flow is called a "conditional flow". The condition determines whether the flow is followed. ### Classic Modeler 1. When connecting components, the form interface provides a field for adding conditions. 1. Select the condition type and configure its parameters. 1. Use the negate option if needed. ## Tips for working with conditions - **Conditions go on connections, not nodes**: This is the most common point of confusion for new users. You do not add a condition as a separate box on the canvas. Instead, you attach it to the arrow/edge between two components. - **Keep conditions simple**: If a condition requires complex logic, consider breaking it into multiple simpler conditions or using [custom events](https://ecaguide.org/eca/concepts/custom_events/index.md) to separate concerns. - **Use negation wisely**: Rather than creating a separate "is not" condition, negate the existing one. - **Test conditions with debugging**: Use the [debugging tools](https://ecaguide.org/eca/debugging/index.md) to verify that conditions evaluate as expected. The logs show which conditions passed and which were skipped. - **Mind token availability**: Conditions often reference tokens. Ensure the token you are checking has been made available by the event or a preceding action. See [Tokens](https://ecaguide.org/eca/concepts/tokens/index.md). # Custom events Custom events are user-defined events that you create and trigger yourself from within ECA models. They allow you to build modular, reusable workflows by breaking complex logic into smaller, self-contained processes. ## What are custom events used for? Custom events serve several important purposes: - **Modularity**: Split large models into smaller, focused models that communicate via custom events. This makes models easier to understand and maintain. - **Looping**: Iterate over lists of items by triggering a custom event for each item. See [Loops](https://ecaguide.org/eca/concepts/loops/index.md). - **Reusability**: Define a process once and trigger it from multiple places. For example, a "send notification" custom event model can be triggered from different models throughout your site. - **Token forwarding**: Pass data between models by forwarding tokens to the custom event. ## Types of custom events ECA provides two types of custom events: Custom event : The basic [Custom event](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) listens for a specific event ID and receives forwarded tokens. It does not carry an entity context by default. Entity-aware custom event : The [Entity-aware custom event](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) works like a standard custom event but also carries a content entity. The entity is always available under the token name `entity` in the receiving model, in addition to any forwarded tokens. ## Triggering custom events Custom events are triggered explicitly using action plugins: Trigger custom event : The [Trigger custom event](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) action fires a custom event with a specified event ID. You can list tokens to forward to the receiving model. Trigger entity-aware custom event : The [Trigger entity-aware custom event](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) action fires an entity-aware custom event, forwarding both the specified entity and any additional tokens. Trigger via Drush : Custom events can also be triggered from the command line using Drush: ```` ``` drush eca:trigger:custom-event my_event_id ``` This is useful for cron jobs, scripts, or manual triggering during development and testing. ```` ## The event ID Every custom event has an **event ID** -- a string that identifies which custom event is being triggered. The event ID is how the triggering action and the listening event are matched. - The event ID can be any string value you choose (e.g. `send_welcome_email`, `process_order`, `notify_admins`). - The event ID is case-sensitive. - Multiple models can listen for the same event ID -- they will all be triggered. ### Empty event IDs An event ID can be left empty. A custom event with an empty event ID acts as a **catch-all**: it responds to every custom event trigger, regardless of the ID used. This can be useful for logging or auditing purposes but should be used with care to avoid unintended processing. ## Forwarding tokens When triggering a custom event, the **Tokens to forward** field specifies which tokens from the current process should be made available in the triggered event's process. - Enter a comma-separated list of token names (without brackets): e.g. `node, user, myValue`. - The tokens will be available in the receiving model under the same names. - For entity-aware custom events, the entity is always forwarded automatically -- you do not need to include it in the tokens list. Common pitfall If tokens appear blank or missing in the custom event's process, the most likely cause is that they were not listed in the "Tokens to forward" field. This is one of the most frequently encountered issues when working with custom events. ## Practical example Consider a model that processes new article nodes and needs to notify all editors: **Model 1: Content created** 1. **Event**: Insert content entity (bundle: article) 1. **Action**: Trigger custom event with ID `notify_editors`, forwarding the token `node` **Model 2: Notify editors** 1. **Event**: Custom event with ID `notify_editors` 1. **Action**: Execute a View returning all users with the "editor" role 1. For each user, send an email using `[node:title]` and `[user:mail]` This separation keeps the content creation model clean and the notification logic reusable. ## Best practices - **Use descriptive event IDs**: Choose clear, meaningful names like `order_completed` rather than vague ones like `event1`. - **Document your custom events**: Since custom events are user-defined, they are not documented automatically. Add comments or notes in your models to explain what each custom event does. - **Forward only what is needed**: Keep the "Tokens to forward" list focused on the tokens the receiving model actually uses. - **Avoid circular triggers**: Be careful not to create situations where model A triggers a custom event handled by model B, which in turn triggers a custom event handled by model A. This can cause infinite loops. # Order of events when entities get saved When working with entity events in ECA, it is crucial to understand the sequence of operations that Drupal performs when an entity is saved. This knowledge helps in choosing the right event for your models and avoiding common pitfalls like infinite loops or data inconsistencies. ## The saving process When an entity is saved, Drupal executes a specific sequence of steps. While the complete process involves many hooks and internal operations, the key events relevant to ECA occur in the following order: 1. [**Initialize content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_fieldvaluesinit/index.md): The entity object is initialized and default field values are populated. 1. [**Presave content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md): This event is triggered before the entity is written to the storage. This is the last chance to modify the entity's properties before they are persisted. 1. **Physical save**: The entity data is written to the database (or other storage). 1. **Insert/Update content entity**: - If the entity is new, the [**Insert content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) event is triggered. - If the entity already existed, the [**Update content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) event is triggered. Other entity lifecycle events Beyond the save process, Drupal also triggers events for other operations on entities: - [**Create content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_create/index.md): Fired when an entity object is first created in memory (before it is saved). - [**Load content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_load/index.md): Fired when an entity is loaded from the database. - [**Validate content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_validate/index.md): Fired during entity validation. - [**Predelete content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_predelete/index.md): Fired before an entity is deleted from the database. - [**Delete content entity**](https://ecaguide.org/plugins/eca/content/events/content_entity_delete/index.md): Fired after an entity has been deleted. ## Best practices ### Modifying the entity being saved If you want to modify the entity that triggered the event (e.g., set a field value based on another field): - **Use the `Presave content entity` event.** - **Do NOT add an action to save the entity.** Since the `Presave` event happens *before* the physical save, any changes you make to the entity object in your ECA model will be automatically included when Drupal proceeds to step 3 (Physical save). Do not save in Presave If you add an action to save the entity within a `Presave` event, you will likely cause an infinite loop or an error, because that save action will trigger the `Presave` event again. In the "Entity: save" action, ensure the "Save entity" option is set to **no** or simply omit the save action if you only modified fields using "Entity: set field value". ### Reacting after save If you need to perform actions that depend on the entity being fully persisted (e.g., sending a notification, creating a related entity, or triggering an external API call): - **Use the `Insert content entity` or `Update content entity` event.** - If you modify the entity in these events and want those changes to persist, you **MUST** explicitly save the entity again. Recursion prevention Be careful when saving an entity within an `Insert` or `Update` event, as this will trigger the save process again (starting from `Presave`). Ensure your model has conditions to prevent infinite loops (e.g., checking if the change has already been applied). ## Related resources - [Entity Events Part 1](https://ecaguide.org/library/test%20models/entity_events_part_1/index.md) — Library model demonstrating entity event behavior - [Entity Events Part 2](https://ecaguide.org/library/test%20models/entity_events_part_2/index.md) — Library model with additional entity event scenarios # Events Events are the starting point of every ECA model. An event represents something that happens on your Drupal site -- a trigger that tells ECA to begin processing. Without at least one event, an ECA model has nothing to respond to. ## What is an event? In Drupal, events are signals dispatched by the system whenever something noteworthy occurs. ECA listens for these signals and, when one matches a model's configuration, starts processing the associated conditions and actions. Think of events as the "when" in the sentence: **"When** *this happens*, check *these conditions*, then do *these actions*." ## Common event categories ECA provides events across many categories. Here are some of the most frequently used: Content events : Triggered when content entities are created, updated, deleted, or viewed. Examples include [Presave content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) and [Insert content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md). For details on entity lifecycle ordering, see [Entity events](https://ecaguide.org/eca/concepts/entity_events/index.md). User events : Triggered by user-related activities such as logging in, logging out, or account creation. Form events : Triggered during form operations -- building, validating, or submitting a form. See [Build form](https://ecaguide.org/plugins/eca/form/events/form_form_build/index.md) for an example. Cron events : Triggered at scheduled intervals when Drupal's cron runs, useful for periodic tasks. Custom events : Events you define yourself, triggered explicitly from within an ECA model using the [Trigger custom event](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) action. See [Custom events](https://ecaguide.org/eca/concepts/custom_events/index.md) for details. Request/response events : Triggered during the HTTP request lifecycle, allowing you to intercept and modify requests or responses. See [Choosing the right request and response events](https://ecaguide.org/eca/tips/request_response_events/index.md). Discovering available events The full list of events available on your site depends on which modules are installed. Browse the [Plugins section](https://ecaguide.org/plugins/index.md) for a comprehensive reference of all events, organised by module. ## How events work in ECA When Drupal dispatches an event, ECA checks whether any enabled models are listening for that event. If a match is found, ECA begins processing: 1. The event fires and ECA receives it. 1. ECA identifies all models subscribed to that event. 1. For each matching model, ECA follows the connections from the event to its successors -- evaluating [conditions](https://ecaguide.org/eca/concepts/conditions/index.md) and executing [actions](https://ecaguide.org/eca/concepts/actions/index.md). A single event can be used in multiple models, and a single model can listen for multiple events. ## Tokens provided by events Most events automatically make certain [tokens](https://ecaguide.org/eca/concepts/tokens/index.md) available for use in subsequent conditions and actions. For example: - **Entity events** provide the related entity as `entity` and also under its type name (e.g. `node`, `user`). - **Form events** provide the form as `form` and `current_form`. - The tokens `user` and `current_user` (the current user entity) are always available regardless of the event type. Refer to each event's documentation page for details on which tokens it provides. ## Adding an event to a model Every ECA model needs at least one event. How you add one depends on which modeler you use: ### Workflow Modeler 1. Open or create a model at **Configuration > Workflow > ECA**. 1. From the toolbar or canvas, add an **Event** node. 1. Select the event type from the categorized list. 1. Configure the event's settings in the side panel (e.g. which content type, which form ID). 1. Connect the event to conditions or actions using edges. ### BPMN.iO 1. Open or create a BPMN.iO model. 1. Click the **Start Event** circle on the canvas (or drag one from the palette). 1. Use the wrench icon to change the event type, then select the ECA event from the configuration panel on the right. 1. Configure the event's settings in the properties panel. 1. Draw sequence flows from the event to subsequent tasks or gateways. ### Classic Modeler 1. Open or create a model using the Classic Modeler. 1. Use the form interface to add an event by selecting from the available event types. 1. Fill in the configuration fields. 1. Connect the event to conditions and actions using the form-based interface. ## Tips for working with events - **Be specific**: Choose the most specific event for your use case. For example, use a content type-specific event rather than a generic "any entity" event to avoid unnecessary processing. - **Mind the execution order**: If multiple models listen for the same event, they all run. Use conditions to guard against unintended side-effects. - **Check token availability**: Before referencing a token in a condition or action, ensure the event (or a preceding action) makes that token available. See [Debugging](https://ecaguide.org/eca/debugging/index.md) for techniques to inspect available tokens at runtime. - **Performance**: Every event subscription adds a small overhead. Disable models you are not actively using. # Gateways ## Current Status (ECA 2.x) **Important**: Gateways are **not fully implemented** in ECA 2.x, this is a work in progress (WiP). The current implementation provides basic functionality but lacks proper BPMN gateway logic. ### Current Behaviour - **Multiple outgoing links**: All paths are processed sequentially in the order they were added; - **Multiple incoming links**: Each incoming link processes everything after the gateway independently; - **No exclusive logic**: Despite being labelled "exclusive gateway" or "x-gateway", a gateway currently behaves like an inclusive gateway; - **Optional condition handling**: Each outgoing path can have explicit conditions, a path without conditions defaults to TRUE and is therefore always open; ## How Gateways Currently Work ### Sequential Processing ``` Event/Action → Gateway → [Path 1] → Actions → [Path 2] → Actions → [Path 3] → Actions ``` All paths execute in sequence, not based on conditions. ### Multiple Inputs When multiple paths flow into a gateway, each arrival triggers separate processing of all subsequent actions. ## Current Use Cases ### 1. Flow Merging Combine multiple event flows into a single processing path: ``` Event A → [Specific prep] ↘ Event B → [Specific prep] → Gateway → [Common processing] Event C → [Specific prep] ↗ Event D → [Specific prep] ↗ ``` **Note**: In the above model, [Common processing] will potentially get executed 4 times if all 4 events are triggered. ### 2. Action Chaining (Alternative to AND Task) Gateways can be used instead of AND tasks for chaining actions when there's only one successor: ``` Action → Gateway → Next Action ``` **Note**: This is equivalent to using an AND task but quicker to implement. ### 3. Conditional Branching (Manual Implementation) For true conditional logic, you must add explicit conditions to each outgoing path: ``` Action → Gateway → [Condition: field > 0] → Path A → [Condition: field ≤ 0] → Path B ``` # Loops ECA does not have a dedicated "loop" element in its modeling palette. However, iterating over a set of items is a common requirement, and ECA provides several approaches to achieve loop-like behavior. ## Iterating over lists with Views The most common pattern for looping in ECA uses a **Views** query combined with a **custom event**: 1. **Execute a View** using the [Views: execute a query](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) action. The View returns a list of entities matching your criteria. 1. For each entity in the result set, ECA automatically triggers a **custom event**, forwarding the current entity as a token. 1. A separate ECA model (or the same model listening for the custom event) processes each entity individually. ``` Event → [Execute View] → for each result → [Custom Event per entity] ↓ [Process single entity] ``` This pattern effectively creates a loop: the View provides the list, and the custom event fires once per item, allowing you to perform actions on each entity. ## Iterating with list operations ECA provides actions for working with lists (arrays) of items: - **List: loop through items** -- iterates over a list token and triggers a custom event for each item. This is the most straightforward loop mechanism. - **List: count items** -- retrieves the number of items in a list, useful for conditional logic based on list size. - **List: add/remove items** -- modifies a list, which can be combined with other patterns for accumulating results. ## Recursive custom events For scenarios where the number of iterations is not known in advance, or where you need conditional looping (similar to a "while" loop in programming), you can use a recursive pattern: 1. An action triggers a [custom event](https://ecaguide.org/eca/concepts/custom_events/index.md) with relevant tokens. 1. The model listening for that custom event performs work and checks a condition. 1. If the condition indicates more iterations are needed, the model triggers the same custom event again with updated tokens. Avoid infinite loops When using recursive custom events, always ensure there is a clear termination condition. An infinite loop will eventually exhaust PHP's execution time or memory limits and may cause your site to become unresponsive. Use a counter token or a clear exit condition, and consider adding a safety limit (e.g. stop after 100 iterations). ## Entity reference traversal When you need to process entities related to a given entity (e.g. all paragraphs in a node, all nodes in a taxonomy term), you can: 1. Use [Entity: load referenced entities](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity_ref/index.md) to retrieve the referenced entities. 1. Iterate over the results using a list loop or Views-based pattern. ## Practical example: send email to all users with a role A common use case is notifying all users who have a specific role: 1. **Event**: Content is created (or any other trigger). 1. **Action**: Execute a View that returns all users with the target role. 1. **Custom event**: Fires once per user found by the View. 1. **Action** (in the custom event model): Send an email to the current user, using tokens from both the original content and the user entity. Token forwarding When using custom events for looping, remember to list all required tokens in the "Tokens to forward" field of the [Trigger custom event](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) action. Without this, the tokens from the original process will not be available inside the loop iteration. ## Performance considerations - **Views-based loops** are efficient for entity-based iteration because they use database queries. - **Recursive loops** add overhead per iteration. Keep the loop body lightweight and avoid deeply nested recursion. - If you need to process a very large number of items, consider using cron-based processing or a queue system to avoid timeout issues. # Permissions There are two main aspects regarding permissions in ECA: permissions required to maintain ECA models, and permissions applied during the execution of those models. ## Maintaining ECA models Permissions for creating, editing and managing ECA models are provided by the [Modeler API](https://www.drupal.org/project/modeler_api) module — a dependency of the ECA UI module. The Modeler API dynamically generates a set of granular permissions for each installed modeler (e.g. BPMN.iO, Workflow Modeler). The most important permissions are: `modeler api collection eca` : View the ECA model collection at `/admin/config/workflow/eca`. `modeler api view eca` : View individual ECA models. `modeler api edit eca` : Create, edit, enable, disable, clone, import and export ECA models. `modeler api delete eca` : Delete ECA models. `modeler api administer eca` : Access the ECA settings page at `/admin/config/workflow/eca/settings`. This is a restricted permission. In addition, there are per-modeler permissions that control which modeler a user may use: `modeler api edit eca with bpmn_io` : Edit ECA models with the BPMN.iO modeler. `modeler api view eca with bpmn_io` : View ECA models rendered by the BPMN.iO modeler. Similar permissions are generated for each additional modeler plugin (e.g. `workflow_modeler`). Further permissions cover metadata editing, context switching, templates, testing and replay: - `modeler api edit metadata eca` — Edit model metadata. - `modeler api switch context eca` — Switch the modeler context. - `modeler api create template eca` — Create ECA templates. - `modeler api edit template eca` — Edit ECA templates. - `modeler api test eca` — Test ECA models. - `modeler api replay eca` — Replay ECA models. Finally, the ECA core module defines one additional permission via its entity type: `administer eca` : Full administrative access to ECA configuration entities. This permission is used by the ECA log view and the External Workflows settings page. ## User permission when executing models All ECA models are processed under the context of the **current user**. This means that all conditions and actions respect the permissions of the user who triggered the event. - **Web requests**: The model executes with the permissions of the currently logged-in user (or Anonymous if not logged in). - **Cron**: Drupal runs cron as the **Anonymous** user (UID 0). Models triggered by the [ECA: Cron](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_cron/index.md) event therefore execute without any authenticated session. - **Drush**: Commands such as `drush cron` or `drush eca:trigger:custom_event` run as **Anonymous** (UID 0) by default, unless the `--uid` option is passed to Drush. If the current user lacks the necessary permissions to perform an action (e.g. publishing content, viewing a specific entity, or executing a View), that action will fail or return incomplete results. ### Global execution user ECA provides a global setting (`eca.settings.user`) that allows **all** model executions to run under a specific user account, regardless of who triggered the event. When this setting is configured (via the ECA settings page at `/admin/config/workflow/eca/settings`): - Every model execution automatically switches to the configured user **before** processing begins. - The original user who triggered the event is available as the `[session_user]` token, so your model can still reference or compare against the real user. - After model execution completes, the user context reverts automatically. This is particularly useful for sites where many models need elevated permissions, avoiding the need to add explicit user-switch actions to every model. ### Switching user context within a model When only certain parts of a model need elevated permissions, you can switch the user context explicitly. ECA provides three actions for this: [User: switch current account](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) : Switch to a specific user by UID. The switch applies only to the **successors** of this action. Once that branch of the model execution completes, the user context automatically reverts to the previous user. This includes any custom events triggered from within the switched context. [User: switch to service user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_service_account/index.md) : Switch to the globally configured **service user** (`eca.settings.service_user`), set on the ECA settings page. This works identically to the regular switch but avoids hard-coding a UID into each model. Using a service user is recommended for portability — the same model can work across different environments without modification. [User: switch back](https://ecaguide.org/plugins/eca/user/actions/eca_switch_back/index.md) : Explicitly switch back to the previous user account before the current branch completes. This is useful when you need to return to the original user context mid-way through a sequence of actions rather than waiting for the automatic revert at the end of the branch. ### Executing Views and queries A common scenario involves using the [Views: Execute query](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) action. Views checks entity access permissions by default, which means: - If the current user (e.g. Anonymous during cron) does not have access to the entities returned by the View, the result set will be empty — even if the entities exist. - View-level access settings such as "Unrestricted" only control who can *run* the View, not which entities are returned. Entity-level access checks still apply unless SQL rewriting is explicitly disabled in the View configuration. **Solution**: Switch the user context to a privileged account before executing the View. Remember to store the original user in a token first if you need to reference it afterwards. Example: Querying a View during cron A model triggered by the ECA cron event needs to load nodes from a View: 1. The model starts as **Anonymous** (UID 0). 1. Add a [User: switch current account](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) action to switch to a user with the necessary permissions. 1. Execute the View — results now include entities the switched user has access to. 1. The user context reverts automatically when the branch completes. If you also need to compare values against the original user, load the current user entity into a token *before* switching. # 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](https://www.drupal.org/project/token) 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](#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 in 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](#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](#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 (DTO), then you can access their (nested) properties just like with the read-only tokens described 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](https://www.drupal.org/project/eca/issues/3348422) which will expose all the implicit tokens from events in the modeler 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](https://ecaguide.org/eca/debugging/index.md) 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](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md), 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](https://ecaguide.org/plugins/eca/form/events/form_form_build/index.md), 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: - [Token: Set value](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Entity: load](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) @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](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) or an [Entity-aware custom event](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) with the [Trigger custom event](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) action or the [Trigger entity-aware custom event](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) 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: 1. A token representing e.g. a node, does not have to be called `node`. Instead, you can call it `currentArticle` or `referencedLocation` 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. 1. When you're looking for token property syntax in the [Token browser](#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 name `node` 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](#making-tokens-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 ecosystem there are many options available to do that: - [Read](https://ecaguide.org/plugins/eca/base/actions/eca_keyvaluestore_read/index.md) and [write](https://ecaguide.org/plugins/eca/base/actions/eca_keyvaluestore_write/index.md) the key/value store - [Read](https://ecaguide.org/plugins/eca/base/actions/eca_keyvalueexpirablestore_read/index.md) and [write](https://ecaguide.org/plugins/eca/base/actions/eca_keyvalueexpirablestore_write/index.md) the expirable key/value store - [Read](https://ecaguide.org/plugins/eca/base/actions/eca_state_read/index.md) and [write](https://ecaguide.org/plugins/eca/base/actions/eca_state_write/index.md) the state - [Read](https://ecaguide.org/plugins/eca/base/actions/eca_privatetempstore_read/index.md) and [write](https://ecaguide.org/plugins/eca/base/actions/eca_privatetempstore_write/index.md) the private temporary store - [Read](https://ecaguide.org/plugins/eca/base/actions/eca_sharedtempstore_read/index.md) and [write](https://ecaguide.org/plugins/eca/base/actions/eca_sharedtempstore_write/index.md) the shared temporary store - [Read](https://ecaguide.org/plugins/eca/config/actions/eca_config_read/index.md) and [write](https://ecaguide.org/plugins/eca/config/actions/eca_config_write/index.md) config - [Get](https://ecaguide.org/plugins/eca/parameters/actions/eca_parameter_get/index.md) and [set](https://ecaguide.org/plugins/eca/parameters/actions/eca_parameter_set/index.md) parameters ## Token Browser While tokens are provided by Drupal core, the token browser is provided by the [Token](https://www.drupal.org/project/token) contrib module and is only available, if that module is installed and enabled. In the context of any ECA modeler, 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](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md): 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](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md): 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](https://ecaguide.org/plugins/eca/base/actions/eca_token_replace/index.md) which resolves that issue such that it replaces tokens up to 5 nesting levels deep. ### Using square brackets in token-enabled fields Since tokens are identified by square brackets, using literal `[` and `]` characters in token-enabled fields can cause unintended token replacement. For example, Tailwind CSS classes like `[&_.label]:hidden` would be misinterpreted as a token reference. See the [Tips & Tricks section on using brackets](https://ecaguide.org/eca/tips/brackets/index.md) for a recommended workaround using custom bracket tokens. ### 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 behavior 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. # ECA Best Practices This section collects recommendations and best practices for building, organizing, and maintaining ECA models. ## Structuring your models One common question when working with ECA is whether to create many small, individual models for each task or to combine related logic into fewer, larger models. ### Individual vs. Combined Models **Recommendation:** Group related functionality into a single model, but keep unrelated logic separate. Prioritize organization and maintainability over theoretical performance concerns. #### Why group related logic? If you have multiple reactions to the same event (e.g., "Presave content"), or a set of events that are logically part of the same workflow (e.g., a "New User Onboarding" process that involves account creation, role assignment, and a welcome email), it makes sense to keep them in one model. This keeps the "story" of that feature in one place, making it easier to understand and maintain. #### Why separate unrelated logic? If you have a model for "User Management" and another for "Article Publishing", keep them separate. This has two benefits: 1. **Organization:** It is easier to find what you are looking for. 1. **Performance:** ECA models are stored as configuration. When an event occurs, ECA loads the models that are listening for that event. By separating unrelated models, you ensure that ECA only loads the configuration necessary for the current context, avoiding unnecessary memory usage and processing overhead. ### Performance Implications While splitting models *can* have a performance benefit by reducing the configuration loaded for any given event, the difference is often negligible for typical sites. **Do not** sacrifice code readability or logical organization for the sake of micro-optimizations. The primary driver for your decision should be: **"Does this structure make it easier for me (and others) to understand and maintain this workflow?"** # Extending ECA ECA is designed to be extensible. Its plugin-based architecture means that modules can provide new events, conditions, and actions without modifying ECA itself. ## Ways to extend ECA There are two primary ways to extend ECA's capabilities: ### Install additional modules Many Drupal contrib modules provide ECA plugins out of the box. Installing a module that integrates with ECA immediately makes its events, conditions, and actions available in your models. See [Modules extending ECA](https://ecaguide.org/eca/extend/modules/index.md) for a list of known modules. ECA itself ships with several sub-modules that add support for specific Drupal subsystems (content, forms, users, views, workflows, and more). The [ECA Starterkit recipe](https://ecaguide.org/eca/install/index.md) installs the most commonly used sub-modules automatically. ### Develop custom plugins If no existing module covers your use case, you can develop custom ECA plugins for your site or contribute them back to the community. ECA provides a scaffolding tool via Drush to help you get started quickly. See [Developing plugins](https://ecaguide.org/eca/extend/plugins/index.md) for details. # Modules extending ECA The ECA project maintains a [list of ecosystem modules](https://www.drupal.org/project/eca/ecosystem) on Drupal.org. The sections below organize those modules by type. ## ECA submodules These submodules ship with the [ECA project](https://www.drupal.org/project/eca) itself. ### Providing ECA functionality - ECA Access: Events and actions to control access on entities and fields - [plugins](https://ecaguide.org/plugins/eca/access/index.md) - ECA Base: Base events, conditions and actions - [plugins](https://ecaguide.org/plugins/eca/base/index.md) - ECA Cache: Actions to read, write or invalidate cache items - [plugins](https://ecaguide.org/plugins/eca/cache/index.md) - ECA Config: Config events - [plugins](https://ecaguide.org/plugins/eca/config/index.md) - ECA Content: Content entity events, conditions and actions - [plugins](https://ecaguide.org/plugins/eca/content/index.md) - ECA Content Access: Grant or revoke content access - [plugins](https://ecaguide.org/plugins/eca/content_access/index.md) - ECA Endpoint: Custom HTTP endpoints with ECA - [plugins](https://ecaguide.org/plugins/eca/endpoint/index.md) - ECA File: File actions such as rename and write - [plugins](https://ecaguide.org/plugins/eca/file/index.md) - ECA Form: Form API events, conditions and actions - [plugins](https://ecaguide.org/plugins/eca/form/index.md) - ECA Language: Language-related actions - [plugins](https://ecaguide.org/plugins/eca/language/index.md) - ECA Log: Events and actions for Drupal log messages - [plugins](https://ecaguide.org/plugins/eca/log/index.md) - ECA Migrate: Migrate events - [plugins](https://ecaguide.org/plugins/eca/migrate/index.md) - ECA Misc: Miscellaneous events and conditions from Drupal core and the kernel - [plugins](https://ecaguide.org/plugins/eca/misc/index.md) - ECA Queue: Events, conditions and actions for queued operations - [plugins](https://ecaguide.org/plugins/eca/queue/index.md) - ECA Render: Render-related actions - [plugins](https://ecaguide.org/plugins/eca/render/index.md) - ECA User: User events, conditions and actions - [plugins](https://ecaguide.org/plugins/eca/user/index.md) - ECA Views: Execute and export Views query results within ECA - [plugins](https://ecaguide.org/plugins/eca/views/index.md) - ECA Workflow: Content entity workflow actions - [plugins](https://ecaguide.org/plugins/eca/workflow/index.md) ### Others - ECA UI: Provide access to ECA in Drupal's admin UI - ECA Development: Provides Drush commands and code generators for developers ## Drupal contrib modules Separate projects on Drupal.org that extend ECA with extra events, conditions or actions. Where auto-generated plugin documentation exists, the list links to the corresponding plugin pages. ### Integrations with other Drupal modules - [Commerce ECA](https://www.drupal.org/project/commerce_eca) - [plugins](https://ecaguide.org/plugins/eca/commerce/index.md) - [CrowdSec](https://www.drupal.org/project/crowdsec) - [plugins](https://ecaguide.org/plugins/eca/crowdsec/index.md) - [DANSE](https://www.drupal.org/project/danse) - [plugins](https://ecaguide.org/plugins/eca/danse/index.md) - [Drupal Remote Dashboard](https://www.drupal.org/project/drd) - [plugins](https://ecaguide.org/plugins/drd/index.md) - [Easy Email](https://www.drupal.org/project/easy_email) - [plugins](https://ecaguide.org/plugins/easy_email/index.md) - [ECA Commerce](https://www.drupal.org/project/eca_commerce) - [ECA Condition](https://www.drupal.org/project/eca_condition) - [ECA Entity Print](https://www.drupal.org/project/eca_entity_print) - [plugins](https://ecaguide.org/plugins/eca/entity_print/index.md) - [ECA Entity Share](https://www.drupal.org/project/eca_entity_share) - Client - [plugins](https://ecaguide.org/plugins/eca/entity_share_client/index.md) - Server - [plugins](https://ecaguide.org/plugins/eca/entity_share_server/index.md) - [ECA Expression Language](https://www.drupal.org/project/eca_expression_language) - [ECA External Workflows](https://www.drupal.org/project/eca_external_workflows) - [ECA Field Widget Actions](https://www.drupal.org/project/eca_field_widget_actions) - [ECA Flag](https://www.drupal.org/project/eca_flag) - [plugins](https://ecaguide.org/plugins/eca/flag/index.md) - [ECA Group](https://www.drupal.org/project/eca_group) - [ECA Helper](https://www.drupal.org/project/eca_helper) - [plugins](https://ecaguide.org/plugins/eca/helper/index.md) - [ECA HTML Parser](https://www.drupal.org/project/eca_html_parser) - [ECA Inline Entity Form](https://www.drupal.org/project/eca_inline_entity_form) - [ECA Maestro](https://www.drupal.org/project/eca_maestro) - [ECA Metatag](https://www.drupal.org/project/eca_metatag) - [plugins](https://ecaguide.org/plugins/eca/metatag/index.md) - [ECA Mustache](https://www.drupal.org/project/eca_mustache) - [ECA Parameters](https://www.drupal.org/project/eca_parameters) - [plugins](https://ecaguide.org/plugins/eca/parameters/index.md) - [ECA Project Browser](https://www.drupal.org/project/eca_project_browser) - [plugins](https://ecaguide.org/plugins/eca/project_browser/index.md) - [ECA Remote Request](https://www.drupal.org/project/eca_remote_request) - [ECA Report](https://www.drupal.org/project/eca_report) - [ECA Simplenews](https://www.drupal.org/project/eca_simplenews) - [ECA Site Building Tools](https://www.drupal.org/project/eca_site_building) - [ECA Starterkit](https://www.drupal.org/project/eca_starterkit) - [ECA State Machine](https://www.drupal.org/project/eca_state_machine) - [plugins](https://ecaguide.org/plugins/eca/state_machine/index.md) - [ECA Tamper](https://www.drupal.org/project/eca_tamper) - [plugins](https://ecaguide.org/plugins/eca/tamper/index.md) - [ECA Telegram](https://www.drupal.org/project/eca_tg) - [ECA Tool](https://www.drupal.org/project/eca_tool) - [ECA Tour](https://www.drupal.org/project/eca_tour) - [ECA Twilio action](https://www.drupal.org/project/eca_twilio_action) - [ECA Variety Pack](https://www.drupal.org/project/eca_variety_pack) - [ECA VBO](https://www.drupal.org/project/eca_vbo) - [plugins](https://ecaguide.org/plugins/eca/vbo/index.md) - [ECA Views data export](https://www.drupal.org/project/eca_views_data_export) - [plugins](https://ecaguide.org/plugins/eca/views_data_export/index.md) - [ECA Webform](https://www.drupal.org/project/eca_webform) - [plugins](https://ecaguide.org/plugins/eca/webform/index.md) - [ECA Webprofiler](https://www.drupal.org/project/eca_webprofiler) - [ECA: Google](https://www.drupal.org/project/eca_google) - [ECA: HubSpot](https://www.drupal.org/project/eca_hubspot) - [ECA: Zoom](https://www.drupal.org/project/eca_zoom) - [GitLab API v4](https://www.drupal.org/project/gitlab_api) - [plugins](https://ecaguide.org/plugins/eca/gitlab_api/index.md) - [Group Actions](https://www.drupal.org/project/group_action) - [plugins](https://ecaguide.org/plugins/group_action/index.md) - [Maestro](https://www.drupal.org/project/maestro) - [Mail Actions](https://www.drupal.org/project/mail_action) - [Mautic ECA](https://www.drupal.org/project/mautic_eca) - [plugins](https://ecaguide.org/plugins/mautic_eca/index.md) - [Message Notify ECA](https://www.drupal.org/project/message_notify_eca) - [Orchestration](https://www.drupal.org/project/orchestration) - [plugins](https://ecaguide.org/plugins/orchestration_eca/index.md) - [Push Framework](https://www.drupal.org/project/push_framework) - [plugins](https://ecaguide.org/plugins/push_framework/index.md) - [Salesforce ECA Integration](https://www.drupal.org/project/salesforce_eca) - [Token ECA Alter](https://www.drupal.org/project/token_eca_alter) - [Workflow ECA](https://www.drupal.org/project/workflow_eca) ### AI and LLM integrations - [AI Integration - ECA](https://www.drupal.org/project/ai_integration_eca) - [plugins](https://ecaguide.org/plugins/ai_integration_eca/index.md) - [Augmentor AI](https://www.drupal.org/project/augmentor) - [plugins](https://ecaguide.org/plugins/augmentor/index.md) - [Prompt AI](https://www.drupal.org/project/prompt) - [plugins](https://ecaguide.org/plugins/prompt/index.md) ### Communication integrations - [BlueSky Integration](https://www.drupal.org/project/bsky) - [plugins](https://ecaguide.org/plugins/bsky/index.md) - [DiscordPHP](https://www.drupal.org/project/discord_php) - [DiscordPHP - Echo](https://www.drupal.org/project/discord_php_echo) - [DiscordPHP Recipe - Echo](https://www.drupal.org/project/discord_php_recipe_echo) - [ECA Kafka connection](https://www.drupal.org/project/eca_kafka) ### External services and APIs - [Bookable Calendar](https://www.drupal.org/project/bookable_calendar) - [HTTP Client Manager](https://www.drupal.org/project/http_client_manager) - [HTTP Client Manager Issuu Oembed](https://www.drupal.org/project/http_client_manager_issuu_oembed) - [Shelly](https://www.drupal.org/project/shelly) - [Solcast](https://www.drupal.org/project/solcast) ### Other related projects - [ECA Context](https://www.drupal.org/project/eca_context) - [ECA Drush](https://www.drupal.org/project/eca_drush) - [IOC: Internet Of Contributors](https://www.drupal.org/project/ioc) - [Laravel Helpers](https://www.drupal.org/project/laravel_helpers) - [Laravel Process](https://www.drupal.org/project/laravel_process) - [SPARC](https://www.drupal.org/project/sparc) ## Known issues ### Variety of workflow modules Currently 3 modules provide workflows, states and transitions: - Workflows: provided by Drupal core - Workflow: contrib module - State machine All three provide similar functionality, but they have nothing to do with each other. This can be confusing when reporting issues about ECA modeling around workflows. Always state which workflow system you are using. Mixing events, conditions and actions from different workflow systems in the same ECA model can cause unexpected results or errors. Pay extra attention when you enable more than one workflow module. # Developing plugins ## Code generator Want to jumpstart ECA plugin development? Try the `eca_development` sub-module (not for use on production sites): ``` drush en eca_development drush gen eca-event # Generates files for ECA event support. drush gen eca-condition # Generates an ECA condition plugin. drush gen eca-action # Generates an ECA action plugin. ``` ## Developer guidelines Let's collect guidelines for developers, so that the code structure becomes more clear and stays consistent. - Default values in plugins: they can be defined in `::defaultConfiguration()` which will pre-set the fields in the UI. But since the user could remove those values, it still may be possible that the `::access` and `::execute` methods could find empty values, even though the default already had a value in them. Therefore, configuration values need to be checked in all use cases and set to default if expectation isn't met. # Tips & Tricks This section contains practical tips and tricks for working with ECA. These are solutions to common challenges that users encounter when building ECA models. ## Available tips - [Using square brackets without unintended token replacement](https://ecaguide.org/eca/tips/brackets/index.md) - How to use `[` and `]` characters in your ECA configuration without ECA treating them as token references. - [Choosing the right request and response events](https://ecaguide.org/eca/tips/request_response_events/index.md) - How to pick the correct kernel event for redirects, response modifications, and route-based logic, and how to avoid caching pitfalls. - [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/index.md) - How to build auto-refreshing regions, click-to-load fragments, and dynamic responses with the `eca_htmx` module, without writing JavaScript. # Using square brackets without unintended token replacement ## The problem ECA uses square brackets `[` and `]` to identify [tokens](https://ecaguide.org/eca/concepts/tokens/index.md). When ECA encounters text like `[something]`, it attempts to replace it with the corresponding token value. If the token does not exist, the content inside the brackets is removed, resulting in an empty string. This becomes a problem when you need to use square brackets for purposes other than tokens. A common example is using CSS frameworks like [Tailwind CSS](https://tailwindcss.com/), which uses bracket notation for arbitrary values. For instance, a class like `[&_.cf-form-label]:tw-hidden` would be interpreted by ECA as a token reference, and the content between the brackets would be stripped away. The same issue arises in any context where square brackets are part of the intended value, such as: - Tailwind CSS arbitrary value classes (e.g. `[&_.label]:hidden`) - Form element machine names containing brackets (e.g. `wrapper][form][submit`) - Regular expressions or other syntax that uses square brackets ## The solution The recommended approach is to define two custom tokens that resolve to the bracket characters themselves: | Token | Value | | ----------------- | ----- | | `[bracket:open]` | `[` | | `[bracket:close]` | `]` | Since token replacement is **not recursive** by default, the resulting bracket characters will not trigger further token replacement. This means you can safely use these tokens wherever you need literal bracket characters. For example, instead of writing: ``` [&_.cf-form-label]:tw-hidden ``` You would write: ``` [bracket:open]&_.cf-form-label[bracket:close]:tw-hidden ``` After token replacement, this produces the intended result: `[&_.cf-form-label]:tw-hidden`. ## Making bracket tokens available globally Rather than defining these tokens in every model that needs them, you can make them available globally using the [ECA token generate event](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_token_generate/index.md). This event fires before ECA processes tokens for any model, making the bracket tokens available everywhere on your site. ### Step-by-step setup 1. **Create a new ECA model** and give it a descriptive name, such as "Global Tokens". 1. **Add the event** [ECA token generate event](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_token_generate/index.md) as the trigger. In the "Name of token" field, enter `bracket:*` to react to all tokens in the `bracket` group. 1. **Add the first action** [Token: set value](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) and configure it: - **Token name**: `bracket:open` - **Token value**: `[` 1. **Add a second action** [Token: set value](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) and configure it: - **Token name**: `bracket:close` - **Token value**: `]` 1. **Save and enable** the model. Once this model is active, the tokens `[bracket:open]` and `[bracket:close]` are automatically available in the token browser and in text fields within any ECA model on your site. You only need to set this up once. Tip This approach of using the ECA token generate event to define utility tokens can be extended to other global tokens you might need across your models. Consider adding other commonly used special characters or values to the same model. # Building HTMX-powered interfaces with ECA [HTMX](https://htmx.org/) lets you build dynamic, interactive interfaces by adding attributes to HTML elements, without writing JavaScript. Drupal core ships HTMX and a small integration layer, and the `eca_htmx` module exposes that integration to ECA models. This lets you build auto-refreshing regions, click-to-load fragments, and dynamic responses entirely from the modeler. This guide explains what Drupal core provides, which ECA plugins map to those features, and how to combine them into working patterns. ## How HTMX works in Drupal HTMX is a declarative markup system. You add `data-hx-*` attributes to an element, and the HTMX JavaScript library turns them into AJAX requests that swap the response into the page. For example, an element with `data-hx-get="/clock"` and `data-hx-trigger="every 1s"` polls `/clock` once a second and replaces its own content with the response. Drupal core provides three building blocks: - **The `core/drupal.htmx` library** — the HTMX runtime plus Drupal glue that re-attaches Drupal behaviors to swapped-in content and loads any new CSS and JavaScript the response requires. - **The minimal response renderer** — when a request is marked as an HTMX request, core returns only the page's main content wrapped in a bare HTML document instead of the full themed page (header, blocks, and footer are omitted). The minimal response also carries an `X-Robots-Tag: noindex` header so the fragment is not indexed by search engines. - **HTMX request and response headers** — HTMX sends `HX-*` request headers (such as `HX-Request` and `HX-Trigger`) and honors `HX-*` response headers (such as `HX-Redirect` and `HX-Trigger`) to coordinate client behavior. The `eca_htmx` module builds entirely on these core building blocks. It never ships its own HTMX JavaScript, and it produces all attributes and headers through core's HTMX helper, so the markup stays consistent with the rest of Drupal. ## The two ways to request a minimal response A recurring source of confusion is that core offers **two** independent ways to get the minimal (main-content-only) response, and they take effect at different stages of the request lifecycle. They are not interchangeable. `_htmx_route` route option : Set on a **route** while routes are being built. Any request to a route carrying this option returns the minimal response. Use the [HTMX: mark route](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_set_route/index.md) action, which reacts to the [Alter route](https://ecaguide.org/plugins/eca/misc/events/routing_alter/index.md) event. `_wrapper_format=drupal_htmx` query parameter : Added to an individual **request** at runtime. Only that request returns the minimal response. Use the [HTMX: minimal response](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_minimal_response/index.md) action, or let the polling and element actions add it automatically through their **only main content** option. Which one to use Mark the **route** when you control the route and want every request to it to return a fragment (for example, a dedicated endpoint that only ever serves a fragment). Mark the **request** when you want a specific interaction to fetch a fragment from a route that otherwise renders a full page. ## The plugins ### Building HTMX elements [HTMX: render element](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_element/index.md) : Builds a single element carrying the HTMX attributes you configure: the request method and URL, the trigger, the swap strategy, the target and select selectors, and options such as a confirmation dialog, indicators, pushed URLs, and request values. Use this for click-to-load fragments, infinite scroll, and similar interactions. [HTMX: poll region](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_poll/index.md) : A specialized element that polls a URL on an interval and swaps in the response. Use it for content that refreshes on its own, such as a clock, a status indicator, or a notification count. The **only main content** option is enabled by default, so the polled URL automatically returns a fragment. Both actions render an element. Place them in a block, an entity display, or any other render context, and they attach `core/drupal.htmx` automatically. ### Reacting to HTMX requests [HTMX: is request](https://ecaguide.org/plugins/eca/htmx/conditions/eca_htmx_is_request/index.md) : A condition that is true when the current request is an HTMX request. Use it to branch a model so that it builds a fragment for HTMX requests and a full page otherwise. [HTMX: compare request value](https://ecaguide.org/plugins/eca/htmx/conditions/eca_htmx_header/index.md) : A condition that compares a value from the current HTMX request — such as the target element, the trigger, or the current URL — against an expected value. The same request information is available as tokens, so you can read the HTMX target or trigger anywhere a token is accepted. ### Shaping HTMX responses [HTMX: set response header](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_response_header/index.md) : Sets any of the HTMX `HX-*` response headers on the current response, for example `HX-Redirect` to redirect the client, `HX-Trigger` to fire a client-side event, or `HX-Retarget` to change where the response is swapped. The `HX-Location` header supports its full form (source, event, handler, target, swap, values, headers, and select). Because this action shapes the response, it reacts to a response event such as the [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) event or an [ECA endpoint response](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md). ## Serving fragments with ECA endpoints The natural source for an HTMX fragment is an [ECA endpoint](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md). An endpoint gives you a URL that an ECA model fully controls: the model builds the response content and can attach HTMX response headers. Because you control the endpoint route, its response is already a fragment — no full page chrome to strip — and it pairs naturally with a polling region or a click-to-load element that points at it. ## Common patterns ### Auto-refreshing region 1. **Event**: any event that builds a render element, such as a block build. 1. **Action**: [HTMX: poll region](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_poll/index.md) — set the URL to an endpoint that returns the fragment, and the interval in seconds. The region polls the endpoint and swaps in the response on every interval. Leave **only main content** enabled so the endpoint returns a fragment. ### Click-to-load content 1. **Event**: any event that builds a render element. 1. **Action**: [HTMX: render element](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_element/index.md) — set the method to `GET`, the URL to the fragment endpoint, the trigger to `click`, and the target to the element that should receive the content. ### Serve a fragment from an endpoint 1. **Event**: [ECA endpoint response](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md) — define the endpoint path. 1. **Action**: [Set response content](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_content/index.md) — build the fragment markup. 1. **Action** (optional): [HTMX: set response header](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_response_header/index.md) — fire a client-side event with `HX-Trigger`, for example to notify other parts of the page that the fragment refreshed. ### Turn an existing route into a fragment 1. **Event**: [Alter route](https://ecaguide.org/plugins/eca/misc/events/routing_alter/index.md). 1. **Action**: [HTMX: mark route](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_set_route/index.md) — set the route name (a `*` wildcard is supported) to mark as an HTMX route. Every request to a marked route then returns the minimal response. ## Related resources - [HTMX: render element](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_element/index.md) — action reference - [HTMX: poll region](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_poll/index.md) — action reference - [HTMX: mark route](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_set_route/index.md) — action reference - [HTMX: minimal response](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_minimal_response/index.md) — action reference - [HTMX: set response header](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_response_header/index.md) — action reference - [HTMX: is request](https://ecaguide.org/plugins/eca/htmx/conditions/eca_htmx_is_request/index.md) — condition reference - [HTMX: compare request value](https://ecaguide.org/plugins/eca/htmx/conditions/eca_htmx_header/index.md) — condition reference - [Choosing the right request and response events](https://ecaguide.org/eca/tips/request_response_events/index.md) — guide - [HTMX Blocks](https://ecaguide.org/library/use%20case/htmx_blocks/index.md) — library example # Choosing the right request and response events When building ECA models that react to incoming HTTP requests — for example to perform redirects, enforce access rules, or modify response headers — it is essential to pick the correct kernel event. The Symfony HTTP kernel dispatches several events during the lifecycle of every request, and each one fires at a different stage. Using the wrong event is the most common source of problems such as redirects working only once, status messages disappearing after a redirect, or models that never fire on cached pages. This guide walks through the available kernel events in the order they are dispatched, explains when to use each one, and highlights the caching pitfalls that trip up many users. ## The HTTP request lifecycle Drupal uses Symfony's HTTP kernel, which dispatches events in the following order for a normal, successful request: 1. **[Start dispatching request](https://ecaguide.org/plugins/eca/misc/events/kernel_request/index.md)** (`kernel.request`) 1. **[Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/index.md)** (`kernel.controller`) 1. **[Controller arguments have been resolved](https://ecaguide.org/plugins/eca/misc/events/kernel_controller_arguments/index.md)** (`kernel.controller_arguments`) 1. **[Controller does not return a Response instance](https://ecaguide.org/plugins/eca/misc/events/kernel_view/index.md)** (`kernel.view`) — only when the controller returns a render array rather than a full Response object 1. **[Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md)** (`kernel.response`) 1. **[Response for request created](https://ecaguide.org/plugins/eca/misc/events/kernel_finish_request/index.md)** (`kernel.finish_request`) 1. **[Response was sent](https://ecaguide.org/plugins/eca/misc/events/kernel_terminate/index.md)** (`kernel.terminate`) Two additional events fire only on the error path: - **[Uncaught exception](https://ecaguide.org/plugins/eca/misc/events/kernel_exception/index.md)** (`kernel.exception`) - **[Exception status code](https://ecaguide.org/plugins/eca/misc/events/kernel_exception_status_code/index.md)** — fires on routing exceptions that produce 4xx or 5xx status codes (available since ECA 2.1.0) ## Choosing the right event The table below summarizes typical use cases and the recommended event for each. | Use case | Recommended event | Why | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Redirect a page request | [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) | Works reliably with all caches enabled, for both anonymous and authenticated users. | | Display a message and redirect | [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) | Messages stored in the session survive the redirect when this event is used. | | Check the current route and act on it | [Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/index.md) | Fires even when pages are served from the dynamic page cache. | | Set or modify response headers | [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) | The response object is available at this stage. | | Redirect 403 pages to login | [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) | Inspect the response status code and redirect accordingly. See the library model [Redirect 403 to Login Page](https://ecaguide.org/library/use%20case/redirect_403_to_login_page/index.md). | | Redirect unpublished content | [Start dispatching request](https://ecaguide.org/plugins/eca/misc/events/kernel_request/index.md) | Intercept the request before the controller runs. See the library model [Redirect unpublished](https://ecaguide.org/library/use%20case/redirect_unpublished/index.md). | | Perform expensive background work | [Response was sent](https://ecaguide.org/plugins/eca/misc/events/kernel_terminate/index.md) | Runs after the response has been delivered to the client, so it does not delay the page load. | | Custom error handling | [Uncaught exception](https://ecaguide.org/plugins/eca/misc/events/kernel_exception/index.md) | Allows you to log, redirect, or display a custom error page. | ## Caching and kernel events Drupal ships with two page-level cache layers that can prevent kernel events from firing at all: `Page Cache` : The **Internal Page Cache** module (`page_cache`) caches full responses for anonymous users. When a cached response exists, the kernel short-circuits the entire request and **none of the kernel events fire** — not even `kernel.request`. `Dynamic Page Cache` : The **Internal Dynamic Page Cache** module (`dynamic_page_cache`) caches rendered responses but still dispatches early kernel events. However, once a response is cached, later events in the chain may receive a cached response rather than a freshly built one. ### Which events fire on cached pages? | Event | Fires with Page Cache (anonymous)? | Fires with Dynamic Page Cache? | | ----------------------------- | ---------------------------------- | --------------------------------------- | | `kernel.request` | No | Yes | | `kernel.controller` | No | Yes | | `kernel.controller_arguments` | No | Yes | | `kernel.view` | No | Sometimes (only if the controller runs) | | `kernel.response` | No | Yes | | `kernel.finish_request` | No | Yes | | `kernel.terminate` | No | Yes | Page Cache bypasses everything When the Internal Page Cache module serves a cached page for an anonymous user, **no ECA model will fire**. If your model must react to every anonymous request, you have two options: 1. Use the [Page Cache Kill Switch](https://ecaguide.org/plugins/eca/cache/actions/eca_page_cache_kill_switch/index.md) action in an earlier model to disable page caching for specific routes. 1. Uninstall the Internal Page Cache module (not recommended for production sites with high traffic). ### The Dynamic Page Cache pitfall Even with the Dynamic Page Cache enabled, not all events behave the same way. A common pitfall: - **`kernel.request`** fires before the controller is resolved. This makes it tempting for redirects, but the core redirect action (`system.action.redirect`) sets the redirect on the **response** event internally. When a cached response is served, the redirect set during `kernel.request` may not take effect because the cached response overwrites it. - **`kernel.controller`** fires after the controller is found, even when the Dynamic Page Cache eventually serves a cached response. This makes it a reliable choice for inspecting the current route. - **`kernel.response`** fires every time a response is being prepared, whether from cache or freshly built. This makes it the most reliable event for redirects and response modifications. Rule of thumb For redirects, prefer the **Response created** event (`kernel.response`). For route-based logic that does not modify the response, the **Controller found** event (`kernel.controller`) is a safe choice. ## Common patterns ### Redirect based on a route 1. **Event**: [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) 1. **Condition**: [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) — compare to the route name, e.g. `entity.taxonomy_term.canonical` 1. **Action**: [Redirect to URL](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) This pattern works reliably with all caches enabled, for both anonymous and authenticated users. ### Redirect and display a status message 1. **Event**: [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) 1. **Condition**: [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) 1. **Action**: Display a message (e.g. using the Drupal messenger) 1. **Action**: [Redirect to URL](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) Note Status messages are stored in the user's session. For anonymous users without a session, messages set before a redirect will be lost. This is standard Drupal behavior and not specific to ECA. ### Inspect or modify the response 1. **Event**: [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) 1. **Action**: [Set headers](https://ecaguide.org/plugins/eca/helper/actions/eca_helper_header_set/index.md) — add or modify response headers such as `Cache-Control`, `X-Robots-Tag`, or custom headers. ### React to a specific route without modifying the response 1. **Event**: [Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/index.md) 1. **Condition**: [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) 1. **Action**: any action that does not depend on the response object (e.g. logging, setting tokens, triggering custom events) See the library model [Route test](https://ecaguide.org/library/simple/route_test/index.md) for a working example. ## Why "View Content Entity" is not the right event for redirects The **View Content Entity** event might seem like the natural choice when you want to react to a user visiting a node or taxonomy term page. However, this event fires whenever the entity is **rendered**, which can happen multiple times per request (e.g. in views, blocks, or embedded references) and is not limited to the canonical page of that entity. Additionally, because this event fires during the rendering phase, any redirect action triggered by it is processed too late — the response may already be cached by the Dynamic Page Cache, causing the redirect to work only on the first uncached request. Use the **Response created** or **Controller found** events instead, combined with a [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) condition to target the correct page. ## Related resources - [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) — event reference - [Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/index.md) — event reference - [Start dispatching request](https://ecaguide.org/plugins/eca/misc/events/kernel_request/index.md) — event reference - [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) — condition reference - [Page Cache Kill Switch](https://ecaguide.org/plugins/eca/cache/actions/eca_page_cache_kill_switch/index.md) — action reference - [Redirect 403 to Login Page](https://ecaguide.org/library/use%20case/redirect_403_to_login_page/index.md) — library example - [Redirect unpublished](https://ecaguide.org/library/use%20case/redirect_unpublished/index.md) — library example - [Route test](https://ecaguide.org/library/simple/route_test/index.md) — library example # Debugging ECA processes models in the background in response to events. Because there is no visible output during processing, finding out why a model does not behave as expected requires dedicated debugging tools. ECA provides three approaches, each suited to different situations: - **Visual debug mode** (ECA 3.1+) -- interactive, detailed, built into the modeler UI. - **Database logging** -- lightweight, works with every ECA version. - **Webprofiler** (ECA 2+) -- per-request isolation of ECA log messages. ## Visual debug mode *Requires ECA 3.1 or later and a modeler that supports it. Currently only the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) supports visual debugging.* Visual debug mode collects detailed processing data -- including the full list of available tokens and their values at every step -- and displays the results directly in the modeler UI. ### Enable debug mode There are two ways to activate it: Manually : Go to **Administration > Configuration > Workflow > ECA > Settings** (`/admin/config/workflow/eca/settings`) and enable the **Debug mode** checkbox. Via the test button : In the Workflow Modeler, click the **Test** button on an event. This temporarily enables debug mode for the duration of the test. If debug mode was not already on, ECA enables it automatically and disables it again when the test completes or when the configured timeout expires. Performance impact Debug mode has a significant performance impact because it normalizes and stores token data on every ECA processing run. Do not leave it enabled on production sites. See [Troubleshooting](https://ecaguide.org/eca/troubleshooting/index.md) for instructions on disabling it via Drush if the UI is not accessible. ### Debug settings The following settings are available at **Administration > Configuration > Workflow > ECA > Settings** or via `drush state:set`: Debug data depth : Maximum recursion depth for normalizing token data (default: `5`, minimum: `2`). Higher values expose more detail in nested data structures but increase processing time. Debug data cases : Maximum number of history cases stored per event (default: `10`, minimum: `1`). Each case captures one complete processing run. Older cases are discarded when the limit is reached. Debug test timeout : Timeout in seconds for test-triggered debug mode (default: `300`, i.e. 5 minutes). When the test button auto-enables debug mode and the test is not completed or canceled within this duration, debug mode is automatically disabled. Set to `0` to disable the timeout. ### Using the test button 1. Open a model in the Workflow Modeler. 1. Click the **Test** button on an event node. 1. Trigger the event (for example, save a node or submit a form). 1. The modeler polls for results and displays the processing history, including all tokens and their values at each step. If you close the browser tab before the test completes, the timeout (default: 5 minutes) ensures debug mode does not stay on indefinitely. ### Disabling debug mode from the command line If debug mode is stuck or the UI is not accessible: ``` drush state:set _eca_internal_debug_mode 0 ``` See the [Troubleshooting](https://ecaguide.org/eca/troubleshooting/index.md) page for the full list of debug-related state keys. ## Database logging This method works with all ECA versions and does not require a specific modeler. **Requirements:** - Enable the **Database Logging** (`dblog`) module. - Go to **Administration > Configuration > Workflow > ECA > Settings** (`/admin/config/workflow/eca/settings`) and set the log level to **Debug**. ECA writes detailed messages about every processing step to the database log. Review them at the dedicated ECA log page: **Administration > Configuration > Workflow > ECA > Log** (`/admin/config/workflow/eca/log`) Messages appear in chronological order. Each message describes the processing step and lists the tokens (name and value) available at that point. Tokens are the key Most unexpected behavior in ECA models comes from a missing token or a token present under a different name. The token list in each log message tells you exactly what is available at every step. This approach is straightforward to enable and works well for simple models. For complex setups with many concurrent models, the volume of log messages can make it harder to isolate specific processing runs. Reset the log level After debugging, set the ECA log level back to a less verbose setting (for example, **Warning** or **Error**). Leaving it at **Debug** generates a large number of log messages that can affect site performance. ## Webprofiler This method provides per-request isolation of ECA log messages, making it easier to debug specific page requests. **Requirements:** - For ECA 1: - Install the Webprofiler module: `composer require drupal/webprofiler` - Enable the **Webprofiler** module. - For ECA 2 and later: - Install the ECA Webprofiler module: `composer require drupal/eca_webprofiler` - Enable the **ECA Webprofiler** module and its dependencies. - Go to **Administration > Configuration > Development > Devel > Webprofiler** (`/admin/config/development/devel/webprofiler`) and enable the ECA toolbar item. The database logging module is not required when using Webprofiler. There is no need to change the ECA log level either. As soon as ECA is enabled as a toolbar item in the Webprofiler settings, debugging data is collected automatically. The Webprofiler toolbar appears at the bottom of the screen with information about the latest page request: Click the ECA icon to open a page with the ECA log messages for that single request: The messages are the same as in database logging, but isolated per request. This makes it much easier to trace ECA processing on pages where multiple models or events are involved. # Troubleshooting ## The site is not working anymore It may happen, that an ECA model contains instructions, that may break your site. As ECA tries catching all the known risks automatically, this shouldn't happen really, but you never know. However, should you find yourself in such a situation, it's not too easy to get yourself out of it again. The UI may not be accessible any longer and disabling a model with e.g. drush won't work either then, because that bootstraps the Drupal site as well before it could change the config. Only for situations like that, ECA provides an easy kill-switch: ``` $settings['eca_disable'] = TRUE; ``` Put this into your `settings.php` somewhere and ECA will be completely disabled. Users with the permission `administer eca` will be notified with a message on the screen, to make them aware that ECA is actually not working. In this disabled mode you can fix the model, that's causing the issue by either editing that model or you can disable or delete that model. When done, remove that line from your settings again and ECA will continue working right away. ## Debug mode causes slow performance ECA's debug mode collects detailed processing data on every request. If debug mode is left enabled unintentionally, it can cause significant performance degradation -- particularly on sites with many entity operations or JSON:API requests. A common scenario: you click the **Test** button in the Workflow Modeler, which temporarily enables debug mode. If you close the browser tab or lose connectivity before the test completes, debug mode stays on indefinitely. Starting with ECA 3.1, a configurable timeout (default: 5 minutes) automatically disables test-triggered debug mode, but manually enabled debug mode has no timeout. ### Check if debug mode is active ``` drush state:get _eca_internal_debug_mode ``` A return value of `1` means debug mode is active. ### Disable debug mode ``` drush state:set _eca_internal_debug_mode 0 ``` ### All debug-related state keys You can view and change all debug settings with `drush state:get` and `drush state:set`: | State key | Default | Description | | ---------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `_eca_internal_debug_mode` | `0` (off) | Master toggle for debug mode. Set to `1` to enable, `0` to disable. | | `_eca_internal_debug_data_depth` | `5` | Maximum recursion depth for normalizing token data. Higher values provide more detail but increase processing time. Minimum: `2`. | | `_eca_internal_debug_data_cases` | `10` | Maximum number of history cases stored per event. Each case captures one complete processing run. Minimum: `1`. | | `_eca_internal_debug_test_timeout` | `300` | Timeout in seconds for test-triggered debug mode. Set to `0` to disable the timeout. | | `_eca_internal_debug_test_started` | not set | Timestamp recorded when the test button auto-enables debug mode. Delete this value to cancel a stuck test timeout: `drush state:delete _eca_internal_debug_test_started`. | These settings are also available in the UI at **Administration > Configuration > Workflow > ECA > Settings** (`/admin/config/workflow/eca/settings`). ## Can't save ECA model due to a missing plugin When saving a model, ECA is validating the config entity to make sure that no obviously wrong configuration gets stored. This will refuse to save, e.g. if a model is missing a value for a required field or if it contains a plugin for either an event, a condition or an action, that no longer exists. A missing plugin happens rarely. It could actually happen, if a module which provides one or more plugins gets updated and no longer delivers all the previous plugins any longer. Another scenario could be with dynamically created plugins that get derived from some other config values. In such cases, plugins could either disappear or simply get renamed, which is the equivalence to a plugin, that no longer exists, i.e. not under the original name. In such a situation, it won't be possible to save the ECA model any longer, not even after removing or replacing the object in the model. This is caused by the way Drupal core's configuration validation is being implemented where the original config entity gets validated once before updating it as well. To circumvent this issue, you can manually add a query argument to the URL in the browser to temporarily turn off the model validation when saving the updated version once. So, if the URL to edit your model looks like this: ``` https://www.example.com/admin/config/workflow/eca/process_someid/edit ``` You should add the query argument `eca_validation=off` to it: ``` https://www.example.com/admin/config/workflow/eca/process_someid/edit?eca_validation=off ``` Then you can make your corrections to the model and save it. From then on, you no longer need that query argument anymore. ## Workflow transition sometimes not recognized When using the workflows module from Drupal core together with content moderation, then the event [Workflow: state transition](https://ecaguide.org/plugins/eca/workflow/events/workflow_transition/index.md) may not recognize the changed state, because the pre-save method in Drupal core may load the wrong revision under certain circumstances. There is a fix in the works for Drupal 11, but it's not yet committed and is unlikely to be back ported to Drupal 10 or even 9. As a workaround, Drupal core can be patched with [this file](https://git.drupalcode.org/project/drupal/-/merge_requests/3599.diff) and which is discussed and provided by [this Drupal issue](https://www.drupal.org/project/drupal/issues/3346430). ## Using non-stable releases If you want to use non-stable releases (e.g. RC, beta or dev), then you should configure your root project to allow that by configuring the minimum acceptable stability with e.g. `composer config minimum-stability beta` for accepting beta releases. Without this, Composer may run into dependency issues. # Frequently Asked Questions This page collects answers to common questions raised in the [ECA support issue queue](https://www.drupal.org/project/issues/eca?categories=4). Each entry links back to the original discussion for full context. ______________________________________________________________________ ## Tokens and field names ### How do I reference multi-value field deltas without conflicting with token replacement? ECA's token system uses square brackets (`[` and `]`) as delimiters. When you need to target a specific delta in a multi-value field, the traditional Drupal bracket notation (e.g. `field_skills[0][target_id]`) clashes with token replacement. **Use dot notation instead:** ``` field_skills.0.target_id ``` To use a dynamic delta from a token (e.g. inside a loop), write: ``` field_skills.[my_delta_token].target_id ``` This avoids the token system misinterpreting your brackets as token references. Tip Dot notation for field deltas is supported in ECA 2.1.x and 3.x. [Original discussion (d.o #3565516)](https://www.drupal.org/project/eca/issues/3565516) ______________________________________________________________________ ### How do I use literal square brackets in ECA field values? If you need literal square brackets in a value — for example Tailwind CSS utility classes like `[&_.cf-form-label]:tw-hidden` or render array keys — ECA will attempt to replace anything inside `[...]` as a token. **Workaround:** Define two global tokens that output literal brackets: 1. Use the **"ECA token generate"** custom event so the tokens are available site-wide. 1. In that event's model, use **"Token: set value"** to create: - Token name: `bracket:open` with value `[` - Token name: `bracket:close` with value `]` 1. Then use `[bracket:open]` and `[bracket:close]` wherever you need literal brackets. Since token replacement is not recursive by default, the brackets will be output literally after the first replacement pass. [Original discussion (d.o #3468841)](https://www.drupal.org/project/eca/issues/3468841) ______________________________________________________________________ ### What does the `:value` suffix do on tokens? When you use a token like `[entity:nid]`, ECA may return a typed data object rather than a plain scalar value. If you need the raw value (e.g. to pass an entity ID as a string to a queue worker or another action), append `:value`: ``` [entity:nid:value] ``` This is particularly important when forwarding tokens to queue workers or comparing values. [Original discussion (d.o #3545797)](https://www.drupal.org/project/eca/issues/3545797) ______________________________________________________________________ ## Entities ### Can I use "Entity: delete" with Paragraphs and other entity types? Yes. The **Entity: delete** action works with *any* entity type, not just nodes. This includes Paragraphs, Media, Taxonomy Terms, Users, and custom entity types. Warning When triggering entity operations from Drush or cron, the current user is anonymous. Ensure the anonymous role has the necessary permissions, or switch the user context within your ECA model. [Original discussion (d.o #3562153)](https://www.drupal.org/project/eca/issues/3562153) ______________________________________________________________________ ### How do I load a User entity by username or email? When using **Entity: Load** with properties, the property values field expects **YAML object syntax with curly braces**: ``` {name: "testuser"} ``` or: ``` {mail: "user@example.com"} ``` Writing `name: "testuser"` without the braces will not be parsed correctly. [Original discussion (d.o #3556182)](https://www.drupal.org/project/eca/issues/3556182) ______________________________________________________________________ ### What does "Defined by token" mean in the "Entity: Load" action? The **"Load entity from"** dropdown in the "Entity: Load" action has a "Defined by token" option. This does *not* mean you provide the entity ID via a token. Instead, it means the **loading mode itself** is determined dynamically by the `eca_token_load_entity_from` token. To load an entity by type and ID, select **"Entity type and ID"** in the dropdown and provide the entity ID in the "Entity ID" field (which supports tokens). [Original discussion (d.o #3550157)](https://www.drupal.org/project/eca/issues/3550157) ______________________________________________________________________ ### How do I clone a node and modify a field before saving? Use this three-step pattern: 1. **Entity: clone** — creates an unsaved copy of the entity. 1. **Entity: set field value** — modify the field(s) you need to change on the cloned entity. 1. **Entity: save** — persist the modified clone. This pattern works well with Views Bulk Operations (VBO): select entities in a view, trigger a VBO action, and let ECA handle the clone-modify-save workflow. [Original discussion (d.o #3540136)](https://www.drupal.org/project/eca/issues/3540136) ______________________________________________________________________ ### Why do I get "Entity: set field value" vs "Entity: get field value" confused? A common mistake when creating a new entity and setting its properties: - **"Entity: set field value"** — *writes* a value to a field. Use this to assign a title, body, or any other field value. - **"Entity: get field value"** — *reads* a value from a field into a token. When targeting the entity, use the **token name** you assigned when creating it (e.g. `newpromotion`), not the entity type machine name. [Original discussion (d.o #3558803)](https://www.drupal.org/project/eca/issues/3558803) ______________________________________________________________________ ## Conditions ### How do I check for multiple user roles? The **"User has role(s)"** condition allows selecting only a single role. This is by design. To check for multiple roles (e.g. Manager OR Employee OR Admin), use **multiple conditions connected with gateways**: - For **OR logic**: connect multiple "User has role" conditions to separate branches from an exclusive gateway, each leading to the same action. - For **AND logic**: chain conditions as successors so all must pass before the action executes. Tip See the [Combined Conditions](https://ecaguide.org/library/simple/combined_conditions/index.md) library model for a working example of AND/OR condition patterns. [Original discussion (d.o #3558514)](https://www.drupal.org/project/eca/issues/3558514) ______________________________________________________________________ ### How do I check if a value is contained in a list of values? If you need to check whether the current node's ID is in a specific list of IDs (similar to an "IN" operator), use the **"Compare two scalar values"** condition with the `contains` operator: - **Value 1:** `,26122,26119,26567,` (the list, wrapped with leading and trailing commas) - **Value 2:** `,[node:id],` (the value to find, also wrapped in commas) - **Operator:** `contains` The leading and trailing commas prevent false positives (e.g. ID `261` matching inside `26122`). Note The `eca_list_contains` condition is designed for token-based lists, not inline comma-separated values. For hardcoded lists, the scalar comparison approach above is more reliable. [Original discussion (d.o #3556083)](https://www.drupal.org/project/eca/issues/3556083) ______________________________________________________________________ ## Forms ### How do I populate a multi-value entity reference field? The approach depends on the widget type and timing: **On form build** (before the user sees the form): : Use **"Form field: set default value"** with just the entity ID. **After an Ajax event** (e.g. after user interaction): : Use **"Form field: set value"** with the format `Entity Name (ID)` for autocomplete widgets. **For multiple values**, use a loop with a delta counter and dot notation: ``` field_entity_reference.0.target_id field_entity_reference.1.target_id ``` Tip **Tags-style**, **Select**, and **Checkboxes** widgets accept multiple values more easily than the single-value **Autocomplete** widget. Consider switching the widget type if multi-value population is a core requirement. [Original discussion (d.o #3565511)](https://www.drupal.org/project/eca/issues/3565511) ______________________________________________________________________ ### How do I distinguish "Add more" Ajax clicks from real form submissions? The form validation event fires for every form submission, including when a user clicks "Add another item" on a multi-value field. To distinguish real form saves from Ajax requests: Check the **`[entity:nid]`** token immediately after the submission event. If the entity has not been saved yet (because it is an Ajax request rather than a real save), the NID will not be available. Use this to skip validation logic during "Add more" clicks. [Original discussion (d.o #3564434)](https://www.drupal.org/project/eca/issues/3564434) ______________________________________________________________________ ### How do I add a custom submit button and handle its click? Adding a custom button (e.g. "Cancel") requires two separate events: 1. **"Build form" event** — use the **"Form: Add Submit Button"** action to add the button to the form. 1. **"Form submit" event** — use the **"Form: Compare Triggered Submission"** condition to detect which button was clicked. Warning Use the **"Build form"** event, not "After Build form", to add the button. The "After Build" event fires too late for button additions. [Original discussion (d.o #3539759)](https://www.drupal.org/project/eca/issues/3539759) ______________________________________________________________________ ## Events and redirects ### Why does my redirect not work with the "Response created" event? The **"Response created"** (`kernel.response`) event fires after Drupal has already started building the response. At that point, it is too late to replace the response with a redirect. Use the **"Controller found to handle request"** (`kernel.controller`) event instead. This event fires early enough for the **"Redirect to URL"** action to take effect. Note The `kernel.response` event still works for modifying response headers or for handling 403/404 error pages, because in those cases the response is being built differently. [Original discussion (d.o #3566396)](https://www.drupal.org/project/eca/issues/3566396) ______________________________________________________________________ ### Can I prevent entity deletion from a pre-delete event? No. By the time the **pre-delete** event fires, Drupal is already committed to the delete operation. Only throwing an exception would stop it, which is not a clean approach. **Alternative:** Use access control to conditionally hide the delete link. For example, use the **"ECA Views Field"** action with the **"Views field"** event: evaluate each entity row in a View to determine whether deletion should be allowed, and show or hide the delete link accordingly. [Original discussion (d.o #3537710)](https://www.drupal.org/project/eca/issues/3537710) ______________________________________________________________________ ### How do I use "Views: Set filter value" with "Views: Execute query"? These two actions cannot be chained sequentially. ECA is **event-driven**: when you execute a View via the **"Views: Execute query"** action, Drupal dispatches the **"Views: Pre Build"** event for that View. Create a separate event listener for the **"Views: Pre Build"** event and use **"Views: Set filter value"** there. This way, the filter is applied automatically whenever the View is built — whether triggered by your "Execute query" action or by any other mechanism. Tip Use the `filter_id` value matching the machine name of the exposed filter field in your View configuration. [Original discussion (d.o #3488727)](https://www.drupal.org/project/eca/issues/3488727) ______________________________________________________________________ ## Queue tasks ### How do I pass data to a queue worker? When using the **"Enqueue task"** action, do not use the `task_value` field to pass entity IDs or other data. Instead: 1. Use the **"Tokens to forward"** field — enter the token *name* (without brackets), e.g. `prelim_nid`. 1. That token will be available in the queue worker model under the same name. 1. For entity field values, use the `:value` suffix to get the raw scalar value: `[entity:nid:value]` rather than `[entity:nid]`. Warning Queue workers run as the **anonymous user**. Ensure the anonymous role has the necessary permissions to load and manipulate the entities your worker needs to access. [Original discussion (d.o #3545797)](https://www.drupal.org/project/eca/issues/3545797) ______________________________________________________________________ ## Workflow and content moderation ### Why does the workflow transition event not fire on re-publishing? When a content-moderated entity is published, moved to draft, and then published again, the **"Workflow: state transition"** event may not recognize the second transition. This is a [known Drupal core bug](https://www.drupal.org/project/drupal/issues/2839195) where `$entity->original` loads the latest *default* revision instead of the latest *revision*, making the from/to states appear identical. **Workaround:** Apply the patch from [Drupal core issue #3346430](https://www.drupal.org/project/drupal/issues/3346430) or the community-provided ECA patch from the discussion linked below. This issue is also documented in the [Troubleshooting](https://ecaguide.org/eca/troubleshooting/index.md) page. [Original discussion (d.o #3417834)](https://www.drupal.org/project/eca/issues/3417834) ______________________________________________________________________ ## Upgrading ### How do I upgrade from ECA 2.x to 3.x? When upgrading ECA and its modeler modules (e.g. bpmn_io) to version 3.x, you must follow the [ECA 3.0.0 release notes](https://www.drupal.org/project/eca/releases/3.0.0) upgrade procedure. ECA 3 includes update scripts that enable the required new modules. Danger Do not upgrade bpmn_io to 3.x without also upgrading ECA to 3.x. The modeler depends on services that moved in the ECA 3.x architecture (e.g. `modeler_api.service`), and upgrading one without the other will cause fatal errors. [Original discussion (d.o #3571323)](https://www.drupal.org/project/bpmn_io/issues/3571323) # Modeler # ECA Modeler ECA allows you to use different modelers to create and manage your workflows. These modelers are plugins that implement the [Modeler API](https://www.drupal.org/project/modeler_api). ## Workflow Modeler (Recommended) The [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) is the recommended visual editor for ECA. It provides a modern, React-based interface with features like execution replay, live testing, and an improved user experience. ## Classic Modeler The [Classic Modeler](https://ecaguide.org/modeler/eca_cm/index.md) is the original modeler built into ECA. It allows editing models directly within the Drupal administrative interface using standard Drupal forms. ## BPMN Modelers ECA also supports BPMN-based modelers: - [BPMN.iO](https://ecaguide.org/modeler/bpmn/bpmn_io/index.md): A popular web-based BPMN modeler. - [Camunda](https://ecaguide.org/modeler/bpmn/camunda/index.md): The Camunda desktop modeler (Deprecated). # Workflow Modeler (Recommended) The [Workflow Modeler](https://www.drupal.org/project/modeler) provides a modern, React-based visual workflow editor for Drupal. Built on React Flow, it offers a professional drag-and-drop interface for creating and editing workflow models — complete with real-time configuration, execution replay, live testing, and full keyboard accessibility. This modeler is the recommended editor for ECA and is the successor to the BPMN.iO modeler. ## Key Features - **Visual Workflow Editing**: Drag-and-drop nodes onto an infinite canvas, connect them with edges, and configure components through dynamic forms. - **Quick-Add**: Context-aware popup for adding successors (actions, gateways, conditions) directly from nodes or edges. - **Execution Replay**: Load past execution data, step through it visually, and inspect token values. - **Live Testing**: Trigger workflow execution directly from the modeler. - **Export**: Export models as Drupal Recipes, archives, JSON, or SVG. - **Accessibility**: WCAG AA compliant with full keyboard navigation and screen reader support. - **Dark Mode**: Built-in support for light and dark themes. ## Installation Install the module using Composer: ``` composer require drupal/modeler drush en modeler ``` If you are using ECA, ensure you have the `eca_ui` module enabled as well: ``` composer require drupal/eca drush en eca eca_ui ``` ## Usage Once installed, the Workflow Modeler activates automatically when editing models: 1. Navigate to the ECA configuration page (**Configuration > Workflow > ECA**). 1. Click **Add** to create a new model, or **Edit** on an existing model. 1. The modeler interface will open, allowing you to design your workflow. For detailed documentation, visit the [official Workflow Modeler documentation](https://project.pages.drupalcode.org/modeler/). ## Screenshots # BPMN Modelers ECA supports the BPMN (Business Process Model and Notation) standard for defining workflows. While the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) is the recommended editor, you can also use other BPMN-compatible tools. # BPMN Modeler FAQ This page collects answers to common questions raised in the [BPMN.iO support issue queue](https://www.drupal.org/project/issues/bpmn_io?categories=4). Each entry links back to the original discussion for full context. ______________________________________________________________________ ## How do I upgrade from BPMN.iO 2.x to 3.x? BPMN.iO 3.x depends on ECA 3.x. Upgrading the modeler without upgrading ECA will cause a fatal error: ``` "bpmn_io.prepare_components" has a dependency on a non-existent service "modeler_api.service" ``` **Always upgrade ECA and BPMN.iO together** and follow the [ECA 3.0.0 release notes](https://www.drupal.org/project/eca/releases/3.0.0) upgrade procedure. ECA 3 includes update scripts that enable the required new modules. [Original discussion (d.o #3571323)](https://www.drupal.org/project/bpmn_io/issues/3571323) ______________________________________________________________________ ## The status message overlaps the modeler UI in Claro When using the Claro admin theme, the "Model saved" status message may appear in the centre of the screen, cannot be dismissed, and never disappears. This is caused by a CSS selector mismatch: the bpmn_io JavaScript that makes messages dismissible uses a selector that does not match Claro's message markup. **Solution:** Switch to the **Gin** admin theme, where message handling is already optimized. Claro is being deprecated in Drupal core in favor of Gin. [Original discussion (d.o #3544342)](https://www.drupal.org/project/bpmn_io/issues/3544342) # Support field types - textfield - textarea - checkbox - checkboxes - radios - select # BPMN.iO BPMN.iO is a modeler for ECA and is fully integrated into Drupal's administration user interface. It provides a graphical user interface that allows to define models using the BPMN ([Business Process Model and Notation](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) standard. [Try BPMN.iO online](https://demo.bpmn.io/) ## Links - [Examples](https://github.com/bpmn-io/bpmn-js-examples) - [Awesome List](https://github.com/bpmn-io/awesome-bpmn-io) - [Viewer html](https://github.com/bpmn-io/bpmn-js-examples/blob/master/url-viewer/index.html) - [Viewer with simulation](https://bpmn-io.github.io/bpmn-js-token-simulation/viewer.html) ## Used components | Library | Version | | ----------------------------------------------------------------------------------------------------------------------- | ------- | | [@bpmn-io/a11y](https://github.com/bpmn-io/a11y/blob/main/CHANGELOG.md) | 0.1.0 | | [@bpmn-io/element-template-chooser](https://github.com/bpmn-io/element-template-chooser/blob/master/CHANGELOG.md) | 1.1.1 | | [@bpmn-io/element-templates-validator](https://github.com/bpmn-io/element-templates-validator/blob/master/CHANGELOG.md) | 2.23.0 | | [@bpmn-io/properties-panel](https://github.com/bpmn-io/properties-panel/blob/master/CHANGELOG.md) | 3.47.0 | | [@camunda/element-templates-json-schema](https://github.com/camunda/element-templates-json-schema) | 0.12.1 | | [bpmn-auto-layout](https://github.com/bpmn-io/bpmn-auto-layout/blob/main/CHANGELOG.md) | 1.3.0 | | [bpmn-js](https://github.com/bpmn-io/bpmn-js/blob/master/CHANGELOG.md) | 18.19.0 | | [bpmn-js-color-picker](https://github.com/bpmn-io/bpmn-js-color-picker/blob/master/CHANGELOG.md) | 0.7.2 | | [bpmn-js-element-templates](https://github.com/bpmn-io/bpmn-js-element-templates/blob/master/CHANGELOG.md) | 2.27.0 | | [bpmn-js-properties-panel](https://github.com/bpmn-io/bpmn-js-properties-panel/blob/master/CHANGELOG.md) | 5.60.0 | | [bpmn-moddle](https://github.com/bpmn-io/bpmn-moddle/blob/master/CHANGELOG.md) | 9.0.4 | | [camunda-bpmn-moddle](https://github.com/camunda/camunda-bpmn-moddle/blob/master/CHANGELOG.md) | 7.0.1 | | [diagram-js](https://github.com/bpmn-io/diagram-js/blob/master/CHANGELOG.md) | 15.18.1 | | [diagram-js-minimap](https://github.com/bpmn-io/diagram-js-minimap/blob/master/CHANGELOG.md) | 5.3.0 | | [jquery](https://github.com/jquery/jquery) | 3.7.1 | | [min-dash](https://github.com/bpmn-io/min-dash) | 4.2.3 | # Installation To download the module with composer use the following command: ``` composer require drupal/bpmn_io ``` **Note:** if you want to use non-stable releases (e.g. RC, beta or dev), then you should configure your root project to allow that by configuring the minimum acceptable stability with e.g. `composer config minimum-stability beta` for accepting beta releases. Without this, composer may run into dependency issues. Enable the module(s) in the admin ui of your site (`/admin/modules`) or with drush: ``` drush en bpmn_io ``` # Usage ## Add a new model 1. In the Manage administrative menu, navigate to Configuration > Workflow > ECA (/admin/config/workflow/eca). A page appears where existing models are listed. 1. Click on *Add new BPMN.iO model*. The BPMN.iO modeler appears. 1. On the right-hand side of the BPMN.iO modeler interface you will find a form to configure the currently selected business process element (click on arrows beside the label to show or hide the form input elements): - **Name**: The name of your model. - **ID**: generated automatically by default. - **Version tag**: version of your model. - **Executable**: uncheck to disable the model. - **Documentation**: - Click *Save*. ## Keyboard Shortcuts When the focus is inside the BPMN canvas, there is support for the following shortcuts: | Function | Shortcut | | -------------- | ------------- | | Undo | ctrl + Z | | Redo | ctrl + Y | | Select All | ctrl + A | | Copy | ctrl + C | | Paste | ctrl + V | | Find | ctrl + F | | Scrolling | ctrl + Arrows | | Direct Editing | E | | Hand Tool | H | | Lasso Tool | L | | Space Tool | S | # Camunda Modeler Deprecated The Camunda Modeler integration is deprecated. We recommend using the [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) which runs directly within Drupal and offers a superior, integrated experience. ### Camunda BPMN Camunda BPMN provides a user interface that allows to export templates for events, conditions and actions from Drupal to the [Camunda Modeler](https://camunda.com/products/camunda-platform/modeler/) desktop application and to import BPMN files created in Camunda Modeller into Drupal. [Camunda Modeller](https://camunda.com/products/camunda-platform/modeler/) is a desktop application for designing automated processes using the BPMN standard. # Installation To download the module with composer use the following command: ``` composer require drupal/camunda ``` **Note:** if you want to use non-stable releases (e.g. RC, beta or dev), then you should configure your root project to allow that by configuring the minimum acceptable stability with e.g. `composer config minimum-stability beta` for accepting beta releases. Without this, composer may run into dependency issues. Enable the module(s) in the admin ui of your site (`/admin/modules`) or with drush: ``` drush en camunda ``` # Usage TODO: export templates, import and update models, etc. # Classic Modeler The Classic Modeler is the original, basic modeler integrated into ECA. It allows for creating and editing models using standard Drupal form elements within the administrative interface. While the new [Workflow Modeler](https://ecaguide.org/modeler/workflow/index.md) is recommended for its visual capabilities and advanced features, the Classic Modeler remains available for users who prefer a form-based approach or for environments where visual editing is not feasible. [Project Page](https://www.drupal.org/project/eca_cm) # Classic Modeler FAQ This page collects answers to common questions raised in the [ECA Classic Modeler support issue queue](https://www.drupal.org/project/issues/eca_cm?categories=4). Each entry links back to the original discussion for full context. ______________________________________________________________________ ## What are "Successors" and how do they work? If you are coming from the Rules module, the concept of **successors** may be unfamiliar. In ECA, successors define the execution chain — they connect events, conditions and actions into a processing flow. A successor is a link consisting of: - One configured **action** (required) - One configured **condition** (optional) The event triggers first. Its successors are the actions that should execute next. Each action can in turn have its own successors, forming a chain. If a successor link includes a condition, the action only executes when that condition returns true. ``` Event → [Condition?] → Action 1 → [Condition?] → Action 2 → ... ``` Note Conditions do not have their own successors. They are attached to the successor link between two elements (an event-to-action or action-to-action connection). [Original discussion (d.o #3302674)](https://www.drupal.org/project/eca_cm/issues/3302674) ______________________________________________________________________ ## How do I combine multiple conditions with AND logic? To require that **all** conditions pass before an action executes, chain them as successive links. Each successor link can have one condition, so chaining multiple links effectively ANDs them: ``` Event → [Condition A] → Action (no-op) → [Condition B] → Action (no-op) → [Condition C] → Final Action ``` Alternatively, use the combined conditions pattern documented in the [library](https://ecaguide.org/library/simple/combined_conditions/index.md). Tip For **OR logic**, connect multiple branches from an exclusive gateway, each with its own condition, leading to the same target action. [Original discussion (d.o #3320234)](https://www.drupal.org/project/eca_cm/issues/3320234) # Plugins # Plugins Here we are going to describe and explain all known ECA plugins. # AI Integration - ECA ## Installation ``` composer require drupal/ai_integration_eca drush pm:install ai_integration_eca ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **AI Integration - ECA** from there. # Chat Run text through the AI chat model. ## Fields `Model` : The applicable model for this operation type. `Token input` : The data input for AI. Please provide the token name only, without brackets. `Token result` : The response from AI will be stored into the token result field to be used in future steps. Please provide the token name only, without brackets. `Specific configuration for the model` : Some models require specific configuration settings, like temperature, voice or response_format.\ The "profile" helps set the behavior of the LLM response. You can change/influence how it response by adjusting the system prompt. Eg. ```` ``` system_name: system system_prompt: you are a helpful assistant ``` ```` `Prompt` : Enter your text here. When submitted, AI will generate a response from its Chats endpoint. Based on the complexity of your text, AI traffic, and other factors, a response can sometimes take up to 10-15 seconds to complete. Please allow the operation to finish. Be cautious not to exceed the requests per minute quota (20/Minute by default), or you may be temporarily blocked. `Schema` : Provide an optional schema for the output. # Embedding Generate a text embedding from an input. ## Fields `Model` : The applicable model for this operation type. `Token input` : The data input for AI. Please provide the token name only, without brackets. `Token result` : The response from AI will be stored into the token result field to be used in future steps. Please provide the token name only, without brackets. `Specific configuration for the model` : Some models require specific configuration settings, like temperature, voice or response_format. # Moderation Determine if a piece of text violates any usage policies. ## Fields `Model` : The applicable model for this operation type. `Token input` : The data input for AI. Please provide the token name only, without brackets. `Token result` : The response from AI will be stored into the token result field to be used in future steps. Please provide the token name only, without brackets. # Speech to Text Process an audio file through the AI speech-to-text endpoint. ## Fields `Model` : The applicable model for this operation type. `Token input` : The data input for AI. Please provide the token name only, without brackets. `Token result` : The response from AI will be stored into the token result field to be used in future steps. Please provide the token name only, without brackets. `Specific configuration for the model` : Some models require specific configuration settings, like temperature, voice or response_format. # Text to Speech Run text through the AI text-to-speech model. ## Fields `Model` : The applicable model for this operation type. `Token input` : The data input for AI. Please provide the token name only, without brackets. `Token result` : The response from AI will be stored into the token result field to be used in future steps. Please provide the token name only, without brackets. `Specific configuration for the model` : Some models require specific configuration settings, like temperature, voice or response_format. # AI Integration - ECA: Agents ## Installation ``` composer require drupal/ai_integration_eca drush pm:install ai_integration_eca_agents ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **AI Integration - ECA: Agents** from there. # AI: Trigger Agent Triggers an AI Agent. ## Fields `AI Agent` : The AI Agent to trigger.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_ai_trigger_agent_agent* `Instructions` : The instructions, which should run.\ This field supports tokens. # Augmentor ## Installation ``` composer require drupal/augmentor drush pm:install augmentor ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Augmentor** from there. # Augmentor content block Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *block_content* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor comment Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *comment* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor order Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_order* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor order item Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_order_item* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor product Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor product attribute value Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product_attribute_value* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor product variation Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product_variation* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor store Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_store* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor contact message Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *contact_message* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor email Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *easy_email* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor flagging Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *flagging* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor group Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *group* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor group relationship Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *group_relationship* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor media item Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *media* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal content block Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *block_content* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal comment Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *comment* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal order Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_order* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal order item Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_order_item* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal product Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal product attribute value Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product_attribute_value* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal product variation Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_product_variation* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal store Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *commerce_store* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal contact message Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *contact_message* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal email Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *easy_email* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal flagging Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *flagging* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal group Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *group* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal group relationship Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *group_relationship* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal media item Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *media* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal content item Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal Paragraph Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *paragraph* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal profile Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *profile* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal shortcut link Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *shortcut* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal taxonomy term Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *taxonomy_term* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Minimal submission Available since: unknown ## Fields `Source Field 1` `Source Field 2` `Source Field 3` `Source Field 4` `Source Field 5` `Source Field 6` `Source Field 7` `Source Field 8` `Source Field 9` `Source Field 10` `Target Field 1` `Response key to use 1` `Target Field 2` `Response key to use 2` `Target Field 3` `Response key to use 3` `Target Field 4` `Response key to use 4` `Target Field 5` `Response key to use 5` `Target Field 6` `Response key to use 6` `Target Field 7` `Response key to use 7` `Target Field 8` `Response key to use 8` `Target Field 9` `Response key to use 9` `Target Field 10` `Response key to use 10` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor content item Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor Paragraph Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *paragraph* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor profile Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *profile* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor shortcut link Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *shortcut* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor taxonomy term Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *taxonomy_term* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Augmentor submission Available since: unknown ## Fields `Source fields` `Advance targeting` `Augmentor` `Action over target field` `Text Format` `Explode separator` : Split augmentor response into an array using this separator. `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # BlueSky Integration ## Installation ``` composer require drupal/bsky drush pm:install bsky ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **BlueSky Integration** from there. # BlueSky: Add Facets Available since: unknown Add facets to a Post object. Facets create links for handles, hashtags, and URLs. ## Fields `Post` : A previously created Post object. # BlueSky: Add Image Available since: unknown Add an image to a Post object. ## Fields `Post` : A previously created Post object. `Image` : Path to an image to upload to BlueSky, attached to the Post. `Alt Text` : Alt text to attach to the image. # BlueSky: Create Post Available since: unknown Create a Post object to send to BlueSky. ## Fields `Message` : The message that will be displayed on the post. `Name of response token` : The response value will be loaded into this specified token. You can access [token_name:body] raw response, [token_name:json] when return is valid json, [token_name:headers], [token_name:status], [token_name:client_error] > 0 when has problem. Please provide the token name only, without brackets. # BlueSky: Send Post Available since: unknown Send a Post object to BlueSky. ## Fields `Post` : The Post to send to BlueSky. `Name of response token` : The response value will be loaded into this specified token. Please provide the token name only, without brackets. # Commerce Product ## Installation ``` composer require drupal/commerce drush pm:install commerce_product ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Commerce Product** from there. # Publish selected product Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. # Unpublish selected product Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. # Content Moderation ## Installation ``` drush pm:install content_moderation ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Content Moderation** from there. # Change moderation state of Content block ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *block_content* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Email Available since: unknown ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *easy_email* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Group Available since: unknown ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *group* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Media Available since: unknown ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *media* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Content ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Profile Available since: unknown ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *profile* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change moderation state of Taxonomy term ## Fields `Workflow` `workflow_submit` `Entity` : Provide the token name of the *taxonomy_term* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Drupal core No separate installation is required. # Redirect to URL ## Fields `URL` : The URL to which the user should be redirected. This can be an internal URL like /node/1234 or an external URL like https://example.com. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Display a message to the user ## Fields `Message` : The message to be displayed to the current user. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Send email ## Fields `Recipient email address` : You may also use tokens: [node:author:mail], [comment:author:mail], etc. Separate recipients with a comma. `Subject` : The subject of the message. `Message` : The message that should be sent. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Publish content block ## Fields `Entity` : Provide the token name of the *block_content* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish comment ## Fields `Entity` : Provide the token name of the *comment* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish product Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. # Publish product variation Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product_variation* that this action should operate with. Please provide the token name only, without brackets. # Publish group Available since: unknown ## Fields `Entity` : Provide the token name of the *group* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish media item Available since: unknown ## Fields `Entity` : Provide the token name of the *media* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish custom menu link ## Fields `Entity` : Provide the token name of the *menu_link_content* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish content item ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish Paragraph Available since: unknown ## Fields `Entity` : Provide the token name of the *paragraph* that this action should operate with. Please provide the token name only, without brackets. # Publish URL alias ## Fields `Entity` : Provide the token name of the *path_alias* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Publish profile Available since: unknown ## Fields `Entity` : Provide the token name of the *profile* that this action should operate with. Please provide the token name only, without brackets. # Publish taxonomy term ## Fields `Entity` : Provide the token name of the *taxonomy_term* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish content block ## Fields `Entity` : Provide the token name of the *block_content* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish comment ## Fields `Entity` : Provide the token name of the *comment* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish product Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product* that this action should operate with. Please provide the token name only, without brackets. # Unpublish product variation Available since: unknown ## Fields `Entity` : Provide the token name of the *commerce_product_variation* that this action should operate with. Please provide the token name only, without brackets. # Unpublish group Available since: unknown ## Fields `Entity` : Provide the token name of the *group* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish media item Available since: unknown ## Fields `Entity` : Provide the token name of the *media* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish custom menu link ## Fields `Entity` : Provide the token name of the *menu_link_content* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish content item ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish Paragraph Available since: unknown ## Fields `Entity` : Provide the token name of the *paragraph* that this action should operate with. Please provide the token name only, without brackets. # Unpublish URL alias ## Fields `Entity` : Provide the token name of the *path_alias* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Unpublish profile Available since: unknown ## Fields `Entity` : Provide the token name of the *profile* that this action should operate with. Please provide the token name only, without brackets. # Unpublish taxonomy term ## Fields `Entity` : Provide the token name of the *taxonomy_term* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Drupal Remote Dashboard ## Installation ``` composer require drupal/drd drush pm:install drd ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Drupal Remote Dashboard** from there. # List and render blocks Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Cron Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Download a database dump Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # DNS lookup for all domains Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_host* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Change domain, protocol and port of a domain Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Move domain to a different core Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Enable all domains Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_core* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Receive domains Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_core* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Download a file Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Error Logs Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Flush Cache Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Info Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # JobScheduler Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # List Cores Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # List Domains Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # List Hosts Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Maintenance Mode Available since: 4.1.0 ## Fields `Mode` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Execute PHP Available since: 4.1.0 ## Fields `PHP Code` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Ping Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Get installed projects Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Check status for all projects Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Update Projects Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_core* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Show Logs of Update Projects Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_core* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Lock a project release Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Unlock a project release Available since: 4.1.0 ## Fields `Terms` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Get a session URL Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Run update.php Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Update Translations Available since: 4.1.0 ## Fields `Terms` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # User Credentials Available since: 4.1.0 ## Fields `User ID` `User name` `Password` `Status` `Entity` : Provide the token name of the *drd_domain* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # ECA for DRD ## Installation ``` composer require drupal/drd drush pm:install drd_eca ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA for DRD** from there. # DRD: Action finished Available since: 4.1.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:drd_action_id]` | The ID of the DRD action. | | `[event:entity]` | The entity the action deals with. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a DRD (Drupal Remote Dashboard) action finishes executing on a remote site. The `[event:drd_action_id]` token contains the plugin ID of the DRD action and `[event:entity]` provides the remote entity (host, core, or domain) the action operated on, if applicable. # DRD: Action started Available since: 4.1.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:drd_action_id]` | The ID of the DRD action. | | `[event:entity]` | The entity the action deals with. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a DRD (Drupal Remote Dashboard) action starts executing on a remote site. The `[event:drd_action_id]` token contains the plugin ID of the DRD action and `[event:entity]` provides the remote entity (host, core, or domain) the action operates on, if applicable. # Easy Email ## Installation ``` composer require drupal/easy_email drush pm:install easy_email ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Easy Email** from there. # Send Easy Email Available since: unknown ## Fields `Entity` : Provide the token name of the *easy_email* that this action should operate with. Please provide the token name only, without brackets. # ECA Core ## Installation ``` composer require drupal/eca drush pm:install eca ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Core** from there. # ECA Access Sets an access result for the event. Possible results are: - allowed - neutral - forbidden ## Installation ``` composer require drupal/eca drush pm:install eca_access ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Access** from there. # Set access result Available since: 1.0.0 Only works when reacting upon *ECA Access* events. Action to set an access result. Attention When more than one of this action are used for the same event, beware the order if important here. As soon as access got denied once, this can never being overridden afterwards. However, allowing access first, and denying it later if certain conditions apply, is what works as intended and is therefore the recommended approach. ## Fields `Access result` : Please note: This action only works when reacting upon *access* events.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_access_set_result_access_result* ``` Sets one of the following access results: ``` - allowed - neutral - forbidden # Determining entity create access Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:context]` | Contains a list of properties depending on the context of the event. | | `[event:entity_bundle]` | The bundle of the entity. | | `[event:uid]` | The ID of the user account of the event. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Fires when Drupal checks whether a user can create a new entity of a given type and bundle. This wraps Drupal's `hook_entity_create_access()`. Use the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) action to grant or deny access. No entity available Since the entity does not exist yet, the `[entity]` token is **not available** in this event. You only have access to the entity type, bundle, language, and the requesting account via `[account]`. ## Fields For any successor of this event, the account that asks for access is available under the [account] token. Example: [account:uid] provides the user ID of the account. Furthermore, following data of the event is available: `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`, `taxonomy_term`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`, `tags`). For entities without bundles (like users), the bundle equals the entity type. ``` `Restrict by language code` : Example: *en* ``` Restricts to the specified language code (e.g., `en`). Useful in multilingual sites where create access might differ per language. Comma-separated for multiple values. ``` # Determining entity access Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:entity_bundle]` | The bundle of the entity. | | `[event:entity_id]` | The entity ID, only available if the entity is not new. | | `[event:entity_type]` | The entity type. | | `[event:operation]` | The operation with which the entity should be accessed, e.g. "view", "update", etc. | | `[event:uid]` | The ID of the user account of the event. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when Drupal checks whether a user can perform an operation on an existing entity. This wraps Drupal's `hook_entity_access()`. Use the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) action to grant or deny access. The account token is the checked account The `[account]` token is the account **being checked for access**, not necessarily the currently logged-in user. When code checks access for a different user (e.g., `$entity->access('view', $other_user)`), the `[account]` token reflects that other user. Performance consideration Access results from ECA are not cached (`maxAge=0`). Use specific filters (entity type, bundle, operation) to minimize the performance impact. ## Fields For any successor of this event, the account that asks for access is available under the [account] token. Example: [account:uid] provides the user ID of the account. Furthermore, following data of the event is available: `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`, `taxonomy_term`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *view, update, delete* ``` Restricts to the specified operation (e.g., `view`, `update`, `delete`). Comma-separated for multiple values. ``` # Determining entity field access Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:entity_bundle]` | The bundle of the entity. | | `[event:entity_id]` | The entity ID, only available if the entity is not new. | | `[event:entity_type]` | The entity type. | | `[event:field]` | The name of the field. | | `[event:operation]` | The operation with which the entity should be accessed, e.g. "view", "update", etc. | | `[event:uid]` | The ID of the user account of the event. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when Drupal checks whether a user can access a specific field on an entity. This wraps Drupal's `hook_entity_field_access()`. Use the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) action to grant or deny access. High frequency event This event fires for **every field** on **every entity** during page rendering. Always use specific filters (entity type, bundle, field name, operation) to narrow matches and avoid performance issues. Note: Field access operations are `view` and `edit` (not `update`/`delete` as with entity-level access). ## Fields For any successor of this event, the account that asks for access is available under the [account] token. Example: [account:uid] provides the user ID of the account. Furthermore, following data of the event is available: `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`, `taxonomy_term`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *view, edit* ``` Restricts to the specified operation. For field access, the operations are `view` and `edit` (not `update` or `delete`). ``` `Restrict by field name` : Example: *title, body, field_myfield* ``` Restricts to the specified field machine name (e.g., `title`, `body`, `field_image`). Comma-separated for multiple values. Highly recommended to set this to avoid triggering on every field access check. ``` # ECA Base Provides some basic events, conditions and actions, like using the state functionality of Drupal. Furthermore, this module contains: - general conditions for comparison - setting tokens - event trigger - counting list items - etc. ## Installation ``` composer require drupal/eca drush pm:install eca_base ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Base** from there. # List: count items Available since: 1.0.0 Counts the items in a list based on several properties. ## Fields `Name of token` : Provide the name of a new token where the counting result should be stored. Please provide the token name only, without brackets. `Token containing the list` : Provide the name of the token that contains a list from which the number of items should be counted. Please provide the token name only, without brackets. # Display an error message to the user Available since: 1.1.0 ## Fields `Message` : The message to be displayed to the current user. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Expirable key value store: delete Available since: 2.1.5 Deletes a value from the Drupal expirable key value store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. # Expirable key value store: read Available since: 2.0.0 Reads a value from the Drupal expirable key value store by the given key. The result is stored in a token. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Name of token` : The name of the token, the value is stored into. Please provide the token name only, without brackets. # Expirable key value store: write Available since: 2.0.0 Writes a value to the Drupal expirable key value store by the given key. ## Fields `Expiration` : The time to live for this item, in seconds. `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Value` : The value to store. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Only if new` : If enabled, this only stores the value if the key does not exist yet. # Key value store: delete Available since: 2.1.5 Delete a value from the Drupal key value store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. # Key value store: read Available since: 2.0.0 Reads a value from the Drupal key value store by the given key. The result is stored in a token. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Name of token` : The name of the token, the value is stored into. Please provide the token name only, without brackets. # Key value store: write Available since: 2.0.0 Write a value to the Drupal key value store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Value` : The value to store. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Only if new` : If enabled, this only stores the value if the key does not exist yet. # List: add item Available since: 1.1.0 Add an item to a list using a specified token. ## Fields `Value to add` : This field supports tokens. `Method` : Options of the specific method to add a value to a list.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_list_add_method* `Index key` : When using the method *Set by specified index*, then an index key must be specified here.\ This field supports tokens. `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. # List: compare items Compares the items in two simple lists (contained in tokens), returning the array of results. ## Fields `Token containing the secondary list` : Provide the name of the token that contains the secondary list in the comparison. Please provide the token name only, without brackets. `Array Function` : Returns an array of items found by the [Array Function](https://www.php.net/manual/en/ref.array.php) selected. `Name of result token` : Provide the name of a new token where the resulting array should be stored. Please provide the token name only, without brackets. `Token containing the primary list` : Provide the name of the token that contains the primary list in the comparison. Please provide the token name only, without brackets. # List: delete data Available since: 1.1.0 Transaction to delete contained data of a list from the database. ## Fields `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. # List: remove item Available since: 1.1.0 Remove an item from a list and optionally store the item as a token. ## Fields `Value to remove` : When *Drop by specified value* is selected above, then a value must be specified here.\ This field supports tokens. `Name of token` : Provide the name of a token that holds the removed item. Please provide the token name only, without brackets. `Method` : When using the "Defined by token" option, make sure there is a token with this name: *eca_list_remove_method* `Index key` : When using the method *Drop by specified index key*, then an index key must be specified here.\ This field supports tokens. `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. # List: save data Available since: 1.1.0 Transaction to save contained data of a list into the database. ## Fields `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. # List: sort items Available since: 3.1.3 Sorts a list. ## Fields `Sort method` `Name of token` : The sorted list will be loaded into this specified token. If this is not provided, the list will be sorted in-place. `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. # Lock: acquire Available since: 1.1.0 Acquires a lock. ## Fields `Lock name` : The name identifies a lock, that may be shared by multiple processes. The lock will be automatically released when this ECA process is finished.\ This field supports tokens. `Lock timeout in seconds` : This timeout is used as a maximum time threshold. When exceeded, the lock is automatically released for other processed again. `Wait for lock until timeout exceeded` : When checked, this action automatically retries acquiring the lock, until the specified timeout above exceeded. `Name of token` : Optionally define a token name to store the result of lock acquisition. The result value is **1** when acquisition was successful, and is set to **0** when it was not successful. Please provide the token name only, without brackets. # Private temporary store: delete Available since: 2.1.5 Delete a value from the Drupal private temporary store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. # Private temporary store: read Available since: 2.0.0 Reads a value from the Drupal private temporary store by the given key. The result is stored in a token. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Name of token` : The name of the token, the value is stored into. Please provide the token name only, without brackets. # Private temporary store: write Available since: 2.0.0 Write a value to the Drupal private temporary store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Value` : The value to store. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Set ECA log level Available since: 2.0.0 The log level for ECA can be changed temporarily for the processing within the current event. ## Fields `Log level` : When using the "Defined by token" option, make sure there is a token with this name: *eca_set_eca_log_level_log_level* # Set field widget value Available since: 2.1.11 This action sets the value for the field widget event. ## Fields `Field widget value` : This field supports tokens. # Set tool output Available since: 2.1.11 This action sets the output for the tool event. ## Fields `Tool output` : This field supports tokens. `Interpret above config value as YAML format` : Nested data can be set using YAML format, for example *front: /node*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *front: "[myurl:path]"* `Validate YAML to prevent this from being executed when invalid` # Shared temporary store: delete Available since: 2.1.5 Delete a value from the Drupal shared temporary store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. # Shared temporary store: read Available since: 2.0.0 Reads a value from the Drupal shared temporary store by the given key. The result is stored in a token. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Name of token` : The name of the token, the value is stored into. Please provide the token name only, without brackets. # Shared temporary store: write Available since: 2.0.0 Write a value to the Drupal shared temporary store by the given key. ## Fields `Collection` : The collection of the store. `Store key` : The key of the value in the store. `Value` : The value to store. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Persistent state: read Available since: 1.1.0 Reads a value from the Drupal state by the given key. The result is stored in a token. Reads a value from the Drupal state by the given key. The result is stored in a token. ## Fields `State key` : The key of the Drupal state.\ This field supports tokens. `Name of token` : The name of the token, the value is stored into. Please provide the token name only, without brackets. # Persistent state: write Available since: 1.1.0 Writes a value into the Drupal state system by the given key. Writes a key/value pair to the Drupal state. The value can be stored in a token. ## Fields `State key` : The key of the Drupal state.\ This field supports tokens. `The value of the state` : The key, where the value is stored into.\ This field supports tokens. `Interpret above config value as YAML format` : Nested data can be set using YAML format, for example *mykey: myvalue*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Token: replace Available since: 2.0.0 Replace all tokens, using a recursive strategy. ## Fields `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Value of the token` : The value of the token.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Token: set context Available since: 1.1.0 Set currently defined token data to be available for any child process. # Token: set random value Available since: 2.1.0 Create a random value and store it in a token. ## Fields `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mode` : The type of random value to generate.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_set_random_value_mode* `Length or min/max` : The length or min/max range of the random value. For sentences, this value determines the number of words and for paragraphs it determines the number of paragraphs. For integer mode, please provide comma separated values for minimum and maximum value. Missing values default to PHPs built in mix and max integer values. For the image mode, please provide a comma separated min and max resolution, defaults to "100x100,1920x1080". For the image mode, the token will contain the path to the generated random image file.\ This field supports tokens. # Token: set value Available since: 1.1.0 Define a locally available token by a specific name and value. ## Fields `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Value of the token` : The value of the token.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Translate Available since: 1.1.0 Translate a given value, and store the translated value as a token. ## Fields `Name of token` : The translation result will be stored in this token. Please provide the token name only, without brackets. `Value to translate` `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Target language` : Define the language that the given value should be translated to.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_translate_target_langcode* # Trigger a custom event Available since: 1.0.0 Triggers a custom event by a specific id. Note: If an entity is involved, you have to use [Custom Event Entity Aware](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md). ## Fields `Event ID` : The ID of the event to be triggered. `Tokens to forward` : Comma separated list of token names from the current context, that will be forwarded to the triggered event. These tokens are then also available for subsequent conditions and actions within the current process. # Chain action for AND condition Available since: 1.0.0 This action chains other actions with an explicit AND condition. # Display a warning message to the user Available since: 1.1.0 ## Fields `Message` : The message to be displayed to the current user. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Compare number of list items Available since: 1.0.0 Condition to compare the number of list items. ## Fields `Name of token containing the list` : Provide the name of the token that contains a list from which the number of items should be counted. `Second value` : The second value to be compared. ``` The list to be counted. ``` `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_count_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_count_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # List: contains item Available since: 2.0.0 Evaluate whether a certain item is in a list. ## Fields `Name of token containing the list` : Provide the name of the token that contains a list of items. Please provide the token name only, without brackets. `Method` : When using the "Defined by token" option, make sure there is a token with this name: *eca_list_contains_method* `Value to lookup` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Compare two scalar values Available since: 1.0.0 Compares two scalar values based on several conditions. Compares two scalar values based on several conditions. ## Fields `First value` : The first value to be compared. `Second value` : The second value to be compared. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_scalar_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_scalar_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Persistent state: compare Available since: 1.0.0 Compares a state value by a given key. ## Fields `Key` : The key of the state. `Value` : The value of the state. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_state_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_state_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Token: exists Available since: 1.1.0 ## Fields `Name of token` : Provide the name of the token to check for. Please provide the token name only, without brackets. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # ECA cron event Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | This event reacts to Drupal's cron system and allows you to schedule ECA processes at specific intervals. ### How it works Drupal core provides a cron API that all modules can hook into. When cron runs, core asks every registered module — including ECA — whether it has work to do. ECA then checks the **Frequency** field of each cron event in your models to determine whether that particular event is due for execution. If it is, the model's actions are processed; otherwise, the event is skipped. This means: 1. **System-level cron must run first.** The ECA cron event does not trigger itself — it only fires when Drupal's cron runs. On production sites, it is strongly recommended to disable the `automated_cron` module and instead run `drush cron` from a system-level crontab (e.g. every minute or at least every 5 minutes). 1. **The Frequency field is a schedule filter, not a trigger.** Setting a frequency of `0 1 * * 1` (every Sunday at 1:00 UTC) does not cause ECA to run at that time by itself. It tells ECA to only execute this event *when cron happens to run* at or after the scheduled time. The more frequently your system cron runs, the more precisely ECA can honor the frequency you define. 1. **Cron runs as the anonymous user.** Unless configured otherwise, cron processes run without an authenticated session. If your actions require specific permissions (e.g. querying a view with access restrictions), add a [User: switch current account](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) action immediately after this event to switch to an account with the necessary permissions. Avoid rendering actions in cron context Actions that render HTML (such as rendering a view) may fail during cron because there is no active HTTP session. You might see errors like *"Failed to start the session because headers have already been sent"*. Consider using non-rendering alternatives or ensure your model accounts for the headless cron context. ## Fields `Frequency` : The frequency of a cron job is defined by a cron specific notation which is best explained at https://en.wikipedia.org/wiki/Cron. Note: date and time need to be provided in UTC timezone. ``` This field defines *when* the ECA cron event should be considered due for execution. It does **not** control when Drupal's system cron runs — that is configured separately at the server or Drupal level. ``` Each time system cron runs, ECA evaluates this frequency expression to decide whether the event should fire. If the current time matches the schedule, the event's actions are executed; otherwise, the event is skipped until the next cron run. **Examples:** | Expression | Meaning | | ------------- | -------------------------------------------------------------------------------- | | `* * * * *` | Every time cron runs (effectively every minute if system cron runs every minute) | | `0 */1 * * *` | Once per hour, at the top of the hour | | `0 2 * * *` | Daily at 02:00 UTC | | `0 1 * * 1` | Every Monday at 01:00 UTC | | `0 0 1 * *` | First day of every month at midnight UTC | Precision depends on system cron frequency If your system cron runs only every 15 minutes, an ECA frequency of `*/5 * * * *` (every 5 minutes) will not actually fire every 5 minutes. ECA can only evaluate the schedule when cron runs, so the effective precision is limited by how often system cron is triggered. # ECA custom event Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[VARIOUS]` | All tokens forwarded by the dispatcher. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Event listening to a custom event. Note: If an entity is involved, you have to use [Custom Event Entity Aware](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md). ## Fields `Event ID` : The custom event ID. Leave empty to trigger all custom events. ``` The custom event ID to listen for. Leave empty to trigger on all custom events. ``` # ECA Field Widget Available since: 2.1.11 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[entity]` | The entity being edited. | | `[field_name]` | The name of the entity field for which the field widget is used. | | `[field_key]` | The index of the field starting with zero and going up if it is a multi-value field. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | This event has currently no configuration options. However, you may want to at least give it a label because that's how it will be displayed in the form display configuration. To get a field widget action from ECA work with form fields, you start with this event and the subsequent actions and conditions receive the above tokens with which you can build your process. To return a value back to the field widget action, which will put that into the related form field, you can either change the value in the provided entity or you can use the [Set field widget value](https://ecaguide.org/plugins/eca/base/actions/eca_set_field_widget_value/index.md) action to set that value. # ECA token generate event Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a token matching the configured pattern is encountered during Drupal's token replacement process. This allows providing dynamic token values on demand. Performance consideration Token replacement happens very frequently across the system (emails, paths, fields, etc.). Keep ECA reactions lightweight to avoid performance issues. ## Fields `Name of token` : Example: *mygroup:value*. Wildcards are supported, e.g. to react upon all "mygroup" tokens: *mygroup:\** Please provide the token name only, without brackets. ``` The token pattern to react upon (e.g., `mygroup:value`). Supports wildcards: `mygroup:*` reacts to all tokens in the 'mygroup' group. ``` # ECA Tool Available since: 2.1.11 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[VARIOUS]` | All tokens forwarded by the dispatcher. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Defines an ECA-based tool that can be invoked by an AI agent or other automated system. The tool description and arguments are critically important for AI agents to understand when and how to use the tool. ## Fields `Description` : Summarizes what this tool is for. This plain text property is particularly important to the AI agent because it provides context and explicitly defines the use case using natural language. ``` A plain-text description of what this tool does. This is critically important for AI agents as they use it to decide when and how to invoke the tool. ``` `Arguments` : The arguments that the AI agent passes into the tool. They must be written in YAML format. This property is also important to the AI agent. Note that the top-level keys (e.g. node, user) become the names of the tokens that are then available to successors of this event. ``` Provide the list of arguments in YAML format so that the caller of this tool know which context need to be made available: ``` ``` node: data_type: "entity:node:article" label: "The article to process" required: true description: "The article that should be investigated in the format {node:nid}, so for example node:2." user: data_type: "entity:user" label: "The user" required: true description: "Provide the user in the format {user:uid} so that their name can be determined and verified if they are the author of the article, e.g. user:5." ``` Each argument has a name, e.g. "node" or "user" in the above example. For each of them, provide the data type, a label, a description, and a flag whether that argument is required or not. Those arguments will be available as tokens to the subsequent conditions and actions following that event. # ECA Cache Module with actions to read, write and invalidate a cache from a specific cache backend. ## Installation ``` composer require drupal/eca drush pm:install eca_cache ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Cache** from there. # Cache ECA: invalidate Available since: 2.0.0 Invalidates a part or the whole ECA cache. ## Fields `Cache tags` : Optionally define cache tags for fine-granular cache invalidation. Separate multiple tags with commas. More information about cache tags can be found in the [documentation](https://www.drupal.org/docs/drupal-apis/cache-api/cache-tags). When empty, then the whole cache is being invalidated. `Cache backend` : When using the "Defined by token" option, make sure there is a token with this name: *eca_cache_invalidate_backend* ``` The following cache backends are available: ``` - default shared cache - runtime in-memory cache - chained cache (in-memory plus shared) `Cache key` : The cache key is a unique machine name and identifies the cache item.\ This field supports tokens. # Cache ECA: read Available since: 2.0.0 Read a value item from ECA cache and store it as a token. ## Fields `Name of token` : The cache item value will be loaded into this specified token. Please provide the token name only, without brackets. `Cache backend` : When using the "Defined by token" option, make sure there is a token with this name: *eca_cache_read_backend* ``` The following cache backends are available: ``` - default shared cache - runtime in-memory cache - chained cache (in-memory plus shared) `Cache key` : The cache key is a unique machine name and identifies the cache item.\ This field supports tokens. # Cache ECA: write Available since: 2.0.0 Write a value item into ECA cache. ## Fields `Cache item value` : The value to cache.\ This field supports tokens. `Interpret above config value as YAML format` : Nested data can be set using YAML format, for example *mykey: myvalue*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Expiration time` : The timestamp in seconds when the cached item expires. Set to -1 for unlimited lifetime.\ This field supports tokens. `Cache tags` : Optionally add cache tags for fine-granular cache invalidation. Separate multiple tags with commas. More information about cache tags can be found in the [documentation](https://www.drupal.org/docs/drupal-apis/cache-api/cache-tags).\ This field supports tokens. `Cache backend` : When using the "Defined by token" option, make sure there is a token with this name: *eca_cache_write_backend* ``` The following cache backends are available: ``` - default shared cache - runtime in-memory cache - chained cache (in-memory plus shared) `Cache key` : The cache key is a unique machine name and identifies the cache item.\ This field supports tokens. # Page Cache Kill Switch Available since: 2.0.0 Kill the page cache for this page # Cache Raw: invalidate Available since: 2.0.0 Invalidates a part or the whole raw cache. ## Fields `Cache tags` : Optionally define cache tags for fine-granular cache invalidation. Separate multiple tags with commas. More information about cache tags can be found in the [documentation](https://www.drupal.org/docs/drupal-apis/cache-api/cache-tags). When empty, then the whole cache is being invalidated. # Cache Raw: read Available since: 2.0.0 Read a value item from raw cache and store it as a token. ## Fields `Name of token` : The cache item value will be loaded into this specified token. Please provide the token name only, without brackets. `Cache backend` : When using the "Defined by token" option, make sure there is a token with this name: *eca_raw_cache_read_backend* ``` The following cache backends are available: ``` - default shared cache - runtime in-memory cache - chained cache (in-memory plus shared) `Cache key` : The cache key is a unique machine name and identifies the cache item.\ This field supports tokens. # Cache Raw: write Available since: 2.0.0 Write a value item into raw cache. ## Fields `Cache item value` : The value to cache.\ This field supports tokens. `Interpret above config value as YAML format` : Nested data can be set using YAML format, for example *mykey: myvalue*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Expiration time` : The timestamp in seconds when the cached item expires. Set to -1 for unlimited lifetime.\ This field supports tokens. `Cache tags` : Optionally add cache tags for fine-granular cache invalidation. Separate multiple tags with commas. More information about cache tags can be found in the [documentation](https://www.drupal.org/docs/drupal-apis/cache-api/cache-tags).\ This field supports tokens. `Cache backend` : When using the "Defined by token" option, make sure there is a token with this name: *eca_raw_cache_write_backend* ``` The following cache backends are available: ``` - default shared cache - runtime in-memory cache - chained cache (in-memory plus shared) `Cache key` : The cache key is a unique machine name and identifies the cache item.\ This field supports tokens. # ECA Commerce ## Installation ``` composer require drupal/eca_commerce drush pm:install eca_commerce ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Commerce** from there. # Order Item: Add Price Adjustment Available since: 1.0.0 ## Fields `Method` : The method to set an entity, like cleaning the old one, etc.. `Type` `Locked` : Note: Adjustments added from UI interactions need to be locked to persist after an order refresh. `Label` : This field supports tokens. `Amount` : This field supports tokens. `Currency` : When using the "Defined by token" option, make sure there is a token with this name: *eca_commerce_add_adjustment_currency* `Percentage` : This field supports tokens. `Included in the base price` `Save entity` : Saves the entity or not after setting the value. # Change Price in Cart Available since: 1.0.0 ## Fields `Final Price` : This should either be a number or a token that outputs a number or price field. This only supports USD. # Commerce: Billing address Available since: 1.0.0 ## Fields `operator` `zone` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order currency Available since: 1.0.0 ## Fields `Currencies` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Customer ID Available since: 1.0.0 ## Fields `Customers` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Customer role Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Customer email Available since: 1.0.0 ## Fields `Email` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Specific products Available since: 1.0.0 ## Fields `Products` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Product categories Available since: 1.0.0 ## Fields `Categories` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Product types Available since: 1.0.0 ## Fields `Product types` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Specific product variation Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Total discounted product quantity Available since: 1.0.0 ## Fields `Operator` `Quantity` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Product variation types Available since: 1.0.0 ## Fields `Product variation types` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Selected payment gateway Available since: 1.0.0 ## Fields `Payment gateways` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order contains specific products Available since: 1.0.0 ## Fields `Products` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order contains product categories Available since: 1.0.0 ## Fields `Categories` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order contains product types Available since: 1.0.0 ## Fields `Product types` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order contains specific product variations Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Shipping address Available since: 1.0.0 ## Fields `operator` `zone` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Store Available since: 1.0.0 ## Fields `Stores` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Current order total Available since: 1.0.0 ## Fields `Operator` `Amount` `Total to compare against` : Totals used may include prior price adjustments. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order type Available since: 1.0.0 ## Fields `Order type` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Commerce: Order contains product variation types Available since: 1.0.0 ## Fields `Product variation types` : Provide a comma separated list of entity IDs. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Cart: The cart was emptied Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[cart]` | The cart entity. | | `[commerce_order_items]` | An array of order item entities. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when all items are removed from a cart. The `[cart]` token provides the cart order entity, and `[commerce_order_items]` provides the removed order items. Fires before the cart order is saved. # Cart: An entity was added to the cart Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[cart]` | The cart entity. | | `[commerce_order_item]` | The order item entity. | | `[entity]` | This is a purchasable entity. | | `[quantity]` | A float of the quantity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a purchasable entity (e.g., a product variation) is added to the cart. The `[cart]` token provides the cart order, `[entity]` the purchasable entity, `[commerce_order_item]` the destination order item, and `[quantity]` the quantity. Fires before the cart order is saved. # Cart: Add order item to cart Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[cart]` | The cart entity. | | `[commerce_order_item]` | The order item entity. | | `[quantity]` | A float of the quantity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an order item is added to the cart. The `[cart]` token provides the cart order, `[commerce_order_item]` the added order item, and `[quantity]` the quantity. Fires before the cart order is saved. # Cart: Order item comparison fields Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[commerce_order_item_comparison_fields]` | The fields to compare. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when determining which fields to compare when deciding if order items can be merged in the cart. Add custom field names to prevent merging when items differ in those fields (e.g., gift messages, custom engravings). # Cart: Remove order item from cart Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[cart]` | The cart entity. | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an order item is removed from the cart. The `[cart]` token provides the cart order and `[commerce_order_item]` the removed item. Fires before the cart order is saved. # Cart: Update order item on cart Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[cart]` | The cart entity. | | `[commerce_order_item]` | The order item entity. | | `[commerce_order_item_original]` | The original item data before the update. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a cart order item is updated (e.g., quantity change). The `[cart]` token provides the cart order, `[commerce_order_item]` the updated item, and `[commerce_order_item_original]` the item before the update. Fires before the cart order is saved. # Checkout: Completion Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a customer completes the checkout process. The `[commerce_order]` token provides the completed order. This is one of the most commonly used Commerce events, ideal for triggering post-purchase workflows such as sending custom notifications, updating inventory in external systems, or enrolling users in programs. # Checkout: Completion register Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an anonymous customer registers a new account during checkout completion. The `[commerce_order]` token provides the checkout order. # Core: Filter conditions Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when Commerce filters the available condition plugins (e.g., for promotions or payment gateways). Useful for programmatically removing or adding condition plugins. # Order: Assign order Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_customer]` | The current customer, this is a Drupal User. | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an order is assigned to a customer -- typically when an anonymous cart is assigned after login or registration, or when an admin reassigns an order. The `[commerce_order]` token provides the order (still with original customer data) and `[commerce_customer]` the new customer. # Order: Create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new order is created in memory, before it is saved. The `[commerce_order]` token provides the new order entity. # Order: Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a order has been deleted from storage. The `[commerce_order]` token provides the deleted order entity. # Order: Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new order is saved for the first time. The `[commerce_order]` token provides the newly saved order entity. # Order: Item create Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new order item is created in memory, before it is saved. The `[commerce_order_item]` token provides the new order item entity. # Order: Item delete Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a order item has been deleted from storage. The `[commerce_order_item]` token provides the deleted order item entity. # Order: Item insert Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new order item is saved for the first time. The `[commerce_order_item]` token provides the newly saved order item entity. # Order: Item load Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a order item is loaded from storage. The `[commerce_order_item]` token provides the loaded order item entity. # Order: Item predelete Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a order item is deleted. The entity still exists at this point. The `[commerce_order_item]` token provides the order item entity about to be deleted. # Order: Item presave Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a order item is saved to storage. Fires for both new and existing entities. The `[commerce_order_item]` token provides the order item entity. # Order: Item update Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing order item is saved. The `[commerce_order_item]` token provides the updated order item entity. # Order: After alter label Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[commerce_order_label]` | The order label. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an order label is being generated, allowing customization of how orders are displayed in admin listings and breadcrumbs. # Order: Load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a order is loaded from storage. The `[commerce_order]` token provides the loaded order entity. # Order: Paid Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when an order has been fully paid (balance reaches zero). Fires only once This event is guaranteed to fire only once per order, even if the order is later refunded and re-paid. Safe for triggering one-time actions like license grants, enrollment, or shipment initiation. # Order: Predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a order is deleted. The entity still exists at this point. The `[commerce_order]` token provides the order entity about to be deleted. # Order: Presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a order is saved to storage. Fires for both new and existing entities. The `[commerce_order]` token provides the order entity. # Order: Profile load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[profiles]` | An array of customer profiles. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when customer profiles (billing, shipping) are being collected for an order. Useful for adding custom profile scopes or overriding which profile is used. # Order: Update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing order is saved. The `[commerce_order]` token provides the updated order entity. # Payment: Create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new payment is created in memory, before it is saved. The `[commerce_payment]` token provides the new payment entity. # Payment: Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a payment has been deleted from storage. The `[commerce_payment]` token provides the deleted payment entity. # Payment: Filter Payment Gateways Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[commerce_order_payment_gateways]` | The payment gateway configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when payment gateways are being loaded for an order during checkout. Useful for conditionally hiding or showing payment methods based on order total, customer role, shipping address, or other criteria. # Payment: Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new payment is saved for the first time. The `[commerce_payment]` token provides the newly saved payment entity. # Payment: Load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a payment is loaded from storage. The `[commerce_payment]` token provides the loaded payment entity. # Payment: Predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a payment is deleted. The entity still exists at this point. The `[commerce_payment]` token provides the payment entity about to be deleted. # Payment: Presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a payment is saved to storage. Fires for both new and existing entities. The `[commerce_payment]` token provides the payment entity. # Payment: Update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_payment]` | The payment entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing payment is saved. The `[commerce_payment]` token provides the updated payment entity. # Core: Post Mail Send Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts after Commerce sends an email (e.g., order receipts, shipment confirmations). Useful for logging, triggering follow-up actions, or integrating with external systems after order-related emails. # Price: Number format Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[commerce_definition]` | This is the number format definition. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when a number format is being resolved for price display. Useful for customizing price formatting per-locale (decimal separator, grouping separator, currency patterns). # Product: Create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new product is created in memory, before it is saved. The `[commerce_product]` token provides the new product entity. # Product: Default variation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[commerce_product_variation_default]` | This is the default product variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when the default variation for a product is being determined. Useful for dynamically selecting which variation is shown by default based on user preferences, inventory, or pricing. # Product: Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a product has been deleted from storage. The `[commerce_product]` token provides the deleted product entity. # Product: Filter Variations Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when filtering the list of enabled variations for a product. Useful for hiding out-of-stock variations, restricting by user role, or implementing location-based variation filtering. # Product: Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new product is saved for the first time. The `[commerce_product]` token provides the newly saved product entity. # Product: Load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a product is loaded from storage. The `[commerce_product]` token provides the loaded product entity. # Product: Predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a product is deleted. The entity still exists at this point. The `[commerce_product]` token provides the product entity about to be deleted. # Product: Presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a product is saved to storage. Fires for both new and existing entities. The `[commerce_product]` token provides the product entity. # Product: Translation delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a translation of a product is deleted. The `[commerce_product]` token provides the product entity. # Product: Translation insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new translation of a product is saved. The `[commerce_product]` token provides the translated product entity. # Product: Update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product]` | The product entity. This is not the variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing product is saved. The `[commerce_product]` token provides the updated product entity. # Product: Variation Ajax Change Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[commerce_product_variation_response]` | The response when changing product variations via ajax. | | `[commerce_product_variation_view_mode]` | The view mode for the product variation. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a product variation is changed via AJAX (e.g., user selects a different size or color). Useful for adding custom AJAX commands to update price displays, stock information, or image galleries. # Product: Variation create Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new product variation is created in memory, before it is saved. The `[commerce_product_variation]` token provides the new product variation entity. # Product: Variation delete Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a product variation has been deleted from storage. The `[commerce_product_variation]` token provides the deleted product variation entity. # Product: Variation insert Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new product variation is saved for the first time. The `[commerce_product_variation]` token provides the newly saved product variation entity. # Product: Variation load Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a product variation is loaded from storage. The `[commerce_product_variation]` token provides the loaded product variation entity. # Product: Variation predelete Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a product variation is deleted. The entity still exists at this point. The `[commerce_product_variation]` token provides the product variation entity about to be deleted. # Product: Variation presave Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a product variation is saved to storage. Fires for both new and existing entities. The `[commerce_product_variation]` token provides the product variation entity. # Product: Variation translation delete Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a translation of a product variation is deleted. The `[commerce_product_variation]` token provides the product variation entity. # Product: Variation translation insert Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new translation of a product variation is saved. The `[commerce_product_variation]` token provides the translated product variation entity. # Product: Variation update Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `[commerce_product_variation]` | The product variation entity. This is not the product entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing product variation is saved. The `[commerce_product_variation]` token provides the updated product variation entity. # Promotion: Coupon create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new coupon is created in memory, before it is saved. The `[commerce_coupon]` token provides the new coupon entity. # Promotion: Coupon delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a coupon has been deleted from storage. The `[commerce_coupon]` token provides the deleted coupon entity. # Promotion: Coupon insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new coupon is saved for the first time. The `[commerce_coupon]` token provides the newly saved coupon entity. # Promotion: Coupon load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a coupon is loaded from storage. The `[commerce_coupon]` token provides the loaded coupon entity. # Promotion: Coupon predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a coupon is deleted. The entity still exists at this point. The `[commerce_coupon]` token provides the coupon entity about to be deleted. # Promotion: Coupon presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a coupon is saved to storage. Fires for both new and existing entities. The `[commerce_coupon]` token provides the coupon entity. # Promotion: Coupon update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_coupon]` | The coupon entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing coupon is saved. The `[commerce_coupon]` token provides the updated coupon entity. # Promotion: Create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new promotion is created in memory, before it is saved. The `[commerce_promotion]` token provides the new promotion entity. # Promotion: Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a promotion has been deleted from storage. The `[commerce_promotion]` token provides the deleted promotion entity. # Promotion: Filter Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order]` | The order entity. | | `[commerce_promotions]` | An array of promotion entities. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when promotions are being evaluated for an order. Useful for implementing custom promotion exclusion logic beyond what Commerce conditions provide (e.g., restrict to first-time customers or based on external loyalty data). # Promotion: Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new promotion is saved for the first time. The `[commerce_promotion]` token provides the newly saved promotion entity. # Promotion: Load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a promotion is loaded from storage. The `[commerce_promotion]` token provides the loaded promotion entity. # Promotion: Predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a promotion is deleted. The entity still exists at this point. The `[commerce_promotion]` token provides the promotion entity about to be deleted. # Promotion: Presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a promotion is saved to storage. Fires for both new and existing entities. The `[commerce_promotion]` token provides the promotion entity. # Promotion: Translate Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a translation of a promotion is deleted. The `[commerce_promotion]` token provides the promotion entity. # Promotion: Translate Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new translation of a promotion is saved. The `[commerce_promotion]` token provides the translated promotion entity. # Promotion: Update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_promotion]` | The promotion entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing promotion is saved. The `[commerce_promotion]` token provides the updated promotion entity. # Core: Referenceable Plugin Types Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when building the list of Commerce plugin types that can be referenced by entity reference fields. # Store: Create Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a new store is created in memory, before it is saved. The `[commerce_store]` token provides the new store entity. # Store: Delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a store has been deleted from storage. The `[commerce_store]` token provides the deleted store entity. # Store: Insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new store is saved for the first time. The `[commerce_store]` token provides the newly saved store entity. # Store: Load Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when a store is loaded from storage. The `[commerce_store]` token provides the loaded store entity. # Store: Predelete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a store is deleted. The entity still exists at this point. The `[commerce_store]` token provides the store entity about to be deleted. # Store: Presave Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts before a store is saved to storage. Fires for both new and existing entities. The `[commerce_store]` token provides the store entity. # Store: Translation delete Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a translation of a store is deleted. The `[commerce_store]` token provides the store entity. # Store: Translation insert Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after a new translation of a store is saved. The `[commerce_store]` token provides the translated store entity. # Store: Update Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_store]` | The store entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts after an existing store is saved. The `[commerce_store]` token provides the updated store entity. # Tax: Build Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_tax_plugin]` | The local tax type plugin. | | `[commerce_tax_zones]` | An array of tax zones. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when tax zones are being built for a local tax type plugin. Useful for dynamically adding special tax zones, modifying rates, or removing zones based on business logic. # Tax: Customer profile Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | `[commerce_order_item]` | The order item entity. | | `[customer_profile]` | A customer profile. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Reacts when determining which customer profile to use for tax calculation per order item. By default the billing profile is used. Shipping-based tax calculation Set the customer profile to the shipping profile to calculate tax based on the ship-to address instead of the billing address. # ECA Config Module with actions and events about the Drupal configuration. You can read and write configuration and also react to specific configuration events. ## Installation ``` composer require drupal/eca drush pm:install eca_config ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Config** from there. # Config Action Available since: 3.0.0 Execute a Drupal Core ConfigAction. ## Fields `Config action` : The config action to be applied.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_config_action_action_id* `Config name` : The config name, for example *system.site*.\ This field supports tokens. `Data` : The data for the config action, provided in YAML format.\ This field supports tokens. # Config: get list Available since: 3.0.8 Gets a list of configuration names and stores it as a token. ## Fields `Token name` : The name of the token to store the configuration list. Please provide the token name only, without brackets. `Configuration prefix` : Optional prefix to filter configuration names.\ This field supports tokens. # Config: read Available since: 1.0.0 Read configuration and store it as a token. ## Fields `Include overridden` : Whether to apply module and settings.php overrides to values. `Name of token` : The targeted configuration value will be loaded into this specified token. Please provide the token name only, without brackets. `Config name` : The config name, for example *system.site*. `Config key` : The config key, for example *page.front*. Leave empty to use the whole config. # Config: write Available since: 1.0.0 Writes into configuration from a token. ## Fields `Config value` : The value to set.\ This field supports tokens. `Interpret above config value as YAML format` : Nested data can be set using YAML format, for example *front: /node*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *front: "[myurl:path]"* `Validate YAML to prevent this from being executed when invalid` `Save configuration` : Save the given config to the Drupal database. `Config name` : The config name, for example *system.site*. `Config key` : The config key, for example *page.front*. Leave empty to use the whole config. # Config installer sync mode Available since: 2.1.3 Determine if config installer is in sync mode. ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Collect information on all config collections Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | An information of all Drupal configuration was collected. # Delete config Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | A Drupal configuration was deleted. ## Fields `Config name` : Leave empty to apply to all events. To limit this event to just specific events, provide the machine name of the configuration, e.g. "system.site". This can also be limited to a range of configuration, e.g. with "node.type.", this applies to all configurations with a name starting with this pattern. ``` The configuration name to filter on (e.g., `system.site`). Supports prefix matching. Leave empty to react to all configuration deletions. ``` `Sync Mode` : During config sync, the Drupal site is in sync mode. ``` Filter by sync mode: 'Always' fires regardless, 'Yes' only during config sync, 'No' only for runtime changes. ``` # Import config Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | A Drupal configuration was imported. # Import config but content missing Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | An imported Drupal configuration content was missed. # Import config validation Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | An import of a Drupal configuration was validated. # Rename config Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | A Drupal configuration was renamed. # Save config Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[config]` | The configuration with all current values. | | `[config_original]` | The configuration with all original values plus overrides. | | `[config_name]` | The name of the configuration. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | A Drupal configuration was saved. ## Fields `Config name` : Leave empty to apply to all events. To limit this event to just specific events, provide the machine name of the configuration, e.g. "system.site". This can also be limited to a range of configuration, e.g. with "node.type.", this applies to all configurations with a name starting with this pattern. ``` The configuration name to filter on (e.g., `system.site`). Supports prefix matching: entering `node.type.` matches all content type configurations. Leave empty to react to all configuration saves. ``` `Sync Mode` : During config sync, the Drupal site is in sync mode. ``` Filter by sync mode: 'Always' fires regardless, 'Yes' only during config sync (e.g., `drush config:import`), 'No' only for runtime changes outside of sync. ``` `Write Mode` : Filter by write mode: 'Always' fires for both, 'New' only when configuration is created for the first time, 'Update' only when existing configuration is modified. # ECA Content This module provides lots of actions, conditions and events for content entities. Almost all interactions with content entities are covered. ## Installation ``` composer require drupal/eca drush pm:install eca_content ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Content** from there. # Entity: clone existing Available since: 2.1.0 Clone an existing content entity without saving it. ## Fields `Name of token` : Provide the name of a token that holds the new entity. Please provide the token name only, without brackets. `Entity label` : The label of the new entity. `Published` : Whether the entity should be published or not. `Owner UID` : The owner UID of the new entity. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Entity: set form display Available since: 1.0.0 Change to a specific form display mode. Only works when reacting upon the event *Prepare content entity form*. ## Fields `Form display mode` : The machine name of the display mode. Please note: This action only works when reacting upon the event "Prepare content entity form". # Entity: Set validation error Available since: 2.1.0 Only works when reacting upon *Validate content entity* events. ## Fields `Error message` : This field supports tokens. `Property path` : The optional property path on the entity, where to set the validation error. This may be the machine name of a field (e.g. *body*) or a property of a field. Example: *body.0.value*\ This field supports tokens. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Entity: delete Available since: 1.0.0 Deletes an existing content entity. ## Fields `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: compare Available since: 2.0.0 Compare 2 entities and return a list of fields that differ ## Fields `Return values` : If checked, the list will return values. If unchecked, it will only return the machine names of changed fields. `Name of token` : Provide the name of a token that holds the result list. Please provide the token name only, without brackets. `Second entity` : Provide the name of a token that holds the original entity. Please provide the token name only, without brackets. `Exclude fields` : List machine names of fields that should be ignored. Provide 1 name per line. `Include fields` : List machine names of fields that should be considered for comparison. Provide 1 name per line. Leave this field empty to include all fields, except for the excluded fields. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Entity: get list of bundles Available since: 2.1.0 Gets the list of bundles for a given entity type. ## Fields `Name of token` : Provide the name of a token that holds the bundle list. Please provide the token name only, without brackets. `Type` : The entity type for which to receive the list of bundles.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_get_bundle_list_type* `Mode` : This either returns a list of bundle IDs or of their labels. # Entity: get default field value Available since: 2.0.0 Get the default value of any field in an entity and store it as a token. ## Fields `Field name` : The machine name of the field, that holds the value.\ This field supports tokens. `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Entity: get list of entity types Available since: 2.1.0 Gets the list of entity types. ## Fields `Name of token` : Provide the name of a token that holds the entity types list. Please provide the token name only, without brackets. `Mode` : This either returns a list of entity type IDs or of their labels. # Entity: get field value Available since: 1.0.0 Get the value of any field in an entity and store it as a token. ## Fields `Field name` : The machine name of the field, that holds the value.\ This field supports tokens. `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # List: add entity Available since: 1.1.0 Add a specified entity to a list. ## Fields `Method` : Options of the specific method to add a value to a list.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_list_add_entity_method* `Index key` : When using the method *Set by specified index*, then an index key must be specified here.\ This field supports tokens. `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # List: remove entity Available since: 1.1.0 Remove an entity from a list and optionally store the removed entity as a token. ## Fields `Name of token` : Provide the name of a token that holds the removed entity. Please provide the token name only, without brackets. `Method` : When using the "Defined by token" option, make sure there is a token with this name: *eca_list_remove_entity_method* `Index key` : When using the method *Drop by specified index key*, then an index key must be specified here.\ This field supports tokens. `Token containing the list` : Provide the name of the token that contains a list of items. If the list does not exist yet, a new one will be created. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Entity: create new Available since: 1.0.0 Create a new content entity without saving it. ## Fields `Name of token` : Provide the name of a token that holds the new entity. Please provide the token name only, without brackets. `Type` : The type of the new entity.\ Note: to create a new user entity, enable the eca_user module and use the "User: create new" action from there.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_new_entity_type* `Language` : The language code of the new entity.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_new_entity_langcode* `Entity label` : The label of the new entity. `Published` : Whether the entity should be published or not. `Owner UID` : The owner UID of the new entity. # Entity: save Available since: 1.0.0 Saves a new or updates an existing content entity. ## Fields `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: set field value Available since: 1.0.0 Allows to set, unset or change the value(s) of any field in an entity. How to empty an entity reference field Leaving the **Field value** empty and using the "Set and clear previous value" method does not work for entity reference fields. Instead, use the **Remove value instead of adding it** method and provide the current value of the field (e.g. the entity ID) as the **Field value**. If the removed value is the only value in the field, the field will be empty afterwards. For an example of this, see [this issue](https://www.drupal.org/project/eca/issues/3504388). ## Fields `Field name` : The machine name of the field, that should be changed. Example: *body.value*\ This field supports tokens. `Field value` : The new field value.\ This field supports tokens. `Method` : The method to set an entity, like cleaning the old one, etc..\ When using the "Defined by token" option, make sure there is a token with this name: *eca_set_field_value_method* ``` Available options: ``` - **Set and clear previous value**: Sets the field to the given value. If the field contained any value before, that will be lost, even if this is a multi-value field. - **Set only when empty**: Sets the field to the given value, but only if the field has been empty before. Otherwise, the previous value will be kept and nothing will be set. - **Append when not full yet**: If the field allows multiple values, the given value will be appended as a new item, if the max. cardinality is not reached yet. Otherwise, this action will be skipped. - **Append and drop first when full**: Same as above, but if the max cardinality has been reached, the first value will be removed and the new value appended to the list. - **Append and drop last when full**: Same as above, but instead of dropping the first, this will drop the last item before appending the new value to the list. - **Prepend when not full yet**: If the field allows multiple values, the given value will be inserted as the first item, if the max. cardinality is not reached yet. Otherwise, this action will be skipped. - **Prepend and drop first when full**: Same as above, but if the max cardinality has been reached, the first value will be removed and the new value inserted at the beginning to the list. - **Prepend and drop last when full**: Same as above, but instead of dropping the first, this will drop the last item before inserting the new value at the beginning of the list. - **Remove value instead of adding it**: Remove the value from a field, if it's contained in the list of existing items. If this removes the last remaining value of the field, then the field will be empty (for an example of this, see [this issue](https://www.drupal.org/project/eca/issues/3504388)). `Strip tags` : Remove the tags or not. `Trim` : Trims the field value or not. `Save entity` : Saves the entity or not after setting the value. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: set new revision Available since: 1.0.0 Flags the entity so that a new revision will be created on the next save. ## Fields `Create new revision` : Whether to create a new revision or not `Revision Log` : The optional revision log message.\ This field supports tokens. `Revision user` : The optional revision user. Leave empty to set the current user.\ This field supports tokens. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: set view mode Available since: 2.0.0 Changes the view mode of the entity. Only work after the event "Alter entity view mode". ## Fields `View mode` : The machine name of the view mode.\ This field supports tokens. # Entity: load Available since: 1.0.0 Load a single entity from current scope or by certain properties, and store it as a token. ## Fields `Name of token` : Provide the name of a token that holds the loaded entity. Please provide the token name only, without brackets. `Load entity from` : Loads the entity from the given list and/or properties below.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_from* `Entity type` : The type of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_entity_type* `Entity ID` : The ID of the entity to be loaded. `Revision ID` : The revision ID of the entity to be loaded. `Property values` : A key-value list of raw field values of the entity to load. This will only be used when loading by properties is selected above. Supports YAML format. Example: *field_mynumber: 1*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"*\ This field supports tokens. `Language` : The language code of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_langcode* `Load latest revision` : Whether loading the latest revision or not. `Load unchanged values` : Whether loading the unchanged values of fields or not. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: load via reference Available since: 1.0.0 Load a single entity that is referenced by an entity from the current scope or by certain properties, and store it as a token. ## Fields `Field name entity reference` : The field name of the entity reference.\ This field supports tokens. `Name of token` : Provide the name of a token that holds the loaded entity. Please provide the token name only, without brackets. `Load entity from` : Loads the entity from the given list and/or properties below.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_ref_from* `Entity type` : The type of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_ref_entity_type* `Entity ID` : The ID of the entity to be loaded. `Revision ID` : The revision ID of the entity to be loaded. `Property values` : A key-value list of raw field values of the entity to load. This will only be used when loading by properties is selected above. Supports YAML format. Example: *field_mynumber: 1*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"*\ This field supports tokens. `Language` : The language code of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_entity_ref_langcode* `Load latest revision` : Whether loading the latest revision or not. `Load unchanged values` : Whether loading the unchanged values of fields or not. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Trigger a custom event (entity-aware) Available since: 1.0.0 Triggers a custom event which is entity aware. See [Custom Event Entity Aware](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md), which is listening to this action here. ## Fields `Event ID` : The ID of the event. Leave empty to trigger all custom events. ``` The id of the custom event (entity aware). ``` `Tokens to forward` : Comma separated list of token names from the current context, that will be forwarded to the triggered event. These tokens are then also available for subsequent conditions and actions within the current process. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity form: compare display mode Available since: 1.0.0 Evaluates against the machine name of the entity form display mode. ## Fields `Form display mode` : The machine name of the display mode. Example: *default* `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_content_form_display_mode_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_content_form_display_mode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Entity: compare Available since: 2.0.0 Compares two entities. ## Fields `Name of token` : Provide the name of a token that holds the result list. Please provide the token name only, without brackets. `Second entity` : Provide the name of a token that holds the original entity. Please provide the token name only, without brackets. `Exclude fields` : List machine names of fields that should be ignored. Provide 1 name per line. `Include fields` : List machine names of fields that should be considered for comparison. Provide 1 name per line. Leave this field empty to include all fields, except for the excluded fields. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Entity: exists Available since: 1.0.0 Performs a lookup whether an entity exists and is accessible. ## Fields `Load entity from` : Loads the entity from the given list and/or properties below.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_exists_from* `Entity type` : The type of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_exists_entity_type* `Entity ID` : The ID of the entity to be loaded. `Revision ID` : The revision ID of the entity to be loaded. `Property values` : A key-value list of raw field values of the entity to load. This will only be used when loading by properties is selected above. Supports YAML format. Example: *field_mynumber: 1*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"*\ This field supports tokens. `Language` : The language code of the entity to be loaded.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_exists_langcode* `Load latest revision` : Whether loading the latest revision or not. `Load unchanged values` : Whether loading the unchanged values of fields or not. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: field is accessible Available since: 1.0.0 Evaluates whether the current user has operational access on an entity field. ## Fields `Field machine name` : The machine name of the field to check. `Operation` : The operation, like view, edit or delete to check accessibility.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_field_is_accessible_operation* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: compare field value Available since: 1.0.0 Compares a field value with an expected custom value. ## Fields `Field name` : The name of the field whose value to compare. `Expected field value` : The expected value. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_field_value_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_field_value_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: field value changed Available since: 1.0.0 Evaluates against the change of a value field of an entity. ## Fields `Field name` : The field name of the entity to check, if its value has changed. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: field value is empty Available since: Evaluates if a value field of an entity is empty. ## Fields `Field name` : The field name of the entity to check, if its value is empty. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: is accessible Available since: 1.0.0 Evaluates whether the current user has operational access on an entity. ## Fields `Operation` : The operation, like view, edit or delete to check accessibility.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_is_accessible_operation* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: is new Available since: 1.0.0 Evaluates if an entity is new. ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity: original has field value Available since: 1.0.0 Compares a field value of an entities *original* by specific properties. ## Fields `Field name` : The name of the field whose value to compare. `Expected field value` : The expected value. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_original_field_value_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_original_field_value_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Entity type and bundle Available since: 1.0.0 Evaluates against the entity type and bundle. ## Fields `Entity type (and bundle)` : When using the "Defined by token" option, make sure there is a token with this name: *eca_entity_type_bundle_type* ``` This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. ``` `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Initialize content entity bundle Available since: 1.0.0 An entity bundle object is being created (instantiated) on runtime, without being saved. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:entity_type_id]` | The entity type. | | `[event:bundle]` | The bundle machine name. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when specific content entity bundles are created. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Delete content entity bundle Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:entity_type_id]` | The entity type. | | `[event:bundle]` | The bundle machine name. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when specific content entity bundles are deleted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Initialize content entity Available since: 1.0.0 An entity object is being created (instantiated) on runtime, without being saved. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are created. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # ECA custom event (entity-aware) Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[VARIOUS]` | All tokens forwarded by the dispatcher. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts on an event with a specific ID, when an entity is involved. ## Fields `Event ID` : The id of the custom event (entity aware). Leave empty to trigger all entity aware events. ``` The id of the custom event (entity aware). ``` # Delete content entity Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are deleted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Init content entity field values Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when field values of specific content entities are initialized. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Insert content entity Available since: 1.0.0 After a new entity got saved (persistently created). Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are inserted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Load content entity Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are loaded. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Options field selection Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when entity options of specific content entities are selected. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. `Restrict by field (machine name)` : The machine name of the field to restrict the event trigger. ``` The machine name of the options field to react to. Leave empty to react to all options fields using the ECA handler. ``` `Token name holding the selection` : The name of the token to hold the selection. Please provide the token name only, without brackets. ``` The token name to hold the selection results. After ECA actions run, the values in this token become the allowed options (key-value pairs where keys are option values and values are labels). ``` # Predelete content entity Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts before specific content entities are deleted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Preload content entity Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:entity_type_id]` | The entity type. | | `[event:ids]` | The IDs of the entities. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts before specific content entities are loaded. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Prepare content entity form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when forms of specific content entities are prepared. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Prepare content entity view Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[entity_view_mode]` | The entity view mode. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when views of specific content entities are prepared. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Presave content entity Available since: 1.0.0 Before a new or existing entity gets saved (persistently created or changed). Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts before specific content entities are saved. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Entity reference field selection Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when entity reference field of specific content entities are selected. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. `Restrict by field (machine name)` : The machine name of the field to restrict the event trigger. ``` The machine name of the entity reference field to react to. Leave empty to react to all entity reference fields using the ECA handler. ``` `Token name holding the selection` : The name of the token to hold the selection. Please provide the token name only, without brackets. ``` The token name to hold the selection results. After ECA actions run, the entities in this token become the referenceable entities. ``` # Initialize content entity revision Available since: 1.0.0 An entity revision object is being created (instantiated) on runtime, without being saved. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when revisions of specific content entities are created. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Delete content entity revision Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when revisions of specific content entities are deleted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Load content entity from storage Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are loaded from storage. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Initialize content entity translation Available since: 1.0.0 An entity translation object is being created (instantiated) on runtime, without being saved. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when translations of specific content entities are created. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Delete content entity translation Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when translations of specific content entities are deleted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Insert content entity translation Available since: 1.0.0 After a new entity translation got saved (persistently created). Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when translations of specific content entities are inserted. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Update content entity Available since: 1.0.0 After an existing entity got saved (persistently changed). Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are updated. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Validate content entity Available since: 2.1.0 When an entity is undergoing validation. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when a content entity undergoes validation (e.g., during form submission or REST API operations). Allows adding custom validation rules without writing PHP code. Use conditions and the appropriate validation actions to add violation messages that will prevent the entity from being saved. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # View content entity Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[entity_view_mode]` | The entity view mode. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Reacts when specific content entities are viewed. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # Alter entity view mode Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:view_mode]` | The view mode machine name. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires before an entity is rendered, allowing the view mode to be changed dynamically. Useful for switching between view modes based on user roles, entity field values, or other runtime conditions. ## Fields `Type (and bundle)` : This field provides a list with all created content entities and its bundles. You can also select **-any-**, if you want to react to all types or bundles. # ECA Content Access ## Installation ``` composer require drupal/eca_content_access drush pm:install eca_content_access ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Content Access** from there. # Content access: grant access Available since: 1.0.0 Grants access to an individual node for a role to overwrite settings of the content type. ## Fields `Operation` `User role` `Follow up` `Clear cache` `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. # Content access: revoke access Available since: 1.0.0 Revoke access from an individual node for a role to overwrite settings of the content type. ## Fields `Operation` `User role` `Follow up` `Clear cache` `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. # ECA CrowdSec ## Installation ``` composer require drupal/crowdsec drush pm:install eca_crowdsec ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA CrowdSec** from there. # IP banned Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_ip]` | The ip address. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when an IP address is banned by CrowdSec. The `[event:crowdsec_ip]` token contains the banned IP address. # IP blocked Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_ip]` | The ip address. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when a request from an IP address is blocked by CrowdSec. The `[event:crowdsec_ip]` token contains the blocked IP address. # Scenario list Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_scenario_list]` | The CrowdSec object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when CrowdSec builds the list of scenarios to monitor. Use this to dynamically add or modify scenarios in the list. The `[event:crowdsec_scenario_list]` token provides the current array of scenarios. # IP signalled Available since: 1.0.0 Provided tokens | Token | Description | | --------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_ip]` | The ip address. | | `[event:crowdsec_scenario]` | The CrowdSec scenario. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when an IP address is signalled upstream to the CrowdSec API. The `[event:crowdsec_ip]` token contains the signalled IP address and `[event:crowdsec_scenario]` identifies the triggered scenario. # Signal scenario list Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_scenario_list]` | The CrowdSec object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when CrowdSec builds the list of scenarios for upstream signaling. Use this to control which scenarios are reported to the CrowdSec API. The `[event:crowdsec_scenario_list]` token provides the current array of scenarios. # IP unbanned Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:crowdsec_ip]` | The ip address. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when a previously banned IP address is unbanned by CrowdSec. The `[event:crowdsec_ip]` token contains the unbanned IP address. # ECA: DANSE integration ## Installation ``` composer require drupal/danse drush pm:install eca_danse ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA: DANSE integration** from there. # Recipient Selection Available since: 2.3.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the DANSE (Drupal Advanced Notification System for Entities) module requests recipient selection through ECA. Use this to dynamically determine which users should receive a notification. The `[danse_recipients]` token provides a list to which you can add user entities or user IDs. Each ECA model using this event automatically registers as a DANSE recipient selection plugin. ## Fields `Event ID` : The event ID to trigger this event directly. ``` The event ID to trigger this event directly. Must match the ID used by the DANSE recipient selection plugin dispatching the event. ``` # ECA Endpoint ## Installation ``` composer require drupal/eca drush pm:install eca_endpoint ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Endpoint** from there. # Request: Get client IP Available since: 1.1.0 ## Fields `Name of token` : Please provide the token name only, without brackets. # Request: Get path argument Available since: 1.1.0 ## Fields `Index position` : The index position of the path argument, starting at 0. Example: When index position is set to *2* and the path is */node/1/edit*, then the returned value is *edit*. When empty, the whole requested path will be returned. `Name of token` : Please provide the token name only, without brackets. # Request: Get URL query parameter Available since: 1.1.0 ## Fields `Query parameter name` : The name of the URL query parameter. Example: To get the parameter of the destination parameter *?destination=...*, then set *destination* as the parameter name. When this field is empty, then all parameters will be returned as a list, keyed by parameter name.\ This field supports tokens. `Name of token` : Please provide the token name only, without brackets. # Request: Get content Available since: 1.1.0 ## Fields `Name of token` : Please provide the token name only, without brackets. # Request: Get content type Available since: 1.1.0 ## Fields `Name of token` : Please provide the token name only, without brackets. # Request: Get header Available since: 1.1.0 ## Fields `Header name` : The name / key of the request header. Example: *Content-Type*. When this field is empty, then all headers will be returned as a list, keyed by header name.\ This field supports tokens. `Name of token` : Please provide the token name only, without brackets. # Request: Get method Available since: 1.1.0 ## Fields `Name of token` : Please provide the token name only, without brackets. # Request: Get uri Available since: 1.1.0 ## Fields `Name of token` : Please provide the token name only, without brackets. # Ajax Response: add css Available since: 2.0.0 ## Fields `CSS file` : The href attribute for the styles, e.g. "/my_styles/special.css".\ This field supports tokens. `Media` : This attribute defines which media the style should be applied to.\ This field supports tokens. # Ajax Response: add js Available since: 2.0.0 ## Fields `URL` : The src attribute for the script.\ This field supports tokens. `Clear previous messages` : If TRUE, loading of the script will be deferred. `CSS Selector` : A CSS selector of the element where the script tags will be appended.\ This field supports tokens. # Ajax Response: insert content after Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: set alert Available since: 2.0.0 ## Fields `Message` : The alert message returned to the ajax response.\ This field supports tokens. # Ajax Response: set announcement Available since: 2.0.0 ## Fields `Message` : The message returned to the ajax response.\ This field supports tokens. `Announce priority` : The priority that will be used for the announcement. Defaults to empty/unset which will not set a priority in the response sent to the client and therefore the default of polite will be used for the message.\ This field supports tokens. # Ajax Response: append content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: insert before content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: set changed Available since: 2.0.0 ## Fields `CSS Selector` : CSS selector for elements to be marked as changed.\ This field supports tokens. `Asterisk` : CSS selector for elements to which an asterisk will be appended.\ This field supports tokens. # Ajax Response: close dialog Available since: 2.0.0 ## Fields `CSS Selector` : CSS selector string of the dialog to close; leave empty for the default.\ This field supports tokens. `Persist dialog in DOM` : Whether to persist the dialog in the DOM or not. # Ajax Response: close modal dialog Available since: 2.0.0 ## Fields `Persist dialog in DOM` : Whether to persist the dialog in the DOM or not. # Ajax Response: css Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the CSS should be applied.\ This field supports tokens. `CSS` : An array of CSS properties and values in YAML format.\ This field supports tokens. # Ajax Response: set data attribute Available since: 2.0.0 ## Fields `Selector` : A CSS selector for the elements to which the data will be attached.\ This field supports tokens. `Name` : The key of the data to be attached to elements matched by the selector.\ This field supports tokens. `Value` : The value of the data to be attached to elements matched by the selector.\ This field supports tokens. # Ajax Response: set focus Available since: 2.0.0 ## Fields `Selector` : A CSS selector of the container with tabbable elements.\ This field supports tokens. # Ajax Response: apply html content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: insert content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: invoke Available since: 2.0.0 ## Fields `CSS Selector` : A jQuery selector.\ This field supports tokens. `Method` : The name of a jQuery method to invoke.\ This field supports tokens. `Arguments` : An array of arguments in YAML format that will be passed to the method.\ This field supports tokens. # Ajax Response: set message Available since: 2.0.0 ## Fields `Type` : The message type.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_endpoint_set_ajax_response_message_type* `Message` : The message returned to the ajax response.\ This field supports tokens. `Wrapper Selector` : The CSS selector for the wrapper for messages. Leave empty to use defaults.\ This field supports tokens. `ID` : The message ID, it can be a simple value or several values separated by a space which can be used as an explicit selector for a message.\ This field supports tokens. `Announce` : The CSS selector for the wrapper for messages. Leave empty to use defaults.\ This field supports tokens. `Announce priority` : The priority that will be used for the announcement. Defaults to empty/unset which will not set a priority in the response sent to the client and therefore the default of polite will be used for the message.\ This field supports tokens. `Clear previous messages` : If TRUE, previous messages will be cleared first. # Ajax Response: open dialog Available since: 2.0.0 ## Fields `CSS Selector` : The selector of the dialog.\ This field supports tokens. `Title` : The title of the dialog.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Dialog options` : Options in YAML format to be passed to the dialog implementation. Any jQuery UI option can be used. See https://api.jqueryui.com/dialog.\ This field supports tokens. `Settings` : Custom settings in YAML format that will be passed to the Drupal behaviors on the content of the dialog. If left empty, the settings will be populated automatically from the current request.\ This field supports tokens. # Ajax Response: open modal dialog Available since: 2.0.0 ## Fields `Title` : The title of the dialog.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Dialog options` : Options in YAML format to be passed to the dialog implementation. Any jQuery UI option can be used. See https://api.jqueryui.com/dialog.\ This field supports tokens. `Settings` : Custom settings in YAML format that will be passed to the Drupal behaviors on the content of the dialog. If left empty, the settings will be populated automatically from the current request.\ This field supports tokens. # Ajax Response: open off-canvas dialog Available since: 2.0.0 ## Fields `Position` : The position to render the off-canvas dialog.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_endpoint_set_ajax_response_open_off_canvas_dialog_position* `Title` : The title of the dialog.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Dialog options` : Options in YAML format to be passed to the dialog implementation. Any jQuery UI option can be used. See https://api.jqueryui.com/dialog.\ This field supports tokens. `Settings` : Custom settings in YAML format that will be passed to the Drupal behaviors on the content of the dialog. If left empty, the settings will be populated automatically from the current request.\ This field supports tokens. # Ajax Response: prepend content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: redirect Available since: 2.0.0 ## Fields `URL` : The URL that will be loaded into window.location. This should be a full URL.\ This field supports tokens. # Ajax Response: replace content Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector of the element where the content will be inserted.\ This field supports tokens. `Content` : The content to be inserted.\ This field supports tokens. `Settings` : An array of JavaScript settings in YAML format to be passed to any attached behaviors.\ This field supports tokens. # Ajax Response: reset table striping Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector for the table to be restriped.\ This field supports tokens. # Ajax Response: scroll to top Available since: 2.0.0 ## Fields `CSS Selector` : A CSS selector.\ This field supports tokens. # Ajax Response: set dialog option Available since: 2.0.0 ## Fields `Selector` : The selector of the dialog whose title will be set. If set to an empty value, the default modal dialog will be selected.\ This field supports tokens. `Name` : The name of the option to set. May be any jQuery UI dialog option. See https://api.jqueryui.com/dialog.\ This field supports tokens. `Value` : The value of the option to be passed to the dialog.\ This field supports tokens. # Ajax Response: set dialog title Available since: 2.0.0 ## Fields `Selector` : The selector of the dialog whose title will be set. If set to an empty value, the default modal dialog will be selected.\ This field supports tokens. `Title` : The title that will be set on the dialog.\ This field supports tokens. # Ajax Response: settings Available since: 2.0.0 ## Fields `Settings` : An array of key/value pairs of JavaScript settings in YAML format.\ This field supports tokens. `Merge` : Whether the settings should be merged into the global drupalSettings. # Ajax Response: tabledrag warning Available since: 2.0.0 ## Fields `ID` : The id of the changed row.\ This field supports tokens. `Table instance` : The identifier of the tabledrag instance.\ This field supports tokens. # Ajax Response: update build id Available since: 2.0.0 ## Fields `Old ID` : The old build ID.\ This field supports tokens. `New ID` : The new build ID.\ This field supports tokens. # Response: set content Available since: 1.1.0 ## Fields `Content` : The response content to set.\ This field supports tokens. # Response: set content type Available since: 1.1.0 ## Fields `content_type` : This field supports tokens. # Response: set expires Available since: 1.1.0 ## Fields `Expires` : The date of expiry, either formatted as a date time string, or a UNIX timestamp.\ This field supports tokens. # Response: set headers Available since: 1.1.0 ## Fields `Headers` : The headers to set. If you can also use YAML syntax by enabling it below.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *Content-Type: "text/html; charset=UTF-8"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *Content-Type: "[content_type]"* `Validate YAML to prevent this from being executed when invalid` # Response: set max age Available since: 1.1.0 ## Fields `Client value (max-age)` : The number of seconds for the client-side max age.\ This field supports tokens. `Shared value (s-max-age)` : The number of seconds for the shared max age.\ This field supports tokens. `Set public` : Cacheability is usually only working when the response is set to be public. When not enabled, the response will be set as private. `Set expires` : When enabled, the expires header is automatically derived from the defined max age. # Response: set status code Available since: 1.1.0 ## Fields `Status code` : Must be a valid HTTP status code.\ This field supports tokens. # ECA Endpoint access Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:arguments]` | The arguments of the request path. | | `[event:uid]` | The ID of the user account of the request. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Fires when Drupal checks access to an ECA endpoint URL. Access defaults to denied If no ECA model grants access, the endpoint returns 403 Forbidden. You must explicitly set the access result using the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) action. ## Fields `First path argument` : The **first** path argument to match up. This argument will be resolved from the URL path */eca/**{first}**/{second}*. ``` The first path argument in the endpoint URL (`/eca/{first}/{second}`). This is the primary discriminator for routing to the correct ECA model. ``` `Second path argument` : Optionally specify a second path argument to match up. This argument will be resolved from the URL path */eca/{first}/**{second}***. ``` The optional second path argument in the endpoint URL (`/eca/{first}/{second}`). Leave empty to match any second argument. ``` # ECA Endpoint response Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:path_arguments]` | The arguments of the request path. | | `[event:request]` | The request. | | `[event:request:method]` | The request method, e.g. "GET" or "POST". | | `[event:request:path]` | The requested path. | | `[event:request:query]` | The query arguments of the request. | | `[event:request:headers]` | The request headers. | | `[event:request:content_type]` | The content type of the request. | | `[event:request:content]` | The content of the POST request. | | `[event:request:ip]` | The client IP. | | `[event:uid]` | The ID of the user account of the request. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Attention Don't forget to also add an [ECA Endpoint access](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_access/index.md) to your model, so that you can allow this endpoint to be requested, unless you determine that by some other means. It's likely that you will need the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) for this, which is available from the ECA Access sub-module, that needs to be enabled separately. ## Fields `First path argument` : The **first** path argument to match up. This argument will be resolved from the URL path */eca/**{first}**/{second}*. ``` The first path argument in the endpoint URL (`/eca/{first}/{second}`). This is the primary discriminator for routing to the correct ECA model. ``` `Second path argument` : Optionally specify a second path argument to match up. This argument will be resolved from the URL path */eca/{first}/**{second}***. ``` The optional second path argument in the endpoint URL (`/eca/{first}/{second}`). Leave empty to match any second argument. ``` # ECA Entity Print ## Installation ``` composer require drupal/eca_entity_print drush pm:install eca_entity_print ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Entity Print** from there. # Print file document from entity Available since: 1.0.0 Print file document from a chosen entity and saves it as a file entity. ## Fields `Name of token` : Name of the token available after file document from view render is generated. Contains the file entity. Please provide the token name only, without brackets. `The exported file name` : Provide a name for the generated file.\ This field supports tokens. `Export type` `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Print file document from views output Available since: 1.0.0 Print file document from a chosen view output and saves it as a file entity. ## Fields `View` : Select the view from the list. The view will always return a list of complete entities. `Display` : Write the view `display id` to execute. Set as default to use the default view configuration. `Arguments` : Provide the Contextual filters of the view in order and one by line. This property supports tokens. `Name of token` : Name of the token available after file document from view render is generated. Contains the file entity. Please provide the token name only, without brackets. `The exported file name` : Provide a name for the generated file.\ This field supports tokens. `Export type` # ECA Entity Share Client ## Installation ``` composer require drupal/eca_entity_share_client drush pm:install eca_entity_share_client ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Entity Share Client** from there. # Entity share: Relationship Field Value Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the Entity Share client module processes a relationship field value during entity import. Use this to alter how referenced entities are resolved or mapped on the client side. # ECA Entity Share Server ## Installation ``` composer require drupal/eca_entity_share_server drush pm:install eca_entity_share_server ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Entity Share Server** from there. # Entity share: Channel list prepared Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the Entity Share server module prepares the channel list for sharing. Use this to dynamically alter which channels or entities are available for sharing with remote clients. # ECA File ## Installation ``` composer require drupal/eca drush pm:install eca_file ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA File** from there. # File: rename Available since: 2.1.0 Rename the physical file of a file entity. ## Fields `New file name` : The new file name without schema or path, but with the file extension.\ This field supports tokens. `Behavior` : The behavior when dealing with existing files.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_file_rename_exists_behavior* `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # File: write Available since: 2.1.0 Write data to a physical file of a file entity. ## Fields `File content` : The content to write to the given file.\ This field supports tokens. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # ECA Flag ## Installation ``` composer require drupal/eca_flag drush pm:install eca_flag ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Flag** from there. # Flag: get flagging for entity Available since: 1.0.0 Get a flagging for a content entity. ## Fields `Name of flag` : Provide the name of a flag.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_flag_get_flagging_flag_name* `Name of token` : Provide the name of a token that holds the loaded entity. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Flag: entity flagged Available since: 1.0.0 Performs a lookup whether an entity is flagged. ## Fields `Name of flag` : Provide the name of a flag. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Delete flagging Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[flagging]` | The flagging entity. | | `[flag]` | The flag entity. | | `[entity]` | The flagged entity | | `[event]` | The event. | | `[event:flag]` | The flag entity (if there is only 1 item). | | `[event:flagging]` | The flagging entity (if there is only 1 item). | | `[event:entity]` | The flagged entity (if there is only 1 item). | | `[event:flaggings]` | The flaggings. | | `[event:flaggings:#]` | The index in the list beginning with 0. | | `[event:flaggings:#:flag]` | The flag entity. | | `[event:flaggings:#:flagging]` | The flagging entity. | | `[event:flaggings:#:entity]` | The flagged entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a flagging entity is deleted from the database. This is triggered via Drupal's entity hook system and runs alongside (but independently from) the Unflag event. Tokens `[flagging]`, `[flag]`, and `[entity]` are available when there is exactly one flagging. Use `[event:flaggings:#:flagging]` to iterate when multiple flaggings are involved. # Flag Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[flagging]` | The flagging entity. | | `[flag]` | The flag entity. | | `[entity]` | The flagged entity | | `[event]` | The event. | | `[event:flag]` | The flag entity. | | `[event:flagging]` | The flagging entity. | | `[event:entity]` | The flagged entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an entity is flagged. This event originates from the Flag module and provides the flagging entity. Tokens `[flagging]`, `[flag]`, and `[entity]` give access to the flagging record, the flag configuration, and the flagged entity respectively. # Insert flagging Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[flagging]` | The flagging entity. | | `[flag]` | The flag entity. | | `[entity]` | The flagged entity | | `[event]` | The event. | | `[event:flag]` | The flag entity. | | `[event:flagging]` | The flagging entity. | | `[event:entity]` | The flagged entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a flagging entity is inserted into the database. This is triggered via Drupal's entity hook system and runs alongside (but independently from) the Flag event. Tokens `[flagging]`, `[flag]`, and `[entity]` provide access to the flagging record, the flag configuration, and the flagged entity. # Unflag Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[flagging]` | The flagging entity. | | `[flag]` | The flag entity. | | `[entity]` | The flagged entity | | `[event]` | The event. | | `[event:flag]` | The flag entity (if there is only 1 item). | | `[event:flagging]` | The flagging entity (if there is only 1 item). | | `[event:entity]` | The flagged entity (if there is only 1 item). | | `[event:flaggings]` | The flaggings. | | `[event:flaggings:#]` | The index in the list beginning with 0. | | `[event:flaggings:#:flag]` | The flag entity. | | `[event:flaggings:#:flagging]` | The flagging entity. | | `[event:flaggings:#:entity]` | The flagged entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a previously flagged entity is unflagged. This event originates from the Flag module and may contain multiple flagging records. Tokens `[flagging]`, `[flag]`, and `[entity]` are available when there is exactly one flagging. Use `[event:flaggings:#:flagging]` to iterate over all flaggings when multiple are removed at once. # ECA Form This module allows to change and extend any existing form. Examples: - Disable or hide existing fields - Set fields as required - Add or change available options - Set and change default values - Add new form fields: - Textfield - Checkboxes - Select lists - etc. - Group field elements together - Collapsible HTML details and containers - Validate user input - Set granular form field errors - Execute custom logic on form submissions - Check for any submitted user input and react accordingly - Redirect to a certain page - Make the form a multistep worflow - Optionally with ajax - Build up custom forms from scratch - This ability requires the [ECA Render](https://ecaguide.org/plugins/eca/render/index.md) module to be installed. ## Usage Everything about forms within ECA will most likely be found within this module. As always in ECA, form-related workflows always start with a certain event. This module covers all main form events that occur when Drupal is processing a form. The following events take place, listed ascending in their time occurring order: - **Build form**: This is the earliest form event, also to be seen as the first layer of **form building** events. This type of event happens, when the render array of the form is initially being build up. - **Process form**: This is the second layer of **form building** events. This can and will be used by components that may rely on logic that happened before within the **Build form** event layer. - **After build form**: The third layer of **form building** events. This can be used for internal follow-up actions,\ that don't affect the final result of the form display anymore. All three events listed above are parts of the **form building** events. These types of events are being triggered in order to display a form to a user. Form building events are being triggered at least once when a form is being rendered on a page. It may be called multiple times on the same page, when a component instructs to rebuild a form. Note **One note about fields of content entities:** The processing of content entity fields is usually happening within the second layer of form events, **Process form**. In case you want to change or extend those fields, the earliest event to react upon is a **Process form** event. Reacting upon **Build form** event to work with entity fields will most likely not work. When submitting a form, Drupal always involves two layers: **Validation** and **Submission**. Drupal always first executes the **validation layer**. When the validation layer results with no validation error, then Drupal will execute the **submission layer**. That means, when at least one validation error was found, then Drupal won't execute the submission layer at all. Derived from that core mechanic, ECA offers two according types of events: - **Validate form**: This happens when Drupal executes the validation layer. - **Submit form**: This happens when Drupal executes the submission layer - but only when no validation errors occurred. Typical triggers of form validation and submission are - The user submitted a form by clicking on a submit button (for example "Save" on a content form). - Ajax (JavaScript) that is changing the output of a form without reloading the whole page. Ajax triggering can (but is not forced to) partially or completely suppress validation errors. However, not all Ajax handlers submit a form, and therefore they won't trigger validation and submission. But many ajax handlers do so, because they can instruct the form to completely rebuild, and they do so by submitting the form. - Programmatic client instructions: For example, automated frontend tests that may fake a form submission by sending form input as a POST request to the web server. ### When to use form events Form events are mostly useful to change the output, and to extend validation and submission behavior of an existing form. Whenever data is coming from form input that needs to be processed, form events may help to achieve this. Furthermore, new custom forms can be created by using actions of the [ECA Render](https://ecaguide.org/plugins/eca/render/index.md) module, specifically the action "Render: custom form" is meant for such use case. When it's about adding or changing data of a content entity in general, events of the [ECA Content](https://ecaguide.org/plugins/eca/content/index.md) may be more suitable and preferred over form events. Specifically events such as [Presave content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md), [Insert content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) and [Update content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) may be considered. ### How to configure a form event Any sort of form event always has the following restriction options, in order to specify for which form(s) the event should apply: - **Restrict by form ID**: At most forms, the element ID of the rendered `
` HTML tag can be set here. **Note for developers**: The form ID is being mapped to a machine name of a Drupal form. The machine name of a Drupal form can be found by looking into PHP code. Specifically, it is the method `getFormId` of the according form class, for example `Drupal\system\Form\SiteInformationForm::getFormId` which returns `system_site_information_settings` as the form ID value. When working with entity forms, the other options listed below can be specified instead. - **Restrict by entity type ID**: The machine name of the entity type. When the model should change something on a content item (for example an article), then the machine name is `node`. For a user form, it is `user` and for a taxonomy term it is `taxonomy_term`. - **Restrict by entity bundle**: Besides the entity type ID, it can be additionally restricted to certain bundle(s) only. When the model should be applied only for articles, and the machine name of the content type is `article`, then exactly this machine name can be set here. - **Restrict by operation**: When targeting a specific entity form, this should usually be specified here too. Otherwise, if not specified, this event will apply for any form having the specified type of entity. Besides edit forms, this would also include delete confirmation forms as an example. Unfortunately at this time, the info what operations exist for a specific type of entity, can only be found by looking into PHP code, specifically within the annotation of the according entity class. A `node` has the following operations available: `default` (used for the add form), `edit` (for the edit form) and `delete`. ### Caveats #### Using the form validation event for a different purpose It is generally a bad idea to execute logic within the form validation error that has nothing to do with form validation. This layer should only be used to validate form input. #### Reading and working with submitted form input On simple forms, using the action [Form field: get submitted value](https://ecaguide.org/plugins/eca/form/actions/eca_form_field_get_value/index.md) can be helpful. But for complex forms, such as of a content entity, it may be hard to get any targeted form input value using this action. When the form is about a certain content entity, such an entity can be build up using the action [Entity form: build entity](https://ecaguide.org/plugins/eca/form/actions/eca_form_build_entity/index.md). With that mechanic, one can directly work with an entity, reading and setting field values with actions provided by the [ECA Content](https://ecaguide.org/plugins/eca/content/index.md) module. #### Hiding form fields It is possible to hide a form field by using the action [Form field: set access](https://ecaguide.org/plugins/eca/form/actions/eca_form_field_access/index.md). It should be noted though, that such instruction is only about display logic in a specific form. Many times however, it is about a real access issue. For example, certain users may never be allowed to see a certain field of a content entity. For such case, using components of the [ECA Access](https://ecaguide.org/plugins/eca/access/index.md) module is more advisable. Setting up field access using ECA Access, it makes sure a user will never be able to access a certain field, which includes form displays. ### Examples - [Content validation](https://ecaguide.org/library/forms/content_validation/index.md) ## Installation ``` composer require drupal/eca drush pm:install eca_form ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Form** from there. # Form: add Ajax handler Available since: 1.0.0 Enhances an existing form field element with an Ajax handler for refreshing parts of a form without refreshing the whole page. ## Fields `Disable validation errors` : Enable this option to completely suppress validation errors. `Validate form fields` : Machine names of form fields that should be validated. Define multiple values separated with commas. Example: *first_name,last_name*. When no fields are defined at all and validation is not disabled above, then the whole form will be validated. `Target` : The machine name of the form element target to refresh via Ajax. When empty, then the whole form will be refreshed. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button. When this form element got Ajax handling attached, using this element will automatically submit the form. Therefore, you can react upon that with regular form events like *Build form*, *Submit form* and when validation is enabled, also *Validate form*.\ This field supports tokens. # Form: add container element Available since: 1.0.0 Adds a div block element to the form for surrounding child elements. ## Fields `Element name` : The element name is a machine name and is used for being identified when rendering the form. Example: *name_info* `Optional` : Indicates whether the container should render when it has no visible children. `Element weight` : The lower the weight, the element appears before other elements having a higher weight. # Form: add grouping element Available since: 1.0.0 Add a collapsible details element (also known as fieldset) for grouping form fields. ## Fields `Element name` : The element name is a machine name and is used for being identified when rendering the form. Example: *name_info* `Title` : This will be shown to the user in the form as grouping title. `Open` : Whether the group should be open to edit or collapsed when displayed. `Element weight` : The lower the weight, the element appears before other elements having a higher weight. `Fields` : Machine names of form fields that should be grouped together. Define multiple values separated with commas. Example: *first_name,last_name* `Introduction text` : Here you can set an introduction text of the group. `Summary value` : Here you can set the summary text of the group. `Group` : Here you can set this element to be a part of a parent group.\ This field supports tokens. # Form: add hidden field Available since: 1.0.0 Add a hidden input field to the current form in scope. ## Fields `Value` : The value of the hidden field.\ This field supports tokens. `Field name` : The field name is a machine name and is used for being identified on form submission. Example: *first_name*. It can later be accessed via token *[current_form:values:first_name]*. `Element weight` : The lower the weight, the submit action appears before other submit actions having a higher weight. # Form: add options field Available since: 1.0.0 Add a field with options as radios, checkboxes or select dropdown to the current form in scope. ## Fields `Allow multiple values` : Whether the user can select more than one value in the option field. `Options` : Can be a comma-separated sequence of key-value pairs (e.g. *k1:v1,k2:v2* or a token that holds a list of key-value pairs. Alternatively use YAML syntax to define one key-value pair per line. Example: *key1: "value1"*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Interpret above value as YAML format` : When using YAML format to define the options above, this option needs to be enabled. `Validate YAML to prevent this from being executed when invalid` `Field type` : List of the available types of the field to be added.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_add_optionsfield_type* `Field name` : The field name is a machine name and is used for being identified on form submission. Example: *first_name*. It can later be accessed via token *[current_form:values:first_name]*. `Field title` : The title of the field to be added. `Field description` : The description of the field to be added. `Field is required` : Whether the added field is required or not. `Default value` : The default value if the field is empty. `Element weight` : The lower the weight, the submit action appears before other submit actions having a higher weight. # Form: add submit button Available since: 1.0.0 Add a submit button with a type and a label to a form. ## Fields `Trigger name` : The trigger name must be a machine name and is used for being identified on form submission. Example: *accept*, *send*. It can later be accessed via token *[current_form:triggered]*. `Button label` : The label of the button shown to the user. `Button type` : Here you can select the type of the button from the list.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_add_submit_button_button_type* `Element weight` : The lower the weight, the submit action appears before other submit actions having a higher weight. # Form: add text field Available since: 1.0.0 Add a plain text field, textarea or formatted text to the current form in scope. ## Fields `Field type` : List of the available types of the field to be added.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_add_textfield_type* `Field name` : The field name is a machine name and is used for being identified on form submission. Example: *first_name*. It can later be accessed via token *[current_form:values:first_name]*. `Field title` : The title of the field to be added. `Field description` : The description of the field to be added. `Field is required` : Whether the added field is required or not. `Default value` : The default value if the field is empty. `Element weight` : The lower the weight, the submit action appears before other submit actions having a higher weight. # Entity form: build entity Available since: 1.0.0 Build an entity from submitted form input and store the result as a token. ## Fields `Name of token` : The built entity will be stored into this specified token. Please note: An entity can only be built when a form got submitted. Example events where it works: *Validate form*, *Submit form*. Please provide the token name only, without brackets. # Form field: set access Available since: 1.0.0 Set access to a form field. ## Fields `Set as access` `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: add state Available since: 2.1.0 Add JavaScript state to a form field or element. ## Fields `Selector` : The JQuery selector for the remote element controlling the state of this field.\ This field supports tokens. `State` : The state of this field that should be controlled by the remote element.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_field_add_state_state* `Condition` : The condition of the remote element controlling the state of this field.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_field_add_state_condition* `Value` : The value for the condition. This is only required if "value" or "NOT value" is selected as the condition.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: set default value Available since: 1.0.0 Prepopulates a default value in the form. ## Fields `Value` : The default value to prepopulate.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. `Strip tags` : Whether stripping all *HTML* and *PHP* tags or not. `Trim` : Whether stripping all whitespaces at the beginning and end or not. `Filter XSS` : Additionally filters out possible cross-site scripting (XSS) text. # Form field: set as disabled Available since: 1.0.0 Disable a form field. ## Fields `Set as disabled` `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: get default value Available since: 2.0.0 Get the default value of a form field and store it as a token. ## Fields `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: get options Available since: 2.0.0 Get the available options of an options form field and store it as a token. ## Fields `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: get submitted value Available since: 1.0.0 Get the submitted input of a form field and store it as a token. ## Fields `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. `Strip tags` : Whether stripping all *HTML* and *PHP* tags or not. `Trim` : Whether stripping all whitespaces at the beginning and end or not. `Filter XSS` : Additionally filters out possible cross-site scripting (XSS) text. # Form field: set as required Available since: 1.0.0 Set a form field as required. ## Fields `Set as required` `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: set description Available since: 3.1.1 Defines description on a form field or element. Leave empty to unset. ## Fields `Element description` : The description of the form field or element.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: set validation error Available since: 1.0.0 Shows a validation error with a given message text. ## Fields `Message` : The error message to be shown regards the form field.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button. Leave empty to set a global error on the form.\ This field supports tokens. # Form field: set label Available since: 2.1.0 Defines label on a form field or element. ## Fields `Element label` : The label of the form field or element.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: set options Available since: 1.0.0 Defines available options on an existing multi-value selection, radio or checkbox field. ## Fields `Options` : Can be a comma-separated sequence of key-value pairs (e.g. *k1:v1,k2:v2* or a token that holds a list of key-value pairs. Alternatively use YAML syntax to define one key-value pair per line. Example: *key1: "value1"*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Interpret above value as YAML format` : When using YAML format to define the options above, this option needs to be enabled. `Validate YAML to prevent this from being executed when invalid` `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form field: set value Available since: 1.0.0 Set or overwrite the submitted input value of a form field. This also works to set form field value when a form gets rebuilt, e.g. during an ajax request. ## Fields `Field value` : This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this options needs to be enabled. `Validate YAML to prevent this from being executed when invalid` `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. `Strip tags` : Whether stripping all *HTML* and *PHP* tags or not. `Trim` : Whether stripping all whitespaces at the beginning and end or not. `Filter XSS` : Additionally filters out possible cross-site scripting (XSS) text. # Form field: set weight Available since: 2.1.0 Defines weight on a form field or element. ## Fields `Element weight` : The weight as integer number.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. # Form: get errors Available since: 1.0.0 Makes form errors available as token. ## Fields `Name of token` : The token will hold the list of existing form errors, keyed by form element. For example, when token name is defines as "*errors*", then a specific element may be accessed with *[errors:\]*. Please provide the token name only, without brackets. # Form: set action Available since: 1.1.0 Set the action URL to use when submitting the form. ## Fields `Action URL` : The URL of a form action like *www.example.com/search*.\ This field supports tokens. # Form: set method Available since: 1.1.0 Set the HTTP method to use when submitting the form. ## Fields `Method` : The method of a form action *GET* or *POST*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_set_method_method* # Form state: get property value Available since: 1.0.0 Get a property value of the current form state in scope and set it as a token. ## Fields `Name of token` : The name of the token the property value should be stored into. Please provide the token name only, without brackets. `Name of property` : Nested properties are supported by using dot notation. Example: *level1.level2* # Form state: set property value Available since: 1.0.0 Sets a property value on the current form state in scope, which can be used on validation and submission. ## Fields `Value of the property` : The value of the property to be set.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this options needs to be enabled. `Validate YAML to prevent this from being executed when invalid` `Name of property` : Nested properties are supported by using dot notation. Example: *level1.level2* # Form state: set rebuild Available since: 1.1.0 Flag the form state to rebuild the form again after submission. ## Fields `Enable rebuild` : When enabled, the form state will be flagged to rebuild. If not, the form state will be flagged to not rebuild. # Form state: set redirect Available since: 1.1.0 Set the redirect destination on the form state. ## Fields `Destination URL` : Leave empty to disable redirect on the form state. Please note: External URLs are not supported.\ This field supports tokens. # Form field: exists Available since: 1.0.0 Looks up the current form structure whether a specified field exists. ## Fields `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Form field: compare submitted value Available since: 1.0.0 Compares a submitted form field value. ## Fields `Field value` : The field value to compare.\ This field supports tokens. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button.\ This field supports tokens. `Strip tags` : Whether stripping all *HTML* and *PHP* tags or not. `Trim` : Whether stripping all whitespaces at the beginning and end or not. `Filter XSS` : Additionally filters out possible cross-site scripting (XSS) text. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_field_value_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_field_value_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Form: has any errors Available since: 1.0.0 Checks whether the current form state has any errors. ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Entity form: compare operation Available since: 1.0.0 Evaluates against the machine name of the entity form operation. ## Fields `Operation` : The machine name of the operation. Example: *default, save, delete* `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_operation_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_operation_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Form: is submitted Available since: 1.0.0 Checks whether the current form is submitted. ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Form: compare triggered submission Available since: 1.0.0 Evaluates against the trigger name of the submission. ## Fields `Trigger name` : The trigger name is the machine name of the form submit element. Example: *submit*. A custom trigger name can be defined for example with the action *"Form: add submit button"*. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_triggered_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_form_triggered_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # After build form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the `#after_build` phase, after the complete form tree has been built and all `#process` callbacks have run. The form structure is fully finalized at this point. Tip Useful for modifications that require inspecting the final form structure. ## Fields `Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of form IDs. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). Matching also works on the base form ID (e.g., `node_form` matches all node entity forms regardless of bundle). ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Example: *article, tags* ``` Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` # Build form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during form building, corresponding to Drupal's `hook_form_alter()`. This is the earliest form event in the lifecycle and the best place for adding or modifying form elements, changing field properties, and restructuring the form. Tip This event fires both during the initial GET request (form rendering) and during POST requests (form rebuilds). ## Fields `Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of form IDs. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). Matching also works on the base form ID (e.g., `node_form` matches all node entity forms regardless of bundle). ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Example: *article, tags* ``` Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` # Process form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the form `#process` phase, after form building is complete. At this stage, Drupal's built-in process callbacks have already expanded compound elements (e.g., individual radio buttons within a radios group are now available). Tip This is the most commonly used form event for manipulating form field values, access, options, and labels. ## Fields `Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of form IDs. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). Matching also works on the base form ID (e.g., `node_form` matches all node entity forms regardless of bundle). ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Example: *article, tags* ``` Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` # Submit form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the form's own submit handler has run. At this stage, validation has passed and the submitted values are available. Tip For entity forms, the `[entity]` token contains the entity built from submitted form values. Attention This event does not provide a render array -- render-array-specific actions are not available during submission. ## Fields `Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of form IDs. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). Matching also works on the base form ID (e.g., `node_form` matches all node entity forms regardless of bundle). ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Example: *article, tags* ``` Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` # Validate form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the form's own validation logic has completed. Use this event to add custom validation errors or inspect validation state. Only fires on form submission, not during initial form rendering. Attention This event does not provide a render array -- render-array-specific actions are not available during validation. ## Fields `Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of form IDs. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). Matching also works on the base form ID (e.g., `node_form` matches all node entity forms regardless of bundle). ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Example: *article, tags* ``` Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` `Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` # Build inline entity form Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[entity]` | The form entity. | | `[ENTITY_TYPE]` | The form entity with the token name being the ID of the entity type. | | `[parent]` | The parent entity, if one exists. | | `[event]` | The event. | | `[event:delta]` | The delta of the entity reference in the parent field. | | `[event:entity]` | The form entity. | | `[event:entity_bundle]` | The bundle of the form entity. | | `[event:entity_id]` | The form entity ID, only available if the entity is not new. | | `[event:entity_type]` | The form entity type. | | `[event:field_name]` | The name of the field. | | `[event:parent]` | The parent entity, if one exists. | | `[event:parent_bundle]` | The bundle of the parent entity, if one exists. | | `[event:parent_id]` | The ID of the parent entity, if one exists and it is not new. | | `[event:parent_type]` | The type of the parent entity, if one exists | | `[event:widget]` | The form widget ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when an inline entity form is being built, either through the Inline Entity Form (IEF) module or the Paragraphs module. The form reference in this event is the **subform** (the inline entity's form), not the parent form. Tip The `[event:entity]` token holds the inline entity (e.g., a paragraph or media item), while `[event:parent]` holds the parent entity (e.g., the node). Additional tokens include `[event:field_name]`, `[event:delta]`, and `[event:widget]`. ## Fields `Parent: Restrict by form ID` : The form ID can be mostly found in the HTML element as "id" attribute. ``` Comma-separated list of **parent** form IDs to match. Matches the form that contains the inline entity form, not the inline entity form itself. You can use either the HTML form ID (with hyphens) or the Drupal machine name (with underscores). ``` `Restrict by entity type ID` : Example: *media, paragraph, storage* ``` Only fires for entity forms. Restricts to the specified entity type (e.g., `node`, `taxonomy_term`, `user`). ``` Tip When left empty along with bundle and operation, the event also fires for non-entity forms. `Restrict by entity bundle` : Only applies to entity forms. Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. `Parent: Restrict by operation` : Example: *default, save, delete* ``` Only applies to entity forms. Restricts to the specified form operation (e.g., `default`, `edit`, `delete`). Comma-separated for multiple values. ``` `Parent: Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified parent entity type (e.g., `node`). Comma-separated for multiple values. ``` `Parent: Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified parent entity bundle (e.g., `article`). Comma-separated for multiple values. ``` `Parent: Restrict by field name` : Example: *field_paragraphs* ``` The field name on the parent entity that renders this inline entity form (e.g., `field_paragraphs`). Comma-separated for multiple values. ``` # ECA GitLab API ## Installation ``` composer require drupal/gitlab_api drush pm:install eca_gitlab_api ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA GitLab API** from there. # Deploy Keys: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:deploykeys_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Deployments: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:deployments_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Deployments: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:deployments_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Deployment Id` : This field supports tokens. # Environments: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:environments_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Environments: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:environments_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Environments: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:environments_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Environment Id` : This field supports tokens. # Environments: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:environments_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Environment Id` : This field supports tokens. # Environments: stop ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:environments_stop_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Environment Id` : This field supports tokens. # Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:events_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: add Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_addlabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups: add Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_addmember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `User Id` : This field supports tokens. `Access Level` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: add Share ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_addshare_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: add Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_addvariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Key` : This field supports tokens. `Value` : This field supports tokens. `Protected` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: all Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_allmember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `User Id` : This field supports tokens. # Groups: all Members ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_allmembers_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Name` : This field supports tokens. `Path` : This field supports tokens. `Description` : This field supports tokens. `Visibility` : This field supports tokens. `Lfs Enabled` : This field supports tokens. `Request Access Enabled` : This field supports tokens. `Parent Id` : This field supports tokens. `Shared Runners Minutes Limit` : This field supports tokens. # Groups: create Deploy Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_createdeploytoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: delete Deploy Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_deletedeploytoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Token Id` : This field supports tokens. # Groups: deploy Tokens ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_deploytokens_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Active` : This field supports tokens. # Groups: issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_issues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: iterations ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_iterations_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: labels ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_labels_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_member_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `User Id` : This field supports tokens. # Groups: members ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_members_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: merge Requests ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_mergerequests_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: packages ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_packages_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: projects ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_projects_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. # Groups: remove Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_removelabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Label Id` : This field supports tokens. # Groups: remove Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_removemember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `User Id` : This field supports tokens. # Groups: remove Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_removevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Key` : This field supports tokens. # Groups: save Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_savemember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `User Id` : This field supports tokens. `Access Level` : This field supports tokens. # Groups: search ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_search_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Groups: subgroups ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_subgroups_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups: transfer ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_transfer_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Project Id` : This field supports tokens. # Groups: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups: update Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_updatelabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Label Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups: update Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_updatevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Key` : This field supports tokens. `Value` : This field supports tokens. `Protected` : This field supports tokens. # Groups: variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_variable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Key` : This field supports tokens. # Groups: variables ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groups_variables_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups Boards: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups Boards: all Lists ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_alllists_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. # Groups Boards: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups Boards: create List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_createlist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. `Label Id` : This field supports tokens. # Groups Boards: delete List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_deletelist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. # Groups Boards: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. # Groups Boards: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. # Groups Boards: show List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_showlist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. # Groups Boards: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups Boards: update List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsboards_updatelist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. `Position` : This field supports tokens. # Groups Epics: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups Epics: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups Epics: issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_issues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Epic Iid` : This field supports tokens. # Groups Epics: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Epic Id` : This field supports tokens. # Groups Epics: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Epic Id` : This field supports tokens. # Groups Epics: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsepics_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Epic Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups Milestones: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Groups Milestones: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Groups Milestones: issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_issues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Groups Milestones: merge Requests ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_mergerequests_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Groups Milestones: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Groups Milestones: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Groups Milestones: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:groupsmilestones_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Milestone Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issue Boards: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issue Boards: all Lists ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_alllists_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. # Issue Boards: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issue Boards: create List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_createlist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. `Label Id` : This field supports tokens. # Issue Boards: delete List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_deletelist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. # Issue Boards: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. # Issue Boards: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. # Issue Boards: show List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_showlist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. # Issue Boards: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issue Boards: update List ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issueboards_updatelist_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Board Id` : This field supports tokens. `List Id` : This field supports tokens. `Position` : This field supports tokens. # Issue Links: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuelinks_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issue Links: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuelinks_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Target Project Id` : This field supports tokens. `Target Issue Iid` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issue Links: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuelinks_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Issue Link Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issues: add Discussion ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_adddiscussion_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Body` : This field supports tokens. # Issues: add Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_adddiscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Body` : This field supports tokens. # Issues: add Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_addnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Body` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issues: add Spent Time ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_addspenttime_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Duration` : This field supports tokens. # Issues: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issues: award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_awardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: closed By Merge Requests ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_closedbymergerequests_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issues: get Time Stats ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_gettimestats_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: group ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_group_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issues: move ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_move_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `To Project Id` : This field supports tokens. # Issues: related Merge Requests ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_relatedmergerequests_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: remove Award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_removeawardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Award Id` : This field supports tokens. # Issues: remove Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_removediscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Note Id` : This field supports tokens. # Issues: remove Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_removenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Note Id` : This field supports tokens. # Issues: reorder ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_reorder_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issues: reset Spent Time ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_resetspenttime_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: reset Time Estimate ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_resettimeestimate_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: set Time Estimate ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_settimeestimate_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Duration` : This field supports tokens. # Issues: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: show Discussion ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_showdiscussion_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. # Issues: show Discussions ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_showdiscussions_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: show Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_shownote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Note Id` : This field supports tokens. # Issues: show Notes ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_shownotes_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: show Participants ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_showparticipants_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: show Resource Label Event ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_showresourcelabelevent_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Label Event Id` : This field supports tokens. # Issues: show Resource Label Events ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_showresourcelabelevents_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: subscribe ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_subscribe_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: unsubscribe ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_unsubscribe_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Issues: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issues: update Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_updatediscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Note Id` : This field supports tokens. `Body` : This field supports tokens. # Issues: update Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issues_updatenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Note Id` : This field supports tokens. `Body` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Issues Statistics: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuesstatistics_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issues Statistics: group ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuesstatistics_group_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Group Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Issues Statistics: project ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:issuesstatistics_project_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Jobs: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Jobs: artifact By Job Id ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_artifactbyjobid_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. `Artifact Path` : This field supports tokens. # Jobs: artifact By Ref Name ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_artifactbyrefname_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Ref Name` : This field supports tokens. `Job Name` : This field supports tokens. `Artifact Path` : This field supports tokens. # Jobs: artifacts ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_artifacts_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: artifacts By Ref Name ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_artifactsbyrefname_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Ref Name` : This field supports tokens. `Job Name` : This field supports tokens. # Jobs: cancel ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_cancel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: erase ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_erase_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: keep Artifacts ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_keepartifacts_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: pipeline Bridges ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_pipelinebridges_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Jobs: pipeline Jobs ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_pipelinejobs_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Jobs: play ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_play_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: retry ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_retry_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Jobs: trace ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:jobs_trace_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Job Id` : This field supports tokens. # Keys: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:keys_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Merge Requests: add Discussion ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_adddiscussion_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Merge Requests: add Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_adddiscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Body` : This field supports tokens. # Merge Requests: add Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_addnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Body` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Merge Requests: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: approvals ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_approvals_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: approval State ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_approvalstate_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: approve ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_approve_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_awardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: changes ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_changes_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: closes Issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_closesissues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: commits ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_commits_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Source` : This field supports tokens. `Target` : This field supports tokens. `Title` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: create Level Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_createlevelrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Name` : This field supports tokens. `Approvals Required` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: delete Level Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_deletelevelrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Approval Rule Id` : This field supports tokens. # Merge Requests: level Rules ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_levelrules_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: merge ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_merge_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: rebase ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_rebase_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Merge Requests: remove Award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_removeawardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Award Id` : This field supports tokens. # Merge Requests: remove Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_removediscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Note Id` : This field supports tokens. # Merge Requests: remove Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_removenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Note Id` : This field supports tokens. # Merge Requests: resolve Discussion ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_resolvediscussion_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Resolved` : This field supports tokens. # Merge Requests: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: show Discussion ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_showdiscussion_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. # Merge Requests: show Discussions ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_showdiscussions_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: show Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_shownote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Note Id` : This field supports tokens. # Merge Requests: show Notes ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_shownotes_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: show Participants ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_showparticipants_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: unapprove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_unapprove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. # Merge Requests: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: update Discussion Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_updatediscussionnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Discussion Id` : This field supports tokens. `Note Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Merge Requests: update Level Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_updatelevelrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Approval Rule Id` : This field supports tokens. `Name` : This field supports tokens. `Approvals Required` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Merge Requests: update Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:mergerequests_updatenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Mr Iid` : This field supports tokens. `Note Id` : This field supports tokens. `Body` : This field supports tokens. # Milestones: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Milestones: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Milestones: issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_issues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Milestones: merge Requests ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_mergerequests_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Milestones: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Milestones: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Milestone Id` : This field supports tokens. # Milestones: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:milestones_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Milestone Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Project Namespaces: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projectnamespaces_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Project Namespaces: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projectnamespaces_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Namespace Id` : This field supports tokens. # Projects: add Badge ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addbadge_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Deploy Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_adddeploykey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Title` : This field supports tokens. `Key` : This field supports tokens. `Canpush` : This field supports tokens. # Projects: add Hook ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addhook_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Url` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addlabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addmember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `User Id` : This field supports tokens. `Access Level` : This field supports tokens. `Expires At` : This field supports tokens. # Projects: add Protected Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addprotectedbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Protected Tag ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addprotectedtag_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Share ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addshare_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: add Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_addvariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key` : This field supports tokens. `Value` : This field supports tokens. `Protected` : This field supports tokens. `Environment Scope` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: all Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_allmember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `User Id` : This field supports tokens. # Projects: all Members ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_allmembers_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: approvals Configuration ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_approvalsconfiguration_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: approvals Rules ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_approvalsrules_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: archive ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_archive_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: badge ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_badge_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Badge Id` : This field supports tokens. # Projects: badges ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_badges_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: boards ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_boards_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: cancel Pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_cancelpipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Name` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: create Approvals Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createapprovalsrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: create Deploy Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createdeploytoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: create Fork Relation ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createforkrelation_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Forked Project Id` : This field supports tokens. # Projects: create For User ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createforuser_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Name` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: create Pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createpipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Commit Ref` : This field supports tokens. `Variables` : This field supports tokens. # Projects: create Project Access Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createprojectaccesstoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: create Trigger ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_createtrigger_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Description` : This field supports tokens. # Projects: delete All Merged Branches ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deleteallmergedbranches_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: delete Approvals Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deleteapprovalsrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Approval Rule Id` : This field supports tokens. # Projects: delete Deploy Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deletedeploykey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key Id` : This field supports tokens. # Projects: delete Deploy Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deletedeploytoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Token Id` : This field supports tokens. # Projects: delete Pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deletepipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: delete Project Access Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deleteprojectaccesstoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Token Id` : This field supports tokens. # Projects: delete Protected Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deleteprotectedbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch Name` : This field supports tokens. # Projects: delete Protected Tag ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deleteprotectedtag_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. # Projects: deploy Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deploykey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key Id` : This field supports tokens. # Projects: deploy Keys ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deploykeys_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: deployment ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deployment_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Deployment Id` : This field supports tokens. # Projects: deployments ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deployments_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: deploy Tokens ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_deploytokens_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Active` : This field supports tokens. # Projects: disable Runner ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_disablerunner_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Runner Id` : This field supports tokens. # Projects: enable Deploy Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_enabledeploykey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key Id` : This field supports tokens. # Projects: enable Runner ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_enablerunner_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Runner Id` : This field supports tokens. # Projects: events ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_events_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: fork ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_fork_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: forks ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_forks_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: get Repository Commit Discussions ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_getrepositorycommitdiscussions_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Commit Id` : This field supports tokens. # Projects: hook ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_hook_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Hook Id` : This field supports tokens. # Projects: hooks ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_hooks_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: issues ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_issues_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: iterations ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_iterations_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: labels ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_labels_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: languages ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_languages_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_member_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `User Id` : This field supports tokens. # Projects: members ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_members_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: pipeline Jobs ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipelinejobs_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: pipelines ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipelines_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: pipeline Test Report ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipelinetestreport_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: pipeline Test Report Summary ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipelinetestreportsummary_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: pipeline Variables ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_pipelinevariables_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: project Access Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_projectaccesstoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Token Id` : This field supports tokens. # Projects: project Access Tokens ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_projectaccesstokens_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: protected Branches ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_protectedbranches_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: protected Tag ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_protectedtag_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. # Projects: protected Tags ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_protectedtags_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: remove Badge ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removebadge_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Badge Id` : This field supports tokens. # Projects: remove Fork Relation ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removeforkrelation_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: remove Hook ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removehook_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Hook Id` : This field supports tokens. # Projects: remove Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removelabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Label Id` : This field supports tokens. # Projects: remove Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removemember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `User Id` : This field supports tokens. # Projects: remove Service ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removeservice_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Service Name` : This field supports tokens. # Projects: remove Share ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removeshare_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Group Id` : This field supports tokens. # Projects: remove Trigger ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removetrigger_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Trigger Id` : This field supports tokens. # Projects: remove Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_removevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: retry Pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_retrypipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Pipeline Id` : This field supports tokens. # Projects: save Member ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_savemember_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `User Id` : This field supports tokens. `Access Level` : This field supports tokens. `Expires At` : This field supports tokens. # Projects: search ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_search_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: set Service ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_setservice_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Service Name` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: transfer ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_transfer_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Namespace` : This field supports tokens. # Projects: trigger ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_trigger_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Trigger Id` : This field supports tokens. # Projects: trigger Pipeline ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_triggerpipeline_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Ref` : This field supports tokens. `Token` : This field supports tokens. `Variables` : Provide a YAML array.\ This field supports tokens. # Projects: triggers ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_triggers_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: unarchive ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_unarchive_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Projects: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Approvals Configuration ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updateapprovalsconfiguration_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Approvals Rule ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updateapprovalsrule_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Approval Rule Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Badge ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updatebadge_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Badge Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Hook ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updatehook_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Hook Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Label ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updatelabel_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Label Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Protected Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updateprotectedbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch Name` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: update Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_updatevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key` : This field supports tokens. `Value` : This field supports tokens. `Protected` : This field supports tokens. `Environment Scope` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: upload Avatar ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_uploadavatar_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `File` : This field supports tokens. # Projects: upload File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_uploadfile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `File` : This field supports tokens. # Projects: users ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_users_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_variable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Key` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Projects: variables ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:projects_variables_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: archive ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_archive_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. `Format` : This field supports tokens. # Repositories: branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_branch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. # Repositories: branches ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_branches_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: cherry Pick ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_cherrypick_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Repositories: commit ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_commit_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. # Repositories: commit Comments ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_commitcomments_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: commit Refs ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_commitrefs_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: commits ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_commits_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: compare ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_compare_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Fromshaormaster` : This field supports tokens. `Toshaormaster` : This field supports tokens. `Straight` : This field supports tokens. `Fromprojectid` : This field supports tokens. # Repositories: contributors ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_contributors_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Repositories: create Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_createbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. `Ref` : This field supports tokens. # Repositories: create Commit ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_createcommit_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: create Commit Comment ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_createcommitcomment_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `Note` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Repositories: create Release ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_createrelease_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. `Description` : This field supports tokens. `Name` : This field supports tokens. # Repositories: create Tag ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_createtag_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Name` : This field supports tokens. `Ref` : This field supports tokens. `Message` : This field supports tokens. # Repositories: delete Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_deletebranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. # Repositories: diff ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_diff_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. # Repositories: get Commit Build Status ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_getcommitbuildstatus_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Repositories: merge Base ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_mergebase_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Refs` : Provide a YAML array.\ This field supports tokens. # Repositories: post Commit Build Status ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_postcommitbuildstatus_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Sha` : This field supports tokens. `State` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Repositories: protect Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_protectbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. `Devpush` : This field supports tokens. `Devmerge` : This field supports tokens. # Repositories: releases ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_releases_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Repositories: revert Commit ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_revertcommit_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. `Sha` : This field supports tokens. # Repositories: tags ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_tags_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repositories: tree ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_tree_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Repositories: unprotect Branch ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_unprotectbranch_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Branch` : This field supports tokens. # Repositories: update Release ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositories_updaterelease_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. `Description` : This field supports tokens. `Name` : This field supports tokens. # Repository Files: create File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositoryfiles_createfile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repository Files: delete File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositoryfiles_deletefile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Repository Files: get File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositoryfiles_getfile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `File Path` : This field supports tokens. `Ref` : This field supports tokens. # Repository Files: get Raw File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositoryfiles_getrawfile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `File Path` : This field supports tokens. `Ref` : This field supports tokens. # Repository Files: update File ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:repositoryfiles_updatefile_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Resource Iteration Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourceiterationevents_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Resource Iteration Events: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourceiterationevents_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Iteration Event Id` : This field supports tokens. # Resource Label Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcelabelevents_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Resource Label Events: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcelabelevents_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Label Event Id` : This field supports tokens. # Resource Milestone Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcemilestoneevents_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Resource Milestone Events: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcemilestoneevents_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Milestone Event Id` : This field supports tokens. # Resource State Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcestateevents_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Resource State Events: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourcestateevents_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Label Event Id` : This field supports tokens. # Resource Weight Events: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourceweightevents_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. # Resource Weight Events: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:resourceweightevents_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Issue Iid` : This field supports tokens. `Resource Label Event Id` : This field supports tokens. # Schedules: add Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_addvariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Schedules: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Schedules: play ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_play_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. # Schedules: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. # Schedules: remove Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_removevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. `Variable Key` : This field supports tokens. # Schedules: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. # Schedules: show All ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_showall_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Schedules: take Ownership ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_takeownership_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. # Schedules: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Schedules: update Variable ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:schedules_updatevariable_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Schedule Id` : This field supports tokens. `Variable Key` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Search: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:search_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Snippets: add Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_addnote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Body` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Snippets: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. # Snippets: award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_awardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. # Snippets: content ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_content_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. # Snippets: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Title` : This field supports tokens. `Filename` : This field supports tokens. `Code` : This field supports tokens. `Visibility` : This field supports tokens. # Snippets: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. # Snippets: remove Award Emoji ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_removeawardemoji_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Award Id` : This field supports tokens. # Snippets: remove Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_removenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Note Id` : This field supports tokens. # Snippets: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. # Snippets: show Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_shownote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Note Id` : This field supports tokens. # Snippets: show Notes ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_shownotes_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. # Snippets: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Snippets: update Note ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:snippets_updatenote_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Snippet Id` : This field supports tokens. `Note Id` : This field supports tokens. `Body` : This field supports tokens. # System Hooks: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:systemhooks_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # System Hooks: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:systemhooks_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Url` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # System Hooks: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:systemhooks_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # System Hooks: test ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:systemhooks_test_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Tags: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Tags: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Tags: create Release ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_createrelease_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Tags: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. # Tags: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. # Tags: update Release ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:tags_updaterelease_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Tag Name` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Users: activate ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_activate_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: all ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_all_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Parameters` : Provide a YAML array.\ This field supports tokens. # Users: block ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_block_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Email` : This field supports tokens. `Password` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Users: create Email For User ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_createemailforuser_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Email` : This field supports tokens. `Skip Confirmation` : This field supports tokens. # Users: create Impersonation Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_createimpersonationtoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Name` : This field supports tokens. `Scopes` : Provide a YAML array.\ This field supports tokens. `Expires At` : This field supports tokens. # Users: create Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_createkey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Title` : This field supports tokens. `Key` : This field supports tokens. # Users: create Key For User ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_createkeyforuser_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Title` : This field supports tokens. `Key` : This field supports tokens. # Users: deactivate ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_deactivate_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: email ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_email_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: emails ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_emails_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # Users: events ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_events_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Users: key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_key_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: keys ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_keys_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # Users: me ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_me_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # Users: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Users: remove Impersonation Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_removeimpersonationtoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Impersonation Token Id` : This field supports tokens. # Users: remove Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_removekey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: remove User Email ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_removeuseremail_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Email Id` : This field supports tokens. # Users: remove User Identity ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_removeuseridentity_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Provider` : This field supports tokens. # Users: remove User Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_removeuserkey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Key Id` : This field supports tokens. # Users: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: unblock ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_unblock_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. # Users: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. `Files` : Provide a YAML array.\ This field supports tokens. # Users: user ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_user_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # Users: user Emails ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_useremails_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. # Users: user Impersonation Token ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_userimpersonationtoken_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Impersonation Token Id` : This field supports tokens. # Users: user Impersonation Tokens ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_userimpersonationtokens_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Users: user Key ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_userkey_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. `Key Id` : This field supports tokens. # Users: user Keys ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_userkeys_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `User Id` : This field supports tokens. # Users: users Memberships ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_usersmemberships_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Users: users Projects ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_usersprojects_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Users: users Starred Projects ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:users_usersstarredprojects_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Id` : This field supports tokens. `Parameters` : Provide a YAML array.\ This field supports tokens. # Version: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:version_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. # Wiki: create ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:wiki_create_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Wiki: remove ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:wiki_remove_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Wiki Slug` : This field supports tokens. # Wiki: show ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:wiki_show_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Wiki Slug` : This field supports tokens. # Wiki: show All ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:wiki_showall_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # Wiki: update ## Fields `GitLab Instance` : When using the "Defined by token" option, make sure there is a token with this name: *eca_gitlab_api_command:wiki_update_gitlab* `Name of token` : The result of the API call will be stored in this token. Please provide the token name only, without brackets. `Project Id` : This field supports tokens. `Wiki Slug` : This field supports tokens. `Params` : Provide a YAML array.\ This field supports tokens. # ECA Helper ## Installation ``` composer require drupal/eca_helper drush pm:install eca_helper ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Helper** from there. # ECA Helper: Set cookie Available since: unknown Action cookie value for response. ## Fields `Cookie name` : The cookie name `Cookie value` : The cookie value. `Expiration time` : The cookie expiration time. Value can timespan or date string. Use 0 for never expired. `Cookie path` : The cookie path. # ECA Helper: Form add css class Available since: unknown Add form css class. ## Fields `Value` : The element value.\ This field supports tokens. # ECA Helper: Form attach library Available since: unknown Attach library with to a form. ## Fields `Value` : The element value.\ This field supports tokens. # ECA Helper: Form field get value Available since: unknown Get form field value. ## Fields `Element key` : The element key to get value for the form element. Example #title, #attributes.class\ This field supports tokens. `Name of response token` : The response value will be loaded into this specified token. Please provide the token name only, without brackets. `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button. Use *!!form* for the current form instead of form element.\ This field supports tokens. # ECA Helper: Form field set value Available since: unknown Set form field value. ## Fields `Field name` : The input name of the form field. This is mostly found in the "name" attribute of an form element. *For submit buttons within content forms:* Use "submit" for the labeled "Save" button, and "preview" for the labeled "Preview" button. Use *!!form* for the current form instead of form element.\ This field supports tokens. `Element key` : The element key to set value for the form element. Example #title, #attributes.class\ This field supports tokens. `Value` : The element value.\ This field supports tokens. `Value in YAML` : Value in the YAML format. `Set array value` : Set or append data to array value. `Method` : The method to set value when use Set array value. # ECA Helper: Header footer tag and script Available since: unknown Add header footer tag, script and style. ## Fields `Position` : Choose position insert tag. `Tag type` : Select tag type. `Tag content` : Input tag content. # ECA Helper: Remove headers Available since: unknown Action remove headers value for response. ## Fields `Headers` : The headers to set. If you can also use YAML syntax by enabling it below.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *Content-Type: "text/html; charset=UTF-8"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *Content-Type: "[content_type]"* # ECA Helper: Set headers Available since: unknown Action set headers value for response. ## Fields `Headers` : The headers to set. If you can also use YAML syntax by enabling it below.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *Content-Type: "text/html; charset=UTF-8"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *Content-Type: "[content_type]"* # ECA Helper: Http Request Available since: unknown Add Http request for ECA ## Fields `Method` `URL` `Data` `Data YAML` : Use Data as yaml format. `Data Serialization` `Query Parameters` : YAML format, for example mykey: myvalue. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: title: "[node:title]" `Headers` : Headers with YAML format. `Cookies` : Cookies with YAML format. `Options` : The Guzzle request options with YAML format. Reference: https://docs.guzzlephp.org/en/stable/request-options.html `Name of response token` : The response value will be loaded into this specified token. You can access [token_name:body] raw response, [token_name:json] when return is valid json, [token_name:headers], [token_name:status], [token_name:client_error] > 0 when has problem. Please provide the token name only, without brackets. # ECA Helper: Preprocess attach library Available since: unknown Attach library with preproces event. ## Fields `Value` : The element value.\ This field supports tokens. # ECA Helper: Preprocess get value Available since: unknown Get element value from preprocess event. ## Fields `Element key` : The element key to get value for the preprocess. Example #title, #attributes.class\ This field supports tokens. `Name of response token` : The response value will be loaded into this specified token. Please provide the token name only, without brackets. # ECA Helper: Preprocess remove item Available since: unknown Remove item by key with preprocess. ## Fields `Element key` : The element key to remove value for the form element. Example #title, #attributes.class\ This field supports tokens. # ECA Helper: Preprocess add css class Available since: unknown Set css class with preproces event. ## Fields `Value` : The element value.\ This field supports tokens. # ECA Helper: Preprocess set value Available since: unknown Set Preprocess variables value. ## Fields `Element key` : The element key to set value for the form element. Example #title, #attributes.class\ This field supports tokens. `Value` : The element value.\ This field supports tokens. `Value in YAML` : Value in the YAML format. `Set array value` : Set or append data to array value. `Method` : The method to set value when use Set array value. # ECA Helper: Quick Action Available since: unknown Quick call custom action for ECA ## Fields `Action` : Select the action `Arguments` : The arguments of the action in the YAML format. `Name of result token` : The result value after call the action will be loaded into this specified token. Please provide the token name only, without brackets. # ECA Helper: Get route name Available since: unknown Get current route name. ## Fields `Name of token` : The route name value will be loaded into this specified token. Please provide the token name only, without brackets. # ECA Helper: Get SERVER Variable Available since: unknown Action get PHP $\_SERVER, $\_COOKIE, $\_SESSION, $\_ENV, $\_GET, $\_POST variable ## Fields `Variable Type` : Select the variable type `Variable` : The name of server variable need to get data. This support token. `Debug` : Enable debug will log all server variable to log messages. `Name of response token` : The response value will be loaded into this specified token. Please provide the token name only, without brackets. # ECA Helper: Status Messages Alter Available since: unknown Action allow alter status messages content. ## Fields `Message value` : Input the message value. Leave blank to use the remove the message. # ECA Helper: Get/Set ThirdPartySetting Available since: unknown Get/Set ThirdPartySetting of instance. ## Fields `Instance` : The name of instance to Get/Set ThirdPartySetting. Please provide the token name only, without brackets. `Method` : Select method for GET or SET for ThirdPartySetting `Module` : The name of module to Get/Set ThirdPartySetting. `Key` : The name of key value to Get/Set ThirdPartySetting. `Value` : The value of key to Get/Set ThirdPartySetting. `Name of response token` : The response value of Get ThirdPartySetting will be loaded into this specified token. Please provide the token name only, without brackets. # ECA Helper: Preprocess Available since: unknown Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during theme preprocessing, allowing you to alter template variables before rendering. Select a specific preprocess hook to target (e.g., `node`, `page`, `block`) or listen to all hooks. The `[hook]` token identifies the current preprocess hook being executed. ## Fields This event provides tokens: "[hook]" the preprocess hook id to identify. # ECA Helper: Status Messages Available since: unknown Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The status messages event. Support [event:type], [event:message]. | | `[event:type]` | The message type. | | `[event:message]` | The message content. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a Drupal status message is about to be displayed. Use this to alter or suppress messages before they reach the user. The `[event:type]` token contains the message type (e.g., `status`, `warning`, `error`) and `[event:message]` contains the message content. # ECA Helper for Workflow ## Installation ``` composer require drupal/eca_helper drush pm:install eca_helper_workflow ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Helper for Workflow** from there. # ECA Helper Workflow: Get workflow for Entity Available since: unknown Get workflow instance of Entity. ## Fields `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # ECA Helper Workflow: Get Label Available since: unknown Get workflow label ## Fields `The workflow state id` : The workflow state id of entity. `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # ECA Helper Workflow: Get workflow state Available since: unknown Get workflow state instance of Entity. ## Fields `State` `State Property` `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # ECA HTMX Provides generic [HTMX](https://htmx.org/) capabilities for ECA, building on Drupal core's HTMX integration. It lets ECA models create auto-polling regions and other HTMX-enabled elements, mark routes or requests to return the minimal (main-content-only) response, react to HTMX requests through conditions and tokens, and set HTMX `HX-*` response headers — all without writing JavaScript. All attributes and headers are produced through Drupal core's HTMX helper and the `core/drupal.htmx` library, so the markup stays consistent with the rest of Drupal. See also For a walkthrough of the available plugins and common patterns, see [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/index.md). ## Installation ``` composer require drupal/eca drush pm:install eca_htmx ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA HTMX** from there. # HTMX: render element Available since: 3.1.3 Build an HTMX-enabled element with a configurable request method, trigger, swap, target and other common HTMX attributes. Building HTMX interactions This action builds a single element carrying the HTMX attributes you configure (request method and URL, trigger, swap strategy, target, and more). It attaches the `core/drupal.htmx` library automatically. Use it for click-to-load fragments, infinite scroll, and similar interactions. For a region that refreshes on a timer, use the [HTMX: poll region](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_poll/index.md) action instead. See [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/#building-htmx-elements). ## Fields `Request method` : The HTTP method HTMX uses for the request.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_element_method* `Request URL` : The URL HTMX requests. Leave empty to request the current URL. Internal paths start with a slash, for example */node/1*.\ This field supports tokens. `Trigger` : The HTMX trigger definition, for example *click*, *change* or *every 5s*.\ This field supports tokens. `Swap strategy` : The HTMX swap strategy, for example *innerHTML*, *outerHTML* or *beforeend*.\ This field supports tokens. `Target` : Optional CSS selector identifying the element that receives the swapped content.\ This field supports tokens. `Select` : Optional CSS selector for the content to select from the response.\ This field supports tokens. `Push URL` : Optional URL to push to the browser history, or *true*/*false* to enable or disable pushing the fetched URL.\ This field supports tokens. `Confirm message` : Optional message to show in a confirmation dialog before the request is issued.\ This field supports tokens. `Indicator` : Optional CSS selector of the element that receives the htmx-request class during the request.\ This field supports tokens. `Values` : Optional values to add to the request parameters, in YAML format, for example *key: "[token]"*.\ This field supports tokens. `Boost` : When enabled, anchors and forms inside the element are progressively enhanced to use AJAX. `Request only the main content` : When enabled, the request is sent with the Drupal "only main content" hint, so the response is the minimal HTMX render rather than a full HTML page. `Initial content` : The markup shown inside the element before any swap occurs.\ This field supports tokens. `Wrapper tag` : The HTML tag of the element, for example *div*, *button* or *span*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_element_wrapper_tag* `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_element_mode* # HTMX: minimal response Available since: 3.1.3 Forces the current request to return the minimal HTMX response instead of a full HTML page, by setting the "\_wrapper_format" query parameter to "drupal_htmx". Affects only the current request This action adds the `_wrapper_format=drupal_htmx` query parameter to the current request, so only that request returns the minimal (main-content-only) response. To mark a route so that **every** request to it returns the minimal response, use the [HTMX: mark route](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_set_route/index.md) action instead. The two approaches act at different stages of the request lifecycle and are not interchangeable — see [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/#the-two-ways-to-request-a-minimal-response). # HTMX: poll region Available since: 3.1.3 Build a region that periodically polls a URL via HTMX and swaps in the returned markup. The polled fragment can be served by an ECA endpoint (see the ECA Endpoint module). Only main content The **only main content** option is enabled by default. When enabled, the polled URL is requested with the Drupal "only main content" hint, so the response is the minimal HTMX render (the main content wrapped in a bare HTML document) rather than a full themed page. Disable it only if the polled URL already returns a fragment by other means. A natural source for the polled fragment is an [ECA endpoint](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md). See [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/#auto-refreshing-region). ## Fields `Poll URL` : The URL that HTMX requests on every poll. The response markup replaces the polled region. An [ECA endpoint](https://www.drupal.org/docs/contributed-modules/eca-event-condition-action/eca-endpoint) can serve this fragment.\ This field supports tokens. `Poll interval (seconds)` : The number of seconds between two polls.\ This field supports tokens. `Swap strategy` : The HTMX swap strategy, for example *innerHTML*, *outerHTML* or *beforeend*.\ This field supports tokens. `Swap target` : Optional CSS selector identifying the element that receives the swapped content. When left empty, the polling region itself is the target.\ This field supports tokens. `Initial content` : The markup shown inside the region before the first poll completes.\ This field supports tokens. `Wrapper tag` : The HTML tag of the polling region, for example *div* or *span*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_poll_wrapper_tag* `Request only the main content` : When enabled, the polled URL is requested with the Drupal "only main content" hint, so the response is the minimal HTMX render rather than a full HTML page. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_poll_mode* # HTMX: set response header Available since: 3.1.3 Set one of the HTMX HX-\* response headers (e.g. redirect, location, push URL, refresh or trigger) on the current response. Reacts to a response event, for example the "Response created" event of the ECA Miscellaneous module or an ECA Endpoint response. Runs on a response event This action sets an HTMX `HX-*` header on the current response, so it must run in response to a response event such as the [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) event or an [ECA endpoint response](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md). The `HX-Location` header supports its full form through the additional location fields (source, event, handler, target, swap, values, headers, and select). See [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/#shaping-htmx-responses). ## Fields `Response header` : The HTMX response header to set.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_response_header_header* `Value` : The header value. For URL headers provide a URL (internal paths start with a slash); for the refresh header use *true* or *false*; for trigger headers provide the event name; for retarget/reswap/reselect provide the CSS selector or swap strategy. For the location header this is the path (URL).\ This field supports tokens. `Location: source` : The source element of the request.\ This field supports tokens. `Location: event` : An event that "triggered" the request.\ This field supports tokens. `Location: handler` : A callback that will handle the response HTML.\ This field supports tokens. `Location: target` : The CSS selector of the target for the swap.\ This field supports tokens. `Location: swap` : The swap strategy, for example *innerHTML* or *outerHTML*.\ This field supports tokens. `Location: select` : A CSS selector for the content to swap into the target.\ This field supports tokens. `Location: values` : A set of values to submit with the request, as a key-value list in YAML format. Example: *key: value*. When using tokens, wrap them as a string. Example: *id: "[node:nid]"*.\ This field supports tokens. `Location: headers` : Headers to submit with the request, as a key-value list in YAML format. Example: *X-Custom: value*. When using tokens, wrap them as a string. Example: *X-Custom: "[token]"*.\ This field supports tokens. # HTMX: mark route Available since: 3.1.3 Mark one or more routes as HTMX routes by setting the "\_htmx_route" option on them. Reacts to the "Alter route" event of the ECA Miscellaneous module. The route name may contain a "\*" wildcard. Runs on the Alter route event This action only has an effect when it runs in response to the [Alter route](https://ecaguide.org/plugins/eca/misc/events/routing_alter/index.md) event, because it needs access to the route collection that is being built. The route name supports a `*` wildcard, so `view.*` matches every route whose name starts with `view.`. Marking a route sets the `_htmx_route` option on it, which takes effect for **every** request to that route. To return the minimal response for a single request instead, use the [HTMX: minimal response](https://ecaguide.org/plugins/eca/htmx/actions/eca_htmx_minimal_response/index.md) action. See [Building HTMX-powered interfaces with ECA](https://ecaguide.org/eca/tips/htmx/#the-two-ways-to-request-a-minimal-response). ## Fields `Route name` : The name of the route(s) to mark as HTMX routes, for example *entity.node.canonical*. A trailing or embedded *acts as a wildcard, for example *view.** matches every route whose name starts with *view.*.\ This field supports tokens. # HTMX: compare request value Available since: 3.1.3 Compares a value from the current HTMX request (e.g. target, trigger or current URL) against an expected value. ## Fields `HTMX request value` : The value from the current HTMX request that should be compared. The boolean values evaluate to "1" or "0".\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_header_value* `Expected value` : The value to compare the selected HTMX request value against. For boolean values use "1" or "0".\ This field supports tokens. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_header_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_htmx_header_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # HTMX: is request Available since: 3.1.3 Evaluates to TRUE when the current request was sent by HTMX (the HX-Request header is present). ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # ECA Language ## Installation ``` composer require drupal/eca drush pm:install eca_language ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Language** from there. # Entity: create translation Available since: 3.1.0 Creates a translation of a content entity, replicating the behavior of the core translation UI. ## Fields `Source language` : The language to copy field values from. Typically the site default language.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_create_entity_translation_source_langcode* `Target language` : The language of the new translation to create.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_create_entity_translation_target_langcode* `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Language: get code Available since: 2.0.0 Get the currently used or negotiated language code. ## Fields `Name of token` : The language code will be stored into this specified token. Please provide the token name only, without brackets. # Language: reset negotiation Available since: 2.0.0 This may be useful when switching between multiple users with different preferred languages. # Language: set code Available since: 2.0.0 Set the currently used or negotiated language code. ## Fields `Language` : The language code to be set.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_set_current_langcode_langcode* # ECA language negotiation Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during Drupal's language negotiation process when the ECA language negotiation method is active. Set the `langcode` to override the negotiated language. If left unset, this negotiation method is skipped and the next method in the chain is consulted. Must be enabled in language settings The ECA language negotiation method must be enabled at **Administration > Configuration > Regional and language > Languages > Detection and selection**. # ECA Log ## Installation ``` composer require drupal/eca drush pm:install eca_log ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Log** from there. # Log Message Available since: 1.0.0 Writes a log message into the given type with the given severity. ## Fields `Type` : The name of the logger type, the message should be logged to. `Severity` : The severity of the log message.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_write_log_message_severity* `Message` : The message, which should be logged. # Log message created Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[log]` | The logger data which dispatched the event. | | `[log:severity]` | The log message severity. | | `[log:message]` | The log message. | | `[log:message:raw]` | The raw log message. | | `[log:message:full]` | The full and formatted log message with all variables replaced. | | `[log:context]` | All context variables of the log message. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires whenever a log message is submitted to Drupal's logging system. The `[log:severity]`, `[log:message:raw]`, `[log:message:full]`, and `[log:context]` tokens provide details about the log entry. Avoid infinite loops If your ECA reaction generates a log message (e.g., via an action that logs), it can cause infinite recursion. Be careful about what actions are triggered from this event. ## Fields `Type` : The name of the logger type. ``` The logger channel/type to filter by (e.g., `php`, `system`, `cron`). Leave empty to match all channels. This corresponds to the 'Type' column in Drupal's database log. ``` `Minimum severity` : The minimum severity. E.g. "critical" also covers "alert" and below. ``` The minimum severity level to react to. Uses RFC 5424 levels: Emergency (0), Alert (1), Critical (2), Error (3), Warning (4), Notice (5), Info (6), Debug (7). Setting to 'Error' also catches more severe levels. ``` # ECA Metatag ## Installation ``` composer require drupal/eca_metatag drush pm:install eca_metatag ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Metatag** from there. # Add tag Available since: 1.0.0 ## Fields `Name` : Provide the name of the metatag for the head section of HTML pages. `Label` : The label is used in the admin UI where the metatag can be configured. `Description` : The description for the field in the admin UI. # Set tag value Available since: 1.0.0 ## Fields `Name` : Explain what a name is for. `Value` : Explain where the label is used. # Alter metatags Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when metatags on a page are being altered. Use this to dynamically change metatag values based on the current context, such as the viewed entity or route. # Provide a list of tags Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the list of available metatag plugins is being collected. Use this to register custom metatag definitions that can then be set via ECA actions. # ECA Migrate ## Installation ``` composer require drupal/eca drush pm:install eca_migrate ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Migrate** from there. # Migrate: Reset migration Available since: 3.0.11 Triggers a migration reset by ID. ## Fields `Migration ID` : The ID of the migration to run.\ This field supports tokens. # Migrate: Rollback migration Available since: 3.0.11 Triggers a migration rollback by ID. ## Fields `Migration ID` : The ID of the migration to run.\ This field supports tokens. # Migrate: Run migration Available since: 3.0.0 Triggers a migration run by ID. ## Fields `Migration ID` : The ID of the migration to run.\ This field supports tokens. `Update existing records` : If checked, existing migrated items will be updated. # Migrate: Skip Row Available since: 2.1.17 Throws a MigrateSkipRowException to skip the current migration row. ## Fields `Skip message` : Optional message explaining why the row was skipped.\ This field supports tokens. `Save to map` : If checked, the skip will be recorded in the migration map table. # Save message to ID map Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[source_id_values]` | The source ID values. | | `[message]` | The message to be logged. | | `[level]` | The severity level of the message. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a message (error, warning, or notice) is logged to a migration's ID map. Useful for monitoring migration errors in real time or sending alerts. # Remove entry from migration map Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[map]` | The map plugin that caused the event to fire. | | `[source_id]` | The source ID values. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an entry is being removed from the migration map table during rollback. # Save to migration map Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[map]` | The map plugin that caused the event to fire. | | `[fields]` | Array of map fields, keyed by field name. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a source-to-destination ID mapping is being saved to the migration map table. # Migration import finished Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a migration import has completed. Useful for sending notifications, triggering cleanup tasks, or chaining dependent migrations. # Migration rollback finished Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a migration rollback has completed. Useful for cleanup and notifications. # Migration row deleted Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[destination_id_values]` | The row's destination ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires just after a single destination item has been deleted during rollback. The entity no longer exists at this point. # Migration row saved Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[row]` | The row about to be imported. | | `[row:source]` | The current migration row source and its properties. Source properties can be accessed by [row:source:PROPERTY_NAME]. | | `[row:destination]` | The current migration row destination and its properties. Destination properties can be accessed by [row:destination:PROPERTY_NAME]. However, such properties only exist if they have been processed before during the migration of the current row. | | `[row:is_stub]` | Whether the current migration row is a stub. | | `[destination_id_values]` | The row's destination ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires just after a single migrated item has been saved. The `[destination_id_values]` token provides the IDs of the saved entity. Useful for post-processing, logging, or creating related data. # Migration import started Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a migration import is about to begin, before any rows are processed. Useful for setup tasks, checking prerequisites, or disabling system behaviors during migration. # Migration rollback started Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a migration rollback is about to begin. Useful for preparing for rollback (e.g., disabling caches) or validating that rollback is safe. # Deleting migration row Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[destination_id_values]` | The row's destination ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires just before a single destination item is deleted during rollback. The entity still exists at this point. Useful for saving backups or auditing before deletion. # Saving migration row Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[migration]` | The migration plugin being run. | | `[migration_id]` | The migration plugin id being run. | | `[row]` | The row about to be imported. | | `[row:source]` | The current migration row source and its properties. Source properties can be accessed by [row:source:PROPERTY_NAME]. | | `[row:destination]` | The current migration row destination and its properties. Destination properties can be accessed by [row:destination:PROPERTY_NAME]. However, such properties only exist if they have been processed before during the migration of the current row. | | `[row:is_stub]` | Whether the current migration row is a stub. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires just before a single migrated item is saved. The `[row]` token provides access to source and destination values (e.g., `[row:source:title]`, `[row:destination:nid]`). Useful for last-minute modifications or conditional row skipping. # Processing migration row value Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[row]` | The row about to be imported. | | `[row:source]` | The current migration row source and its properties. Source properties can be accessed by [row:source:PROPERTY_NAME]. | | `[row:destination]` | The current migration row destination and its properties. Destination properties can be accessed by [row:destination:PROPERTY_NAME]. However, such properties only exist if they have been processed before during the migration of the current row. | | `[row:is_stub]` | Whether the current migration row is a stub. | | `[value]` | The migration row value to process. | | `[destination_property]` | The destination property. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the processing of a migration row value when using the ECA migrate process plugin. This allows transforming field values using ECA actions instead of writing PHP code. The `[value]` token holds the current value being processed. Set the result using the token specified in the configuration. ## Fields `Token name holding the processed value` : The name of the token to hold the processed value. ``` The name of the token to hold the processed result. After ECA actions run, the value of this token becomes the transformed output. ``` # ECA Miscellaneous ## Installation ``` composer require drupal/eca drush pm:install eca_misc ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Miscellaneous** from there. # Recipe: apply Available since: 2.1.2 Applies a given recipe. ## Fields `Recipe package name` : The Composer package name of the recipe, that should be applied, e.g. "drupal/drupal_cms_privacy_basic"\ This field supports tokens. # Build URL from route Available since: 3.1.3 Builds a URL from a route name, parameters and options. ## Fields `Route name` : Example: `entity.node.canonical`\ This field supports tokens. `Route parameters` : Enter a key-value list of parameters. Supports YAML format. Example: *node: 1*. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *node: "[node:nid]"*\ This field supports tokens. `Additional options` : Enter a key-value list of options. Supports YAML format. Use dot notation for nested arrays. Example: ```` ``` query: foo: bar fragment: comments ``` When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *fragment: "[node:nid]"* This field supports tokens. ```` `Generate absolute URL` : Check this to always generate an absolute URL (with scheme and host). `Name of token` : Provide the name of a token where the generated URL should be stored. Please provide the token name only, without brackets. # Set page title Available since: 3.1.3 Sets the title of the current page. Works on forms (e.g. the "Build form" event) and on regular pages such as entity view pages, views pages and controller results. ## Fields `Title` : The title for the current page. This field supports tokens.\ This field supports tokens. # Throw exception Available since: 2.1.3 Throws an exception that are be caught by ECA. ## Fields `Exception type` `Response message` : An optional message explaining why the exception was thrown.\ This field supports tokens. `Log as an error` : If enabled, the exception will be logged as an error. # Token: load query argument Available since: 2.1.ß Loads a query argument from the request into the token environment. ## Fields `Name of query argument` : This field supports tokens. `Name of token` : The name of the token, the argument value gets stored into. Please provide the token name only, without brackets. # Token: load route parameter Available since: 1.0.0 Loads a route parameter into the token environment. ## Fields `Request` : The request route match.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_token_load_route_param_request* `Name of route parameter` : The routes and their parameters can be found in the *MODULE.routing.yml* file. Example for the route *entity.node.preview*: */node/preview/{node_preview}/{view_mode_id}* where *node_preview* and *view_mode_id* are the parameter names.\ This field supports tokens. `Name of token` : The name of the token, the parameter value gets stored into. Please provide the token name only, without brackets. `Get raw value` : If checked, the raw value of the route parameter will be stored into the token. # Is Ajax Available since: 2.1.8 Determines if the current request is an AJAX request. ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Recipe uses config action Available since: 2.1.3 Checks if a recipe uses a specific config action. ## Fields `Recipe package name` : The Composer package name of the recipe, that needs to be checked, e.g. "drupal/drupal_cms_privacy_basic"\ This field supports tokens. `Config Action` : Enter the name of the config action you want to check for.\ This field supports tokens. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Route match Available since: 1.0.0 Gets and compares the name of the route. ## Fields `Request` : The request route match.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_route_match_request* `Route name` : The routes and their parameters can be found in the *MODULE.routing.yml* file, e.g. the route name *entity.node.preview*. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_route_match_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_route_match_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Block content get dependency Available since: 1.0.0 Fires, when getting the dependency of a non-reusable block. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when getting the access dependency of a non-reusable (inline) block content entity. Requires the Block Content module. This allows defining custom access dependencies for inline blocks when the default access dependency is not set. # Build resource type Available since: 1.0.0 Fires during the resource type build process. Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the JSON:API resource type build process. Requires the JSON:API module. Useful for disabling specific entity types from the JSON:API, renaming fields in the API response, or hiding sensitive fields. # Sanitize file name Available since: 1.0.0 Fires during a file upload that lets subscribers sanitize the filename. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during a file upload to allow sanitizing or renaming the uploaded filename. Useful for enforcing naming conventions, removing special characters, or adding prefixes to uploaded files. # Prepare layout builder element Available since: 1.0.0 Fires, when preparing a layout builder element. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when preparing a Layout Builder element for rendering, before the layout sections are rendered. Requires the Layout Builder module. Useful for modifying layout sections or section components programmatically before rendering. # Recipe applied Available since: 1.0.0 Fires, when a recipe has been applied. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a Drupal Recipe has been applied. Avoid modifying config or content Since recipes are often applied in chains, config and content may be about to change again. This event is best used for notifications, logging, or updating state values. ## Fields `Base path of recipe` : The base path of the recipe that got applied; e.g. if the recipe is stored in "/var/www/recipe/my_recipe" then the base path is "my_recipe". Leave empty to respond to all recipes. ``` The directory basename of the recipe to match (e.g., `my_recipe`). Leave empty to react to all recipes. ``` # Save translated string Available since: 1.0.0 Fires, when saving a translated string. Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. | Fires when a translated string is saved through the locale system. Requires the Locale module. Useful for invalidating caches, logging translation changes, or synchronizing translations with external systems. # Build render array Available since: 1.0.0 Fires, when a render array of a component is built. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a Layout Builder section component (block) is being converted into a render array. Requires the Layout Builder module. Useful for modifying the render output of individual layout components, adding wrappers, or injecting additional markup. # Select page display mode Available since: 1.0.0 Fires when selecting a page display variant to use. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when selecting which page display variant plugin renders the page. Useful for switching between different page layouts based on route conditions. # Service container finished initializing Available since: 1.0.0 Fires, when the service container finished initializing in subrequest. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the Drupal service container has finished initializing for a sub-request. This is useful for setting up language overrides or service customizations specific to sub-request contexts (e.g., BigPipe, ESI). # Controller found to handle request Available since: 1.0.0 Fires, once a controller was found for handling a request. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a controller has been found to handle the request, but before the controller is called. This allows inspecting or replacing the controller at runtime. # Controller arguments have been resolved Available since: 1.0.0 Fires, once controller arguments have been resolved. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the controller arguments have been resolved but before the controller is invoked. This allows modifying or inspecting the arguments that will be passed to the controller. # Uncaught exception Available since: 1.0.0 Fires, when an uncaught exception appears. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:method]` | The request method, e.g. "GET" or "POST". | | `[event:path]` | The requested path. | | `[event:query]` | The query arguments of the request. | | `[event:headers]` | The request headers. | | `[event:content_type]` | The content type of the request. | | `[event:content]` | The content of the POST request. | | `[event:ip]` | The client IP. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an uncaught exception occurs during request processing. Useful for custom error pages, error logging, notifications, or redirecting on specific exceptions. Tokens available: `[event:method]`, `[event:path]`, `[event:query]`, `[event:headers]`, `[event:content_type]`, `[event:content]`, `[event:ip]`. # Exception status code Available since: 2.1.0 Event that is dispatched when a routing exception 4xx or 5xx is found. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an HTTP exception with a 4xx or 5xx status code is encountered during routing. The `[event:code]` token provides the HTTP status code. Useful for redirecting users on specific error codes (e.g., redirect to login on 403, custom page on 404), or sending notifications on server errors. # Response for request created Available since: 1.0.0 Fires, when a response was generated for a request. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a response has been generated for the current request (both main and sub-requests). Primarily used for cleanup, such as resetting global state after a sub-request. # Start dispatching request Available since: 1.0.0 Fires at the very beginning of request dispatching. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:method]` | The request method, e.g. "GET" or "POST". | | `[event:path]` | The requested path. | | `[event:query]` | The query arguments of the request. | | `[event:headers]` | The request headers. | | `[event:content_type]` | The content type of the request. | | `[event:content]` | The content of the POST request. | | `[event:ip]` | The client IP. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires at the very beginning of request dispatching, before any controller is resolved. This is the first event in the HTTP request lifecycle. Tokens available: `[event:method]`, `[event:path]`, `[event:query]`, `[event:headers]`, `[event:content_type]`, `[event:content]`, `[event:ip]`. Useful for intercepting requests early (e.g., redirects, access checks, maintenance mode), logging all incoming requests, or setting up request-scoped state. # Response created Available since: 1.0.0 Fires, once a response was created for replying to a request. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:method]` | The request method, e.g. "GET" or "POST". | | `[event:path]` | The requested path. | | `[event:query]` | The query arguments of the request. | | `[event:headers]` | The request headers. | | `[event:content_type]` | The content type of the request. | | `[event:content]` | The content of the POST request. | | `[event:ip]` | The client IP. | | `[event:code]` | The response code. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a response has been created but before it is sent to the client. Useful for adding or modifying response headers (CORS, caching, security headers), altering the response body, or changing HTTP status codes. Tokens available: `[event:method]`, `[event:path]`, `[event:query]`, `[event:headers]`, `[event:content_type]`, `[event:content]`, `[event:ip]`, `[event:code]`. # Response was sent Available since: 1.0.0 Fires, once a response was sent. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the response has been sent to the client. This is the very last event in the request lifecycle and only fires for main requests. Post-response processing Use this event for expensive operations that should not delay the response, such as sending emails, generating reports, or cache warming. # Controller does not return a Response instance Available since: 1.0.0 Fires, when a controller does not return a Response instance. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:method]` | The request method, e.g. "GET" or "POST". | | `[event:path]` | The requested path. | | `[event:query]` | The query arguments of the request. | | `[event:headers]` | The request headers. | | `[event:content_type]` | The content type of the request. | | `[event:content]` | The content of the POST request. | | `[event:ip]` | The client IP. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a controller returns something other than a Response object (e.g., a render array). In Drupal, this is the event that turns render arrays into HTTP responses. Tokens available: `[event:method]`, `[event:path]`, `[event:query]`, `[event:headers]`, `[event:content_type]`, `[event:content]`, `[event:ip]`. # Alter route Available since: 1.0.0 Fires during route collection to alter routes. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during route collection, allowing modification of existing routes before they are saved. This is a build-time event that fires during cache rebuilds, not on every request. Useful for changing route requirements (permissions), modifying route paths, or adding custom options to existing routes. # Allow new routes Available since: 1.0.0 Fires during route collection to allow new routes. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during route collection, allowing new routes to be added dynamically. This event fires before the route alter event and is a build-time event. Useful for generating routes programmatically based on configuration or external data. # Route building finished Available since: 1.0.0 Fires, when route building has ended. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the route building process has completed and all routes have been saved. This is a build-time event that occurs during cache rebuilds. Useful for triggering actions that depend on the full set of routes being available. # ECA Node Access ## Installation ``` composer require drupal/eca drush pm:install eca_node_access ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Node Access** from there. # Set node access records Available since: 3.1.3 Sets the node access grant records for the node. Only works when reacting upon the *Node Access: record access grants for a node* event. ## Fields `Realm` : An arbitrary string that must match the realm used in the set node access records action. *Please note, this action only works when reacting upon the Node Access: record access grants for a node event.*\ This field supports tokens. `Grant ID` : The grant identifier must be an integer. Note that the node ID being acted on in the "Node Access: record access grants for a node" event will by default be available as [entity] or [node].\ This field supports tokens. `Grant view` `Grant update` `Grant delete` # Set node grants Available since: 3.1.3 Sets the node grants for the account. Only works when reacting upon the *Node Access: node grants for an account* event. ## Fields `Realm` : An arbitrary string that must match the realm used in the set node access records action. *Please note, this action only works when reacting upon the Node Access: node grants for an account event.*\ This field supports tokens. `Grant IDs` : Grant identifiers must be integers. To pass in multiple, separate with a comma.\ This field supports tokens. # Node Access: node grants for an account Available since: 3.1.3 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:operation]` | The node operation being requested: view, update or delete. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | ## Fields `Operation` : Optionally restrict these grants to a single node operation. When set, the event only applies when Drupal requests grants for that operation; leave as "Any operation" to apply for view, update and delete. # Node Access: record access grants for a node Available since: 3.1.3 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | # ECA Parameters ## Installation ``` composer require drupal/eca_parameters drush pm:install eca_parameters ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Parameters** from there. # Get parameter Available since: 1.0.0 Get a parameter and store its value as a token. ## Fields `Parameter name` : The machine name of the parameter. Examples: *my_eca_parameter*, *global:my_global_param*, *node.article:my_article_param*. Available parameters: No parameters have been defined via configuration yet. `Name of token` : Please provide the token name only, without brackets. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Set parameter Available since: 1.0.0 Set a parameter on the ECA parameters collection. ## Fields `Parameter name` : The machine name of the parameter. Example: *my_eca_parameter* `Value of the parameter` `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Save according collection` : When enabled, the configuration will be saved permanently with the newly set value. If not enabled, the set value only persists on runtime. # Parameter: exists Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. `Parameter name` : The machine name of the parameter. Examples: *my_eca_parameter*, *global:my_global_param*, *node.article:my_article_param*. Available parameters: No parameters have been defined via configuration yet. # Parameter: compare value Available since: 1.0.0 ## Fields `Parameter name` : The machine name of the parameter. Examples: *my_eca_parameter*, *global:my_global_param*, *node.article:my_article_param*. Available parameters: No parameters have been defined via configuration yet. `Value` : This field supports tokens. `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_parameter_value_operator* ``` Comparison operator. Possible values: ``` - equal - greater than - less than - starts with - ends with - contains - at least - at most `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_parameter_value_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. # Requesting parameter Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:parameter_name]` | The parameter name. | | `[event:entity]` | The entity. | | `[event:ENTITY_TYPE]` | The entity type. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a parameter value is being requested by the Parameters module. Use this to dynamically provide parameter values through ECA instead of (or in addition to) static configuration. The `[event:parameter-name]` token contains the machine name of the requested parameter. Context entities are available via `[entity]` or by their entity type ID. ## Fields `Parameter name` : The machine name of the requested parameter. Examples: *my_eca_parameter*, *my_global_param*, *my_article_param*. ``` The machine name of the requested parameter to listen for. Examples: `my_eca_parameter`, `my_global_param`, `my_article_param`. ``` # ECA Project Browser ## Installation ``` composer require drupal/eca drush pm:install eca_project_browser ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Project Browser** from there. # Project Browser: Alter source plugin info Available since: 2.1.2 Allows to change certain properties of source plugins. ## Fields `Plugin` `Label` `Description` `Local task: title` `Local task: weight` # Alter source plugin info Available since: 2.1.2 Fires during project browser source plugin alter. Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during project browser source plugin discovery, allowing modification of source plugin definitions at runtime. Requires the Project Browser module. # ECA Push Framework ## Installation ``` composer require drupal/push_framework drush pm:install eca_push_framework ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Push Framework** from there. # Direct PUsh Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a direct push notification is triggered programmatically via ECA. Use the configured Event ID to match the specific push event. ## Fields `Event ID` : The event ID to trigger this event directly. ``` The event ID to trigger this event directly. Must match the ID used by the code dispatching the direct push. ``` # Post render notification Provided tokens | Token | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[push_notification]` | The push notification. | | `[push_notification:channel]` | The notification channel. | | `[push_notification:recipient]` | The recipient user account. | | `[push_notification:entity]` | The entity. | | `[push_notification:title]` | The title of the entity. | | `[push_notification:display_mode]` | The display mode for the entity. | | `[push_notification:language_key]` | The language key of the notification. | | `[push_notification:output]` | The rendered output of the notification. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a notification has been rendered for a specific language. Use this to alter the final rendered output markup before it is delivered. The `[push_notification:output]` token contains the rendered markup, alongside `[push_notification:language_key]` and the base tokens (`channel`, `recipient`, `entity`, `title`, `display_mode`). # Pre build notification Provided tokens | Token | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[push_notification]` | The push notification. | | `[push_notification:channel]` | The notification channel. | | `[push_notification:recipient]` | The recipient user account. | | `[push_notification:entity]` | The entity. | | `[push_notification:title]` | The title of the entity. | | `[push_notification:display_mode]` | The display mode for the entity. | | `[push_notification:language_key]` | The language key of the notification. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires before a notification is built for a specific language. At this stage, the entity view has not yet been rendered. The `[push_notification:language_key]` token identifies the current language being processed, in addition to the base tokens (`channel`, `recipient`, `entity`, `title`, `display_mode`). # Pre render notification Provided tokens | Token | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[push_notification]` | The push notification. | | `[push_notification:channel]` | The notification channel. | | `[push_notification:recipient]` | The recipient user account. | | `[push_notification:entity]` | The entity. | | `[push_notification:title]` | The title of the entity. | | `[push_notification:display_mode]` | The display mode for the entity. | | `[push_notification:language_key]` | The language key of the notification. | | `[push_notification:elements]` | The list of elements. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the notification has been built but before it is rendered for a specific language. Use this to alter the render array elements before they are turned into final markup. The `[push_notification:elements]` token provides access to the render array, alongside `[push_notification:language_key]` and the base tokens (`channel`, `recipient`, `entity`, `title`, `display_mode`). # Prepare templates Provided tokens | Token | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[push_notification]` | The push notification. | | `[push_notification:channel]` | The notification channel. | | `[push_notification:recipient]` | The recipient user account. | | `[push_notification:entity]` | The entity. | | `[push_notification:title]` | The title of the entity. | | `[push_notification:display_mode]` | The display mode for the entity. | | `[push_notification:subject]` | The subject of the notification. | | `[push_notification:body]` | The body of the notification. | | `[push_notification:text_format]` | The text format of the notification. | | `[push_notification:is_html]` | The flag if the body of the notification is in html. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires once before the language loop when Push Framework prepares notification templates. Use this to alter the display mode, subject, body, text format, or HTML flag before any language-specific rendering begins. The `[push_notification:subject]`, `[push_notification:body]`, `[push_notification:text_format]`, and `[push_notification:is_html]` tokens are available alongside the base tokens (`channel`, `recipient`, `entity`, `title`, `display_mode`). # ECA Queue ## Installation ``` composer require drupal/eca drush pm:install eca_queue ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Queue** from there. # Enqueue a task Available since: 1.0.0 ## Fields `Task name` : The task name will be used to identify, what type of task is to be processed. When multiple tasks are created that are of the same nature, they should share the same task name. When reacting upon the event "ECA processing queued task", you can use this name to recognize the task. `Task value (optional)` : You may optionally define a task value here for more granular task control. `Tokens to forward` : Comma separated list of token names from the current context, that will be put into the task. # Enqueue a task with a delay Available since: 1.0.0 ## Fields `Delay value` : This field supports tokens. `Delay unit` : When using the "Defined by token" option, make sure there is a token with this name: *eca_enqueue_task_delayed_delay_unit* `Task name` : The task name will be used to identify, what type of task is to be processed. When multiple tasks are created that are of the same nature, they should share the same task name. When reacting upon the event "ECA processing queued task", you can use this name to recognize the task. `Task value (optional)` : You may optionally define a task value here for more granular task control. `Tokens to forward` : Comma separated list of token names from the current context, that will be put into the task. # ECA processing queued task Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a queued ECA task is being processed. Tasks are placed in the queue by the 'Enqueue task' action and processed during cron or manually. The task carries token data set by the action that enqueued it, making those tokens available to subsequent actions and conditions. ## Fields `Task name` : The task name will be used to identify, what type of task is to be processed. When multiple tasks are created that are of the same nature, they should share the same task name. ``` The task name used to identify what type of task is being processed. Must match the task name used in the 'Enqueue task' action. ``` `Task value (optional)` : An optional additional value for finer-grained filtering. Combined with the task name to determine which ECA model handles the task. `Distribute: Process tasks of this name in their own queue.` : When enabled, tasks with this name are processed in a dedicated queue, separate from the default ECA queue. This allows independent processing and cron management. `Cron run time (seconds)` : **Please note:** This option is only available when the *Distribute* option is enabled above. Leave empty to disable processing when running cron. ``` Only available when 'distribute' is enabled. Specifies how many seconds the cron worker should spend processing tasks from this queue during each cron run. Leave empty to disable cron-based processing. ``` # ECA Render ## Installation ``` composer require drupal/eca drush pm:install eca_render ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Render** from there. # Get active theme Available since: 1.1.0 Get the currently active theme and store the value as a token. ## Fields `Token name` : Specify the name of the token, that holds the name of the currently active theme. Please provide the token name only, without brackets. # Render: add attached library Available since: 3.0.12 Attach a JavaScript/CSS library to an existing render array element. Only works when reacting upon a rendering event, such as *Build form* or *Build ECA Block*. ## Fields `Machine name` : Specify the machine name / key of the render element.\ Leave blank to target parent. `Library ID` : Given in the format of `module_name/library_name`.\ This field supports tokens. # Render: add attached drupalSettings Available since: 3.0.12 Add a drupalSettings entry to an existing render array element. Only works when reacting upon a rendering event, such as *Build form* or *Build ECA Block*. ## Fields `Collection name` : drupalSettings module name or collection name.\ This field supports tokens. `Key` : drupalSettings key within the collection.\ This field supports tokens. `Machine name` : Specify the machine name / key of the render element.\ Leave blank to target parent. `Value` : Value to attach.\ This field supports tokens. # Render: add class Available since: 2.0.0 Add a class to the attributes of an existing render array element. Only works when reacting upon a rendering event, such as *Build form* or *Build ECA Block*. ## Fields `Machine name` : Specify the machine name / key of the render element.\ This field supports tokens. `Class name` : The name of the class.\ This field supports tokens. # Render: alter breakpoint Available since: 3.0.4 Allows creating or altering breakpoint definitions, which are normally defined by theme or module code. ## Fields `ID` : This field supports tokens. `Definition` : These values will override values from an existing breakpoint definition with the same ID.\ This field supports tokens. # Render: alter link, add attribute Available since: 3.0.3 Alter a link element by adding an attribute. ## Fields `Name of attribute` : The name of the attribute to add to the link. Leave empty to not add an attribute when the attributes will be reset.\ This field supports tokens. `Value of attribute` : The value of the attribute to add to the link. Leave empty to not add an attribute when the attributes will be reset.\ This field supports tokens. `Reset attributes` : If checked, the currently set attributes will be removed before adding the new attribute. Note that the class and the title attributes will not be reset. # Render: alter link, add class Available since: 3.0.3 Alter a link element by adding a class to its attributes. ## Fields `Class` : The class to add to the link. Leave empty to not add a class when the classes will be reset.\ This field supports tokens. `Reset classes` : If checked, the currently set classes will be removed before adding the new class. # Render: alter link, add query argument Available since: 3.0.3 Alter a link element by adding a query argument. ## Fields `Name of query argument` : The name of the query argument to add to the link. Leave empty to not add a query argument when the query arguments will be reset.\ This field supports tokens. `Value of query argument` : The value of the query argument to add to the link. Leave empty to not add a query argument when the query arguments will be reset.\ This field supports tokens. `Reset query arguments` : If checked, the currently set query arguments will be removed before adding the new query argument. # Render: alter link, set absolute Available since: 3.0.3 Alter a link element by setting it absolute or not. ## Fields `Set absolute` : If checked, the link will be absolute. If not checked, the link will be relative. # Render: alter link, set language Available since: 3.0.3 Alter a link element by setting its language. ## Fields `Language` : The language code to be set. Select "undefined" to unset the language.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_render_alter_link_set_language_langcode* # Render: alter link, set visible text Available since: 3.0.3 Alter a link element by setting its visible text. ## Fields `Visible text` : The visible text of the link.\ This field supports tokens. # Render: alter link, set title attribute Available since: 3.0.3 Alter a link element by setting its title attribute. ## Fields `Title attribute` : The title attribute. Leave empty to unset the title attribute.\ This field supports tokens. # Render: alter link, set url Available since: 3.0.3 Alter a link element by setting its url. ## Fields `URL` : The url of the link.\ This field supports tokens. # Render: build Available since: 1.1.0 Build a custom defined render array. ## Fields `Value` : The value of the render build. This can be arbitrary markup text or a valid [render array](https://www.drupal.org/docs/drupal-apis/render-api/render-arrays).\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_build_mode* # Render: cacheability Available since: 1.1.0 Add cacheability metadata to a render array. Only works when reacting upon a rendering event, such as "Build form" or "Build ECA Block". ## Fields `Type` : [Click here](https://www.drupal.org/docs/8/api/cache-api/cache-api#s-cacheability-metadata) to get more info about cacheability metadata.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_render_cacheability_cache_type* `Value` : Separate multiple values with commas. When using *Max age*, the value must be a valid number (integer).\ This field supports tokens. # Render: custom form Available since: 1.1.0 Build a custom form using "ECA Form" events. ## Fields `Custom form ID` : This custom form ID is being used to identify the form on *ECA Form* events. *It is always prefixed with "eca_custom\_"*. Example: When specified the custom form ID *my_custom_form*, then it can be identified e.g. on the event *Build form* using the form ID *eca_custom_my_custom_form*. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_custom_form_mode* # Render: HTML details Available since: 1.1.0 Build a HTML details element. ## Fields `Title` : This will be shown to the user in the form as grouping title. `Open` `Introduction text` `Summary value` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_details_mode* # Render: dropbutton Available since: 1.1.0 Build a HTML dropbutton element. ## Fields `Dropbutton type` : A string defining a type of dropbutton variant for styling proposes. Renders as class "dropbutton--[type]". `Links` : This field optionally supports YAML if selected below.\ This field supports tokens. `Interpret above specified links as YAML format` : Links can be specified as a list with YAML syntax. Example: *-\ title: Edit\ url: "/node/[node:nid]/edit/"\ -\ title: Delete* ``` When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* ``` `Validate YAML to prevent this from being executed when invalid` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_dropbutton_mode* # Render: entity form Available since: 1.1.0 Build an entity form using a specified entity. ## Fields `Operation` : Example: *default, save, delete*\ This field supports tokens. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_entity_form_mode* `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Render: view entity Available since: 1.1.0 View a specified entity. ## Fields `View mode` : Example: *default, teaser*\ This field supports tokens. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_entity_view_mode* `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Render: view field Available since: 1.1.0 View a field of a specified entity. ## Fields `Field name` : The machine name of the field. Example: *field_tags*\ This field supports tokens. `View mode` : Example: *default, teaser*\ This field supports tokens. `Display options` : Alternatively, instead of specifying a view mode above, you can set custom display options here by using YAML format. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_entity_view_field_mode* `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Render: file contents Available since: 1.1.0 ## Fields `URI` : Either the relative path of the file or a full URL. `Encoding` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_file_contents_encoding* `Token name for MIME type` : Optionally define the name of a token, that stores the detected MIME type of the file. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_file_contents_mode* # Render: image Available since: 1.1.0 Build an image HTML element (not responsive). ## Fields `URI` : Either the relative path of the file or a full URL. `Style name` : Optionally, specify the configuration ID of the image style to use.\ This field supports tokens. `Alt text` : Specify the alternative text for text-based browsers. `Title` : Optionally specify the value of the title attribute. `Width` : Optionally specify the value of the width attribute. `Height` : Optionally specify the value of the height attribute. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_image:image_mode* # Render: lazy element Available since: 1.1.0 Build a lazy render element, optionally with arguments. ## Fields `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Element argument` : Optionally specify an argument to be passed to the lazy element.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_lazy_mode* # Render: link Available since: 1.1.0 Build a link element, optionally displaying its content as a modal or dialog. ## Fields `Title` : The title of the link.\ This field supports tokens. `URL` : The link destination as a valid URL.\ This field supports tokens. `Enforce absolute` : This makes the destination URL of the link always absolute, also for relative and internal URLs. `Link type` : Choose how the content of the link should be displayed. More about dialog types can be found [here](https://www.drupal.org/docs/drupal-apis/ajax-api/ajax-dialog-boxes#s-types-of-dialogs)."\ When using the "Defined by token" option, make sure there is a token with this name: *eca_render_link_link_type* `Width percentage` : Specify the number of width percentage if the link content is being rendered in a modal or dialog. `Display link as` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_link_display_as* `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_link_mode* # Render: markup Available since: 1.1.0 Renders markup using a specified render array. ## Fields `Value` : The value of the render build. This can be arbitrary markup text or a valid [render array](https://www.drupal.org/docs/drupal-apis/render-api/render-arrays).\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_markup_mode* # Render: responsive image Available since: 1.1.0 Build an image HTML element (responsive). ## Fields `URI` : Either the relative path of the file or a full URL. `Responsive image style` : Specify the configuration ID of the responsive image style.\ This field supports tokens. `Alt text` : Specify the alternative text for text-based browsers. `Title` : Optionally specify the value of the title attribute. `Width` : Optionally specify the value of the width attribute. `Height` : Optionally specify the value of the height attribute. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_responsive_image:responsive_image_mode* # Render: serialize Available since: 1.1.0 Serializes data. ## Fields `Format` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_serialize:serialization_format* `Value` : The value to serialize.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_serialize:serialization_mode* # Render: set weight Available since: 1.1.0 Set the weight of an existing render array element. Only works when reacting upon a rendering event, such as *Build form* or *Build ECA Block*. ## Fields `Machine name` : Specify the machine name / key of the render element.\ This field supports tokens. `Element weight` : The weight as integer number.\ This field supports tokens. # Render: text Available since: 1.1.0 Build a renderable text element. ## Fields `Text` : This field supports tokens. `Filter format` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_text:filter_format* `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_text:filter_mode* # Render: Twig Available since: 1.1.0 Render an inline template using the Twig engine. ## Fields `Template` : Must be valid Twig syntax.\ This field supports tokens. `Context values` : Optionally specify context values to pass to the template. Can be an array using YAML syntax (needs to be enabled below) or a token holding the context data. Available token data will be automatically forwarded.\ This field supports tokens. `Interpret above value as YAML format` : Nested data can be set using YAML format, for example *mykey: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_twig_mode* # Render: unserialize Available since: 1.1.0 Un-serializes / deserializes data. ## Fields `Data type` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_unserialize:serialization_type* `Format` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_unserialize:serialization_format* `Value` : The value to deserialize.\ This field supports tokens. `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_unserialize:serialization_mode* # Render: Views Available since: 1.1.0 Render the contents of a configured view. ## Fields `View` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_views:views_view_id* `Display` `Arguments` `Machine name` : Optionally define a machine name of this render element. It will be made available under that name in the render array of the current event in scope. Nested elements can be set with using "\]\[" brackets, for example *details\]\[title*.\ This field supports tokens. `Token name` : Optionally define a token name of this render element. It will be made available under that token name for later usage. Please provide the token name only, without brackets. `Element weight` : Optionally specify an element weight. The lower the weight, the element appears before other elements having a higher weight. `Build mode` : When using the "Defined by token" option, make sure there is a token with this name: *eca_render_views:views_mode* # Set active theme Available since: 1.1.0 ## Fields `Theme name` : Specify the machine name of the theme to set.\ This field supports tokens. # ECA alter link Available since: 3.0.3 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires for every link rendered on the page through the theme layer. Very high frequency This event fires for **every single link** on a page. Always use conditions to filter which links should be modified to avoid performance issues. Useful for adding attributes (e.g., `target="_blank"`), injecting tracking parameters, or adding CSS classes to links. # ECA Block Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[BLOCK_CONTEXT]` | The value of the block context under the given name of the token. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an ECA Block is rendered. Each ECA block event creates a corresponding block that can be placed in Drupal's Block Layout UI. Populate the render array using ECA actions to control the block's output. Block context values (such as the current node or user) are available as tokens when the block is placed in a context that provides them. ## Fields `Block name` : This block name will be used for being identified in the list of available blocks. ``` The human-readable name for this block. This name will appear in the block listing UI and is used to generate the machine name. ``` # Alter breakpoints Available since: 1.1.0 Allows to alter the breakpoint definitions. Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when Drupal builds its breakpoint plugin definitions, typically during cache rebuilds. Useful for defining custom responsive breakpoints via ECA instead of YAML files. # ECA contextual links Available since: 1.1.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[ROUTE_ENTITY]` | The entity from the route referenced by the token name as route parameter name. | | `[event]` | The event. | | `[event:group]` | The context group name. | | `[event:route_parameters]` | The route parameters. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when contextual links (pencil icon menus) are being assembled for renderable elements. Requires the Contextual module. Useful for adding custom contextual link items (e.g., 'Send to review', 'Clone') to entities of specific bundles. ## Fields `Restrict by link group` : Example: *menu* ``` Restricts to the specified contextual link group (e.g., `menu`). Leave empty to match all groups. ``` `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`). Comma-separated for multiple values. ``` # ECA entity Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:display]` | The entity display. | | `[event:entity]` | The entity. | | `[event:mode]` | The view mode. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when any content entity is being rendered, for any view mode. This wraps Drupal's `hook_entity_view()`. Useful for injecting custom render elements into entity displays (banners, computed values, warnings) or altering the entity's render array based on the view mode. ## Fields `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`, `taxonomy_term`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`, `tags`). Comma-separated for multiple values. ``` # ECA entity operation links Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when operation links are being gathered for an entity (e.g., 'Edit', 'Delete' dropdowns in admin listing tables). Useful for adding custom operation links (e.g., 'Clone', 'Publish', 'Archive') to entity listings. ## Fields `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` Restricts to the specified entity type (e.g., `node`). Comma-separated for multiple values. ``` `Restrict by entity bundle` : Example: *article, tags* ``` Restricts to the specified bundle (e.g., `article`). Comma-separated for multiple values. ``` # ECA Extra field Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Defines a custom extra field that appears in the entity's Manage Display or Manage Form Display UI. The extra field can be reordered and placed in regions like any real field. Populate the render array using ECA actions to control the field's output. The extra field name, entity type, and bundle are configured in this event. ## Fields `Restrict by entity type ID` : Example: *node, taxonomy_term, user* ``` The entity type this extra field should appear on (e.g., `node`). When empty, the field is registered for all entity types. ``` `Restrict by entity bundle` : Example: *article, tags* ``` The bundle this extra field should appear on (e.g., `article`). When empty, the field is registered for all bundles of the specified entity type. ``` `Machine name of the extra field` : The *machine name* of the extra field. Must only container lowercase alphanumeric characters and underscores. ``` The machine name for this extra field. Must contain only lowercase alphanumeric characters and underscores. ``` `Label of the extra field` : The human-readable label of the extra field. ``` The human-readable label shown in Manage Display or Manage Form Display. ``` `Description` : An optional description for this extra field, shown in field management interfaces. `Display type` : Choose whether this extra field appears in the entity's **view display** (rendered output) or **form display** (edit form). `Weight` : The default weight order. Must be an integer number. ``` The default weight (sort order) of this extra field. Can be overridden by dragging in the Manage Display UI. ``` `Default visible` : When enabled, the extra field will be automatically displayed by default. ``` When enabled, the extra field will be visible by default without requiring manual activation in Manage Display. ``` # ECA lazy element Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[argument]` | An optional argument for rendering the element. | | `[name]` | The name that identifies the lazy element for the event. | | `[event]` | The event. | | `[event:argument]` | An optional argument for rendering the element. | | `[event:name]` | The name that identifies the lazy element for the event. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a lazy ECA render element is being resolved. Lazy elements bypass page caching and are rendered separately (e.g., via BigPipe). Personalized content Use lazy elements for user-specific content (e.g., 'Welcome back, [username]', shopping cart count) that must not be cached with the rest of the page. The `[name]` and `[argument]` tokens identify the specific lazy element. ## Fields `Element name` : The name of the element, as it was specified in the configured action *Render: lazy element*. In any successor of this event, you have access to following tokens: ``` - **[name]**: Contains the name of the element. - **[argument]**: Contains the optional argument for the element. The element name that identifies this lazy element. Must match the name used in the 'Render: lazy element' action. ``` # ECA local tasks Available since: 2.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when local task tabs (primary and secondary tabs) are being rendered. Useful for dynamically adding or removing tabs on entity or admin pages. # ECA Views field Available since: 1.1.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[entity]` | The entity. | | `[ENTITY_TYPE]` | The entity by entity type, or the related entity by entity type. | | `[RELATED_ENTITY]` | The related entity. | | `[event]` | The event. | | `[event:entity]` | The entity. | | `[event:relationship]` | Get the relationship entities of the views row. | | `[event:view_display]` | The current display of the view. | | `[event:view_id]` | The view ID. | | `[event:view_args:?]` | The list of arguments given to the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires when an ECA Views field renders a row. The 'ECA Views field' must be added to a View as a global field, and the field name configured here must match. The entity for the current row is available via `[event:entity]`, and relationship entities via `[event:relationship]`. ## Fields `Field name` : The specified name of the field, as it is configured in the view. ``` The field name that identifies this ECA Views field. Must match the name configured in the Views field settings. ``` # ECA State Machine ## Installation ``` composer require drupal/eca_state_machine drush pm:install eca_state_machine ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA State Machine** from there. # State Machine: trigger entity state transition Available since: 1.0.0 ## Fields `Field name` `Transition` `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # State Machine: Entity State Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity` : Provide the token name of the *entity* that this condition should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Field name` `State` # State Machine: WorkflowTransition Available since: 1.0.0 ## Fields `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Transition` # State Machine: post_transition Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:entity]` | The entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after a state machine workflow transition has been applied to an entity. Use this to trigger follow-up actions based on the new state. The `[entity]` token provides the entity that has transitioned. # State Machine: pre_transition Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:entity]` | The entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires before a state machine workflow transition is applied to an entity. Use this to validate or prevent transitions. The `[entity]` token provides the entity undergoing the transition. # ECA Tamper ## Installation ``` composer require drupal/eca_tamper drush pm:install eca_tamper ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Tamper** from there. # Tamper: Make URLs absolute Available since: 1.0.0 Make URLs in markup absolute. (i.e. href='/stuff/things' to href='http://example.com/stuff/things). ## Fields Make URLs in markup absolute. (i.e. href='/stuff/things' to href='http://example.com/stuff/things). `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Base URL source` : The source name which holds the base URL. For example: https://example.com. # Tamper: Aggregate Available since: 1.0.0 Aggregates data, such as picking the maximum value. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Function` : Method of how to process multiple values into a single value. `Count mode` : The recursive option will count all elements in a multidimensional array. # Tamper: Filter items Available since: 1.0.0 Filter empty items from a list. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Cast to integer Available since: 1.0.0 This plugin will convert any value to its integer form. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Convert to Boolean Available since: 1.0.0 Convert to boolean. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Truth` : The value set to true. `False` : The value set to false. `Match case` : If enabled, the comparison becomes case-sensitive. `If no match` : The value to set if the true and false values do not match. `Other text` # Tamper: Convert case Available since: 1.0.0 Convert case. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `How to convert case` # Tamper: Copy Available since: 1.0.0 Copy value from one source to another. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `To or from` : Select whether this source value should be copied *to* another source, or *from* another source to this one. `Source` : List of sources accessible for copying. # Tamper: Country to ISO code Available since: 1.0.0 Converts this field from a country name string to the two character ISO 3166-1 alpha-2 code. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Date Offset Available since: 1.0.0 Offset date timestamp. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Offset` : A user-defined php date offset format string like "+1 month". See the [PHP manual](https://www.php.net/manual/en/datetime.modify.php) for available options.\ This field supports tokens. # Tamper: Set value or default value Available since: 1.0.0 Set value or default value. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Value` : This field will be set to the value specified. `Only if empty` : This field will be set to the value specified only if the imported field is empty. # Tamper: Encode/Decode Available since: 1.0.0 Encode (or Decode) the field contents. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Conversion mode:` # Tamper: Entity Finder Available since: 1.0.0 Finds an entity based on columns and fields. Returns the ID of the entity. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Entity type` # Tamper: Explode Available since: 1.0.0 Break up sequenced data into an array ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `String separator` : This will break up sequenced data into an array. For example, "a, b, c" would get broken up into the array('a', 'b', 'c'). A space can be represented by %s, tabs by %t, newlines by %n, and carriage returns by %r. `Limit` : If limit is set and positive, the returned items will contain a maximum of limit with the last item containing the rest of string. If limit is negative, all components except the last -limit are returned. If the limit parameter is zero, then this is treated as 1. If limit is not set, then there will be no limit on the number of items returned. # Tamper: Find replace Available since: 1.0.0 Find and replace text ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Text to find` `Text to replace` `Case sensitive` : If checked, "book" will match "book" but not "Book" or "BOOK". `Respect word boundaries` : If checked, "book" will match "book" but not "bookcase". `Match whole word/phrase` : If checked, then the whole word or phrase will be matched, e.g. "book" will match "book" but not "the book". If this option is selected then "Respect word boundaries" above will be ignored. # Tamper: Find replace (multiline) Available since: 1.0.0 Find and replace text, with multiple search/replacement patterns defined together. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Text to find and the replacements` : Enter one match per line in the format `search|replacement`, though the separator can be changed below. The replacements will be processed in order provided above. `Search/replacement value separator` : Control the character used to separate the "search" from the "replace" string in the field above. Defaults to "|", to match the value separator used on the Drupal core list fields. `Case sensitive` : If checked, "book" will match "book" but not "Book" or "BOOK". `Respect word boundaries` : If checked, "book" will match "book" but not "bookcase". `Match whole word/phrase` : If checked, then the whole word or phrase will be matched, e.g. "book" will match "book" but not "the book". If this option is selected then "Respect word boundaries" above will be ignored. # Tamper: Find replace REGEX Available since: 1.0.0 Find replace REGEX ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `REGEX to find` : A regular expression in the form: // `Replacement pattern` : The replacement pattern. `Limit number of replacements` : This sets an optional limit. Leave it blank for no limit. # Tamper: Hash Available since: 1.0.0 Makes the value a hash of the values of item being tampered. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Data to hash` : Note: if the source item is not available, a hash from the input value will be generated instead. `Only if empty` : A hash will only be generated if the input value is empty. You probably want to disable this option if you want to generate a hash of the input value. # Tamper: HTML entity decode Available since: 1.0.0 Convert all HTML entities such as & and " to & and ". ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: HTML entity encode Available since: 1.0.0 This will convert all HTML special characters such as > and & to > and &apm;. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Implode Available since: 1.0.0 Converts an array to a string. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `String glue` : Join array elements into a string. For example, array('a', 'b', 'c') would become "a, b, c". A space can be represented by %s, tabs by %t, and newlines by %n. # Tamper: Keyword filter Available since: 1.0.0 Filter based on a list of words/phrases. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Words or phrases to filter on` : A list of words/phrases that need to appear in the text. Enter one value per line. `Respect word boundaries` : If checked, then "book" will match "book" but not "bookcase". `Exact` : If checked, then "book" will only match "book". This will override the "Respect word boundaries" setting above. `Case sensitive` : If checked, then "book" will match "book" but not "Book" or "BOOK". `Invert filter` : Inverting the filter will remove items with the specified text. # Tamper: Math Available since: 1.0.0 Performs basic mathematical calculations on the imported value. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Operation` : The operation to apply to the imported value. `Flip` : Normally, the feed item will be processed like input-value / setting-value. This option switches the order so that it is setting-value / input-value. `Value` : A numerical value. `Skip calculation when the data is not numeric` : If checked, the data is returned as is when it is not numeric. If not checked, empty data will be treated as zero. # Tamper: Format a number Available since: 1.0.0 Format a number. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Decimals` : The number of decimal places. `Decimal point` : The character to use as the decimal point. `Thousands separator` : The character to use as the thousands separator. # Tamper: Required Available since: 1.0.0 Make this field required. If it is empty, the item will not be processed. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Invert filter` : Inverting the filter will save items only if the field is empty. # Tamper: Rewrite Available since: 1.0.0 Rewrite a field using tokens. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Replacement pattern` : - You can insert values using square brackets like `[fieldname]` (see replacement patterns below). - You can also use nested values such as `[author.name.first]` or `[address.street]`. - If the input is an array, the plugin will apply the expression to each value. - You can also use the special placeholder `{key}` to insert the current array key. For example: `[prices.{key}.amount]`. `Available replacement patterns` # Tamper: Skip tampers on empty Available since: 1.0.0 If it is empty, further Tamper plugins won't be applied. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Format string Available since: 1.0.0 Format string ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Format` : See the [sprintf](http://www.php.net/manual/en/function.sprintf.php) documentation for more details. # Tamper: State to abbrev Available since: 1.0.0 Converts this field from a full state name string to the two character abbreviation. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Get string length Available since: 1.0.0 Get the length of a string ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Pad a string Available since: 1.0.0 Pad a string ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Pad length` : If the input value has a length less than this, it will use the string below to increase the length. `Pad string` : The string to use for padding. If blank, a space will be used. `Pad type` # Tamper: Get position of sub-string Available since: 1.0.0 Get the position of a sub-string in a string ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `String to search for position` # Tamper: Strip tags Available since: 1.0.0 Strip tags. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Allowed tags` : A list of allowed tags such as *\*\** # Tamper: String to Unix Timestamp Available since: 1.0.0 This will take a string containing an English date format and convert it into a Unix Timestamp. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Custom date format` : The custom php date format string to parse the date with. This is optional and mainly useful when working with [certain date formats](https://stackoverflow.com/a/2892002). See the [PHP manual](https://www.php.net/manual/en/datetimeimmutable.createfromformat.php) for available options. `Fallback to strtotime() if the date could not be parsed with the provided date format.` # Tamper: Time Offset Available since: 1.0.0 Offset timestamp. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Timezone` # Tamper: Unix timestamp to Date Available since: 1.0.0 Unix timestamp to Date ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Date format` : A user-defined php date format string like "m-d-Y H:i". See the [PHP manual](http://www.php.net/manual/function.date.php) for available options. # Tamper: Transliterates text from Unicode to US-ASCII. Available since: 1.0.0 Runs the value through the transliteration service. Letters will have language decorations and accents removed. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: Characters to trim Available since: 1.0.0 Characters to trim. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Characters to trim` : The characters to remove from the string. If blank, then whitespace will be removed. `Side` # Tamper: Truncate Available since: 1.0.0 Truncate ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Number of characters` : The number of characters the text will be limited to. `Ellipses` : Add ellipses (…) to the end of the truncated text. `Truncate on a word boundary` : Attempt to truncate on a word boundary. # Tamper: Twig Available since: 1.0.0 Rewrite a field using twig. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Twig template` `Available replacement patterns` # Tamper: Unique Available since: 1.0.0 Makes the elements in a multivalued field unique. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. # Tamper: URL Decode Available since: 1.0.0 Run values through the [urldecode()](http://us3.php.net/urldecode) function. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Decode method` : Run values through the [urldecode()](http://us3.php.net/urldecode) function. # Tamper: URL Encode Available since: 1.0.0 Run values through the [urlencode()](http://us3.php.net/urlencode) function. ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Encode method` : Run values through the [urlencode()](http://us3.php.net/urlencode) function. # Tamper: Get number of words Available since: 1.0.0 Get the number of words in a string ## Fields `Data to be tampered` : This field supports tokens. `Result token name` : Provide a token name under which the tampered result will be made available for subsequent actions. `Limit` : If limit is set and positive, the returned items will contain a maximum of limit with the last item containing the rest of string. If limit is negative, all components except the last -limit are returned. If the limit parameter is zero, then this is treated as 1. If limit is not set, then there will be no limit on the number of items returned. # Tamper: Aggregate Available since: 1.0.0 Aggregates data, such as picking the maximum value. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:aggregate_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:aggregate_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Function` : Method of how to process multiple values into a single value. `Count mode` : The recursive option will count all elements in a multidimensional array. `Data to be tampered` `Data to compare with` # Tamper: Cast to integer Available since: 1.0.0 This plugin will convert any value to its integer form. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:cast_to_int_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:cast_to_int_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Convert to Boolean Available since: 1.0.0 Convert to boolean. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:convert_boolean_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:convert_boolean_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Truth` : The value set to true. `False` : The value set to false. `Match case` : If enabled, the comparison becomes case-sensitive. `If no match` : The value to set if the true and false values do not match. `Other text` `Data to be tampered` `Data to compare with` # Tamper: Convert case Available since: 1.0.0 Convert case. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:convert_case_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:convert_case_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `How to convert case` `Data to be tampered` `Data to compare with` # Tamper: Copy Available since: 1.0.0 Copy value from one source to another. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:copy_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:copy_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `To or from` : Select whether this source value should be copied *to* another source, or *from* another source to this one. `Source` : List of sources accessible for copying. `Data to be tampered` `Data to compare with` # Tamper: Country to ISO code Available since: 1.0.0 Converts this field from a country name string to the two character ISO 3166-1 alpha-2 code. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:country_to_code_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:country_to_code_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Date Offset Available since: 1.0.0 Offset date timestamp. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:dateoffset_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:dateoffset_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Offset` : A user-defined php date offset format string like "+1 month". See the [PHP manual](https://www.php.net/manual/en/datetime.modify.php) for available options. `Data to be tampered` `Data to compare with` # Tamper: Set value or default value Available since: 1.0.0 Set value or default value. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:default_value_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:default_value_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Value` : This field will be set to the value specified. `Only if empty` : This field will be set to the value specified only if the imported field is empty. `Data to be tampered` `Data to compare with` # Tamper: Encode/Decode Available since: 1.0.0 Encode (or Decode) the field contents. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:encode_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:encode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Conversion mode:` `Data to be tampered` `Data to compare with` # Tamper: Entity Finder Available since: 1.0.0 Finds an entity based on columns and fields. Returns the ID of the entity. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:entity_finder_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:entity_finder_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Entity type` `Data to be tampered` `Data to compare with` # Tamper: Find replace Available since: 1.0.0 Find and replace text ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Text to find` `Text to replace` `Case sensitive` : If checked, "book" will match "book" but not "Book" or "BOOK". `Respect word boundaries` : If checked, "book" will match "book" but not "bookcase". `Match whole word/phrase` : If checked, then the whole word or phrase will be matched, e.g. "book" will match "book" but not "the book". If this option is selected then "Respect word boundaries" above will be ignored. `Data to be tampered` `Data to compare with` # Tamper: Find replace (multiline) Available since: 1.0.0 Find and replace text, with multiple search/replacement patterns defined together. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_multiline_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_multiline_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Text to find and the replacements` : Enter one match per line in the format `search|replacement`, though the separator can be changed below. The replacements will be processed in order provided above. `Search/replacement value separator` : Control the character used to separate the "search" from the "replace" string in the field above. Defaults to "|", to match the value separator used on the Drupal core list fields. `Case sensitive` : If checked, "book" will match "book" but not "Book" or "BOOK". `Respect word boundaries` : If checked, "book" will match "book" but not "bookcase". `Match whole word/phrase` : If checked, then the whole word or phrase will be matched, e.g. "book" will match "book" but not "the book". If this option is selected then "Respect word boundaries" above will be ignored. `Data to be tampered` `Data to compare with` # Tamper: Find replace REGEX Available since: 1.0.0 Find replace REGEX ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_regex_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:find_replace_regex_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `REGEX to find` : A regular expression in the form: // `Replacement pattern` : The replacement pattern. `Limit number of replacements` : This sets an optional limit. Leave it blank for no limit. `Data to be tampered` `Data to compare with` # Tamper: Hash Available since: 1.0.0 Makes the value a hash of the values of item being tampered. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:hash_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:hash_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to hash` : Note: if the source item is not available, a hash from the input value will be generated instead. `Only if empty` : A hash will only be generated if the input value is empty. You probably want to disable this option if you want to generate a hash of the input value. `Data to be tampered` `Data to compare with` # Tamper: HTML entity decode Available since: 1.0.0 Convert all HTML entities such as & and " to & and ". ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:html_entity_decode_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:html_entity_decode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: HTML entity encode Available since: 1.0.0 This will convert all HTML special characters such as > and & to > and &apm;. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:html_entity_encode_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:html_entity_encode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Math Available since: 1.0.0 Performs basic mathematical calculations on the imported value. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:math_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:math_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Operation` : The operation to apply to the imported value. `Flip` : Normally, the feed item will be processed like input-value / setting-value. This option switches the order so that it is setting-value / input-value. `Value` : A numerical value. `Skip calculation when the data is not numeric` : If checked, the data is returned as is when it is not numeric. If not checked, empty data will be treated as zero. `Data to be tampered` `Data to compare with` # Tamper: Format a number Available since: 1.0.0 Format a number. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:number_format_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:number_format_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Decimals` : The number of decimal places. `Decimal point` : The character to use as the decimal point. `Thousands separator` : The character to use as the thousands separator. `Data to be tampered` `Data to compare with` # Tamper: Rewrite Available since: 1.0.0 Rewrite a field using tokens. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:rewrite_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:rewrite_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Replacement pattern` `Available replacement patterns` `Data to be tampered` `Data to compare with` # Tamper: Format string Available since: 1.0.0 Format string ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:sprintf_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:sprintf_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Format` : See the [sprintf](http://www.php.net/manual/en/function.sprintf.php) documentation for more details. `Data to be tampered` `Data to compare with` # Tamper: State to abbrev Available since: 1.0.0 Converts this field from a full state name string to the two character abbreviation. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:state_to_abbrev_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:state_to_abbrev_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Get string length Available since: 1.0.0 Get the length of a string ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_len_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_len_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Pad a string Available since: 1.0.0 Pad a string ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_pad_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_pad_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Pad length` : If the input value has a length less than this, it will use the string below to increase the length. `Pad string` : The string to use for padding. If blank, a space will be used. `Pad type` `Data to be tampered` `Data to compare with` # Tamper: Get position of sub-string Available since: 1.0.0 Get the position of a sub-string in a string ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_pos_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:str_pos_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `String to search for position` `Data to be tampered` `Data to compare with` # Tamper: Strip tags Available since: 1.0.0 Strip tags. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:strip_tags_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:strip_tags_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Allowed tags` : A list of allowed tags such as *\*\** `Data to be tampered` `Data to compare with` # Tamper: String to Unix Timestamp Available since: 1.0.0 This will take a string containing an English date format and convert it into a Unix Timestamp. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:strtotime_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:strtotime_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Custom date format` : The custom php date format string to parse the date with. This is optional and mainly useful when working with [certain date formats](https://stackoverflow.com/a/2892002). See the [PHP manual](https://www.php.net/manual/en/datetimeimmutable.createfromformat.php) for available options. `Fallback to strtotime() if the date could not be parsed with the provided date format.` `Data to be tampered` `Data to compare with` # Tamper: Time Offset Available since: 1.0.0 Offset timestamp. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:timeoffset_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:timeoffset_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Timezone` `Data to be tampered` `Data to compare with` # Tamper: Unix timestamp to Date Available since: 1.0.0 Unix timestamp to Date ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:timetodate_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:timetodate_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Date format` : A user-defined php date format string like "m-d-Y H:i". See the [PHP manual](http://www.php.net/manual/function.date.php) for available options. `Data to be tampered` `Data to compare with` # Tamper: Transliterates text from Unicode to US-ASCII. Available since: 1.0.0 Runs the value through the transliteration service. Letters will have language decorations and accents removed. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:transliteration_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:transliteration_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Data to be tampered` `Data to compare with` # Tamper: Characters to trim Available since: 1.0.0 Characters to trim. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:trim_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:trim_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Characters to trim` : The characters to remove from the string. If blank, then whitespace will be removed. `Side` `Data to be tampered` `Data to compare with` # Tamper: Truncate Available since: 1.0.0 Truncate ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:truncate_text_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:truncate_text_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Number of characters` : The number of characters the text will be limited to. `Ellipses` : Add ellipses (…) to the end of the truncated text. `Truncate on a word boundary` : Attempt to truncate on a word boundary. `Data to be tampered` `Data to compare with` # Tamper: URL Decode Available since: 1.0.0 Run values through the [urldecode()](http://us3.php.net/urldecode) function. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:url_decode_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:url_decode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Decode method` : Run values through the [urldecode()](http://us3.php.net/urldecode) function. `Data to be tampered` `Data to compare with` # Tamper: URL Encode Available since: 1.0.0 Run values through the [urlencode()](http://us3.php.net/urlencode) function. ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:url_encode_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:url_encode_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Encode method` : Run values through the [urlencode()](http://us3.php.net/urlencode) function. `Data to be tampered` `Data to compare with` # Tamper: Get number of words Available since: 1.0.0 Get the number of words in a string ## Fields `Comparison operator` : The available comparison operators like *equals* or *less than*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:word_count_operator* `Comparison type` : The type of the comparison.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_tamper_condition:word_count_type* `Case sensitive comparison` : Compare the values based on case sensitivity. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. `Limit` : If limit is set and positive, the returned items will contain a maximum of limit with the last item containing the rest of string. If limit is negative, all components except the last -limit are returned. If the limit parameter is zero, then this is treated as 1. If limit is not set, then there will be no limit on the number of items returned. `Data to be tampered` `Data to compare with` # ECA User ## Installation ``` composer require drupal/eca drush pm:install eca_user ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA User** from there. # User: get preferred language code Available since: 2.0.0 Get the preferred language code and store it as a token. ## Fields `Name of token` : The language code will be stored into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. # User: create new Available since: 2.0.0 Create a new user without saving it. ## Fields `Name of token` : Provide the name of a token that holds the new user. Please provide the token name only, without brackets. `User name` : The user name of the new user. If that name already exists, a hyphen followed by a number will be appended. `Email address` : The email address of the new user. If that email already exists for another user, this action will fail. `Status` : Whether the user should be active or not. `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. # User: switch current account Available since: 1.0.0 Switch to given user account. **Note:** the changed user account is only active in all successors of the user switch action and will be reset to the previous user accounts when leaving this context. ## Fields `User ID (UID)` : The numeric ID of the user account to switch to.\ This field supports tokens. # User: switch back Available since: 2.1.4 Switch to previous user account. # User: switch to service user Available since: 2.1.3 Switch to the globally configured service account. # Current user: load Available since: 1.0.0 Load the current user and store it as a token. ## Fields `Name of token` : The loaded current user will be stored into this token. Please provide the token name only, without brackets. # Current user ID Available since: 1.0.0 Compares a user ID with the current user ID. ## Fields `User ID` : The user ID, which gets compared.\ This field supports tokens. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Current user has permission Available since: 1.0.0 Checks, whether the current user has a given permission. ## Fields `Permission` : The permission to check, like *administer node display*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_current_user_permission_permission* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Role of current user Available since: 1.0.0 Checks, whether the current user has a given role. ## Fields `User role` : The user role to check, like *editor* or *administrator*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_current_user_role_role* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # ID of user Available since: 1.0.0 Compares a user ID with a loaded ID of a given user account. ## Fields `User account` : The ID of an account or a token with a stored account entity. `User ID` : The user ID, which gets compared.\ This field supports tokens. `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # User has permission Available since: 1.0.0 Checks, whether a given user account has a given permission. ## Fields `User account` : The ID of an account or a token with a stored account entity. `Permission` : The permission to check, like *administer node display*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_user_permission_permission* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Role of user Available since: 1.0.0 Checks, whether a given user account has a given role. ## Fields `User account` : The ID of an account or a token with a stored account entity. `User role` : The user role to check, like *editor* or *administrator*.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_user_role_role* `Negate the condition` : Negates the condition. Makes TRUE to FALSE and vice versa. # Cancelling a user Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The user entity of the event. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Reacts when a user account is being cancelled. Does not fire for the delete cancellation method This event does **not** fire when the cancellation method is set to "Delete the account and its content." For that case, use the [Delete content entity](https://ecaguide.org/plugins/eca/content/events/content_entity_delete/index.md) event instead. The four built-in cancellation methods that this event supports are: - **Block the account** -- Disable the account and keep content. - **Block the account and unpublish content** -- Disable the account and unpublish all associated content. - **Reassign content** -- Delete the account and make its content belong to the Anonymous user. # Flood blocked IP Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The flooding user entity. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when a login attempt is blocked by Drupal's flood control due to too many failed attempts from a particular IP address. This wraps the Drupal core `UserEvents::FLOOD_BLOCKED_IP` event, which fires when the flood threshold for `user.failed_login_ip` is exceeded. Account token may be empty For IP-based flood blocks, the `[account]` token may not resolve to a user entity because the flood control only tracks the IP address, not a specific user account. # Flood blocked user Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The flooding user entity. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts when a login attempt is blocked by Drupal's flood control due to too many failed attempts targeting a specific user account. This wraps the Drupal core `UserEvents::FLOOD_BLOCKED_USER` event. Both form-based login and HTTP basic authentication login attempts are tracked. The `[account]` token provides the user entity of the targeted account. # Login of a user Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The user entity of the event. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Reacts when a user logs in. This event fires after the login is fully finalized -- the session is already active and the last login timestamp has been saved. The `[account]` token (alias: `[entity]`) provides the user entity of the account that just logged in. # Logout of a user Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The user entity of the event. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Reacts when a user logs out. This event fires while the session still exists -- it is destroyed immediately after all event processing completes. The `[account]` token provides the user entity of the account that is logging out. # Set current user Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[account]` | The user entity of the event. Alias: `entity` | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Reacts every time the current user account is set. This wraps the Drupal core `AccountEvents::SET_USER` event. Fires very frequently This event fires on virtually every request (during session initialization), on login, on logout, and any time the current user is programmatically switched. Use with caution as it can trigger very frequently and may cause performance issues if the ECA model performs expensive operations. When this event fires during logout, the account being set is the anonymous user (uid 0). # ECA VBO ## Installation ``` composer require drupal/eca_vbo drush pm:install eca_vbo ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA VBO** from there. # VBO: Get configuration value Available since: 1.0.0 Get a configuration value from the action of the bulk operation and store it as a token. ## Fields `Config key` : The config key, for example *message_text*. This may also be the machine name of a custom form field. Leave empty to use the whole config. **Please note:** This action only works upon the event *VBO: Execute Views bulk operation*. `Name of token` : The targeted configuration value will be loaded into this specified token. `Replace tokens` : When checked, existing Tokens within the user-provided configuration input will be replaced. `Default value` : Optionally specify a default value when no value is given for the specified config key.\ This field supports tokens. # VBO: Get Views argument Available since: 1.0.0 Get an argument passed to the according view of the bulk operation and store it as a token. ## Fields `Argument index key` : Index counting starts at 0. Leave empty to get all available arguments. `Name of token` : The argument value will be loaded into this specified token. `Default value` : Optionally specify a default value when no value is given for the specified index.\ This field supports tokens. # VBO: Set custom access on Views Bulk Operation Available since: 1.0.0 This action only works upon the event *VBO: Custom access for Views bulk operation*. ## Fields `Access granted` # VBO: Set result Available since: 1.0.0 Set the result output of an executed views bulk operation. This action only works upon the event *VBO: Execute Views bulk operation*. ## Fields `Result` : This field supports tokens. # VBO: Confirm form build of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO confirmation form is being built. This is a separate page that shows the user what they are about to execute and asks for final confirmation. Use ECA actions to add extra information or elements to the confirmation page. Can be skipped If the VBO action is preconfigured with `skip_confirm`, the confirmation form is automatically submitted and this step is bypassed. ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Confirm form submit of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO confirmation form is submitted, right before execution begins. This is the last event before the bulk operation processes entities. ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Confirm form validate of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO confirmation form is being validated. Does not fire if the confirmation step is skipped. ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Custom access for Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the access check to determine whether the current user can see and use a particular bulk operation. Use the [VBO: Set custom access](https://ecaguide.org/plugins/eca/vbo/actions/eca_vbo_set_custom_access/index.md) action to grant or deny access. Requires ECA bulk operations field The operation name filter only works when the View uses the **ECA bulk operations** Views field plugin, not the standard VBO field. ## Fields `Operation name` : Important note: The operation name is only available, when the operation got executed from the *ECA bulk operations* Views field plugin. ``` The operation name to check access for. Only available when using the ECA bulk operations Views field plugin. ``` `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Execute Views bulk operation (one by one) Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event:entity]` | The currently processed entity. | | `[event:entity:id]` | The entity ID. | | `[event:entity:label]` | The entity label. | | `[event:entity:type]` | The ID of the entity type. | | `[event:entity:bundle]` | The bundle of the entity. | | `[event:entity:langcode]` | The language code ID of the entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Fires once for each selected entity during the bulk operation. This is the primary execution event where you implement per-entity logic. The entity from the current Views row is available as the standard entity context. Use the [VBO: Get configuration value](https://ecaguide.org/plugins/eca/vbo/actions/eca_vbo_get_config_value/index.md) action to retrieve user input from the configuration form. ## Fields `Operation name` : The operation name identifies this process and will show up in the bulk operations configuration form as selectable action. If you need custom access handling using the operation name, then make sure that the Views configuration is using the *ECA bulk operations* Views field plugin.\ By using one-by-one execution (for each single entity), you have following tokens available: ``` - *[event:view]* containing info about the used view - *[event:action]* containing info about the executed action - *[event:entity]* containing info about the entity in scope The operation name identifies this bulk operation. It will appear as a selectable action in the Views bulk operations configuration. ``` `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Execute Views bulk operation (multiple at once) Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event:queue]` | The queued entities to process. | | `[event:queue:count]` | The number of items in the queue. | | `[event:queue:ids]` | The list of entity ids. | | `[event:queue:revisions]` | The list of entity revision ids. | | `[event:queue:items]` | The list of entities. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires once with all selected entities before per-entity execution begins. The `[event:queue]` token provides access to the full list of selected entities. Use this for batch-level operations (e.g., generating a single report, sending one notification for all entities, or pre-filtering the entity queue). ## Fields `Operation name` : The operation name identifies this process and will show up in the bulk operations configuration form as selectable action. If you need custom access handling using the operation name, then make sure that the Views configuration is using the *ECA bulk operations* Views field plugin.\ By using multiple execution (selected entities at once), you have following tokens available: ``` - *[event:view]* containing info about the used view - *[event:action]* containing info about the executed action - *[event:queue]* containing info about the queued entities selected for processing The operation name identifies this bulk operation. It will appear as a selectable action in the Views bulk operations configuration. ``` `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Form build of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO action's configuration form is being built. This form appears after selecting a bulk operation and clicking 'Apply to selected items'. Use ECA actions to add custom form elements for collecting additional input from the user. Auto-skip when empty If no form elements are added by ECA, this step is automatically skipped and the user proceeds directly to the confirmation page. ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Form submit of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO action's configuration form is submitted. The submitted values become part of the action's configuration and are available in all subsequent events (confirmation and execution). ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # VBO: Form validate of Views bulk operation Available since: 1.0.0 Provided tokens | Token | Description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:view]` | The view config entity. | | `[event:view:id]` | The view ID. | | `[event:view:display_id]` | The display ID. | | `[event:action]` | The action plugin. | | `[event:action:plugin]` | The ID of the action plugin. | | `[event:action:config]` | An array with key value pairs of the configuration of the plugin. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the VBO action's configuration form is being validated. Only fires if the configuration form was displayed (not skipped). Use this to validate user input collected during the form build step. ## Fields `Operation name` : The operation name that identifies the bulk operation this event reacts to. `Optionally restrict by view ID` : Optionally restrict to a specific View by machine name. Leave empty to react to all Views. Comma-separated for multiple values. `Optionally restrict by view display ID` : Optionally restrict to a specific View display (e.g., `page_1`, `block_1`). Leave empty to react to all displays. Comma-separated for multiple values. # ECA Views Provides integration between ECA and the Drupal Views module. This allows ECA models to execute Views queries, export results to files, manipulate query parameters, and react to Views lifecycle events (such as pre/post build, execute, and render phases). Understanding Views query results in ECA When using the **Views: Execute query** or **Views: Export query into file** actions, the result stored in a token is a list of **complete entity objects**. It does not reflect the field configuration of the View — field formatters, labels, rewritten values, and display settings have no effect on the token data. You always receive the full entities that matched the query, which you can then access using standard entity property tokens. ## Installation ``` composer require drupal/eca drush pm:install eca_views ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Views** from there. # Views: Export query into file Available since: 1.0.0 Use a view to execute a query and save the results to a file. You can also save the results in a token. Token results are complete entities, not field-configured output When the option to store results in a token is enabled, the token contains a list of **complete entity objects** — not the formatted field output configured in the View. Field formatters, labels, rewritten fields, and display settings from the View have no effect on the token values. See the [Views: Execute query](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) documentation for details. The **exported file** itself does use the View's display and field configuration as expected. ## Fields `Store results also in a token?` : Check this box to save the results to a token as well `Token name for file name` : Provide a token name where ECA will store the effectively used filename of the output. Please provide the token name only, without brackets. `File name` : Sets the name of the file where the data will be exported. If left empty, the file name configured in the view will be used, or a random name otherwise.\ This field supports tokens. `Name of token` : Name of the token available after view execution. Contains an indexed list of elements that the view returns. Please provide the token name only, without brackets. `View` : Select the view from the list. The view will always return a list of complete entities.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_views_export_view_id* `Display` : Write the view `display id` to execute. Set as default to use the default view configuration. `Arguments` : Provide the values for contextual filters in the same order as they are defined in the view. Separate multiple values with the `/` character. # Views: Execute query Available since: 1.0.0 Use a View to execute a query and store the results in a token that contains an indexed list of the results. Despite the type of view that you use, always get the complete entities obtained by the view. You can access the entity properties using the token style. Query results are complete entities, not field-configured output The result of this action is a list of **complete entity objects** loaded from the database. It does **not** reflect the field configuration of the View (i.e. which columns are selected, how they are formatted, or which labels are assigned in the View's field settings). This means: - All entity properties and field values are available on each result item, regardless of whether they appear as fields in the View display. - Conversely, computed or rewritten fields that only exist in the View's display configuration are **not** part of the result. - Field formatters, labels, and display settings configured in the View have no effect on the token values you receive. To access values from the result list, use the token name you configure below together with an index and entity property tokens, for example `[my_results:0:title]` for the title of the first result entity. ## Fields `Name of token` : Name of the token available after view execution. Contains an indexed list of elements that the view returns. Please provide the token name only, without brackets. `View` : Select the view from the list. The view will always return a list of complete entities.\ When using the "Defined by token" option, make sure there is a token with this name: *eca_views_query_view_id* `Display` : Write the view `display id` to execute. Set as default to use the default view configuration. `Arguments` : Provide the values for contextual filters in the same order as they are defined in the view. Separate multiple values with the `/` character. # Views: Query Substitution Available since: 2.0.0 ## Fields `Value to replace` : Provide the string that should be replaced in the query.\ This field supports tokens. `Replacement value` : Provide the string that should replace the above string in the query.\ This field supports tokens. # Views: Set filter value Available since: 2.0.0 ## Fields `Filter ID` : The ID of the view filter.\ This field supports tokens. `The value of the filter` : The value of the filter. This can either be a string or a YAML array when multiple keys have to be set for that filter.\ This field supports tokens. `Interpret above config value as YAML format` : Interpret above value as YAML format `Validate YAML to prevent this from being executed when invalid` # Views: Access Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Fires during access checking for a View display. This only works when the View display's access plugin is set to **ECA** in the Views UI. Access defaults to denied If no ECA model grants access, the View will be inaccessible. You must explicitly set the access result using the [Set access result](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) action. Performance Views with ECA access are **not cached** (`maxAge=0`). This can have significant performance implications on high-traffic sites. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Post Build Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the entire query has been constructed, all handlers initialized, and the query altered. The view is fully built at this point. Useful for inspecting the built query, modifying field visibility based on exposed filter values, or adding additional fields before execution. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Post Execute Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires immediately after query execution (or cache retrieval). The result set is available but handler `preRender()` has not yet run. Useful for modifying the result set (adding, removing, or reordering rows), logging execution metrics, or displaying messages based on result count. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Post Render Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the display handler has produced its render array. This is the only Views event that provides a render array for manipulation. Useful for modifying the final render output, adding post-render callbacks, or adjusting cache settings. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Pre Build Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires at the start of the build phase, after the display has been set but before query construction and handler initialization begin. The display handler is available, but query and field/filter/sort handlers are not yet initialized. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Pre Execute Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after the build phase but before the database query is executed. This is the last chance to modify the query before it hits the database. You can abort execution by setting `abort` in the build info. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Pre Render Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after all handler `preRender()` methods have run but before the display handler renders the output. The result set is fully prepared at this point. Useful for reordering results, adding CSS/JS, or modifying field handler output before template rendering. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Pre View Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires at the very beginning of the Views lifecycle, before any building, query construction, or execution. This is the earliest Views event. The view arguments can be modified at this stage. No query, handlers, or styles are initialized yet. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Query Alter Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during the build phase, after all handlers have added their conditions but before the query is finalized. This is the place to add extra WHERE conditions, JOINs, or modify sort orders dynamically. Useful for row-level access control, dynamic filtering based on user context, or adding conditions beyond what Views handlers provide. ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # Views: Query Substitutions Available since: 2.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[event]` | The event. | | `[event:args:?]` | The list of arguments given to the view. | | `[event:display_id]` | The display_id of the view. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during query building and again during query execution, allowing injection of dynamic runtime values into Views queries. Useful for providing context-dependent query parameters (e.g., current user's department, geographic location, or tenant ID). ## Fields `View` : Select the view from the list. ``` Select the View this event should react to. Only enabled Views are listed. ``` `Display` : Provide the view `display id` to which to respond. Leave empty to respond on any display. ``` The machine name of a specific display (e.g., `page_1`, `block_1`). Leave empty to react to all displays of the selected View. ``` # ECA Views data export ## Installation ``` composer require drupal/eca_views_data_export drush pm:install eca_views_data_export ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Views data export** from there. # Set column value Available since: 1.0.0 ## Fields `Column` `Value` # Alter a row Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[current_result]` | The result object of the event. | | `[current_row]` | The row object of the event. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires for each row during a Views data export, allowing you to alter row data before it is written to the export file. The `[current_row]` token contains the row data (field values keyed by field name) and `[current_result]` provides the raw Views result object for the row. You can optionally filter by View ID and Display ID to target specific exports. ## Fields `View ID` : The machine name of the view to filter for. Leave empty to react to all views. `Display ID` : The display ID within the view to filter for (e.g., `data_export_1`). Leave empty to react to all displays. # ECA Webform ## Installation ``` composer require drupal/eca_webform drush pm:install eca_webform ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Webform** from there. # Webform: Get third-party setting Available since: 2.1.0 ## Fields `Provider` : The machine name of the module that provides the setting.\ This field supports tokens. `Setting name` : The machine name of the setting, that holds the value.\ This field supports tokens. `Name of token` : The setting value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Webform: Set third-party setting Available since: 2.1.0 ## Fields `Provider` : The machine name of the module that provides the setting.\ This field supports tokens. `Setting name` : The machine name of the setting, that holds the value.\ This field supports tokens. `Setting value` : The new setting value.\ This field supports tokens. `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Webform Submission: Get data Available since: 1.0.0 ## Fields `Field name` : The machine name of the field, that holds the value.\ This field supports tokens. `Name of token` : The field value will be loaded into this specified token. Please provide the token name only, without brackets. `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Webform Submission: Set data Available since: 1.0.0 ## Fields `Field name` : The machine name of the field, that holds the value.\ This field supports tokens. `Field value` : The new field value.\ This field supports tokens. `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Access rules Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when collecting access rules that should be manageable on a per-webform basis. Access rules define operations (like custom view/edit operations) that site administrators can grant to specific roles in each webform's access settings. # Alter access rules Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after all access rules have been collected, allowing modification of the available rules. Use this to remove unwanted rules or change default role assignments. # Alter admin third party settings form Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:form]` | The form array. | | `[event:webform:form_state]` | The form state object. | | `[event:webform:operation]` | The operation for which the access can be altered. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the global webform admin settings form is being built. Use this to add custom module-specific settings to the webform configuration page. # Element access Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:account]` | The user account entity. | | `[event:webform:context]` | The webform context. | | `[event:webform:element]` | The form element. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Fires when checking whether a user can access a specific webform element during create, view, or update operations. Use the appropriate access actions to grant or deny per-element access. The `[event:webform:operation]` token is `create`, `view`, or `update`, and `[event:webform:element]` provides the element render array. # Alter element Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:context]` | The webform context. | | `[event:webform:element]` | The form element. | | `[event:webform:form_state]` | The form state object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires for every element in a webform during form preparation. This is one of the most commonly used webform events for modifying element properties (labels, placeholders, default values, attributes) or attaching custom JavaScript behaviors. High frequency This event fires once per element in the form tree. Use conditions to target specific elements and keep reactions lightweight. # Alter element configuration form Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:form]` | The form array. | | `[event:webform:form_state]` | The form state object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when the webform element configuration (edit) form is being built in the Webform UI builder. Use this to add custom configuration fields for properties defined via the element default properties alter event. # Alter element default properties Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:definition]` | The property definition. | | `[event:webform:properties]` | The properties. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when assembling a webform element's default properties. Add custom properties here to make them configurable per element. Works with element configuration form alter Add a property here with an empty default value, then add a form field for it using the element configuration form alter event. # Alter element info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:handlers]` | The webform handlers. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during webform element plugin discovery, allowing modification of the metadata about available element types. Use this to hide, relabel, or recategorize element types in the webform builder. # Element input masks Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:input_masks]` | The input masks. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when collecting available input masks for text-based webform elements. Input masks constrain user input to specific formats (e.g., phone numbers, dates, postal codes). Use this to provide custom input mask definitions. # Alter element input masks Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:input_masks]` | The input masks. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after all input masks have been collected, allowing modification of the available masks. Use this to remove, modify, or conditionally add input masks. # Alter element translatable properties Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:definition]` | The property definition. | | `[event:webform:properties]` | The properties. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when determining which element properties are available for translation. Add custom property names to make them translatable in the webform translation interface. # Alter handler info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:definitions]` | The handler definitions. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during webform handler plugin discovery, allowing modification of available handler types. Webform handlers process submissions (e.g., email handler, remote post handler). Use this to hide, relabel, or override handler types. # Alter handler invoke Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:args]` | The handler arguments. | | `[event:webform:handler]` | The handler. | | `[event:webform:method_name]` | The name of the method. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires whenever any method on a webform handler is about to be invoked. This is a powerful interception point for conditionally enabling/disabling handlers, altering handler arguments, or preprocessing data before it reaches the handler. The `[event:webform:method_name]` token identifies the method (e.g., `submit_form`, `post_save`, `pre_save`). # Help info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:help_info]` | The help information. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when collecting help entries for the webform help system. Use this to provide custom help messages or tutorials that appear on specific webform admin pages. # Alter help info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:help_info]` | The help information. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after all help entries have been collected, allowing modification of existing help messages. Use this to change titles, routes, or content of help entries. # Alter image select images Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:element]` | The form element. | | `[event:webform:images]` | The list of images. | | `[event:webform:image_id]` | The image entity ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when images for a webform image select element are being loaded. Use this to dynamically filter, add, or replace images based on user context or external data. # Alter options Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:element]` | The form element. | | `[event:webform:options]` | The list of options. | | `[event:webform:option_id]` | The option ID. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when options for a webform select/checkbox/radio element are being prepared. Use this to dynamically populate options from external sources, filter options based on user context, or reorder options. # Alter source entity info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:definitions]` | The handler definitions. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during WebformSourceEntity plugin discovery, allowing modification of how webforms discover their source entity context (e.g., the node containing a webform field). # Submission access Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:account]` | The user account entity. | | `[event:webform:operation]` | The operation for which the access can be altered. | | `[event:webform:submissions]` | The webform submissions. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[account]` | The user account of the event. | Fires when checking whether a user can perform an operation (view, update, delete) on a webform submission. Use the appropriate access actions to grant or deny access. The `[event:webform:account]` token provides the checked account, and `[event:webform:operation]` the requested operation. # Alter submission form Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:form]` | The form array. | | `[event:webform:form_id]` | The form ID. | | `[event:webform:form_state]` | The form state object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a webform submission form is being built, before rendering. Functionally similar to Drupal's `hook_form_alter()` but specific to webform submission forms. Use this to add submit handlers, modify form structure, or inject custom elements. # Alter submission query access Available since: 1.0.0 Provided tokens | Token | Description | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:query]` | The submission query access. | | `[event:webform:submission_tables]` | The webform submission tables. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a database query listing webform submissions is being modified for access control. Use this to add conditions for row-level security or custom access filtering at the query level. # Submissions post-purge Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:submissions]` | The webform submissions. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires after webform submissions have been purged. The submissions no longer exist in the database. Useful for cleanup of related data in external systems. # Submissions pre-purge Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:submissions]` | The webform submissions. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires before webform submissions are purged during the scheduled purge process. The submissions still exist at this point. Useful for archiving data or sending notifications before deletion. # Alter third party settings form Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[form]` | The current form. Alias: `current_form` | | `[form:id]` | The form ID. | | `[form:base_id]` | The form base ID. | | `[form:operation]` | The form operation. | | `[form:mode]` | The form mode. | | `[form:triggered]` | The form field name that triggered the form event. | | `[form:values]` | | | `[form:values:FIELD_NAME]` | The field value for each of the named fields. | | `[form:num_errors]` | The number of form errors. | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:form]` | The form array. | | `[event:webform:form_state]` | The form state object. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an individual webform's settings form is being built. Unlike the admin variant (which is global), this event fires per-webform. Use this to add module-specific configuration fields to each webform's settings. # Alter variant info Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[event]` | The event. | | `[event:webform]` | The webform. | | `[event:webform:access_rules]` | The access rules. | | `[event:webform:variants]` | The variants. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires during webform variant plugin discovery, allowing modification of variant plugin definitions. Webform variants enable A/B testing or conditional form variations. # ECA Workflow ## Installation ``` composer require drupal/eca drush pm:install eca_workflow ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **ECA Workflow** from there. # Entity workflow Editorial: transition Available since: 1.0.0 ## Fields `New state` : When using the "Defined by token" option, make sure there is a token with this name: *eca_workflow_transition:editorial_new_state* `Revision Log` : This field supports tokens. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Workflow: state transition Available since: 1.0.0 Provided tokens | Token | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[user]` | The current user. Alias: `current_user` | | `[htmx]` | Information about the current HTMX request. | | `[htmx:is_request]` | Whether the current request was sent by HTMX ("1" or "0"). | | `[htmx:boosted]` | Whether the current request was boosted by HTMX ("1" or "0"). | | `[htmx:history_restore]` | Whether the current request is for HTMX history restoration ("1" or "0"). | | `[htmx:target]` | The value of the HX-Target request header. | | `[htmx:trigger]` | The value of the HX-Trigger request header. | | `[htmx:trigger_name]` | The value of the HX-Trigger-Name request header. | | `[htmx:current_url]` | The value of the HX-Current-URL request header. | | `[htmx:prompt]` | The value of the HX-Prompt request header. | | `[from_state]` | The source workflow state of the entity. | | `[to_state]` | The destination workflow state of the entity. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | | `[entity]` | The entity of the event. | | `[ENTITY_TYPE]` | The entity of the event under the name of its entity type. | Drupal core bug prevents transition recognition under certain circumstances For more details, there is a workaround available which is described in the [Troubleshooting Section](https://ecaguide.org/eca/troubleshooting/#workflow-transition-sometimes-not-recognized) ## Fields `Type (and bundle)` : Select the entity type and bundle to restrict this event to, or choose 'All' to react to transitions on any moderated entity. `From state` : Optionally restrict to the machine name of the previous state. ``` The machine name of the previous state (e.g., `draft`). Leave empty to match any source state. May be empty for newly created entities. ``` `To state` : Optionally restrict to the machine name of the new state. ``` The machine name of the new state (e.g., `published`). Leave empty to match any destination state. ``` # Entity Print ## Installation ``` composer require drupal/entity_print drush pm:install entity_print ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Entity Print** from there. # Print ## Fields `Export type` `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Entity Share Client ## Installation ``` composer require drupal/entity_share drush pm:install entity_share_client ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Entity Share Client** from there. # Update policy Available since: unknown ## Fields `Policy` : Select the policy to apply `Entity` : Provide the token name of the *entity_import_status* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Flag ## Installation ``` composer require drupal/flag drush pm:install flag ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Flag** from there. # Delete flagging (unflag) Available since: unknown ## Fields `Entity` : Provide the token name of the *flagging* that this action should operate with. Please provide the token name only, without brackets. # Group Actions ## Installation ``` composer require drupal/group_action drush pm:install group_action ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Group Actions** from there. # Group: add content Available since: unknown ## Fields `Type of group content` `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Group content values` : A key-value list of raw field values to set for the Group content. Supports tokens. Set one value per line. Example: *field_mynumber: 1\ group_roles: mygroup-myrole1\ group_roles: mygroup-myrole2* `How to add` `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Group: add user as member Available since: unknown ## Fields `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Group content values` : A key-value list of raw field values to set for the Group content. Supports tokens. Set one value per line. Example: *field_mynumber: 1\ group_roles: mygroup-myrole1\ group_roles: mygroup-myrole2* `How to add` `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Group: remove content Available since: unknown ## Fields `Type of group content` `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Group: remove user as member Available since: unknown ## Fields `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Group: update content Available since: unknown ## Fields `Type of group content` `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Group content values` : A key-value list of raw field values to set for the Group content. Supports tokens. Set one value per line. Example: *field_mynumber: 1\ group_roles: mygroup-myrole1\ group_roles: mygroup-myrole2* `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Group: update user membership Available since: unknown ## Fields `Group ID / UUID` : The numerical or universally unique ID of the group. This field supports tokens. `Entity ID / UUID` : The entity ID. Supports tokens. Leave blank to use the entity this action will operate on. `Group content values` : A key-value list of raw field values to set for the Group content. Supports tokens. Set one value per line. Example: *field_mynumber: 1\ group_roles: mygroup-myrole1\ group_roles: mygroup-myrole2* `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Mautic ECA The Mautic ECA module provides integration between Drupal and Mautic marketing automation platform through ECA (Events-Conditions-Actions) workflows. ## Features - **Contact Management**: Create, update, delete, and retrieve contacts from Mautic - **Segment Management**: Manage contact segments and add/remove contacts from segments - **Do Not Contact**: Handle unsubscribe and bounce management with proper channel tracking - **Webhook Integration**: Receive and process Mautic webhooks for real-time event handling - **Bulk Operations**: List and manage multiple contacts/segments with filtering and pagination - **Token Support**: Full integration with ECA tokens for dynamic data handling ## Prerequisites - Mautic instance with API access enabled - Mautic API module configured with connection settings - Valid Mautic API credentials (username/password or OAuth) - Proper API permissions for the operations you plan to use ## Common Use Cases - **User Synchronization**: Sync Drupal users with Mautic contacts upon registration - **Marketing Automation**: Trigger marketing campaigns based on Drupal events - **Lead Generation**: Handle form submissions and convert them to Mautic leads - **Email Preferences**: Manage email preferences and handle unsubscribes - **Event Tracking**: Track user interactions and send data to Mautic for scoring - **Content Personalization**: Use Mautic contact data to personalize Drupal content ## Setup Instructions 1. **After installing the module** 1. **Configure Mautic Connection**: 1. Go to Configuration > Web services > Mautic API (`/admin/config/services/mautic_api`) 1. Add a new connection with your Mautic instance URL and API credentials 1. To check if the connection is working, edit the newly created connection. You should see the status of the connection displayed at the top. 1. **Create ECA Models**: 1. Use the ECA Modeller to create workflows 1. Add Mautic actions and events to your models ## Installation ``` composer require drupal/mautic_eca drush pm:install mautic_eca ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Mautic ECA** from there. # Mautic: Add Contact to Segment Add a Contact to a Segment in a specified Mautic instance. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Segment ID` : Enter the Mautic Segment ID to add the contact to. `Contact ID` : Enter the Mautic Contact ID to add to the segment. # Mautic: Add Contact to Do Not Contact Add a contact to Do Not Contact in the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Contact ID` : Enter the Mautic contact ID. `Channel` : Channel of DNC. For example 'email', 'sms'. Default is 'email'. `Reason` : Reason for DNC. 1: Unsubscribed, 2: Bounced, 3: Manual. `Channel ID` : ID of the entity which was the reason for unsubscribe (optional). `Comments` : A text describing details of DNC entry (optional). # Mautic: Create Contact Create a new contact in the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `JSON Data` : Enter the JSON data to create the contact in Mautic. This field must contain valid JSON and can contain tokens. ``` ## Example json data ``` ### Basic Contact ``` { "email": "john.doe@example.com", "firstname": "John", "lastname": "Doe" } ``` ### Contact with Tags and Custom Fields ``` { "email": "john.doe@example.com", "firstname": "John", "lastname": "Doe", "tags": ["newsletter", "customer"], "customFields": { "company": "Acme Corp", "phone": "+1234567890" } } ``` # Mautic: Create Segment Create a new segment in the selected Mautic instance. Creates a new segment in Mautic with the provided JSON data. Segments are used to group contacts based on specific criteria. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `JSON Data` : Enter the JSON data to create the segment in Mautic. This field must contain valid JSON and can contain tokens. ``` ## Example json data ``` ### Basic Segment ``` { "name": "Newsletter Subscribers", "description": "Users who have subscribed to our newsletter" } ``` ### Segment with Filters ``` { "name": "High Value Customers", "description": "Customers with high engagement scores", "filters": [ { "glue": "and", "field": "points", "object": "lead", "type": "number", "filter": "gte", "display": null, "operator": "gte", "value": "100" } ] } ``` # Mautic: Delete Contact Delete a contact for the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the mautic ID of the contact to delete. # Mautic: Delete Segment Delete a segment from the selected Mautic instance. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the Mautic ID of the segment to delete. # Mautic: Get Contact Get a contact from the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the mautic ID of the contact to get. # Mautic: Get Segment Get a segment from the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the Mautic ID of the segment to get. # Mautic: List Contact List a contact in the selected Mautic connection. Retrieves a list of contacts from Mautic with optional filtering, sorting, and pagination. This action is useful for bulk operations and data synchronization. ## Search Examples - **By Email**: `email:john@example.com` - **By Tag**: `tags:newsletter` - **By Name**: `firstname:John` - **By Date**: `dateAdded:2024-01-01` - **By Custom Field**: `company:Acme Corp` - **Multiple Criteria**: `tags:newsletter AND firstname:John` ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Search filter` : String or search command to filter entities by. Supports tokens. ``` Search command to filter contacts by supports tokens and various search operators. ``` `Start` : Starting row for the entities returned. `Limit` : Limit number of entities to return. 0 to return all. `Order by` : Column to sort by. Can use any column listed in the response. However, all properties in the response that are written in camelCase need to be changed a bit. Before every capital add an underscore _ and then change the capital letters to non-capital letters. So dateIdentified becomes date_identified, modifiedByUser becomes modified_by_user etc. `Sort direction` : Sort direction: asc or desc. `Published only` : Only return currently published entities. `Minimal` : Return only array of entities without additional lists in it. # Mautic: List Segments List segments in the selected Mautic connection. Retrieves a list of segments from Mautic with optional filtering, sorting, and pagination. This action is useful for bulk operations and data synchronization. ## Search Examples - **By Name**: `name:Newsletter` - **By Description**: `description:subscribers` - **By Date**: `dateAdded:2024-01-01` - **By Published**: `isPublished:true` - **Multiple Criteria**: `name:Newsletter AND isPublished:true` ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Search filter` : String or search command to filter segments by. Supports tokens. ``` Search command to filter segments by name or other criteria. Supports tokens and basic search operators. ``` `Start` : Starting row for the segments returned. `Limit` : Limit number of segments to return. 0 to return all. `Order by` : Column to sort by. Can use any column listed in the response. `Sort direction` : Sort direction: asc or desc. `Published only` : Only return currently published segments. `Minimal` : Return only array of segments without additional lists in it. # Mautic: Remove Contact from Do Not Contact Remove a contact from Do Not Contact in the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Contact ID` : Enter the Mautic contact ID. `Channel` : Channel of DNC. For example 'email', 'sms'. Default is 'email'. # Mautic: Update Contact Update the contact for the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the mautic ID of the contact to update. `JSON Data` : Enter JSON data to update the contact in Mautic. This field must contain valid JSON and can contain tokens. # Mautic: Update Segment Update the segment for the selected Mautic connection. ## Fields `Mautic connection` : Select the Mautic connection to use for this action. `Name of token` : Provide the name of a token where the value should be stored. Please provide the token name only, without brackets. `Mautic ID` : Enter the Mautic ID of the segment to update. `JSON Data` : Enter JSON data to update the segment in Mautic. This field must contain valid JSON and can contain tokens. # Mautic: Webhook Received Event When a Mautic webhook is received. Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[webhook_data]` | Raw webhook data from Mautic. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when a Mautic webhook is received by the Mautic API module. Use this to react to Mautic events such as contact updates, form submissions, or email interactions. The webhook payload is available as a token under the name configured in the Token Name field (defaults to `webhook_data`). ## Fields `Webhook Configuration` : No webhook configurations found. Please create webhook configurations in the Mautic API module first. ``` Select the webhook configuration to use for this event. You can create webhook configurations in the Mautic API module settings. ``` `Token Name` : Enter the name for the token that will contain the webhook data. ``` The token name under which the raw webhook data from Mautic will be available. Defaults to `webhook_data`. ``` # Node ## Installation ``` drush pm:install node ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Node** from there. # Make selected content sticky ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Make selected content not sticky ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Promote selected content to front page ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Demote selected content from front page ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Orchestration ECA ## Installation ``` composer require drupal/orchestration drush pm:install orchestration_eca ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Orchestration ECA** from there. # Add item to poll result by ID Available since: 1.0.0 Adds an item together with its ID to the poll result. ## Fields `The ID of the item` : This field supports tokens. `Data` : This field supports tokens. `Interpret above data as YAML format` : Nested data can be set using YAML format, for example *my_key: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Add item to poll result by timestamp Available since: 1.0.0 Adds an item together with the creation timestamp to the poll result. ## Fields `The timestamp when the data was created` : Leave empty to use the current timestamp.\ This field supports tokens. `Data` : This field supports tokens. `Interpret above data as YAML format` : Nested data can be set using YAML format, for example *my_key: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Dispatch webhook Available since: 1.0.0 Dispatches a webhook and sends extra data along with it. ## Fields `Webhook` : Select a webhook to dispatch. `Data` : This field supports tokens. `Interpret above data as YAML format` : Nested data can be set using YAML format, for example *my_key: "My value"*. When using this format, this option needs to be enabled. When using tokens and YAML altogether, make sure that tokens are wrapped as a string. Example: *title: "[node:title]"* `Validate YAML to prevent this from being executed when invalid` # Poll by ID Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[last_id]` | The last ID received during the last poll. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an external system polls Drupal for data that has been created since a given ID. The polling endpoint receives JSON with a `name` and `id` field. The `[last_id]` token provides the last ID received during the previous poll. Use ECA actions to call `addItem()` on the event to return data items with their IDs. ## Fields `Event ID` : The event ID which needs to be the same that the polling uses to receive the data. ``` The event ID which needs to match the `name` field in the polling request's JSON payload. ``` # Poll by timestamp Available since: 1.0.0 Provided tokens | Token | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `[last_poll]` | The timestamp when the last poll was executed. | | `[event]` | The event. | | `[event:machine_name]` | The machine name of the ECA event. | | `[session_user]` | The user account that dispatched the event, regardless if ECA is processing models under a different account. This is only available if ECA is configured to always run under a specific account. | Fires when an external system polls Drupal for data that has changed since a given timestamp. The polling endpoint receives JSON with a `name` and `timestamp` field. The `[last_poll]` token provides the timestamp of the previous poll. Use ECA actions to call `addItem()` on the event to return data items with their timestamps. ## Fields `Event ID` : The event ID which needs to be the same that the polling uses to receive the data. ``` The event ID which needs to match the `name` field in the polling request's JSON payload. ``` # Pathauto ## Installation ``` composer require drupal/pathauto drush pm:install pathauto ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Pathauto** from there. # Update URL alias of an entity Available since: unknown # Private Content ## Installation ``` composer require drupal/private_content drush pm:install private_content ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Private Content** from there. # Make selected content private Available since: unknown ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. # Make selected content public Available since: unknown ## Fields `Entity` : Provide the token name of the *node* that this action should operate with. Please provide the token name only, without brackets. # Prompt ## Installation ``` composer require drupal/prompt drush pm:install prompt ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Prompt** from there. # Prompt: set field value with IA Available since: unknown Allows to set, unset or change the value(s) of any field in an entity. ## Fields `Field name` : The machine name of the field, that should be changed. Example: *body.value*\ This field supports tokens. `Method` : The method to set an entity, like cleaning the old one, etc..\ When using the "Defined by token" option, make sure there is a token with this name: *prompt_set_field_value_method* `Strip tags` : Remove the tags or not. `Trim` : Trims the field value or not. `Save entity` : Saves the entity or not after setting the value. `Prompt Id` : The Prompt Id to use. This property supports tokens. `Entity` : Provide the token name of the *entity* that this action should operate with. Please provide the token name only, without brackets. # Push Framework ## Installation ``` composer require drupal/push_framework drush pm:install push_framework ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Push Framework** from there. # Allow all push notifications ## Fields `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. # Block all push notifications ## Fields `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. # Push a notification to a channel. ## Fields `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # User ## Installation ``` drush pm:install user ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **User** from there. # Add a role to the selected users ## Fields `Role` `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Block the selected users ## Fields `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Remove a role from the selected users ## Fields `Role` `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Unblock the selected users ## Fields `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` # Views Bulk Operations ## Installation ``` composer require drupal/views_bulk_operations drush pm:install views_bulk_operations ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Views Bulk Operations** from there. # Cancel the selected user accounts Available since: unknown ## Fields `When cancelling these accounts` `Require email confirmation to cancel account` : When enabled, the user must confirm the account cancellation via email. `Notify user when account is canceled` : When enabled, the user will receive an email notification after the account has been canceled. `Entity` : Provide the token name of the *user* that this action should operate with. Please provide the token name only, without brackets. ``` See also: [Tokens being forwarded](https://ecaguide.org/eca/concepts/tokens/#tokens-being-forwarded) ``` `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Delete selected entities / translations Available since: unknown ## Fields `Replace tokens` : When enabled, tokens will be replaced *before* executing the action. **Please note:** Actions might already take care of replacing tokens on their own. Therefore, use this option only with care and when it makes sense. # Webform ## Installation ``` composer require drupal/webform drush pm:install webform ``` Instead of using Drush to enable the module, you can also go to "Administration / Extend" (`/admin/modules`) and enable the module **Webform** from there. # Archive webform Available since: unknown ## Fields `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Close webform Available since: unknown ## Fields `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Open webform Available since: unknown ## Fields `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Lock submission Available since: unknown ## Fields `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Star/Flag submission Available since: unknown ## Fields `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Unlock submission Available since: unknown ## Fields `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Unstar/unflag submission Available since: unknown ## Fields `Entity` : Provide the token name of the *webform_submission* that this action should operate with. Please provide the token name only, without brackets. # Restore webform Available since: unknown ## Fields `Entity` : Provide the token name of the *webform* that this action should operate with. Please provide the token name only, without brackets. # Library # Access to form fields with tokens Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0028 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0028 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0028 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how to access form field values during validation or submission, how to find out the proper token syntax for each form field type, and also an alternative approach by building a temporary entity from form field values to use the more transparent entity token syntax. In this video, see how easy it is to create this model and get precious insights into the inner workings of ECA. [Watch now](https://tube.tchncs.de/w/oFTsbEQ8RHQZKkswkzmaFf). ## Dependencies - config - field.field.node.article.field_flag - field.field.node.article.field_text - field.field.node.location.field_flag - field.field.node.location.field_text - field.storage.node.field_flag - field.storage.node.field_text - node.type.article - node.type.location - module - eca_form - menu_ui - node ## Used plugins ### Events - [Validate form ()](https://ecaguide.org/plugins/eca/form/events/form_form_validate/index.md) ### Actions - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Build entity](https://ecaguide.org/plugins/eca/form/actions/eca_form_build_entity/index.md) - [Message on the entity](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Content validation Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0009 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0009 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0009 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This example model changes the behaviour when editing a content of type "article" in a form: - It groups the title and body field together - It makes sure that the body field is not empty, when trying to publish the article. ## Dependencies - config - field.field.node.article.body - field.field.node.page.body - field.storage.node.body - node.type.article - node.type.page - module - eca_base - eca_content - eca_form - node - text ## Used plugins ### Events - [Process form ()](https://ecaguide.org/plugins/eca/form/events/form_form_process/index.md) - [Validate form ()](https://ecaguide.org/plugins/eca/form/events/form_form_validate/index.md) ### Conditions - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Entity: field value is empty](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value_empty/index.md) ### Actions - [Group title and body into "Authoring"](https://ecaguide.org/plugins/eca/form/actions/eca_form_add_group_element/index.md) - [Build node from submitted values](https://ecaguide.org/plugins/eca/form/actions/eca_form_build_entity/index.md) - [Chain for AND condition](https://ecaguide.org/plugins/eca/base/actions/eca_void_and_condition/index.md) - [Set validation error on body field](https://ecaguide.org/plugins/eca/form/actions/eca_form_field_set_error/index.md) ## Changelog ## v1 Initial version ## v2 Fixing title field # Add role to inserted or updated user Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0029 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0029 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0029 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how to add a role to an inserted or updated user entity. There are actually 3 potential ways of doing this, only 1 of them being recommended. The recorded session (see link below) shows the issues you can run into when choosing one of the other options and it may become transparent, why the third option is the best of the available ones. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/odtnGZjaEAKtzZSVX1gdAS). ## Dependencies - module - eca_base - eca_content - eca_user ## Used plugins ### Events - [Presave content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Role of user](https://ecaguide.org/plugins/eca/user/conditions/eca_user_role/index.md) ### Actions - [Switch to user 1](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Load saved user entity](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Print success message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Add role to field](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Print fail message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) ## Changelog ## v1 Initial version ## v2 Clean-up the model ## v3 Do not save entity as this model acts in pre-save event # Add role to new user Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0035 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0035 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0035 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose A variant of eca_lib_0029: «Add role to inserted or updated user». Except this variant is only concerned with new users, updated users are not processed. ## Dependencies - config - node.type.article - node.type.page - taxonomy.vocabulary.tags - user.role.content_editor - module - comment - contextual - eca_base - eca_content - eca_user - file - modeler_api - node - path - system - taxonomy - toolbar ## Used plugins ### Events - [Presave content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Entity: not new](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_is_new/index.md) - [Entity: is new](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_is_new/index.md) - [Not has role?](https://ecaguide.org/plugins/eca/user/conditions/eca_user_role/index.md) - [Has role?](https://ecaguide.org/plugins/eca/user/conditions/eca_user_role/index.md) ### Actions - [User: switch current account](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Entity: set field value](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [ECA: User already has role, exit msg.](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Display a message to the user](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [ECA: Not a new user, exit msg.](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Token: set value](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) ## Changelog ## v1 Initial version # Asynchronous views export Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0016 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0016 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0016 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model provides an endpoint `/eca/export/users` which can be published as a menu item or a link. When requested, it does this: - Check access and only allow users with the administror role to cal that endpoint - Enqueue a task called `export-users` and forward the email address of the current user - Display a message to the user and redirect them back to the page where they came from After that, the task is being queued and will be executed by the next cron of the Drupal site. This will then execute the view and export the result into a csv file. Finally, an email will be sent to the user who originally requested the export together with the link from where they can download the export. Building this model has been recorded: [watch video](https://tube.tchncs.de/w/qpc4qAu2jPMPqcnzV8125h) ## Dependencies - config - views.view.user_admin_people - module - eca_access - eca_base - eca_endpoint - eca_queue - eca_user - eca_views - user ## Used plugins ### Events - [ECA Endpoint response (export)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md) - [ECA Endpoint access (export)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_access/index.md) - [ECA processing queued task ()](https://ecaguide.org/plugins/eca/queue/events/eca_queue_processing_task/index.md) ### Conditions - [Role of current user](https://ecaguide.org/plugins/eca/user/conditions/eca_current_user_role/index.md) ### Actions - [Get user's email address](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Enqueue the export task](https://ecaguide.org/plugins/eca/queue/actions/eca_enqueue_task/index.md) - [Print message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Get the referrer URL](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_get_request_header/index.md) - [Redirect the user](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) - [Allow access](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) - [Run export](https://ecaguide.org/plugins/eca/views/actions/eca_views_export/index.md) - [Send email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Switch user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) # Auto create entity with values from another one and the current user Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0020 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0020 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0020 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model reacts upon creating a new page node. It then creates a new article node, its title is populated with the page auther's name, some static text and the title of the created page. The [recorded video](https://tube.tchncs.de/w/2nSZ9TDmtZ5YYrnyFfaNUC) provides more explanation as we go on. ## Dependencies - config - node.type.article - node.type.page - module - eca_content ## Used plugins ### Events - [Insert content entity (Content: Basic page)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) ### Actions - [Create a new article](https://ecaguide.org/plugins/eca/content/actions/eca_new_entity/index.md) - [Save](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Calculated entity field Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0022 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0022 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0022 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model calculates a field value and stores it with a node, each time that node gets either created or updated. This shows in a simple example, how the contrib module "Calculated Field" can be replaced with ECA models. The creation of this module was recorded with lots of additional explanations and can be [watched here](https://tube.tchncs.de/w/3gDpeV9TynLeoxk4XQfZ7c). ## Dependencies - config - field.field.node.carpet.field_area - field.field.node.carpet.field_length - field.field.node.carpet.field_width - field.storage.node.field_area - field.storage.node.field_length - field.storage.node.field_width - node.type.carpet - module - eca_content - eca_tamper - menu_ui - node ## Used plugins ### Events - [Presave content entity (Content: Carpet)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Actions - [Calculate area](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_math/index.md) - [Store area value](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Combined Conditions Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0002 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0002 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0002 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This means: - event 1: action "do something" is executed if condition 1 and condition 2 are both TRUE - event 2: do something is executed when condition 3 or condition 4 is TRUE - event 3: do something is executed when condition 5 or 6 AND condition 7 or 8 are TRUE With that pattern, you can achieve all possible combinations of AND and OR conditions ## Dependencies - module - eca_base # Count user logins Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0012 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0012 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0012 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model adds a number field to the user entity with a default value 0. It then increments that value, each time that user logs into the site. ## Dependencies - config - field.field.user.user.field_number_of_logins - field.storage.user.field_number_of_logins - module - eca_content - eca_tamper - eca_user - user ## Used plugins ### Events - [Login of a user](https://ecaguide.org/plugins/eca/user/events/user_login/index.md) ### Actions - [Read value from user](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) - [Increment value](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_math/index.md) - [Write value back to the user entity](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Create user entity from JSON Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0030 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0030 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0030 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how to create a content entity with data from a JSON string. It also shows why creating a user entity "the classic way" doesn't work, more about the reasons for that are explained in the video. The creation of this module was recorded and the video with additional explanations can be [watch here](https://tube.tchncs.de/w/3z2AD4Lbmoo1QVmBqzmemc). ## Dependencies - module - eca_base - eca_content - eca_render - eca_user - serialization ## Used plugins ### Events - [ECA custom event (U1)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) - [ECA custom event (U2)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Create user entity specific](https://ecaguide.org/plugins/eca/user/actions/eca_new_user/index.md) - [Save the user](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) - [Success message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Switch to user 1](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Unserialize json for user](https://ecaguide.org/plugins/eca/render/actions/eca_render_unserialize_serialization/index.md) - [Save user](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) - [Success Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Detect user role changes Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0010 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0010 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0010 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose When a user entity gets saved, this model compares the list of original and current roles of that user and finds out, which ones got added and which ones got removed. This involves 2 loops where we first go through the list of current roles to see if one of them is missing from the list of original roles. Then we gro through the list of original roles to see if ones of them is missing in the list of current roles. For each missing role, this model shows a message on screen. ## Dependencies - module - eca_base - eca_content - user ## Used plugins ### Events - [Presave content entity (User: User)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Compare number of list items](https://ecaguide.org/plugins/eca/base/conditions/eca_count/index.md) - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Load the original user entity](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Get next role](https://ecaguide.org/plugins/eca/base/actions/eca_list_remove/index.md) - [Message that the role is new](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Join original IDs](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Join current IDs](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Message that role has been removed](https://ecaguide.org/plugins/eca/base/actions/eca_warning_message/index.md) - [Get the list of original roles](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) - [Get the list of current roles](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) ## Changelog ## v1 Initial version ## v2 Replace "Token: set value" actions by "Entity: get field value" actions # Display message to specific user roles only Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0015 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0015 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0015 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model prints a message on screen, when the user opens the user profile form for editing. The message output is limited to users that have one of the roles editor, customer or auditor. ## Dependencies - module - eca_form - eca_user ## Used plugins ### Events - [Build form ()](https://ecaguide.org/plugins/eca/form/events/form_form_build/index.md) ### Conditions - [Role of current user](https://ecaguide.org/plugins/eca/user/conditions/eca_current_user_role/index.md) ### Actions - [Display message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # ECA and http services Version v1 React Flow BPMN iO Initialising viewer… Instead of downloading the archive, you can download and apply this model as a recipe (Drupal 10.3 or later): ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0032 # Enable recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0032 # Enable recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0032 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model has 2 parts: 1. It demonstrates how to use API endpoints provided by the [http_client_manager](https://www.drupal.org/project/http_client_manager) module and accessing the data they receive from remote services. 1. It then also demonstrates how to use ECA endpoints to controll the access to that endpoint and building up a response to it. In a follow up model, we will then show how the ECA endpoint can be made available to the HTTP Client Manager, so that one Drupal sites could be offering an API endpoint controlled by ECA, and another Drupal site then requested data from that API. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/eTrzr42LFCmpGv682rqrgz). ## Dependencies - module - eca_access - eca_base - eca_endpoint - http_client_manager ## Used plugins ### Events - [ECA custom event (http01)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) - [ECA Endpoint access (tv)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_access/index.md) - [ECA Endpoint response (tv)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md) ### Actions - [Store result in a token](https://ecaguide.org/plugins/eca/base/actions/eca_privatetempstore_read/index.md) - [Print result](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [allow access](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) - [Define response content](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_content/index.md) - [Set response code](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_status_code/index.md) - [Set json content type](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_content_type/index.md) ## Changelog `v1` : Initial release. # ECA and http services - part 2 Version v1 React Flow BPMN iO Initialising viewer… Instead of downloading the archive, you can download and apply this model as a recipe (Drupal 10.3 or later): ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0033 # Enable recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0033 # Enable recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0033 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model is a follow up version of [ECA and http services](https://ecaguide.org/library/simple/eca_and_http_services/index.md) and uses a self-defined services API for the HTTP Client Manager. This module requires the services API defined in a [Custom Module](https://ecaguide.org/library/simple/eca_and_http_services_-_part_2/eca_tv_demo.zip). Please download, copy to your Drupal site and enable it before importing this model. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/vUXqDxeKtqppRUB2MDWiJq). ## Dependencies - module - eca_access - eca_base - eca_endpoint - http_client_manager ## Used plugins ### Events - [ECA Endpoint access (tv)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_access/index.md) - [ECA Endpoint response (tv)](https://ecaguide.org/plugins/eca/endpoint/events/eca_endpoint_response/index.md) - [ECA custom event (http01)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [allow access](https://ecaguide.org/plugins/eca/access/actions/eca_access_set_result/index.md) - [Set content](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_content/index.md) - [Set response code](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_status_code/index.md) - [Set json content type](https://ecaguide.org/plugins/eca/endpoint/actions/eca_endpoint_set_response_content_type/index.md) - [Read received data into a token](https://ecaguide.org/plugins/eca/base/actions/eca_privatetempstore_read/index.md) - [Print message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) ## Changelog `v1` : Initial version # ECA and Views Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0034 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0034 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0034 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model shows the difference between the [Views: Execute Query](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) action and the [Render: Views](https://ecaguide.org/plugins/eca/render/actions/eca_render_views_views/index.md) action. The first one always returns a list of entities (more about in the video, see link below) and the second one returns the rendered result. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/jnzoru2XFHgpoToQB5P6AT). ## Dependencies - config - views.view.eca_content_count - module - eca_base - eca_content - eca_render - eca_tamper - eca_user - eca_views - node - user ## Used plugins ### Events - [ECA custom event (views)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) - [ECA custom event (entity-aware) (Print View Result)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) ### Actions - [Switch to user 1](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Query ECA Content Count](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Trigger Print View Result](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Render ECA Content Count](https://ecaguide.org/plugins/eca/render/actions/eca_render_views_views/index.md) - [Trim the result](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_trim/index.md) - [Strip tags](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_strip_tags/index.md) # ECA working with VBO Version v1 React Flow BPMN iO Initialising viewer… Instead of downloading the archive, you can download and apply this model as a recipe (Drupal 10.3 or later): ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0019 # Enable recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0019 # Enable recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0019 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model shows how you get Drupal views working with VBO and ECA together. The creation of this model was [recorded in a video](https://tube.tchncs.de/w/vNRrQDcmEA2QbW771acZZi) and explains a lot more detail there. ## Dependencies - module - eca_vbo - views_bulk_operations ## Used plugins ### Events - [VBO: Execute Views bulk operation (one by one) (Print title of nodes)](https://ecaguide.org/plugins/eca/vbo/events/vbo_execute/index.md) - [VBO: Custom access for Views bulk operation (Print title of nodes)](https://ecaguide.org/plugins/eca/vbo/events/vbo_custom_access/index.md) ### Actions - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [yes](https://ecaguide.org/plugins/eca/vbo/actions/eca_vbo_set_custom_access/index.md) ## Changelog `v1` : Initial version # Find values in lists Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0013 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0013 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0013 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model defines a serialized list with all of the list items being separated by a pipe character from each other. It then defines 5 different values and verfies if they are contained in the list, displaying either a success or failure message. The comparison requires the pipe character also surounding the values in order to not get false positives, e.g. the value "x" us not an item in the list, whereas "xyz" is. ## Dependencies - module - eca_base - eca_tamper ## Used plugins ### Events - [ECA custom event (compare)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Conditions - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Set value abc](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set value xyz](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Success message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Print value](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Set value def](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Failure message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Define the list](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set value x](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set value to mno](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Increment counter](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_math/index.md) - [Initialize counter](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) # Get next incremental ID Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0011 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0011 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0011 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model increments a sidewide ID by 1 and returns that on screen. It uses Drupal's state service to store the value inbetween requests. ## Dependencies - module - eca_base - eca_tamper ## Used plugins ### Events - [ECA custom event (increment)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Read value from state](https://ecaguide.org/plugins/eca/base/actions/eca_state_read/index.md) - [Increment by 1](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_math/index.md) - [Write value back to state](https://ecaguide.org/plugins/eca/base/actions/eca_state_write/index.md) - [Print message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Acquire lock](https://ecaguide.org/plugins/eca/base/actions/eca_lock_acquire/index.md) ## Changelog ## v1 Initial version ## v2 Add an "Acquire lock" action to make sure it still works with concurrent users. # Grant new user role after 3 conditions are met Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0026 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0026 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0026 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model automatically adds or removes a role from a user, when this gets updated, depending upon 3 conditions that are stored with the user entity. Only if all 3 conditions are met, the role gets added. In all other cases the role gets removed. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/jTSnTrBF2YkUJHEtEoZVrW). ## Dependencies - config - user.role.moderator - module - eca_base - eca_content - user ## Used plugins ### Events - [Update content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Conditions - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Add role](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md) - [Remove role](https://ecaguide.org/plugins/user/actions/user_remove_role_action/index.md) ## Changelog ## v1 Initial release ## v2 Replace role content_moderator with new role moderator to avoid extra dependencies that are derived from permissions # Keep 2 fields in sync Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0018 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0018 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0018 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how a text field in a user entity can be kept in sync with a similar field in an associated profile entity. This works in both directions. Regardless which of the entities gets updated, the other one will be updated automatically as well. Without paying attention, this could lead into an infinite loop. Therefore, the related entity only gets updated if the field values are not the same already. The creation of that model has been recorded: [Watch the video](https://tube.tchncs.de/w/99udnEHSUb5V7Dj66zes59) ## Dependencies - config - field.field.profile.contact_detail.field_real_name - field.field.user.user.field_real_name - field.storage.profile.field_real_name - field.storage.user.field_real_name - profile.type.contact_detail - module - eca_base - eca_content - profile - user ## Used plugins ### Events - [Update content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) - [Update content entity (Profile: Contact detail)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Conditions - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Load profile entity](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Set real name in profile](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Load user entity](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set real name in user](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Notifications Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0021 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0021 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0021 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model responds to a number of events (user login, registration, error messages, new comments, etc.) and send notifications to a number of different channels like email, Mattermost and Alerta. The creation of this model has been commented and [recorded on video](https://tube.tchncs.de/w/pS9U9PiczAUNjr4xRajVBa). ## Dependencies - module - eca_base - eca_content - eca_crowdsec - eca_log - eca_user - push_framework ## Used plugins ### Events - [Login of a user](https://ecaguide.org/plugins/eca/user/events/user_login/index.md) - [Insert content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) - [Log message created ()](https://ecaguide.org/plugins/eca/log/events/log_log_message/index.md) - [IP signalled](https://ecaguide.org/plugins/eca/crowdsec/events/crowdsec_signalled/index.md) - [Insert content entity (Comment: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) ### Actions - [Notify email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Notify Alerta](https://ecaguide.org/plugins/push_framework/actions/push_framework_notify/index.md) - [Notify Mattermost](https://ecaguide.org/plugins/push_framework/actions/push_framework_notify/index.md) - [Set subject](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set body](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) # Processing sequence Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0014 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0014 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0014 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model comes with 2 processes, that look similar but do behave differently. They get executed by calling `drush eca:trigger:custom_event procorder` on the console of the Drupal site. What the 2 processes do is to set a token value, then overwrite that token with a different value and finally print the value out on screen as a message. However, that's what we expect but not what we get. For the first process (the left one), that's what we get. But the second one seems to have a mistake: it doesn't print 12, instead we get the value 5. This is because the processing order of succeeding actions is not necessarily what we see on screen - where both processes look the same. Instead, the order depends on the order in which the successors got added to the predecessor. The problem being present is, that BPMN, while it relies on that order, doesn't have any form of indicator that would help us to see that in the visual model. We have recorded a video which discusses that topic alongside this model and demonstrates how to find out about the order os successors. It then also shows how to fix the order in case it got messed up. You can find that by [following this link](https://tube.tchncs.de/w/a92s9649VVKuMdoXZHbLDq?start=12m45s). ## Dependencies - module - eca_base ## Used plugins ### Events - [ECA custom event (procorder)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Set token to 1](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Overwrite token value to 2](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Print message with value](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Set token to 5](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Overwrite token value to 12](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) # Route test Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0001 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0001 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0001 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose If a node page gets requested and the node is of type "article", a message will be printed. This is using the event [Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/?h=controller+found+handle+request) as this is working even if pages are cached. ## Dependencies - module - eca_content - eca_misc ## Used plugins ### Events - [Controller found to handle request](https://ecaguide.org/plugins/eca/misc/events/kernel_controller/index.md) ### Conditions - [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) - [Entity type and bundle](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_type_bundle/index.md) ### Actions - [Add node from route to token](https://ecaguide.org/plugins/eca/misc/actions/eca_token_load_route_param/index.md) - [Print node title as message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) ## Changelog ## v1 Initial version ## v2 Updated to latest plugin versions, fixed some typos, change the event from "Start dispatching request" to "Controller found to handle request" # Scheduled publishing Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0023 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0023 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0023 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how to automatically publish and unpublish nodes by scheduled dates and times. The creation of this module was recorded and the video with additional explanations [can be watch here](https://tube.tchncs.de/w/5cs5Du3579Nwau1m9Rv92G). ## Dependencies - config - views.view.due_nodes_for_publishing - module - eca_base - eca_content - eca_user - eca_views - node - user ## Used plugins ### Events - [ECA cron event ( *\* * \** )](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_cron/index.md) - [ECA custom event (entity-aware) (publish)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) - [ECA custom event (entity-aware) (unpublish)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) - [ECA custom event (auto-publish)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Switch user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [View: get due nodes for publishing](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Trigger publish event](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Publish node](https://ecaguide.org/plugins/core/actions/entity_publish_action_node/index.md) - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [View: get due nodes for unpublishing](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Trigger unpublish event](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Unpublish node](https://ecaguide.org/plugins/core/actions/entity_unpublish_action_node/index.md) # Send email on user registration with field values Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0025 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0025 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0025 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model sends an email to a user that has just registered on the site. That email contains field values, that the user just provided in the registration form, where one of the fields is mandatory and the other one is optional. The email message is different, depending upon the optional field being filled or not. The creation of this model was recorded and [can be watched here](https://tube.tchncs.de/w/7oZPDv2fWfg3fpHENjCqpK). ## Dependencies - config - field.field.user.user.field_country - field.field.user.user.field_home_town - field.storage.user.field_country - field.storage.user.field_home_town - module - eca_base - eca_content - user ## Used plugins ### Events - [Insert content entity (User: User)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) ### Conditions - [Entity: field value is empty](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value_empty/index.md) ### Actions - [Send email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Build message](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Append country](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) # Send email to users of a given role Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0024 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0024 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0024 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model sends an email to all users of a certain role. It contains a view with a contextual filter to limit the list of users to those of the given role. The creation of this model was recorded with lots of additional explanations (e.g. how to use an existing model as a starting point) and [can be watched here](https://tube.tchncs.de/w/8dZuXYZHmuDTutddrTZUfE). ## Dependencies - config - views.view.user_admin_people - module - eca_base - eca_content - eca_user - eca_views - user ## Used plugins ### Events - [ECA custom event (email)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) - [ECA custom event (entity-aware) (x1)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) ### Actions - [List users](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Switch user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Trigger X1](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) # Send notification including revision log message for node changes Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0017 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0017 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0017 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model sends an email when any node got updated. That email contains a couple of tokens, e.g. the name of the user who edited the node and the link to the node. It also contains the the revision log message that the user has left in the edit form. As the author may skip the revision log, this model also makes that field required. The creation of that model has been recorded and there have actually some unexpected difficulties, that you can watch live, how they got resolved: [Watch the video](https://tube.tchncs.de/w/dzL382ZCTE2RzLSbMQHJk5) In version 2 of this model, we've added content moderation functionality and a section field for a wiki page content type, such that email notifications get sent to different recipients depending on state and section of the updated node. The creation of this model's enhancement has also been recorded: [Watch the second video](https://tube.tchncs.de/w/s3yX3pWuZhMA5WPYQNpnyp) ## Dependencies - config - node.type.wiki - module - eca_base - eca_content - eca_form - menu_ui ## Used plugins ### Events - [Update content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) - [Build form ()](https://ecaguide.org/plugins/eca/form/events/form_form_build/index.md) - [Update content entity (Content: Wiki)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Conditions - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) ### Actions - [Send email to admin](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Make revision log required](https://ecaguide.org/plugins/eca/form/actions/eca_form_field_require/index.md) - [Set role to reviewers](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Send email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Set role to publisher](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set role to admin](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set email to original author](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set email to products](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set email to departments](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Set email to markets](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) ## Changelog ## v1 Initial version ## v2 Adding moderation states and sections # Simplenews auto sub unsub Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0036 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0036 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0036 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Automatically subscribes or unsubscribers users from a designated Simplenews newsletter based on the user's role. Triggered by user entity presave. Requires the eca_simplenews contributed module. ## Dependencies - module - eca_base - eca_content - eca_simplenews - modeler_api ## Used plugins ### Events - [Presave content entity (User: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Was administrator role](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [Was not administrator role](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [NOT has administrator role](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [Has administrator role](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [User is currently subscribed to default newsletter](/plugins/eca/simplenews/conditions/eca_simplenews_is_subscribed_condition.md) - [User is NOT currently subscribed to default newsletter](/plugins/eca/simplenews/conditions/eca_simplenews_is_subscribed_condition.md) - [User has NOT previously unsubscribed from any newsletter](/plugins/eca/simplenews/conditions/eca_simplenews_check_for_self_unsubscribes.md) - [User has previously unsubscribed from any newsletter](/plugins/eca/simplenews/conditions/eca_simplenews_check_for_self_unsubscribes.md) ### Actions - [AND](https://ecaguide.org/plugins/eca/base/actions/eca_void_and_condition/index.md) - [Unsubscribe from default newsletter](/plugins/eca/simplenews/actions/eca_simplenews_unsubscribe_from_newsletter.md) - [Subscribe to default newsletter](/plugins/eca/simplenews/actions/eca_simplenews_subscribe_to_newsletter.md) - [Notify of previous unsubscribe](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) ## Changelog Initial version # Switch Case Default Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0004 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0004 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0004 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Demonstrate how typical switch-case PHP constructors could be simulated in ECA models - similar to if-elsif-else statements. The model is similar to what you would normally do in PHP like this: ``` switch ($field_select) { case 'a1': case 'a2': case 'a3': case 'c7': // Set Status to 3 $field_status = 3; case 'b1': case 'b2': // Set Status to 4 $field_status = 4; default: // Set default Status $field_status = 2; } ``` Important note: after the action "Set default Status to 2", ECA first checks the conditions of ALL successors; only then does it execute the actions that follow for those conditions that return TRUE. That's why the "no condition" link has no condition, as we want to execute that path in any case, but not before the top two paths had a chance to change the status. Therefore the condition, if the status is still 2, happens with a delay, i.e. really after everything else has been completed. ## Dependencies - config - node.type.article - module - eca_base - eca_content ## Used plugins ### Events - [Presave content entity (Content: Article)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Set Status to 3](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set Status to 4](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set default Status to 2](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Message containing status value](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) ## Changelog ## v1 Initial version ## v2 Add the "no condition" for the default value # Update user entity when they save an article node Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0027 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0027 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0027 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model appends a comment to the author of a node when they create a new one or update an existing one. The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/7jPP8ZXuhahq5K87L2cSrn). ## Dependencies - config - field.field.user.user.field_author_comments - field.storage.user.field_author_comments - module - eca_content - user ## Used plugins ### Events - [Insert content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) - [Update content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Actions - [Load authors user entity](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Set author comment in the user entity](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Working with dates and time Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0031 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0031 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0031 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model works with a date and time value from a node field and does various things to it: outputting in different formats, adding some time range, changing timezone, etc. Especially the timezone feature requires a [patch to the tamper module](https://www.drupal.org/project/tamper/issues/3268276#comment-15000895). The creation of this module was recorded and the video with additional explanations can be [watched here](https://tube.tchncs.de/w/h8YzBS8cSVdNux1FUcYkhm). ## Dependencies - config - field.field.node.article.field_date_1 - field.storage.node.field_date_1 - node.type.article - module - datetime - eca_content - eca_misc - eca_tamper - node ## Used plugins ### Events - [Controller arguments have been resolved](https://ecaguide.org/plugins/eca/misc/events/kernel_controller_arguments/index.md) ### Conditions - [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) ### Actions - [Get date value from field date 1](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) - [Output plain value](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Load node from route](https://ecaguide.org/plugins/eca/misc/actions/eca_token_load_route_param/index.md) - [Convert date into timestamp](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_strtotime/index.md) - [Output timestamp](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Format timestamp into day, month, time](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_timetodate/index.md) - [Output day/month/time](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Add 1 week](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_math/index.md) - [Output 1 week later](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Format timestamp into date](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_timetodate/index.md) - [Format in PST timezone](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_timetodate/index.md) - [Output PST date](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Calculate PST time](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_timeoffset/index.md) # Basic entity tests Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0004 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0004 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0004 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model contains somebasic conditions and actions on nodes. ## Dependencies - module - eca_content - eca_user - node ## Used plugins ### Events - [Update content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) - [Presave content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Entity type and bundle](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_type_bundle/index.md) ### Actions - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Make stícky](https://ecaguide.org/plugins/node/actions/node_make_sticky_action/index.md) - [Promote to front page](https://ecaguide.org/plugins/node/actions/node_promote_action/index.md) - [Set title](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Load user](https://ecaguide.org/plugins/eca/user/actions/eca_token_load_user_current/index.md) # Cross references Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0001 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0001 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0001 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Two different node types are referring each other. If one node gets saved with a reference to another node, the other node gets automatically updated to link back to the first node. ## Dependencies - config - field.field.node.type_1.field_other_node - field.field.node.type_2.field_other_node - field.storage.node.field_other_node - node.type.type_1 - node.type.type_2 - module - eca_base - eca_content - node ## Used plugins ### Events - [Insert content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) - [Update content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Conditions - [Entity type and bundle](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_type_bundle/index.md) - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Entity: field value is empty](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value_empty/index.md) ### Actions - [Load original entity](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Load referenced node](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity_ref/index.md) - [Set Cross Ref](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [void](https://ecaguide.org/plugins/eca/base/actions/eca_void_and_condition/index.md) - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Empty Cross Ref](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Entity Events Part 1 Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0002 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0002 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0002 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Triggers custom events in the same model and in another model, see also "Entity Events Part 2" ## Dependencies - module - eca_base - eca_content - eca_user ## Used plugins ### Events - [Presave content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) - [ECA custom event (entity-aware) (C1)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) - [Set current user](https://ecaguide.org/plugins/eca/user/events/user_set_user/index.md) - [ECA custom event ()](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Trigger C1](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Trigger C2](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Load current user](https://ecaguide.org/plugins/eca/user/actions/eca_token_load_user_current/index.md) - [Trigger C3](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Trigger Cplain](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) # Entity Events Part 2 Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0003 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0003 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0003 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Implements 2 custom events that get triggered by another model, see also "Entity Events Part 1" ## Dependencies - module - eca_content ## Used plugins ### Events - [ECA custom event (entity-aware) (C2)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) - [ECA custom event (entity-aware) (C3)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) ### Actions - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Forward tokens to custom event Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0010 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0010 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0010 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Demonstrates how okens can be forwarded to triggered custom events. ## Dependencies - module - eca_base - eca_content - eca_user ## Used plugins ### Events - [Presave content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) - [ECA custom event (CE1)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) - [ECA custom event (CE2)](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_custom/index.md) ### Actions - [Add current user to token](https://ecaguide.org/plugins/eca/user/actions/eca_token_load_user_current/index.md) - [Trigger custom event without tokens](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) - [Trigger custom event with tokens](https://ecaguide.org/plugins/eca/base/actions/eca_trigger_custom_event/index.md) - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Redirects for deleted entities Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0007 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0007 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0007 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose When a node gets deleted, this model creates an automatic redirect config entity to redirect visitors who want to go to the deleted node to the contact form instead. ## Dependencies - module - eca_content - redirect ## Used plugins ### Events - [Delete content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_delete/index.md) ### Actions - [Create redirect](https://ecaguide.org/plugins/eca/content/actions/eca_new_entity/index.md) - [Set source path](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set destination](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set title](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set status](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Save new entity Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0008 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0008 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0008 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Create new tag with the same label as the triggering node. ## Dependencies - module - eca_content ## Used plugins ### Events - [Insert content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) ### Actions - [Load node](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Create new tag](https://ecaguide.org/plugins/eca/content/actions/eca_new_entity/index.md) - [Save tag](https://ecaguide.org/plugins/eca/content/actions/eca_save_entity/index.md) # Set field values Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0009 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0009 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0009 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Set single and multi value fields with values, testing different variations. ## Dependencies - config - field.field.node.type_set_field_value.field_text_line - field.field.node.type_set_field_value.field_text_lines - field.storage.node.field_text_line - field.storage.node.field_text_lines - node.type.type_set_field_value - module - eca_content - node ## Used plugins ### Events - [Presave content entity (Content: Type Set Field Value)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Conditions - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Entity: is new](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_is_new/index.md) ### Actions - [Set text line](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Set lines 1](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Overwrite text line](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Append line](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Append another line](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Reset lines](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) - [Prepend line](https://ecaguide.org/plugins/eca/content/actions/eca_set_field_value/index.md) # Views Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0005 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0005 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0005 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose During cron, this model switches the user context, queries a view to receive all user accounts and loops over all those users triggering a custom event for each of them to print their names in messages. ## Dependencies - config - views.view.user_admin_people - module - eca_base - eca_content - eca_user - eca_views - user ## Used plugins ### Events - [ECA cron event ( *\* * \** )](https://ecaguide.org/plugins/eca/base/events/eca_base_eca_cron/index.md) - [ECA custom event (entity-aware) (x1)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) ### Actions - [List users](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Switch user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Trigger X1](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Msg](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) # Write Log Message Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_test_0006 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_test_0006 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_test_0006 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Write log messages. ## Dependencies - module - eca_content - eca_log ## Used plugins ### Events - [Presave content entity (Content: - any -)](https://ecaguide.org/plugins/eca/content/events/content_entity_presave/index.md) ### Actions - [Log](https://ecaguide.org/plugins/eca/log/actions/eca_write_log_message/index.md) # ECA Feature Demo Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0007 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0007 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0007 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates a number of smart features around user accounts: 1. When a user registers themselves or gets created by an existing user, then all existing users with the admin role get informed by email. If the current user has the admin role, a message also get displayed with a link to the mailhog application to review the emails. 1. When a user logs in, a number of actions applies: depending on their role, different redirect destinations will be used after login. Also, the assigment of the internal user role gets executed, see below. 1. When a user gets updated, the assigment of the internal user role also gets executed. The assignment of the internal user role assigns that role to the current user if their email domain contains @example.com and removes it otherwise. It does that only if the situation had changed and also displays an according message on screen. ## Dependencies - config - user.role.internal - views.view.user_admin_people - module - eca_base - eca_content - eca_user - eca_views - user ## Used plugins ### Events - [Login of a user](https://ecaguide.org/plugins/eca/user/events/user_login/index.md) - [Insert content entity (User: User)](https://ecaguide.org/plugins/eca/content/events/content_entity_insert/index.md) - [Update content entity (User: User)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) ### Conditions - [Role of current user](https://ecaguide.org/plugins/eca/user/conditions/eca_current_user_role/index.md) - [Compare number of list items](https://ecaguide.org/plugins/eca/base/conditions/eca_count/index.md) - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [Role of user](https://ecaguide.org/plugins/eca/user/conditions/eca_user_role/index.md) ### Actions - [Redirect to content overview](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) - [Redirect to admin overview](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) - [Redirect to user profile](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) - [Inform admins by email](https://ecaguide.org/plugins/core/actions/action_send_email_action/index.md) - [Load all admin users](https://ecaguide.org/plugins/eca/views/actions/eca_views_query/index.md) - [Pop an admin from the list](https://ecaguide.org/plugins/eca/base/actions/eca_list_remove/index.md) - [Save new user as token](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Switch user](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) - [Display link to Mailhog](https://ecaguide.org/plugins/eca/base/actions/eca_warning_message/index.md) - [Add internal role](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md) - [Remove internal role](https://ecaguide.org/plugins/user/actions/user_remove_role_action/index.md) - [Message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Warning](https://ecaguide.org/plugins/eca/base/actions/eca_warning_message/index.md) - [Save user as token](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) ## Changelog ## v1 Initial version ## v2 Do not redirect after a password reset login. # HTMX Blocks Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0037 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0037 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0037 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Provides 2 blocks, one of which contains a digital clock that refreshes once a second. The other one waits for a click and then dynamically loads the content of node 1. ## Dependencies - module - eca_access - eca_endpoint - eca_htmx - eca_render ## Changelog ## v1 Initial version # Multi value field loop Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0006 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0006 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0006 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This model demonstrates how to loop over all values of a multi value field without using custom events. ## Dependencies - config - field.field.user.user.field_user_networks - field.storage.user.field_user_networks - taxonomy.vocabulary.networks - module - eca_base - eca_content - eca_user - taxonomy - user ## Used plugins ### Events - [Login of a user](https://ecaguide.org/plugins/eca/user/events/user_login/index.md) ### Conditions - [Compare number of list items](https://ecaguide.org/plugins/eca/base/conditions/eca_count/index.md) ### Actions - [Put list of user networks into a token](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) - [Pop an item from the list](https://ecaguide.org/plugins/eca/base/actions/eca_list_remove/index.md) - [Print message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Load term](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) ## Changelog ## v1 Initial version ## v2 Fix token syntax for loading a term entity, see https://www.drupal.org/project/eca/issues/3506997 # Redirect 403 to Login Page Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0008 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0008 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0008 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose This module redirects page requests, that would normaly respond with a "403 Access denied" page, to the login form. Very much like the module "Redirect 403 To Login Page" which can be replaced with this model. Note: this model requires ECA 1.2, or you need to apply the patch from https://www.drupal.org/project/eca/issues/3332859 if you want to use it on ECA 1.1 ## Dependencies - module - eca_base - eca_misc - eca_user ## Used plugins ### Events - [Response created](https://ecaguide.org/plugins/eca/misc/events/kernel_response/index.md) ### Conditions - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) - [Role of current user](https://ecaguide.org/plugins/eca/user/conditions/eca_current_user_role/index.md) ### Actions - [AND](https://ecaguide.org/plugins/eca/base/actions/eca_void_and_condition/index.md) - [Redirect](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) # Redirect unpublished Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0003 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0003 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0003 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose If a user requests an unpublished article node, but doesn't have the permission to view unpublished nodes, then the request gets redirected to the contact form. ## Dependencies - module - eca_content - eca_misc - eca_user ## Used plugins ### Events - [Start dispatching request](https://ecaguide.org/plugins/eca/misc/events/kernel_request/index.md) ### Conditions - [Route match](https://ecaguide.org/plugins/eca/misc/conditions/eca_route_match/index.md) - [Entity type and bundle](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_type_bundle/index.md) - [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Current user has permission](https://ecaguide.org/plugins/eca/user/conditions/eca_current_user_permission/index.md) ### Actions - [Add node from route to token](https://ecaguide.org/plugins/eca/misc/actions/eca_token_load_route_param/index.md) - [Print node title as message](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Redirect](https://ecaguide.org/plugins/core/actions/action_goto_action/index.md) - [Switch User](https://ecaguide.org/plugins/eca/user/actions/eca_switch_account/index.md) # User network changes Version React Flow BPMN iO Initialising viewer… You can apply this model as a recipe (Drupal 10.3 or later) to your own Drupal site: ``` ## Import recipe composer require drupal-eca-recipe/eca_lib_0005 # Apply recipe with Drush (requires version 13 or later): drush recipe ../recipes/eca_lib_0005 # Apply recipe without Drush: cd web && php core/scripts/drupal recipe ../recipes/eca_lib_0005 # Rebuilding caches is optional, sometimes required: drush cr ``` ## Purpose Users have references to a number of networks and when one gets added or deleted, this model recognizes the exact change and displays different messages about it. For further reading, please [go to this tutorial](https://ecaguide.org/resources/tutorials/btown-1/index.md). ## Dependencies - config - field.field.user.user.field_user_networks - field.storage.user.field_user_networks - taxonomy.vocabulary.networks - module - eca_base - eca_content - eca_tamper - taxonomy - user ## Used plugins ### Events - [Update content entity (User: User)](https://ecaguide.org/plugins/eca/content/events/content_entity_update/index.md) - [ECA custom event (entity-aware) (additions)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) - [ECA custom event (entity-aware) (deletions)](https://ecaguide.org/plugins/eca/content/events/content_entity_custom/index.md) ### Conditions - [Compare two scalar values](https://ecaguide.org/plugins/eca/base/conditions/eca_scalar/index.md) ### Actions - [Load original version of user (unchanged)](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Show Message: no changes](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Serialize new networks](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_encode/index.md) - [Serialize orig networks](https://ecaguide.org/plugins/eca/tamper/actions/eca_tamper_encode/index.md) - [Custom event: additions](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Custom event: deletions](https://ecaguide.org/plugins/eca/content/actions/eca_trigger_content_entity_custom_event/index.md) - [Load item provided by custom event](https://ecaguide.org/plugins/eca/content/actions/eca_token_load_entity/index.md) - [Message: new item](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Message: item exists](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Message: deleted item](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Message: item remains](https://ecaguide.org/plugins/core/actions/action_message_action/index.md) - [Get field value: new networks](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) - [Get field value: orig networks](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) # Resources # Articles Here we collect useful links around the ECA ecosystem. If you have a link that should be added, please follow instructions at [How to contribute](https://ecaguide.org/#contribute). ## Blog Posts July 23, 2023 Philip Norton [Drupal 10: Creating A Notification System Using The Message And ECA Modules](https://www.hashbangcode.com/article/drupal-10-creating-notification-system-using-message-and-eca-modules) July, 2023 Michael Anello (DrupalEasy) [Using the ECA module to replace a not-Drupal-10-ready contrib module (Termcase)](https://www.drupaleasy.com/blogs/ultimike/2023/07/using-eca-module-replace-not-drupal-10-ready-contrib-module-termcase) June 8, 2023 Vimal Joseph (Zyxware) [4 Must-Have Drupal Modules for Public Sector Websites](https://www.zyxware.com/article/6564/4-must-have-drupal-modules-for-public-sector-websites) April 17, 2023 Jürgen Haas [Now is the right time to update Drupal 7 to 10 thanks to ECA](https://www.lakedrops.com/en/blog/now-right-time-update-drupal-7-10-thanks-eca) December 7, 2022 Mike Herchel [Using ECA to Send Emails When a Field’s Value Changes](https://herchel.com/articles/using-eca-send-emails-when-fields-value-changes) December 4, 2022 Mike Herchel [Using ECA to Send Emails When Creating Nodes](https://herchel.com/articles/using-eca-send-emails-when-creating-nodes) November 22, 2022 Jürgen Haas [Drupal ECA wins at German/Austrian Splash Awards 2022](https://www.lakedrops.com/en/blog/drupal-eca-wins-germanaustrian-splash-awards-2022) November 15, 2022 Jürgen Haas [ECA for Drupal: Successful launch, moving on](https://www.lakedrops.com/en/blog/eca-drupal-successful-launch-moving) September 11, 2022 Philip Norton [Creating Drupal processes with the event condition action module](https://www.codeenigma.com/blog/creating-drupal-processes-event-condition-action-module) July 7, 2022 Jürgen Haas [Drupal ECA integrates bpmn.io](https://bpmn.io/blog/posts/2022-drupal-eca-integration.html) June 22, 2022 Jürgen Haas [ECA rules engine for Drupal: RC1 released](https://www.lakedrops.com/en/blog/eca-rules-engine-drupal-rc1-released) January 14, 2022 Jürgen Haas [State of ECA: What's new in Drupal's new rules engine with beta-2](https://www.lakedrops.com/en/blog/state-eca-whats-new-drupals-new-rules-engine-beta-2) September 17, 2021 Jürgen Haas [Event Condition Action - Business Process Modeling in Drupal 9+](https://www.lakedrops.com/en/blog/event-condition-action-business-process-modeling-drupal-9) ## Slides - September 2023 [ECA, the no-code solution that empowers you to orchestrate your Drupal sites](https://www.lakedrops.com/slides/2023-09-28-en-drupal-italy-eca.html) - July 2023 [ECA, the no-code solution that empowers you to orchestrate your Drupal sites](https://www.lakedrops.com/slides/2023-07-20-en-ddd-eca.html) - January 2023 [ECA - No-Code Orchestrierung für Drupal](https://www.lakedrops.com/slides/2023-01-12-de-dug-berlin-eca.html), German language - June 2022 [ECA Release Candidate 1](https://www.lakedrops.com/slides/2022-06-25-en-mountaincamp-eca.html) - April 2022 [ECA Update beta 8](https://www.lakedrops.com/slides/2022-04-12-en-nwdug-eca.html) - January 2022 [ECA Update beta 2](https://www.lakedrops.com/slides/2022-01-13-en-sfdug-eca.html) - October 2021 [ECA Update beta 1](https://www.lakedrops.com/slides/2021-10-29-en-drupalcampnyc-eca.html) - September 2021 [ECA introduction](https://www.lakedrops.com/slides/2021-09-16-de-dach-eca.html) ## Presentations - July 21, 2023, DrupalDevDays Vienna, [ECA Session Photos](https://www.flickr.com/photos/beta-robot/53066670908/in/pool-ddd23) - January 21, 2023, DrupalCamp DEN, [No-code API integrations with ECA and HTTP Client Manager](https://drupal-camp2023.den-japan.org/session/c06), Brandon Williams (amazee.io), - January 13, 2023, DUG Berlin, [ECA Feature Demo](https://drupalberlin.de/meeting-januar-2023) # Tutorials ## September 2021 ### Part 1 ### Part 2 # Looping through user networks and take action on changes [Originally published on 23. October 2022 by Barry (btown)](https://www.drupal.org/project/eca/issues/3317084) ## Problem/Motivation Even though it's really quite simple, it took me a while to understand how to setup a loop - I was looking for something more complex. I'm sharing my solution here in case it helps others. On my site, user profiles have an entity reference field that points to taxonomy terms called "networks". A user can belong to an unlimited number of networks (currently there are about a dozen). When a user profile is updated, I wanted a model to check if there had been any changes to the networks the user had selected. If there have been changes, I wanted to take different actions based on additions and deletions. For demonstration purposes, the end result displays a message for each addition, deletion or no change. The final product will be somewhat simplified - unnecessary actions will be removed as I don't care about no-changes, just additions and deletions. However, I included them as I was building my model to ensure I understood and checked each step. ## Commentary Sorry there are so many steps in my example. I wanted to provide an opportunity to review each event, condition and action so that details weren't missed. ## Example with Explanation ### 1. Starting event: Update Content Entity - Type (and bundle): `user:user` ### 2. Action: Entity Load - Name of token: `unchanged-user` - Load entity from: `current scope` (default value) - Entity type: `user` - Load unchanged values: `yes` ### 3. Condition: Compare two scalar values - First value: `[unchanged-user:field_user_networks]` - Comparison operator: `equals` - Second value: `[user:field_user_networks]` ### 4. Action: Display a message to the user - Message: `No changes to networks` ### 5. Condition: Compare two scalar values Same as step 3 but negated. - First value: `[unchanged-user:field_user_networks]` - Comparison operator: `equals` - Second value: `[user:field_user_networks]` - Negate the condition: `Yes` ### 6. Action: Entity - get field value Get the new values: - Field name: `field_user_networks` - Name of token: `new-networks-list` - Entity: `user` ### 6a. Action: Tamper: Encode/Decode Encode new list of networks for later comparison. - Data: `[user:field_user_networks]` - Token name: `new-networks` - Serialization mode: `Json Encode` ### 7. Action: Entity - get field value Get the original values: - Field name: `field_user_networks` - Name of token: `orig-networks-list` - Entity: `unchanged-user` ### 7a. Action: Tamper: Encode/Decode Encode original list of networks for later comparison. - Data: `[unchanged-user:field_user_networks]` - Token name: `orig-networks` - Serialization mode: `Json Encode` ### 8. Action: Trigger a custom event (entity aware) Trigger event for additions: - Event ID: `additions` - Tokens to forward: `orig-networks` - Entity: `new-networks-list` ### 9. Action: Trigger a custom event (entity aware) Trigger event for deletions: - Event ID: `deletions` - Tokens to forward: `new-networks`\* - Entity: `orig-networks-list`\* - \*\*\* Note reversal from previous step\*\* ### 10. Action: ECA Custom Event (entity-aware) - Event ID: `additions` ### 11. Action: Entity Load This is the current item from the list. - Name of token: `loaded-term` - Load entity from: `Current scope` (default value) - Entity type: `Taxonomy term` ### 12. Condition: Compare two scalar values Does the list of original networks contain the current item? - First value: `[orig-networks]` - Comparison operator: `contains` - Second value: `>[loaded-term:name]<` - Negate the condition: `yes` ### 13. Action: Display a message to the user Show the new item's name. - Message: `new item: [loaded-term:name]` ### 14. Condition: Compare two scalar values Same as step 12 but not negated. - First value: `[orig-networks]` - Comparison operator: `contains` - Second value: `>[loaded-term:name]<` ### 15. Action: Display a message to the user Show the existing item's name. - Message: `item exist already: [loaded-term:name]` ### 16. Action: ECA Custom Event (entity-aware) - Event Id: `deletions` ### 17. Action: Entity Load Same as step 11, but in a different pathway. - Name of token: `loaded-term` - Load entity from: `Current scope` (default value) - Entity type: `Taxonomy term` ### 18. Condition: compare two scalar values Check if the new list of networks contains the current item: - First value: `[new-networks]` - Comparison operator: `contains` - Second value: `>[loaded-term:name]<` - Negate the condition: `yes` ### 19. Action: Display a message to the user Show the deleted item's name. - Message: `deleted item: [loaded-term:name]` ### 20. Condition: Compare two scalar values Same as step 18 but not negated. - First value: `[new-networks]` - Comparison operator: `contains` - Second value: `>[loaded-term:name]<` ### 21. Action: Display a message to the user - Message: `item remains: [loaded-term:name]` ### 22. Save and test your model! - Save the model - Edit a user - Remove one item from their list of networks - Add one item - Save user - Check the status message ## Download This ECA model is [available for download](https://ecaguide.org/library/use%20case/user_network_changes/index.md). # Using ECA to Send Emails When Creating Nodes [Originally published on 4. December 2022 by Mike Herchel](https://herchel.com/articles/using-eca-send-emails-when-creating-nodes) The Florida DrupalCamp website (where [session submissions are currently open](https://www.fldrupal.camp/submit-session)!), sends an email when someone submits a session, and another one when we mark the session as accepted or rejected. Within the past week, I moved the [FLDC site](https://www.fldrupal.camp/) from using Drupal core’s Workflows module (along with the [Workbench Emails module](https://www.drupal.org/project/workbench_email)) to using the new(ish) [ECA module](https://www.drupal.org/project/eca), which I’m in the process of falling in love with. ECA provides almost infinite flexibility, while side-stepping some of the core Workflows issues that we were having. In this article, I’ll set up the ECA module, and then configure it to send an email when a user creates a session node. ~~There will be a followup article~~ After this article, read [how to configure ECA to send an email when the session is accepted or rejected](https://ecaguide.org/resources/tutorials/mherchel-2/index.md). ## About ECA ECA stands for “Event Condition Action”, and is a module that where you can create custom workflows and logic. The primary reason I love Drupal is the ease of configuring custom solutions through “site building”, which is Drupal’s term for clicking around and configuring the CMS to build what you want. The [ECA module](https://www.drupal.org/project/eca) gives your site-building toolbox some amazingly useful mechanisms that can reduce the use of custom code, and simplify development for site-builders. ## ECA is complex (sort of…) ECA reminds me of Drupal core’s Views module, in that it has a very complex user interface, but it allows you to create extremely complex things that would normally require custom code. Much like Views UI, the UI of ECA takes a bit of getting used to, but once you’re familiar with it, you can work pretty effectively! That all being said, there is plenty of [documentation](https://ecaguide.org/index.md), and the maintainers are extremely responsive and helpful within the #eca channel within Drupal Slack. ## Downloading ECA and BPMN.iO To install and configure ECA, you need to pull it down via Composer. ``` composer require drupal/eca ``` However the ECA module is just the backend module (think of it as the Views module without Views UI). In order to configure it, you’ll need a “modeler”. I use what (I think) is the most popular one, [BPMN.iO](https://www.drupal.org/project/bpmn_io). ``` composer require drupal/bpmn_io ``` ## Installing ECA We’ll need to install several modules in order to work with ECA: - `eca` - this is the core module - `eca_content` - this enables ECA to work with content entities (like creation, updating, etc) - `eca_ui` - This is a UI to see (but not configure) existing “ECAs” - `bpmn_io` - This is the UI to create and configure “ECAs” You can enable these modules either through the UI or through Drush. ``` drush en -y eca eca_content eca_ui bpmn_io ``` ## Configuring ECA Navigate to ECA via Configuration > Workflow > ECA You’ll be presented with this screen showing no existing ECAs. ### 1. Add a ECA/model Click the link to “Add new model”, and you will be presented with the BPMN user interface. If you click on the “General” section within the Process pane on the right hand side, you can give this model a name. I named ours “Send email on session creation”. ### 2. Create a start event The next step is to create the start event. You do this by dragging the “circle” from the left toolbar onto the canvas. ### 3. Configure that start event. 1. Click on the start event circle. 1. On the right hand side of the screen you’ll see the event’s properties. Expand the “general” section, and give it a name. 1. Within the “Template” section, click the blue “Select” button, and select the option for “Insert content entity”.\ **BEWARE** - Be sure to select "Insert content entity, as opposed to "Create content entity"! The option to “Create content entity” does not work as you expect. You’ll want to use the “Insert” option instead.\ According to the maintainer Jürgen Haas, “The create entity event is triggered by Drupal core when PHP initializes the Node object to then fill it with values. So that's very early in the process and no real values are available at that point.” 1. Change the “Type (and bundle) to “Content: Session”. For the FLDC site, “Session” is the label for the session content type. ### 4. Create the task to send emails The next step is to configure the task to send the emails. 1. Click on the start event circle. Icons will appear to the right hand side. 1. Click the rounded rectangle icon that is labeled “Append task” when you hover your mouse over the icon. 1. On the properties within the right hand side, give the task a name. I named mine “Send email” 1. Within the “recipient’s email address” field, enter a value. You can use tokens here. There’s a “Browse available tokens” link above the properties pane. I use the `[node:author:mail]` token. 1. Enter in a subject and message. 1. Save and you're done! ## Conclusion I feel at this point, I’m only using about 2% of ECA’s power. I’m excited to dive deeper, although as a front-end developer, I probably won’t have too many opportunities. In my next article on ECA, I’m going to walk through a slightly more complex workflow where I configure ECA to send emails when we accept or reject sessions. This involves comparing field values, etc. In the meantime, if you’d like to see ECA in action, please [submit a session to Florida DrupalCamp](https://www.fldrupal.camp/submit-session)! The session deadline is December 19th! # Using ECA to Send Emails When a Field’s Value Changes [Originally published on 7. December 2022 by Mike Herchel](https://herchel.com/articles/using-eca-send-emails-when-fields-value-changes) The [Florida DrupalCamp](https://www.fldrupal.camp/) website (where [session submissions are open](https://www.fldrupal.camp/submit-session) till December 19th), uses the [ECA module](https://www.drupal.org/project/eca) to send transactional emails. In [part 1 of this series](https://ecaguide.org/resources/tutorials/mherchel-1/index.md), I walk through using ECA to send an email when a user creates a “session” node. If you’ve not read that article yet, check it out now as it gives a good background of ECA. In this next article, I’ll walk through the steps of sending confirmation and rejection emails when a field is changed to indicate the session is accepted or rejected. We’ll also display a confirmation message to the user that emails have been sent out. ## FLDC site architecture The Florida DrupalCamp website has a node type called `session`. Along with the normal expected fields, there’s an optional “Acceptance” field (`field_acceptance`) that’s a reference to a taxonomy vocabulary where there are two entries: “Accepted”, and “Rejected”. I have the following ECA related modules installed and enabled: - `eca` - this is the core module - `eca_content` - this enables ECA to work with content entities (like creation, updating, etc) - `eca_ui` - This is a UI to see (but not configure) existing ECA modals. - `bpmn_io` - This is the UI to create and configure models ## Where we’re going To give you an idea of where we’re ending up, here’s a screenshot of the final model within ECA. ### 1. Navigate to ECA The first step is to navigate to Admin > Configuration > Workflow > ECA. You’ll see a list of your current models (below we see the one that we create in step 1 of this series). Click on the “Add new model” button at the top right and then give the model a name (we name this "Send email on acceptance / rejection"). ### 2. Create the start event To start, we need to create an event to trigger the ECA workflow. 1. Drag the “Create Start Event” circle from the left toolbar to the canvas. 1. Within the properties pane on the right hand side, click the “Select” button within the “Template” section. 1. A modal appears. Choose the option for “Update content entity”. 1. Change the type of this entity to “Content: Session” (“Session” is the name of our content type that updating will trigger this model). 1. Give this event a name. We call ours, “Session is updated”. ### 3. Append the “Load original entity” task The next step is that we need to load the entity without its modified fields. We’ll then give this entity a token name so we can reference it later. 1. Click the start event circle. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts a task. 1. Label the task “Load original entity”. 1. In the “Template” section, Click the “Select” button and choose “Entity: load”. 1. In the “Custom properties” section, change the “Name of token” field to `originalentity`. We’ll be referencing this later, so watch for typos! 1. Near the bottom, change the option for “Load unchanged values” to yes. ### 4. Append another task: “Load new values” We also need another task to load the entity with its new values (so we can compare). We’ll chain this task off of the previous one. ``` Note that I'm being explicit very here. While graciously reviewing this, maintainer [Jürgen Haas](https://www.drupal.org/u/jurgenhaas) noted that this step is not necessary, because the event already provides that token automatically. ``` 1. Click the “Load original entity” task. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts another task. 1. Label the task “Load new values”. 1. In the “Template” section, Click the “Select” button and choose “Entity: load”. 1. In the “Custom properties” section, change the “Name of token” field to `updatedentity`. Once again, we’ll be referencing this later, so watch for typos! 1. Near the bottom, we do not modify the “Load unchanged values” dropdown. ### 5. Create conditional to only proceed to “Load new values” if the acceptance field is empty We only want to send an email if the acceptance field has not yet been set, this will prevent emails from going out if we update other fields. To do this, we create a conditional. 1. Select on the arrow that goes from the “Load original entity” task to the “Load new values” task. This will bring a “Sequence flow” property pane to the right. 1. In the “Template” section, Click the “Select” button and choose “Entity: field value is empty”. 1. Label the condition, “Check if acceptance is empty”. 1. Within the “Field name” field, enter the machine name of the field you want to check. For FLDC it’s `field_acceptance`. 1. Within the “Entity” field, we enter in the token that we created for the original entity’s values, `originalentity`. Once again, no typos! ### 6. Append task: “Send acceptance email” The next step is to create the task that will actually send the email! 1. Click the “Load new values” task. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts another task. 1. Label the task “Send acceptance email”. 1. In the “Template” section, Click the “Select” button and choose “Send email”. 1. Insert either an email address or a token representing an email address into the “Recipient email address” field. I use the `[updatedentity:author:mail]` token to represent the author of the session node. Note that I can specify the previously created entity tokens here, but do not need to because this node token is taken from the event. 1. Fill out the “Subject” and “Message” fields. Note you can also use tokens here. ### 7. Create conditional to only proceed if the acceptance field is set to “Accepted” Before we send the acceptance email, we obviously need to check that the `field_acceptance` field is set to “Accepted”. To do this, we need to check that the value is set to `46`, which is the ID of the “Accepted” taxonomy term that I created. 1. Select on the arrow that goes from the “Load new values” task to the “Send acceptance email” task. This will bring a “Sequence flow” property pane to the right. 1. Label the condition, “Check if acceptance is accepted”. 1. In the “Template” section, Click the “Select” button and choose “Entity: compare field value”. 1. Within the “Field name” field, enter the machine name of the field you want to check. For us it’s `field_acceptance`. 1. For the “Expected field value” field, set the value to the value you’re expecting. For FLDC, we’re expecting `46`, which is the ID of the “Accepted” taxonomy term that we created. 1. Within the “Entity” field, we enter in the token that we created for the original entity’s values, `updatedentity`. Be sure no typos! ### 8. Append a new task to show “Emails sent” message to the user After the emails are sent, we want to let the admin know that action happened. To do this we display a message. 1. Click the “Send acceptance email” task. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts another task. 1. Label the task “Display message to user”. 1. In the “Template” section, Click the “Select” button and choose “Display a message to user”. 1. Within the “Message” field, Enter the message that you want to display. ### 9. Create alternate workflow to send rejection emails and show message The “Accepted” emails are now going out! Let's do this again for rejection emails by replicating steps 6-8. 1. Same as before, we click the “Load new values” task. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts another task. 1. Label the task “Send rejection email”. 1. With your mouse, grab the starting point of the arrow that is splitting off from the “Check if acceptance is accepted” arrow. Drag it to the bottom of the “Load new values” task. 1. Select the “Send rejection email” task that you just created. 1. In the “Template” section, Click the “Select” button and choose “Send email” 1. Insert either an email address or a token representing an email address into the “Recipient email address” field. I use the `[updatedentity:author:mail]` token to represent the author of the session node. 1. Fill out the “Subject” and “Message” fields. Note you can also use tokens here. 1. Select the arrow that goes from the “Load new values” task to the “Send rejection email” task. This will bring a “Sequence flow” property pane to the right. 1. Label the condition, “Check if acceptance is rejected” 1. In the “Template” section, Click the “Select” button and choose “Entity: compare field value” 1. Within the “Field name” field, enter the machine name of the field you want to check. For us it’s `field_acceptance`. 1. For the “Expected field value” field, set the value to the value you’re expecting. We’re expecting `47`, which is the ID of the “Rejected” taxonomy term that we created. 1. Once again, within the “Entity” field, we enter in the token that we created for the original entity’s values, `updatedentity`. 1. Click the “Send rejection email” task. You’ll see some icons appear to the right of it. Click the rounded rectangle “Append task” icon, which inserts another task. 1. Label the task “Display message to user” 1. In the “Template” section, Click the “Select” button and choose “Display a message to user” 1. Within the “Message” field, Enter the message that you want to display. ## We’re done! And with that, we have a completely functional system to send transactional emails without any custom code! [Drupal confirmation message screenshot showing the ECA message](https://ecaguide.org/images/mherchel/eca-2/image3.png) ECA displays a message stating that an email has been sent to the node author. [Screenshot of gmail inbox showing the messages from ECA](https://ecaguide.org/images/mherchel/eca-2/image2.png) You can see both the session creation email, and the new acceptance email that ECA sent. Sidenote, Cox cable does not block outbound SMTP. I performed these actions on my local computer 🤷‍♂️ As you’ve seen, barely scratching the surface of what the ECA module can do. But hopefully with this tutorial, you can see how its interface works, and imagine the possibilities! # Granting a User Role Based on a Product Purchase Based on the discussion in [drupal.org issue #3477420](https://www.drupal.org/project/eca_commerce/issues/3477420), this guide walks through creating an ECA model that automatically grants a user role when a customer purchases a specific product. This is a common requirement for membership sites, gated content, or any scenario where purchasing a product should unlock additional permissions. ## Prerequisites Before you begin, make sure the following modules are installed and enabled: - [Drupal Commerce](https://www.drupal.org/project/commerce) - [ECA](https://www.drupal.org/project/eca) (core module) - [ECA Commerce](https://ecaguide.org/plugins/eca/commerce/index.md) (`eca_commerce`) - [ECA Content](https://ecaguide.org/plugins/eca/content/index.md) (`eca_content`) - A modeler such as [BPMN.iO](https://www.drupal.org/project/bpmn_io) ``` composer require drupal/eca drupal/eca_commerce drupal/bpmn_io drush en -y eca eca_commerce eca_content eca_ui bpmn_io ``` You should also have: - At least one Commerce product (the "membership" product or similar) - A Drupal role to assign (e.g. `member`) ## Understanding the Right Event A common mistake is to use the [Checkout: Completion](https://ecaguide.org/plugins/eca/commerce/events/eca_commerce_checkout_completion/index.md) event. This does not work reliably for anonymous checkout flows, because the user account may not yet be created at the time that event fires. The correct event to use is [**Order: Assign order**](https://ecaguide.org/plugins/eca/commerce/events/eca_commerce_order_assign/index.md). This event fires when Commerce assigns an order to a customer, which happens after the user account has been created (for anonymous checkouts) or is already available (for authenticated users). It provides two key tokens: | Token | Description | | --------------------- | ------------------------------------ | | `[commerce_customer]` | The customer — a Drupal user entity. | | `[commerce_order]` | The order entity. | This works for both scenarios: - **Anonymous checkout** with the "Create a new account for an anonymous order" setting enabled — the user is created before this event fires. - **Authenticated users** who are already logged in when purchasing. ## Basic Approach: Grant a Role on Any Purchase If you want to grant a role whenever *any* order is assigned to a customer (regardless of which product was purchased), the model is straightforward. ### Step 1. Create a New ECA Model Navigate to **Configuration > Workflow > ECA** and click **Add new model**. Give it a name, e.g. "Grant role on product purchase". ### Step 2. Add the Start Event 1. Drag a start event (circle) onto the canvas. 1. In the properties panel, select the event **Order: Assign order** (`eca_commerce_order_assign`). ### Step 3. Add the Action to Grant the Role 1. Click the start event and append a new task. 1. Select the action [**Add a role to the selected users**](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md). 1. Configure the fields: `Role` : Select the role you want to grant, e.g. `member`. `Entity` : Enter `commerce_customer` (without brackets). This is the token provided by the event, representing the user who placed the order. 1. Save the model. That is all you need for the basic case. When a customer completes an order, ECA will automatically assign the chosen role to their account. ## Advanced Approach: Grant a Role Only for a Specific Product In many cases, you only want to grant the role when a particular product has been ordered — not for every purchase. Since the "Order: Assign order" event provides the full order entity, you can loop through the order items and check whether the target product is among them. ### Step 1. Create the Start Event Same as above: use the **Order: Assign order** event. ### Step 2. Get the Order Items 1. Append a task to the start event. 1. Select the action [**Entity: get field value**](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md). 1. Configure: `Field name` : `order_items` — this is the field on the Commerce order entity that references its order items. `Token name` : `order_items_list` `Entity` : `commerce_order` This stores the list of order item entities into the token `order_items_list`. ### Step 3. Loop Through the Order Items 1. Append a task to the previous action. 1. Select the action [**Token: set value**](https://ecaguide.org/plugins/eca/base/actions/eca_token_set_value/index.md) or use the looping mechanism that fits your ECA version. The recommended approach is to use the [**Entity: compare field value**](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) condition on each order item. For each item in the loop, compare the `purchased_entity` field against the product variation ID you are looking for. Alternative: List contains item If you know the exact product variation ID, you may also be able to use the [**List: contains item**](https://ecaguide.org/plugins/eca/base/conditions/eca_list_contains/index.md) condition to check whether the order items list contains the target product. This depends on the data format returned by Commerce for the order items reference field. ### Step 4. Add a Condition to Check the Product After obtaining each order item (e.g. via a loop), add a gateway with a condition: 1. Select the condition [**Entity: compare field value**](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md). 1. Configure: `Field name` : `purchased_entity` — this references the product variation on the order item. `Expected value` : The ID of the product variation that should trigger the role grant, e.g. `2`. `Operator` : `equals` `Entity` : The current order item token from your loop. ### Step 5. Grant the Role (Conditional) Connect the "yes" path from the condition gateway to the role assignment action: 1. Select [**Add a role to the selected users**](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md). 1. Set the `Role` to the desired role (e.g. `member`). 1. Set `Entity` to `commerce_customer`. Save the model. ## Summary | Component | Plugin / Token | | ------------------------- | ------------------------------------------------------------------------------------------------------------------ | | Event | [Order: Assign order](https://ecaguide.org/plugins/eca/commerce/events/eca_commerce_order_assign/index.md) | | Customer token | `[commerce_customer]` | | Order token | `[commerce_order]` | | Action (role) | [Add a role to the selected users](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md) | | Condition (product check) | [Entity: compare field value](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) | | Action (get items) | [Entity: get field value](https://ecaguide.org/plugins/eca/content/actions/eca_get_field_value/index.md) | ## Tips - **Do not use "Checkout: Completion"** for anonymous checkout flows. The user may not exist yet at that point. - **"Order: Assign order"** fires when Commerce assigns the order to a user. For anonymous checkouts, this happens after the user account is created. - If you need to check for a specific product, loop through the order items and compare the `purchased_entity` field against the target product variation ID. - The `[commerce_customer]` token is a full Drupal user entity, so you can use it directly in the "Entity" field of user-related actions. - For debugging, enable ECA logging under **Configuration > Workflow > ECA > Settings** to trace which events fire and which tokens are available. ## Related Resources - [ECA Commerce plugin reference](https://ecaguide.org/plugins/eca/commerce/index.md) - [Order: Assign order event](https://ecaguide.org/plugins/eca/commerce/events/eca_commerce_order_assign/index.md) - [Add a role to the selected users action](https://ecaguide.org/plugins/user/actions/user_add_role_action/index.md) - [Entity: compare field value condition](https://ecaguide.org/plugins/eca/content/conditions/eca_entity_field_value/index.md) - [Drupal.org discussion: How to grant a user role when a specific product has been ordered?](https://www.drupal.org/project/eca_commerce/issues/3477420) # Taxonomy url alias with an anchor This will walk you through how to re-write a taxonomy's url alias with an anchor ('#') (on creation or save). For this example we will use movie "gCinema (genre)" taxonomy. We need to add two fields to our taxonomy term at "/admin/structure/taxonomy/manage/cinema_genre/overview/fields" All fields will be "plain text" "simple text". Name the fields: `field_cinema_g_name_html`, and `field_cinema_g_name_node_view`. Now go to `/admin/config/workflow/eca` and create a "New Model", this will be our canvas to work with. - First things first, lets give our model a name, so on the right side of your screen, you will find your details palate, (which we will refer later also). - General --> Name: Cinema (genre) Now click the "Save" button at the top of your screen" - Drag and drop "Create StartEvent" (the circle from the palette on the left), This will be our "Event to fire on" That will tell eca when to activate our code. - Template: Pre-save content entity Next we will add create a task for our code to do.\ Click on our circle on our canvas, and you will see a small pop-up palette that contains a few items. Drag and drop the square or "Append Task" on to your canvas. This task we are going to fill the `field_cinema_g_name_node_view` field that we created in our taxonomy term. - General --> Name: set field value - Template: Entity: set field value - Custom properties --> Field name: `field_cinema_g_name_node_view` - Custom properties --> Field value: [term:name] (the reason we move the term name directly to the text field because in drupal using the term name in views and other systems is a bit tough, but a text field all system support) Click on the circle again and add another task. This task chain will fill the `field_cinema_g_name_html` field we created on our taxonomy term. (the first event in this chain is to replace the spaces with dashes) - General --> Name: replace - Template: Tamper: find replace regex - Custom properties --> Data to be tampered: [term:name] - Custom properties --> Regex to find: /[\\s]/ - Custom properties --> Replacement pattern: - - Custom properties --> Result token name: `[cinema_g_name_html_replace]` While clicked on the square, use the small pop-up and add a task. (now we need to take our resulting string from the above task and turn it all lowercase) - General --> Name: lowercase - Template: Tamper convert case - Custom properties -- > Data to be tampered: `[cinema_g_name_html_replace]` - Custom properties -- > How to convert case: Convert to lowercase - Custom properties -- > Result token name: `[cinema_g_name_html_lower]` While clicked on the square, use the small pop-up and add a task. (we now need to set the value of `field_cinema_g_name_html`) - General --> Name: set field value - Template: Entity: set field value - Custom properties --> Field name: `field_cinema_g_name_html` - Custom properties --> Field value: `[cinema_g_name_html_lower]` ______________________________________________________________________ Now click on the circle again and add another task. (we need to set the value of the url alias of our taxonomy term) - General --> Name: replace - Template: Tamper: find replace regex - Custom properties --> Data to be tampered: [term:name] - Custom properties --> Regex to find: /[\\s]/ - Custom properties --> Replacement pattern: - - Custom properties --> Result token name: `[cinema_g_path_replace]` While clicked on the square, use the small pop-up and add a task. (now we need to take our resulting string from the above task and turn it all lowercase) - General --> Name: lowercase - Template: Tamper convert case - Custom properties -- > Data to be tampered: `[cinema_g_path_replace]` - Custom properties -- > How to convert case: Convert to lowercase - Custom properties -- > Result token name: `[cinema_g_path_lower]` While clicked on the square, use the small pop-up and add a task. (we now need to set the value of `field_cinema_g_name_html`) - General --> Name: set field value - Template: Entity: set field value - Custom properties --> Field name: `path` - Custom properties --> Field value: `[cinema_g_path_lower]` # Videos ## Podcasts ### Talking Drupal - Module of the week - November 2022 [Episode375](https://www.talkingdrupal.com/375) ## Presentation recordings ### DrupalCamp Spain - September 2022 ### NWDUG Meetup - April 2022 ### SFDUG Meetup - January 2022