From 7ea1271bd3d4f6e48e5e1628b897a62729448994 Mon Sep 17 00:00:00 2001
From: Earl Miles <merlin@logrus.com>
Date: Mon, 12 Jan 2009 22:03:28 +0000
Subject: [PATCH] Add node edit override functionality.

---
 delegator/plugins/tasks/node_edit.inc | 114 ++++++++++++++++++++++++++
 includes/form.inc                     |  11 ++-
 plugins/arguments/node_edit.inc       |  11 +--
 plugins/contexts/node_edit_form.inc   |  20 ++---
 4 files changed, 137 insertions(+), 19 deletions(-)
 create mode 100644 delegator/plugins/tasks/node_edit.inc

diff --git a/delegator/plugins/tasks/node_edit.inc b/delegator/plugins/tasks/node_edit.inc
new file mode 100644
index 00000000..320bfb8b
--- /dev/null
+++ b/delegator/plugins/tasks/node_edit.inc
@@ -0,0 +1,114 @@
+<?php
+// $Id$
+
+/**
+ * Specialized implementation of hook_delegator_tasks(). See api-task.html for
+ * more information.
+ */
+function delegator_node_edit_delegator_tasks() {
+  return array(
+    'node_edit' => array(
+      // This is a 'page' task and will fall under the page admin UI
+      'task type' => 'page',
+
+      'title' => t('Node view'),
+      'description' => t('The node edit task allows you to control what handler will handle the job of editing a node at the path <em>node/%node/edit</em>. If no handler is set or matches the criteria, the default Drupal node renderer will be used.'),
+
+      'admin title' => 'Node edit', // translated by menu system
+      'admin description' => 'Overrides for the built in node edit handler at <em>node/%node/edit</em>.',
+      'admin path' => 'node/%node/edit',
+
+      // Menu hooks so that we can alter the node/%node menu entry to point to us.
+      'hook menu' => 'delegator_node_edit_menu',
+      'hook menu alter' => 'delegator_node_edit_menu_alter',
+
+      // This is task uses 'context' handlers and must implement these to give the
+      // handler data it needs.
+      'handler type' => 'context', // handler type -- misnamed
+      'get arguments' => 'delegator_node_edit_get_arguments',
+      'get context placeholders' => 'delegator_node_edit_get_contexts',
+    ),
+  );
+}
+
+/**
+ * Callback defined by delegator_node_edit_delegator_tasks().
+ *
+ * Alter the node view input so that node view comes to us rather than the
+ * normal node view process.
+ */
+function delegator_node_edit_menu_alter(&$items, $task) {
+  // Override the node view handler for our purpose.
+  $items['node/%node/edit']['page callback'] = 'delegator_node_edit';
+  $items['node/%node/edit']['file path'] = $task['path'];
+  $items['node/%node/edit']['file'] = $task['file'];
+}
+
+/**
+ * Entry point for our overridden node view.
+ *
+ * This function asks its assigned handlers who, if anyone, would like
+ * to run with it. If no one does, it passes through to Drupal core's
+ * node view, which is node_page_view().
+ */
+function delegator_node_edit($node) {
+  // Load my task plugin
+  $task = delegator_get_task('node_edit');
+
+  // Load the node into a context.
+  ctools_include('context');
+  ctools_include('context-task-handler');
+  $contexts = ctools_context_handler_get_task_contexts($task, '', array($node));
+
+  // Load the landlers.
+  $handlers = delegator_load_sorted_handlers($task, '', TRUE);
+
+  // Try each handler.
+  foreach ($handlers as $handler) {
+    if ($function = delegator_get_renderer($handler)) {
+      $output = $function($handler, $contexts);
+      if ($output) {
+        // Since we're not using node_show() we need to emulate what it used to do.
+        // Update the history table, stating that this user viewed this node.
+        node_tag_new($node->nid);
+
+        // TRUE is a special return used to let us know that it handled the
+        // task but does not wish us to render anything, as it already did.
+        // This is needed for the 'no blocks' functionality.
+        if ($output === TRUE) {
+          return;
+        }
+        return $output;
+      }
+    }
+  }
+
+  // Fall back!
+  module_load_include('inc', 'node', 'node.pages');
+  return node_page_edit($node);
+}
+
+/**
+ * Callback to get arguments provided by this task handler.
+ *
+ * Since this is the node view and there is no UI on the arguments, we
+ * create dummy arguments that contain the needed data.
+ */
+function delegator_node_edit_get_arguments($task, $subtask_id) {
+  return array(
+    array(
+      'keyword' => 'node',
+      'identifier' => t('Node being edited'),
+      'id' => 0,
+      'name' => 'node_edit',
+      'settings' => array(),
+    ),
+  );
+}
+
+/**
+ * Callback to get context placeholders provided by this handler.
+ */
+function delegator_node_edit_get_contexts($task, $subtask_id) {
+  return ctools_context_get_placeholders_from_argument(delegator_node_edit_get_arguments($task, $subtask_id));
+}
diff --git a/includes/form.inc b/includes/form.inc
index 4ac55576..22d12d69 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -69,7 +69,8 @@ function ctools_build_form($form_id, &$form_state) {
       else {
         // Use a copy of the function's arguments for manipulation
         $args_temp = $args;
-        $args_temp[0] = &$form_state;
+        array_unshift($args_temp, 'placeholder');
+        $args_temp[0] = &$form_state; // replaces the placeholder.
         array_unshift($args_temp, $form_id);
 
         $form = call_user_func_array('drupal_retrieve_form', $args_temp);
@@ -131,6 +132,11 @@ function ctools_build_form($form_id, &$form_state) {
     $form = ctools_rebuild_form($form_id, $form_state, $args);
   }
 
+  // If whoever is calling this wants the $form array (so that it can render it
+  // another way, for example) then return it.
+  if (!empty($form_state['want form'])) {
+    return $form;
+  }
   // If we haven't redirected to a new location by now, we want to
   // render whatever form array is currently in hand.
   return drupal_render_form($form_id, $form);
@@ -145,7 +151,8 @@ function ctools_rebuild_form($form_id, &$form_state, $args, $form_build_id = NUL
   // Remove the first argument. This is $form_id.when called from
   // drupal_get_form and the original $form_state when called from some AHAH
   // callback. Neither is needed. After that, put in the current state.
-  $args[0] = &$form_state;
+  array_unshift($args, 'placeholder');
+  $args[0] = &$form_state; // Replaces placeholder.
   // And the form_id.
   array_unshift($args, $form_id);
   $form = call_user_func_array('drupal_retrieve_form', $args);
diff --git a/plugins/arguments/node_edit.inc b/plugins/arguments/node_edit.inc
index dff82b32..ece6c26c 100644
--- a/plugins/arguments/node_edit.inc
+++ b/plugins/arguments/node_edit.inc
@@ -30,8 +30,13 @@ function ctools_node_edit_context($arg = NULL, $conf = NULL, $empty = FALSE) {
     return ctools_context_create_empty('node_edit_form');
   }
 
+  // We can accept either a node object or a pure nid.
+  if (is_object($arg)) {
+    return ctools_context_create('node_edit_form', $arg);
+  }
+
   if (!is_numeric($arg)) {
-    return NULL;
+    return FALSE;
   }
 
   $node = node_load($arg);
@@ -39,10 +44,6 @@ function ctools_node_edit_context($arg = NULL, $conf = NULL, $empty = FALSE) {
     return NULL;
   }
 
-  if (array_filter($conf['types']) && empty($conf['types'][$node->type])) {
-    return NULL;
-  }
-
   // This will perform a node_access check, so we don't have to.
   return ctools_context_create('node_edit_form', $node);
 }
diff --git a/plugins/contexts/node_edit_form.inc b/plugins/contexts/node_edit_form.inc
index 37ec9317..995d2f33 100644
--- a/plugins/contexts/node_edit_form.inc
+++ b/plugins/contexts/node_edit_form.inc
@@ -41,25 +41,21 @@ function ctools_context_create_node_edit_form($empty, $node = NULL, $conf = FALS
   }
 
   if (!empty($node) && node_access('update', $node)) {
-    // This is from node_edit_page cause Drupal still doesn't use fapi right.
-    if ($_POST['op'] == t('Delete')) {
-      // Note: we redirect from node/nid/edit to node/nid/delete to make the tabs disappear.
-      if ($_REQUEST['destination']) {
-        $destination = drupal_get_destination();
-        unset($_REQUEST['destination']);
-      }
-      drupal_goto('node/'. $node->nid .'/delete', $destination);
-    }
+    module_load_include('inc', 'node', 'node.pages');
+    ctools_include('form');
+    $form_id = $node->type . '_node_form';
+
+    $form_state = array('want form' => TRUE, 'args' => array($node));
+    $form = ctools_build_form($form_id, $form_state);
 
-    $form = drupal_retrieve_form($node->type . '_node_form', $node);
-    drupal_process_form($node->type . '_node_form', $form);
     // Fill in the 'node' portion of the context
     $context->data     = $node;
     $context->title    = $node->title;
     $context->argument = $node->nid;
 
     $context->form       = $form;
-    $context->form_id    = $node->type . '_node_form';
+    $context->form_state = &$form_state;
+    $context->form_id    = $form_id;
     $context->form_title = $node->title;
     $context->node_type  = $node->type;
     return $context;
-- 
GitLab