hook_menu_alter () для переопределения LOCAL_TASK с помощью MENU_NORMAL_ITEM - PullRequest
1 голос
/ 16 февраля 2011

Я хочу переопределить вкладку, которая отображается в профиле пользователя, и вместо этого сделать ее пунктом меню в основных ссылках.

Например, я использую модуль Пригласить, который определяет некоторые пункты меню, в том числе ...

function invite_menu() {

  // bunch of menu items...

  // User profile tabs
  $items['user/%user/invites'] = array(
    'title' => 'Invitations',
    'page callback' => 'invite_user_overview',
    'access callback' => 'invite_user_access',
    'access arguments' => array('track invitations', 1),
    'type' => MENU_LOCAL_TASK,
    'file' => 'invite_admin.inc',
  );
}

Так как я хочу переопределить это MENU_LOCAL_TASK, я определяю hook_menu_alter () следующим образом, устанавливая элемент как Вместо этого MENU_NORMAL_ITEM в основных ссылках.

function mymod_menu_alter(&$items) {

  if (!empty($items['user/%user/invites'])) {
    $items['user/%user/invites']['title'] = 'My Override';
    $items['user/%user/invites']['type'] = MENU_NORMAL_ITEM;
    $items['user/%user/invites']['menu_name'] = 'primary-links';
  }
}

Пока все хорошо ... Я перестраиваю menu_router, чтобы увидеть изменения, и пункт делает не отображаются в основных ссылках.

Проходя по коду, я обнаружил, что после перестройки menu_router мой новый пункт меню запускается через menu_link_save () (menu.inc). Мой пункт меню входит в эта функция с первичными ссылками, установленными как "menu_name". Но это перезаписывается в меню навигации следующим образом.

function menu_link_save(&$item) {
  // ...
  // do some stuff
  // ...

    // -----------------------------------------------------------
    // THIS FAILS
    // -----------------------------------------------------------
    if (isset($item['plid'])) {
    $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE mlid = %d", $item['plid']));
  }

У моего товара нет пледа. Если бы это было так, мы бы потом стали золотом ...

  else {
    // Find the parent - it must be unique.
    $parent_path = $item['link_path'];
    $where = "WHERE link_path = '%s'";
    // Only links derived from router items should have module == 'system', and
    // we want to find the parent even if it's in a different menu.

    // -----------------------------------------------------------
    // THIS PASSES, SO ...
    // -----------------------------------------------------------
    if ($item['module'] == 'system') {
      $where .= " AND module = '%s'";
      $arg2 = 'system';
    }
    else {
      // If not derived from a router item, we respect the specified menu name.
      $where .= " AND menu_name = '%s'";
      $arg2 = $item['menu_name'];
    }
    do {

      // -----------------------------------------------------------
      // WE FIND THE PARENT ("user/%")
      // -----------------------------------------------------------
      $parent = FALSE;
      $parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
      $result = db_query("SELECT COUNT(*) FROM {menu_links} ". $where, $parent_path, $arg2);
      // Only valid if we get a unique result.
      if (db_result($result) == 1) {
        $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} ". $where, $parent_path, $arg2));
      }
    } while ($parent === FALSE && $parent_path);
  }

Итак, теперь у нас есть родитель, и это 'user /%', чье "menu_name" - "навигация". Хорошо, но это не подходит для моего пункта меню, который хочет жить по основным ссылкам. Что происходит дальше, это перезапись ...

  if ($parent !== FALSE) {
    $item['menu_name'] = $parent['menu_name'];
  }

Мой вопрос: как мне этого добиться? Из того, что я могу собрать, мне нужен плед, или что-то, что создает плед. Похоже, это не должно быть очень сложно. Чего мне не хватает?

1 Ответ

2 голосов
/ 17 февраля 2011

Как вы сказали: «Мне нужен plid или что-то, что создает plid» - так что если вы хотите, чтобы ваш элемент отображался на верхнем уровне меню первичных ссылок, вы можете попробовать добавить plid 0 ( == нет родителя == запись верхнего уровня) в вашей записи hook_menu_alter:

function mymod_menu_alter(&$items) {

  if (!empty($items['user/%user/invites'])) {
    $items['user/%user/invites']['title'] = 'My Override';
    $items['user/%user/invites']['type'] = MENU_NORMAL_ITEM;
    $items['user/%user/invites']['menu_name'] = 'primary-links';
    $items['user/%user/invites']['plid'] = 0;
  }
}

Это может помочь. Если вы хотите, чтобы ваш элемент отображался в существующем элементе меню первичных ссылок, вам, очевидно, нужно получить млид этого существующего элемента.

ПРИМЕЧАНИЕ / ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Явная установка подобного plid не задокументирована для hook_menu(), и система меню выполняет массивацию некоторых данных в массиве элементов до вызова menu_link_save(), поэтому:

  • Во-первых, это может не сработать из-за потери пледа в пути.
  • Даже если это работает, оно может быть ненадежным и / или иметь непредвиденные побочные эффекты.

Таким образом, вы можете рассмотреть альтернативу создания желаемой записи первичных ссылок не с помощью hook_menu_alter, а отдельно с использованием menu_link_maintain() (должны разрешать подстановочные пути).

...