From 9106a36c93003ed4913f5347a238a1c8539c8389 Mon Sep 17 00:00:00 2001
From: Earl Miles <merlin@logrus.com>
Date: Wed, 29 Apr 2009 16:58:34 +0000
Subject: [PATCH] More upgrade improvements including allowing optional named
 arguments!

---
 delegator/plugins/tasks/page.admin.inc        | 39 +++++----------
 delegator/plugins/tasks/page.inc              | 49 ++++++++++++++++---
 includes/context.inc                          |  4 ++
 plugins/content_types/block/block.inc         | 26 ++++++++--
 plugins/content_types/node/node.inc           |  4 +-
 .../user_context/user_profile.inc             |  4 +-
 6 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/delegator/plugins/tasks/page.admin.inc b/delegator/plugins/tasks/page.admin.inc
index b63bcc73..917daac1 100644
--- a/delegator/plugins/tasks/page.admin.inc
+++ b/delegator/plugins/tasks/page.admin.inc
@@ -150,7 +150,7 @@ function delegator_page_menu(&$items, $task) {
         $page_arguments[]   = $position;
         $access_arguments[] = $position;
       }
-      else {
+      else if ($bit[0] != '!') {
         $path[] = $bit;
       }
     }
@@ -273,30 +273,6 @@ function delegator_page_clear_page_cache($name) {
   ctools_object_cache_clear('delegator_page', $name);
 }
 
-/**
- * Get a list of named arguments in a delegator page path.
- *
- * @param $path
- *   A normal Drupal path.
- *
- * @return
- *   An array of % marked variable arguments, keyed by the argument's name.
- *   The value will be the position of the argument so that it can easily
- *   be found. Items with a position of -1 have multiple positions.
- */
-function delegator_page_get_named_arguments($path) {
-  $arguments = array();
-  $bits = explode('/', $path);
-  foreach ($bits as $position => $bit) {
-    if ($bit && $bit[0] == '%') {
-      // special handling for duplicate path items and substr to remove the %
-      $arguments[substr($bit, 1)] = isset($arguments[$bit]) ? -1 : $position;
-    }
-  }
-
-  return $arguments;
-}
-
 /**
  * Draw the "this task is locked from editing" box.
  */
@@ -528,7 +504,7 @@ function delegator_page_form_basic(&$form, &$form_state) {
   $form['path'] = array(
     '#type' => 'textfield',
     '#title' => t('Path'),
-    '#description' => t('The URL path to get to this page. You may create placeholders in the path by using %, or named placeholders by using %name. For example: "node/%node/foo", "forum/%forum" or "dashboard/%input". Named placeholders can be turned into contexts on the arguments form.'),
+    '#description' => t('The URL path to get to this page. You may create named placeholders for variable parts of the path by using %name for required elements and !name for optional elements. For example: "node/%node/foo", "forum/%forum" or "dashboard/!input". These named placeholders can be turned into contexts on the arguments form.'),
     '#default_value' => $page->path,
   );
 }
@@ -565,11 +541,22 @@ function delegator_page_form_basic_validate(&$form, &$form_state) {
     return;
   }
 
+  $found = FALSE;
+  $error = FALSE;
   foreach (explode('/', $form_state['values']['path']) as $bit) {
     if ($bit[0] == '%') {
+      if ($found) {
+        form_error($form['path'], t('You cannot have a dynamic path element after an optional path element.'));
+      }
       $path[] = '%';
     }
+    else if ($bit[0] == '!') {
+      $found = TRUE;
+    }
     else {
+      if ($found) {
+        form_error($form['path'], t('You cannot have a static path element after an optional path element.'));
+      }
       $path[] = $bit;
     }
   }
diff --git a/delegator/plugins/tasks/page.inc b/delegator/plugins/tasks/page.inc
index 6375125c..9e1ff9d2 100644
--- a/delegator/plugins/tasks/page.inc
+++ b/delegator/plugins/tasks/page.inc
@@ -285,13 +285,6 @@ function delegator_page_execute($subtask_id) {
   $page = delegator_page_load($subtask_id);
   $task = delegator_get_task($page->task);
 
-  if ($function = ctools_plugin_get_function($task, 'page callback')) {
-    $args = func_get_args();
-    // overwrite the id with the actual page so it won't be loaded again.
-    $args[0] = $page;
-    return call_user_func_array($function, $args);
-  }
-
   // Turn the contexts into a properly keyed array.
   $contexts = array();
   $args = array();
@@ -305,6 +298,25 @@ function delegator_page_execute($subtask_id) {
     }
   }
 
