<?php
-// $Id: book.module,v 1.1 2006/05/07 07:29:15 urbanfalcon Exp $
+// $Id: book.module,v 1.361 2006/04/17 20:48:26 dries Exp $
+// Edited to add page weights permissions in access control
 
 /**
  * @file
  * Allows users to collaboratively author a book.
  */
+ 
+/*
+* Custom function to aid javascript-based book parenting.
+* -returns the nid of the top level node of the book tree to which $nid belongs
+* -used as the initial value of the book select
+*/
+function book_top_level_book($nid) {
+	if ($nid){
+		$book_list_query = db_query('SELECT * FROM {book} ORDER BY nid');
+		while($book = db_fetch_object($book_list_query)) {
+			$book_list[$book->nid] = $book;
+			}
+		$current->nid = $nid;
+		while($book_list[$current->nid]->parent != 0) {
+			$current->nid = $book_list[$current->nid]->parent;
+			}
+		return $current->nid;
+		}
+	}
+	
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns an array of all top level book nodes
+* -used to initialize the book select
+*/
+function book_top_level_booklist() {
+	$search = array('"', '(', ')', chr(10), chr(13));
+	$replace = array('\"', '\(', '\)', '', '');
+	if (user_access('administer nodes')) {
+		$root_books[0] = t('New book');
+		}
+	$book_list_query = db_query('SELECT b.*, n.title FROM {book} b JOIN {node} n ON n.nid = b.nid WHERE n.status = 1 ORDER BY b.weight, n.title');
+	while ($node = db_fetch_object($book_list_query)) {
+		$node->title = $node->title . (user_access('administer nodes') || user_access('adjust page weights') ? ' : '. $node->weight : ''); //show weights
+		if ($node->parent == 0){ //only show root books in this list
+			$root_books[$node->nid] = str_replace($search, $replace, $node->title);			
+			}
+		}
+	return $root_books;
+	}
+	
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns the array of book data that everything else operates on.
+*/
+function book_booklist_query() {
+	$result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.status = 1 ORDER BY b.weight, n.title'));
+	while ($node = db_fetch_object($result)) {
+		if (!$children[$node->parent]) {
+			$children[$node->parent] = array();
+			}
+		array_push($children[$node->parent], $node);
+		}
+	return $children;
+	}
+
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns an array of all the books beneath $root_book_nid in the book tree.
+* -used to initialize the parent select
+* @param
+* $root_book_nid : the top level book
+* @param
+* $booklist: result of book_booklist_query()
+*/
+function book_current_book_chapters($booklist, $root_book_nid) {
+	if ($root_book_nid){
+		return book_toc_recurse($root_book_nid, '', array(), $booklist, $exclude);
+		} else {
+		return array();
+		}
+	}
+	
+/**
+* Custom function to aid javascript-based book parenting.
+* @param
+* $root_books: array of top level books
+* @param
+* $booklist: result of book_booklist_query()
+*/
+function book_insert_bookjs($booklist, $root_books, $default_parent = 0) {
+	$search = array('"', '(', ')', chr(10), chr(13));
+	$replace = array('\"', '\(', '\)', '', '');
+	foreach($root_books as $nid => $title) {
+		$root_book_pages[$nid] = book_toc_recurse($nid, '', array(), $booklist, $exclude);
+		}
+	$init_option .= "		case \"0\":\n";
+	$init_option .= '			parentSelect.options[0] = new Option("'. t('<top-level>') . "\", 0);\n";
+	$init_option .= "			break;\n";
+	foreach($root_book_pages as $key => $root_book) {		
+		if ($key) {
+			$init_option .= "		case \"$key\":\n";
+			$init_option .= '			parentSelect.options[0] = new Option("'. t('<top-level>') . "\", $key);\n";
+			foreach($root_book as $book_nid => $book_page_title) {
+				$book_nid == $default_parent ? $defaultSelected = ", true" : $defaultSelected = "";
+				$book_page_title = str_replace($search, $replace, $book_page_title);
+				if ($book_nid != arg(1)){
+					$init_option .= "			parentSelect.options[parentSelect.options.length] = new Option(\"".$book_page_title."\", ".$book_nid.$defaultSelected.");\n";
+					}
+				}
+			$init_option .= "			break;\n";
+			}
+		}
+	$jscript = "<script type=\"text/javascript\">
+<!--
+function setParentSelect(bookSelect, defaultParent) {
+	var bookOption = bookSelect.selectedIndex;
+	var bookOptionValue = bookSelect.options[bookOption].value;
+	var parentSelect = bookSelect.form['edit-parent'];
+	parentSelect.options.length = 0;
+	switch (bookOptionValue) {
+".$init_option."
+		}
+	}
+// -->
+</script>";
+	drupal_set_html_head($jscript);
+	} 
 
 /**
  * Implementation of hook_node_info().
@@ -17,7 +136,7 @@
  * Implementation of hook_perm().
  */
 function book_perm() {
-    return array('outline posts in books', 'create book pages', 'create new books', 'edit book pages', 'edit own book pages', 'see printer-friendly version');
+    return array('outline posts in books', 'create book pages', 'create new books', 'edit book pages', 'edit own book pages', 'see printer-friendly version', 'adjust page weights');
 }
 
 /**
@@ -231,104 +350,236 @@
 }
 
 /**
- * Implementation of hook_form().
+ * Helper function for javascript form elements().
  */
