diff --git a/modules/geocoder_field/geocoder_field.module b/modules/geocoder_field/geocoder_field.module index 0231fcddc5716ea426df0a22aac16e167fa4dc16..f144e26512ca85ef319886650c5e2fd7e94a9663 100644 --- a/modules/geocoder_field/geocoder_field.module +++ b/modules/geocoder_field/geocoder_field.module @@ -163,9 +163,14 @@ function geocoder_field_entity_presave(EntityInterface $entity) { return; } + // Skip any action if requested. $geocoder_config = \Drupal::configFactory()->get('geocoder.settings'); - // Check geocoder_presave_disabled setting and do nothing if enabled. - if ($geocoder_config->get('geocoder_presave_disabled')) { + $config_disabled = $geocoder_config->get('geocoder_presave_disabled'); + // Check if geocoder presave is disabled at runtime by a request attribute. + // i.e. via WorkspacePublishingSubscriber + // (@see https://www.drupal.org/i/3301512) + $runtime_disabled = \Drupal::request()->attributes->get('geocoder_presave_disabled', FALSE); + if ($config_disabled || $runtime_disabled) { return; } diff --git a/modules/geocoder_field/geocoder_field.services.yml b/modules/geocoder_field/geocoder_field.services.yml index 1bcd1c0dced23b95f73dea2252cccfed3d869172..98767805053dd91e6b96ef27494acc5701bf8f46 100644 --- a/modules/geocoder_field/geocoder_field.services.yml +++ b/modules/geocoder_field/geocoder_field.services.yml @@ -9,3 +9,9 @@ services: class: Drupal\geocoder_field\PreprocessorPluginManager parent: default_plugin_manager arguments: ["@country_manager"] + + geocoder_field.workspace_publishing_subscriber: + class: Drupal\geocoder_field\EventSubscriber\WorkspacePublishingSubscriber + arguments: ['@request_stack'] + tags: + - { name: event_subscriber } diff --git a/modules/geocoder_field/src/EventSubscriber/WorkspacePublishingSubscriber.php b/modules/geocoder_field/src/EventSubscriber/WorkspacePublishingSubscriber.php new file mode 100644 index 0000000000000000000000000000000000000000..460ff3fe127f8e9575af4687e085c100ca5593b9 --- /dev/null +++ b/modules/geocoder_field/src/EventSubscriber/WorkspacePublishingSubscriber.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\geocoder_field\EventSubscriber; + +use Drupal\workspaces\Event\WorkspacePostPublishEvent; +use Drupal\workspaces\Event\WorkspacePrePublishEvent; +use Drupal\workspaces\Event\WorkspacePublishEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\RequestStack; + +/** + * Event subscriber to respond to workspace publishing events. + * + * The geocoding operations from geocoder_field_entity_presave() can be very + * expensive when updating many entities at once. Workspace publishing doesn't + * change any field data, it only re-saves the latest workspace-specific + * revision and sets it as the default one, so there is no need to update + * geocoding data. + * + * @see geocoder_field_entity_presave() + */ +class WorkspacePublishingSubscriber implements EventSubscriberInterface { + + public function __construct( + protected RequestStack $requestStack, + ) {} + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array { + if (!class_exists(WorkspacePublishEvent::class)) { + return []; + } + + return [ + WorkspacePrePublishEvent::class => ['onPrePublish'], + WorkspacePostPublishEvent::class => ['onPostPublish'], + ]; + } + + /** + * Adds a custom request attribute to prevent geocoding updates. + */ + public function onPrePublish(): void { + if ($request = $this->requestStack->getCurrentRequest()) { + $request->attributes->set('geocoder_presave_disabled', TRUE); + } + } + + /** + * Removes the custom request attribute. + */ + public function onPostPublish(): void { + if ($request = $this->requestStack->getCurrentRequest()) { + $request->attributes->remove('geocoder_presave_disabled'); + } + } + +}