diff --git a/rename_admin_paths.install b/rename_admin_paths.install new file mode 100644 index 0000000000000000000000000000000000000000..962d4f34d56b143f35049638424e81ab5ddfe7a1 --- /dev/null +++ b/rename_admin_paths.install @@ -0,0 +1,48 @@ +<?php + +/** + * @file + * Provides the uninstall hook for the Rename Admin Paths module. + */ + +declare(strict_types=1); + +use Drupal\views\Entity\View; + +/** + * Implements hook_uninstall(). + * + * Reverts custom admin paths in views back to 'admin' on module uninstall. + */ +function rename_admin_paths_uninstall(): void { + // Load the config to get the current custom admin path. + $config = \Drupal::config('rename_admin_paths.settings'); + $custom_admin_path = $config->get('admin_path_value') ?? 'admin'; + + // Load all views. + $views = View::loadMultiple(); + + foreach ($views as $view) { + $executable = $view->getExecutable(); + + foreach ($view->get('display') as $display_id => $display) { + if (isset($display['display_options']['path']) && $display['display_options']['path'] !== '') { + $current_path = $display['display_options']['path']; + + // If the path starts with the custom prefix, revert it back to 'admin'. + if (str_starts_with($current_path, $custom_admin_path . '/')) { + $new_path = str_replace($custom_admin_path, 'admin', $current_path); + + $executable->setDisplay($display_id); + $executable->display_handler->setOption('path', $new_path); + } + } + } + + // Save the updated view. + $view->save(); + } + + // Clear the render cache to reflect the changes. + \Drupal::service('cache_tags.invalidator')->invalidateTags(['rendered']); +} diff --git a/src/Form/RenameAdminPathsSettingsForm.php b/src/Form/RenameAdminPathsSettingsForm.php index e43becab80ff4e2175ad1ab9fdaa2e8ec44cd89b..e9e09501abd208b7b6096f01487782ce3d07f7a5 100644 --- a/src/Form/RenameAdminPathsSettingsForm.php +++ b/src/Form/RenameAdminPathsSettingsForm.php @@ -13,6 +13,8 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\rename_admin_paths\Config; use Drupal\rename_admin_paths\EventSubscriber\RenameAdminPathsEventSubscriber; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\views\Entity\View; +use Drupal\Core\Cache\CacheBackendInterface; /** * Settings form for the Rename Admin Paths module. @@ -26,6 +28,7 @@ final class RenameAdminPathsSettingsForm extends ConfigFormBase { TypedConfigManagerInterface $typed_config_manager, private readonly Config $config, private readonly RouteBuilderInterface $routeBuilder, + private readonly CacheBackendInterface $cache, ) { parent::__construct($config_factory, $typed_config_manager); } @@ -40,6 +43,7 @@ final class RenameAdminPathsSettingsForm extends ConfigFormBase { $container->get('config.typed'), $container->get(Config::class), $container->get('router.builder'), + $container->get('cache.default'), ); } @@ -126,8 +130,7 @@ final class RenameAdminPathsSettingsForm extends ConfigFormBase { * The form state. */ public function validate(array &$element, FormStateInterface $formState): void { - // @phpstan-ignore-next-line Permit this use of empty. - if (empty($element['#value'])) { + if ($element['#value'] === '' || $element['#value'] === NULL) { $formState->setError( $element, $this->t('Path replacement value must contain a value.') @@ -157,10 +160,21 @@ final class RenameAdminPathsSettingsForm extends ConfigFormBase { #[\Override] public function submitForm(array &$form, FormStateInterface $form_state): void { $this->saveConfiguration($form_state); + $dynamic_prefix = $form_state->getValue('admin_path_value'); // At this stage we rebuild all routes to use the new renamed paths. $this->routeBuilder->rebuild(); + // Check if the admin path has been disabled (unchecked). + if ((bool) $form_state->getValue('admin_path') === FALSE) { + // If the path is disabled, revert the views' paths to the original ones. + $this->updateOrRevertViewPaths($dynamic_prefix, TRUE); + } + else { + // If enabled, update the views' paths to reflect the new value. + $this->updateOrRevertViewPaths($dynamic_prefix, FALSE); + } + // Add confirmation message. parent::submitForm($form, $form_state); @@ -188,4 +202,56 @@ final class RenameAdminPathsSettingsForm extends ConfigFormBase { $this->config->save(); } + /** + * Updates or reverts the view paths based on the given flag. + * + * @param string $dynamic_prefix + * The dynamic prefix (e.g., 'backend') to use in the path. + * @param bool $revert + * If TRUE, reverts paths from the dynamic prefix to 'admin'. + * If FALSE, updates paths from 'admin' to the dynamic prefix. + */ + private function updateOrRevertViewPaths(string $dynamic_prefix, bool $revert = FALSE): void { + // Load all views. + $views = View::loadMultiple(); + + // Iterate through all the views. + foreach ($views as $view) { + // Get the executable view object. + $executable = $view->getExecutable(); + + // Loop through all displays in the view. + foreach ($view->get('display') as $display_id => $display) { + // Check if the display has a path. + if (isset($display['display_options']['path'])) { + $current_path = $display['display_options']['path']; + + // Modify the path based on whether we're updating or reverting. + if ($revert && strpos($current_path, $dynamic_prefix . '/') === 0) { + // Revert the dynamic prefix to 'admin'. + $new_path = str_replace($dynamic_prefix, 'admin', $current_path); + } + elseif (!$revert && strpos($current_path, 'admin/') === 0) { + // Update 'admin' to the dynamic prefix. + $new_path = str_replace('admin', $dynamic_prefix, $current_path); + } + else { + // Skip if no change is needed. + continue; + } + + // Set the display and update the path. + $executable->setDisplay($display_id); + $executable->display_handler->setOption('path', $new_path); + } + } + + // Save the updated view. + $view->save(); + } + + // Optionally clear the cache to ensure the changes are reflected. + $this->cache->deleteAll(); + } + } diff --git a/tests/src/Functional/AdminFormTest.php b/tests/src/Functional/AdminFormTest.php index 4e7ccc32716d541a682ba8267f397c6dbde71e46..3475d24547de178f84622a6cca29640bbe0ea9ec 100644 --- a/tests/src/Functional/AdminFormTest.php +++ b/tests/src/Functional/AdminFormTest.php @@ -21,7 +21,7 @@ class AdminFormTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected static $modules = ['rename_admin_paths']; + protected static $modules = ['views', 'rename_admin_paths']; /** * Setup admin user. diff --git a/tests/src/Unit/Form/RenameAdminPathsSettingsFormTest.php b/tests/src/Unit/Form/RenameAdminPathsSettingsFormTest.php index 25d151f169369f0888f98144a5f7369b28114b2e..f7c2cf04c25f7248975e89885502c77933a44ae8 100644 --- a/tests/src/Unit/Form/RenameAdminPathsSettingsFormTest.php +++ b/tests/src/Unit/Form/RenameAdminPathsSettingsFormTest.php @@ -13,6 +13,7 @@ use Drupal\rename_admin_paths\Config; use Drupal\rename_admin_paths\Form\RenameAdminPathsSettingsForm; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Drupal\Core\Cache\CacheBackendInterface; /** * Tests the behavior of the module settings form. @@ -27,7 +28,7 @@ class RenameAdminPathsSettingsFormTest extends UnitTestCase { * Test when an invalid value is provided. */ public function testValidatePathWithoutValue(): void { - $element = []; + $element = ['#value' => '']; $this->getForm()->validate($element, $this->getInvalidFormState()); } @@ -107,8 +108,10 @@ class RenameAdminPathsSettingsFormTest extends UnitTestCase { $routeBuilder = $this->createMock(RouteBuilderInterface::class); + $cache = $this->createMock(CacheBackendInterface::class); + $settings_form = new RenameAdminPathsSettingsForm( - $config_factory, $typed_config_manager, $config, $routeBuilder, + $config_factory, $typed_config_manager, $config, $routeBuilder, $cache ); // Inject StringTranslationTrait. $settings_form->setStringTranslation($this->getStringTranslationStub());