-function book_form(&$node) {
-  if ($node->nid && !$node->parent && !user_access('create new books')) {
-    $form['parent'] = array('#type' => 'value', '#value' => $node->parent);
-  }
-  else {
-    $form['parent'] = array('#type' => 'select',
-      '#title' => t('Parent'),
-      '#default_value' => ($node->parent ? $node->parent : arg(4)),
-      '#options' => book_toc($node->nid),
-      '#weight' => -4,
-      '#description' => user_access('create new books') ? t('The parent section in which to place this page.  Note that each page whose parent is &lt;top-level&gt; is an independent, top-level book.') : t('The parent that this page belongs in.'),
-    );
-  }
-
-  $form['title'] = array('#type' => 'textfield',
-    '#title' => t('Title'),
-    '#required' => TRUE,
-    '#default_value' => $node->title,
-    '#weight' => -5,
-  );
-  $form['body_filter']['body'] = array('#type' => 'textarea',
-    '#title' => t('Body'),
-    '#default_value' => $node->body,
-    '#rows' => 20,
-    '#required' => TRUE,
-  );
-  $form['body_filter']['format'] = filter_form($node->format);
-
-  $form['log'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Log message'),
-    '#default_value' => $node->log,
-    '#weight' => 5,
-    '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
-  );
-
-  if (user_access('administer nodes')) {
-    $form['weight'] = array('#type' => 'weight',
-      '#title' => t('Weight'),
-      '#default_value' => $node->weight,
-      '#delta' => 15,
-      '#weight' => 5,
-      '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
-    );
-  }
-  else {
-    // If a regular user updates a book page, we create a new revision
-    // authored by that user:
-    $form['revision'] = array('#type' => 'hidden', '#value' => 1);
-  }
+function theme_book_script_form(&$form){
+  $output = "<script type=\"text/javascript\" language=\"javascript\">\n";
+  $output .= "document.write('<fieldset class=\" collapsible\"><legend>".t('Page hierarchy')."</legend>";
+  $output .= str_replace("\n","",form_render($form));
+  $output .= "</fieldset>');";
+  $output .= "\n</script>\n";
+  return $output;
+}
 
-  return $form;
+/**
+ * Implementation of hook_footer().
+ */
+function book_footer($main = 0){
+	$book_select_init_parent = "<script type=\"text/javascript\" language=\"javascript\">\n";	
+	$book_select_init_parent .= "if (isJsEnabled()) {\n";
+	$book_select_init_parent .= "addLoadEvent(setParentSelect(document.getElementById('edit-book')));\n";
+	$book_select_init_parent .= "}\n";
+	$book_select_init_parent .= "</script>\n";
+	return $book_select_init_parent;
 }
 
 /**
+ * Implementation of hook_form().
+ */
+function book_form(&$node) {
+	if ($node->nid && !$node->parent && !user_access('create new books')) {
+		$form['parent'] = array('#type' => 'value', '#value' => $node->parent);
+		} else {
+		$book_list = book_booklist_query();
+		$top_level_book_list = book_top_level_booklist();
+		$top_level_book = $node->parent > 0 ? book_top_level_book($node->parent) : (arg(4) ? book_top_level_book(arg(4)) : $node->nid);
+		$default_parent = $node->parent ? $node->parent : arg(4);	
+		book_insert_bookjs($book_list, $top_level_book_list, $default_parent);
+		
+		//if javascript is turned on, display interactive form
+		//render fieldset group via theme_book_script_form
+		$form['script_wrapper'] = array(
+			'#type' => 'markup',
+			'#weight' => -4,	  
+			'#theme' => book_script_form,
+			);	
+		$form['script_wrapper']['book'] = array(
+			'#type' => 'select',
+			'#title' => t('Book'),	  
+			'#default_value' => $top_level_book,
+			'#options' => $top_level_book_list,
+			'#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The top level book of this page. Weights are shown following the semi-colon.') : t('The top level book of this page.'),
+			'#attributes' => array('onchange' => 'setParentSelect(this);'),
+			);	
+		$form['script_wrapper']['parent'] = array(
+			'#type' => 'select',
+			'#title' => t('Parent'),	  
+			'#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The parent of this page. Weights are shown following the semi-colon.') : t('The parent that this page belongs in.'),
+			);
+			
+		//if javascript is turned off, then default to original
+		$form['noscript_wrapper'] = array(
+			'#type' => 'fieldset',
+			'#prefix' => "<noscript>\n",
+			'#title' => t('Page hierarchy'),
+			'#collapsible' => TRUE,
+			'#collapsed' => FALSE,
+			'#suffix' => "</noscript>\n",	  
+			'#weight' => -4,	  
+			);	
+		$form['noscript_wrapper']['parent'] = array('#type' => 'select',
+			'#title' => t('Parent'),	  
+			'#default_value' => ($node->parent ? $node->parent : arg(4)),
+			'#options' => book_toc($node->nid),
+			'#description' => user_access('create new books') ? t('The parent section in which to place this page.  Note that each page whose parent is &lt;top-level&gt; is an independent, top-level book.') : t('The parent that this page belongs in.'),
+			);
+		}
+	
+	$form['title'] = array('#type' => 'textfield',
+		'#title' => t('Title'),
+		'#required' => TRUE,
+		'#default_value' => $node->title,
+		'#weight' => -5,
+		);
+	$form['body_filter']['body'] = array('#type' => 'textarea',
+		'#title' => t('Body'),
+		'#default_value' => $node->body,
+		'#rows' => 20,
+		'#required' => TRUE,
+		);
+	$form['body_filter']['format'] = filter_form($node->format);
+	
+	$form['log_wrapper'] = array(
+		'#type' => 'fieldset',
+		'#title' => t('Log message'),
+		'#collapsible' => TRUE,
+		'#collapsed' => FALSE,
+		'#weight' => 5,	
+		);		
+	$form['log_wrapper']['log'] = array(
+		'#type' => 'textarea',
+		'#title' => t('Document history'),
+		'#default_value' => $node->log,
+		'#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
+		);
+	
+	if (user_access('administer nodes') || user_access('adjust page weights')) {
+		$form['weight_wrapper'] = array(
+			'#type' => 'fieldset',
+			'#title' => t('Page ordering'),
+			'#collapsible' => TRUE,
+			'#collapsed' => TRUE,
+			'#weight' => 4,	  
+			);	  
+		$form['weight_wrapper']['weight'] = array('#type' => 'weight',
+			'#title' => t('Weight'),
+			'#default_value' => $node->weight,
+			'#delta' => 15,
+			'#description' => t('Pages at a given level are ordered first by weight and then by title.'),
+			);
+		} else {
+		// If a regular user updates a book page, we create a new revision
+		// authored by that user:
+		$form['revision'] = array('#type' => 'hidden', '#value' => 1);
+		}
+	
+	return $form;
+	}
+
+/**
  * Implementation of function book_outline()
  * Handles all book outline operations.
  */
 function book_outline($nid) {
-  $node = node_load($nid);
-  $page = book_load($node);
-
-  $form['parent'] = array('#type' => 'select',
-    '#title' => t('Parent'),
-    '#default_value' => $page->parent,
-    '#options' => book_toc($node->nid),
-    '#description' => t('The parent page in the book.'),
-  );
-  $form['weight'] = array('#type' => 'weight',
-    '#title' => t('Weight'),
-    '#default_value' => $page->weight,
-    '#delta' => 15,
-    '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
-  );
-  $form['log'] = array('#type' => 'textarea',
-    '#title' => t('Log message'),
-    '#default_value' => $node->log,
-    '#description' => t('An explanation to help other authors understand your motivations to put this post into the book.'),
-  );
-
-  $form['nid'] = array('#type' => 'value', '#value' => $nid);
-  if ($page->nid) {
-    $form['update'] = array('#type' => 'submit',
-      '#value' => t('Update book outline'),
-    );
-    $form['remove'] = array('#type' => 'submit',
-      '#value' => t('Remove from book outline'),
-    );
-  }
-  else {
-    $form['add'] = array('#type' => 'submit', '#value' => t('Add to book outline'));
-  }
-
-  drupal_set_title(check_plain($node->title));
-  return drupal_get_form('book_outline', $form);
-}
+	$node = node_load($nid);
+	$page = book_load($node);
+	$book_list = book_booklist_query();
+	$top_level_book_list = book_top_level_booklist();
+	$top_level_book = $page->parent > 0 ? book_top_level_book($page->parent) : (arg(4) ? book_top_level_book(arg(4)) : $page->nid);
+	$default_parent = $page->parent ? $page->parent : arg(4);	
+	book_insert_bookjs($book_list, $top_level_book_list, $default_parent);
+	
+	//if javascript is turned on, display interactive form
+	//render fieldset group via theme_book_script_form
+	$form['script_wrapper'] = array(
+		'#type' => 'markup',
+		'#weight' => -4,	  
+		'#theme' => book_script_form,
+		);	
+    $form['script_wrapper']['book'] = array(
+		'#type' => 'select',
+		'#title' => t('Book'),	  
+		'#default_value' => $top_level_book,
+		'#options' => $top_level_book_list,
+		'#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The top level book of this page. Weights are shown following the semi-colon.') : t('The top level book of this page.'),
+		'#attributes' => array('onchange' => 'setParentSelect(this);'),
+		);	
+	$form['script_wrapper']['parent'] = array(
+		'#type' => 'select',
+		'#title' => t('Parent'),	  
+		'#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The parent section in which to place this page. Weights are shown following the semi-colon.') : t('The parent section in which to place this page.'),
+		);
+		
+	//if javascript is turned off, then default to original
+	$form['noscript_wrapper'] = array(
+		'#type' => 'fieldset',
+		'#prefix' => "<noscript>\n",
+		'#title' => t('Page hierarchy'),
+		'#collapsible' => TRUE,
+		'#collapsed' => FALSE,
+		'#suffix' => "</noscript>\n",	  
+		'#weight' => -4,	  
+		);	
+	$form['noscript_wrapper']['parent'] = array('#type' => 'select',
+		'#title' => t('Parent'),	  
+		'#default_value' => $page->parent,
+		'#options' => book_toc($node->nid),
+		'#description' => user_access('create new books') ? t('The parent section in which to place this page.  Note that each page whose parent is &lt;top-level&gt; is an independent, top-level book.') : t('The parent that this page belongs in.'),
+		);  
+		
+	$form['log_wrapper'] = array(
+		'#type' => 'fieldset',
+		'#title' => t('Log message'),
+		'#collapsible' => TRUE,
+		'#collapsed' => FALSE,
+		'#weight' => 5,		
+		);		
+	$form['log_wrapper']['log'] = array(
+		'#type' => 'textarea',
+		'#title' => t('Document history'),
+		'#default_value' => $node->log,
+		'#description' => t('An explanation to help other authors understand your motivations to put this post into the book.'),
+		);
+		
+	if (user_access('administer nodes') || user_access('adjust page weights')) {
+		$form['weight_wrapper'] = array(
+			'#type' => 'fieldset',
+			'#title' => t('Page ordering'),
+			'#collapsible' => TRUE,
+			'#collapsed' => FALSE,  
+			'#weight' => 4,			
+			);	  
+		$form['weight_wrapper']['weight'] = array('#type' => 'weight',
+			'#title' => t('Weight'),
+			'#default_value' => $page->weight,
+			'#delta' => 15,
+			'#description' => t('Pages at a given level are ordered first by weight and then by title.'),
+			);
+		}
+		
+	$form['nid'] = array('#type' => 'value', '#value' => $nid);
+	if ($page->nid) {
+		$form['update'] = array(
+			'#type' => 'submit',
+			'#value' => t('Update book outline'),
+			'#weight' => 6,	
+			);
+		$form['remove'] = array(
+			'#type' => 'submit',
+			'#value' => t('Remove from book outline'),
+			'#weight' => 6,				
+			);
+		} else {
+		$form['add'] = array(
+			'#type' => 'submit', 
+			'#value' => t('Add to book outline'),
+			'#weight' => 6,				
+			);
+		}
+	
+	drupal_set_title(check_plain($node->title));
+	return drupal_get_form('book_outline', $form);
+	}
 
 /**
  * Handles book outline form submissions.
@@ -547,7 +798,7 @@
   if ($children[$nid]) {
     foreach ($children[$nid] as $foo => $node) {
       if (!$exclude || $exclude != $node->nid) {
-        $toc[$node->nid] = $indent .' '. $node->title;
+   		$toc[$node->nid] = $indent .' '. $node->title . (user_access('administer nodes') || user_access('adjust page weights') ? ' : '. $node->weight : '');
         $toc = book_toc_recurse($node->nid, $indent .'--', $toc, $children, $exclude);
       }
     }
@@ -1034,6 +1285,4 @@
   if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'outline') {
     return t('The outline feature allows you to include posts in the <a href="%book">book hierarchy</a>.', array('%book' => url('book')));
   }
-}
-
-
+}
