diff --git a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php index 8cefe16..1dd37ad 100644 --- a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php +++ b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\tour\TipsBag; use Drupal\tour\TourInterface; +use Symfony\Component\HttpFoundation\ParameterBag; /** * Defines the configured tour entity. @@ -53,11 +54,11 @@ class Tour extends ConfigEntityBase implements TourInterface { public $label; /** - * The paths in which this tip can be displayed. + * The routes on which this tour should be displayed. * * @var array */ - protected $paths = array(); + protected $routes = array(); /** * Holds the collection of tips that are attached to this tour. @@ -85,10 +86,12 @@ public function __construct(array $values, $entity_type) { /** * {@inheritdoc} */ - public function getPaths() { - return $this->paths; + public function getRoutes() { + return $this->routes; } + + /** * {@inheritdoc} */ @@ -121,7 +124,7 @@ public function getTips() { public function getExportProperties() { $properties = parent::getExportProperties(); $names = array( - 'paths', + 'routes', 'tips', ); foreach ($names as $name) { @@ -130,4 +133,32 @@ public function getExportProperties() { return $properties; } + /** + * {@inheritdoc} + */ + public function matchRoute($route_name, ParameterBag $route_params) { + static $keyed_routes; + if (!isset($keyed_routes)) { + $keyed_routes = array(); + foreach ($this->routes as $route) { + $keyed_routes[$route['route_name']] = isset($route['route_params']) ? $route['route_params'] : array(); + } + } + if (!isset($keyed_routes[$route_name])) { + // We don't know about this route. + return FALSE; + } + if (empty($keyed_routes[$route_name])) { + // We don't need to worry about route params, the route name is enough. + return TRUE; + } + foreach ($keyed_routes[$route_name] as $key => $value) { + // If a required param is missing or doesn't match, return FALSE. + if (!$route_params->has($key) || $route_params->get($key) !== $value) { + return FALSE; + } + } + return TRUE; + } + } diff --git a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php b/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php index 75d196c..7a26ef4 100644 --- a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php +++ b/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php @@ -129,8 +129,8 @@ public function testTourFunctionality() { 'id' => 'tour-entity-create-test-en', 'label' => 'Tour test english', 'langcode' => 'en', - 'paths' => array( - 'tour-test-1', + 'routes' => array( + array('route_name' => 'tour_test.1'), ), 'tips' => array( 'tour-test-1' => array( @@ -173,5 +173,25 @@ public function testTourFunctionality() { // Test hook_tour_alter(). $this->assertText('Altered by hook_tour_tips_alter'); + + // Navigate to tour-test-3 and verify the tour_test_1 tip is found with + // appropriate classes. + $this->drupalGet('tour-test-3/foo'); + $elements = $this->xpath('//li[@data-id=:data_id and @class=:classes and ./h2[contains(., :text)]]', array( + ':classes' => 'tip-module-tour-test tip-type-text tip-tour-test-1', + ':data_id' => 'tour-test-1', + ':text' => 'The first tip', + )); + $this->assertEqual(count($elements), 1, 'Found English variant of tip 1.'); + + // Navigate to tour-test-3 and verify the tour_test_1 tip is not found with + // appropriate classes. + $this->drupalGet('tour-test-3/bar'); + $elements = $this->xpath('//li[@data-id=:data_id and @class=:classes and ./h2[contains(., :text)]]', array( + ':classes' => 'tip-module-tour-test tip-type-text tip-tour-test-1', + ':data_id' => 'tour-test-1', + ':text' => 'The first tip', + )); + $this->assertEqual(count($elements), 0, 'Found English variant of tip 1.'); } } diff --git a/core/modules/tour/lib/Drupal/tour/TourInterface.php b/core/modules/tour/lib/Drupal/tour/TourInterface.php index d5e4135..7813201 100644 --- a/core/modules/tour/lib/Drupal/tour/TourInterface.php +++ b/core/modules/tour/lib/Drupal/tour/TourInterface.php @@ -8,6 +8,7 @@ namespace Drupal\tour; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Symfony\Component\HttpFoundation\ParameterBag; /** * Provides an interface defining a tour entity. @@ -15,12 +16,25 @@ interface TourInterface extends ConfigEntityInterface { /** - * The paths that this tour will appear on. + * The routes that this tour will appear on. * * @return array - * Returns array of paths for the tour. + * Returns array of routes for the tour. */ - public function getPaths(); + public function getRoutes(); + + /** + * Whether the tour matches a given set of route parameters. + * + * @param string $route_name + * The route name the parameters are for. + * @param \Symfony\Component\HttpFoundation\ParameterBag $route_params + * Parameter bag of raw route params. + * + * @return bool + * TRUE if the tour matches the route parameters. + */ + public function matchRoute($route_name, ParameterBag $route_params); /** * Returns tip plugin. diff --git a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2.yml b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2.yml index 62e5ae8..0b93fa6 100644 --- a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2.yml +++ b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2.yml @@ -2,8 +2,8 @@ id: tour-test-2 module: tour_test label: Tour test english langcode: en -paths: - - tour-test-2/* +routes: + - { route_name: tour_test.2 } tips: tour-test-2: id: tour-test-2 diff --git a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test.yml b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test.yml index 3fa6d5c..54e2bfe 100644 --- a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test.yml +++ b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test.yml @@ -2,8 +2,9 @@ id: tour-test module: tour_test label: Tour test english langcode: en -paths: - - tour-test-1 +routes: + - { route_name: tour_test.1 } + - { route_name: tour_test.3, route_params: { locale: foo } } tips: tour-test-1: id: tour-test-1 diff --git a/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php b/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php index 126be87..30e1602 100644 --- a/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php +++ b/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php @@ -23,8 +23,15 @@ public static function create(ContainerInterface $container) { /** * Outputs some content for testing tours. + * + * @param string $locale + * (optional) Dummy locale variable for testing routing parameters. Defaults + * to 'foo'. + * + * @return array + * Array of markup. */ - public function tourTest1() { + public function tourTest1($locale = 'foo') { return array( 'tip-1' => array( '#type' => 'container', diff --git a/core/modules/tour/tests/tour_test/tour_test.routing.yml b/core/modules/tour/tests/tour_test/tour_test.routing.yml index 32f934d..5e4d254 100644 --- a/core/modules/tour/tests/tour_test/tour_test.routing.yml +++ b/core/modules/tour/tests/tour_test/tour_test.routing.yml @@ -18,3 +18,12 @@ tour_test.2: _content: '\Drupal\tour_test\Controller\TourTestController::tourTest2' requirements: _access: 'TRUE' + +tour_test.3: + path: '/tour-test-3/{locale}' + defaults: + locale: 'foo' + _content: '\Drupal\tour_test\Controller\TourTestController::tourTest1' + requirements: + _access: 'TRUE' + diff --git a/core/modules/tour/tour.module b/core/modules/tour/tour.module index 8bd9ec1..77fd0ea 100644 --- a/core/modules/tour/tour.module +++ b/core/modules/tour/tour.module @@ -5,6 +5,7 @@ * Main functions of the module. */ use Drupal\Core\Cache\CacheBackendInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; /** * Implements hook_permission(). @@ -108,23 +109,23 @@ function tour_preprocess_page(&$variables) { return; } - // @todo replace this with http://drupal.org/node/1918768 once it is committed. - $path = current_path(); - // Load all of the items and match on path. - $tours = entity_load_multiple('tour'); - - $path_alias = drupal_strtolower(\Drupal::service('path.alias_manager')->getPathAlias($path)); - foreach ($tours as $tour_id => $tour) { - // @todo Replace this with an entity query that does path matching when - // http://drupal.org/node/1918768 lands. - $pages = implode("\n", $tour->getPaths()); - if (!drupal_match_path($path_alias, $pages) && (($path == $path_alias) || drupal_match_path($path, $pages))) { - unset($tours[$tour_id]); + // Load all of the items and match on route name. + $request = \Drupal::request(); + $route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME); + + $results = \Drupal::entityQuery('tour') + ->condition('routes.*.route_name', $route_name) + ->execute(); + if (!empty($results) && $tours = entity_load_multiple('tour', array_keys($results))) { + foreach ($tours as $id => $tour) { + // Match on params. + if (!$tour->matchRoute($route_name, $request->attributes->get('_raw_variables'))) { + unset($tours[$id]); + } + } + if (!empty($tours)) { + $variables['page']['help']['tour'] = entity_view_multiple($tours, 'full'); } - } - - if ($tours) { - $variables['page']['help']['tour'] = entity_view_multiple($tours, 'full'); } } diff --git a/core/modules/views_ui/config/tour.tour.views-ui.yml b/core/modules/views_ui/config/tour.tour.views-ui.yml index a7e6fa9..98637b6 100644 --- a/core/modules/views_ui/config/tour.tour.views-ui.yml +++ b/core/modules/views_ui/config/tour.tour.views-ui.yml @@ -3,8 +3,9 @@ uuid: 261db4f0-603c-440d-8211-17a095614851 module: views_ui label: 'Views ui' langcode: en -paths: - - 'admin/structure/views/view/*' +routes: + - { route_name: views_ui.edit } + - { route_name: views_ui.edit_display } tips: views-ui-active-display: id: views-ui-active-display