diff --git a/core/core.services.yml b/core/core.services.yml index 6134359..1f3c2a1 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -258,7 +258,9 @@ services: - [fromRequest, ['@request']] router.route_provider: class: Drupal\Core\Routing\RouteProvider - arguments: ['@database'] + arguments: ['@database', '@router.builder'] + tags: + - { name: event_subscriber } router.matcher.final_matcher: class: Drupal\Core\Routing\UrlMatcher router.matcher: @@ -303,7 +305,12 @@ services: arguments: ['@database'] router.builder: class: Drupal\Core\Routing\RouteBuilder - arguments: ['@router.dumper', '@lock', '@event_dispatcher', '@module_handler', '@controller_resolver'] + arguments: ['@router.dumper', '@lock', '@event_dispatcher', '@module_handler', '@controller_resolver', '@state'] + router.rebuild_subscriber: + class: Drupal\Core\EventSubscriber\RouterRebuildSubscriber + arguments: ['@router.builder'] + tags: + - { name: event_subscriber } path.alias_manager.cached: class: Drupal\Core\CacheDecorator\AliasManagerCacheDecorator arguments: ['@path.alias_manager', '@cache.path'] diff --git a/core/includes/common.inc b/core/includes/common.inc index 9d03679..147703e 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -4994,7 +4994,6 @@ function drupal_flush_all_caches() { // Important: This rebuild must happen last, so the menu router is guaranteed // to be based on up to date information. \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); // Re-initialize the maintenance theme, if the current request attempted to // use it. Unlike regular usages of this function, the installer and update diff --git a/core/includes/menu.inc b/core/includes/menu.inc index c41e11e..2617e9c 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -475,13 +475,7 @@ function menu_get_item($path = NULL, $router_item = NULL) { $router_items[$path] = $router_item; } if (!isset($router_items[$path])) { - // Rebuild if we know it's needed, or if the menu masks are missing which - // occurs rarely, likely due to a race condition of multiple rebuilds. - if (\Drupal::state()->get('menu_rebuild_needed') || !\Drupal::state()->get('menu.masks')) { - menu_router_rebuild(); - \Drupal::service('router.builder')->rebuild(); - \Drupal::cache()->deleteTags(array('local_task' => 1)); - } + \Drupal::service('router.builder')->rebuildIfNeeded(); $original_map = arg(NULL, $path); $parts = array_slice($original_map, 0, MENU_MAX_PARTS); @@ -2532,13 +2526,13 @@ function menu_router_rebuild() { $transaction = db_transaction(); try { + // Ensure the route based router is up to date. + \Drupal::service('router.builder')->rebuildIfNeeded(); list($menu) = menu_router_build(TRUE); _menu_navigation_links_rebuild($menu); // Clear the menu, page and block caches. menu_cache_clear_all(); _menu_clear_page_cache(); - // Indicate that the menu has been successfully rebuilt. - \Drupal::state()->delete('menu_rebuild_needed'); } catch (Exception $e) { $transaction->rollback(); @@ -2740,6 +2734,9 @@ function _menu_navigation_links_rebuild($menu) { } // Find any item whose router path does not exist any more. + // Do not delete entries with an empty path as this can remove menu links in + // the process of being created. + $paths[] = ''; $query = \Drupal::entityQuery('menu_link') ->condition('router_path', $paths, 'NOT IN') ->condition('external', 0) diff --git a/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php new file mode 100644 index 0000000..d432656 --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php @@ -0,0 +1,71 @@ +routeBuilder = $route_builder; + } + + /** + * Rebuilds routers if necessary. + * + * @param \Symfony\Component\HttpKernel\Event\PostResponseEvent $event + * The event object. + */ + public function onKernelTerminate(PostResponseEvent $event) { + $this->routeBuilder->rebuildIfNeeded(); + } + + /** + * Rebuilds the menu_router and deletes the local_task cache tag. + * + * @param \Symfony\Component\EventDispatcher\Event $event + * The event object. + */ + public function onRouterRebuild(Event $event) { + menu_router_rebuild(); + Cache::deleteTags(array('local_task' => 1)); + } + + /** + * Registers the methods in this class that should be listeners. + * + * @return array + * An array of event listener definitions. + */ + static function getSubscribedEvents() { + $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 200); + $events[RoutingEvents::FINISHED][] = array('onRouterRebuild', 200); + return $events; + } + +} diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index fbd42c5..40456a9 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -83,7 +83,7 @@ class ThemeHandler implements ThemeHandlerInterface { * * @var \Drupal\Core\Routing\RouteBuilder */ - protected $routerBuilder; + protected $routeBuilder; /** * The system listing info @@ -459,7 +459,7 @@ protected function getSystemListingInfo() { */ protected function resetSystem() { if ($this->routeBuilder) { - $this->routeBuilder->rebuild(); + $this->routeBuilder->setRebuildNeeded(); } $this->systemListReset(); diff --git a/core/lib/Drupal/Core/Routing/RouteBuilder.php b/core/lib/Drupal/Core/Routing/RouteBuilder.php index 76a826b..3260710 100644 --- a/core/lib/Drupal/Core/Routing/RouteBuilder.php +++ b/core/lib/Drupal/Core/Routing/RouteBuilder.php @@ -9,6 +9,7 @@ use Drupal\Component\Discovery\YamlDiscovery; use Drupal\Core\Controller\ControllerResolverInterface; +use Drupal\Core\KeyValueStore\StateInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Routing\RouteCollection; @@ -23,7 +24,7 @@ * Because this class makes use of the modules system, it cannot currently * be unit tested. */ -class RouteBuilder { +class RouteBuilder implements RouteBuilderInterface { /** * The dumper to which we should send collected routes. @@ -68,7 +69,7 @@ class RouteBuilder { protected $controllerResolver; /** - * Construcs the RouteBuilder using the passed MatcherDumperInterface. + * Constructs the RouteBuilder using the passed MatcherDumperInterface. * * @param \Drupal\Core\Routing\MatcherDumperInterface $dumper * The matcher dumper used to store the route information. @@ -81,19 +82,17 @@ class RouteBuilder { * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver * The controller resolver. */ - public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler, ControllerResolverInterface $controller_resolver) { + public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler, ControllerResolverInterface $controller_resolver, StateInterface $state = NULL) { $this->dumper = $dumper; $this->lock = $lock; $this->dispatcher = $dispatcher; $this->moduleHandler = $module_handler; $this->controllerResolver = $controller_resolver; + $this->state = $state; } /** - * Rebuilds the route info and dumps to dumper. - * - * @return bool - * Returns TRUE if the rebuild succeeds, FALSE otherwise. + * {@inheritdoc} */ public function rebuild() { if (!$this->lock->acquire('router_rebuild')) { @@ -149,12 +148,30 @@ public function rebuild() { $this->dumper->addRoutes($collection); $this->dumper->dump(array('provider' => 'dynamic_routes')); + $this->state->delete(static::REBUILD_NEEDED); $this->lock->release('router_rebuild'); $this->dispatcher->dispatch(RoutingEvents::FINISHED, new Event()); return TRUE; } /** + * {@inheritdoc} + */ + public function rebuildIfNeeded() { + if ($this->state->get(static::REBUILD_NEEDED, FALSE)) { + return $this->rebuild(); + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function setRebuildNeeded() { + $this->state->set(static::REBUILD_NEEDED, TRUE); + } + + /** * Returns the YAML discovery for getting all the .routing.yml files. * * @return \Drupal\Component\Discovery\YamlDiscovery diff --git a/core/lib/Drupal/Core/Routing/RouteBuilderInterface.php b/core/lib/Drupal/Core/Routing/RouteBuilderInterface.php new file mode 100644 index 0000000..2c9ef24 --- /dev/null +++ b/core/lib/Drupal/Core/Routing/RouteBuilderInterface.php @@ -0,0 +1,35 @@ +rebuildNeeded && $this->rebuild()) { + $this->rebuildNeeded = FALSE; + return TRUE; + } + return FALSE; + } + + /** + * @inheritdoc + */ + public function setRebuildNeeded() { + $this->rebuildNeeded = TRUE; + } + } diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php index 18dc506..20b0ec1 100644 --- a/core/lib/Drupal/Core/Routing/RouteProvider.php +++ b/core/lib/Drupal/Core/Routing/RouteProvider.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Routing; use Drupal\Component\Utility\String; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RouteCollection; @@ -18,7 +19,7 @@ /** * A Route Provider front-end for all Drupal-stored routes. */ -class RouteProvider implements RouteProviderInterface { +class RouteProvider implements RouteProviderInterface, EventSubscriberInterface { /** * The database connection from which to read route information. @@ -35,6 +36,13 @@ class RouteProvider implements RouteProviderInterface { protected $tableName; /** + * The route builder. + * + * @var \Drupal\Core\Routing\RouteBuilderInterface + */ + protected $routeBuilder; + + /** * A cache of already-loaded routes, keyed by route name. * * @var array @@ -46,11 +54,14 @@ class RouteProvider implements RouteProviderInterface { * * @param \Drupal\Core\Database\Connection $connection * A database connection object. + * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder + * The route builder. * @param string $table * The table in the database to use for matching. */ - public function __construct(Connection $connection, $table = 'router') { + public function __construct(Connection $connection, RouteBuilderInterface $route_builder, $table = 'router') { $this->connection = $connection; + $this->routeBuilder = $route_builder; $this->tableName = $table; } @@ -99,7 +110,12 @@ public function getRouteCollectionForRequest(Request $request) { $collection = $this->getRoutesByPath($path); - if (!count($collection)) { + // Try rebuilding the router if it is necessary. + if (!$collection->count() && $this->routeBuilder->rebuildIfNeeded()) { + $collection = $this->getRoutesByPath($path); + } + + if (!$collection->count()) { throw new ResourceNotFoundException(String::format("The route for '@path' could not be found", array('@path' => $path))); } @@ -269,4 +285,19 @@ public function getAllRoutes() { return new LazyLoadingRouteCollection($this->connection, $this->tableName); } + /** + * {@inheritdoc} + */ + public function reset() { + $this->routes = array(); + } + + /** + * {@inheritdoc} + */ + static function getSubscribedEvents() { + $events[RoutingEvents::FINISHED][] = array('reset'); + return $events; + } + } diff --git a/core/lib/Drupal/Core/Routing/RouteProviderInterface.php b/core/lib/Drupal/Core/Routing/RouteProviderInterface.php index f84a19b..8c8e356 100644 --- a/core/lib/Drupal/Core/Routing/RouteProviderInterface.php +++ b/core/lib/Drupal/Core/Routing/RouteProviderInterface.php @@ -40,4 +40,9 @@ public function getRoutesByPattern($pattern); */ public function getAllRoutes(); + /** + * Resets the route provider object. + */ + public function reset(); + } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockHiddenRegionTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockHiddenRegionTest.php index 208710e..3fa85d6 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockHiddenRegionTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockHiddenRegionTest.php @@ -64,8 +64,9 @@ public function testBlockNotInHiddenRegion() { \Drupal::config('system.theme') ->set('default', $theme) ->save(); - \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); + // Enabling a theme will cause the kernel terminate event to rebuild the + // router. Simulate that here. + \Drupal::service('router.builder')->rebuildIfNeeded(); // Ensure that "block_test_theme" is set as the default theme. $this->drupalGet('admin/structure/block'); diff --git a/core/modules/color/lib/Drupal/color/Tests/ColorTest.php b/core/modules/color/lib/Drupal/color/Tests/ColorTest.php index 4193152..a22b003 100644 --- a/core/modules/color/lib/Drupal/color/Tests/ColorTest.php +++ b/core/modules/color/lib/Drupal/color/Tests/ColorTest.php @@ -48,8 +48,6 @@ function setUp() { ), ); theme_enable(array_keys($this->themes)); - $this->container->get('router.builder')->rebuild(); - menu_router_rebuild(); // Array filled with valid and not valid color values $this->colorTests = array( diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php index c6e4094..393db33 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php @@ -669,8 +669,9 @@ public function testThemeDiscovery() { // Enable the test theme and rebuild routes. $theme = 'config_translation_test_theme'; theme_enable(array($theme)); - \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); + // Enabling a theme will cause the kernel terminate event to rebuild the + // router. Simulate that here. + \Drupal::service('router.builder')->rebuildIfNeeded(); $this->drupalLogin($this->admin_user); diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index ea29536..ff56a8e 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -130,7 +130,7 @@ function field_ui_entity_info(&$entity_info) { function field_ui_entity_bundle_create($entity_type, $bundle) { // When a new bundle is created, the menu needs to be rebuilt to add our // menu item tabs. - \Drupal::state()->set('menu_rebuild_needed', TRUE); + \Drupal::service('router.builder')->setRebuildNeeded(); } /** @@ -139,7 +139,7 @@ function field_ui_entity_bundle_create($entity_type, $bundle) { function field_ui_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { // When a bundle is renamed, the menu needs to be rebuilt to add our // menu item tabs. - \Drupal::state()->set('menu_rebuild_needed', TRUE); + \Drupal::service('router.builder')->setRebuildNeeded(); } /** @@ -237,14 +237,14 @@ function field_ui_library_info() { * Implements hook_view_mode_presave(). */ function field_ui_view_mode_presave(EntityViewModeInterface $view_mode) { - \Drupal::state()->set('menu_rebuild_needed', TRUE); + \Drupal::service('router.builder')->setRebuildNeeded(); } /** * Implements hook_view_mode_delete(). */ function field_ui_view_mode_delete(EntityViewModeInterface $view_mode) { - \Drupal::state()->set('menu_rebuild_needed', TRUE); + \Drupal::service('router.builder')->setRebuildNeeded(); } /** diff --git a/core/modules/file/lib/Drupal/file/Tests/Views/ExtensionViewsFieldTest.php b/core/modules/file/lib/Drupal/file/Tests/Views/ExtensionViewsFieldTest.php index 87ab5f8..9683c1f 100644 --- a/core/modules/file/lib/Drupal/file/Tests/Views/ExtensionViewsFieldTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/Views/ExtensionViewsFieldTest.php @@ -18,7 +18,7 @@ class ExtensionViewsFieldTest extends ViewUnitTestBase { /** * {@inheritdoc} */ - public static $modules = array('file', 'file_test_views'); + public static $modules = array('file', 'file_test_views', 'user'); /** * Views used by this test. diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install index b7dc67d..2a61238 100644 --- a/core/modules/menu/menu.install +++ b/core/modules/menu/menu.install @@ -13,7 +13,6 @@ function menu_install() { // Add a link for each custom menu. \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); $system_link = entity_load_multiple_by_properties('menu_link', array('link_path' => 'admin/structure/menu', 'module' => 'system')); $system_link = reset($system_link); diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php index 638f47f..fd998d0 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php @@ -542,7 +542,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { } // Find the route_name. if (!isset($this->route_name)) { - if ($result = \Drupal::service('router.matcher.final_matcher')->findRouteNameParameters($this->link_path)) { + if (!$this->external && $result = \Drupal::service('router.matcher.final_matcher')->findRouteNameParameters($this->link_path)) { list($this->route_name, $this->route_parameters) = $result; } else { diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index 0e95f42..61b4b6c 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -121,7 +121,7 @@ public function save(EntityInterface $entity) { } if ($entity->isNew()) { - $entity->mlid = $this->database->insert($this->entityInfo->getBaseTable())->fields(array('menu_name' => 'tools'))->execute(); + $entity->mlid = $this->database->insert($this->entityInfo->getBaseTable())->fields(array('menu_name' => $entity->menu_name))->execute(); $entity->enforceIsNew(); } diff --git a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php index d0419d4..d40900d 100644 --- a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php +++ b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php @@ -205,11 +205,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { */ public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { parent::postSave($storage_controller, $update); - - $this->state()->set('menu_rebuild_needed', TRUE); - // @todo The above call should be sufficient, but it is not until - // https://drupal.org/node/2167323 is fixed. - \Drupal::service('router.builder')->rebuild(); + $this->routeBuilder()->setRebuildNeeded(); } /** @@ -239,13 +235,13 @@ public static function sort($a, $b) { } /** - * Wraps the state storage. + * Wraps the route builder. * - * @return \Drupal\Core\KeyValueStore\StateInterface + * @return \Drupal\Core\Routing\RouteBuilderInterface * An object for state storage. */ - protected function state() { - return \Drupal::state(); + protected function routeBuilder() { + return \Drupal::service('router.builder'); } /** diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchKeywordsConditionsTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchKeywordsConditionsTest.php index 15ae685..5f6e0bc 100644 --- a/core/modules/search/lib/Drupal/search/Tests/SearchKeywordsConditionsTest.php +++ b/core/modules/search/lib/Drupal/search/Tests/SearchKeywordsConditionsTest.php @@ -36,7 +36,6 @@ function setUp() { $this->drupalLogin($this->searching_user); // Test with all search modules enabled. \Drupal::config('search.settings')->set('active_plugins', array('node_search', 'user_search', 'search_extra_type_search'))->save(); - \Drupal::state()->set('menu_rebuild_needed', TRUE); } /** diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchPageOverrideTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchPageOverrideTest.php index 0f371e1..d916207 100644 --- a/core/modules/search/lib/Drupal/search/Tests/SearchPageOverrideTest.php +++ b/core/modules/search/lib/Drupal/search/Tests/SearchPageOverrideTest.php @@ -38,11 +38,9 @@ function setUp() { // Enable the extra type module for searching. \Drupal::config('search.settings')->set('active_plugins', array('node_search', 'user_search', 'search_extra_type_search'))->save(); - \Drupal::service('router.builder')->rebuild(); } function testSearchPageHook() { - $this->container->get('router.builder')->rebuild(); $keys = 'bike shed ' . $this->randomName(); $this->drupalGet("search/dummy_path/{$keys}"); $this->assertText('Dummy search snippet', 'Dummy search snippet is shown'); diff --git a/core/modules/system/lib/Drupal/system/Entity/Menu.php b/core/modules/system/lib/Drupal/system/Entity/Menu.php index fa5d7fd..7ac7bf1 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Menu.php +++ b/core/modules/system/lib/Drupal/system/Entity/Menu.php @@ -8,6 +8,7 @@ namespace Drupal\system\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\system\MenuInterface; /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php index ccc327d..6d0fee8 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php @@ -186,7 +186,6 @@ protected function doTestMenuName() { // rebuild. menu_test_menu_name('changed'); \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); $menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test')); $menu_link = reset($menu_links); diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php index 8c01748..e02c9c4 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php @@ -7,10 +7,11 @@ namespace Drupal\system\Tests\Menu; +use Drupal\Core\Routing\RouteBuilderInterface; use Drupal\simpletest\WebTestBase; /** - * Tests rebuilding the menu by setting 'menu_rebuild_needed.' + * Tests rebuilding the router. */ class RebuildTest extends WebTestBase { public static function getInfo() { @@ -22,9 +23,9 @@ public static function getInfo() { } /** - * Test if the 'menu_rebuild_needed' variable triggers a menu_rebuild() call. + * Tests that set a router rebuild needed works. */ - function testMenuRebuildByVariable() { + function testMenuRebuild() { // Check if 'admin' path exists. $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); $this->assertEqual($admin_exists, 'admin', "The path 'admin/' exists prior to deleting."); @@ -36,9 +37,9 @@ function testMenuRebuildByVariable() { $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); $this->assertFalse($admin_exists, "The path 'admin/' has been deleted and doesn't exist in the database."); - // Now we enable the rebuild variable and send a request to rebuild the menu - // item. Now 'admin' should exist. - \Drupal::state()->set('menu_rebuild_needed', TRUE); + // Now we set the router to be rebuilt. After the rebuild 'admin' should exist. + \Drupal::service('router.builder')->setRebuildNeeded(); + // The request should trigger the rebuild. $this->drupalGet(''); $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/MockRouteProvider.php b/core/modules/system/lib/Drupal/system/Tests/Routing/MockRouteProvider.php index de56a90..4a6ece5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/MockRouteProvider.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/MockRouteProvider.php @@ -82,4 +82,11 @@ public function getAllRoutes() { return $this->routes->all(); } + /** + * @inheritdoc} + */ + public function reset() { + $this->routes = array(); + } + } diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php index bae0909..b143797 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php @@ -18,6 +18,7 @@ use Drupal\Core\Database\Database; use Drupal\Core\Routing\MatcherDumper; use Drupal\Tests\Core\Routing\RoutingFixtures; +use Drupal\Tests\Core\Routing\NullRouteBuilder; /** * Basic tests for the RouteProvider. @@ -31,6 +32,13 @@ class RouteProviderTest extends UnitTestBase { */ protected $fixtures; + /** + * A null route builder to enable testing of the route provider. + * + * @var \Drupal\Core\Routing\RouteBuilderInterface + */ + protected $routeBuilder; + public static function getInfo() { return array( 'name' => 'Route Provider tests', @@ -43,6 +51,7 @@ function __construct($test_id = NULL) { parent::__construct($test_id); $this->fixtures = new RoutingFixtures(); + $this->routeBuilder = new NullRouteBuilder(); } public function tearDown() { @@ -57,7 +66,7 @@ public function tearDown() { public function testCandidateOutlines() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection); + $provider = new RouteProvider($connection, $this->routeBuilder); $parts = array('node', '5', 'edit'); @@ -81,7 +90,7 @@ public function testCandidateOutlines() { */ function testExactPathMatch() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -105,7 +114,7 @@ function testExactPathMatch() { */ function testOutlinePathMatch() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -134,7 +143,7 @@ function testOutlinePathMatch() { */ function testOutlinePathMatchTrailingSlash() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -163,7 +172,7 @@ function testOutlinePathMatchTrailingSlash() { */ function testOutlinePathMatchDefaults() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -201,7 +210,7 @@ function testOutlinePathMatchDefaults() { */ function testOutlinePathMatchDefaultsCollision() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -240,7 +249,7 @@ function testOutlinePathMatchDefaultsCollision() { */ function testOutlinePathMatchDefaultsCollision2() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -279,7 +288,7 @@ function testOutlinePathMatchDefaultsCollision2() { */ public function testOutlinePathMatchZero() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -314,7 +323,7 @@ public function testOutlinePathMatchZero() { */ function testOutlinePathNoMatch() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -343,7 +352,7 @@ function testOutlinePathNoMatch() { */ function testSystemPathMatch() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -368,7 +377,7 @@ function testSystemPathMatch() { */ protected function testRouteByName() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); @@ -403,7 +412,7 @@ protected function testRouteByName() { */ public function testGetRoutesByPatternWithLongPatterns() { $connection = Database::getConnection(); - $provider = new RouteProvider($connection, 'test_routes'); + $provider = new RouteProvider($connection, $this->routeBuilder, 'test_routes'); $this->fixtures->createTables($connection); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 697f8c7..035555e 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -35,8 +35,7 @@ function system_theme_default() { // implementations, and doing the variable_set() before the theme_enable() // could result in a race condition where the theme is default but not // enabled. - \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); + \Drupal::service('router.builder')->setRebuildNeeded(); \Drupal::cache('cache')->deleteTags(array('local_task' => 1)); // The status message depends on whether an admin theme is currently in use: diff --git a/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php b/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php index 9540364..4188c47 100644 --- a/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php +++ b/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php @@ -181,6 +181,7 @@ protected function alterRoutes(RouteCollection $collection, $provider) { * {@inheritdoc} */ public function routeRebuildFinished() { + $this->reset(); $this->state->set('views.view_route_names', $this->viewRouteNames); } diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php index 3617409..d3c3862 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php @@ -49,7 +49,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php index 8ff7823..77841f3 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php @@ -45,7 +45,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } /** diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterDateTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterDateTest.php index 72b7b21..36b8d58 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterDateTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterDateTest.php @@ -151,7 +151,7 @@ protected function _testBetween() { protected function _testUiValidation() { $this->drupalLogin($this->drupalCreateUser(array('administer views', 'administer site configuration'))); - menu_router_rebuild(); + $this->drupalGet('admin/structure/views/view/test_filter_date_between/edit'); $this->drupalGet('admin/structure/views/nojs/config-item/test_filter_date_between/default/filter/created'); diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php index 4ab42ad..9b74533 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php index 6e3e4e5..0c1f32a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php index 62b16d3..a1f50ef 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php index cb444c9..f00eaf3 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router', 'variable', 'key_value_expire')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php index 91d9654..a347d47 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php @@ -76,7 +76,6 @@ protected function viewsData() { function testFilterInOperatorUi() { $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration')); $this->drupalLogin($admin_user); - menu_router_rebuild(); $path = 'admin/structure/views/nojs/config-item/test_filter_in_operator_ui/default/filter/type'; $this->drupalGet($path); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php index 1532b40..9fe91bb 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php @@ -86,7 +86,9 @@ function testStaticAccessPlugin() { $display['display_options']['access']['options']['access'] = TRUE; $access_plugin->options['access'] = TRUE; $view->save(); - $this->container->get('router.builder')->rebuild(); + // Saving a view will cause the router to be rebuilt when the kernel + // termination event fires. Simulate that here. + $this->container->get('router.builder')->rebuildIfNeeded(); $this->assertTrue($access_plugin->access($this->normal_user)); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayAttachmentTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayAttachmentTest.php index c5d6255..7e55039 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayAttachmentTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayAttachmentTest.php @@ -40,9 +40,6 @@ protected function setUp() { * Tests the attachment plugin. */ protected function testAttachment() { - // @todo Remove that once http://drupal.org/node/1828444 got in. - \Drupal::state()->set('menu_rebuild_needed', TRUE); - $this->drupalGet('test-display-attachment'); $result = $this->xpath('//div[contains(@class, "view-content")]'); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php index 066ff2a..29bc169 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php @@ -7,12 +7,9 @@ namespace Drupal\views\Tests\Plugin; -use Drupal\Core\Routing\RouteBuildEvent; -use Drupal\views\EventSubscriber\RouteSubscriber; use Drupal\views\Tests\ViewUnitTestBase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\Routing\RouteCollection; /** * Tests the page display plugin. @@ -57,7 +54,7 @@ protected function setUp() { parent::setUp(); // Setup the needed tables in order to make the drupal router working. - $this->installSchema('system', array('router', 'menu_router', 'url_alias')); + $this->installSchema('system', array('menu_router', 'url_alias')); $this->installSchema('menu_link', 'menu_links'); } @@ -65,9 +62,6 @@ protected function setUp() { * Checks the behavior of the page for access denied/not found behaviours. */ public function testPageResponses() { - // @todo Importing a route should fire a container rebuild. - $this->container->get('router.builder')->rebuild(); - $subrequest = Request::create('/test_page_display_403', 'GET'); $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); $this->assertEqual($response->getStatusCode(), 403); @@ -87,6 +81,9 @@ public function testPageResponses() { $view = views_get_view('test_page_display'); // Disable the view, rebuild menu, and request the page again. $view->storage->disable()->save(); + // Router rebuild would occur in a kernel terminate event so we need to + // simulate that here. + \Drupal::service('router.builder')->rebuildIfNeeded(); $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); $this->assertEqual($response->getStatusCode(), 404); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php index 0ea9565..e527d52 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php @@ -250,6 +250,7 @@ public function testInvalidDisplayPlugins() { // Rebuild the router, and ensure that the path is not accessible anymore. views_invalidate_cache(); + \Drupal::service('router.builder')->rebuildIfNeeded(); $this->drupalGet('test_display_invalid'); $this->assertResponse(404); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php index 6315015..aa7306c 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php @@ -25,7 +25,7 @@ class DisplayUnitTest extends ViewUnitTestBase { * * @var array */ - public static $modules = array('block', 'node'); + public static $modules = array('block', 'node', 'field', 'user'); /** * Views plugin types to test. diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php index e3e3db0..2ad29c9 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php @@ -67,8 +67,6 @@ public function testSubmitButton() { $view->display_handler->setOption('exposed_form', $exposed_form); $view->save(); - views_invalidate_cache(); - // Make sure the submit button label changed. $this->drupalGet('test_exposed_form_buttons'); $this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', $expected_label); @@ -82,8 +80,6 @@ public function testSubmitButton() { $view->display_handler->setOption('exposed_form', $exposed_form); $view->save(); - views_invalidate_cache(); - // Make sure the submit button label shows 'Apply'. $this->drupalGet('test_exposed_form_buttons'); $this->helperButtonHasLabel('edit-submit-test-exposed-form-buttons', t('Apply')); @@ -120,8 +116,6 @@ public function testResetButton() { $view->display_handler->setOption('exposed_form', $exposed_form); $view->save(); - views_invalidate_cache(); - // Look whether the reset button label changed. $this->drupalGet('test_exposed_form_buttons', array('query' => array('type' => 'article'))); $this->assertResponse(200); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/MiniPagerTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/MiniPagerTest.php index b18e0d3..10955d4 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/MiniPagerTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/MiniPagerTest.php @@ -49,7 +49,6 @@ protected function setUp() { * Tests the rendering of mini pagers. */ public function testMiniPagerRender() { - menu_router_rebuild(); $this->drupalGet('test_mini_pager'); $this->assertText('›› test', 'The next link appears on the first page.'); $this->assertText('Page 1', 'The current page info shows the first page.'); diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php index d71c283..ede97bd 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php @@ -51,7 +51,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'router')); + $this->installSchema('system', array('menu_router')); $this->installSchema('taxonomy', array('taxonomy_term_data', 'taxonomy_term_hierarchy')); $this->installConfig(array('taxonomy')); } diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewUnitTestBase.php b/core/modules/views/lib/Drupal/views/Tests/ViewUnitTestBase.php index e5ec825..620e4fe 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewUnitTestBase.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewUnitTestBase.php @@ -54,6 +54,9 @@ protected function setUpFixtures() { $this->installSchema('views_test_data', $table); } + // The router table is required for router rebuilds. + $this->installSchema('system', array('router')); + // Load the test dataset. $data_set = $this->dataSet(); $query = db_insert('views_test_data') diff --git a/core/modules/views/views.module b/core/modules/views/views.module index c30c940..ea46a10 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -552,20 +552,13 @@ function views_invalidate_cache() { Cache::deleteTags(array('content' => TRUE)); // Set the menu as needed to be rebuilt. - \Drupal::state()->set('menu_rebuild_needed', TRUE); + \Drupal::service('router.builder')->setRebuildNeeded(); $module_handler = \Drupal::moduleHandler(); // Reset the RouteSubscriber from views. \Drupal::getContainer()->get('views.route_subscriber')->reset(); - // Set the router to be rebuild. - // @todo Figure out why the cache rebuild is trigged but the route table - // does not exist yet. - if (db_table_exists('router')) { - \Drupal::service('router.builder')->rebuild(); - } - // Invalidate the block cache to update views block derivatives. if ($module_handler->moduleExists('block')) { \Drupal::service('plugin.manager.block')->clearCachedDefinitions(); diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/ExposedFormUITest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/ExposedFormUITest.php index 0df5845..dab40a5 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/ExposedFormUITest.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/ExposedFormUITest.php @@ -43,7 +43,6 @@ protected function setUp() { * Tests the admin interface of exposed filter and sort items. */ function testExposedAdminUi() { - menu_router_rebuild(); $edit = array(); $this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type'); diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php index 764bb0b..86029a9 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php @@ -87,7 +87,7 @@ function testEditUI() { 'ui_show_display_embed' => FALSE, ); $this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration')); - views_invalidate_cache(); + $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); $this->assertNoFieldById('edit-displays-top-add-display-embed'); diff --git a/core/tests/Drupal/Tests/Core/Routing/NullRouteBuilder.php b/core/tests/Drupal/Tests/Core/Routing/NullRouteBuilder.php new file mode 100644 index 0000000..2631c48 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Routing/NullRouteBuilder.php @@ -0,0 +1,18 @@ + 'Route Builder', @@ -92,8 +99,9 @@ protected function setUp() { $this->yamlDiscovery = $this->getMockBuilder('\Drupal\Component\Discovery\YamlDiscovery') ->disableOriginalConstructor() ->getMock(); + $this->state = $this->getMock('\Drupal\Core\KeyValueStore\StateInterface'); - $this->routeBuilder = new TestRouteBuilder($this->dumper, $this->lock, $this->dispatcher, $this->moduleHandler, $this->controllerResolver); + $this->routeBuilder = new TestRouteBuilder($this->dumper, $this->lock, $this->dispatcher, $this->moduleHandler, $this->controllerResolver, $this->state); $this->routeBuilder->setYamlDiscovery($this->yamlDiscovery); } @@ -110,6 +118,10 @@ public function testRebuildLockingUnlocking() { ->method('release') ->with('router_rebuild'); + $this->state->expects($this->once()) + ->method('delete') + ->with('router_rebuild_needed'); + $this->yamlDiscovery->expects($this->any()) ->method('findAll') ->will($this->returnValue(array())); @@ -254,6 +266,44 @@ public function testRebuildWithProviderBasedRoutes() { $this->assertTrue($this->routeBuilder->rebuild()); } + /** + * Tests \Drupal\Core\Routing\RouteBuilder::rebuildIfNeeded() method. + */ + public function testRebuildIfNecessary() { + $this->lock->expects($this->once()) + ->method('acquire') + ->with('router_rebuild') + ->will($this->returnValue(TRUE)); + + $this->lock->expects($this->once()) + ->method('release') + ->with('router_rebuild'); + + $this->state->expects($this->once()) + ->method('set') + ->with('router_rebuild_needed'); + + $this->state->expects($this->once()) + ->method('delete') + ->with('router_rebuild_needed'); + + $this->state->expects($this->exactly(2)) + ->method('get') + ->with('router_rebuild_needed') + ->will($this->onConsecutiveCalls(TRUE, FALSE)); + + $this->yamlDiscovery->expects($this->any()) + ->method('findAll') + ->will($this->returnValue(array())); + + $this->routeBuilder->setRebuildNeeded(); + + // This will trigger a successful rebuild. + $this->assertTrue($this->routeBuilder->rebuildIfNeeded()); + + // This will not trigger a rebuild. + $this->assertFalse($this->routeBuilder->rebuildIfNeeded()); + } } /**