29
A Deep Dive into Drupal 8 Routing DrupalCamp Mumbai April 1, 2017 Naveen Valecha

A deep dive into Drupal 8 routing

Embed Size (px)

Citation preview

Page 1: A deep dive into Drupal 8 routing

A Deep Dive into Drupal 8 Routing

DrupalCamp MumbaiApril 1, 2017Naveen Valecha

Page 2: A deep dive into Drupal 8 routing

About me

● Drupal: naveenvalecha● Git Administer on Drupal.org● Site Maintainer of groups.drupal.org● Twitter: @_naveenvalecha_● Web: https://www.valechatech.net● Drupal 5,6,7,8

Page 3: A deep dive into Drupal 8 routing

Agenda

● What are Routes. Why we need them?● Routes and Controllers● Access checking on routes● Custom Access Checkers● CSRF Prevention on routes● Altering routes● Dynamic Routes● Parameter Upcasting

Page 4: A deep dive into Drupal 8 routing

Routing System

● hook_menu to Symfony2 routing● Replace paths with route names for rendering

links● Converting all page callbacks to controllers● New breadcrumb system, new menu link system,

conversion of local tasks and actions to plugins

Page 5: A deep dive into Drupal 8 routing

Routing System - Cont.

● menu links, local tasks, local actions, contextual links

● Split all the pieces from hook_menu into YAML files finally

● module.routing.yml module.links.menu.yml● module.links.task.yml module.links.action.yml● module.contextual.yml

Page 6: A deep dive into Drupal 8 routing

hook_menu to Symfony Routing

● PHP array to multiple yaml files● Performance improvements● Developer Experience(DX)● Clean Code● Procedural to Object Oriented(OO)

Page 7: A deep dive into Drupal 8 routing

D7 hook_menu

$items['admin/appearance/settings'] = array(

'title' => 'Settings',

'description' => 'Configure default and theme specific settings.',

'page callback' => 'drupal_get_form',

'page arguments' => array('system_theme_settings'),

'access arguments' => array('administer themes'),

'type' => MENU_LOCAL_TASK,

'file' => 'system.admin.inc',

'weight' => 20,

);

Page 8: A deep dive into Drupal 8 routing

D8 system.routing.yml

system.theme_settings: path: '/admin/appearance/settings' defaults: _form: '\Drupal\system\Form\ThemeSettingsForm' _title: 'Appearance settings' requirements: _permission: 'administer themes'

Page 9: A deep dive into Drupal 8 routing

D8 system.links.task.yml

system.theme_settings: route_name: system.theme_settings

title: 'Settings' base_route: system.themes_page

weight: 100

Page 10: A deep dive into Drupal 8 routing

Route

● A route is a path which is defined for Drupal to return some sort of content on. For example, the default front page, '/node' is a route.

● Use mm.routing.yml for defining routes

Page 11: A deep dive into Drupal 8 routing

Routes and Controllers

● The routing system is responsible for matching paths to controllers, and you define those relations in routes. You can pass on additional information to your controllers in the route. Access checking is integrated as well.

Page 12: A deep dive into Drupal 8 routing

Route - Slugentity.node.preview:

path: '/node/preview/{node_preview}/{view_mode_id}'

defaults:

_controller: '\Drupal\node\Controller\NodePreviewController::view'

_title_callback: '\Drupal\node\Controller\NodePreviewController::title'

requirements:

_node_preview_access: '{node_preview}'

options:

parameters:

node_preview:

type: 'node_preview'

Page 13: A deep dive into Drupal 8 routing

/*** Defines a controller to render a single node in preview.*/class NodePreviewController extends EntityViewController {

/** * {@inheritdoc} */ public function view(EntityInterface $node_preview, $view_mode_id = 'full', $langcode = NULL) { $node_preview->preview_view_mode = $view_mode_id; $build = parent::view($node_preview, $view_mode_id);

return $build; }}

Page 14: A deep dive into Drupal 8 routing

example.content: path: '/example' defaults: _controller: '\Drupal\example\Controller\ExampleController::content' custom_arg: 12 requirements: _permission: 'access content'

// ...public function content(Request $request, $custom_arg) { // Now can use $custom_arg (which will get 12 here) and $request.}

Page 15: A deep dive into Drupal 8 routing

Routes Structure

● Path(*): /node/preview/{node_preview}/{view_mode_id}

● defaults(*)○ _controller:

