current situation / problem

  • Currently, the book module can only handle one big outline with ALL the book nodes in the site. There may be several 'books' but they are handled as one.
  • One immediate consequence is that the pull-down menu can rapidly become unwieldy because all nodes are listed within.
  • book.module has no native way of making the difference between books

Most sites have more than one book:
http://drupal.org/book
http://www.wechange.org/book
etc.

What this patch does

This patch will allow the book.module to make a big step forward between 4.7 and 4.8.
It allows the system to make the difference between different books, so that each can be handled differently, by different authors, with different permissions, design, etc.
Only the pages within the one book are listed in the pull-down menu, making it much shorter in many cases.
Recursive calculation of the book outline (for example for the book outline block) will be much quicker because the system needs to sort fewer book pages.

This patch is only the ground work that opens a world of new possibilities for the book.module. With it, the book.module will deserve its name better ;) , as seen below.

How it works

There are now two tables: {book} and {book_pages} to differentiate between each individual books (like those on your bookshelf) and the pages/nodes they contain. This way, each book node gets to have a $node->bid (book ID) which will allow for more features.

The content of the former {book} table is copied to {book_pages} with a bid field added, and a brand new {book} table is created with some basic field:
1) bid : book ID
2) uid: user ID of the book's author/maintainer.
3) title which is currently the same as the title of the first node in that book's outline.
4) weight
and) more fields can be added as required, like description (like the back-cover of a paper book), a list of different attributes (picture of book cover, etc.).

During the upgrade, the node->bid stored in the {book_pages} table is updated.

In book.module, all references of {book} have been replaced by {book_pages} so that by default, it doesn't break anything.
And already a few minor adjustments have been made to make use of the new table.

When accessing book/, one gets the list of the books, as usual, except that the list is pulled from the simpler {book} table.
Each book in the lit links to book/$bid. Currently, book/2 simply redirects to the first node in the outline, but later, it can be upgraded so that it leads to the 'cover page' of the book.
In other words, the same way we have http://drupal.org/forum/8 leading to a special page with that forum, we can have http://drupal.org/book/8 leading to a specially designed page for a book cover, with title, author, picture, and the back-cover text, the table of content, etc...

And, http://drupal.org/book/8/edit would work the same as user/8/edit or node/8/edit. (TODO)

What new features can be introduced, now?

Many if we consider all the new features that can be added directly in book.module and in contrib modules and by themers, etc...

A few that I care about:

  • Permissions (access/create/edit/relocate) can be granted individually for each book without the need for contrib access module.
  • The author/maintainer of any one book can grant those rights to other users for his book. (like in og_book, but with this patch, each og group can have more than one book assigned to the group).
  • Theming / styling can be made for each book.
  • Allow blocks to appear or not on book pages with a certain bid
  • Better caching possibility of the book outline, because it can be done more easily per book (improving performance)
  • you complete the list ;)

With this patch, a 'book' node/outline can be used as usual for those who want. But it also allows to use a 'book' more like a real book.
The module would deserve its name better.
With the possibility to add a simple story or forum topic to the book outline, the specificity of the book node was getting lost. Now, we can organize a book just like a real book.

Two case studies:

reuniting.info would like to publish this pdf in book nodes, into a separate book:
http://www.reuniting.info/download/pdf/TheKarezzaMethodfv.pdf

This is another real book being published online. The first node in the book is the table of content:
http://www.wechange.org/forming_tribalized_communities
note that the design/layout of the TOC could be done automatically and cached (when accessing the aliasable urlbook/8 for example (with book cover design/picture, etc as described above).

Imagine how the 'cover page' each of the books at drupal.org could be redesigned.

Still to do

There are still a lot of minor issues to sort. Please review and I'll submit updates (if you don't :) ).

Maybe we can get a basic feature set committed before delving into more advanced possibilities.

CommentFileSizeAuthor
#125 book_pages_pw_125.diff68.69 KBpwolanin
#119 book_pages_pw_119.diff67.02 KBpwolanin
#109 book_pages_pw_109.diff64.7 KBpwolanin
#105 book_pages_100.diff.txt64.99 KBbeginner
#99 book_pages_pw_99.diff64.19 KBpwolanin
#97 generate-48book.php.txt5.93 KBpwolanin
#96 book_pages_pw_96.diff61.72 KBpwolanin
#95 template.php_4.txt693 bytespwolanin
#92 book_pages_pw_91.diff60.35 KBpwolanin
#91 generate-47book.php.txt5.75 KBpwolanin
#90 book_pages_pw_90.diff60.17 KBpwolanin
#89 book_pages_pw_89.diff60.13 KBpwolanin
#88 generate-book.php_0.txt5.88 KBpwolanin
#87 book_pages_pw_86.diff60.21 KBpwolanin
#85 book_pages_pw_84.diff60.17 KBpwolanin
#82 book_pages_pw_82.diff60.09 KBpwolanin
#80 generate-book.php.txt5.56 KBpwolanin
#79 book_pages_pw_79.diff60.09 KBpwolanin
#78 book_pages_pw_78.diff59.24 KBpwolanin
#77 book_pages_pw_77.diff53.39 KBpwolanin
#76 book_pages_pw_76.diff51.37 KBpwolanin
#72 book_pages_pw_72.diff48.02 KBpwolanin
#69 book_pages_pw_69.diff48.01 KBpwolanin
#65 book_cover22.diff.txt43.97 KBbeginner
#62 book_cover21.diff.txt45.84 KBbeginner
#61 book_8.module53.06 KBbeginner
#58 book_7.module52.13 KBbeginner
#54 book_cover17.diff.txt44.16 KBbeginner
#53 book_4.module52.46 KBbeginner
#48 book_cover16.diff.txt41.95 KBbeginner
#42 book_cover15.diff.txt41.9 KBbeginner
#41 book_cover14.diff.txt40.44 KBbeginner
#40 book_cover13.diff.txt39.91 KBbeginner
#37 book_cover12.diff.txt40.1 KBbeginner
#36 book_cover11.diff.txt36.78 KBbeginner
#35 book_cover.diff.txt34.83 KBbeginner
#25 book7.diff.txt38.44 KBbeginner
#13 book6.diff.txt37.01 KBbeginner
#12 book5.diff.txt34.1 KBbeginner
#6 book4.diff.txt32.92 KBbeginner
#5 book3.diff.txt32.07 KBbeginner
#2 book2.diff_0.txt19.94 KBbeginner
book2.diff.txt19.93 KBbeginner

Comments

dww’s picture

Status: Active » Needs work

looks interesting. i've got some ideas about improving book, too (http://drupal.org/node/61397#comment-116556), and perhaps those would be more easily accomplished built on top of your proposed changes.

a *very* quick skim of your patch revealed this in the db update hook:

+      $ret[] = update_sql("CREATE TABLE `wechange_book` (
...
+      $ret[] = update_sql("ALTER TABLE `wechange_book_pages` ADD `bid` INT( 10 ) UNSIGNED NOT NULL AFTER `nid` ;");
+      $ret[] = update_sql("ALTER TABLE `wechange_book_pages` ADD INDEX ( `bid` );");

what's up with "webchange_book"? looks like the rest of your patch assumes (as it should) that this table is just called "book"...

also, this isn't acceptable in core:

 case 'pgsql':
+        //TODO

;) i feel your pain, but you'll need to find a pgsql person to help you get this (at least) pgsql compatible before any of the core developers will seriously consider it. of course, you're probably waiting to see if it's just going to be shot down from the start before you pour much more time into it, which is probably a good move on your part...

anyway, without looking in detail at the code, and without having thought too much about it yet, i think this is a good move in principle. +1 to the idea, code definitely needs work.

thanks for pushing this forward, beginner!

-derek

beginner’s picture

StatusFileSize
new19.94 KB

Thanks for your encouraging comments.

Ooops about wechange_book. I guess you can guess which site's date I used for testing :)
That's the only correction in this patch. mysql users should be able to test it without problems.

About posgresql, I made the note obvious: I knew it would be noticed :) . I tried to look for the postgresql/mysql handbook page about how to make sql compatible (saw it once) but didn't find it.

You do have an ambitious TODO list! I guess that this patch makes nearly all of what you planned for books easily possible now, but only as long as we speak about a whole book (the metadata being set for the book at book/$bid/edit).
If you want to set metadata for a subset of a book, then you still have almost everything to do. But I don't see why you would need that: Book A can be rendered differently from Book B, but there's no reason why chapter 1 should have different metadata than chapter 2 of the same book... but if it can be done, why not?

