From b2404da31c235bd9d8e5bb8aebefcc9c68e14411 Mon Sep 17 00:00:00 2001
From: mxh <16778-hauptm@users.noreply.drupalcode.org>
Date: Wed, 19 Mar 2025 09:26:00 +0000
Subject: [PATCH 01/10] Issue #3513674 by mxh, jurgenhaas: ECA Extra field does
 not work with Field Group in forms

---
 modules/render/eca_render.module | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/modules/render/eca_render.module b/modules/render/eca_render.module
index 418e3dc92..9a3b6165d 100644
--- a/modules/render/eca_render.module
+++ b/modules/render/eca_render.module
@@ -378,6 +378,10 @@ function _eca_render_trigger_extra_field(array &$build, EntityInterface $entity,
       $render_build = &$event->getRenderArray();
     }
     $build[$name] = $render_build;
+    if (!empty($build[$name]) && ($display_type === 'form') && !isset($build[$name]['#type'])) {
+      // Wrap as container so that the extra field can be grouped.
+      $build[$name]['#type'] = 'container';
+    }
     if (!isset($build['#weight']) && isset($options['weight'])) {
       $build['#weight'] = $options['weight'];
     }
-- 
GitLab


From 674336ef48cc6ea569b34ed9441d0955eee084ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Haas?=
 <21467-jurgenhaas@users.noreply.drupalcode.org>
Date: Wed, 19 Mar 2025 09:40:46 +0000
Subject: [PATCH 02/10] Issue #3513657 by jurgenhaas, mxh: ECA Views field:
 Additionally pass along arguments passed to the view

---
 modules/render/src/Plugin/ECA/Event/RenderEvent.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/modules/render/src/Plugin/ECA/Event/RenderEvent.php b/modules/render/src/Plugin/ECA/Event/RenderEvent.php
index 060fb5764..d5214c11c 100644
--- a/modules/render/src/Plugin/ECA/Event/RenderEvent.php
+++ b/modules/render/src/Plugin/ECA/Event/RenderEvent.php
@@ -575,6 +575,9 @@ class RenderEvent extends EventBase implements PluginUsageInterface {
       new Token(name: 'view_id', description: 'The view ID.', classes: [
         EcaRenderViewsFieldEvent::class,
       ]),
+      new Token(name: 'view_args:?', description: 'The list of arguments given to the view.', classes: [
+        EcaRenderViewsFieldEvent::class,
+      ]),
     ]
   )]
   protected function buildEventData(): array {
@@ -613,6 +616,7 @@ class RenderEvent extends EventBase implements PluginUsageInterface {
       $data += [
         'entity' => $event->getEntity(),
         'relationships' => $event->getRelationshipEntities(),
+        'view_args' => $event->getFieldPlugin()->view->args,
         'view_id' => $event->getFieldPlugin()->view->id(),
         'view_display' => $event->getFieldPlugin()->view->current_display,
       ];
-- 
GitLab


From 7f0199cae20070cd028415aadffb067a416cf053 Mon Sep 17 00:00:00 2001
From: Daniel <11906-dsasser@users.noreply.drupalcode.org>
Date: Mon, 31 Mar 2025 16:04:17 +0000
Subject: [PATCH 03/10] Issue #3515195 by coderdan, jurgenhaas: Add
 migration_id token to migrate events

---
 .../src/Plugin/ECA/Event/MigrateEvent.php     | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/modules/migrate/src/Plugin/ECA/Event/MigrateEvent.php b/modules/migrate/src/Plugin/ECA/Event/MigrateEvent.php
index b3636d4ab..debb719ad 100644
--- a/modules/migrate/src/Plugin/ECA/Event/MigrateEvent.php
+++ b/modules/migrate/src/Plugin/ECA/Event/MigrateEvent.php
@@ -102,6 +102,17 @@ class MigrateEvent extends EventBase {
       MigrateIdMapMessageEvent::class,
     ]
   )]
