diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index a2a754f..7dedbf6 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -284,6 +284,9 @@ public function install(array $module_list, $enable_dependencies = TRUE) { // @see https://www.drupal.org/node/2208429 \Drupal::service('theme_handler')->refreshInfo(); + // In order to make uninstalling transactional if anything uses routes. + \Drupal::service('router.route_provider')->rebuildRoutesIfUsed(); + // Allow the module to perform install tasks. $this->moduleHandler->invoke($module, 'install'); @@ -388,6 +391,9 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { // Remove all configuration belonging to the module. \Drupal::service('config.manager')->uninstall('module', $module); + // In order to make uninstalling transactional if anything uses routes. + \Drupal::service('router.route_provider')->rebuildRoutesIfUsed(); + // Notify interested components that this module's entity types are being // deleted. For example, a SQL-based storage handler can use this as an // opportunity to drop the corresponding database tables. diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php index be647e1..bba9d71 100644 --- a/core/lib/Drupal/Core/Routing/RouteProvider.php +++ b/core/lib/Drupal/Core/Routing/RouteProvider.php @@ -90,6 +90,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv protected $pathProcessor; /** + * Something ugly. + * + * @var bool + */ + protected $rebuildRoutesIfUsed = FALSE; + + /** * Cache ID prefix used to load routes. */ const ROUTE_LOAD_CID_PREFIX = 'route_provider.route_load:'; @@ -210,6 +217,7 @@ public function preLoadRoutes($names) { $routes = $cache->data; } else { + $this->checkAndRebuildRoutes(); try { $result = $this->connection->query('SELECT name, route FROM {' . $this->connection->escapeTable($this->tableName) . '} WHERE name IN ( :names[] )', array(':names[]' => $routes_to_load)); } @@ -338,6 +346,8 @@ protected function getRoutesByPath($path) { return $collection; } + $this->checkAndRebuildRoutes(); + // The >= check on number_parts allows us to match routes with optional // trailing wildcard parts as long as the pattern matches, since we // dump the route pattern without those optional parts. @@ -387,6 +397,7 @@ public function reset() { $this->routes = array(); $this->serializedRoutes = array(); $this->cacheTagInvalidator->invalidateTags(['routes']); + $this->rebuildRoutesIfUsed = FALSE; } /** @@ -401,6 +412,7 @@ static function getSubscribedEvents() { * {@inheritdoc} */ public function getRoutesPaged($offset, $length = NULL) { + $this->checkAndRebuildRoutes(); $select = $this->connection->select($this->tableName, 'router') ->fields('router', ['name', 'route']); @@ -425,4 +437,22 @@ public function getRoutesCount() { return $this->connection->query("SELECT COUNT(*) FROM {" . $this->connection->escapeTable($this->tableName) . "}")->fetchField(); } + /** + * Checks if the rebuildRoutesIfUsed is set and rebuilds the routes. + */ + protected function checkAndRebuildRoutes() { + if ($this->rebuildRoutesIfUsed) { + \Drupal::service('router.builder')->rebuild(); + } + } + + /** + * Causes the first use of the route provider to rebuild routes. + */ + public function rebuildRoutesIfUsed() { + $this->rebuildRoutesIfUsed = TRUE; + // Do not return $this because this method is not supposed to be nice to + // use. + } + } diff --git a/core/modules/content_translation/content_translation.install b/core/modules/content_translation/content_translation.install index 8465fe3..0f8a184 100644 --- a/core/modules/content_translation/content_translation.install +++ b/core/modules/content_translation/content_translation.install @@ -5,6 +5,8 @@ * Installation functions for Content Translation module. */ +use \Drupal\Core\Url; + /** * Implements hook_install(). */ @@ -12,6 +14,21 @@ function content_translation_install() { // Assign a fairly low weight to ensure our implementation of // hook_module_implements_alter() is run among the last ones. module_set_weight('content_translation', 10); + + // Translation works when at least two languages are added. + if (count(\Drupal::languageManager()->getLanguages()) < 2) { + $t_args = [ + ':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString() + ]; + $message = t('This site has only a single language enabled. Add at least one more language in order to translate content.', $t_args); + drupal_set_message($message, 'warning'); + } + // Point the user to the content translation settings. + $t_args = [ + ':settings_url' => Url::fromRoute('language.content_settings_page')->toString() + ]; + $message = t('Enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args); + drupal_set_message($message, 'warning'); } /** diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index f70e4ca..083fc4c 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -14,7 +14,6 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; -use Drupal\Core\Url; /** * Implements hook_help(). @@ -50,28 +49,6 @@ function content_translation_help($route_name, RouteMatchInterface $route_match) } /** - * Implements hook_modules_installed(). - */ -function content_translation_modules_installed(array $modules) { - if (in_array('content_translation', $modules)) { - // Translation works when at least two languages are added. - if (count(\Drupal::languageManager()->getLanguages()) < 2) { - $t_args = [ - ':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString() - ]; - $message = t('This site has only a single language enabled. Add at least one more language in order to translate content.', $t_args); - drupal_set_message($message, 'warning'); - } - // Point the user to the content translation settings. - $t_args = [ - ':settings_url' => Url::fromRoute('language.content_settings_page')->toString() - ]; - $message = t('Enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args); - drupal_set_message($message, 'warning'); - } -} - -/** * Implements hook_module_implements_alter(). */ function content_translation_module_implements_alter(&$implementations, $hook) {