From 69986883e69585b89d11510fa1db2aa7fc6f457f Mon Sep 17 00:00:00 2001 From: Andrei Mateescu <2117-amateescu@users.noreply.drupalcode.org> Date: Mon, 9 Dec 2024 22:15:43 +0000 Subject: [PATCH] Issue #3301512 by amateescu, itamair, kiseleva.t, s_leu, alecsmrekar, plach: Extend the ability to skip geocoding when processing a large number of entity updates, like migrations or workspace publishing --- modules/geocoder_field/geocoder_field.module | 9 ++- .../geocoder_field.services.yml | 6 ++ .../WorkspacePublishingSubscriber.php | 62 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 modules/geocoder_field/src/EventSubscriber/WorkspacePublishingSubscriber.php diff --git a/modules/geocoder_field/geocoder_field.module b/modules/geocoder_field/geocoder_field.module index 0231fcd..f144e26 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 1bcd1c0..9876780 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 0000000..460ff3f --- /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'); + } + } + +} -- GitLab