+  #[Token(
+    name: 'migration_id',
+    description: 'The migration plugin id being run.',
+    classes: [
+      MigrateImportEvent::class,
+      MigratePreRowSaveEvent::class,
+      MigrateRollbackEvent::class,
+      MigrateRowDeleteEvent::class,
+      MigrateIdMapMessageEvent::class,
+    ]
+  )]
   #[Token(
     name: 'map',
     description: 'The map plugin that caused the event to fire.',
@@ -176,6 +187,18 @@ class MigrateEvent extends EventBase {
         }
         break;
 
+      case 'migration_id':
+        if ($event instanceof MigrateImportEvent
+          || $event instanceof MigratePreRowSaveEvent
+          || $event instanceof MigrateRollbackEvent
+          || $event instanceof MigrateRowDeleteEvent
+          || $event instanceof MigrateIdMapMessageEvent
+        ) {
+          $migration = $event->getMigration();
+          return $migration->id();
+        }
+        break;
+
       case 'map':
         if ($event instanceof MigrateMapSaveEvent
           || $event instanceof MigrateMapDeleteEvent
-- 
GitLab


From 718d02727e4c6b7b67e7a33449318addb46cc05c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Haas?=
 <21467-jurgenhaas@users.noreply.drupalcode.org>
Date: Wed, 2 Apr 2025 15:41:41 +0000
Subject: [PATCH 04/10] Issue #3516245 by jurgenhaas, lammensj: Event data not
 available

---
 .../EcaExecutionGeneralSubscriber.php              | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/EventSubscriber/EcaExecutionGeneralSubscriber.php b/src/EventSubscriber/EcaExecutionGeneralSubscriber.php
index 2898446d0..0d4534e6c 100644
--- a/src/EventSubscriber/EcaExecutionGeneralSubscriber.php
+++ b/src/EventSubscriber/EcaExecutionGeneralSubscriber.php
@@ -12,6 +12,7 @@ use Drupal\eca\Event\AfterInitialExecutionEvent;
 use Drupal\eca\Event\BeforeInitialExecutionEvent;
 use Drupal\eca\Event\EntityEventInterface;
 use Drupal\eca\Event\RenderEventInterface;
+use Drupal\eca\Plugin\ECA\Event\EventInterface;
 
 /**
  * General ECA event subscriber for EcaEvents::BEFORE_INITIAL_EXECUTION events.
@@ -40,6 +41,15 @@ class EcaExecutionGeneralSubscriber extends EcaExecutionSubscriberBase {
     classes: [EntityEventInterface::class],
   )]
   public function onBeforeInitialExecution(BeforeInitialExecutionEvent $before_event): void {
+    // Find previous token provider of type EventInterface and remove it from
+    // the list and remember it to be restored afterwards.
+    foreach ($this->tokenService->getDataProviders() as $dataProvider) {
+      if ($dataProvider instanceof EventInterface) {
+        $this->tokenService->removeTokenDataProvider($dataProvider);
+        $before_event->setPrestate('previous_data_provider', $dataProvider);
+      }
+    }
+
     $plugin = $before_event->getEcaEvent()->getPlugin();
     $this->tokenService->addTokenDataProvider($plugin);
 
@@ -86,6 +96,10 @@ class EcaExecutionGeneralSubscriber extends EcaExecutionSubscriberBase {
   public function onAfterInitialExecution(AfterInitialExecutionEvent $after_event): void {
     $plugin = $after_event->getEcaEvent()->getPlugin();
     $this->tokenService->removeTokenDataProvider($plugin);
+    // Restore the previous EventInterface token data provider if available.
+    if ($dataProvider = $after_event->getPrestate('previous_data_provider')) {
+      $this->tokenService->addTokenDataProvider($dataProvider);
+    }
   }
 
   /**
-- 
GitLab


From 1ac9f25ee91867fbdf46a5d814cd9c81b8394413 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Haas?=
 <21467-jurgenhaas@users.noreply.drupalcode.org>
Date: Mon, 31 Mar 2025 16:25:35 +0000
Subject: [PATCH 05/10] Issue #3515498 by jurgenhaas, ikam: Form Field: Set as
 Disable - usage of the "Set as Disabled" yes/no

---
 .../src/Plugin/Action/FormFieldDisable.php    | 29 ++++++++-----------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/modules/form/src/Plugin/Action/FormFieldDisable.php b/modules/form/src/Plugin/Action/FormFieldDisable.php
index 0dba943d5..0fd14b331 100644
--- a/modules/form/src/Plugin/Action/FormFieldDisable.php
+++ b/modules/form/src/Plugin/Action/FormFieldDisable.php
@@ -29,29 +29,24 @@ class FormFieldDisable extends FormFlagFieldActionBase {
    */
   protected function flagAllChildren(&$element, bool $flag): void {
     parent::flagAllChildren($element, $flag);
-    $this->setFormFieldAttributes($element);
-  }
-
-  /**
-   * Set form field attributes on the given element.
-   *
-   * Sometimes it is too late that the form builder sets proper HTML attributes.
-   * Therefore, this helper method assures they are set.
-   *
-   * @param array &$element
-   *   The form element.
-   *
-   * @see \Drupal\Core\Form\FormBuilder::handleInputElement
-   */
-  protected function setFormFieldAttributes(array &$element): void {
     if (empty($element['#input'])) {
       return;
     }
     if (!empty($element['#allow_focus'])) {
-      $element['#attributes']['readonly'] = 'readonly';
+      if ($flag) {
+        $element['#attributes']['readonly'] = 'readonly';
+      }
+      else {
+        unset($element['#attributes']['readonly']);
+      }
     }
     else {
-      $element['#attributes']['disabled'] = 'disabled';
+      if ($flag) {
+        $element['#attributes']['disabled'] = 'disabled';
+      }
+      else {
+        unset($element['#attributes']['disabled']);
+      }
     }
   }
 
-- 
GitLab


From 47a80fd00e61cf2cb77890976a74f97e6814b942 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Haas?=
 <21467-jurgenhaas@users.noreply.drupalcode.org>
Date: Wed, 9 Apr 2025 09:23:50 +0000
Subject: [PATCH 06/10] Update some routes

---
 modules/ui/eca_ui.routing.yml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/modules/ui/eca_ui.routing.yml b/modules/ui/eca_ui.routing.yml
index d21d9e27f..0f9e0c4b0 100644
--- a/modules/ui/eca_ui.routing.yml
+++ b/modules/ui/eca_ui.routing.yml
@@ -17,6 +17,7 @@ eca.save:
     _controller: '\Drupal\eca_ui\Controller\EcaController::save'
   requirements:
     _permission: 'administer eca'
+    _csrf_request_header_token: 'TRUE'
 entity.eca.delete_form:
   path: '/admin/config/workflow/eca/{eca}/delete'
   defaults:
@@ -30,24 +31,28 @@ entity.eca.enable:
     _controller: '\Drupal\eca_ui\Controller\EcaController::enable'
   requirements:
     _permission: 'administer eca'
+    _csrf_token: 'TRUE'
 entity.eca.disable:
   path: '/admin/config/workflow/eca/{eca}/disable'
   defaults:
     _controller: '\Drupal\eca_ui\Controller\EcaController::disable'
   requirements:
     _permission: 'administer eca'
+    _csrf_token: 'TRUE'
 entity.eca.clone:
   path: '/admin/config/workflow/eca/{eca}/clone'
   defaults:
     _controller: '\Drupal\eca_ui\Controller\EcaController::clone'
   requirements:
     _permission: 'administer eca'
+    _csrf_token: 'TRUE'
 entity.eca.export:
   path: '/admin/config/workflow/eca/{eca}/export'
   defaults:
     _controller: '\Drupal\eca_ui\Controller\EcaController::export'
   requirements:
     _permission: 'administer eca'
+    _csrf_token: 'TRUE'
 entity.eca.export_recipe:
   path: '/admin/config/workflow/eca/{eca}/recipe'
   defaults:
-- 
GitLab


From 2046e305ce2ce22527547c4641045ba02ca50c72 Mon Sep 17 00:00:00 2001
From: starlight-sparkle <66705-PixlRainbow@users.noreply.drupalcode.org>
Date: Wed, 9 Apr 2025 04:13:14 +0000
Subject: [PATCH 07/10] Issue #3518078: eca_render: Action "Render:
 Unserialize" does not work for "_eca_token" format

---
 modules/render/src/Plugin/Action/Unserialize.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/modules/render/src/Plugin/Action/Unserialize.php b/modules/render/src/Plugin/Action/Unserialize.php
index 69d874357..9f43c8eec 100644
--- a/modules/render/src/Plugin/Action/Unserialize.php
+++ b/modules/render/src/Plugin/Action/Unserialize.php
@@ -70,6 +70,10 @@ class Unserialize extends Serialize {
     $serialized = (string) $this->tokenService->replace($value);
 
     $format = $this->configuration['format'];
+    if ($format === '_eca_token') {
+      $format = $this->getTokenValue('format', 'json');
+    }
+
     $type = $this->configuration['type'];
     if ($type === '_eca_token') {
       $type = $this->getTokenValue('type', 'array');
-- 
GitLab


From 8ed78fc6bcfd820eda9597362f2ffb60488b16b0 Mon Sep 17 00:00:00 2001
From: Martin Anderson-Clutz <46883-mandclu@users.noreply.drupalcode.org>
Date: Thu, 10 Apr 2025 13:49:17 +0000
Subject: [PATCH 08/10] Issue #3517979 by mandclu, jurgenhaas: Allow ECA to
 manipulate module-provided menu links

---
 modules/menu/eca_menu.info.yml                |  7 ++
 .../menu/src/Plugin/Action/EnableMenuItem.php | 91 +++++++++++++++++++
 2 files changed, 98 insertions(+)
 create mode 100644 modules/menu/eca_menu.info.yml
 create mode 100644 modules/menu/src/Plugin/Action/EnableMenuItem.php

diff --git a/modules/menu/eca_menu.info.yml b/modules/menu/eca_menu.info.yml
new file mode 100644
index 000000000..7016156c1
--- /dev/null
+++ b/modules/menu/eca_menu.info.yml
@@ -0,0 +1,7 @@
+name: 'ECA Menu'
+type: module
+description: 'Additional options for working with menu links.'
+core_version_requirement: ^10.3 || ^11
+package: ECA
+dependencies:
+  - eca:eca
diff --git a/modules/menu/src/Plugin/Action/EnableMenuItem.php b/modules/menu/src/Plugin/Action/EnableMenuItem.php
new file mode 100644
index 000000000..9af138063
--- /dev/null
+++ b/modules/menu/src/Plugin/Action/EnableMenuItem.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Drupal\eca_menu\Plugin\Action;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Menu\MenuLinkManagerInterface;
+use Drupal\eca\Plugin\Action\ConfigurableActionBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Enables a specified menu item.
+ *
+ * @Action(
+ *   id = "eca_menu_enable_menu_item",
+ *   label = @Translation("Menu Item: Enable or Disable"),
+ *   description = @Translation("Enable or disable a menu link (can be module provided)."),
+ *   eca_version_introduced = "2.1.x",
+ *   type = "entity"
+ * )
+ */
+class EnableMenuItem extends ConfigurableActionBase {
+
+  /**
+   * The MenuLinkManager.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkManagerInterface
+   */
+  protected MenuLinkManagerInterface $menuLinkManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->menuLinkManager = $container->get('plugin.manager.menu.link');
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration(): array {
+    return [
+      'menu_item' => '',
+      'enabled' => TRUE,
+    ] + parent::defaultConfiguration();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
+    $form['menu_item'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('ID of menu item'),
+      '#default_value' => $this->configuration['menu_item'],
+      '#description' => $this->t('The id of a menu item provided by code (e.g. not a menu_link_content created in the menu UI).'),
+      '#eca_token_replacement' => TRUE,
+      '#required' => TRUE,
+    ];
+    $form['enabled'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Enable'),
+      '#description' => $this->t('Select to have the menu item enabled, or leave unchecked to have it disabled.'),
+      '#default_value' => $this->configuration['enabled'],
+    ];
+
+    return parent::buildConfigurationForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
+    $this->configuration['menu_item'] = $form_state->getValue('menu_item');
+    $this->configuration['enabled'] = !empty($form_state->getValue('enabled'));
+    parent::submitConfigurationForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute(mixed $entity = NULL): void {
+    $menuItemId = (string) $this->tokenService->replace($this->configuration['menu_item']);
+    $definition = $this->menuLinkManager->getDefinition($menuItemId);
+    // Set the 'enabled' value based on the configuration, and save.
+    $definition['enabled'] = ($this->configuration['enabled']) ? 1 : 0;
+    $this->menuLinkManager->updateDefinition($menuItemId, $definition);
+  }
+
+}
-- 
GitLab


From 7d2f97596a37fac9c11474f46acdedd88288a533 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Haas?=
 <21467-jurgenhaas@users.noreply.drupalcode.org>
Date: Fri, 18 Apr 2025 09:45:07 +0000
Subject: [PATCH 09/10] Issue #3519886 by jurgenhaas: ECA Form: set field value
 in ajax calls

---
 modules/form/src/Plugin/Action/FormFieldDefaultValue.php | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/modules/form/src/Plugin/Action/FormFieldDefaultValue.php b/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
index cb25dddea..1f2ea7ab0 100644
--- a/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
+++ b/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
@@ -29,9 +29,12 @@ class FormFieldDefaultValue extends FormFieldActionBase {
    */
   protected function doExecute(): void {
     if ($element = &$this->getTargetElement()) {
+      $form_state = $this->getCurrentFormState();
       $element = &$this->jumpToFirstFieldChild($element);
       $value = $this->configuration['value'];
-      $default_value_key = '#default_value';
+      $default_value_key = $form_state->isRebuilding() ?
+        '#value' :
+        '#default_value';
 
       switch ($element['#type'] ?? NULL) {
 
-- 
GitLab


From a08b9f735ed01bc0fd6c295ea09ed8f777194135 Mon Sep 17 00:00:00 2001
From: jurgenhaas <juergen.haas@lakedrops.com>
Date: Sat, 26 Apr 2025 11:34:58 +0200
Subject: [PATCH 10/10] Issue #3519886 by jurgenhaas, mxh: ECA Form: provide a
 way to set the form field value when submitted via Ajax

---
 modules/form/src/Plugin/Action/FormFieldDefaultValue.php | 5 +----
 modules/form/src/Plugin/Action/FormFieldSetValue.php     | 4 ++++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/modules/form/src/Plugin/Action/FormFieldDefaultValue.php b/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
index 1f2ea7ab0..cb25dddea 100644
--- a/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
+++ b/modules/form/src/Plugin/Action/FormFieldDefaultValue.php
@@ -29,12 +29,9 @@ class FormFieldDefaultValue extends FormFieldActionBase {
    */
   protected function doExecute(): void {
     if ($element = &$this->getTargetElement()) {
-      $form_state = $this->getCurrentFormState();
       $element = &$this->jumpToFirstFieldChild($element);
       $value = $this->configuration['value'];
-      $default_value_key = $form_state->isRebuilding() ?
-        '#value' :
-        '#default_value';
+      $default_value_key = '#default_value';
 
       switch ($element['#type'] ?? NULL) {
 
diff --git a/modules/form/src/Plugin/Action/FormFieldSetValue.php b/modules/form/src/Plugin/Action/FormFieldSetValue.php
index 4b0737965..187620de0 100644
--- a/modules/form/src/Plugin/Action/FormFieldSetValue.php
+++ b/modules/form/src/Plugin/Action/FormFieldSetValue.php
@@ -114,6 +114,10 @@ class FormFieldSetValue extends ConfigurableActionBase {
     }
     $this->filterFormFieldValue($value);
 
+    if ($element = &$this->getTargetElement()) {
+      $element['#value'] = $value;
+    }
+
     $original_field_name = $this->configuration['field_name'];
     $this->configuration['field_name'] = (string) $this->tokenService->replace($original_field_name);
 
-- 
GitLab