Commit 7f0a4039 authored by dpi's avatar dpi

Initial commit

parents
This diff is collapsed.
Views Advanced Routing
Views Advanced Routing is a module providing a custom display extender for Views
allowing you to take advantage of Drupal 8's new routing system. You can set the
defaults, requirements, and options for each route.
See Drupal 8 documentation on routing YAML: https://www.drupal.org/node/2092643
Copyright (C) 2015 Daniel Phin (@dpi)
# License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Usage
## Enable Views Advanced Routing
1. Enable the module.
2. Go to *Administration -> Structure -> Views*
Click the 'Settings' tab.
Click the 'Advanced' sub tab.
3. Under __Display extenders__, enable the 'Route' checkbox.
4. Save configuration.
## Using Routes
1. Open a view with a 'page' or 'feed' display.
2. In the center column, a new 'Route' setting will be displayed.
Click the link too set your custom route settings.
3. Route YAML is in the same format as Drupals '*routing.yml' files.
Strip top level YAML keys such as defaults, requirements, options and paste
values directly into the textbox.
4. Save the view.
## FAQ
### Path
Use the built-in views path setting to set path. If you have need parameter
converters you should change the format from `{node}` to `%node`.
If you require __entity parameter converters__, you can use this code in your
custom 'options' YAML:
```yaml
parameters:
parameter_name:
type: 'entity:my_entity_type'
```
Where parameter_name is the %parameter_name used in the path. It is usually the
same name as the entity_type. For example, a tab attached to a node page:
__Path: node/%node/my_view_name__
```yaml
parameters:
node:
type: 'entity:node'
```
\ No newline at end of file
<?php
/**
* @file
* Contains \Drupal\views_test_data\Plugin\views\display_extender\DisplayExtenderTest.
*/
namespace Drupal\views_advanced_routing\Plugin\views\display_extender;
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\display\DisplayRouterInterface;
use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
use Drupal\Component\Serialization\Yaml;
use Symfony\Component\Routing\Route;
/**
* Advanced route editor.
*
* @ViewsDisplayExtender(
* id = "views_advanced_routing_route",
* title = @Translation("Route")
* )
*/
class AdvancedRouting extends DisplayExtenderPluginBase {
/**
* Stores some state booleans to be sure a certain method got called.
*
* @var array
*/
public $testState;
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
// YAML.
$options['route'] = ['default' => ''];
return $options;
}
/**
* Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary().
*
* $options keys is section as used by buildOptionsForm().
*/
public function optionsSummary(&$categories, &$options) {
if (!$this->displayHandler instanceof DisplayRouterInterface) {
return;
}
parent::optionsSummary($categories, $options);
$categories['views_advanced_routing'] = [
'title' => '',
'column' => 'second',
'build' => [
// Page settings is -10, Access is -5.
'#weight' => -6,
],
];
$message = [];
$route = $this->options['route'];
if (!empty($route['defaults'])) {
$message[] = $this->t('Defaults');
}
if (!empty($route['requirements'])) {
$message[] = $this->t('Requirements');
}
if (!empty($route['options'])) {
$message[] = $this->t('Options');
}
$options['views_advanced_routing_route'] = [
'category' => 'views_advanced_routing',
'title' => $this->t('Route'),
'value' => implode(' | ', $message) ?: $this->t('None'),
];
}
/**
* Overrides Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase::buildOptionsForm().
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$section = $form_state->get('section');
if ($section == 'views_advanced_routing_route') {
$route = $this->options['route'];
$form['route'] = [
'#title' => t('Route YAML'),
'#type' => 'fieldset',
'#tree' => TRUE,
];
$form['route']['defaults'] = [
'#type' => 'textarea',
'#title' => t('Defaults'),
'#default_value' => !empty($route['defaults']) ? Yaml::encode($route['defaults']) : '',
];
$form['route']['requirements'] = [
'#type' => 'textarea',
'#title' => t('Requirements'),
'#default_value' => !empty($route['requirements']) ? Yaml::encode($route['requirements']) : '',
];
$form['route']['options'] = [
'#type' => 'textarea',
'#title' => t('Options'),
'#default_value' => !empty($route['options']) ? Yaml::encode($route['options']) : '',
];
}
}
/**
* @inheritDoc
*/
public function validateOptionsForm(&$form, FormStateInterface $form_state) {
$section = $form_state->get('section');
if ($section == 'views_advanced_routing_route') {
$route_info = [
'defaults' => [],
'requirements' => [],
'options' => [],
];
// $key: defaults, requirements, options.
$route = $form_state->getValue('route');
foreach ($route as $key => $value) {
try {
$route_data = Yaml::decode($route[$key]) ?: [];
if (is_array($route_data)) {
$route_info[$key] = $route_data;
}
else {
$form_state->setError($form['route'][$key], $this->t('Value must be an array.'));
}
}
catch (InvalidDataTypeException $e) {
$form_state->setError($form['route'][$key], $this->t('YAML does not validate: @exception', [
'@exception' => $e->getMessage(),
]));
}
}
try {
new Route('<none>', $route_info['defaults'], $route_info['requirements'], $route_info['options']);
}
catch (\Exception $e) {
// Creating the route can throw exceptions.
$form_state->setError($form['route'], $e->getMessage());
}
$form_state->set('route_info', $route_info);
}
}
/**
* Overrides Drupal\views\Plugin\views\display\DisplayExtenderPluginBase::submitOptionsForm().
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
$section = $form_state->get('section');
if ($section == 'views_advanced_routing_route') {
if ($route_info = $form_state->get('route_info')) {
$this->options['route'] = $route_info;
}
}
}
}
<?php
/**
* @file
* Contains \Drupal\views_advanced_routing\Routing\RouteSubscriber.
*/
namespace Drupal\views_advanced_routing\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\views\Plugin\views\display\DisplayRouterInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
use Symfony\Component\Routing\RouteCollection;
/**
* Customizes Views routes.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* The view storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $viewStorage;
/**
* Constructs a RouteSubscriber object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*/
public function __construct(EntityManagerInterface $entity_manager) {
$this->viewStorage = $entity_manager->getStorage('view');
}
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
$views = [];
foreach (Views::getApplicableViews('uses_route') as $data) {
list($view_id, $display_id) = $data;
$views[$view_id][] = $display_id;
}
foreach ($views as $view_id => $displays) {
/** @var \Drupal\views\Entity\View $view */
$view = $this->viewStorage->load($view_id);
foreach ($displays as $display_id) {
if (($vex = $view->getExecutable()) && $vex instanceof ViewExecutable) {
if ($vex->setDisplay($display_id) && $display = $vex->displayHandlers->get($display_id)) {
if ($display instanceof DisplayRouterInterface) {
$options = $display->getOption('display_extenders');
if (isset($options['views_advanced_routing_route'])) {
$route = $collection->get($display->getRouteName());
$settings = $options['views_advanced_routing_route'];
if ($route && !empty($settings['route'])) {
$route_info = $settings['route'];
$route_info += [
'defaults' => [],
'requirements' => [],
'options' => [],
];
$route
->addOptions($route_info['options'])
->addRequirements($route_info['requirements'])
->addDefaults($route_info['defaults']);
$collection->add($display->getRouteName(), $route);
}
}
}
}
$vex->destroy();
}
}
}
}
}
name: Views Advanced Routing
type: module
description: 'Provides advanced route customisation for Views.'
package: Views
core: 8.x
\ No newline at end of file
services:
views_advanced_routing.route_subscriber:
class: Drupal\views_advanced_routing\Routing\RouteSubscriber
arguments: ['@entity.manager']
tags:
- { name: event_subscriber }
\ No newline at end of file
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