I'll try to figure out the posgresql bit (help, anyone?)

A few questions

1) currently book/1 is redirected to the topmost page in the book. That link is actually a placeholder for a cover page for the book. Which do you prefer and why? What you would have on the cover page, and how to render it?

2) Any hints on the best way to handle per-book permissions?

edrupalec’s picture

Fantastic!
I've thought this is one of the major issues that needs to be addressed. It's ludicrous to have drop-down boxes that are 1000 lines long. Thank you very, very much. You can change your username to "expert"!

pwolanin’s picture

The concept sounds great to me.

One question- how do you determine the author/maintainer of a "book"? Is this just the author of the first node? Or, is this a node-independent piece of data? Can a book have multiple authors?

beginner’s picture

StatusFileSize
new32.07 KB

Thank you both for encouraging me to go ahead with this patch.

@edrupalec: thank you, but I know very well that compared to core Drupal developers, I really am a beginner :)

@pwolanin: for the imported data, the author of the book is the author of the top level page of that book. For new books, the author is the one who created the new book. The author can change the book's meta data. But I am not taking any existing feature away: each page of a a book can be authored by a different user. If you don't understand, the best is for you to try the patch :). It's getting close to ready.

I am trying hard not to introduce too many features. I am preparing the ground for new features to be introduced in other issues. This patch is big enough as it is.

Here is the current working state: postgresql support added, database definitions added, and adjusted most of the node/add/book(page) book/add navigation, etc.
I'm still working on a minor issue: the previous/next links at the bottom of a book node.

please test and report: it's a big patch: the more people test it, the more likely and the quicker it will be committed to core.

beginner’s picture

StatusFileSize
new32.92 KB

last patch for today.

dries’s picture

I'm not convinced this is the right direction ...
One immediate consequence is that the pull-down menu can rapidly become unwieldy because all nodes are listed within.

This is actually a great feature, as pages can move from one book to another.

Permissions (access/create/edit/relocate) can be granted individually for each book without the need for contrib access module.

Here you are assuming that each book has exactly one maintainer/author, not?

Better caching possibility of the book outline, because it can be done more easily per book (improving performance)

The book outline shouldn't be cached. Instead, we should switch to a different algorithm to retrieve the book outline. In particular, we should use the comment.module's approach which allows the entire thread to be retrieved with a single SQL query.

beginner’s picture

> > One immediate consequence is that the pull-down menu can rapidly become unwieldy because all nodes are listed within.

This is actually a great feature, as pages can move from one book to another.

We still should be able to move pages from one book to another but not yet in this patch. I wanted to do that next and it will involve only one extra step: select the book first, then the place in the outline.

In real life, though, this will rarely happen. Once admins understand that each book can really be a separate entity (like each book on your bookshelf), they'll create books for each different topic: why should I want to move my page about kittens from my book about pets to my book about history?

> > Permissions (access/create/edit/relocate) can be granted individually for each book without the need for contrib access module.

Here you are assuming that each book has exactly one maintainer/author, not?

No, as I said several times above, I am not taking away any existing feature. A book can be multi-authored (one author per page or per revision if need be, like today).

I am preparing the ground for new features that will come later. Users from the group 'historians' can add pages anywhere in the book about history, but only pet-owners (or whatever) can create/edit pages on the corresponding book.

Also, there can be a book created by the site admin with FAQs, etc... which is locked to other users, and there can be other books open to the community, etc...

I'm sure others will think of many ways to exploit the possibilities created here.

dww’s picture

beginner: One immediate consequence is that the pull-down menu can rapidly become unwieldy because all nodes are listed within.

dries: This is actually a great feature, as pages can move from one book to another.

dries, you must admit that while it's definitely a good feature to be able to move pages between books, the current UI is a nightmare. i don't have a great solution in mind, but i think what we've got now needs help. maybe we need an active select, and have 2 drop-downs: 1 for the book this page belongs in, and the other for what page in that book should be the parent of this page. then, if you change the option in the "book" dropdown, the active-select kicks in and changes the options available in the "page" dropdown...

eaton’s picture

Agreed, regarding moving pages. I've posted handbook entries and spent more time trying to scroll to the correct parent page than I did writing the entry itself. It's good to be able to move things around at will, but finding something in a 400 item select box offsets that ability.

pwolanin’s picture

@dww- I agree.

How about this idea: in the drop down, only list the top-level book name for all books except the current one where you see the whole hierarchy. If you move a page to a different book, it gets put somewhere by default. The advantage is that it avoids any dependence on JS.

This is a little suboptimal, since you then have to go and put that page where you want it within the other heirarchy. But, in terms of actual useability, how often are pages moved between books?

Another thing to think about, how and where do you control whether I can move my pages into your book, if this module is going to lend itself to per-book editing permissions.

beginner’s picture

StatusFileSize
new34.1 KB

Just toyed with breadcrumbs: no time to do more today. I'll address other issues mentioned above another day.

beginner’s picture

StatusFileSize
new37.01 KB

patch update: move one page from one book to another.
This feature will be rarely used, so I have tucked this function in a local tab.
The other solution was as suggested above to put a drop-down select field within the edit page, but 1) it would clutter the edit page further and 2) incurs extra sql queries overheads during each edit whether the function is used or not.

so now, you want to move a page to another book, you click the 'move to book' tab, select the book you want to move the page to. Also, you are given the choice to move the children together to the new book or leave them to the original book. Upon submit, you're back to the page's edit tab in case you want to change the location within the new book outline.

Note that I am not addressing extra per-book permissions in this patch: this will be the object of a new patch. I haven't added any permissions, so I am using the most appropriate existing permission for each task.

Did any of your actually install the patch and test it? (if you can try upgrading -on a test platform- one of your sites which has the most books and book pages so you can see the difference better).
I need feedback from people who have used the patch on the navigation, UI and the overall feeling when performing different tasks.

beginner’s picture

Another thing to think about, how and where do you control whether I can move my pages into your book, if this module is going to lend itself to per-book editing permissions.

Since I didn't add any permission, right now users who have the permission "outline posts in books" can move any page to any book.

