The second function 'example_user_access()' (two listed below) implements the 'hook_user_access()' function. The line:

$account = array_shift($arguments);

I understand is set to '%user'. So if we were at the url 'user/jmm42/content', then it should be:

$account = jmm42.

http://php.net/manual/en/function.array-shift.php

However, the code implies the value 'jmm42' is keyed by 'uid', where:

$account->uid = jmm42 // (#1)

- - -

<?php
function example_menu() {
 
$items['user/%user/content'] = array(
   
'title' => 'Content creation',
   
'page callback' => 'example_user_page',
   
'page arguments' => array(1),
   
'access callback' => 'example_user_access',
   
'access arguments' => array(1, 'view content creation permissions', 'administer users'),
   
'type' => MENU_LOCAL_TASK,
  );
  return
$items;
}
function
example_user_access() {
  global
$user;
 
$arguments = func_get_args();
 
$account = array_shite($arguments);
  if (
$account->uid != $user->uid) {  // (#1)
   
return FALSE;
  }
  foreach (
$arguments as $permission) {
    if(!
user_access($permission)) {
      return
FALSE;
    }
  ]
  return
TRUE;
}
?>

Comments

jmm42’s picture

The example (provided below), takes %node and assigns it to the '$node->type'. Where is this key 'type' coming from? So, if we were at the url 'node/abc/test'

the code implies the value 'abc' is keyed by 'type', namely:

$node->type == 'abc' ... // (#2)

Can someone direct me to what file / function in core that makes these assignments (#1), (#2)?

- - -

<?php
function addtabexample_menu() {
 
$items = array();

 
$items['node/%node/test'] = array(
   
'title' => 'Test',
   
'page callback' => 'handle_test',
   
'page arguments' => array('node', 1),
   
'access callback' => 'addtabexample_access_callback',
   
'access arguments' => array(1),
   
'type' => MENU_LOCAL_TASK,
   
'weight' => 100,
  );

  return
$items;
}

function
addtabexample_access_callback($node) {
  return
$node->type == 'abc' && user_access('access content');  // (#2)
}
?>
goofus’s picture

Hello,
The detailed answer nevets has provided is exactly correct. My suggestion is in addition to that correct answer.

I've noticed you've posted a lot of really good questions (in this forum). Another way of getting your questions answered is to run Drupal through a standard source code debugger. For php. I use xdebug along with an IDE. The IDE provides the debugger with an easy to use, GUI front end. There are many free IDE's to choose from. I use Netbeans for an IDE -- php version (http://netbeans.org/). XDebug as a debugger (http://xdebug.org/). There is a wiki for the setup here: http://wiki.netbeans.org/HowToConfigureXDebug. Again there are many other fine IDE's. Netbeans just happens to be the one I am using for PHP projects (like Drupal).

If you run Drupal through a debugger, you can step through the code processing and inspect the data structures. For me, it's the best way to make full use of "open source" :) Thus, I highly recommend checking it out. Specially with someone like your self who has a healthy curiosity !! (meant as a complement :) ).

Good Luck :)

Thinking is the best way to travel.

nevets’s picture

It is a combination of the path (user/%user/content) and the page arguments (array(1)).

A number (1) in the array of page arguments says to use that part of the path (0 would be 'user', 1 is '%user' and 2 is 'content'). The %user (as well as %node) tells Drupal to call user_load (node_load) with the value in the path (a user id) and the value returned is what is passed the callback.

jmm42’s picture

Ah, yes -- had forgotten about that. What if the path looked like: user/%/content -- would a loader function get called, or would we just simply pass that magic value '%' as a parameter to respective segments of the hook_menu()?

jmm42’s picture

In, this case, no loader function is called for the second portion of the url, namely '%':

user/%/content

Rather, only the access argument is substituted with the '%' value. For more details:

http://drupal.org/node/109153

- - -

For more information:

'menu_router_build()' invokes 'hook_menu()' defined within the 'menu.inc'. This function contains '_menu_router_build()' which invokes each of the load functions (in our case 'user_load()'). The load function (and more generally, the menu router items) is cached within the following line of 'menu_router_build()':

_menu_router_cache($menu);