Вывести развернутое содержание книг в модуле Book в Друпал 6

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

Аватар пользователя VladSavitsky VladSavitsky 20 мая 2008 в 21:55

После изучения API Drupal 6 написал такое:

<?php
//http://api.drupal.org/api/function/book_block/6
function book_toc_recursive() {
  $book_menus = array();
  $pseudo_tree = array(0 => array('below' => FALSE));
  foreach (book_get_books() as $book_id => $book) {
    $menu_item=menu_tree_all_data($book['menu_name'], $book);
    $book_menus[$book_id] = menu_tree_output($menu_item);
  }
  return theme('book_all_books_block', $book_menus);
}
echo book_toc_recursive();
?>

Код выводит таки оглавление, но до 2го уровня вложенности.
А мне нужно все уровни. Чтобы было как настоящее содержание в книге.
Подскажите как это сделать.

Вот фото того, что есть на данный момент:

ВложениеРазмер
Иконка изображения book_toc_recursive.png41.81 КБ

Комментарии

Аватар пользователя Nikit Nikit 21 мая 2008 в 15:48

чот у бука нужных апишных нет, пришлось вручную набросать:

<?php
function book_toc_recursive($bid, $pid) {
$sql = "SELECT a.mlid, b.link_path, b.link_title FROM book a INNER JOIN menu_links b ON a.mlid = b.mlid WHERE (a.bid=%d) AND (b.plid=%d) order by a.mlid";

$result = db_query(db_rewrite_sql($sql), $bid, $pid);
if ($result) {
print "

    ";
    while ($data = db_fetch_object($result)) {
    print "
  • " . l($data->link_title, $data->link_path) . "
  • ";
    book_toc_recursive($bid, $data->mlid);
    }
    print "

";
}
}
book_toc_recursive(181, 0);
?>

Аватар пользователя VladSavitsky VladSavitsky 24 мая 2008 в 10:56

Чего-то не получается. Получаю кучу предупреждений типа:

warning: Illegal offset type in isset or empty in .../modules/taxonomy/taxonomy.module on line 1014.

Сейчас будем искать решение. Спасибо огромное за ответ.

Аватар пользователя VladSavitsky VladSavitsky 24 мая 2008 в 12:29

Нет, не делал...

Ура! Заработало. Оказалось, что нужно было подставить id существующей книги, а не 0, ни 1, ни 181 у меня не было...
Ок. Вот код, который выводит полное оглавление всех книг в Друпал 6 в виде иерархии:

function book_toc_recursive($bid, $pid) {
$sql = "SELECT a.mlid, b.link_path, b.link_title FROM book a INNER JOIN menu_links b ON a.mlid = b.mlid WHERE (a.bid=%d) AND (b.plid=%d) order by a.mlid";

$result = db_query(db_rewrite_sql($sql), $bid, $pid);
if ($result) {
print "

    ";
    while ($data = db_fetch_object($result)) {
    print "
  • " . l($data->link_title, $data->link_path) . "
  • ";
    book_toc_recursive($bid, $data->mlid);
    }
    print "

";
}
}

$all_books=book_get_books();
foreach ($all_books as $book_id=>$link) {
book_toc_recursive($book_id, 0);
}
?>

Посмотреть работу сниппета можно на морде сайта drupalcookbook.ru
Ура! Огромное спасибо за помощь.

Drupal CookBook - Готовить может каждый!Решение было сохранено на сайте DrupalCookBook.ru:

Вывести полное содержание всех книг (book) на сайте в виде иерархии.

Авторы, предложившие решения, также указаны в сохранённой статье.

Аватар пользователя Nikit Nikit 25 мая 2008 в 6:41

а можно пример незакрытия тегов?
дополняю:
пояснения к функции:
function book_toc_recursive($bid, $pid)
$bid - номер книжки
$pid - номер начального узла, используется в рекурсии, для начала 0

...
// if ($result) {

// можно чуть обезопаситься:
// 8-ая строка
      print "<li>" . l(check_plain($data->link_title), $data->link_path) . "</li>";
...

Аватар пользователя VladSavitsky VladSavitsky 4 июня 2008 в 0:25

