Awhile back I noticed that the node_page_title() function in node.module was frequently producing run-time warnings because its argument wasn't an object.
I submitted a work-around patch which got rejected. I was told to find and fix the offending code that is calling the function incorrectly.
In my installation, the usual offender is buried within the _menu_item_localize() function of the includes/menu.inc file. Specifically, at around line 503, is the following line of code:
$item['title'] = call_user_func_array($callback, menu_unserialize($item['title_arguments'], $map));
For at least some of my menu options, $callback is equal to "node_page_title". When that occurs, the code is incorrect for at least the reason that menu_unserialize() always returns an array instead of the object that node_page_title() expects.
Worse, the array it returns (at least on my installation) is something like Array ([0] => 29)) which, even if it were converted to an object, obviously doesn't contain the page title. The unserialized version contained in the database is always a:1:{i:0;i:1;} which apparently is a default value.
For the most recent traceback in my logs, the relevant call chain is:
-
_menu_link_translate()calls_menu_item_localize($item, $map, $link_translate)with$item['title_callback']set to'node_page_title'$item['title_arguments']set to'a:1:{i:0;i:1;}'$mapset toArray ([0] => 'node', [1] => 29)$link_translateset to1
-
_menu_item_localize()callsnode_page_title($node)with$nodeset toArray ([0] => 29)
-
node_page_title()throws an error- because its only line of code assumes that
$node->titleexists.
I'm sorry that I don't have a fix for the problem. For now, on my site, I'm going to work around the problem as follows:
/**
* Title callback.
*/
function node_page_title($node) {
if (!(is_object($node))) {
if (is_array($node)) {
if (is_integer($node[0])) {
$node = node_load($node[0]);
}
else {
$node = node_load($node);
}
}
elseif (is_integer($node)) {
$node = node_load($node);
}
else {
return NULL;
}
}
return $node->title;
}
Please feel free to find and implement a simpler, more rational fix.
Comments
Comment #1
Anonymous (not verified) commentedOne of the reasons why typecasting the parameters would be very good. But to resolve the issue of using the result of menu_unserialize() as a parameter you can typecast the result with (object)menu_unserialize() and the array parameters will become object parameters.
I disagree with the mentality of
and would much rather have the function protect itself from misuse. It is too bad that this issue will be carried into D7.
Comment #2
pillarsdotnet commentedActually, typcasting to an object still wouldn't solve the problem, as the array doesn't have a key called 'title'.
Comment #3
damien tournoud commentedThat means that some module in your installation is trying to do something apparently silly. I believe that node_page_title() is *not* called with
array(29), but simply with the integer29, which basically means that node_load(29) is not called, or that something misbehaves somewhere in the process.Could you try to dump the full
$itemwhich makes the error appear?Comment #4
damien tournoud commented@pillarsdotnet: any news about that? have you been able to dump the full
$item?Comment #5
pillarsdotnet commentedSorry; haven't checked status in a couple of days.
If you look at the code of the node_page_title() function, it expects to be passed an object, not an integer or an array.
I can give you the backtrace from which I inferred the original report. In that particular case, the offending menu item is a link to a book page.
node_page_title(29)call_user_func_array(node_page_title, Array (0 => 29))called at includes/menu.inc:503
called at includes/menu.inc:661
called at includes/menu.inc:1009
(...skipping other menu items for brevity...)
(...skipping other menu items for brevity...)
called at includes/menu.inc:947
menu_tree_page_data(primary-links)called at includes/menu.inc:1252
menu_navigation_links(primary-links)called at includes/menu.inc:1217
menu_primary_links()called at includes/theme.inc:1809
Comment #6
pillarsdotnet commentedComment #7
pillarsdotnet commentedWell, I'm not using d6 anymore, and it appears that nobody else has experienced this problem, so I'm going to close the issue.
Comment #8
dman commentedFor searchers that may find this issue: This issue is the best analysis of the actual problem ... though the root cause that gets us here is still undefined.
I also agree that Drupal core should include a lot more assertions, input checking and waterproofing against unexpected input. But I can't convince anyone of that either.
Anyway - I HAVE encountered this in D7, though replicating it is indescribable - I was called in to pick up a site with 120 experimental modules turned on and off so there is no audit trail.
After disabling all the suspects I could find mentioned in other threads, including
search by page, #1709914: Notice: Trying to get property of non-object in node_page_title() (Zeile 2108 von /var/www/modules/node/node.module).
menu_block #1318210: "Trying to get property of non-object in node_page_title" error when cron runs from page view trigger.
page title #961778: Trying to get property of non-object in node_page_title_pattern_alter()
ds_extras, and taxonomy_menu
It still didn't go away.
Eventually I found some dud data in my menu table:
- the menu_name entries of "0", and "Array" are screwy and I dunno how they got there. Somebody was playing with dev modules I think.
Looking at them, I confirmed that the entries were reflecting the pages this error was showing on.
The DB rows were abnormally empty as well.
Hm. On a test copy,
fixed it for me!. (be sure to quote the '0' or you will destroy the world)
HOW it got into this state, I can't guess. Could be the menu was provided by a module that was since disabled or deleted. Or taxonomy_menu - which builds menus on the fly all the time had an aneurism at some point.
Comment #9
Anonymous (not verified) commentedBut only for development. If a method were devised that could filter out the assertions (i.e. remove the assertions from the code) for a production ready site you might get some attention.
Comment #10
rooby commentedI have seen this on a number of Drupal 7 sites where a node page has been added to the management menu, under the Administration menu item, with the drupal core toolbar module enabled.
So that you have added a new item to the toolbar.
When toolbar_get_menu_tree() runs and there is a manually created node/23 type path in there you get this error.
This seems to consistently cause the problem.
I have yet to dig deeper into why.
Comment #11
rooby commentedIt is because of this (from _menu_link_translate()):
Because menu_tree_check_access() has previously been called, _menu_load_objects() is not called, however _menu_item_localize() can still be called after that and it relies on _menu_load_objects() having already been run.
_menu_load_objects() should always be called before _menu_item_localize().
I will search the issue queue for existing issues for this when I get home or else open a new issue.
Comment #12
rooby commentedI will be following that up in #1697570: _menu_load_objects() is not always called when building menu trees