The other advantage of having the "move page to another book" function on another tab, is that the call back function for that tab can later include all the roles/permissions check to see which books the user has the said permission for (all these checks don't need to be done on regular view/edit tasks).

Later, the user may have the permission "outline posts in books A, B and D" but not C. The function will evaluate this and present the appropriate drop-down select. But that's for later.

pwolanin’s picture

Sounds excellent. I will try to test the patch this weekend.

pwolanin’s picture

Ok, trying the patch out now. I like the way it's headed and here's some feedback:

The option to create a new book doesn't appear at /node/add I suppose you can argue it shouldn't, since it's not a node. Maybe a better approach would be to make each book a node? Similar to the way each group is a node in the organic groups module? In fact, the more I think about it the more important this seems. If it's not a node, then it becomes much harder to associate taxonomy terms, use access control modules, associate it with organic groups, etc.

When I'm adding a book page from the create content menu, I'd suggest re-using the same form with the drop-down as when moving a book page to a different book. I think it's a little confusing to have two different interfaces for these operations. In particular, it's confusing now when I'm adding a new book page and I'm asked to select from the list of books at /book, the "New book" tab is visible which makes me think that I can add the page to a new book by clicking this.

Right now you apparently cannot delete a book? I suppose to allow deletion there needs to be a mechanism in place for making the book pages within that book orphans?

Right now the new code doesn't seem to work well for non-book-page nodes that have been included in a book hierarchy. For example, on those pages if I click the "outline" tab I get the previous type of book drop-down showing all the book pages . It seems like the UI here needs some thought. Maybe do away with the "outline" tab, and only have a a tab that says either "add to book" or "move to book". The "move to book" tab would be the place to include the "Remove from book" type of button that currently appears on the "outline" tab for non-book-page nodes. I think for pages already in a book it would make sense to inject the book-outline drop-down into the editing form rather than having the "outline" tab.

Right now the "move to book" tab does appear for non-book-page nodes, but going through the process here doesn't actually seem to move the node into the book.

This is more in terms of improving the module in general, and not a comment on your patch. On the /node/x/edit for a book page (or ideally any page in a book following my suggestion above), I think the book terminology should be clarified. The cuurent heading for the drop down is "Parent". And the help text below is "The parent that this page belongs in.". I think the ideal would be to replace "Parent' with something like "Position in book: %s" with %s getting replaced with the name of the book it belongs to. The text underneath could be improved to something like "Select the page within this book that should be the parent of this page".

A minor point- the meaning of <top-level> has changed, which is fine but which probably should be documented clearly since it's likely to cause some initial confusion.

beginner’s picture

pwolanin: thanks! That's a great feedback. Thank you for taking the time to test the patch.

Among the issues you mention, I was aware of some, but not of others. Thank you for pointing out those to me. I think all your points are valid.

I have other stuff coming up in the next few days, so it may be a few days before I can provide a new patch to fix all the issues you mention (and one or two more you don't but that I know of).

Of your comments, one stands out for me because I was precisely thinking about it while walking on my way to the office, just before reading your feedback: the concept of a "book cover" as a node type. I need to study a bit more how Drupal works so that I can implement the concept. Meanwhile, can others also give me hints on the way to code this?

I'm back on this issue in a few days to read your comments and work on a new patch. thanks.

pwolanin’s picture

In terms of making a node type, the easiest would be just to start from "story". Also brainstorming additional name possibilities to "book" or "book cover" node, how about something like a "book binding", or "book spine"?

You could also follow the current OG model where any node type can be a group. However, I think it may be better to avoid that level of complexity.

dww’s picture

having a book as a node is a good idea. however, i think "book" is the best term for this. "spine", "binding", etc all have other possible meanings, which could add confusion. you wouldn't want the UI to say "move this page to another book binding". just call it a "book". then we have "books" and "book pages", which seems utterly natural to me. ;)

in terms of moving pages, i agree that avoiding JS where unnecessary is a good idea. however, i don't like the idea of moving a page to a new book and having it just show up randomly in the new book (or worse yet, at the top-level of the new book). how about this -- when you move a page to a new book, the page is just stuffed into the top-level of the new book (as proposed) but is automatically unpublished. when you hit [submit] for the move operation, it could bring you back to the edit tab again (instead of the node view tab) and the drupal_set_message() text should clearly state something like:

This page has been moved to the %title book, but is now unpublished. You can put it into the book outline by selecting an appropriate parent page, and making it visible again by selecting the "Published" checkbox under the "Publishing options" set of fields.

obviously, that's a little bit wordy and we could probably do better, but you get the basic idea. i suppose we could even keep the default behavior of going back to the node view tab after the edit, in which case the drupal_set_message() text would be roughly the same, but would be re-phrased about "you can now edit the page to put it into the book outline..." and could perhaps include a link to the edit tab.

still no time for a more thorough review or testing. but i'm following the discussion closely. more later.

pwolanin’s picture

Ok, just a brain storm. I'm perfectly happy using "book" and "book page".

If I recall correctly, the version above does force you to an edit screen after you move the book page to a new book. Thus, you can immediately choose a place for it in the hierarchy. I think the default (where it starts) is at the top level, which seems the most reasonable thing to do.

dww’s picture

i'm just brain-storming, too. :)

the important point (maybe lost among everything else) in my previous comment is that when you move a page to a new book, it should be unpublished, so that the author/editor must select a reasonable place to display the page in the new book before it becomes visible to the world.

either that, or we just use an active select. ;)

hingo’s picture

Since you are trying to solve something I'd like to use on an upcoming site of mine, I hereby sign up for the job as guinea pig. Here are results from diff6:

* update.php did not automatically detect version to upgrade from. If I've understood correctly, this is not you patch'es fault but something may have gone wrong in the previous upgrade (to 4.7.1)?

* It seems that now you take each top level book page and make that into a separate book. Assuming that your patch gets accepted into Drupal core, I think it is wrong to assume that, even though it might be correct in a majority of cases. It would be better that those who think they only have one book do so also after your upgrade, and those that have multiple books have to go through some upgrading procedure which could even be manually moving top-level pages to new books of their own.

* On a correlating note, now each top level page creates a new book of the same name. So when you view the first page in a book the breadcrumbs say something like "Home > books > book about history > book about history". This is another reason why old top level book pages should not automatically become books.

* Go to: create content > book page > [select one of the books]
It would be nice to show somewhere which book a page is being added to

* There is a new menu item "books". I can disable it in administer > menus, but I'd like to be able to do that from administer > access control so that it would be visible to some and not to others.

* Following Drupal style, "Move to book", "Add page", "New page"... should not be capitalised. (It seems you have them all capitalised)

I guess if you are going to make "book" a node type, it is not a good time to start using this patch just yet on a production system? I can take a small hit for being a happy guinea pig, but if there are still major rewrites ahead maybe it's wiser for me to wait.

Then the real question: it sounds like you already have an idea on implementing per-book access control? Care to share about that?

hingo’s picture

Readers of this thread might be interested to know, that I developed a simple version of the book.module that allows you to define protected books.

nikle’s picture

The Book 6 patch does not apply properly to 4.7.2

nikdotca modules $ patch -p 0 <book.patch 
can't find file to patch at input line 8
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|Index: database/database.4.0.mysql
|===================================================================
|RCS file: /cvs/drupal/drupal/database/database.4.0.mysql,v
|retrieving revision 1.4
|diff -u -p -r1.4 database.4.0.mysql
|--- database/database.4.0.mysql        26 May 2006 09:21:10 -0000      1.4
|+++ database/database.4.0.mysql        27 May 2006 16:55:52 -0000
--------------------------
File to patch: book.module
patching file book.module
Hunk #1 FAILED at 133.
1 out of 1 hunk FAILED -- saving rejects to file book.module.rej
can't find file to patch at input line 42
beginner’s picture

StatusFileSize
new38.44 KB

reroll of the previous patch so that it applies cleanly, for those who want to test it.
No changes made.

I do my best to finish other business, so that I can dedicate more time to this issue, taking into account the comments above. Sorry for the delay.

@nikle: you should apply this patch to cvs, not to Drupal 4.7.

beginner’s picture

I need advice!

I just finished the other job that was holding me up. I am ready to give this issue some more love. Sorry for the delay.

It was mentioned earlier that the best way to handle both 'book cover' and 'book pages' was to create a new node type. I am starting to learn what creating a new node type involves... and the changes would be extensive.
Actually, it seems it's not possible to declare two node types within one module (or I haven't found out how to do that). I am looking at project.module which seems to do that ('project' and 'project issue'), but many other files are included which add to the complexity.

Creating a 'book cover' as a new node type is much, much more complex than what I first set out to do. I am still happy and willing to go ahead, but I do need help, especially from those who know well Drupal core.

I am also concerned about another thing: the only person who commented negatively on this issue is none else than Dries, who said he's not convinced this is the right direction ...
The extra features I set out to implement would be great, but does Dries have a point about the direction taken?

Dries: if it were you, how would you implement what I am proposing here?

It's a lot of work, and I don't want to be wasting my time chasing windmills.

What do you think?
Do you think something similar can be achieved with a contrib module? (we can alter form, but how far can we alter sql queries...?)

Dries?
dww?

Crell’s picture

I haven't been following this thread extensively, but on the subject of multiple nodes from one module, it is actually fairly straightforward in 4.7.

See: http://api.drupal.org/api/4.7/function/hook_node_info

If you want to define a book node and a bookcover node, you'd have something like this:

function book_node_info() { 
   return array( 
     'book' => array('name' => t('book page'), 'base' => 'book'), 
     'bookcover' => array('name' => t('book cover'), 'base' => 'bookcover') 
   ); 
 }

Then all of your node hooks for the book node have a prefix of "book_", while those for the bookcover node have "bookcover_".

Personally, I like to then separate my node functions out into a separate file, mymodule_node_mynodename.inc, and require_once() it. It makes no difference to Drupal currently, but I find it better code organization to split the module up into each node, then the non-node-hooks in the mymodule.module file. (I'd actually love .node files, but that's another topic. :-))

HTH

beginner’s picture

Thanks Crell for the review. I had tried book_node_info() already.
Still I can't get the two node types to display on the node/add page.

I still don't make the difference between the hook_whatever() called for each module and the 'base' function callback defined in hook_node_info().

For example, project module list its two node types (project_project and project_issue) in the same hook_functions:

