1

I am altering an existing route and adding a custom access. The custom access is a method that I want to have it in it's own access controller:

  /**
   * Alters existing routes.
   */
  public function alterRoutes(RouteBuildEvent $event) {
    $collection = $event->getRouteCollection();

    if ($route = $collection->get('entity.node.clone_form')) {
      // Add custom access
      $route->setRequirement('_custom_access', '\Drupal\eclone_extras\Controller\EcloneExtrasAccessController::access');
    }
  }

Then in my access controller I have:

namespace Drupal\eclone_extras\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class EcloneExtrasAccessController extends ControllerBase{

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity type ID.
   *
   * @var string
   */
  protected $entityTypeId;

  /**
   * Constructs a new ContentEntityCloneBase.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param string $entity_type_id
   *   The entity type ID.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, $entity_type_id) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityTypeId = $entity_type_id;
  }

  /**
   * {@inheritdoc}
   */
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
    return new static(
      $container->get('entity_type.manager'),
      $entity_type->id()
    );
  }
  /**
   * Custom access checker for the create lock requirements route.
   *
   * @see \Drupal\content_lock\Routing\ContentLockRoutes::routes()
   */
  public function access() {
    // do access stuff
    return TRUE;
  }

}

But I keep getting the following errors:

0 passed in /var/www/drupal8/web/core/lib/Drupal/Core/Controller/ControllerBase.php on line 118 and exactly 2 expected in Drupal\eclone_extras\Controller\EcloneExtrasAccessController->__construct() (line 36 of modules/custom/eclone_extras/src/Controller/EcloneExtrasAccessController.php).
  • 1
    You need your class to extend Controllerbase or implement ContainerInjectionInterface yourself, otherwise the class resolver can't provide you with the container to get the injected services from. – 4k4 Jun 21 '18 at 18:27
  • @4K4 sorry, this was with extend ControllerBase as you can tell from the error. I updated the code. – awm Jun 21 '18 at 18:41
  • 3
    OK, then it's createInstance(), which should be named create() to override the method in ControllerBase. – 4k4 Jun 21 '18 at 18:47
  • I think access() should return Drupal\Core\Access\AccessResult. For example, Drupal\Core\Access\AccessResult::allowed(). – imclean Feb 5 at 22:45
  • 4k4 is correct, createInstance should be create(), overriding ControllerBase::create api.drupal.org/api/drupal/… – Jaypan Feb 5 at 23:05
0

This can be done using services. Here's an example which injects the entity type manager interface.

eclone_extras.services.yml:

services:
  eclone_extras.access:
    class: Drupal\eclone_extras\Access\EcloneExtrasAccess
    arguments: ['@entity_type.manager']

Route subscriber:

 /**
   * Alters existing routes.
   */
  public function alterRoutes(RouteBuildEvent $event) {
    $collection = $event->getRouteCollection();

    if ($route = $collection->get('entity.node.clone_form')) {
      // Add custom access
      $route->setRequirement('_custom_access', 'eclone_extras.access::access');
    }
  }

Access class:

namespace Drupal\eclone_extras\Access;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

class EcloneExtrasAccess {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs a new ContentEntityCloneBase.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param string $entity_type_id
   *   The entity type ID.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * Custom access checker for the create lock requirements route.
   *
   * @see \Drupal\content_lock\Routing\ContentLockRoutes::routes()
   */
  public function access() {
    // do access stuff
    return AccessResult::allowed();
  }

}

The access callback gets some parameters as well, such as Account and possibly request.

Refs:

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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