From 55d5a98fdc11586fef7c3cb5c58ce2e5e778afa6 Mon Sep 17 00:00:00 2001
From: Matthew Grasmick <matthew.grasmick@acquia.com>
Date: Mon, 2 Feb 2015 17:12:02 -0500
Subject: [PATCH] Issue #2416135 by grasmash: Provide separate tab for node
 scheduling

---
 scheduler.admin.inc |  3 ++-
 scheduler.edit.inc  | 57 ++++++++++++++++++++++++++++++++++++++++
 scheduler.module    | 76 ++++++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 120 insertions(+), 16 deletions(-)

diff --git a/scheduler.admin.inc b/scheduler.admin.inc
index 839fb8e..6bbb33b 100644
--- a/scheduler.admin.inc
+++ b/scheduler.admin.inc
@@ -361,8 +361,9 @@ function _scheduler_form_node_type_form_alter(&$form, $form_state) {
     '#title' => t('Display scheduling options as'),
     '#default_value' => variable_get('scheduler_use_vertical_tabs_' . $form['#node_type']->type, 1),
     '#options' => array(
-      '1' => t('Vertical tab'),
       '0' => t('Separate fieldset'),
+      '1' => t('Vertical tab'),
+      '2' => t('Separate tab'),
     ),
     '#description' => t('Use this option to specify how the scheduling options will be displayed when editing a node.'),
   );