function project_help($section) {
    case 'node/add#project_project':
      return t('A project enables teams to track outstanding items which need resolution');
    case 'node/add#project_issue':
      return t('Add a new issue (bug report, feature request, etc) to an existing project.');

same for hook_menu: both are declared within the same function:

function project_menu($may_cache) {
$items[] = array(
    'path' => 'node/add/project_project', 
    'title' => t('project'), 
    'callback' => 'node_page', 
    'access' => $access, 
    'type' => MENU_NORMAL_ITEM);
$items[] = array(
    'path' => 'node/add/project_issue', 
    'title' => t('issue'), 
    'callback' => 'node_page', 
    'access' => $access, 
    'type' => MENU_NORMAL_ITEM, 
    'weight' => 1);

My first understanding was that I needed to create separate functions bookcover_help() and bookcover_menu(), but it seems it's not necessary.
Anyhow, I tried both approaches, but I still fail to have 'bookcover' listed on node/add .

Crell’s picture

Yeah, nodes are not fully separated from modules, which I agree is bad. I believe you have to also add a menu entry for each one in hook_menu().

Feel free to contact me off-thread for more, so that we don't clutter up this thread anymore than we need to. :-) (Or there should be a handbook page somewhere...)

pwolanin’s picture

Well, is there any reason not to break this into two separate module files? I think the OG module could provide some interesting cross-pollination of ideas for this. For example, one can choose which node types are groups, and which node types can be added to a group's content. A default "group" type of node module is included, but any other node type can be used instead or in addition (incl. flexinode, etc).

OG also has functionality where the any user designated a "manager" of the group can edit any content posted to that group.

Allowing site admins the ability to choose other/custom node types as books (essentially the cover page and/or TOC of the book's content) seems like it would enhance the flexibility and extensibility.

pwolanin’s picture


The node relativity module also seems to be related, at least in some respects http://drupal.org/node/17004

beginner’s picture

I have figured out my mistake. (I was missing hook_perm, i.e. book_cover_perm).

@Crell: thanks for the offer. :) I'll contact you some day, if I need.

Now that I am back on track, I'll be quiet for a while, as I will be working on integrating all the comments above into a better patch. It may take a while as there is a lot to do...

@all: thanks for your support :)

Andrupal’s picture

I'm very excited by these developments, as my site would be greatly enhanced by distinct books. I'm trying to give each Organic Group its own book. Is this going to be possible with these modifications?

I tried the patch and hunks #5, 9 and 13 failed at lines 235, 438, 582 respectively. I also ran update.php and no changes were made to the database. Any thoughts? Should I wait until this patch is further along.

pwolanin’s picture

did you try applyying the patch to 4.7 or to HEAD? I'd wait anyhow until beginner produces the next iteration.

beginner’s picture

StatusFileSize
new34.83 KB

This patch is only for the curious and to be used on a clean cvs install (import function from 4.7 broken).

I started from scratch because implementing a book_cover node type changed the whole coding logic in my previous patches.
I have not finished implementing all your recommendations, yet.

Wait until later next week for a more complete patch to test.

beginner’s picture

StatusFileSize
new36.78 KB

here's a long overdue update especially since HEAD has changed a lot.

You can test this patch on a clean install or upgrading an existing site (NOT a live one!!!).

major changes:
0) major update to catch up with HEAD.
1) book_cover is a node type.
2) those who don't want the extra features (book_cover) can use the module exactly as before: a book_page doesn't need to be part of a book.
3) accordingly, the existing book_pages are not incorporated into any book.
4) License block, with the license of the whole book.

to do:
1) breadcrumbs,
2) a few important links missing (add book page link in book_cover).
3) check all text strings: use of t().
4) check hard-coded html: if you see any, tell me how I should handle it.

I'll do my best to have a commitable patch by the end of July: I'll work on it everyday until everybody is pleased. :)

beginner’s picture

StatusFileSize
new40.1 KB

All major issues have, I believe, now been dealt with.

1) missing link mentioned above fixed.
2) breadcrumbs work
3) adding other nodes to outline works.

TODO:

1)REVIEW this patch.
2) improve presentation of book_cover nodes: I need suggestions.
3) fix the scores of minor issues (mostly at code level).

pwolanin’s picture


I'll try to test this- I assume this requires a HEAD install, not 4.7?

beginner’s picture

yes :)

beginner’s picture

StatusFileSize
new39.91 KB

changes:
1) some code optimization (one less db query)
2) fixes a small bug. Another node type can be added to a book or to the outline independently of any book, then choose the place in the outline among independent book pages.

Currently, a node (story, forum, etc. node) can be added into the outline, but if you want to move it to another book, you have to remove it from the outline altogether before re-adding it to the proper book. Do you feel it's a major useability issue that should be 'fixed' in this patch, or do you feel it's acceptable?
(moving from book to book should be pretty rare in a properly organized web site).

beginner’s picture

StatusFileSize
new40.44 KB

changes:
1) in node/add : added a link to a page where a book can be selected, otherwise the book page is not created as part of any book (meaning we have the choice to do either).
2) further code optimization.

beginner’s picture

StatusFileSize
new41.9 KB

changes:
1) somewhat improved presentation of book cover (with book author, body, license, and table of content).
2) when deleting a book_cover, a warning is given that all associated book pages will loose their attribution to any book (I.e. $bid = 0).

beginner’s picture

Important note:
One of the purposes of this patch was to allow for a different theming of the whole page according to $bid, the book.
I was thinking to make this possible by adding a class definition either in <html> tag soup or in the <body> bag, like this: code> for any page belonging to book ID 2.

I notice that there is currently no drupal function that would allow us to do that simply.

I see 3 solutions:

1) change page.tpl.php for each theme adding some php logic to add the class name where appropriate.
2) create a drupal API function to add a class name in <body>, that other modules could use, also, a bit like we currently have stuff like: if ($site_slogan) { ? ><div class='site-slogan'>< ?php print $site_slogan ? ></div>< ?php }
3) add a setting for each book_cover to input a link to a css file for that book and use http://api.drupal.org/api/HEAD/function/drupal_set_html_head to add the css file declaration.
4) do nothing and let the admins do something similar to 1) by themselves.

Right now, I am more in favor of 3), because it is more within the scope of this patch.
what do you think?

pwolanin’s picture

Won't the proposed changes to phptemplate allow for per-node substitution of a different page.tpl.php? http://drupal.org/node/65706

I realize an automatic system would be easier for some users, but maybe not by enough to be worth the effort of getting it in?

beginner’s picture

Status: Needs work » Needs review

That issue seems to make a per-node-type page.tpl possible.
I would like to have a per $bid template. (apparently, it's more or less what shoq was asking for, but Eaton replied it's not relevant to the issue). Whatever the solution, the purpose was to have different themes for different books. A whole new .tpl.php would be much more flexible than simply an additional style.css file that I was suggesting above.

Anyhow, this is a secondary issue that could be left for a second patch. Maybe I was too greedy to bring this up at this stage :).

pwolanin’s picture

Trying to test this- last big patch seems to have broken some of the menu paths:

patching file modules/book/book.module
Hunk #4 FAILED at 131.

pwolanin’s picture

Hmmm, install doesn't seem to have worked either:

user warning: Table 'dp1.book' doesn't exist

beginner’s picture

StatusFileSize
new41.95 KB

this patch is updated for head and fixes the menu problem.

It seems that the install function is broken in head, and book_install() is not called when enabling the module. It worked as intended last time I tried, before the large patches landed in head. It is not a problem with this patch but a problem recently introduced in head. I'll investigate and try to find out what is broken.

Meanwhile, you can create the tables manually after enabling the module:

CREATE TABLE {book_pages} (
        vid int(10) unsigned NOT NULL default '0',
        nid int(10) unsigned NOT NULL default '0',
        bid int(10) unsigned NOT NULL default '0',
        parent int(10) NOT NULL default '0',
        weight tinyint(3) NOT NULL default '0',
        PRIMARY KEY (vid),
        KEY nid (nid),
        KEY bid (bid),
        KEY parent (parent)
      ) /*!40100 DEFAULT CHARACTER SET UTF8 */;

