Мутация book или каталог из книги.

Прислано: player

вт, 20/05/2008 - 08:42

Был у меня тут недавно случай. Нужно было сделать каталог. Причем для каталога выдвигалось 3-а основных требования.

  1. Простота в управлении (а именно автоматическое создание меню)
  2. Неограниченный уровень вложенности
  3. Вывод подчиненного материала (node) на странице родителя в виде таблицы с картинками.

Искал решение, даже ветку завел Book, Node Hierarchy что еще позволяет делать иерархию? , попробовал category который глючный и сложный для простого обывателя. В итоге пришел к выводу, что по управляемости стандартный book самый простой (генерирует меню автоматически), и каталог слепить можно. Да только вот беда, в book нельзя сделать вывод тизеров материала, а можно выводить лишь названия подчиненного материала. Но разве для drupal это проблема? Конечно нет.
Решение:
Для начала снабдим нашу страницу подшивки изображением. В этотм нам поможет CCK и его доп. модуль imagefield. Ну и contemplate нам понадобится для красивого оформления этого дела. Работу с данными инструментами описывать не буду, т.к. на форуме и так много всего про них сказано. Будем считать что у нас в странице подшивки есть поле изображения
Лезем в код нашего любимого модуля book и ищем там все функции со словом theme_. Находим 3-и функции.
theme_book_navigation($node)
theme_book_export_html($title, $content)
theme_book_admin_table($form)
Ну и как Вы думаете какая нам нужна? Конечно theme_book_navigation($node). Так что берем и смело копируем её в template.php.

<?php
function theme_book_navigation($node) {
  
$output '';
  
$links '';

  if (
$node->nid) {
    
$tree book_tree($node->nid); // получает меню навигации

    // генерирует массив ссылок (те что в node.tpl.php $links)
    
if ($prev book_prev($node)) {
      
drupal_add_link(array('rel' => 'prev''href' => url('node/'$prev->nid)));
      
$links .= l(t('‹ ') . $prev->title'node/'$prev->nid, array('class' => 'page-previous''title' => t('Go to previous page')));
    }
    if (
$node->parent) {
      
drupal_add_link(array('rel' => 'up''href' => url('node/'$node->parent)));
      
$links .= l(t('up'), 'node/'$node->parent, array('class' => 'page-up''title' => t('Go to parent page')));
    }
    if (
$next book_next($node)) {
      
drupal_add_link(array('rel' => 'next''href' => url('node/'$next->nid)));
      
$links .= l($next->title t(' ›'), 'node/'$next->nid, array('class' => 'page-next''title' => t('Go to next page')));
    }

    if (isset(
$tree) || isset($links)) {
      
$output '<div class="book-navigation">';
      if (isset(
$tree)) {
        
$output .= $tree;
      }
      if (isset(
$links)) {
        
$output .= '<div class="page-links clear-block">'$links .'</div>';
      }
      
$output .= '</div>';
    }
  }

  return 
$output;
}
?>

Как видите это еще не решение проблемы, т.к. содержание навигации создается не theme_book_navigation а book_tree($node->nid). Собственно все ясно. Нам нужно написать свою book_tree которая будет возвращать не только ссылки но и картинки например.
Для того чтобы посмотреть код booktree можно опять таки взглянуть в код модуля.
Ого оказывается что она состоит еще из одной функции book_tree_recurse. Не слишком ли много функций? Для нашей задачи хватит вполне 2-х функций расположенных в template.php. В book_tree есть функция <?php book_tree_recurse($parent$depth$children$unfold?> которая рекурсивно обходит книгу в поиске её детей для создания навигации.
Именно её мы и заменим на свою <?php my_tree_recurse($nid$depth$children$unfold = array(), $td 0)?> сама же book_tree для нашей задачи особо не нужна
Ниже уже готовый для моего случая код с некоторым комментариями.
<?php
function combustion_book_navigation($node) {
  
$output '';
  if (
$node->nid) {
    
//$tree = book_tree($node->nid);
    // Код ниже взят из book_tree
    
$depth 3;
    
$prnt $node->nid;
    
$result db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 ORDER BY b.weight, n.title'));
    while (
$node db_fetch_object($result)) {
      
$list = isset($children[$node->parent]) ? $children[$node->parent] : array();
      
$list[] = $node;
      
$children[$node->parent] = $list;
    }
    
// наша функция, аналог book_tree_recurse
    
$tree my_tree_recurse($prnt$depth$children$unfold = array());

    if (isset(
$tree)) {
      
$output .= '<div class="book-navigation">';
      if (isset(
$tree)) {
        
$output .= '<div style="clear:both;"></div><table>'.$tree.'</table>';
      }
      
$output .= '</div>';
    }
  }
  return 
$output;
}

//$td это счетчие тегов <td> в таблице
function my_tree_recurse($nid$depth$children$unfold = array(), $td 0) {
  
$output '';
  if (
$depth 0) {
    if (isset(
$children[$nid])) {
      foreach (
$children[$nid] as $foo => $node) {
        if (
$td == 0)  $output .= '<tr>';
          
$td++;
          
$output .= "<td width='160px' valign='top' style='padding:4px;'>";
        if (
in_array($node->nid$unfold)) {
          if (
$tree my_tree_recurse($node->nid$depth 1$children$unfold)) {
            
$output .= '<li class="expanded">';
            
$output .= l($node->title'node/'$node->nid);
            
$output .= '<ul class="menu">'$tree .'</ul>';
            
$output .= '</li>';
          }
          else {
            
$output .= '<li class="leaf">'l($node->title'node/'$node->nid) .'</li>';
          }
        }
        else {
      
// если есть вложенная структура
          
if ($tree my_tree_recurse($node->nid1$children)) {
            
//  node_load считаю достаточно ресурсоемкой функцией. тут больше для примера
            
$nd =  node_load($node->nid);
            
// field_[0]['filename'] можно посмотреть как называется
            //  ваш массив в contemplate
            
$output .= "<a href='".$nd->nid."'><img src='".base_path()."files/imagecache/thumbnail/files/im/".$nd->field_[0]['filename']."'/></a></br>";
            
$output .= "<h5>".l($nd->title'node/'$nd->nid)."</h5>";
            
$output .= "<p class='trumb-desc'>".$nd->teaser."</p>";
          }
          else {
            
// если последние дети
            
$nd =  node_load($node->nid);
            
$output .= "<a href='".$nd->nid."'><img src='".base_path()."files/imagecache/thumbnail/files/im/".$nd->field_[0]['filename']."'/></a></br>";
            
$output .= "<h5>".l($nd->title'node/'$nd->nid)."</h5>";
            
$output .= "<p class='trumb-desc'>".$nd->teaser."</p>";
          }
        }
        
// вывод в 3-и колонки 
        
$output .= "</td>";
        if (
$td == 3) {
          
$output .= '</tr>';
          
$td 0;
        }
      }
    }
  }
  return 
$output;
}
?>

__________________________
Bite my shiny, metal ass!

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано Geldora в вт, 20/05/2008 - 08:49.

Спасибо! А посмотреть в действии можно?


Опубликовано player в вт, 20/05/2008 - 08:51.

пока нет. все на стадии тестирования заказчиком. А что смотреть? Не верите? =)


Опубликовано VladSavitsky в вт, 20/05/2008 - 10:15.

"Неограниченный уровень вложенности"
Насколько я понимаю в Друпал 6 есть ограничение на количество вложенности для модуля Book (9 уровней). В Друпал. 5 такого не было. Но я не проверял предел вложенности.


Опубликовано player в вт, 20/05/2008 - 10:27.

Я если честно тоже не проверял. Думал что для 5-ки он не ограничен. Ну кто знает, тот напишет думаю.


Опубликовано VladSavitsky в вт, 20/05/2008 - 10:34.

Для 5ки вложенность не ограничена - в 6ке есть ограничение.

Подскажите, пожалуйста, как мне в Друпал 6 вывести развернутый список всей иерархии книг на одной странице?
Я сделал для Друпал 5: http://drupal.ru/book/toc
Но для Друпал 6 всё поменялось...


Опубликовано player в вт, 20/05/2008 - 12:26.

К сожалению уже больше месяца в 6-ку не ногой. некогда.


Опубликовано Roof в вт, 20/05/2008 - 18:00.

Запомним, спасибо.


Опубликовано Skirr в ср, 21/05/2008 - 14:56.

VladSavitsky написал(а):

Для 5ки вложенность не ограничена - в 6ке есть ограничение.

Подскажите, пожалуйста, как мне в Друпал 6 вывести развернутый список всей иерархии книг на одной странице?
Я сделал для Друпал 5: http://drupal.ru/book/toc
Но для Друпал 6 всё поменялось...

неуверен, но может поможет http://api.drupal.org/api/file/modules/book/book-all-books-block.tpl.php...
Покрайне мере пишут что в блоке можно вывести всё меню.


Опубликовано shumod в пн, 09/06/2008 - 13:56.

Попробовал сделать по описанию - вылезает ошибка:
Fatal error: Cannot redeclare theme_book_navigation() (previously declared in Z:\home\new\www\modules\book\book.module:481) in Z:\home\new\www\themes\garland\template.php on line 125


Опубликовано player в пн, 09/06/2008 - 15:54.

А все точно по описанию сделали? Для начала скопируйте код просто

<?php 
garland_book_navigation
() {
 return 
"IT WORKS!";
}
?>

в Z:\home\new\www\themes\garland\template.php И посмотрите что выведется там где была навигация..


Опубликовано gor в пн, 09/06/2008 - 16:08.

shumod написал(а):

Попробовал сделать по описанию - вылезает ошибка:
Fatal error: Cannot redeclare theme_book_navigation() (previously declared in Z:\home\new\www\modules\book\book.module:481) in Z:\home\new\www\themes\garland\template.php on line 125

вместо дословного theme_book_navigation() необходимо theme заменить на имя вашей темы. Для garland это garland.


Опубликовано shumod в вт, 10/06/2008 - 08:26.

player написал(а):

А все точно по описанию сделали?

Сделал следующее:

  • вырезал "function theme_book_navigation($node) { и т. д. " из book.module и вставил в template.php, изменил theme на garland.
  • заменил book_tree_recurse($parent, $depth, $children, $unfold) в book.module на my_tree_recurse($nid, $depth, $children, $unfold = array(), $td = 0)
  • вставил function combustion_book_navigation($node) и function my_tree_recurse($nid, $depth, $children, $unfold = array(), $td = 0) в book.module
  • заработало, ссылки на дочерние страницы пропали, только при вставке

garland_book_navigation() {
return "IT WORKS!";
}
опять вылезает ошибка :
Parse error: syntax error, unexpected '{' in Z:\home\new\www\themes\garland\template.php on line 38


Опубликовано player в вт, 10/06/2008 - 08:51.

с book.module ничего делать не надо. его можно только смотреть и все. Мы тут работаем только с template.php.


Опубликовано gor в вт, 10/06/2008 - 13:01.

Цитата:

опять вылезает ошибка :
Parse error: syntax error, unexpected '{' in Z:\home\new\www\themes\garland\template.php on line 38

на 38 строке кода в указаном файле вы допустили ошибку.
Возьмите учебник по PHP и почитайте его, если же вам это не интересно - попросите какого нить друга програмиста помочь (которому вы доверите доступ к своему сайту) или наймите специалиста, который поможет вам за деньги.


Опубликовано Tankha в ср, 06/08/2008 - 21:25.

Третий день пытаюсь сделать тоже самое для 6-ки... В конечном итоге уперся в один неразрешимый пока вопрос (использую CCK и contemplate) - как получить список дочерних страниц книги?

Добавлено:
Пересмотрел все таблицы. Где же хранится ссылка на родителя?
Мда. Друпал оказывается не так прост как была надежда.


Опубликовано axel в чт, 07/08/2008 - 07:37.

В D6 структура book завязана на меню. См. в таблице book есть ссылка mlid, после см. таблицу menu_links WHERE module = 'book'. Там есть plid - родитель для mlid.


Опубликовано alhoff в ср, 04/03/2009 - 21:10.

to Tankha:Третий день пытаюсь сделать тоже самое для 6-ки... В конечном итоге уперся в один неразрешимый пока вопрос (использую CCK и contemplate) - как получить список дочерних страниц книги?

Выложите результаты работы, в задних рядах тоже интересуются!!! : )


Опубликовано EllECTRONC в ср, 04/03/2009 - 22:45.

<подписка>


Опубликовано kiev1 в вс, 19/04/2009 - 11:00.

модуль Books это капитальный тупик - надо использовать таксономию.