Наконец-то дошли руки (хотя я ногами хожу) и я переделал этот скрипт. Исправил ошибку с незакрытыми тегами и чуток оптимизировал вывод:
<?php
//v.5
unset($output);
function book_toc_recursive($bid, $pid) {
$sql="SELECT b.mlid, ml.link_path, ml.link_title, ml.has_children FROM book b INNER JOIN menu_links ml ON b.mlid = ml.mlid WHERE (b.bid=%d) AND (ml.plid=%d) order by b.mlid";
$result = db_query(db_rewrite_sql($sql), $bid, $pid);
if ($result) {
while ($data = db_fetch_object($result)) {
$output.="

  • ".l(check_plain($data->link_title), $data->link_path);
    if ($data->has_children) $output.="
      ".book_toc_recursive($bid, $data->mlid)."

    ";
    $output.="

  • ";
    }
    }
    return $output;
    }
    $all_books=book_get_books();
    foreach ($all_books as $book_id=>$link) {
    print "

      ".book_toc_recursive($book_id, 0)."

    ";
    }
    ?>

    Проверить валидность можно тут (скрипт работает на главной): http://validator.w3.org/check?verbose=1&uri=http%3A%2F%2Fdrupalcookbook....
    Раньше была туча ошибок - жаловался на незакрытые теги <ul> и <li>.

    Аватар пользователя Skirr Skirr 8 июня 2008 в 18:32

    вставил код для Д6 в блок. У всех кроме юзер№1 ошибка:
    user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by a.mlid)' at line 1 query: SELECT a.mlid, b.link_path, b.link_title FROM book a INNER JOIN menu_links b ON a.mlid = b.mlid INNER JOIN node_access na ON na.nid = n.nid WHERE (na.grant_view >= 1 AND ((na.realm = 'all' AND na.gid = 0) OR (na.realm = 'domain_site' AND na.gid = 0) OR (na.realm = 'domain_id' AND na.gid = 0)) ) AND ( (a.bid=3) AND (b.plid=0) order by a.mlid) in /includes/common.inc(1537) : eval()'d code on line 5.

    Аватар пользователя Skirr Skirr 29 июня 2008 в 22:35

    оказалось конфликтует с domain access.
    выход пока нашёл такой:

    function book_toc_recursive($bid, $pid) {
      $sql = "SELECT a.mlid, b.link_path, b.link_title FROM book a INNER JOIN menu_links b ON a.mlid = b.mlid WHERE (a.bid=%d) AND (b.plid=%d) order by a.mlid";
     /*echo db_rewrite_sql($sql);*/
      $result = db_query($sql, $bid, $pid);
      if ($result) {
        print "<ul class=\"menu\">";
        while ($data = db_fetch_object($result)) {
          print "<li>" . l($data->link_title, $data->link_path) ;
          book_toc_recursive($bid, $data->mlid). "</li>";
        }
        print "</ul>";
      }
    }
    $all_books=book_get_books();
    foreach ($all_books as $book_id=>$link) {
       book_toc_recursive($book_id, 0);
    }

    и что бы css для меню подхватывался перенёс book_toc_recursive($bid, $data->mlid) во внутрь тега li

    Аватар пользователя Cerber Cerber 9 июля 2008 в 0:25

    Ну незнаю может пригодиться но я вот нашел такое решение.

    $menu_items=menu_get_names();
    foreach ($menu_items as $key => $val)
    {
        if (strpos($val, 'book')!==false)
        {
            echo theme('dhtml_menu_tree',menu_tree_all_data($menu_items[$key]));
        }
    }

    Строка

    echo theme('dhtml_menu_tree',menu_tree_all_data($menu_items[$key]));

    использована мною для создания меню с помощью мода DHTML Menu.
    А так по идее идее стоку

    echo theme('dhtml_menu_tree',menu_tree_all_data($menu_items[$key]));

    Можно заменить на

    $menu_book=menu_tree_all_data($menu_items[$key]);
    $book_menus[$key] = menu_tree_output($menu_book);

    Ну а дальше с массивом $book_menus можно делать все что угодно.

    Аватар пользователя fasdalf@fasdalf.ru fasdalf@fasdalf.ru 21 ноября 2008 в 15:48

    Был косячок в запросе. Правильно - так.
    <?php
    //v.7 for Drupal 6
    unset($output);
    function is_book_page_new($changed) {
    //Период, в течении которого статьи считаются новыми.
    if ($changed>strtotime("-7 day")) return ' class="changed"';
    }
    function book_toc_recursive($bid, $pid) {
    $sql="SELECT b.mlid, ml.link_path, ml.link_title, ml.has_children, n.changed FROM {book} b INNER JOIN {menu_links} AS ml ON b.mlid = ml.mlid, {node} AS n WHERE (b.bid=%d) AND (ml.plid=%d) AND b.nid=n.nid AND n.status=1 ORDER BY b.mlid";
    $result = db_query(db_rewrite_sql($sql), $bid, $pid);
    if ($result) {
    while ($data = db_fetch_object($result)) {
    $output.='

  • changed).'>'.l($data->link_title, $data->link_path);
    if ($data->has_children) $output.='
      '.book_toc_recursive($bid, $data->mlid).'

    ';
    $output.='

  • ';
    }
    }
    return $output;
    }
    $all_books=book_get_books();
    foreach ($all_books as $book_id=>$link) {
    print '

      '.book_toc_recursive($book_id, 0).'

    ';
    }
    ?>

    Аватар пользователя fasdalf@fasdalf.ru fasdalf@fasdalf.ru 10 марта 2009 в 17:05

    В запросе
    <?php
    $sql="SELECT b.mlid, ml.link_path, ml.link_title, ml.has_children, n.changed
    FROM {book} b INNER JOIN {menu_links} AS ml ON b.mlid = ml.mlid, {node} AS n
    WHERE (b.bid=%d) AND (ml.plid=%d) AND b.nid=n.nid AND n.status=1
    ORDER BY b.mlid";
    ?>
    ORDER BY b.mlid меняем на ORDER BY b.link_title

    Аватар пользователя Петр2402 Петр2402 18 марта 2009 в 18:07

    Сейчас тоже смотрю на это дело. Попробуй не ORDER BY b.link_title , а ORDER BY ml.link_title
    ===
    и вопрос глупый попутно можно задать?
    Задача: Нужно вывести одну из подшивок на такое отображение.
    Я так понимаю нужно исправить вот эту строчку:
    book_toc_recursive($book_id, 0);
    Вопрос: Где посмотреть этот самый book_id или как именно исправить?

    UPD
    Вот примерно это хотел http://setegnom.com/node/774
    >>>Где посмотреть этот самый book_id
    это циферка после node/, например, у node/9, book_id = 9 (вдруг таким как я пригодиццо)

    Аватар пользователя bulinat@drupal.org bulinat@drupal.org 22 сентября 2010 в 13:25

    Спасибо, отличный сниппет. Первоначальный код у меня выводил ограниченную вложенность, код в редакции fasdalf выводит полную структуру.