\Drupal\node\Controller\NodePreviewController::view

○ _form: \Drupal\Core\Form\FormInterface

○ _entity_view, _entity_form:○ _title(optional), _title_context(optional),

_title_callback(optional)

Page 16: A deep dive into Drupal 8 routing

Routes Structure

● methods(optional)● Requirements

○ _permission, _role, _access, _entity_access, _custom_access, _format, _content_type_format

○ _module_dependencies○ _csrf_token

Page 17: A deep dive into Drupal 8 routing

Access checking

Permissionrequirements:

_permission: 'administer content types'

Role

requirements: _role: 'administrator'

Page 18: A deep dive into Drupal 8 routing

Access checking - Custom

class NodeRevisionAccessCheck implements AccessInterface {

public function access(Route $route, AccountInterface $account, $node_revision = NULL, NodeInterface $node = NULL) {

if ($node_revision) {

$node = $this->nodeStorage->loadRevision($node_revision);

}

$operation = $route->getRequirement('_access_node_revision');

return AccessResult::allowedIf($node && $this->checkAccess($node, $account, $operation))->cachePerPermissions()->addCacheableDependency($node);

}

}

Page 19: A deep dive into Drupal 8 routing

Route - CSRF Protection

aggregator.feed_refresh:

path: '/admin/config/services/aggregator/update/{aggregator_feed}'

defaults:

_controller: '\Drupal\aggregator\Controller\AggregatorController::feedRefresh'

_title: 'Update items'

requirements:

_permission: 'administer news feeds'

_csrf_token: 'TRUE'

Page 20: A deep dive into Drupal 8 routing

Routes - Altering

class NodeAdminRouteSubscriber extends RouteSubscriberBase {

protected function alterRoutes(RouteCollection $collection) {

if ($this->configFactory->get('node.settings')->get('use_admin_theme')) {

foreach ($collection->all() as $route) {

if ($route->hasOption('_node_operation_route')) {

$route->setOption('_admin_route', TRUE);

}

}

}

}

}

Page 21: A deep dive into Drupal 8 routing

Dynamic Routes

Image.routing.yml

route_callbacks: - '\Drupal\image\Routing\ImageStyleRoutes::routes'

Page 22: A deep dive into Drupal 8 routing

Dynamic Routes - Cont.

class ImageStyleRoutes implements ContainerInjectionInterface { public function routes() { $routes = []; $directory_path = $this->streamWrapperManager->getViaScheme('public')->getDirectoryPath(); $routes['image.style_public'] = new Route( '/' . $directory_path . '/styles/{image_style}/{scheme}', [ '_controller' => 'Drupal\image\Controller\ImageStyleDownloadController::deliver', ], [ '_access' => 'TRUE', ] ); return $routes; }}

Page 23: A deep dive into Drupal 8 routing

Route-Parameter Upcasting

entity.node.preview:

path: '/node/preview/{node_preview}/{view_mode_id}'

defaults:

_controller: '\Drupal\node\Controller\NodePreviewController::view'

_title_callback: '\Drupal\node\Controller\NodePreviewController::title'

requirements:

_node_preview_access: '{node_preview}'

options:

parameters:

node_preview:

type: 'node_preview'

Page 24: A deep dive into Drupal 8 routing

Route-Parameter Upcasting Cont.

node.services.ymlnode_preview:

class: Drupal\node\ParamConverter\NodePreviewConverter

arguments: ['@user.private_tempstore']

tags:

- { name: paramconverter }

lazy: true

Page 25: A deep dive into Drupal 8 routing

Route-Parameter Upcasting Cont.

class NodePreviewConverter implements ParamConverterInterface {

public function convert($value, $definition, $name, array $defaults) {

$store = $this->tempStoreFactory->get('node_preview');

if ($form_state = $store->get($value)) {

return $form_state->getFormObject()->getEntity();

}

}

public function applies($definition, $name, Route $route) {

if (!empty($definition['type']) && $definition['type'] == 'node_preview') {

return TRUE;

}

return FALSE;

}

Page 26: A deep dive into Drupal 8 routing

What’s for Drupal 9?

● Consider having a single class for Match Dumper, Route Provider and Route Builder

● Automatically unserialize request data and serialize outgoing data

Page 28: A deep dive into Drupal 8 routing

Questions?

Page 29: A deep dive into Drupal 8 routing

THANK YOU!