Hi all,

Love the module and saw that support for Book modules was on the Todo list. Well I got a hacking on it today and have the following patches for consideration:

--- views_data.inc.orig 2006-02-23 15:33:06.000000000 -0700
+++ views_data.inc      2006-02-23 19:35:17.000000000 -0700
@@ -164,6 +164,32 @@
     );
   }

+
+  if (module_exist('book')) {
+    $tables['book'] = array(
+      "name" => "book",
+      "provider" => "internal",
+      "join" => array(
+        "left" => array(
+          "table" => "node",
+          "field" => "nid"
+        ),
+        "right" => array(
+          "field" => "nid"
+        ),
+      ),
+      "filters" => array(
+        'parent' => array(
+          'name' => "Book: Parent Node",
+          'list' => "views_handler_filter_book_parent_zero",
+          'operator' => "views_handler_operator_andor",
+          'help' => "This allows you to filter books based on parent node.",
+        ),
+      ),
+    );
+  }
+
+
   if (module_exist('comment')) {
     $tables['comments'] = array(
       "name" => "comments",
--- views.module.orig   2006-02-23 16:09:27.000000000 -0700
+++ views.module        2006-02-23 19:31:45.000000000 -0700
@@ -1847,6 +1847,19 @@
  *   The query object being worked on.
  */

+/*
+ * Returns list of parent nodes.
+ */
+function views_handler_filter_book_parent_zero() {
+  $parents = array();
+  $result = db_query("SELECT DISTINCT parent FROM {book} ORDER BY parent");
+  while ($obj = db_fetch_object($result)) {
+    $parents[$obj->parent] = "$obj->parent";
+  }
+  return $parents;
+}
+
+
 /*
  * Filter a view based on taxonomy id.
  */

The following output is an export of a default configuration for books made to look as much like the default as possible.

  $view = new stdClass();
  $view->name = 'book';
  $view->description = '';
  $view->access = array (
);
  $view->page = TRUE;
  $view->page_title = 'Books';
  $view->page_header = '';
  $view->page_header_format = '1';
  $view->page_type = 'list';
  $view->url = 'book';
  $view->use_pager = TRUE;
  $view->nodes_per_page = '10';
  $view->sort = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'sortorder' => 'ASC',
      'options' => '',
    ),
  );
  $view->argument = array (
  );
  $view->field = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'label' => '',
      'handler' => 'views_handler_field_nodelink',
    ),
  );
  $view->filter = array (
    array (
      'tablename' => 'node',
      'field' => 'type',
      'operator' => 'OR',
      'options' => '',
      'value' => array (
  0 => 'book',
),
    ),
    array (
      'tablename' => 'node',
      'field' => 'status',
      'operator' => '=',
      'options' => '',
      'value' => '1',
    ),
    array (
      'tablename' => 'node',
      'field' => 'distinct',
      'operator' => '=',
      'options' => '',
      'value' => '',
    ),
    array (
      'tablename' => 'book',
      'field' => 'parent',
      'operator' => 'AND',
      'options' => '',
      'value' => array (
  0 => '0',
),
    ),
  );
  $view->requires = array(node, book);
  $views[$view->name] = $view;

What do you think?

Comments

merlinofchaos’s picture

It's a good start.

Book support needs an argument, I think it's crucial; having a view tied to a single book is not nearly as useful as being able to have a view where you simply pass in a NID and get all the direct children of the book page.

davev’s picture

Thats what this does.

views_handler_filter_book_parent_zero() returns a list of all nodes that are listed as parents of other nodes.

You can then select one or several to build the view.

Although i'm experience a bug with this patch right now where it displays one link for every time the node had a revision. Every link is to the current revision.

So I need to add some sort of vid filtering.

merlinofchaos’s picture

Nono, you misunderstand what i mean by 'argument'.

An argument is a special type, with one of the more complex handlers in the system.

It's something a user can put in the URL and is generally used like a filter, though it doesn't have to be. What you have there is a 'filter' handler, and I'm talking about an 'argument' handler. (Search the code for views_handler_argument_ to get an idea what they look like).

the greenman’s picture

I've done a little work to extend this code and add an argument handler. This will probably have the same issues with versioning as before, as I have not yet had a look at that.

One question:
In summary view, we get a num_nodes column, which is rather random in this case. What is the best way to make this mean something ?

I am not big on patches, so I have made this code work as a module called book_extensions . So, if you save this to book_extensions.module and enable it, the book functionality will be added to views.

function book_extensions_views_tables()
{

    $tables['book'] = array ("name" => "book", "join" => 
       array ("left" => array ("table" => "node", "field" => "nid"), 
              "right" => array ("field" => "nid"),), 
              "filters" => array ('parent' => array (
                    'name' => "Book: Parent Node", 
                    'list' => "views_handler_filter_book_parent_zero", 
                     'operator' => "views_handler_operator_andor", 
                     'help' => "This allows you to filter books based on parent node.",
       ),),);
    return $tables;
}

function book_extensions_views_arguments()
{
    $arguments = array ('book_parent' => array ('name' => t("Book Parent"), 'handler' => "views_handler_arg_book_parent"),);
    return $arguments;
}

function views_handler_filter_book_parent_zero()
{
    $parents = array ();
    $result = db_query("SELECT DISTINCT parent FROM {book} ORDER BY parent");
    while ($obj = db_fetch_object($result))
    {
        $parents[$obj->parent] = "$obj->parent";
    }
    return $parents;
}

function views_handler_arg_book_parent($op, & $query, $argtype, $arg = '')
{
    switch ($op)
    {
        case 'summary' :
            $query->ensure_table("book");
            $query->add_field("parent", "book");
            $query->add_field("title", "node");
            $query->add_field("nid");
            $fieldinfo['field'] = "book.parent";
            return $fieldinfo;
            break;
        case 'filter' :
            $query->ensure_table("book");
            $query->add_where("book.parent = '$arg'");
            $query->add_where("book.vid = node.vid");
            break;
        case 'link' :
            return l($query->title, "$arg/$query->nid");
        case 'title' :
            if ($query)
            {
                $term = db_fetch_object(db_query("SELECT title FROM {node} WHERE nid = '%d'", $query));
                return $term->title;
            }
    }
}

    
merlinofchaos’s picture

Status: Active » Fixed

This (or something very much like it; I added some stuff) now in HEAD.

Anonymous’s picture

Status: Fixed » Closed (fixed)