CREATE TABLE {book} (
        bid INT( 10 ) UNSIGNED NOT NULL default '0' PRIMARY KEY ,
        nid INT( 10 ) UNSIGNED NOT NULL default '0' ,
        book_author VARCHAR(255) NOT NULL default '' ,
        book_license LONGTEXT NOT NULL default '' ,
        weight TINYINT( 3 ) NOT NULL default '0',
        KEY nid (nid)
      ) /*!40100 DEFAULT CHARACTER SET UTF8 */

You don't need to run the update 1 after that.

beginner’s picture

I confirm that the install problem is not related to this patch. I just tried on a fresh, vanilla cvs version and I have the same problem:
http://drupal.org/node/76509

btw, the patch above includes a temporary fix (to be removed later) for this other critical bug:
http://drupal.org/node/74992

@pwolanin: btw, thanks for stopping by and reviewing :)

pwolanin’s picture

Ok, an initial review now that it's working. Overall, I think this is going in the right direction, so I hope you'll see the below as constructive criticism:

The 2-step outline procedure for non-book nodes seems pretty smooth and reasonable.

On a book_cover page: "Table of Content" should be "Table of Contents"

The setup at /node/add for book pages is counter-intuitive now and a little hard to understand. I'd suggest forcing all book pages to go under a book_cover. If no book_cover nodes have been created, an error message and link to create book_cover would be better. Allowing the independent, top-level book page thing seems confusing. I'd suggest essentially that creating a book page from /node/add should essentially follow the 2-step process that's used for moving a book page to a within a different book_cover. First you have to choose a book_cover to go within, and then 2nd you can edit the node and position it within the pages contained in the book_cover.

I'm not sure then how to deal with the deletion of a book_cover. You could simply not allow it until all contained pages have been moved or deleted, though I'm not sure if this is possible within the current API. Maybe some sneaky use of hook_form_alter. Or (especially if the trashbin patch gets in) deleting the book_cover could also delete all associated nodes.

The outline feature at /admin/content/book seems not to work, or at least not in the way I'm expecting.

When adding (editing?) a book page, it would be nice if the heading at the top of the page should indicate which book_cover it will be under. i.e. book cover: page title, since there still seem to be some breadcrumb problems, and the "Parent:" drop-down doesn't indicate which book_cover this page belongs to. I guess this is an alternative- label this drop-down with the book_cover title.

If I have no book_cover nodes defined, the "outline" tab still appears. I'd disable it as per requiring all book-related nodes to fall within a book_cover.

If I delete or have no book_cover nodes, the book shelf shows all the top-level book pages.

pwolanin’s picture

Thinking about how to prevent book_cover deletion when there are child pages:

How about using (node_access('delete', $node)?

I guess the problem with this is that any user with "adminiser nodes" will be able to delete without a check by the book.module.

I sort of don't like to suggest it, but how about automatic creation of a book_cover called "orphans" where orphaned book pages are relocated?

pwolanin’s picture

Ok, more thinking- just send book pages whose book_cover is deleted to the orphaned pages limbo:
/admin/content/book/orphan

You could surely set a message upon book_cover deletion informing trhe user that their book pages can now be found there?

beginner’s picture

StatusFileSize
new52.46 KB

Peter, I made numerous improvement in reply to your feedback.
I attach a copy of the module for your convenience. The patch is coming next.
In the next post, I'll outline what changes I have made, but first, I have to reply to the idea that "all book pages must belong to a book".

If you remember my early patches, that was my approach at the beginning. That's what I wanted to implement.
Since then, I both had an email exchange with Dries (about #7 above), and thought further about this issue.

Dries is really not keen on this patch, and he didn't reply when I pointed out that reasons he gave me against the patch were either not applicable, or simple stuff that could be sorted. It may take some effort to convince him to accept this patch, and he will commit it obviously only if it is perfect, which it is not yet :). Also, I promissed him that I am not taking any functionality away, just adding some more.

Also, in my early patches, I imported the book pages and assigned them to a book cover (that would have been created for the purpose, as a placeholder). That was against Drupal's policy to "break the code (in order to improve it) but not break the users' data'. I am sure that with such an approach, more than one would have (rightly) been angry to be forced to reorganize their sites. That's why in the latter patches, I don't touch the existing pages at all: we better let the admins add the pages they want to book covers they have themselves created, ... or not.

I we both insist that each book page must be part of a book, I can guarantee you that this patch will never get committed: better get the functionality that exists in the current patch, than nothing at all.
Also, it is better to retain some flexibility and let the admins use the module the way that best serves their needs.

Now, the idea to force a book page to belong to a book is not a bad idea per se. It may be the right solution for some sites (but not all).
Technically, it can be easily accomplished; I know how to do it, if need be.
But it is better kept for another patch, once this once is committed. Once this issue is closed, I'll review the whole thread and open several follow up issues for, err, issues that we knowingly left aside.
This is one of those issues. It can be dealt with in a follow up to this patch, by adding a permission: "allow (user group) to add book pages outside of any book (not linked to any book cover)." Thus we can allow/prevent users from doing so.
But first, let's make sure this patch goes in this month. We only have 2-3 weeks left.

Does it make sense, and are you ok about this?

beginner’s picture

StatusFileSize
new44.16 KB

Here's the patch. The module attached above includes this patch and was provided mainly for pwolanin's convenience.
For all others who would like to test, be aware that the module install in HEAD is currently broken: see #48.

Changes in this patch:

1) As per the discussion above, a book pages doesn't have to belong to a specific book. Book pages can be used independently of any book cover just like they are now.
It means that both book covers and top-level independent book pages can be used as the top of a book, and are visible in /book (book shelf).
In order to remove some confusion, in several places, I have listed separately under different headings the book covers and the independent top-level pages.

2)Table of Content -> Table of contents (small c)

3) book shelve: separate book covers from independent book pages. There are now two lists.

4) admin/content/book: fixed. with same separation between books covers and independent book pages.

5) when adding or editing book pages, drop-down item is labelled with book_cover title, if applicable.

6) At node/add/book_page now asks which book, if any, the page should be part of.

7) checked that all strings are t()'ed.

8) checked admin of orphaned pages: works as intended.

TODO:
Dries complained of hard coded HTML.

Even without this patch, there is some hardcoded HTML in book.module. In places where I add some more HTML, I really don't know how else I am supposed to do (i.e. nested lists for table of content, h2 headings in only 1 or 2 places , etc.)
I'll keep browsing the api to get a clue on how it is supposed to be done, but I would appreciate some hints, etc.

beginner’s picture

the install procedure has been fixed in head, so new testers only need to enable the book.module. You only need to run update.php if you are upgrading from an existing (test) website.

pwolanin’s picture

I'm sure the recent changes to HEAD have made more work necessary to move this patch along.

Let me know if there are some TODO items with the code that you'd like my assistance with.

In regard to your comments above, I don't feel strongly about having book_pages outside a book- just seems like a cleaner interface to me to avoid it.

pwolanin’s picture

As far as hard-coded HTML, looks like one easy change might include a couple like this:

    $output .= '<h2>' . t('Independent top level book pages') . '</h2>';
    $output .= theme('item_list', $books);

to this:

 $output .= theme('item_list', $books,t('Independent top level book pages'));

Alsp,

_book_cover_toc($bid) 

should probably just do the query/array building and then call a theme function (also needs rewrite)

function _book_cover_toc($bid) {
  $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, bp.parent, bp.weight FROM {node} n INNER JOIN {book_pages} bp ON n.vid = bp.vid WHERE n.status = 1 AND bp.bid = %d ORDER BY bp.weight, n.title'), $bid);

  while ($node = db_fetch_object($result)) {
    if (!$children[$node->parent]) {
      $children[$node->parent] = array();
    }
    $children[$node->parent][] = $node;
  }

  return theme('book_toc',$children);
}

and then anyone who wanted to could totally change the theme function, including using a different function to walk through the array:

function theme_book_toc ($children) {
  $toc = '<hr /><div class="book_toc"><h3>' . t('Table of contents') . '</h3>';
  $toc .= build_book_toc($children);
  $toc .= '</div><hr />';
  return $toc;
}

function build_book_toc($children, $nid = 0) {
  if ($children[$nid]) {
    $toc = '<ol>';
    foreach ($children[$nid] as $foo => $node) {
      $toc .= '<li>'. l($node->title , 'node/'.$node->nid). '</li>';
      $toc .= build_book_toc($children,$node->nid);
    }
    $toc .= '</ol>';
  }
  return $toc;
}
beginner’s picture

