Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Admin paths are no longer defined in hook_admin_paths() and are now defined in *.routing.yml files instead.

The following key-value pair can be added into yaml route definition in order to specify whether it is an admin route or not:

  options:
    _admin_route: FALSE

* Routes starting with "/admin" will get by default TRUE value assigned.

Removing admin routes

Drupal 7:

/**
 * Implements hook_admin_paths().
 */
function block_admin_paths() {
  $paths = array(
    // Exclude the block demonstration page from admin treatment.
    // This allows us to present this page in its true form, full page.
    'admin/structure/block/demo/*' => FALSE,
  );
  return $paths;
}

Drupal 8 (in block.routing.yml)

block.admin_demo:
  path: '/admin/structure/block/demo/{theme}'
  defaults:
    _controller: '\Drupal\block\Controller\BlockController::demo'
  requirements:
    _access_theme: 'TRUE'
    _permission: 'administer blocks'
  options:
    _admin_route: FALSE

Adding admin routes

Drupal 7:

/**
 * Implements hook_admin_paths().
 */
function custom_block_admin_paths() {
  $paths = array(
    'block/add' => TRUE,
    'block/add/*' => TRUE,
    'block/*' => TRUE,
    'block/*/delete' => TRUE,
    'admin/structure/block/custom-blocks/*' => TRUE,
  );
  return $paths;
}

Drupal 8 (in custom_block.routing.yml):

custom_block.add_page:
  path: '/block/add'
  defaults:
    _controller: 'Drupal\custom_block\Controller\CustomBlockController::add'
    _title: 'Add custom block'
  options:
    _admin_route: TRUE
  requirements:
    _permission: 'administer blocks'

Matching admin routes

Drupal 7:

$is_admin = path_is_admin($path);

Drupal 8:

$is_admin = \Drupal::service('router.admin_context')->isAdminRoute(\Symfony\Component\Routing\Route $route);

// In order to get the $route you probably should use the $route_match
$route = \Drupal::routeMatch()->getRouteObject();
$is_admin = \Drupal::service('router.admin_context')->isAdminRoute($route);

* Omit the $path (Drupal 7) or $route (Drupal 8) parameter to check if the current page is an admin page.

Impacts: 
Module developers

Comments

cweagans’s picture

How would I go about declaring a route as an admin route if I don't control the routing.yml file for that route? For instance, if I create a view that's meant to be an admin page at /some/arbitrary/path - how can I tell Drupal that it is an admin page?

cweagans’s picture

Okay, got this figured out.

First, you need to implement a Route Subscriber (https://www.drupal.org/node/2187643), and then in the alterRoutes() method, you can do something like this:

if ($route = $collection->get('somemodule.yourroute')) {
  $route->setOption('_admin_route', TRUE);
}
steffenr’s picture

Thanks for figuring out, how to fix this problem. I also run into the same problem.
If you have this case on several views displays, you could also use the https://www.drupal.org/project/views_advanced_routing module.

SteffenR

jonhattan’s picture

Funny part is when you try to check if an arbitrary path route is admin.

I've managed to do it this way:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;

$path = '/node/1';
$request = Request::create($path);

$route_match = \Drupal::service('router.no_access_checks')->matchRequest($request);
$route = $route_match[RouteObjectInterface::ROUTE_OBJECT];
$is_admin = \Drupal::service('router.admin_context')->isAdminRoute($route);

I'm not sure if 'router.no_access_checks' is the proper service to use here. It seems 'router.matcher' does the same job.

robshambaugh’s picture

I'm using the Seven theme as the Admin theme but a custom theme for the rest of the site. Each user can have a couple types of User Profiles (member and owner). When editing a user at /user/1/edit, the admin theme is used. But editing the profile at /user/1/member/ or /user/1/owner/ defaults to the custom theme. How can I make the admin theme work for the profile paths?

alexi721’s picture

Any suggestions on how to switch the profile form (in 'edit' mode) to the Admin theme? Thank you very much in advance.

jwilson3’s picture

You have three options:

  • Write code: Implement a custom module with a Route Subscriber as cweagans wrote above that implements the RouteSubscriberBase::alterRoutes() method to add '_admin_theme' = 'TRUE' for the route(s) you desire.
  • Write patch: consider contributing a patch to your favorite module that either fixes the _admin_route: TRUE setting in module's *.routes.yml file. Or exposes the option to use admin theme in module settings.
  • No-code: Install Switch Page Theme and configure it to use the 'Seven' theme (or whatever your admin theme is) for the route(s) you desire and for the user roles you desire. Wildcards are supported. For example: /user/*/member, /user/*/owner or for Profile module: /profile/*/edit.

Please beware that the non-code option is slightly inferior because it does not respect the 'Admin theme' setting nor the Permissions to view the admin theme in Drupal core, which means you need to manually keep this configuration in sync with those other configurations from core, and if those values ever change in the life of your project, you risk things becoming inconsistent for your site administrators and content creators.

Edit: Fixed feedback from @marlo0's comment below.

marlo0’s picture

Thanks for laying out these options. But in your code suggestions, it should be _admin_route = TRUE not _admin_theme = 'TRUE' as you have put. This had me frustrated for a little bit so it could help others!

See https://www.drupal.org/docs/8/api/routing-system/structure-of-routes, it clearly specifies that the option is _admin_route

batigolix’s picture

Note that the route for the user edit page is called 'entity.user.edit_form', which you can use in the RouteSubscriberBase::alterRoutes() method as follows:

if ($route = $collection->get('entity.user.edit_form')) {
  $route->setOption('_admin_route', FALSE);
}