diff --git a/scheduler.edit.inc b/scheduler.edit.inc
index ebff0d1..c049dbf 100644
--- a/scheduler.edit.inc
+++ b/scheduler.edit.inc
@@ -175,6 +175,63 @@ function _scheduler_form_alter(&$form, $form_state) {
 }
 
 /**
+ * Page callback for node schedule tab.
+ */
+function scheduler_node_tab($node) {
+  if (user_access('schedule (un)publishing of nodes')) {
+    // Check if scheduling has been enabled for this node type.
+    $publishing_enabled = variable_get('scheduler_publish_enable_' . $node->type, 0) == 1;
+    $unpublishing_enabled = variable_get('scheduler_unpublish_enable_' . $node->type, 0) == 1;
+    if ($publishing_enabled || $unpublishing_enabled) {
+      drupal_set_title(t('Schedule %title', array('%title' => $node->title)), PASS_THROUGH);
+
+      $form = drupal_get_form('scheduler_node_form', $node);
+      return $form;
+    }
+  }
+}
+
+/**
+ * Builds independent scheduler form for a specific node.
+ */
+function scheduler_node_form($form, $form_state, $node) {
+  $form['#node'] = $node;
+  $form['type']['#value'] = $node->type;
+  _scheduler_form_alter($form, $form_state);
+
+  $form['scheduler_settings']['#collapsed'] = FALSE;
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save schedule'),
+    '#weight' => 100,
+  );
+
+  return $form;
+}
+
+/**
+ * Validate handler for scheduler_node_form.
+ */
+function scheduler_node_form_validate($form, $form_state) {
+  $node = $form['#node'];
+  scheduler_node_validate($node, $form, $form_state);
+}
+
+/**
+ * Submit handler for scheduler_node_form.
+ */
+function scheduler_node_form_submit($form, $form_state) {
+  $values = $form_state['values'];
+  $node = $form['#node'];
+  $node->publish_on = $values['publish_on'];
+  $node->unpublish_on = $values['unpublish_on'];
+
+  scheduler_node_presave($node);
+  scheduler_update_node_schedule($node);
+}
+
+/**
  * Callback function for the Scheduler date entry elements.
  */
 function scheduler_date_value_callback(&$element, $input = FALSE, &$form_state) {
diff --git a/scheduler.module b/scheduler.module
index 2f60371..0c03ead 100644
--- a/scheduler.module
+++ b/scheduler.module
@@ -134,10 +134,30 @@ function scheduler_menu() {
     'type' => MENU_LOCAL_TASK,
     'file' => 'scheduler.admin.inc',
   );
+  $items['node/%node/scheduler'] = array(
+    'title' => 'Schedule',
+    'page callback' => 'scheduler_node_tab',
+    'page arguments' => array(1),
+    'access callback' => 'scheduler_node_tab_access',
+    'access arguments' => array(1),
+    'description' => 'Displays scheduling information for a node',
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'scheduler.edit.inc',
+  );
   return $items;
 }
 
 /**
+ * Implements hook_admin_paths().
+ */
+function scheduler_admin_paths() {
+  $paths = array(
+    'node/*/scheduler' => TRUE,
+  );
+  return $paths;
+}
+
+/**
  * Return the users access to the scheduler list page.
  *
  * Separate function required because of the two access values to be checked.
@@ -156,6 +176,21 @@ function scheduler_list_access_callback($uid = NULL) {
 }
 
 /**
+ * Returns the users access to the scheduler node tab.
+ *
+ * @param object $node
+ *   The node for which access is checked.
+ *
+ * @return bool
+ *   TRUE if the user has access, otherwise FALSE.
+ */
+function scheduler_node_tab_access($node) {
+  $display_tab = (int) variable_get('scheduler_use_vertical_tabs_' . $node->type, 1) == 2;
+
+  return $display_tab && user_access('schedule (un)publishing of nodes') && node_access('update', $node);
+}
+
+/**
  * Implements hook_help().
  */
 function scheduler_help($section) {
@@ -218,7 +253,8 @@ function scheduler_form_alter(&$form, $form_state) {
     // Check if scheduling has been enabled for this node type.
     $publishing_enabled = variable_get('scheduler_publish_enable_' . $form['type']['#value'], 0) == 1;
     $unpublishing_enabled = variable_get('scheduler_unpublish_enable_' . $form['type']['#value'], 0) == 1;
-    if ($publishing_enabled || $unpublishing_enabled) {
+    $alter_form = variable_get('scheduler_use_vertical_tabs_' . $form['type']['#value'], 1) != 2;
+    if ($alter_form && ($publishing_enabled || $unpublishing_enabled)) {
       module_load_include('inc', 'scheduler', 'scheduler.edit');
       _scheduler_form_alter($form, $form_state);
     }
@@ -609,20 +645,7 @@ function scheduler_node_update($node) {
   // otherwise the user probably cleared out the (un)publish dates so we should
   // remove the record.
   if (!empty($node->publish_on) || !empty($node->unpublish_on)) {
-    db_merge('scheduler')->key(array('nid' => $node->nid))->fields(array(
-      'publish_on' => $node->publish_on,
-      'unpublish_on' => $node->unpublish_on,
-    ))->execute();
-
-    // Invoke the events to indicate that an existing node has been scheduled.
-    if (module_exists('rules')) {
-      if (!empty($node->publish_on)) {
-        rules_invoke_event('scheduler_existing_node_is_scheduled_for_publishing_event', $node, $node->publish_on, $node->unpublish_on);
-      }
-      if (!empty($node->unpublish_on)) {
-        rules_invoke_event('scheduler_existing_node_is_scheduled_for_unpublishing_event', $node, $node->publish_on, $node->unpublish_on);
-      }
-    }
+    scheduler_update_node_schedule($node);
   }
   else {
     scheduler_node_delete($node);
@@ -630,6 +653,29 @@ function scheduler_node_update($node) {
 }
 
 /**
+ * Updates the schedule for a specific node.
+ *
+ * @param object $node
+ *   The node for which the schedule should be updated.
+ */
+function scheduler_update_node_schedule($node) {
+  db_merge('scheduler')->key(array('nid' => $node->nid))->fields(array(
+    'publish_on' => $node->publish_on,
+    'unpublish_on' => $node->unpublish_on,
+  ))->execute();
+
+  // Invoke the events to indicate that an existing node has been scheduled.
+  if (module_exists('rules')) {
+    if (!empty($node->publish_on)) {
+      rules_invoke_event('scheduler_existing_node_is_scheduled_for_publishing_event', $node, $node->publish_on, $node->unpublish_on);
+    }
+    if (!empty($node->unpublish_on)) {
+      rules_invoke_event('scheduler_existing_node_is_scheduled_for_unpublishing_event', $node, $node->publish_on, $node->unpublish_on);
+    }
+  }
+}
+
+/**
  * Implements hook_node_delete().
  */
 function scheduler_node_delete($node) {
-- 
2.2.1

