From 6e798368453528963fc0420d9c3f57d87387e8fe Mon Sep 17 00:00:00 2001 From: Chris Green <chrisgreen@arizona.edu> Date: Mon, 26 May 2025 14:10:36 -0700 Subject: [PATCH 1/5] Issue #3526657 Extract switcher link logic from ToolbarHandler into new SwitcherManager service --- environment_indicator.module | 26 +------ environment_indicator.services.yml | 6 ++ src/Service/SwitcherManager.php | 109 +++++++++++++++++++++++++++++ src/ToolbarHandler.php | 67 ++++-------------- 4 files changed, 130 insertions(+), 78 deletions(-) create mode 100644 src/Service/SwitcherManager.php diff --git a/environment_indicator.module b/environment_indicator.module index fffb6058..1e60da92 100644 --- a/environment_indicator.module +++ b/environment_indicator.module @@ -126,7 +126,7 @@ function environment_indicator_page_top(array &$page_top) { } // Only add the environment indicator switcher if there are environments to // switch to. - if ($items = _environment_indicator_switcher_links()) { + if ($items = \Drupal::service('environment_indicator.switcher_manager')->getLinks()) { uasort($items, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); $page_top['indicator']['switcher'] = [ '#theme' => 'links', @@ -143,7 +143,7 @@ function environment_indicator_page_top(array &$page_top) { ]; $page_top['indicator'] += [ '#cache' => [ - 'tags' => Cache::mergeTags(['config:environment_indicator.settings'], _environment_indicator_switcher_cache_tags()), + 'tags' => Cache::mergeTags(['config:environment_indicator.settings'], \Drupal::service('environment_indicator.switcher_manager')->getCacheTags()), ], ]; } @@ -225,17 +225,6 @@ function environment_indicator_toolbar() { ->toolbar(); } -/** - * Helper function that generates the environment switcher links. - * - * @return array - * A renderable array with the links. - */ -function _environment_indicator_switcher_links(): array { - return \Drupal::service('environment_indicator.toolbar_handler') - ->getLinks(); -} - /** * Helper function that checks if there is external integration. * @@ -250,17 +239,6 @@ function _environment_indicator_external_integration_is_enabled(string $integrat ->externalIntegration($integration); } -/** - * Get the cache tags for the environment indicator switcher. - * - * @return string[] - * The cache tags. - */ -function _environment_indicator_switcher_cache_tags(): array { - return \Drupal::service('environment_indicator.toolbar_handler') - ->getCacheTags(); -} - /** * Loads an environment indicator in a procedural way. * diff --git a/environment_indicator.services.yml b/environment_indicator.services.yml index 6115b450..7344a74c 100644 --- a/environment_indicator.services.yml +++ b/environment_indicator.services.yml @@ -8,3 +8,9 @@ services: - '@state' - '@settings' - '@entity_type.manager' + - '@environment_indicator.switcher_manager' + environment_indicator.switcher_manager: + class: Drupal\environment_indicator\Service\SwitcherManager + arguments: + - '@entity_type.manager' + - '@current_route_match' diff --git a/src/Service/SwitcherManager.php b/src/Service/SwitcherManager.php new file mode 100644 index 00000000..119199fc --- /dev/null +++ b/src/Service/SwitcherManager.php @@ -0,0 +1,109 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\environment_indicator\Service; + +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Routing\CurrentRouteMatch; +use Drupal\Core\Url; + +/** + * Manages active environment switcher entities and builds UI-ready link data. + * + * This service centralizes logic related to the environment switcher list, + * including filtering active switchers and formatting their metadata as + * render-ready link arrays. It also provides cache tags to support proper + * cache invalidation when switcher configuration changes. + * + * Responsibilities: + * - Load and filter switchers based on status (and eventually permissions). + * - Build renderable links for UI components (e.g., page top, toolbar). + * - Provide cache tags related to switcher listings. + * + * Future enhancements may include: + * - Per-switcher access checks (once fixed in the module). + * - Domain/path/language-aware filtering. + * - Grouping, prioritization, or transformations. + * + * This service intentionally keeps responsibilities simple and centralized. + * If needed, future refactors may extract access filtering, link rendering, + * or entity loading into dedicated services or helpers. + */ +class SwitcherManager { + + /** + * The entity type manager service. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected EntityTypeManagerInterface $entityTypeManager; + + /** + * The current route match service. + * + * @var \Drupal\Core\Routing\CurrentRouteMatch + */ + protected CurrentRouteMatch $routeMatch; + + /** + * Constructs a new SwitcherManager instance. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager + * The entity type manager service. + * @param \Drupal\Core\Routing\CurrentRouteMatch $routeMatch + * The current route match service. + */ + public function __construct(EntityTypeManagerInterface $entityTypeManager, CurrentRouteMatch $routeMatch) { + $this->entityTypeManager = $entityTypeManager; + $this->routeMatch = $routeMatch; + } + + /** + * Builds an array of environment switcher links. + * + * @return array[] + * A render array of link definitions for each active environment. + */ + public function getLinks(): array { + /** @var \Drupal\environment_indicator\Entity\EnvironmentIndicator[] $entities */ + $entities = $this->entityTypeManager->getStorage('environment_indicator')->loadMultiple(); + + $current_path = Url::fromRoute('<current>')->toString(); + + $links = []; + foreach ($entities as $entity) { + if (!$entity->status() || empty($entity->getUrl())) { + continue; + } + + $links[] = [ + 'attributes' => [ + 'style' => sprintf('color: %s; background-color: %s;', $entity->getFgColor(), $entity->getBgColor()), + 'title' => t('Opens the current page in the selected environment.'), + ], + 'title' => t('Open on @label', ['@label' => $entity->label()]), + 'url' => Url::fromUri($entity->getUrl() . $current_path), + 'type' => 'link', + 'weight' => $entity->getWeight(), + ]; + } + + uasort($links, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']); + + return $links; + } + + /** + * Returns cache tags related to the switcher list. + * + * @return string[] + * An array of cache tags. + */ + public function getCacheTags(): array { + return $this->entityTypeManager + ->getDefinition('environment_indicator') + ->getListCacheTags(); + } + +} diff --git a/src/ToolbarHandler.php b/src/ToolbarHandler.php index 10b1b8ce..29bb9dbf 100644 --- a/src/ToolbarHandler.php +++ b/src/ToolbarHandler.php @@ -12,7 +12,7 @@ use Drupal\Core\Site\Settings; use Drupal\Core\State\StateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; -use Drupal\environment_indicator\Entity\EnvironmentIndicator; +use Drupal\environment_indicator\Service\SwitcherManager; /** * Toolbar integration handler. @@ -70,6 +70,13 @@ class ToolbarHandler { */ protected EntityTypeManagerInterface $entityTypeManager; + /** + * The SwitcherManager service. + * + * @var \Drupal\environment_indicator\Service\SwitcherManager + */ + protected SwitcherManager $switcherManager; + /** * ToolbarHandler constructor. * @@ -85,6 +92,8 @@ class ToolbarHandler { * The settings. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. + * @param \Drupal\environment_indicator\Service\Service\SwitcherManager $switcher_manager + * The switcher manager service. */ public function __construct( ModuleHandlerInterface $module_handler, @@ -93,6 +102,7 @@ class ToolbarHandler { StateInterface $state, Settings $settings, EntityTypeManagerInterface $entity_type_manager, + SwitcherManager $switcher_manager, ) { $this->moduleHandler = $module_handler; $this->config = $config_factory->get('environment_indicator.settings'); @@ -101,6 +111,7 @@ class ToolbarHandler { $this->state = $state; $this->settings = $settings; $this->entityTypeManager = $entity_type_manager; + $this->switcherManager = $switcher_manager; } /** @@ -206,7 +217,7 @@ class ToolbarHandler { ]; } - if ($links = $this->getLinks()) { + if ($links = $this->switcherManager->getLinks()) { $items['environment_indicator']['tray']['environment_links'] = [ '#theme' => 'links__toolbar_shortcuts', '#links' => $links, @@ -316,56 +327,4 @@ class ToolbarHandler { return $this->entityTypeManager->getDefinition('environment_indicator')->getListCacheTags(); } - /** - * Get all the links for the switcher. - * - * @return array - * Returns all the links. - */ - public function getLinks(): array { - if (!$environment_entities = EnvironmentIndicator::loadMultiple()) { - return []; - } - - $current = Url::fromRoute('<current>'); - $current_path = $current->toString(); - $url = parse_url($current_path); - $path = $url['path']; - if (isset($url['query'])) { - $path .= '?' . $url['query']; - } - $environment_entities = array_filter( - $environment_entities, - function (EnvironmentIndicator $entity) { - return $entity->status() - && !empty($entity->getUrl()) - && $this->hasAccessEnvironment($entity->id()); - } - ); - - $links = array_map( - function (EnvironmentIndicator $entity) use ($path) { - return [ - 'attributes' => [ - 'style' => 'color: ' . $entity->getFgColor() . '; background-color: ' . $entity->getBgColor() . ';', - 'title' => $this->t('Opens the current page in the selected environment.'), - ], - 'title' => $this->t('Open on @label', ['@label' => $entity->label()]), - 'url' => Url::fromUri($entity->getUrl() . $path), - 'type' => 'link', - 'weight' => $entity->getWeight(), - ]; - }, - $environment_entities - ); - - if (!$links) { - return []; - } - - uasort($links, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); - - return $links; - } - } -- GitLab From d9d98cc4bbf1e8d59e75dc4ba47cc01361650735 Mon Sep 17 00:00:00 2001 From: Arun Sahijpal <69732-arunsahijpal@users.noreply.drupalcode.org> Date: Wed, 7 May 2025 22:33:41 +0000 Subject: [PATCH 2/5] Updates --- environment_indicator.module | 1 - 1 file changed, 1 deletion(-) diff --git a/environment_indicator.module b/environment_indicator.module index 1e60da92..f1f8bca2 100644 --- a/environment_indicator.module +++ b/environment_indicator.module @@ -127,7 +127,6 @@ function environment_indicator_page_top(array &$page_top) { // Only add the environment indicator switcher if there are environments to // switch to. if ($items = \Drupal::service('environment_indicator.switcher_manager')->getLinks()) { - uasort($items, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); $page_top['indicator']['switcher'] = [ '#theme' => 'links', '#links' => $items, -- GitLab From 6bfa7790f5a487ba6442353a8d662174095896b1 Mon Sep 17 00:00:00 2001 From: Chris Green <chrisgreen@arizona.edu> Date: Tue, 27 May 2025 17:17:59 -0700 Subject: [PATCH 3/5] Add back getLinks --- src/ToolbarHandler.php | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/ToolbarHandler.php b/src/ToolbarHandler.php index 29bb9dbf..286f16d2 100644 --- a/src/ToolbarHandler.php +++ b/src/ToolbarHandler.php @@ -317,6 +317,58 @@ class ToolbarHandler { return FALSE; } + /** + * Get all the links for the switcher. + * + * @return array + * Returns all the links. + */ + public function getLinks(): array { + if (!$environment_entities = EnvironmentIndicator::loadMultiple()) { + return []; + } + + $current = Url::fromRoute('<current>'); + $current_path = $current->toString(); + $url = parse_url($current_path); + $path = $url['path']; + if (isset($url['query'])) { + $path .= '?' . $url['query']; + } + $environment_entities = array_filter( + $environment_entities, + function (EnvironmentIndicator $entity) { + return $entity->status() + && !empty($entity->getUrl()) + && $this->hasAccessEnvironment($entity->id()); + } + ); + + $links = array_map( + function (EnvironmentIndicator $entity) use ($path) { + return [ + 'attributes' => [ + 'style' => 'color: ' . $entity->getFgColor() . '; background-color: ' . $entity->getBgColor() . ';', + 'title' => $this->t('Opens the current page in the selected environment.'), + ], + 'title' => $this->t('Open on @label', ['@label' => $entity->label()]), + 'url' => Url::fromUri($entity->getUrl() . $path), + 'type' => 'link', + 'weight' => $entity->getWeight(), + ]; + }, + $environment_entities + ); + + if (!$links) { + return []; + } + + uasort($links, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); + + return $links; + } + /** * Get the cache tags for the environment indicator switcher. * -- GitLab From a466986565162bf90d233465761a105827251c59 Mon Sep 17 00:00:00 2001 From: Chris Green <chrisgreen@arizona.edu> Date: Tue, 27 May 2025 17:34:06 -0700 Subject: [PATCH 4/5] Updates --- environment_indicator.module | 34 ++++++++++++++++++++++++++++++++++ src/ToolbarHandler.php | 32 ++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/environment_indicator.module b/environment_indicator.module index f1f8bca2..b42eb38e 100644 --- a/environment_indicator.module +++ b/environment_indicator.module @@ -224,6 +224,40 @@ function environment_indicator_toolbar() { ->toolbar(); } +/** + * Helper function that generates the environment switcher links. + * + * @return array + * A renderable array with the links. + * + * @deprecated in environment_indicator:4.0.22 and is removed from environment_indicator:5.0.0. + * Use + * \Drupal::service('environment_indicator.switcher_manager')->getLinks() + * instead. + * @see https://www.drupal.org/node/3526893 + */ +function _environment_indicator_switcher_links(): array { + return \Drupal::service('environment_indicator.toolbar_handler') + ->getLinks(); +} + +/** + * Get the cache tags for the environment indicator switcher. + * + * @return string[] + * The cache tags. + * + * @deprecated in environment_indicator:4.0.22 and is removed from environment_indicator:5.0.0. + * Use + * \Drupal::service('environment_indicator.switcher_manager')->getLinks() + * instead. + * @see https://www.drupal.org/node/3526893 + */ +function _environment_indicator_switcher_cache_tags(): array { + return \Drupal::service('environment_indicator.toolbar_handler') + ->getCacheTags(); +} + /** * Helper function that checks if there is external integration. * diff --git a/src/ToolbarHandler.php b/src/ToolbarHandler.php index 286f16d2..b430e6ef 100644 --- a/src/ToolbarHandler.php +++ b/src/ToolbarHandler.php @@ -317,11 +317,33 @@ class ToolbarHandler { return FALSE; } + /** + * Get the cache tags for the environment indicator switcher. + * + * @return array + * The cache tags. + * + * @deprecated in environment_indicator:4.0.22 and is removed from environment_indicator:5.0.0. + * Use + * \Drupal::service('environment_indicator.switcher_manager')->getCacheTags() + * instead. + * @see https://www.drupal.org/node/3526893 + */ + public function getCacheTags(): array { + return $this->entityTypeManager->getDefinition('environment_indicator')->getListCacheTags(); + } + /** * Get all the links for the switcher. * * @return array * Returns all the links. + * + * @deprecated in environment_indicator:4.0.22 and is removed from environment_indicator:5.0.0. + * Use + * \Drupal::service('environment_indicator.switcher_manager')->getLinks() + * instead. + * @see https://www.drupal.org/node/3526893 */ public function getLinks(): array { if (!$environment_entities = EnvironmentIndicator::loadMultiple()) { @@ -369,14 +391,4 @@ class ToolbarHandler { return $links; } - /** - * Get the cache tags for the environment indicator switcher. - * - * @return array - * The cache tags. - */ - public function getCacheTags(): array { - return $this->entityTypeManager->getDefinition('environment_indicator')->getListCacheTags(); - } - } -- GitLab From a0a00f4c8c27a53b3bc16b6c4faf8659d91a533a Mon Sep 17 00:00:00 2001 From: Chris Green <chrisgreen@arizona.edu> Date: Tue, 27 May 2025 17:35:59 -0700 Subject: [PATCH 5/5] Updates --- environment_indicator.module | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/environment_indicator.module b/environment_indicator.module index b42eb38e..2c33584f 100644 --- a/environment_indicator.module +++ b/environment_indicator.module @@ -241,6 +241,20 @@ function _environment_indicator_switcher_links(): array { ->getLinks(); } +/** + * Helper function that checks if there is external integration. + * + * @param string $integration + * Name of the integration: toolbar, admin_menu, ... + * + * @return bool + * TRUE if integration is enabled. FALSE otherwise. + */ +function _environment_indicator_external_integration_is_enabled(string $integration): bool { + return \Drupal::service('environment_indicator.toolbar_handler') + ->externalIntegration($integration); +} + /** * Get the cache tags for the environment indicator switcher. * @@ -258,20 +272,6 @@ function _environment_indicator_switcher_cache_tags(): array { ->getCacheTags(); } -/** - * Helper function that checks if there is external integration. - * - * @param string $integration - * Name of the integration: toolbar, admin_menu, ... - * - * @return bool - * TRUE if integration is enabled. FALSE otherwise. - */ -function _environment_indicator_external_integration_is_enabled(string $integration): bool { - return \Drupal::service('environment_indicator.toolbar_handler') - ->externalIntegration($integration); -} - /** * Loads an environment indicator in a procedural way. * -- GitLab