EDIT: I may have realised what the problem is, or at least part of it. I've been focussing on Zen's page.tpl.php section

<?php if ($primary_links): ?>
    <div id="primary" class="clear-block">
        <?php print theme('links', $primary_links); ?>
    </div> <!-- /#primary -->
<?php endif; ?>

The problem with this, is that I'm using the standard blocks primary links with Zen's own primary links display turned off. Result? This code isn't being called at all because the links display reverts to control of the Drupal core. You can just about tell this because Zen's div has ID "primary" while Drupal's blocks div has ID "block-menu-primary-links".

This doesn't exlain why eclectus_links isn't being used yet but it certainly explains why nothing custom or even a basic print statement work.

If I solve this completely I'll post it as a comment.

END OF EDIT.

Before anyone refers me to the obvious documentation, here's what I've tried so far (where eclectus is the subtheme name):

  • templates.php is copied from the Zen STARTERKIT directory.
  • I have copied theme_links from theme.inc and renamed it eclectus_links so it now reads function eclectus_links($links, $attributes = array('class' => 'links')) .
  • I know this file is being parsed because I missed out a closing bracket when copying and it immediately broke my site.
  • 'Rebuild theme registry on every page' is on.
  • I went to Admin -> Site Config -> Performance and hit 'Clear cached data' anyway.
  • I went to Site Building -> Themes -> settings -> Eclectus and hit 'Save configuration' (a necessary extra step, I have found)

I got nothing.

Here is what I have read:

In the foreach loop, I've added a basic

if (!empty($link['title'])) {
	$link['title'] = $i . ': ' . $link['title'];
}
 

for testing so it now reads:

function eclectus_links($links, $attributes = array('class' => 'links')) {
  global $language;
  $output = '';

  if (count($links) > 0) {
    $output = '<ul'. drupal_attributes($attributes) .'>';

    $num_links = count($links);
    $i = 1;

    foreach ($links as $key => $link) {
      $class = $key;

      // Add first, last and active classes to the list of links to help out themers.
      if ($i == 1) {
        $class .= ' first';
      }
      if ($i == $num_links) {
        $class .= ' last';
      }
      if (!empty($link['title'])) {
        $link['title'] = $i . ': ' . $link['title'];
      }
      if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))
          && (empty($link['language']) || $link['language']->language == $language->language)) {
        $class .= ' active';
      }
      $output .= '<li'. drupal_attributes(array('class' => $class)) .'>';

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
        $output .= l($link['title'], $link['href'], $link);
      }
      else if (!empty($link['title'])) {
        // Some links are actually not links, but we wrap these in <span> for adding title and class attributes
        if (empty($link['html'])) {
          $link['title'] = check_plain($link['title']);
        }
        $span_attributes = '';
        if (isset($link['attributes'])) {
          $span_attributes = drupal_attributes($link['attributes']);
        }
        $output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>';
      }

      $i++;
      $output .= "</li>\n";
    }

    $output .= '</ul>';
  }
}
 

Nothing.

I've also tried dropping in

function eclectus_indylinkclass ($links) {
	$message = '\n<!-- eclectus_indylinkclass: nothing -->\n';
	$eye = 1;

	if (count($links) > 0)
	{
		$message =  '\n<!-- \n';
		foreach ($links as $link)
		{
			$message .= 'eclectus_indyclasslinks' . $eye . ': ' . $link['href'] . "\n";
			++$eye;
		}
		$message .= '-->\n';
	}
	
	return $message;
}

with the intention of trying to alter only the primary links before they hit theme_links (yes, I will be checking that) but no comments appear in my source code when I call it in page.tpl.php as either $eclectus_indyclasslink or indyclasslink. No ouput, no errors.

This is driving me somewhat bananas.

Comments

UrbanFuturistic’s picture

EDIT: I hadn't taken account of Zen's use of menu_item_link for styling tabs. Copied the code from its own template.php and updated the code down at the bottom. The home link was coming up with an ID of ecen- and nothing further despite code that's supposed to resolve this.

 if ($link['link_path'] == '') {
    $link['link_path'] = 'front';
} 

is now

 if ($link['link_path'] == '<front>') {
    $link['link_path'] = 'front';
} 

END OF EDIT

The problem was with the misdirection of Zen using theme_links for its output of the primary links whereas the standard approach is to use theme_menu_item and theme_menu_item_links. Took me a while to track all that down as the downside to Drupal's overrideability is that function names are concatenated and never directly stated (for those new to this, theme_menu_item_link is called with something like theme('menu_item_link', $data['link'])' ). Maybe that can be a project for me when I've got more free time, to drop comments on such function calls so that people know what function is called by default.

Anyway, starting with the code available at: http://www.orangebus.co.uk/blog/tom/2009-12-22/automatic-unique-ids-drup...

In case that goes down (site drop off the internet all the time after all), my current code is:

function eclectus_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  
  // Our custom code starts here. >>>
  
  // Check for the menu we need
  if ($link['menu_name'] == 'primary-links') {
    /*
     * If this item points to the site front page, remove the < > symbols
     * or this keyword will result in the link target path being just '/'
     * and so your id will just be 'nav_', as opposed to 'nav_front'. Change
     * to suit your preference.
     */
    if ($link['link_path'] == '<front>')
	 {
      $link['link_path'] = 'front';
    }
   
    /*
     * Generate URL from the link path, replace slashes with hyphens
     */
    $link['localized_options']['attributes']['id'] = 'ecen' . strtr(url($link['link_path']), '/', '-');
  }
 
  // <<< Our custom code ends here.

  //Necessary code from Zen starts here

  // If an item is a LOCAL TASK, render it as a tab
  if ($link['type'] & MENU_IS_LOCAL_TASK) {
    $link['title'] = '<span class="tab">' . check_plain($link['title']) . '</span>';
    $link['localized_options']['html'] = TRUE;
  }

  //Code from Zen ends here

  return l($link['title'], $link['href'], $link['localized_options']);
}

Now all I need to do is sort localisation so it's different images dependent on country.

robonoob’s picture

Thanks. I am learning theming stuff. This give me some ideas on how to theme menu item in blocks, and it is nice.

I saw that you have added your own theme_links function, and it was not called. And your theme_menu_item_link($link) function applies only on the primary menu in a block.

I would love to know, however, as Zen use theme('links', $primary_links), how can I override the function? Same as you, I added my own version of theme_links function, and found that it was not called. ( I commented out the return $output line, and if it were called, the primary links and secondary links should be ignored)

Or should I use only the primary menu in a block?

UrbanFuturistic’s picture

Rule 1: Drupal can be a bit funny, even if rebuilding is on all the time so this can confuse the issue. If you want to be really sure it's not working, manually clear the cache and then go to the theme configuration page and, without changing anything, hit the 'save changes' button. The last bit is particularly important when making changes to the .info file of your theme.

Rule 2: When building a subtheme, always check in the original theme's 'template.php' to see if it overrides the same function you're trying to override. If you override the same function you'll need to copy the code from Zen, not the original code from the module. The above example was where I had to copy said code because not doing so knackered the nice tabbed look menus.

OK, short version. I turned off the Zen tickbox for Primary Links which means the call in the theme doesn't get used. Personally I'm not a fan of he builtin version because it's difficult to move and IMO makes it harder to use as well as being a duplicate if you add the menu-block for primary Links. Same goes for the search bar.

There was then the problem of disparity in that Zen calls theme_links() and the blocks method calls theme_menu_item_link(). So, when I dropped the Zen primary links and added the menu block, the former stopped getting called for primary links in favour of the latter. Basically, it didn't work because I was changing the wrong function.

So, if you're using the Zen version you'll have to edit the HTML to move it and it will call theme_links(). If you use blocks it will call theme_menu_item_link().

What you're seeing when it calls theme('links', $primary_links) is proper calling of a themable function. What happens there is that theme() takes the first parameter, looks for one called _links() and if it doesn't find it falls back on theme_links(). When it calls whichever function it finds it then passes every other parameter it's got onto that function. So for reasons of overriding the look of the i18n language menu I've overriden theme_links for the theme eclectus with eclectus_links after all. This means that before this, theme('links', $primary_links) would have resulted in a call to theme_links($primary_links), now it results in a call to eclectus_links($primary_links).

Hopefully, this isn't too confusing. I've not been entirely well today so I'm a little fuzzy and I'm not certain this is as clear as it could be.

I'm not sure if I mentioned it and it got lost in all the above, but if you look at the IDs in the HTML you'll often find clues to what's generated a portion of the page as the ID is generated based entirely on its purpose. In the above case, the ID comes up as block-menu-primary-links. Other IDs for menus might be block-locale-0 for example. So, the menu has been generates by the block module, which has called the menu module. Usually when this happens you get something like block-menu-0 but primary and secondary links are special cases and so get their own specific IDs (with the idea that they won't be duplicated).

This is something of an asides but it's a slightly easier starting point for tracking what code does what.

robonoob’s picture

Thanks. I'll check it again to see if I missed something, such as flashing theme cache, template code.....etc.

adrianmak’s picture

tagged

UrbanFuturistic’s picture

Still a tad new to this site: what does 'tagged' mean?

herojig’s picture

I noticed this too, although I don't understand your workaround (yet). I am building a zen subtheme here:
www.animalnepal.org/drupal_hum and the unexpected naming is throwing me.

But what I am trying to fix now is that I lost the username in the upper left corner (top of navigation) and don't know how to get it back. I realize my subtheme is a bit of a mess now, but I think my problem is somehow related to this?

Phoenix.Consultants.Nepal (www.phoenixstudiosnepal.com)