2

I am trying to remove items from a menu based on the type of node it links to.

I'm currently achieving this using hook_menu_link and menu_get_object. I'm running into problems because the size of the menu is 500+ items, resulting in 5000+ DB queries to generate the page.

If I remove the hook_menu_link function and show all menu items, the DB queries drop to around 700.

Here is the current code:

function amoss_menu_link(&$variables) {

  // Hide book sections from the menu;.
  if (isset($variables['element']['#original_link']['link_path'])) {
    if ($variables['element']['#original_link']['menu_name'] == 'book-toc-1') {
      if (book_modifications_is_book_section($variables['element']['#original_link']['link_path'])) {
        return '';
      }
    }
  }

  // Output a menu link.
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}

function book_modifications_is_book_section($link_path) {

  if (book_modifications_get_type_from_link_path($link_path) == 'book_section') {
    return TRUE;
  }

  return FALSE;
}

function book_modifications_get_type_from_link_path($link_path) {
  $node = menu_get_object('node', 1, $link_path);

  if (isset($node->type)) {
    return $node->type;
  }
  else {
    return '';
  }

}

I tried to use drupal_static in the book_modifications_get_type_from_link_path function, that killed the conditional checks.

I tried caching the results for each item with set_cache, but this was not successful either.

function book_modifications_get_type_from_link_path( $link_path ) {

    if ($cache = cache_get('book_modifications_'. $link_path )) {
        $type = $cache->data;
    }
    else {
        // Do your expensive calculations here, and populate $my_data
        // with the correct stuff..
        $node = menu_get_object('node', 1, $link_path);
        $type = isset( $node->type ) ? $node->type : '';
        // dpm('miss');
        cache_set('book_modifications_'. $link_path, $type, 'CACHE_TEMPORARY');
    }

        // dpm($type);
    return $type;
}

I appreciate any suggestions for making this slow operation faster.

0

Gathering node paths for the book_section nodes in a function cached with drupal_static and using removing items from the menu based on that, rather than loading node objects for each menu item removed thousands or surplus DB queries.

Refactored code

function amoss_menu_link(&$variables) {

  // Hide book sections from the menu;.
  if (isset($variables['element']['#original_link']['link_path'])) {
    if ($variables['element']['#original_link']['menu_name'] == 'book-toc-1') {
        $book_sections = book_modifications_get_book_section_paths();

      if ( in_array( $variables['element']['#original_link']['link_path'], $book_sections ) ) {
        return '';
      }
    }
  }

  // Output a menu link.
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}



function book_modifications_get_book_section_paths() {
    $book_section_paths = &drupal_static(__FUNCTION__);

    if (!isset($book_section_paths)) {
        $book_section_paths = array();
        $nids = db_select('node', 'n')
        ->fields('n', array('nid'))
        ->condition('type', 'book_section', '=')
        ->execute()
        ->fetchCol();

        foreach ( $nids as $id ) {
            $book_section_paths[] = 'node/'.$id;
        }

    }

    return $book_section_paths;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.