Commit 15606012 authored by alexpott's avatar alexpott
Browse files

Issue #1918768 by larowlan, tim.plunkett: Refactor tour module to use routes instead of paths.

parent 34bb38f8
...@@ -84,3 +84,18 @@ filter: ...@@ -84,3 +84,18 @@ filter:
status: status:
type: boolean type: boolean
label: 'Enabled' label: 'Enabled'
# Array of routes with route_name and route_params keys.
route:
type: mapping
label: 'Route'
mapping:
route_name:
type: text
label: 'Route Name'
route_params:
type: sequence
label: 'Route Params'
sequence:
- type: string
label: 'Param'
...@@ -22,12 +22,12 @@ tour.tour.*: ...@@ -22,12 +22,12 @@ tour.tour.*:
langcode: langcode:
type: string type: string
label: 'Default language' label: 'Default language'
paths: routes:
type: sequence type: sequence
label: 'Path settings' label: 'Route settings'
sequence: sequence:
- type: path - type: route
label: 'Path' label: 'Route'
tips: tips:
type: sequence type: sequence
label: 'Tips' label: 'Tips'
...@@ -68,5 +68,3 @@ tour.tip.text: ...@@ -68,5 +68,3 @@ tour.tip.text:
body: body:
type: text type: text
label: 'Body' label: 'Body'
...@@ -53,11 +53,18 @@ class Tour extends ConfigEntityBase implements TourInterface { ...@@ -53,11 +53,18 @@ class Tour extends ConfigEntityBase implements TourInterface {
public $label; public $label;
/** /**
* The paths in which this tip can be displayed. * The routes on which this tour should be displayed.
* *
* @var array * @var array
*/ */
protected $paths = array(); protected $routes = array();
/**
* The routes on which this tour should be displayed, keyed by route id.
*
* @var array
*/
protected $keyedRoutes;
/** /**
* Holds the collection of tips that are attached to this tour. * Holds the collection of tips that are attached to this tour.
...@@ -85,8 +92,8 @@ public function __construct(array $values, $entity_type) { ...@@ -85,8 +92,8 @@ public function __construct(array $values, $entity_type) {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getPaths() { public function getRoutes() {
return $this->paths; return $this->routes;
} }
/** /**
...@@ -121,7 +128,7 @@ public function getTips() { ...@@ -121,7 +128,7 @@ public function getTips() {
public function getExportProperties() { public function getExportProperties() {
$properties = parent::getExportProperties(); $properties = parent::getExportProperties();
$names = array( $names = array(
'paths', 'routes',
'tips', 'tips',
); );
foreach ($names as $name) { foreach ($names as $name) {
...@@ -130,4 +137,38 @@ public function getExportProperties() { ...@@ -130,4 +137,38 @@ public function getExportProperties() {
return $properties; return $properties;
} }
/**
* {@inheritdoc}
*/
public function hasMatchingRoute($route_name, $route_params) {
if (!isset($this->keyedRoutes)) {
$this->keyedRoutes = array();
foreach ($this->getRoutes() as $route) {
$this->keyedRoutes[$route['route_name']] = isset($route['route_params']) ? $route['route_params'] : array();
}
}
if (!isset($this->keyedRoutes[$route_name])) {
// We don't know about this route.
return FALSE;
}
if (empty($this->keyedRoutes[$route_name])) {
// We don't need to worry about route params, the route name is enough.
return TRUE;
}
foreach ($this->keyedRoutes[$route_name] as $key => $value) {
// If a required param is missing or doesn't match, return FALSE.
if (empty($route_params[$key]) || $route_params[$key] !== $value) {
return FALSE;
}
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function resetKeyedRoutes() {
unset($this->keyedRoutes);
}
} }
...@@ -128,8 +128,8 @@ public function testTourFunctionality() { ...@@ -128,8 +128,8 @@ public function testTourFunctionality() {
'id' => 'tour-entity-create-test-en', 'id' => 'tour-entity-create-test-en',
'label' => 'Tour test english', 'label' => 'Tour test english',
'langcode' => 'en', 'langcode' => 'en',
'paths' => array( 'routes' => array(
'tour-test-1', array('route_name' => 'tour_test.1'),
), ),
'tips' => array( 'tips' => array(
'tour-test-1' => array( 'tour-test-1' => array(
...@@ -172,5 +172,25 @@ public function testTourFunctionality() { ...@@ -172,5 +172,25 @@ public function testTourFunctionality() {
// Test hook_tour_alter(). // Test hook_tour_alter().
$this->assertText('Altered by hook_tour_tips_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.');
} }
} }
...@@ -15,12 +15,25 @@ ...@@ -15,12 +15,25 @@
interface TourInterface extends ConfigEntityInterface { interface TourInterface extends ConfigEntityInterface {
/** /**
* The paths that this tour will appear on. * The routes that this tour will appear on.
* *
* @return array * @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 array $route_params
* Associative array of raw route params.
*
* @return bool
* TRUE if the tour matches the route parameters.
*/
public function hasMatchingRoute($route_name, $route_params);
/** /**
* Returns tip plugin. * Returns tip plugin.
...@@ -41,4 +54,9 @@ public function getTip($id); ...@@ -41,4 +54,9 @@ public function getTip($id);
*/ */
public function getTips(); public function getTips();
/**
* Resets the statically cached keyed routes.
*/
public function resetKeyedRoutes();
} }
<?php
/**
* @file
* Contains \Drupal\tour\Tests\Entity\TourTest.
*/
namespace Drupal\tour\Tests\Entity\TourTest;
use Drupal\Tests\UnitTestCase;
/**
* Tests the Tour entity.
*
* @group Tour
*
* @coversDefaultClass \Drupal\tour\Entity\Tour
*/
class TourTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Tour entity tests',
'description' => 'Test \Drupal\tour\Entity\Tour.',
'group' => 'Tour',
);
}
/**
* Tests \Drupal\tour\Entity\Tour::hasMatchingRoute().
*
* @param array $routes
* Array of routes as per the Tour::routes property.
* @param string $route_name
* The route name to match.
* @param array $route_params
* Array of route params.
* @param bool $result
* Expected result.
*
* @covers ::hasMatchingRoute()
*
* @dataProvider routeProvider
*/
public function testHasMatchingRoute($routes, $route_name, $route_params, $result) {
$tour = $this->getMockBuilder('\Drupal\tour\Entity\Tour')
->disableOriginalConstructor()
->setMethods(array('getRoutes'))
->getMock();
$tour->expects($this->any())
->method('getRoutes')
->will($this->returnValue($routes));
$this->assertSame($result, $tour->hasMatchingRoute($route_name, $route_params));
$tour->resetKeyedRoutes();
}
/*
* Provides sample routes for testing.
*/
public function routeProvider() {
return array(
// Simple match.
array(
array(
array('route_name' => 'some.route'),
),
'some.route',
array(),
TRUE,
),
// Simple non-match.
array(
array(
array('route_name' => 'another.route'),
),
'some.route',
array(),
FALSE,
),
// Empty params.
array(
array(
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'bar'),
),
),
'some.route',
array(),
FALSE,
),
// Match on params.
array(
array(
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'bar'),
),
),
'some.route',
array('foo' => 'bar'),
TRUE,
),
// Non-matching params.
array(
array(
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'bar'),
),
),
'some.route',
array('bar' => 'foo'),
FALSE,
),
// One matching, one not.
array(
array(
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'bar'),
),
array(
'route_name' => 'some.route',
'route_params' => array('bar' => 'foo'),
),
),
'some.route',
array('bar' => 'foo'),
TRUE,
),
// One matching, one not.
array(
array(
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'bar'),
),
array(
'route_name' => 'some.route',
'route_params' => array('foo' => 'baz'),
),
),
'some.route',
array('foo' => 'baz'),
TRUE,
),
);
}
}
...@@ -2,8 +2,8 @@ id: tour-test-2 ...@@ -2,8 +2,8 @@ id: tour-test-2
module: tour_test module: tour_test
label: Tour test english label: Tour test english
langcode: en langcode: en
paths: routes:
- tour-test-2/* - route_name: tour_test.2
tips: tips:
tour-test-2: tour-test-2:
id: tour-test-2 id: tour-test-2
......
...@@ -2,8 +2,11 @@ id: tour-test ...@@ -2,8 +2,11 @@ id: tour-test
module: tour_test module: tour_test
label: Tour test english label: Tour test english
langcode: en langcode: en
paths: routes:
- tour-test-1 - route_name: tour_test.1
- route_name: tour_test.3
route_params:
locale: foo
tips: tips:
tour-test-1: tour-test-1:
id: tour-test-1 id: tour-test-1
......
...@@ -23,8 +23,15 @@ public static function create(ContainerInterface $container) { ...@@ -23,8 +23,15 @@ public static function create(ContainerInterface $container) {
/** /**
* Outputs some content for testing tours. * 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( return array(
'tip-1' => array( 'tip-1' => array(
'#type' => 'container', '#type' => 'container',
......
...@@ -18,3 +18,12 @@ tour_test.2: ...@@ -18,3 +18,12 @@ tour_test.2:
_content: '\Drupal\tour_test\Controller\TourTestController::tourTest2' _content: '\Drupal\tour_test\Controller\TourTestController::tourTest2'
requirements: requirements:
_access: 'TRUE' _access: 'TRUE'
tour_test.3:
path: '/tour-test-3/{locale}'
defaults:
locale: 'foo'
_content: '\Drupal\tour_test\Controller\TourTestController::tourTest1'
requirements:
_access: 'TRUE'
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Main functions of the module. * Main functions of the module.
*/ */
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
/** /**
* Implements hook_permission(). * Implements hook_permission().
...@@ -108,23 +109,23 @@ function tour_preprocess_page(&$variables) { ...@@ -108,23 +109,23 @@ function tour_preprocess_page(&$variables) {
return; return;
} }
// @todo replace this with http://drupal.org/node/1918768 once it is committed. // Load all of the items and match on route name.
$path = current_path(); $request = \Drupal::request();
// Load all of the items and match on path. $route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME);
$tours = entity_load_multiple('tour');
$results = \Drupal::entityQuery('tour')
$path_alias = drupal_strtolower(\Drupal::service('path.alias_manager')->getPathAlias($path)); ->condition('routes.*.route_name', $route_name)
foreach ($tours as $tour_id => $tour) { ->execute();
// @todo Replace this with an entity query that does path matching when if (!empty($results) && $tours = entity_load_multiple('tour', array_keys($results))) {
// http://drupal.org/node/1918768 lands. foreach ($tours as $id => $tour) {
$pages = implode("\n", $tour->getPaths()); // Match on params.
if (!drupal_match_path($path_alias, $pages) && (($path == $path_alias) || drupal_match_path($path, $pages))) { if (!$tour->hasMatchingRoute($route_name, $request->attributes->get('_raw_variables')->all())) {
unset($tours[$tour_id]); 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');
} }
} }
......
...@@ -3,8 +3,9 @@ uuid: 261db4f0-603c-440d-8211-17a095614851 ...@@ -3,8 +3,9 @@ uuid: 261db4f0-603c-440d-8211-17a095614851
module: views_ui module: views_ui
label: 'Views ui' label: 'Views ui'
langcode: en langcode: en
paths: routes:
- 'admin/structure/views/view/*' - route_name: views_ui.edit
- route_name: views_ui.edit_display
tips: tips:
views-ui-active-display: views-ui-active-display:
id: views-ui-active-display id: views-ui-active-display
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment