Задача
Найти и понять изменения в модуле Book, чтобы можно было адаптировать сниппеты и модули, которые взаимодействуют с модулем Book, для работы в Друпал 6.
Решение
Друпал 5.х
В Друпал 5.x при сохранении страницы книги делалась запись в таблице "node" с типом 'book' и соответствующая запись в таблице "book" (nid), чтобы определить отношение к родительской странице - если родиль установлен в 0, то это книга самого верхнего уровня. Это просто!
Все данные модуля хранились в одной таблице:
Друпал 6.х
В 6.x таблица "book" теперь содержит только поля nid, bid и mlid.
В интерфейсе Друпала также видно, что на странице node/add/book невозможно больше просто указать страницу-родитель, но нужно выбрать существующую книгу и ОБЯЗАТЕЛЬНО страницу-родитель в этой книге.
Модуль Book был переписан, чтобы использвоать новую систему меню
Модуль Book теперь использует новую систему меню Drupal 6.x (таблица {menu_links}) для хранения и воссоздания иерархии книги. Любые модули, которые прежде работали через интерфейс модуля Book должны быть переписаны. Вся информация, сохранённая в документе (node) модулем Book теперь находится в свойстве $node->book.
Многие API функции модуля Book были изменены. Например, функция book_recurse была удалена. Для большинства случаев, она может быть заменена book_export_traverse, но она больше не имеет параметра $depth.
Анализ таблиц в базе данных
CREATE TABLE `book` (
`mlid` int(10) unsigned NOT NULL default '0',
`nid` int(10) unsigned NOT NULL default '0',
`bid` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`mlid`),
UNIQUE KEY `nid` (`nid`),
KEY `bid` (`bid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- Структура таблицы `menu_links`
CREATE TABLE `menu_links` (
`menu_name` varchar(32) NOT NULL default '',
`mlid` int(10) unsigned NOT NULL auto_increment,
`plid` int(10) unsigned NOT NULL default '0',
`link_path` varchar(255) NOT NULL default '',
`router_path` varchar(255) NOT NULL default '',
`link_title` varchar(255) NOT NULL default '',
`options` text,
`module` varchar(255) NOT NULL default 'system',
`hidden` smallint(6) NOT NULL default '0',
`external` smallint(6) NOT NULL default '0',
`has_children` smallint(6) NOT NULL default '0',
`expanded` smallint(6) NOT NULL default '0',
`weight` int(11) NOT NULL default '0',
`depth` smallint(6) NOT NULL default '0',
`customized` smallint(6) NOT NULL default '0',
`p1` int(10) unsigned NOT NULL default '0',
`p2` int(10) unsigned NOT NULL default '0',
`p3` int(10) unsigned NOT NULL default '0',
`p4` int(10) unsigned NOT NULL default '0',
`p5` int(10) unsigned NOT NULL default '0',
`p6` int(10) unsigned NOT NULL default '0',
`p7` int(10) unsigned NOT NULL default '0',
`p8` int(10) unsigned NOT NULL default '0',
`p9` int(10) unsigned NOT NULL default '0',
`updated` smallint(6) NOT NULL default '0',
PRIMARY KEY (`mlid`),
KEY `path_menu` (`link_path`(128),`menu_name`),
KEY `menu_plid_expand_child` (`menu_name`,`plid`,`expanded`,`has_children`),
KEY `menu_parents` (`menu_name`,`p1`,`p2`,`p3`,`p4`,`p5`,`p6`,`p7`,`p8`,`p9`),
KEY `router_path` (`router_path`(128))
) ENGINE=MyISAM AUTO_INCREMENT=407 DEFAULT CHARSET=utf8 AUTO_INCREMENT=407 ;
Анализ $node->book
Создадим документ типа Book и выполним в нём код (формат ввода должен быть PHP):
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
var_dump($node->book);
}
?>
Получаем такой результат:
["mlid"]=> string(3) "409"
["nid"]=> string(2) "27"
["bid"]=> string(2) "56"
["menu_name"]=> string(11) "book-toc-56"
["plid"]=> string(3) "257"
["link_path"]=> string(7) "node/27"
["router_path"]=> string(6) "node/%"
["link_title"]=> string(20) "Содержание"
["options"]=> array(0) {}
["module"]=> string(4) "book"
["hidden"]=> string(1) "0"
["external"]=> string(1) "0"
["has_children"]=> string(1) "0"
["expanded"]=> string(1) "0"
["weight"]=> string(1) "0"
["depth"]=> string(1) "2"
["customized"]=> string(1) "0"
["p1"]=> string(3) "257"
["p2"]=> string(3) "409"
["p3"]=> string(1) "0"
["p4"]=> string(1) "0"
["p5"]=> string(1) "0"
["p6"]=> string(1) "0"
["p7"]=> string(1) "0"
["p8"]=> string(1) "0"
["p9"]=> string(1) "0"
["updated"]=> string(1) "0"
["href"]=> string(7) "node/27"
["title"]=> string(20) "Содержание"
}
Выводы
- Таблица book в Друпал 6.х содержит поле bid (Book id), которое хранит nid страницы самого высокого уровня в книге.
- Каждая страница книги также имеет поле mlid (Menu links id) для связи с таблицей menu_links.
Это необходимо потому, что иерархия страниц в книге теперь реализована в menu_links, а не в таблице book. - Максимальная вложенность ограничена 9ю уровнями.
Элементы массива $node->book
- mlid - id menu_links, позволяет модулю Book подключиться к menu_links
- nid - id документа
- bid - сокращение от "book_id"
- menu_name - Для документов типа Book всегда начинается с "book-toc-" + nid документа самого верхнего уровня. menu_name одинаковое для всех документов одной книги.
- plid - mlid непосредственного родителя (0 - самый верхний уровень)
- link_path - адрес документа в меню
- router_path
- link_title - текст ссылки в меню
- options array(0) {}
- module - системное имя модуля. Хранится в menu_links.module
- hidden - скрытый элемент меню
- external
- has_children - есть ли дочерние документы (0 - нет, 1 - есть)
- expanded - развёрнуто (0- нет, 1 - да)
- weight - вес (используется для сортировки элементов одного уровня)
- depth - глубина вложенности (1 - самый верхний уровень)
- customized
- p1 - самый верхний уровень в иерархии меню. Содержит mlid родителя
- p2 - уровень в иерархии. В нашем случае содержит mlid текущего документа
- p3 - 0 - если нет дочерних документов.
- p4
- p5
- p6
- p7
- p8
- p9
- updated
- href - адрес документа
- title - заголовок документа
Использованные материалы
- Book.module changes from Drupal 5.x -> 6.x
- The book module has been rewritten to use the new menu system
- improve book module: use nodeapi and menu API - весь процесс изменений в модуле Book с версии 5.х до 6.х
Полезные ссылки
Book: structured document publishing
Оригинал статьи: Изменения в модуле Book в Друпал 6
Комментарии
спасибо большое! Считаю модуль book одним из главных достоинств Друпала.
А для чего применяют бук в основном?
Модуль очень нужен в хозяйстве (правда не все им умеют пользоваться).
А вот для его он нужен и в каких случаях лучше почитать, ткнув в одну из ссылок под заголовком статьи:
Другие статьи по теме: Drupal 6.*, book, upgrade, изменения, книга, обновление, подшивка
Кто-то ещё разбирался с этим чудо-модулем?
Поделитесь опытом! Нужен сниппет, который выводит полное содержание всех книг в развёрнутом виде, как было сделано тут: http://drupal.ru/book/toc
Хотелось использовать стандартные функции, но пока безуспешно.
Другой вариант - брать из базы данные и формировать вывод самостоятельно... Можно конечно, но труднее и не кошерно как-то...
если еще актуально...
Сегодня целый день искала, так и не нашла, пришлось разбираться с модулем book
Вот код для кастомного блока, выводящего полное содержание указанной книги. Наверное, можно для всех книг аналогичное написать.
<?php
$book_top_page=YOUR_NODE_ID;
$tree = menu_tree_all_data(book_menu_name($book_top_page));
print menu_tree_output($tree);
?>
MarinaMim,
А зачем? Есть стандартный блок, который выводит оглавление для всей книги, к которой принадлежит нода.
Сниппет полного содержания уже опубликован и работает на этом сайте: http://drupal.ru/book/toc
Подскажите, может есть дополнение к модулю book чтобы можно было выполнять сортировку оглавления визуально, как в блоках?