5

I am trying to restrict node access for anonymous users based on a custom field. I got it working for accessing the node directly like this:

$country = "GB";
if ($node->hasField('field_country_hide')) {
  $country_code = $node->field_country_hide->value;

  if ($country_code == $country) {
    // this user should not be allowed to see this article
    return AccessResult::forbidden();
  }
} else {
  return AccessResult::neutral();
}

But this doesn't restrict access for the node in a view listing. What is the best way to go about hiding a node in a view listing?

3
  • is this a page view or block view?
    – No Sssweat
    Commented Aug 12, 2016 at 5:12
  • The answer that I have in mind depends on it, so please specify.
    – No Sssweat
    Commented Aug 12, 2016 at 13:32
  • @NoSssweat it is a page view.
    – Janey
    Commented Aug 15, 2016 at 14:56

2 Answers 2

3

Drupal doesn't evoke hook_node_access() when executing a view; it's querying the DB directly to get the data. As such, you're not going to be able evoke the same PHP snippet to have Views filter the result.

The "best" way (read: simple) is to have views create a query filter that does the same thing; you can add a Content: Country Hide filter (or whatever your custom field is named) with the Operator set to Is equal to and the Value set to GB.

That will filter the nodes as you need, but you'll still need to provide the context (i.e. is the user anonymous or not). Here it's unclear. There's no "best" because there's not one way to provide context and it will depend on your needs.

One idea that comes to mind is to add 2 View blocks, one with the GB filter and one without, and set the block to display depending on the user role. But again, this will depend on your requirements. There's always custom Views integration or, if you want to go the site builder route, other modules that provide context like Context, Panels, etc.

1
  • 1
    That's the same idea I had in mind, use different view blocks and change the access from permission to role. Since @Janey is using a page view, she could have an empty page view and create 2 different attachments instead of blocks, or create a custom module or custom node to create a custom path where she puts those view blocks in.
    – No Sssweat
    Commented Aug 18, 2016 at 4:05
0

For doing access control on views, i used the hook_views_post_execute.

To hide certain nodes for anonymous user, it can be something like this

 function my module_views_post_execute(ViewExecutable $view)
 {

$user=\Drupal::currentUser();
$userRole=$user->getAccount()->getRoles();
$anonymous=$user->isAnonymous();


if ($view->id() == 'your_view_machine_name') {
foreach ($view->result as  $elementKey => $result ) {
    $node=$result->_entity;  
    $anonymous_hidden=$node->field_intranet_only->getValue();

    // Remove node if no rights
    if (($anonymous_hidden[0]['value'] == true) && ($anonymous==true) ){
          unset($view->result[$elementKey]);
    }
}
}
 }

Your Answer

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

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