2

We are using the Profile module and I'm trying to hide the menu tab on the user's account for certain users based on a value of a field on the user.

I have the alterRoute set.

namespace Drupal\mymodule\Routing;

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

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    // Change access for path '/user/%/myprofile'.
    if ($route = $collection->get('profile.user_page.single')) {
      $route->setRequirement('_custom_access', 'Drupal\mymodule\Access\ProfileAccessCheck::access');
    }
  }

}

I've created the services in the mymodule.services.yml file.

services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber }
  mymodule.profile_access_checker:
    class: Drupal\mymodule\Access\ProfileAccessCheck
    tags:
      - { name: access_check, applies_to: _custom_access }

And here is my ProfileAccessCheck.php

namespace Drupal\mymodule\Access;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\Routing\Route;
use Drupal\user\UserInterface;

/**
 * Checks whether the profile type allows multiple profiles per user.
 */
class ProfileAccessCheck implements AccessInterface {

  /**
   * Checks access for the single/multiple pages.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The currently logged in account.
   * @param \Drupal\user\UserInterface $user
   *   The user account.
   */
  public function access(AccountInterface $account, $user) {
    $user_access = $user->access('view', $account, TRUE);
    if (!$user_access->isAllowed()) {
      // The account does not have access to the user's canonical page
      // ("/user/{user}"), don't allow access to any sub-pages either.
      return AccessResult::allowed();
    }

    if(!empty($account->field_pro_profile->getValue()) && $account->field_pro_profile->getValue() == 'Disable') {
      return AccessResult::forbidden();
    }
    return AccessResult::allowed();
  }

}

I have a couple of issues. First is, I'm getting this error:

Error: Call to a member function access() on string in Drupal\mymodule\Access\ProfileAccessCheck->access() (line 26 of modules/custom/mymodule/src/Access/ProfileAccessCheck.php).

If I remove that access $user->access line then I get this error:

Notice: Undefined property: Drupal\Core\Session\AccountProxy::$field_pro_profile in Drupal\mymodule\Access\ProfileAccessCheck->access() (line 26 of modules/custom/mymodule/src/Access/ProfileAccessCheck.php).

I'm also getting this error on some other pages like the module enable/disable page /admin/modules:

RuntimeException: Callable "Drupal\mymodule\Access\ProfileAccessCheck::access" requires a value for the "$user" argument. in Drupal\Component\Utility\ArgumentsResolver->handleUnresolvedArgument() (line 142 of core/lib/Drupal/Component/Utility/ArgumentsResolver.php).

Why can't I access the user object, what am I missing? Also, it seems to be overriding the access from the profile module. What is the correct way to make sure I call the original module access function too? Because it does not return tabs if I do AccessResult::neutral(); it hides all tabs that match user/%/%

5
  • I think that the function declaration is incorrect and should probably be: public function access(UserInterface $user, $profileType) {.
    – Jaypan
    Commented Dec 22, 2021 at 0:39
  • 1
    public function access(UserInterface $user, AccountInterface $account) {
    – No Sssweat
    Commented Dec 22, 2021 at 14:11
  • @Jaypan Yeah I tried that too. It gives me this error. RuntimeException: Callable "Drupal\mymodule\Access\ProfileAccessCheck::access" requires a value for the "$profileType" argument. in Drupal\Component\Utility\ArgumentsResolver->handleUnresolvedArgument() (line 142 of core/lib/Drupal/Component/Utility/ArgumentsResolver.php).
    – jphelan
    Commented Dec 22, 2021 at 15:38
  • @NoSssweat that works! But I can't seem to access the $profileType. I need to check it and make sure it's the correct value in the third argument because it's effecting other user tabs besides the profile. I've tried adding it at different spots and I get this RuntimeException: Callable "Drupal\mymodule\Access\ProfileAccessCheck::access" requires a value for the "$profileType" argument. in Drupal\Component\Utility\ArgumentsResolver->handleUnresolvedArgument() (line 142 of core/lib/Drupal/Component/Utility/ArgumentsResolver.php).
    – jphelan
    Commented Dec 22, 2021 at 15:55
  • I have almost identical code for a different problem and this is the access function: public function access(UserInterface $user, AccountInterface $account) { return AccessResult::forbidden(); } and still get the same error: RuntimeException: Callable "Drupal\ssc_custom\Access\CommentReplyAccess::access" requires a value for the "$user" argument.
    – liquidcms
    Commented Apr 4, 2022 at 21:18

0

Your Answer

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

Browse other questions tagged or ask your own question.