Commit e6823285 authored by Dries's avatar Dries

Issue #1932048 by nick_schuch, tim.plunkett, larowlan: Clean up tour ConfigEntity architecture.

parent 6ba3cb12
......@@ -20,11 +20,12 @@
* label = @Translation("Tour"),
* module = "tour",
* controller_class = "Drupal\Core\Config\Entity\ConfigStorageController",
* render_controller_class = "Drupal\tour\TourRenderController",
* config_prefix = "tour.tour",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid",
* "uuid" = "uuid"
* }
* )
*/
......@@ -34,7 +35,6 @@ class Tour extends ConfigEntityBase {
* The name (plugin ID) of the tour.
*
* @var string
* Unique identifier for this tour.
*/
public $id;
......@@ -42,7 +42,6 @@ class Tour extends ConfigEntityBase {
* The label of the tour.
*
* @var string
* A human readable name for this tour.
*/
public $label;
......@@ -50,9 +49,8 @@ class Tour extends ConfigEntityBase {
* The paths in which this tip can be displayed.
*
* @var array
* An array of paths.
*/
protected $paths;
protected $paths = array();
/**
* Holds the collection of tips that are attached to this tour.
......@@ -66,7 +64,7 @@ class Tour extends ConfigEntityBase {
*
* @var array
*/
protected $tips;
protected $tips = array();
/**
* Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::__construct();
......@@ -108,13 +106,25 @@ public function getTip($id) {
}
/**
* Returns a list of tips.
* Returns the tips for this tour.
*
* @return array
* A list of tips.
* An array of tip plugins.
*/
public function getTipList() {
return array_keys($this->tips);
public function getTips() {
$tips = array();
foreach ($this->tips as $id => $tip) {
$tips[] = $this->getTip($id);
}
uasort($tips, function ($a, $b) {
if ($a->getWeight() == $b->getWeight()) {
return 0;
}
return ($a->getWeight() < $b->getWeight()) ? -1 : 1;
});
drupal_container()->get('module_handler')->alter('tour_tips', $tips, $this);
return array_values($tips);
}
/**
......@@ -123,15 +133,13 @@ public function getTipList() {
public function getExportProperties() {
$properties = parent::getExportProperties();
$names = array(
'id',
'label',
'paths',
'tips',
'langcode',
);
foreach ($names as $name) {
$properties[$name] = $this->get($name);
}
return $properties;
}
}
......@@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\tour\TipPluginText.
* Contains \Drupal\tour\Plugin\tour\tip\TipPluginText.
*/
namespace Drupal\tour\Plugin\tour\tip;
......@@ -24,7 +24,6 @@ class TipPluginText extends TipPluginBase {
* The body text which is used for render of this Text Tip.
*
* @var string
* A string of text used as the body.
*/
protected $body;
......@@ -32,7 +31,6 @@ class TipPluginText extends TipPluginBase {
* The forced position of where the tip will be located.
*
* @var string
* A string of left|right|top|bottom.
*/
protected $location;
......@@ -40,7 +38,7 @@ class TipPluginText extends TipPluginBase {
* Returns a ID that is guaranteed uniqueness.
*
* @return string
* A unique string.
* A unique id to be used to generate aria attributes.
*/
public function getAriaId() {
static $id;
......@@ -54,7 +52,7 @@ public function getAriaId() {
* Returns body of the text tip.
*
* @return string
* The body of the text tip.
* The tip body.
*/
public function getBody() {
return $this->get('body');
......@@ -64,14 +62,14 @@ public function getBody() {
* Returns location of the text tip.
*
* @return string
* The location (left|right|top|bottom) of the text tip.
* The tip location.
*/
public function getLocation() {
return $this->get('location');
}
/**
* Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getAttributes();
* Overrides \Drupal\tour\TipPluginBase::getAttributes().
*/
public function getAttributes() {
$attributes = parent::getAttributes();
......@@ -84,7 +82,7 @@ public function getAttributes() {
}
/**
* Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getOutput();
* Implements \Drupal\tour\TipPluginInterface::getOutput().
*/
public function getOutput() {
$output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->getAriaId() . '-label">' . check_plain($this->getLabel()) . '</h2>';
......
......@@ -8,7 +8,7 @@
namespace Drupal\tour;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Plugin\Discovery\CacheDecorator;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\tour\TipPluginInterface;
/**
......@@ -20,7 +20,6 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
* The label which is used for render of this tip.
*
* @var string
* The label of this tip.
*/
protected $label;
......@@ -28,7 +27,6 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
* Allows tips to take more priority that others.
*
* @var string
* A number which pertains to ordering.
*/
protected $weight;
......@@ -36,14 +34,13 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
* The attributes that will be applied to the markup of this tip.
*
* @var array
* An array of attributes.
*/
protected $attributes;
/**
* Overrides \Drupal\Component\Plugin\PluginBase::__construct().
*/
public function __construct(array $configuration, $plugin_id, CacheDecorator $discovery) {
public function __construct(array $configuration, $plugin_id, DiscoveryInterface $discovery) {
parent::__construct($configuration, $plugin_id, $discovery);
$this->definition = $this->discovery->getDefinition($plugin_id);
......@@ -51,28 +48,28 @@ public function __construct(array $configuration, $plugin_id, CacheDecorator $di
}
/**
* Implements \Drupal\tour\Plugin\tour\tour\TourInterface::getLabel().
* Implements \Drupal\tour\TipPluginInterface::getLabel().
*/
public function getLabel() {
return $this->get('label');
}
/**
* Implements \Drupal\tour\Plugin\tour\tour\TourInterface::getWeight().
* Implements \Drupal\tour\TipPluginInterface::getWeight().
*/
public function getWeight() {
return $this->get('weight');
}
/**
* Implements \Drupal\tour\Plugin\tour\tour\TourInterface::getAttributes().
* Implements \Drupal\tour\TipPluginInterface::getAttributes().
*/
public function getAttributes() {
return $this->get('attributes');
}
/**
* Implements \Drupal\tour\Plugin\tour\tour\TourInterface::get().
* Implements \Drupal\tour\TipPluginInterface::get().
*/
public function get($key) {
if (!empty($this->configuration[$key])) {
......@@ -81,7 +78,7 @@ public function get($key) {
}
/**
* Implements \Drupal\tour\Plugin\tour\tour\TourInterface::set().
* Implements \Drupal\tour\TipPluginInterface::set().
*/
public function set($key, $value) {
$this->configuration[$key] = $value;
......
......@@ -65,4 +65,5 @@ public function set($key, $value);
* A renderable array.
*/
public function getOutput();
}
......@@ -27,16 +27,8 @@ class TipPluginManager extends PluginManagerBase {
public function __construct(array $namespaces) {
$this->discovery = new AnnotatedClassDiscovery('tour', 'tip', $namespaces);
$this->discovery = new CacheDecorator($this->discovery, 'tour');
$this->factory = new DefaultFactory($this->discovery);
}
/**
* Overrides \Drupal\Component\Plugin\PluginManagerBase::createInstance().
*
* Pass the TipsBag to the plugin constructor.
*/
public function createInstance($plugin_id, array $configuration = array(), TipsBag $bag = NULL) {
$plugin_class = DefaultFactory::getPluginClass($plugin_id, $this->discovery);
return new $plugin_class($configuration, $plugin_id, $this->discovery, $bag);
}
}
......@@ -16,6 +16,7 @@
* A collection of tips.
*/
class TipsBag extends PluginBag {
/**
* The initial configuration for each tip in the bag.
*
......@@ -70,10 +71,11 @@ protected function initializePlugin($instance_id) {
if (isset($this->configurations[$instance_id])) {
$configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]);
}
$this->pluginInstances[$instance_id] = $this->manager->createInstance($type, $configuration, $this);
$this->pluginInstances[$instance_id] = $this->manager->createInstance($type, $configuration);
}
else {
throw new PluginException(format_string("Unknown tip plugin ID '@tip'.", array('@tip' => $instance_id)));
}
}
}
......@@ -24,4 +24,5 @@ public function build(ContainerBuilder $container) {
$container->register('plugin.manager.tour.tip', 'Drupal\tour\TipPluginManager')
->addArgument('%container.namespaces%');
}
}
<?php
/**
* @file
* Contains \Drupal\tour\TourRenderController.
*/
namespace Drupal\tour;
use Drupal\Core\Entity\EntityRenderController;
use Drupal\Core\Entity\EntityInterface;
/**
* Provides a Tour render controller.
*/
class TourRenderController extends EntityRenderController {
/**
* Overrides \Drupal\Core\Entity\EntityRenderController::viewMultiple().
*/
public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
$build = array();
foreach ($entities as $entity_id => $entity) {
$tips = $entity->getTips();
$count = count($tips);
$list_items = array();
foreach ($tips as $index => $tip) {
if ($output = $tip->getOutput()) {
$list_items[] = array(
'output' => $output,
'counter' => array(
'#type' => 'container',
'#attributes' => array(
'class' => array(
'tour-progress',
),
),
'#children' => t('!tour_item of !total', array('!tour_item' => $index + 1, '!total' => $count)),
),
'#wrapper_attributes' => $tip->getAttributes(),
);
}
}
// If there is at least one tour item, build the tour.
if ($list_items) {
end($list_items);
$key = key($list_items);
$list_items[$key]['#wrapper_attributes']['data-text'] = t('End tour');
$build[$entity_id] = array(
'#theme' => 'item_list',
'#items' => $list_items,
'#type' => 'ol',
'#attributes' => array(
'id' => 'tour',
'class' => array(
'element-hidden',
),
),
);
}
}
// If at least one tour was built, attach the tour library.
if ($build) {
$build['#attached']['library'][] = array('tour', 'tour');
}
return $build;
}
}
......@@ -5,6 +5,8 @@
* Provides tests for tour module
*/
use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_menu().
*/
......@@ -76,9 +78,9 @@ function tour_test_2() {
}
/**
* Implements hook_tour_alter().
* Implements hook_tour_tips_alter().
*/
function tour_test_tour_tips_alter(array &$tour_tips, $path) {
function tour_test_tour_tips_alter(array &$tour_tips, EntityInterface $entity) {
foreach ($tour_tips as $tour_tip) {
if ($tour_tip->get('id') == 'tour-code-test-1') {
$tour_tip->set('body', 'Altered by hook_tour_tips_alter');
......
......@@ -8,12 +8,12 @@
/**
* Allow modules to alter tour items before render.
*
* @param array $tour_items
* @param array $tour_tips
* Array of \Drupal\tour\TipPluginInterface items.
* @param string $path
* The path for which the tour is valid.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The tour which contains the $tour_tips.
*/
function hook_tour_tips_alter(array &$tour_tips, $path) {
function hook_tour_tips_alter(array &$tour_tips, Drupal\Core\Entity\EntityInterface $entity) {
foreach ($tour_tips as $tour_tip) {
if ($tour_tip->get('id') == 'tour-code-test-1') {
$tour_tip->set('body', 'Altered by hook_tour_tips_alter');
......
......@@ -121,83 +121,18 @@ function tour_preprocess_page(&$variables) {
$tours = entity_load_multiple('tour', $tour_ids);
$path_alias = drupal_strtolower(drupal_container()->get('path.alias_manager')->getPathAlias($path));
foreach ($tours as $tour) {
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))) {
foreach ($tour->getTipList() as $id) {
$tour_items[] = $tour->getTip($id);
}
if (!drupal_match_path($path_alias, $pages) && (($path == $path_alias) || drupal_match_path($path, $pages))) {
unset($tours[$tour_id]);
}
}
// Allow other modules to alter.
drupal_container()->get('module_handler')->alter('tour_tips', $tour_items, $path);
if (empty($tour_items)) {
return;
if ($tours) {
$variables['page']['help']['tour'] = entity_view_multiple($tours, 'full');
}
// Sort by weight.
uasort($tour_items, function ($a, $b) {
if ($a->getWeight() == $b->getWeight()) {
return 0;
}
return ($a->getWeight() < $b->getWeight()) ? -1 : 1;
});
$index = 1;
$count = count($tour_items);
foreach ($tour_items as $tour_item) {
$list_items[] = array(
'output' => $tour_item->getOutput(),
'counter' => array(
'#type' => 'container',
'#attributes' => array(
'class' => array(
'tour-progress',
),
),
'#children' => t('!tour_item of !total', array('!tour_item' => $index, '!total' => $count)),
),
'#wrapper_attributes' => $tour_item->getAttributes(),
);
$index++;
}
// Give the last tip the "End tour" button.
end($list_items);
$key = key($list_items);
$list_items[$key]['#wrapper_attributes']['data-text'] = t('End tour');
$variables['page']['help']['tour'] = array(
'#theme' => 'item_list',
'#items' => $list_items,
'#type' => 'ol',
'#attributes' => array(
'id' => 'tour',
'class' => array(
'element-hidden',
),
),
'#attached' => array(
'library' => array(
// We must also attach the jquery.joyride library here, because it only
// works within the window within which it is loaded. This means that if
// we want the Tour module to work inside the Overlay, we must ensure
// that jquery.joyride also is loaded there. (And since the Toolbar does
// not get loaded inside the Overlay, we cannot rely on it being loaded
// that way.)
// If this a non-overlay page, then Drupal's dependency checking will
// ensure this gets loaded only once.
array('tour', 'jquery.joyride'),
// Similarly, we must load tour's CSS, in order to style the tour tips
// in the desired way inside the Overlay.
array('tour', 'tour-styling'),
),
),
);
}
/**
......
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