Status: Needs review » Needs work
StatusFileSize
new52.13 KB

Peter, thank you for your assistance. If you wish to help, I attach a copy of my book module so you don't have to patch.

Right now, I am trying to update the module to work with the CCK-ified head.
Many things are broken, now. I already fixed a few, but many problem still remain. I have already spent some time trying to figure out how things are supposed to work.

book_view() has been removed, but I need it back to deal with both node types so that I can display the extra fields for the book cover. Problem is, each time I add the function back, the content of a book page and book cover disappear altogether...
First I am trying to view a book page as before CCK hit core.

Then I'll try to figure out how to load the extra book cover fields (author, license).

My immediate problem is that the documentation is not up to date or not complete, and I no longer have an example to copy from.
http://api.drupal.org/api/HEAD/function/hook_view
http://drupal.org/node/64279#node-view

beginner’s picture

ok, I have figured out book_view(). A default book page loads properly.
Now I need to find out how to get the extra fields for a book cover.
$node->author and $node->license are not set...

pwolanin’s picture

Are you trying to get the extra fields to load from the db, or to display during node_view?

beginner’s picture

StatusFileSize
new53.06 KB

After much searching, I come to the conclusion that the new node API is broken.
http://drupal.org/node/78549.

/node/add and /admin/content/types do not work properly because of that bug, but if you access directly /node/add/book_cover it works.
I'll check that issue first, then implement your suggested changes re. html.

Beside the noted bug, the attached module should work on your test platform (if it includes the DB changes noted in #48) with head.

beginner’s picture

Status: Needs work » Needs review
StatusFileSize
new45.84 KB

The functionality is the same as in the module previously attached.
All changes now are on the code style level.

Changes in this patch:
1) full update to post-CCK cvs.
2) The patch temporarily include the patch RTBC'ed for the issue: http://drupal.org/node/78549 , so you can test the full functionality.
3) Peter's theming suggestions in #57 have all been implemented (thanks for teaching how to do things :) ). I have checked all other occurrences of similar code.
4) corrected the coding of embedded links, many coding style issues, and small theming issues.
5) removed some commented out code that was allowing to move a book page to a new book but leave its children in the original book. Instead, the user is warned that the children will be moved together with the parent: the user can update the children first if needed (not likely!).
6) Now that I now how to properly use the theming functions :) I have created theme_book_author and theme_book_license to theme the book cover (neither appear if they are not set).

My patch is now ready (again) for proper review.

Please,
a) Review the UI and the functionality. Most has been discussed already, and some points mentioned above will be dealt in follow up issues.
b) Review the code itself. I have corrected all the problems I was aware of including all the hard-coded html issues mentioned above.

pwolanin’s picture

I am trying to review this patch in detail and maybe make some modest changes- I'll assume you're not making more changes now?

In particular, I want to unify the UI for adding/moving pages to books.

also, why not put an "outline" tab on all pages? I think this may be simpler than the current system- for the book cover, the outline tab could bring you conveniently to the outline for that book.

pwolanin’s picture

I'm trying to review this in detail and maybe make some modest changes- I'll assume you're not changing it any more and try to post a revised patch later this evening or tomorrow.

beginner’s picture

StatusFileSize
new43.97 KB

I am just keeping up with HEAD.
No code changes in book.module, but
1) the patch for the node-type bug has just been committed (much quicker than I expected), and the corresponding patch is removed here. http://drupal.org/node/78549
2) changes for postgreSQL in book.install to conform to the coding style in today's postgreSQL patch. http://drupal.org/node/76681

I tested the update function and it works as expected.

beginner’s picture

re: #63:

-1 both on the 'outline' tab on all pages and a similar form for selecting a book and moving a page to a book.
You mentioned this earlier in the thread, and while coding, I have thought about those two ideas a lot.
There are two reasons why it is not a good idea.

1) It is a bad UI useability issue to have a same interface doing very different tasks. It would only confuse the user. If I see a form, I know I am moving an existing page to another book. If I see a list of links, I know I am selected a book to create a new node. Same: if I see an outline tab, I know I am dealing with a non-book_page node-type that can be taken off the book outline alltogether if necessary. Visually, I know straight away what I am doing.

2) Code wise, when creating a new book page, I must use GET method to select the book to add the page to, to conform to the rest of the UI (e.g. 'add child page'). When moving a page to another book, I must use the POST method to use the FAPI.
If I were to try to force the former to use POST or the latter to use GET, the code would be much more complex for no exact benefit.

I hope this is ok with you.

pwolanin’s picture

Well, I'm making some progress but it's not fully backed yet. I'll let you look at my concept. I'm trying for maximum reuse of code and interface. I'm trying to make "outline" look the same for book_pages and non-book_pages with the exception that non-book_pages have an extra option to remove from the book outline. Both have a "move to another book" option. the outline tab on a book (cover) redirects to the outline admin page for that book. Maybe it should show as a local task, rather than redirecting.

Also, there are a couple issues that seem more fundamental

the book_page table should not use vid since there is not proper revisionsing for non-book_page nodes. Also, if you move a book_page to another book, there would be odd side effect of loading a revision that's back in the other book/with parents in another book. The OG module does not try to track the vid, only the nid of nodes within a group and I think that makes sense here. I'm not sure how to do the SQL for the upgrade path- basicially all the entries in the book table for the non-current vid should be discarded/not copied to a new table.

Second, the book table should include vid and use this as the primary key, since the data (license, author, etc) may be different per revision.

also, i think the node type should be named book and book_page to match the table names.

beginner’s picture

For the outline tab, see #66. I'd rather you leave them as is for now.
For the rest, I'm happy about the improvements

pwolanin’s picture

StatusFileSize
new48.01 KB

