0

I have a node with ID equal to 60, which has a URL alias that is "mynodes/about-us." I would like to change the access callback of that node to myfunction().

It doesn't work when I use the URL alias:

function celsis_forms_menu_alter(&$items) {
    $items['mynodes/about-us']['access callback'] = myfunction;
}

function myfunction() {
     return FALSE;
}

But it works when I use the node number:

$items['node/60']['access callback'] = myfunction;

How can I get the url alias to work and would it be possible to change the access callback for all nodes with alias starting with mynodes/*?

2

You cannot do that because when Drupal invokes hook_menu() and hook_menu_alter() the value contained in $_GET['q'], which is used to find the menu callback to use, has been already changed from the path alias to the normal path. drupal_path_initialize(), which is called by drupal_bootstrap() contains the following code:

  if (!empty($_GET['q'])) {
    $_GET['q'] = drupal_get_normal_path($_GET['q']);
  }
  else {
    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
  }

What you are trying to achieve can be accomplished in another way: implementing hook_node_access(). Differently from the equivalent hook in Drupal 6, it can be implemented also from modules that don't define a new content type.

function mymodule_node_access($node, $op, $account) {
  if ($op == 'view') {
    $path_alias = request_path();
    // ...
  }
}

$account contains the user object to which is being given access to the node. If the hook returns NODE_ACCESS_ALLOW, then the user has access to the node for the operation passed in $op; if the hook returns NODE_ACCESS_DENY, the user doesn't have access to the node; when it returns NODE_ACCESS_IGNORE, it leaves to other modules the decision.

request_path() returns the path alias if one was used. This means that if the user is using a URL like example.com/node/60, it returns "node/60"; if the user is using example.com/mynodes/about-us, which is an alias for example.com/node/60, it returns "mynodes/about-us." In the case the user is using example.com/index.php, the function returns an empty string.

| improve this answer | |
2

How about this? It's a bit of a simpler alternative. I'm guessing that you want the access callback to continue functioning even if you later create a new node and give it this same alias:

    function celsis_forms_menu_alter(&$items) {
      // Retrieve the Drupal system path for the page's alias
      $about_us_path = drupal_get_normal_path('mynodes/about-us');
      $items[$about_us_path]['access callback'] = 'myfunction';
    }

    function myfunction() {
      return FALSE;
    }

Note that if you do point this alias at a different node, you will need to clear the cache for this logic to keep working. hook_menu_alter is called when the menu is rebuilt.

| improve this answer | |
  • Drupal doesn't define a menu callback for "node/60"; using that hook implementation, you are probably going to get a partial menu callback definition. – kiamlaluno Nov 5 '11 at 2:55
  • 1
    kiamlaluno is right -- you need to if (!isset($items[$about_us_path])) $items[$about_us_path] = $items['node/%']; just before the 'myfunction'. – user49 Nov 5 '11 at 13:41
  • The OP said node/60 worked, so I was running with that assumption. If it doesn't, my code would need to be adapted. The underlying logic is what I wanted to convey. Thanks for enhancing and correcting it! – wizonesolutions Nov 5 '11 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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