+  $count = 0;
+  $names = delegator_page_get_named_arguments($page->path);
+  $bits = explode('/', $page->path);
+
+  foreach ($page->arguments as $name => $argument) {
+    // Optional arguments must be converted to contexts too, if they exist.
+    if ($bits[$names[$name]][0] == '!' && isset($args[$count])) {
+      $argument['keyword'] = $name;
+      ctools_include('context');
+      $context = ctools_context_get_context_from_argument($argument, $args[$count]);
+      $contexts[$context->id] = $context;
+    }
+    $count++;
+  }
+
+  if ($function = ctools_plugin_get_function($task, 'page callback')) {
+    return call_user_func_array($function, array($page, $contexts, $args));
+  }
+
   ctools_include('context-task-handler');
   $output = ctools_context_handler_render($task, $subtask_id, $contexts, $args);
   if ($output === FALSE) {
@@ -459,3 +471,26 @@ function delegator_page_export($page, $with_handlers = FALSE, $indent = '') {
   return $output;
 }
 
+/**
+ * Get a list of named arguments in a delegator page path.
+ *
+ * @param $path
+ *   A normal Drupal path.
+ *
+ * @return
+ *   An array of % marked variable arguments, keyed by the argument's name.
+ *   The value will be the position of the argument so that it can easily
+ *   be found. Items with a position of -1 have multiple positions.
+ */
+function delegator_page_get_named_arguments($path) {
+  $arguments = array();
+  $bits = explode('/', $path);
+  foreach ($bits as $position => $bit) {
+    if ($bit && ($bit[0] == '%' || $bit[0] == '!')) {
+      // special handling for duplicate path items and substr to remove the %
+      $arguments[substr($bit, 1)] = isset($arguments[$bit]) ? -1 : $position;
+    }
+  }
+
+  return $arguments;
+}
diff --git a/includes/context.inc b/includes/context.inc
index d58ef4ba..cf292570 100644
--- a/includes/context.inc
+++ b/includes/context.inc
@@ -153,6 +153,10 @@ class ctools_context_required {
   }
 
   function select($contexts, $context) {
+    if (!is_array($contexts)) {
+      $contexts = array($contexts);
+    }
+
     if (empty($context) || empty($contexts[$context])) {
       return FALSE;
     }
diff --git a/plugins/content_types/block/block.inc b/plugins/content_types/block/block.inc
index ebd4a3b7..92af4fe9 100644
--- a/plugins/content_types/block/block.inc
+++ b/plugins/content_types/block/block.inc
@@ -64,7 +64,7 @@ function ctools_block_content_type_content_types() {
  * based on the module and delta supplied in the configuration.
  */
 function ctools_block_content_type_render($subtype, $conf) {
-  list($module, $delta) = explode('-', $subtype, 2);
+  list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf);
   $block = (object) module_invoke($module, 'block', 'view', $delta);
   if (empty($block)) {
     return;
@@ -136,6 +136,17 @@ function ctools_block_content_type_edit_form(&$form, &$form_state) {
   // Does nothing!
 }
 
+/**
+ * Submit function to fix the subtype for really old panel panes.
+ */
+function ctools_block_content_type_edit_form_submit(&$form, &$form_state) {
+  if (empty($form_state['subtype']) && isset($form_state['pane'])) {
+    $form_state['pane']->subtype = $form_state['conf']['module'] . '-' . $form_state['conf']['delta'];
+    unset($form_state['conf']['module']);
+    unset($form_state['conf']['delta']);
+  }
+}
+
 /**
  * Returns an edit form for a block.
  */
@@ -204,7 +215,7 @@ function ctools_block_content_type_edit_form(&$form, &$form_state) {
  * Returns the administrative title for a type.
  */
 function ctools_block_content_type_admin_title($subtype, $conf) {
-  list($module, $delta) = explode('-', $subtype, 2);
+  list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf);
   $block = module_invoke($module, 'block', 'list');
   if (empty($block) || empty($block[$delta])) {
     return t('Deleted/missing block @module-@delta', array('@module' => $module, '@delta' => $delta));
@@ -219,7 +230,7 @@ function ctools_block_content_type_admin_title($subtype, $conf) {
  * based on the module and delta supplied in the configuration.
  */
 function ctools_block_content_type_admin_info($subtype, $conf) {
-  list($module, $delta) = explode('-', $subtype, 2);
+  list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf);
   $block = (object) module_invoke($module, 'block', 'view', $delta);
   if (!empty($block) && !empty($block->subject)) {
     $block->title = $block->subject;
@@ -227,6 +238,15 @@ function ctools_block_content_type_admin_info($subtype, $conf) {
   }
 }
 
+function _ctools_block_get_module_delta($subtype, $conf) {
+  if (strpos($subtype, '-')) {
+    return explode('-', $subtype, 2);
+  }
+  else {
+    return array($conf['module'], $conf['delta']);
+  }
+}
+
 /**
  * Provide default icon and categories for blocks when modules don't do this
  * for us.
diff --git a/plugins/content_types/node/node.inc b/plugins/content_types/node/node.inc
index 8a364ebf..931e72a7 100644
--- a/plugins/content_types/node/node.inc
+++ b/plugins/content_types/node/node.inc
@@ -131,14 +131,14 @@ function ctools_node_content_type_edit_form(&$form, &$form_state) {
 
   $form['leave_node_title'] = array(
     '#type' => 'checkbox',
-    '#default_value' => $conf['leave_node_title'],
+    '#default_value' => !empty($conf['leave_node_title']),
     '#title' => t('Leave node title'),
     '#description' => t('Advanced: if checked, do not touch the node title; this can cause the node title to appear twice unless your theme is aware of this.'),
   );
 
   $form['identifier'] = array(
     '#type' => 'textfield',
-    '#default_value' => $conf['identifier'],
+    '#default_value' => !empty($conf['identifier']) ? $conf['identifier'] : '',
     '#title' => t('Identifier'),
     '#description' => t('Whatever is placed here will appear in $node->panel_identifier in the node template to make it easier to theme a node or part of a node as necessary. This identifier will automatically be added as a node template suggestion: node-panel-IDENTIFIER.tpl.php'),
   );
diff --git a/plugins/content_types/user_context/user_profile.inc b/plugins/content_types/user_context/user_profile.inc
index 79044801..85e2b1ae 100644
--- a/plugins/content_types/user_context/user_profile.inc
+++ b/plugins/content_types/user_context/user_profile.inc
@@ -20,8 +20,8 @@ function ctools_user_profile_content_type_render($subtype, $conf, $panel_args, $
   $block = new stdClass();
   $block->module = 'user-profile';
 
-  if ($account === FALSE || ($account->access == 0 && !user_access('administer users'))) {
-    return drupal_not_found();
+  if (!$account || ($account->access == 0 && !user_access('administer users'))) {
+    return NULL;
   }
   // Retrieve and merge all profile fields:
   $fields = array();
-- 
GitLab