Сортировка элементов меню Book по дате добавления

Главные вкладки

Аватар пользователя CSoft CSoft 3 августа 2011 в 21:42

Довольно часто встаёт вопрос - как отсортировать ссылки меню модуля Book не по весу и названию, как идёт стандартно, а по дате добавления материала?

Главная проблема заключается в том, что эти ссылки являются самыми обычными пунктами меню, почему у нас есть только один значимый критерий сортировки - вес.

На основе этой информации можно использовать вот какие хитрости.

Создаём свой модуль, в него добавляем вот такой простенький код:

function MODULE-NAME_nodeapi(&$node, $op, $teaser, $page) {
  switch ($op) {
    case 'insert':
    case 'update':
      if (!empty($node->book['bid'])) {
        // Добавляем в вес пункта дату создания ноды, чтобы отсортировать меню по возрастанию
        $node->book['weight'] = $node->created;
        menu_link_save($node->book);
      }
      break;
  }
}

Что мы здесь имеем? Просто при создании или обновлении ноды в вес соответствующего ей пункта меню запишется timestamp значение даты создания материала. Эта небольшая уловка даст нам возможность отсортировать меню по возрастанию даты добавленных материалов.

Имейте ввиду, что если у вас уже есть добавленные ноды, то придётся массово как-то обновлять в базе для них пункты меню (их веса). Если нод немного, достаточно их поочерёдно пересохранить - новый вес запишется. А для новых нод наше правило уже будет действовать.

Теперь усложняем задачу. Представим, что нам нужно наоборот сортировать пункты по убыванию даты. (Первый код остаётся в силе, никуда не девайте его!) В файл template.php запишем нашу preprocess-функцию по переопределения переменных шаблона book-navigation.tpl.php, где, собственно, меню и выводится:

function phptemplate_preprocess_book_navigation(&$variables) {
  $book_link = $variables['book_link'];

  $flat = book_get_flat_menu($book_link);

  $children = array();

  if ($book_link['has_children']) {
    // Проходим массив, пока не найдём текущую страницу
    do {
      $link = array_shift($flat);
    } while ($link && ($link['mlid'] != $book_link['mlid']));
   
    // Переворачиваем массив, чтобы пункты меню шли по убыванию веса
    $flat = array_reverse($flat, TRUE);
   
    // Продолжаем проход по массиву и собираем ссылки, родитель которых равен текущей странице
    while (($link = array_shift($flat)) && $link['plid'] == $book_link['mlid']) {
      $data['link'] = $link;
      $data['below'] = '';
      $children[] = $data;
    }
  }
 
  $variables['tree'] = $children ? menu_tree_output($children) : '';
}

То есть, я полностью повторил те действия, которые происходят стандартно в этой функции для определения значения переменной $tree, за единственным исключением, что я в середине кода переворачиваю массив. Так как они по весу уже шли по возрастанию, теперь они будут убывать по дате Smile

Минусы этих трюков очевидны - данные решения являются несовместимыми со стандартной возможностью вручную менять веса пунктов на странице admin/content/book/%nid. После сохранения формы вся наша работа просто-напросто будет заменена на эти значения. Но, согласитесь, какой смысл идти и сортировать там, раз нам нужна другая сортировка, к которой мы здесь и пришли Smile

Вот, собственно, такие нехитрые действия помогли мне (после некоторых исследований особенностей работы модуля Book) отсортировать пункты меню по убыванию.

Надеюсь, этот материал поможет кому-то из вас. В любом случае, в копилке знаний сообщества лишним он точно не будет Smile

P. S. Если есть какие недочёты или упущения - напишите, я обязательно исправлю их Smile