Please take a look at the attached patch (doesn't include node module patch). I was already well down the path of merging the outline tabs, and perhaps it will grow on you when you see it. I realize there is some cleanup that is needed in terms of the form appearance, but it seems to be functional.

The update part of the install file is still non-working. Also, the permissions may need work. Found several bugs that are present in the 4.7 module, though I'm not sure I'll remember them to try to fix them (one's in 4.7's book_submit).

pwolanin’s picture

Also- a side benefit of this approach to the outlining is that the permissions to outline a node can be totally separated from the permission to edit the node. i.e. someone who cannot edit a book_page can still move it to a different position in the book or move it to a different book.

drumm’s picture

I was hoping that the hard-coded book node type would actually be removed and this module would use only nodeapi now that we have configurable content types.

I'll review this again if it gets to 'ready to be committed' (same for all features).

pwolanin’s picture

StatusFileSize
new48.02 KB

Oops, one feature was broken- I got hung up on the new node URLs: node/add/book-page vs. node/add/book_page. Fixed in the attached patch.

As far as making the book_page type optional or redundent: I think this patch is pretty close to this. The essential difference is that the edit form for a book node may include the select form to choose the level in the book and the weight, while for other node types this is only accessible via the "outline" tab.

pwolanin’s picture

Also, the book_page type serves as a default for the "add child page" and related functionality. I'm really not sure how you could do that with a defined node type.

drumm’s picture

Make a prefilled book node type, like page and story when the book mopdule is installed (first enabled). Also prefill the settings to make that node type function as a book page.

pwolanin’s picture

@drumm- Well, I can imagine how much of the functionality could be accomplished that way. However, I'm not sure how one could do the kind of two-step process that kicks in now at node/add/book_page. if you click "book_page" under create content, the code above redirects to a form to choose which book to put the page in, before sending you to the actual node form. I suppose that this could be considered dispensible??

pwolanin’s picture

Status: Needs review » Needs work
StatusFileSize
new51.37 KB

setting back to needs work - attached patch is (I hope) continuing to move in the right direction, but is not complete.

I changed book_page_form further so that the "special" paths are like node/add/book-page/$bid/$parent. This simplifies the function so only one check is needed. Need to think further about how to deal with the case of a manually entered path where the user doesn't have access to view the book. I think if they don't have access to the parent (or the parent doesn't exist), then the select just defaults to .

Tried to rename some functions to distinguish book/book_page

Also worked on the display function for the book_page menu, but it may need more. There is some very odd logic the way it works now.

I'm also thinking that like OG, the bid should be the nid of the book node? This would probably simplfy some of the SQL and logic. The only downside is that bid values will be arbitraty and potentially large numbers rather than in order.

Upgrade path is still undefined. I've been thinking about this and still wonder if converting all the top-level book pages to book nodes might not be the best solution???

pwolanin’s picture

StatusFileSize
new53.39 KB

trying to work more kinks out and improve the overall code.

Diff attached, but this is almost certainly broken by recent changes to HEAD (FAPI and t()). I will endeavor to update this to work with HEAD.

pwolanin’s picture

StatusFileSize
new59.24 KB

I think this is fixed now to work with HEAD and incorporate recent patches.

some areas that still need work:

function book_help
function book_view

also, the orphan pages page is a little odd (I think it's the same in 4.7 though), since the nodes have to be edited to re-attach them. Maybe a link to the "outline" page for that node should be included also as an operation.

pwolanin’s picture

StatusFileSize
new60.09 KB

found a couple more mistakes (including using nid rather than vid for joins between the book and node tables, and a broken book_update()). Also, made an (untested) stab at the update function.
Try this instead of #78

pwolanin’s picture

StatusFileSize
new5.56 KB

attached script is hacked from the devel module- iit will quickly create book and book_page nodes for testing purposes. Create a few users and enable the path module before running. Note- put this script in the Drupal root directory and expect it to take a minute or two.

Running this script and then looking at the book TOCs, it seems that there are problems with the book navigation code when you are at a node with no children.

pwolanin’s picture

Also, there is a problem with the book block: for pages associated with a book (bid != 0), the block still only shows the nodes up to the immediate parent that has parent == 0 , and titles the block that parent. Thus, the block only shows a "chapter" rather than the whole "book".

pwolanin’s picture

StatusFileSize
new60.09 KB

caught a bug where user_access was called instead of node_access. Caused ugly SQL errors, etc.

beginner’s picture

you must incorporate my code changes in #65 in book.install (postgresql).

beginner’s picture

you also need to update your working copy:

-// $Id: book.install,v 1.5 2006/08/20 06:38:50 dries Exp $
+// $Id: book.install,v 1.3 2006/08/04 06:58:44 dries Exp $

pwolanin’s picture

StatusFileSize
new60.17 KB

Oh, right- I must have been working off an earlier version of the install file. See attached.

also, there's some problem in the genration script I posted with the assignment of parents. I'll try to fix and re-post.

beginner’s picture

add child page link missing on a book (cover).

pwolanin’s picture

StatusFileSize
new60.21 KB

fixed permission checks for links

pwolanin’s picture

StatusFileSize
new5.88 KB

better generation script attached- #of nodes desired can now be set at the top. Also, before I was forgetting to empty the array of parents when moving to the next book.

pwolanin’s picture

StatusFileSize
new60.13 KB

Ok, put back node type checking for the outline tab as per e-mail.

The outline function on the admin pages is horribly inefficient and needs some love (using the same tree function as generates the selects, etc). I think it's also displaying in the wrong order (look at the weights).

Also, attach patch fixes the book navigation block. If bid != 0, title is the book title, all pages displayed. If bid ==0, title is the title of the top level book that's a direct parent, and only the pages under that parent are displayed.

pwolanin’s picture

StatusFileSize
new60.17 KB

oops- block code still wasn't quite right.

pwolanin’s picture

StatusFileSize
new5.75 KB

script attached to create lots of 4.7-style book nodes to test the update code.

pwolanin’s picture

StatusFileSize
new60.35 KB

changed the update script- book nodes need to be renamed to book_page

beginner’s picture

Have you checked #86?
Other than that, I think it's getting ready.

pwolanin’s picture

yes the link is fixed for child page.

a couple outstanind isssue if you want to try tackling them:

the help text and links need work, since the book/book_page change hasn't really been delt with there.

Also, there is no printer-friendly link on books (covers) - I'm not sure what need to be done to make that work.

pwolanin’s picture

StatusFileSize
new693 bytes

Ok, the conversion frmo a separate counter from bid to useing the book nid as bid is nearly done. The book_form now includes a select for the weight (missing before) and a select for the *new* toc_depth field.

Also, I took out the <ol> function for making the book TOC and used the same function that generates the block. The reason: the toc_depth field for each book that allows you to choose to what depth the TOC should be expanded on the book page. However, this only makes sense when using the expanded/leaf attributes so that you can see which items have children.

Attached is a version of the original function that can be plugged into your theme folder. I'm not sure if something like this could be included- maybe just put it as a theme snippet.

pwolanin’s picture

Status: Needs work » Needs review
StatusFileSize
new61.72 KB

Ok, I haven't found any bugs in the last 10 minutes, so mayeb it's ready to review. Helper node-generating script to follow.

Also, beware this block bug: http://drupal.org/node/80150

pwolanin’s picture

StatusFileSize
new5.93 KB

script to generate book and book_page nodes that match schema from #96

pwolanin’s picture

this patch: http://drupal.org/node/4074
was just applied which seems to break #96. will try to re-work.

pwolanin’s picture

StatusFileSize
new64.19 KB

Added equivalent change to the above-referenced patch. Also fixed up book_help.

Note- look at function book_submit(). I fixed a bug(?) there so now if a user edits a book page they become its author. This doesn't happen in 4.7 because of an incorrect reference to $book rather than $node.

beginner’s picture

Status: Needs review » Reviewed & tested by the community

Ok! I can't find any bug any more, and the major issues I had before have been dealt with.
The code itself is much improved and optimized compared to where I left it.

Now we do need a proper review from Neil or Dries :).

To the reviewers:
The thread is long: would it need if we made a summary of what this patch does, and what it does NOT?

drumm’s picture

Status: Reviewed & tested by the community » Needs work

Don't change past updates (such as system #1000). Make new updates.

beginner’s picture

What do you mean?
We are not updating the system but book: book_update_1000().
I tested it once (updating from 4.7) and it worked.
The book module doesn't have any update, yet, so what should the first number be?

drumm’s picture

Status: Needs work » Needs review

I misread that. This would be our first non-system core update hook.

This is still not ready to commit since it is a huge change only reviewed by two people. This must be okay for the documentation team for Drupal.org since we have to deal with this module too.

I'd like to reiterate that I think we should be removing hard-coded content types instead of adding them.

pwolanin’s picture

@drumm, I have been thinking about the use of non-hard-coded types. I certainly think we could get there if it's really important to you for this cycle, but there are two problems:
1) time before Sept 1st.
2) is it possible now with the forms API tp do multi-step forms (via form alter)?

For #2 I got no answer on the devel list,though maybe i'll try again. The problem is with the book_page type. We want to be able to go to a form to select a book if the user chooses that type from the create content page. The current solution uses a redirect within book_page_form().

beginner’s picture

StatusFileSize
new64.99 KB

fixes a minor bug.

boris mann’s picture

What if you selected, in settings, which node type (or types) to be a book page? This leaves us without a book page, but still gives you a method to deal with nodes that are meant to be in a book.

pwolanin’s picture

@Boris - I think that could indeeed be a next step, but would be enough of a change that it may need to be for a subsequent release (see below).

@drumm - I'm on the documentation list and have permissions to update Drupal handbook pages, so I can be involved in that effort.

Also, as food for thought, this is were I see that this module *could* go:

1) All types are DB- defined, user configurable (as per Neil's idea).

2) Admins can choose one or more node types to be "book" types (like OG groups)

3) For each book, the admin can choose a (different) default type for the child pages.

