User login

Not dead yet: Overcoming fatal errors converting a theme with some override functions in template.php

Searched words: 
module upgrade drupal 5 to 6 menu_item_link upgrading drupal 5 to D6 menu_item_link function Drupal module developer guide upgrade 5 to 6

Upgrading a theme from Drupal 5 to Drupal 6, Agaric ran across this lovely fatal error:

Fatal error: Call to undefined function menu_item_link() in /sites/example/www/sites/default/themes/agaric_custom_theme/template.php on line 15

And indeed, menu_item_link ends with Drupal 5: http://api.drupal.org/api/function/menu_item_link/5

There is, however, a theme_menu_item_link for Drupal 6: http://api.drupal.org/api/function/theme_menu_item_link/6

(There was for 5 also however, so it can't be a replacement for menu_item_link

Replacing

<?php
        $link
= menu_item_link($mid);
?>

with the theme function does NOT work:

<?php
        $link
= theme('menu_item_link', $mid);  // main problem: it expects a path, not a menu ID
?>

Found using grep -nHR menu_item_link . at the base of a Drupal 5 installation, let's look at a function that used menu_item_link() in Drupal 5:

<?php
function menu_get_active_breadcrumb() {

 

// No breadcrumb for the front page.
 
if (drupal_is_front_page()) {
    return array();
  }

 

// We do *not* want to use "variable_get('site_frontpage', 'node)" here
  // as that will create the link '/node'. This is unsightly and creates
  // a second URL for the homepage ('/' *and* '/node').
 
$links[] = l(t('Home'), '');

 

$trail = _menu_get_active_trail();
  foreach (
$trail as $mid) {
   
$item = menu_get_item($mid);
    if (
$item['type'] & MENU_VISIBLE_IN_BREADCRUMB) {
     
$links[] = menu_item_link($mid);
    }
  }

 

// The last item in the trail is the page title; don't display it here.
 
array_pop($links);

  return

$links;
}
?>

And here's the same function in Drupal 6:

<?php
function menu_get_active_breadcrumb() {
 
$breadcrumb = array();

 

// No breadcrumb for the front page.
 
if (drupal_is_front_page()) {
    return
$breadcrumb;
  }

 

$item = menu_get_item();
  if (
$item && $item['access']) {
   
$active_trail = menu_get_active_trail();

    foreach (

$active_trail as $parent) {
     
$breadcrumb[] = l($parent['title'], $parent['href'], $parent['localized_options']);
    }
   
$end = end($active_trail);

   

// Don't show a link to the current page in the breadcrumb trail.
   
if ($item['href'] == $end['href'] || ($item['type'] == MENU_DEFAULT_LOCAL_TASK && $end['href'] != '<front>')) {
     
array_pop($breadcrumb);
    }
  }
  return
$breadcrumb;
}
?>

Conclusion: it's quite different and after I concluded I didn't even need the function that was calling menu_item_link(), I realized the far more direct way to fix this was to look at the function that called it:

SEOposition's phptemplate_menu_item(), based on Drupal 5's theme_menu_item(), needed to be replaced with a version compatible with Drupal 6's theme_menu_item(). The main difference is that the function gets passed in a menu item, not a menu ID– so there is no need for menu_item_link() at all!

Before, Drupal 5 version:

<?php
function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
       
// grab text from link
       
$link = menu_item_link($mid);
       
$textbegin = strpos($link, ">") + 1;
       
$textend = strpos($link, "<", 2);
       
$textlen = $textend - $textbegin;
       
$text = substr($link, $textbegin, $textlen);
       
$text = $text.($leaf ? '' : ($children ? ':' : '&hellip;'));
       
$link = substr_replace($link, $text, $textbegin, $textlen);

        return

'<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'. $link . $children ."</li>\n";
}
?>

// adds branch indicators to menu links
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
$class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
// grab text from link
$textbegin = strpos($link, ">") + 1;
$textend = strpos($link, "<", 2);
$textlen = $textend - $textbegin;
$text = substr($link, $textbegin, $textlen);
$text = $text.($leaf ? '' : ($children ? ':' : '…'));
$link = substr_replace($link, $text, $textbegin, $textlen);

    return '<li class="' . $class . '">' . $link . $menu . "</li>\n";

}

And I still don't really get what purpose it serves, heh. But it works!

Another problem: Unsupported operand types

WHAT? (I was disconcerted because the problem seemed to be coming from Drupal core!)

Fatal error: Unsupported operand types in /sites/help4computers/www/includes/common.inc on line 1445

Ah: That's the ubiquitous l() (for Link) function that takes an array of options in D6, rather than a long comma-separated list of parameters as it did previously.

The line and file sited in the error:

<?php
function l($text, $path, $options = array()) {  // Merge in defaults.
 
$options += array(      'attributes' => array(),
     
'html' => FALSE,
    );
//...
}
?>

Solution is simply to use the Drupal 6 style array for options, which was easy because the code in question already had all the link elements as options– just had to delete all the separate listings of each array element after href and leave the link array:

<?php
      $outputbuffer
.= '(' . l($link['title'], $link['href'], $link).")";
?>

Reference:

http://drupal.org/node/132442

Resolution

Comments

Agaric saves the day again

or so this e-mail from Brian Dominick was titled:

Once more, the first Google result offering a real solution to a real
Drupal-related problem is by Benjamin Melançon.

This time I was looking for a fix to the "Fatal error: Unsupported
operand types in ....common.inc on line 1445" problem. (Wow, you gotta
love those PHP error reports. ColdFusion offers detailed information and
even suggestions about how to fix the problem and where to look in
documentation. PHP uses words like "operand" then says, "fuck you if you
want more help -- it's not like you paid for this software." Has kind of
that feel-good, ultra-elitist open-source attitude.)

Anyway, you saved the day again, without me even having to harass you.
So thanks. And I did my civic duty by posting a note on the Drupal.org
thread where I got the code that threw the error.

http://drupal.org/node/128085#comment-1099770

That's the Agaric way... making all the stupid mistakes you're going to make... first! (Oh creator-of-life PHP, forgive Brian for his faith in Coldfusion... someday he will see the light.)

Post new comment

The content of this field is kept private and will not be shown publicly.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <blockquote> <small> <h2> <h3> <h4> <h5> <h6> <sub> <sup> <p> <br> <strike> <table> <tr> <td> <thead> <th> <tbody> <tt> <output>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Lines and paragraphs break automatically.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.