4

I want change all /user, /user/* urls by /profile, /profile/* urls. From a custom module, I copied all user routes (found in /core/module/user/user.routing.yml) to my custom .routing.yml file. I replaced all "user*" paths by "profile*".

Now, I have the following.

mycustommodule.register:
  path: '/profile/register'
  defaults:
    _entity_form: 'user.register'
    _title: 'Create new account'
  requirements:
    _access_user_register: 'TRUE'

mycustommodule.pass:
  path: '/profile/password'
  defaults:
    _form: '\Drupal\user\Form\UserPasswordForm'
    _title: 'Reset your password'
  requirements:
    _access: 'TRUE'
  options:
    _maintenance_access: TRUE

mycustommodule.page:
  path: '/profile'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::userPage'
    _title: 'My account'
  requirements:
    _user_is_logged_in: 'TRUE'

mycustommodule.login:
  path: '/profile/login'
  defaults:
    _form: '\Drupal\user\Form\UserLoginForm'
    _title: 'Log in'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE

mycustommodule.login.http:
  path: '/profile/login'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::login
  methods: [POST]
  requirements:
    _user_is_logged_in: 'FALSE'
    _format: 'json'

mycustommodule.login_status.http:
  path: '/profile/login_status'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::loginStatus
  methods: [GET]
  requirements:
    _access: 'TRUE'
    _format: 'json'

mycustommodule.logout.http:
  path: '/profile/logout'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::logout
  methods: [POST]
  requirements:
    _user_is_logged_in: 'TRUE'
    _format: 'json'
    _csrf_token: 'TRUE'

mycustommodule.cancel_confirm:
  path: '/profile/{user}/cancel/confirm/{timestamp}/{hashed_pass}'
  defaults:
    _title: 'Confirm account cancellation'
    _controller: '\Drupal\user\Controller\UserController::confirmCancel'
    timestamp: 0
    hashed_pass: ''
  requirements:
    _entity_access: 'user.delete'
    user: \d+

mycustommodule.reset.login:
  path: '/profile/reset/{uid}/{timestamp}/{hash}/login'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::resetPassLogin'
    _title: 'Reset password'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

mycustommodule.reset:
  path: '/profile/reset/{uid}/{timestamp}/{hash}'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::resetPass'
    _title: 'Reset password'
  requirements:
    _access: 'TRUE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

mycustommodule.reset.form:
  path: '/profile/reset/{uid}'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::getResetPassForm'
    _title: 'Reset password'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

From my website, when I go to the http://mysite/profile, I'm redirected to the correct page (the user view), but the URL change automatically to http://mysite/user. I want keep the URL as http://mysite/profile. How can I do that? Is it possible?

3 Answers 3

8

The routes you've defined are new routes with different names and this is the reason the standard routes are still in place. If you want to override the standard routes you would have to use the same route names like user.page:.

But this is not the best approach to alter multiple routes. Better use a route subscriber:

src/EventSubscriber/RouteSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Routing\RouteSubscriberBase;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\Routing\RouteCollection;

class RouteSubscriber extends RouteSubscriberBase {

  protected function alterRoutes(RouteCollection $collection) {
    foreach ($collection->all() as $route) {
      if (strpos($route->getPath(), '/user') === 0) {
        $route->setPath(preg_replace('/^\/user/', '/profile', $route->getPath()));
      }
    }
  }


  public static function getSubscribedEvents() {
    $events = parent::getSubscribedEvents();

    $events[RoutingEvents::ALTER] = array('onAlterRoutes', -250);

    return $events;
  }

}

mymodule.services.yml

services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\EventSubscriber\RouteSubscriber
    tags:
      - { name: event_subscriber }
0
1

Answer from 4k4 is good BUT it goes through all routes which is IMHO not right. Instead try this approach:

<?php

/**
 * @file
 * Contains \Drupal\mymodule\RouteOverride\PageManagerRoutesOverride.
 */

namespace Drupal\mymodule\RouteOverride;

use Drupal\Core\Routing\RouteBuildEvent;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Discovery\YamlDiscovery;

/**
 * Class PageManagerRoutesOverride
 * Overrides paths for the Page Manager module to suit the structure of mymodule.
 */
class PageManagerRoutesOverride implements EventSubscriberInterface {

  /**
   * Path to the root of the project.
   *
   * @var string
   */
  protected $root;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs a new PageManagerRoutesOverride object.
   *
   * @param string $app_root
   *   The current application root path.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_hander
   *   The module handler service.
   */
  public function __construct($app_root, ModuleHandlerInterface $module_hander) {
    $this->root = $app_root;
    $this->moduleHandler = $module_hander;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[RoutingEvents::ALTER] = 'alterRoutes';
    return $events;
  }

  /**
   * Alters existing routes.
   *
   * @param \Drupal\Core\Routing\RouteBuildEvent $event
   *   The route building event.
   */
  public function alterRoutes(RouteBuildEvent $event) {
    // See if the Page Manager UI module is enabled.
    if (!$this->moduleHandler->moduleExists('page_manager_ui')) {
      return;
    }

    // Page manager has just too many routes and is still quite prone to changes
    // so instead of overriding them manually, we'll use the actual route definitions.
    $module_directory = $this->moduleHandler->getModule('page_manager_ui')->getPath();
    $discovery = new YamlDiscovery('routing', [$this->root . '/' . $module_directory]);
    $route_files = $discovery->findAll();

    // Get the route names.
    if (isset($route_files['page_manager_ui'])) {
      $route_names = array_keys($route_files['page_manager_ui']);
    } else {
      $route_names = [];
    }

    // Fetch the collection which can be altered.
    $collection = $event->getRouteCollection();

    // Process the routes.
    foreach ($route_names AS $route_name) {
      // Fetch the route.
      $route = $collection->get($route_name);

      // Set the new path.
      $route_path = strtr($route->getPath(), [
        '/admin/structure/page_manager' => '/mymodule/content/page-builder',
        '/admin/structure/page_variant' => '/mymodule/content/page-builder'
      ]);
      $route->setPath($route_path);

      // Some custom alterations.
      switch ($route_name) {
        case 'entity.page.collection':
          $route->setDefault('_title', 'Page builder');
          break;
      }
    }
  }

}

And the service:

mymodule.page_manager_routes_override:
  class: Drupal\mymodule\RouteOverride\PageManagerRoutesOverride
  arguments: ['@app.root', '@module_handler']
  tags:
    - { name: event_subscriber }
2
  • @ivan-jaros How to do it in D7?
    – Umair
    May 5, 2017 at 13:42
  • @Umair you can use hook_menu_alter(I think) and probably hook_link_alter(or something like that) and hook_boot(to add redirect) but easier would be to use path alias. Depends on the needs.
    – user21641
    May 5, 2017 at 14:51
0

If you aren't a coder, the Rename Admin Paths module can do this.

It allows you to rename /user routes and /admin routes in Drupal 7, 8, and 9.

Install the module, go to the config, and choose the new routes.

YOU NEED TO TEST THIS! Some contrib modules are badly coded and will break if the user route is not at /user or the /admin route is not at admin. If such an error occurs, it should be reported to that module's issue queue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.