4) Clean up lots of inefficient code (reduce # of queries) for the book navigation and others. (note that this work could be considered bug fixes, done after Sept 1, and maybe backported to 4.7)

I'm very reluctant to try implement 1-3 all in the next week, though I think 1-3 are actually not that hard. Partly, I'm a little worried about trying to keep up with the prospective changes in the content types code . I also don't want to put that level of effort in without some real assurance that the patch is likely to go into HEAD.

sepeck’s picture

In concept this looks to expand an already powerful feature of Drupal's. Seperating books and adding descrete permissions.

I myself don't mind the long move pages tree and have often switched pages between books but can see how some wouldn't like the current UI. The intial use case as to why one wouldn't was to limited. I can think of several alternative use cases but am not bothered by it to make a long discussion.

So... what's in the patch? Needs a summary seperate from the original issue in May and the misc other wrap ups since. I agree with Drumm that I would prefer less hard coded content types as we're going that way with core but am not married to it right now. In any case I understand the reluctance to go if not sure of the reception. Otherwise I like what I've been able to parse regarding the increased functionality and I suspect it will be a popular addition. I am moved enough that if I can this weekend I will even try and test it with HEAD.

pwolanin’s picture

StatusFileSize
new64.7 KB

The patch in #105 doesn't apply cleanly for me, so I've attached another with the same bug fix, plus a reworking of one utility function (book_update_children_bid) - no UI or functional change.

Let's think about moving the issue, since some of the initial description does not really apply (including the schema and some of the permissions). This patch does not currently try to provide per-book permissions.

m3avrck’s picture

Wow, this is awesome. This makes books actually useful! I might have to rethink books with this one, I could actually use them in some cases. This would be fantastic for educational based distros.

eaton’s picture

I certainly understand if you're not interested in pouring more energy into major changes, but #3 that you mentioned -- "For each book, the admin can choose a (different) default type for the child pages" -- would make this tremendously useful as a tool for online webcomics and other such structured sites. Right now, it's a bit of a pain managing those things, and these changes would make it a good deal simpler.

pwolanin’s picture

Ok, I'll take a look at how to implement #3. Does any one have sugesstions as far as the data structure and UI? My initial thought it to make this part of the {book} table and to present the option as part of the book create/update form. Should the visibility of this option be based on an existing permission (e.g. "administer nodes")?

beginner’s picture

It is indeed a good idea, but Dries just wrote on the list about not cramming too many new features into one patch.
It would be ironic if adding a new feature actually decreases the chances of the patch being committed...

Can the existing patch be properly reviewed (quick!) by those interested?
Additional features can (and will) be added in follow up patches.

eaton’s picture

beginner makes an excellent point. adding node type configurability may be best left to subsequent patches, as nice as the feature is. This patch is already pretty heavy, energy should probably go to making it commit-ready rather than adding a few more features to the checklist.

Anonymous’s picture

Relevant to the Book Module (though distinct from the changes in the patch) is some cleanup I've proposed on the module's documentation in Core.

As follows:

By presenting a valuable feature of the Book Module as the defining one, the documentation in core (and in the Handbook) hides the module's power and makes the module seem limited in a way it is not.

The core documentation says:

A book is a collaborative writing effort: users can
collaborate writing the pages of the book, positioning the
pages in the right order, and reviewing or modifying pages
previously written. So when you have some information to
share or when you read a page of the book and you didn't
like it, or if you think a certain page could have been
written better, you can do something about it.

My suggested revision:

A book is a set of pages tied together in sequence, with
links and menus (automatically created) to guide users from
section to section or to the previous page or the next.
Users can collaborate in writing the book, reviewing or
modifying the pages, and putting them in the right order.

A book may be collaborative but doesn't have to be. I can write a one-man book that no one else can modify. Or, for that matter, with the right permissions I can collaborate on a story or a page. The ability to allow or disallow limited or unlimited collaboration is a Drupal feature from top to bottom. (Put that last line in lights and send it to the marketing team.)

When I first came upon Drupal I saw the "collaborative book module" touted as its outstanding feature-- but it seemed an odd one, and for my one-man site likely irrelevant. Perhaps for literary geeks experimenting with a multi-author novel?

Both for informing and for marketing, the docs here deserve to be fixed.

---------------------------------

Going a bit further, here's what I'd do to the whole page (tightening the copy here and there):

Home

create content
Choose an item from the list:

book page
A book is a set of pages tied together in sequence, with links and menus (automatically created) to guide users from section to section or to the previous page or the next. Users can collaborate in writing the book, reviewing or modifying the pages, and putting them in the right order.

page
If you want to add a static page, like a contact page or an about page, use a page.

story
Stories are articles in their simplest form. They have a title, a body, and (taken from the body) a teaser. You can also use stories for a blog or for news articles.

It's hard to know, sometimes, whether I'm sending suggestions to the right place. If this is not the right place, I'd be grateful if someone would move this set of suggestions to where they should go.

sepeck’s picture

O Godiva,

this would be better as an issue against the documentation project or on the documentation mailling list. This issue is for a patch for the next version of Drupal. No need to reply to this.

karens’s picture

I think this would be a great addition and I need functionality like this in an upcoming project, so I'm about to test this. I couldn't get the book.install part of the patch to apply, but the patch to book.module worked fine.

I absolutely need the ability to make both the book and book_page configurable types since I need to be able to add other fields to them (using cck). This should actually reduce the size of the code by letting other modules handle table and field maintenance and eliminate possibly unnecessary fields (i.e. not everyone has any need to track 'license' for each book, but may have other fields they need.)

I guess I agree (reluctantly) not to slow things down by adding that capability in now but would like to see it be a top priority.

Anyway, this looks like a wonderful and much needed effort.

pwolanin’s picture

right now any node type *can* be added to a book, so the reason to make other node types than book_page the default child page is for an easier workflow.

If this patch were to get in within the next day or so, I'll try to supply additional patches to add at least part of the other functionality I proposed. So, please test and provide you feedback on this patch!

pwolanin’s picture

StatusFileSize
new67.02 KB

attached is another patch against the most recent HEAD. The functionality of this patch is the same as the previous but includes some clean-up and reformatting of comments to try to better conform to http://drupal.org/node/1354, plus added validation of the book ID ($node->bid) when setting the $node->bid for a new node based upon the URL. To facilitate this, the book/parent info is now added to the URL as a query string, rather than as part of the path (before: node/add/book_page/1/1, now: node/add/book_page?book=1/1).

pwolanin’s picture

for those who want to test the patch- test site with dummy content:
http://book.wolanin.net

dries’s picture

This patch conflicts somewhat with my view of the book module. I want the book module to become a generic tool to outline/structure nodes in hiearchies and to provide the nagivational elements for that. I would also like to get rid of the "book page node type" and just use a CCK node types (or simple stories) to populate the book hierarchy.

In a way, I want the book module to be less of a book module. This patch makes the book module more of a book module (eg. it adds license information, book covers, book authors, etc).

Coding style needs work. For example, we use dashes, not underscores to name CSS elements.

karens’s picture

I tried to follow this whole long thread to see if this was discussed earlier, so may have missed it. Does it make sense to make this a contributed module instead of a patch to core? I think this kind of functionality (once the ability to use configurable content types for book and page are added) is going to be valuable to many, but will be overkill for others. To me, this is sort of a 'book plus' module that not everyone will need. Why not just make it a contributed module, and let the people who need it work the bugs out of it without affecting people who are perfectly happy with the current book module. Like other contributed modules, if it is useful enough and used by enough people, it might get rolled into core in the future.

The only problem with that approach that I can see is the naming of the module since you'll need a name other than book.

@Dries, I agree that the function of the current book module is more navigational than book-like and that there needs to be a module that provides that simple navigational functionality. I think the confusion is that it is called 'book' when it is not exactly that, and people who really need the ability to create real books think they will get it and do not. (I found that confusing, too at first). I think making this kind of book functionality available in another module would be big win for everyone. Too bad the names are going to be confusing :-)

karens’s picture

I'll just throw this out, knowing that it would probably create too much havoc to consider. I'd like to see the core book module re-named to 'outline', which is much more descriptive of its actual use, then set this module up to be 'book', for people who need to create things that are really books.

pwolanin’s picture

I'm in full areement with Dries at to what the end result should look like. It's really a question of the best tatics - I'd like to see a version of this patch go in, and then have additional patches as incremental steps towards the goal.

@KarenS - I don't think the functionality of this vs. the existing book module is different enough to warrant a split. I'd rather see a core module that's much more flexible, but that woks similarly to the current book module by default.

pwolanin’s picture

StatusFileSize
new68.69 KB

Attached patch cleans up the CSS classes per Dries' comment and gets rid of hard-coded <hr/> elements in favor of adding borders with CSS. Also caught a minor bug and tried to improve the code a little by reducing queries.

As far as I'm concerned, this patch is RTBC and would be a fine addition to 4.8. From here I will start a new issue and try to modify this in stages as follows:

  1. drop the license and author fields from the book table
  2. add a field to the book table for a selectable default child page type
  3. allow other node types to be "books"
  4. make the "book" and "book_page" types DB-defined
pwolanin’s picture

Please direct follow on to: http://drupal.org/node/81226

drumm’s picture

Status: Needs review » Closed (duplicate)