commit dc9364b0e725638c131aed440d6d4d1d30016d1a
parent 2b375b2c3e93ff2db2dfee226b16f407ebf8154b
Author: Florian Dold <florian@dold.me>
Date: Tue, 9 Dec 2025 12:13:29 +0100
ensure node fields are added/removed when config is changed
Previously, the field types were updated in the TurnstileSettingsForm.
When the config was changed using drush instead of the Website, this led
to an inconsistent state between the config and the actual node field
types.
We fix this issue by instead modifying the field types in an
event listener that is called when the config is saved.
Diffstat:
3 files changed, 181 insertions(+), 71 deletions(-)
diff --git a/src/EventSubscriber/TurnstileConfigSubscriber.php b/src/EventSubscriber/TurnstileConfigSubscriber.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+ * Location: src/EventSubscriber/TurnstileConfigSubscriber.php
+ *
+ * Subscriber for turnstile config changes.
+ */
+
+namespace Drupal\taler_turnstile\EventSubscriber;
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\taler_turnstile\TurnstileFieldManager;
+use Drupal\Core\Messenger\MessengerInterface;
+
+class TurnstileConfigSubscriber implements EventSubscriberInterface {
+
+ // This provides the $this->t() method.
+ use StringTranslationTrait;
+
+ /**
+ * The entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * The Turnstile field manager.
+ *
+ * @var \Drupal\taler_turnstile\TurnstileFieldManager
+ */
+ protected $fieldManager;
+
+
+ /**
+ * The messenger service.
+ *
+ * @var \Drupal\Core\Messenger\MessengerInterface
+ */
+ protected $messenger;
+
+ /**
+ * Constructs a TurnstileSettingsForm object.
+ *
+ * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+ * The factory for configuration objects.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+ * The entity type manager.
+ * @param \Drupal\taler_turnstile\TurnstileFieldManager $field_manager
+ * The field manager.
+ * @param \Drupal\taler_turnstile\TalerMerchantApiService $api_service
+ * The API service.
+ */
+ public function __construct(TranslationInterface $string_translation,
+ MessengerInterface $messenger,
+ EntityTypeManagerInterface $entity_type_manager,
+ TurnstileFieldManager $field_manager) {
+ $this->stringTranslation = $string_translation;
+ $this->messenger = $messenger;
+ $this->entityTypeManager = $entity_type_manager;
+ $this->fieldManager = $field_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents() {
+ // Listen for the configuration save event.
+ $events[ConfigEvents::SAVE][] = ['onConfigSave'];
+ return $events;
+ }
+
+ /**
+ * React to configuration changes.
+ *
+ * @param \Drupal\Core\Config\ConfigCrudEvent $event
+ * The configuration event.
+ */
+ public function onConfigSave(ConfigCrudEvent $event) {
+ $config = $event->getConfig();
+ if ($config->getName() !== 'taler_turnstile.settings') {
+ return;
+ }
+ if ($event->isChanged('enabled_content_types')) {
+
+ $old_enabled_types = $config->getOriginal('enabled_content_types');
+ $new_enabled_types = $config->get('enabled_content_types');
+
+ // Find content types to add and remove.
+ $types_to_add = array_diff($new_enabled_types, $old_enabled_types);
+ $types_to_remove = array_diff($old_enabled_types, $new_enabled_types);
+
+ // Add fields to newly enabled content types.
+ if (!empty($types_to_add)) {
+ $this->fieldManager->addFieldsToContentTypes($types_to_add);
+ }
+
+ // Remove fields from disabled content types.
+ if (!empty($types_to_remove)) {
+ $this->fieldManager->removeFieldsFromContentTypes($types_to_remove);
+ }
+ if (empty($new_enabled_types)) {
+ $this->fieldManager->cleanupFieldStorage();
+ }
+ // Display summary of changes.
+ if (!empty($types_to_add) || !empty($types_to_remove)) {
+ $this->displayFieldChanges($types_to_add, $types_to_remove);
+ }
+ \Drupal::logger('taler_turnstile')->info('Turnstile content types changed from @old to @new.', [
+ '@old' => json_encode($old_enabled_types),
+ '@new' => json_encode($new_enabled_types),
+ ]);
+ }
+ }
+
+ /**
+ * Display messages about field changes.
+ *
+ * @param array $types_added
+ * Content types that had fields added.
+ * @param array $types_removed
+ * Content types that had fields removed.
+ */
+ protected function displayFieldChanges(array $types_added, array $types_removed) {
+ $content_types = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
+
+ if (!empty($types_added)) {
+ $added_labels = [];
+ foreach ($types_added as $type) {
+ if (isset($content_types[$type])) {
+ $added_labels[] = $content_types[$type]->label();
+ }
+ }
+ if (!empty($added_labels)) {
+ $this->messenger->addStatus(
+ $this->t('Price category fields added to: @types', [
+ '@types' => implode(', ', $added_labels),
+ ])
+ );
+ }
+ }
+
+ if (!empty($types_removed)) {
+ $removed_labels = [];
+ foreach ($types_removed as $type) {
+ if (isset($content_types[$type])) {
+ $removed_labels[] = $content_types[$type]->label();
+ }
+ }
+ if (!empty($removed_labels)) {
+ $this->messenger->addStatus(
+ $this->t('Price category fields removed from: @types', [
+ '@types' => implode(', ', $removed_labels),
+ ])
+ );
+ }
+ }
+ }
+}
diff --git a/src/Form/TurnstileSettingsForm.php b/src/Form/TurnstileSettingsForm.php
@@ -158,7 +158,7 @@ class TurnstileSettingsForm extends ConfigFormBase {
return;
}
- $http_status = $this->apiService->checkAccess ($payment_backend_url, $access_token);
+ $http_status = $this->apiService->checkAccess($payment_backend_url, $access_token);
switch ($http_status) {
case 502:
$form_state->setErrorByName('payment_backend_url',
@@ -225,23 +225,6 @@ class TurnstileSettingsForm extends ConfigFormBase {
$new_enabled_types = array_filter($form_state->getValue('enabled_content_types'));
$new_enabled_types = array_values($new_enabled_types);
- // Find content types to add and remove.
- $types_to_add = array_diff($new_enabled_types, $old_enabled_types);
- $types_to_remove = array_diff($old_enabled_types, $new_enabled_types);
-
- // Add fields to newly enabled content types.
- if (!empty($types_to_add)) {
- $this->fieldManager->addFieldsToContentTypes($types_to_add);
- }
-
- // Remove fields from disabled content types.
- if (!empty($types_to_remove)) {
- $this->fieldManager->removeFieldsFromContentTypes($types_to_remove);
- }
- if (empty($new_enabled_types)) {
- $this->fieldManager->cleanupFieldStorage();
- }
-
$grant_access_on_error = $form_state->getValue('grant_access_on_error');
// Save configuration.
@@ -252,55 +235,5 @@ class TurnstileSettingsForm extends ConfigFormBase {
$config->save();
parent::submitForm($form, $form_state);
-
- // Display summary of changes.
- if (!empty($types_to_add) || !empty($types_to_remove)) {
- $this->displayFieldChanges($types_to_add, $types_to_remove);
- }
}
-
- /**
- * Display messages about field changes.
- *
- * @param array $types_added
- * Content types that had fields added.
- * @param array $types_removed
- * Content types that had fields removed.
- */
- protected function displayFieldChanges(array $types_added, array $types_removed) {
- $content_types = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
-
- if (!empty($types_added)) {
- $added_labels = [];
- foreach ($types_added as $type) {
- if (isset($content_types[$type])) {
- $added_labels[] = $content_types[$type]->label();
- }
- }
- if (!empty($added_labels)) {
- $this->messenger()->addStatus(
- $this->t('Price category fields added to: @types', [
- '@types' => implode(', ', $added_labels),
- ])
- );
- }
- }
-
- if (!empty($types_removed)) {
- $removed_labels = [];
- foreach ($types_removed as $type) {
- if (isset($content_types[$type])) {
- $removed_labels[] = $content_types[$type]->label();
- }
- }
- if (!empty($removed_labels)) {
- $this->messenger()->addStatus(
- $this->t('Price category fields removed from: @types', [
- '@types' => implode(', ', $removed_labels),
- ])
- );
- }
- }
- }
-
}
\ No newline at end of file
diff --git a/taler_turnstile.services.yml b/taler_turnstile.services.yml
@@ -1,12 +1,24 @@
services:
taler_turnstile.api_service:
class: Drupal\taler_turnstile\TalerMerchantApiService
- arguments: ['@http_client_factory', '@logger.channel.taler_turnstile']
+ arguments: ["@http_client_factory", "@logger.channel.taler_turnstile"]
taler_turnstile.field_manager:
class: Drupal\taler_turnstile\TurnstileFieldManager
- arguments: ['@entity_type.manager']
+ arguments: ["@entity_type.manager"]
logger.channel.taler_turnstile:
parent: logger.channel_base
- arguments: ['taler-turnstile']
+ arguments: ["taler-turnstile"]
+
+ taler_turnstile.config_subscriber:
+ class: Drupal\taler_turnstile\EventSubscriber\TurnstileConfigSubscriber
+ arguments:
+ [
+ "@string_translation",
+ "@messenger",
+ "@entity_type.manager",
+ "@taler_turnstile.field_manager",
+ ]
+ tags:
+ - { name: event_subscriber }