Index: skeleton_sync.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/skeleton/skeleton_sync.inc,v
retrieving revision 1.1
diff -u -r1.1 skeleton_sync.inc
--- skeleton_sync.inc	12 Mar 2009 18:22:29 -0000	1.1
+++ skeleton_sync.inc	1 Apr 2009 01:57:08 -0000
@@ -3,14 +3,34 @@
 /**
  * Syncronize form. Contains lists of updated, added, and deleted templates.
  *
+ * @return
+ *   The rendered HTML of the page.
+ */
+function skeleton_sync_page() {
+  $output .= drupal_get_form('skeleton_sync_content_form');
+  // TODO: Show a seperate list for new templates added to a skeleton.
+  $output .= drupal_get_form('skeleton_sync_template_form');
+
+  // TODO: Show a seperate list for templates removed from a skeleton.
+  return $output;
+}
+
+/**
+ * Syncronize content form.
+ *
  * @param $form_state
  *   The state of the form.
  * @return
  *   The form array.
  */
-function skeleton_sync_form($form_state) {
+function skeleton_sync_content_form($form_state) {
   $form = array();
-  $form['help'] = array(
+  $form['content'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Syncronize template content'),
+    '#collapsible' => TRUE,
+  );
+  $form['content']['help'] = array(
     '#prefix' => '<p>',
     '#suffix' => '</p>',
     '#value' => t('Use this form to syncronize changed templates with pages which have all ready been created.'),
@@ -25,33 +45,30 @@
     $updated[$node->nid] = t('<a href="@node-url">%title</a>, in the <a href="@book-url">%book-title</a> book, created from the <a href="@template-url">%template</a> template.', array('@node-url' => url('node/' . $node->nid), '%title' => $node->title, '@book-url' => url('node/' . $book->nid), '%book-title' => $book->title, '%template' => $eligble_node->template, '@template-url' => url('admin/content/skeleton/template/' . $eligble_node->template_id . '/view')));
   }
   if (!empty($updated)) {
-    $form['nodes'] = array(
+    $form['content']['#collapsed'] = FALSE;
+    $form['content']['nodes'] = array(
       '#type' => 'checkboxes',
       '#title' => t('Select the nodes you wish to update'),
       '#options' => $updated,
     );
-    $form['submit'] = array(
+    $form['content']['submit'] = array(
       '#type' => 'submit',
       '#value' => t('Synchronize'),
     );
   }
   else {
-    $form['no_nodes'] = array(
+    $form['content']['#collapsed'] = TRUE;
+    $form['content']['no_nodes'] = array(
       '#prefix' => '<p>',
       '#suffix' => '</p>',
-      '#value' => t('There are no nodes eligible for synchronizing.')
+      '#value' => t('There are no nodes eligible for content synchronizing.')
     );
   }
-
-  // TODO: Show a seperate list for new templates added to a skeleton.
-
-  // TODO: Show a seperate list for templates removed from a skeleton.
-
   return $form;
 }
 
 /**
- * Submit handler for the syncronize form.
+ * Submit handler for the syncronize content form.
  *
  * @param $form
  *   The form being submitted.
@@ -59,7 +76,7 @@
  * @param $form_state
  *   The state of the form.
  */
-function skeleton_sync_form_submit($form, $form_state) {
+function skeleton_sync_content_form_submit($form, $form_state) {
   $batch = array(
     'title' => t('Updating content'),
     'init_message' => t('Content updating is starting.'),
@@ -74,6 +91,119 @@
 }
 
 /**
+ * Form for pushing out new templates to existing skeletons.
+ */
+function skeleton_sync_template_form($form_state) {
+  $form = array();
+  $form['templates'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Syncronize templates'),
+    '#collapsible' => TRUE,
+  );
+  // Find all copies of instantiated skeletons which do not contain a template.
+  $skeleton_result = db_query("SELECT DISTINCT skeleton_id FROM {skeleton_template_node}");
+  while ($skeleton_id = db_result($skeleton_result)) {
+    $templates = array();
+    $updated = array();
+    $skeleton = skeleton_load($skeleton_id);
+    $form['templates']['skeletons'] = array(
+      '#tree' => TRUE,
+    );
+    $form['templates']['skeletons'][$skeleton_id] = array();
+    $template_result = db_query("SELECT DISTINCT template_id FROM {skeleton_template_node} WHERE skeleton_id = %d", $skeleton_id);
+    while ($template_id = db_result($template_result)) {
+      $templates[] = $template_id;
+    }
+    $updated_result = db_query("SELECT template_id FROM {skeleton_data} WHERE skeleton_id = %d AND template_id NOT IN (" . implode(',', $templates) . ")", $skeleton_id);
+    while ($updated_id = db_result($updated_result)) {
+      $template = skeleton_template_load($updated_id);
+      $updated[$updated_id] = l($template->template, 'admin/content/skeleton/template/' . $template->template_id . '/view');
+    }
+    if (!empty($updated)) {
+      $form['templates']['skeletons'][$skeleton_id] = array(
+        '#type' => 'checkboxes',
+        '#title' => t('Create new pages from new templates assigned to <a href="@skeleton-url">%skeleton</a>', array('@skeleton-url' => url('admin/content/skeleton/skeleton/' . $skeleton->skeleton_id . '/edit'), '%skeleton' => $skeleton->skeleton)),
+        '#options' => $updated,
+      );
+      $form['templates']['submit'] = array(
+        '#type' => 'submit', 
+        '#value' => t('Syncronize'),
+      );
+    }
+    else {
+      $form['templates']['#collapsed'] = TRUE;
+      $form['templates']['no_templates'] = array(
+        '#prefix' => '<p>',
+        '#suffix' => '</p>',
+        '#value' => t('There are no templates eligible for content synchronizing.')
+      );
+    }
+  }
+  return $form;
+}
+
+/**
+ * Submit handler for pushing out new templates to existing books.
+ */
+function skeleton_sync_template_form_submit($form, &$form_state) {
+  module_load_include('inc', 'node', 'node.pages');
+  module_load_include('inc', 'skeleton', 'skeleton_token');
+  foreach($form_state['values']['skeletons'] as $skeleton_id => $templates) {
+    $templates = array_filter($templates);
+    foreach($templates as $template_id) {
+      // Find the template parent of this template
+      // $template = skeleton_template_load($template_id);
+      // If the parent is 0, we place it under the top-most book node.
+      // Otherwise, place it under the parent template in the book.
+      $parent = db_result(db_query("SELECT parent FROM {skeleton_data} WHERE skeleton_id = %d AND template_id = %d", $skeleton_id, $template_id));
+      if ($parent == 0) {
+        // TODO!
+      }
+      else {
+        $parent_nids_result = db_query("SELECT nid, tokens FROM {skeleton_template_node} WHERE skeleton_id = %d AND template_id = %d", $skeleton_id, $parent);
+        while($parent_info = db_fetch_object($parent_nids_result)) {
+          $parent_info->tokens = unserialize($parent_info->tokens);
+          $data = db_result(db_query("SELECT node_data FROM {skeleton_template} WHERE template_id = %d", $template_id));
+          $node = array();
+          $node['values'] = unserialize($data);
+          $parent_node = node_load($parent_info->nid);
+          $node['values']['book'] = array();
+          $node['values']['book']['bid'] = $parent_node->book['bid'];
+          $node['values']['book']['plid'] = $parent_node->book['mlid'];
+          $node['values']['book']['options'] = array();
+    
+          // Replace custom tokens in the title and body fields. Replace skeleton
+          // tokens first so they may be used as node tokens such as [title].
+          if (!empty($parent_info->tokens)) {
+            $node['values']['title'] = token_replace($node['values']['title'], 'skeleton', $parent_info->tokens);
+            $node['values']['body'] = token_replace($node['values']['body'], 'skeleton', $parent_info->tokens);
+          }
+    
+          $node['values']['title'] = token_replace($node['values']['title'], 'node', (object)$node['values']);
+          $node['values']['body'] = token_replace($node['values']['body'], 'node', (object)$node['values']);
+    
+          $node['values']['uid'] = $parent_node->uid;
+          $node['values']['name'] = $parent_node->name;
+    
+          $node['values']['tokens'] = $parent_info->tokens;
+   
+          // We have to add the skeleton ID here as we can't save it with the
+          // template as a template may have multiple skeletons.
+          $node['values']['skeleton_id'] = $skeleton_id;
+    
+          $node['values']['op'] = t('Save');
+          drupal_execute($node['values']['type'] .'_node_form', $node, (object)$node['values']);
+          // TODO: This will probably need to be removed if this call is integrated
+          // into the book module. See http://drupal.org/node/364529 for details.
+          menu_rebuild();
+          $form_state['nids'][] = $node['nid'];
+        }
+      }
+    }
+  }
+}
+
+/**
  * Update an instantiated node based on an updated template.
  *
  * @param $nid
@@ -114,4 +244,4 @@
   node_save($node);
   db_query("UPDATE {skeleton_template_node} SET template_status = 'synced' WHERE nid = %d", $node->nid);
   $context['results'][] = t('Updated %title', array('%title' => $node->title));
-}
\ No newline at end of file
+}
Index: skeleton.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/skeleton/skeleton.module,v
retrieving revision 1.18
diff -u -r1.18 skeleton.module
--- skeleton.module	12 Mar 2009 18:27:26 -0000	1.18
+++ skeleton.module	1 Apr 2009 01:57:08 -0000
@@ -71,8 +71,7 @@
     'file' => 'skeleton_admin.inc',
   );
   $items['admin/content/skeleton/sync'] = array(
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('skeleton_sync_form'),
+    'page callback' => 'skeleton_sync_page',
     'access arguments' => array('configure skeleton outlines'),
     'type' => MENU_LOCAL_TASK,
     'title' => 'Synchronize',
@@ -333,7 +332,7 @@
 function skeleton_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   switch ($op) {
     case 'load':
-      if ($template = db_fetch_object(db_query("SELECT skeleton_id, template_id, tokens FROM {skeleton_template_node} WHERE nid = %d", $node->nid))) {
+      if ($template = db_fetch_object(db_query("SELECT skeleton_id, template_id, tokens FROM {skeleton_template_node} WHERE nid = %d AND template_status != 'overridden'", $node->nid))) {
         $node->skeleton_template = new stdClass();
         $node->skeleton_template->skeleton_id = $template->skeleton_id;
         $node->skeleton_template->template_id = $template->template_id;
@@ -351,11 +350,13 @@
       }
       break;
     case 'update':
-    case 'delete':
       if (!$node->skeleton_template->keep_connected) {
-        db_query("DELETE FROM {skeleton_template_node} WHERE nid = %d", $node->nid);
+        db_query("UPDATE {skeleton_template_node} SET template_status = '%s' WHERE nid = %d", 'overridden', $node->nid);
       }
       break;
+    case 'delete':
+      db_query("DELETE FROM {skeleton_template_node} WHERE nid = %d", $node->nid);
+      break;
   }
 }
 
@@ -376,13 +377,14 @@
     module_load_include('inc', 'skeleton', 'skeleton_template');
     skeleton_alter_node_form($form, $form_state, $form_id);
   }
-  else if ($form_node == $form_id && arg(0) == 'admin' && arg(2) == 'skeleton' && arg(3) == 'skeleton' && arg(5) == 'create') {
+  else if ($form_node == $form_id && (arg(0) == 'admin' && arg(2) == 'skeleton' && arg(3) == 'skeleton' && arg(5) == 'create')
+    || (arg(0) == 'admin' && arg(2) == 'skeleton' && arg(3) == 'sync')) {
     // We need skeleton_id to be defined so forms validate properly. This value
     // should always be provided by the function instantiating the skeleton.
     $form['skeleton_id'] = array('#type' => 'hidden', '#value' => $form_state['values']['skeleton_id']);
     $form['template_id'] = array('#type' => 'hidden', '#value' => $form_state['values']['template_id']);
     $form['tokens'] = array('#type' => 'hidden', '#value' => $form_state['values']['tokens']);
-  }  
+  }
 }
 
 /**
@@ -396,7 +398,7 @@
  *   FALSE otherwise. 
  */
 function _skeleton_template_connected($node) {
-  return user_access('configure skeleton outlines') && db_result(db_query("SELECT COUNT(1) FROM {skeleton_template_node} WHERE nid = %d", $node->nid));
+  return user_access('configure skeleton outlines') && db_result(db_query("SELECT COUNT(1) FROM {skeleton_template_node} WHERE nid = %d AND template_status != 'overridden'", $node->nid));
 }
 
 /**
