Drupals node building mechanism

(This walkthrough done on pre-4.5 CVS code in August 2004.)

The node_page controller checks for a $_POST['op'] entry and, failing that, sets $op to arg(1) which in this case is the '1' in node/1. A numeric $op is set to arg(2) if arg(2) exists, but in this case it doesn't ('1' is the end of the URL, remember?) so the $op is hardcoded to 'view'. Thus, we succeed in the 'view' case of the switch statement, and are shunted over to node_load(). The function node_load() takes two arguments, $conditions (an array with nid set to desired node id -- other conditions can be defined to further restrict the upcoming database query) for which we use arg(1), and $revision, for which we use _GET['revision']. The 'revision' key of the _GET array is unset so we need to make brief stop at error_handler because of an undefined index error. That doesn't stop us, though, and we continue pell-mell into node_load using the default $revision of -1 (that is, the current revision). The actual query that ends up being run is

SELECT n.*, u.uid, u.name, u.picture, u.data FROM node n INNER JOIN users u on u.uid WHERE n = '1'

We get back a joined row from the database as an object. The data field from the users table is serialized, so it must be unserialized. This data field contains the user's roles. How does this relate to the user_roles table? Note that the comment "// Unserialize the revisions and user data fields" should be moved up before the call to drupal_unpack().

We now have a complete node that looks like the following:




This is a test node body








a:1:{s:5... (serialized data)














array containing one key-value pair, 0 = '2'








This is a test node body











All of the above are strings except the roles array.

So now we have a node loaded from the database. It's time to notify the appropriate module that this has happened. We do this via the node_invoke($node, 'load') call. The module called via this callback may return an array of key-value pairs, which will be added to the node above.

The node_invoke() function asks node_get_module_name() to determine the name of the module that corresponds with the node's type. In this case, the node type is a page, so the page.module is the one we'll call, and the specific name of the function we'll call is page_load(). If the name of the node type has a hyphen in it, the left part is used. E.g., if the node type is page-foo, the page module is used.

The page_load() function turns out to be really simple. It just retrieves the format, link and description columns from the page table. The 'format' column specifies whether we're dealing with a HTML or PHP page. The 'link' and 'description' fields are used to generate a link to the newly created page, however, those will be deprecated with the improved menu system. To that extend, the core themes no longer use this information (unlike some older themes in the contributions repository). We return to node_load(), where the format, link and description key-value pairs are added to the node's definition.

Now it's time to call the node_invoke_nodeapi() function to allow other modules to do their thing. We check each module for a function that begins with the module's name and ends with _nodeapi(). We hit paydirt with the comment module, which has a function called comment_nodeapi(&$node, $op, arg = 0). Note that the node is passed in by reference so that any changes made by the module will be reflected in the actual node object we built. The $op argument is 'load', in this case. However, this doesn't match any of comment_nodeapi()'s symbols in its controller ('settings', 'fields', 'form admin', 'validate' and 'delete' match). So nothing happens.

Our second hit is node_nodeapi(&$node, $op, $arg = 0) in the node.module itself. Again, no symbols are matched in the controller so we just return.

We'll try again with taxonomy_nodeapi(&$node, $op, $arg = 0). Again, no symbols match; the taxonomy module is concerned only with inserts, updates and deletes, not loads.

Note that any of these modules could have done anything to the node if they had wished.

Next, the node is replaced with the appropriate revision of the node, if present as an attribute of $node. It is odd that this occurs here, as all the work that may have been done by modules is summarily blown away if a revision other than the default revision is found.

Finally, back in node_page(), we're ready to get down to business and actually produce some output. This is done with the statement print theme('page', node_show($node, arg(3)), $node->title);

And what that statement calls is complex enough to again warrant another commentary. (Not yet done.)

0 0

Post a comment