From 25b0bc65097e6d4326cace2d0fc474f026de412a Mon Sep 17 00:00:00 2001
From: Earl Miles <merlin@logrus.com>
Date: Tue, 31 Mar 2009 03:35:35 +0000
Subject: [PATCH] Page locking + improvements to locking notification on
 handlers.

---
 css/ctools.css                         | 12 ++++
 delegator/css/task-handlers.css        |  6 ++
 delegator/delegator.admin.inc          | 58 ++++++++++++----
 delegator/delegator.install            | 74 +++++++++++++++-----
 delegator/delegator.module             |  8 +++
 delegator/plugins/tasks/page.admin.inc | 96 +++++++++++++++++++++++---
 delegator/plugins/tasks/page.inc       | 27 ++++++--
 includes/export.inc                    |  2 +-
 8 files changed, 237 insertions(+), 46 deletions(-)
 create mode 100644 css/ctools.css

diff --git a/css/ctools.css b/css/ctools.css
new file mode 100644
index 00000000..5cf9c5b4
--- /dev/null
+++ b/css/ctools.css
@@ -0,0 +1,12 @@
+/* $Id$ */
+.ctools-locked {
+  color: red;
+  border: 1px solid red;
+  padding: 1em;
+}
+
+.ctools-owns-lock {
+  background: #FFFFDD none repeat scroll 0 0;
+  border: 1px solid #F0C020;
+  padding: 1em;
+}
diff --git a/delegator/css/task-handlers.css b/delegator/css/task-handlers.css
index 8c2af600..f90eed90 100644
--- a/delegator/css/task-handlers.css
+++ b/delegator/css/task-handlers.css
@@ -18,6 +18,12 @@
   padding: 1em;
 }
 
+.delegator-owns-lock {
+  background: #FFFFDD none repeat scroll 0 0;
+  border: 1px solid #F0C020;
+  padding: 1em;
+}
+
 .delegator-operations div {
   display: inline;
 }
diff --git a/delegator/delegator.admin.inc b/delegator/delegator.admin.inc
index b7ffe084..acf71647 100644
--- a/delegator/delegator.admin.inc
+++ b/delegator/delegator.admin.inc
@@ -132,6 +132,8 @@ function delegator_admin_set_task_cache($task, $subtask_id, $cache) {
   // Then write it.
   $key = delegator_make_task_name($task['name'], $subtask_id);
   ctools_include('object-cache');
+
+  $cache->changed = TRUE;
   $cache = ctools_object_cache_set('delegator_handlers', $key, $cache);
 }
 
@@ -500,8 +502,12 @@ function delegator_admin_list_form(&$form_state) {
     '#submit' => array('delegator_admin_list_form_cancel'),
   );
 
-  $form['#delegator-lock'] = $cache->locked;
-  $form['#task-name'] = $form_state['task_name'];
+  if (!empty($cache->locked)) {
+    $form['warning'] = array('#value' => theme('delegator_admin_lock', $cache->locked, $form_state['task_name']));
+  }
+  else if (!empty($cache->changed)) {
+    $form['warning'] = array('#value' => theme('delegator_admin_changed'));
+  }
 
   // Set up a list of callbacks for our actions. This method allows
   // clever form_alter uses to add more actions easily.
@@ -552,26 +558,47 @@ function delegator_admin_make_dropdown_links($actions) {
   return $links;
 }
 
+/**
+ * Draw the "this task is locked from editing" box.
+ */
+function theme_delegator_admin_lock($lock, $task_name) {
+  $account  = user_load($lock->uid);
+  $name     = theme('username', $account);
+  $lock_age = format_interval(time() - $lock->updated);
+  $break    = url('admin/build/delegator/' . $task_name . '/break-lock', array('query' => array('destination' => $_GET['q'], 'cancel' => $_GET['q'])));
+
+  ctools_add_css('ctools');
+  $output = '<div class="ctools-locked">';
+  $output .= t('This task handler is being edited by user !user, and is therefore locked from editing by others. This lock is !age old. Click here to <a href="!break">break this lock</a>.', array('!user' => $name, '!age' => $lock_age, '!break' => $break));
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * Draw the "you have unsaved changes and this task is locked." message.
+ */
+function theme_delegator_admin_changed() {
+  ctools_add_css('ctools');
+  $output = '<div class="ctools-owns-lock">';
+  $output .= t('You have modified this task handler but the changes have not yet been permanently saved. It will be locked for editing by others until you save or cancel these changes.');
+  $output .= '</div>';
+
+  return $output;
+}
+
 /**
  * Theme the form so it has a table.
  */
 function theme_delegator_admin_list_form($form) {
   $output = '';
-  if (!empty($form['#delegator-lock'])) {
-    $account  = user_load($form['#delegator-lock']->uid);
-    $name     = theme('username', $account);
-    $lock_age = format_interval(time() - $form['#delegator-lock']->updated);
-    $break    = url('admin/build/delegator/' . $form['#task-name'] . '/break-lock');
 
-    $output .= '<div class="delegator-locked">';
-    $output .= t('This task is being edited by user !user, and is therefore locked from editing by others. This lock is !age old. Click here to <a href="!break">break this lock</a>.', array('!user' => $name, '!age' => $lock_age, '!break' => $break));
-    $output .= '</div>';
+  if (isset($form['warning'])) {
+    $output .= drupal_render($form['warning']);
   }
-
   if (isset($form['description'])) {
     $output .= drupal_render($form['description']);
   }
-  if (isset($form['subatsk_description'])) {
+  if (isset($form['subtask_description'])) {
     $output .= drupal_render($form['subtask_description']);
   }
 
@@ -1054,6 +1081,13 @@ function delegator_administer_task_handler_edit($task_name, $handler_id, $name,
   ctools_include('wizard');
   $output = ctools_wizard_multistep_form($form_info, $step, $form_state);
 
+  if (!empty($cache->locked)) {
+    $output = theme('delegator_admin_lock', $cache->locked, $task_name) . $output;
+  }
+  else if (!empty($cache->changed)) {
+    $output = theme('delegator_admin_changed') . $output;
+  }
+
   drupal_add_css(drupal_get_path('module', 'delegator') . '/css/task-handlers.css');
   if (!empty($plugin['forms'][$step]['no blocks'])) {
     print theme('page', $output, FALSE);
diff --git a/delegator/delegator.install b/delegator/delegator.install
index 627d6123..6150fba3 100644
--- a/delegator/delegator.install
+++ b/delegator/delegator.install
@@ -29,39 +29,39 @@ function delegator_schema_1() {
       'did' => array(
         'type' => 'serial',
         'not null' => TRUE,
-        'description' => t('Primary ID field for the table. Not used for anything except internal lookups.'),
+        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
         'no export' => TRUE,
       ),
       'name' => array(
         'type' => 'varchar',
         'length' => '255',
-        'description' => t('Unique ID for this task handler. Used to identify it programmatically.'),
+        'description' => 'Unique ID for this task handler. Used to identify it programmatically.',
       ),
       'task' => array(
         'type' => 'varchar',
         'length' => '64',
-        'description' => t('ID of the task this handler is for.'),
+        'description' => 'ID of the task this handler is for.',
       ),
       'subtask' => array(
         'type' => 'varchar',
         'length' => '64',
-        'description' => t('ID of the subtask this handler is for.'),
+        'description' => 'ID of the subtask this handler is for.',
         'not null' => TRUE,
         'default' => '',
       ),
       'handler' => array(
         'type' => 'varchar',
         'length' => '64',
-        'description' => t('ID of the task handler being used.'),
+        'description' => 'ID of the task handler being used.',
       ),
       'weight' => array(
         'type' => 'int',
-        'description' => t('The order in which this handler appears. Lower numbers go first.'),
+        'description' => 'The order in which this handler appears. Lower numbers go first.',
       ),
       'conf' => array(
         'type' => 'text',
         'size' => 'big',
-        'description' => t('Serialized configuration of the handler, if needed.'),
+        'description' => 'Serialized configuration of the handler, if needed.',
         'not null' => TRUE,
         'serialize' => TRUE,
       ),
@@ -73,18 +73,18 @@ function delegator_schema_1() {
   );
 
   $schema['delegator_weights'] = array(
-    'description' => t('Contains override weights for delegator handlers that are in code.'),
+    'description' => 'Contains override weights for delegator handlers that are in code.',
     'fields' => array(
       'name' => array(
         'type' => 'varchar',
         'length' => '255',
-        'description' => t('Unique ID for this task handler. Used to identify it programmatically.'),
+        'description' => 'Unique ID for this task handler. Used to identify it programmatically.',
         'not null' => TRUE,
         'default' => '',
       ),
       'weight' => array(
         'type' => 'int',
-        'description' => t('The order in which this handler appears. Lower numbers go first.'),
+        'description' => 'The order in which this handler appears. Lower numbers go first.',
       ),
     ),
     'primary key' => array('name'),
@@ -94,7 +94,7 @@ function delegator_schema_1() {
   );
 
   $schema['delegator_pages'] = array(
-    'description' => t('Contains page subtasks for implementing pages with arbitrary tasks.'),
+    'description' => 'Contains page subtasks for implementing pages with arbitrary tasks.',
     'export' => array(
       'identifier' => 'page',
     ),
@@ -102,48 +102,60 @@ function delegator_schema_1() {
       'pid' => array(
         'type' => 'serial',
         'not null' => TRUE,
-        'description' => t('Primary ID field for the table. Not used for anything except internal lookups.'),
+        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
         'no export' => TRUE,
       ),
       'name' => array(
         'type' => 'varchar',
         'length' => '255',
-        'description' => t('Unique ID for this subtask. Used to identify it programmatically.'),
+        'description' => 'Unique ID for this subtask. Used to identify it programmatically.',
+      ),
+      'type' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'description' => 'What type of page this is, so that we can use the same mechanism for creating tighter UIs for targeted pages.',
       ),
       'admin_title' => array(
         'type' => 'varchar',
         'length' => '255',
-        'description' => t('Human readable title for this page subtask.'),
+        'description' => 'Human readable title for this page subtask.',
       ),
       'path' => array(
         'type' => 'varchar',
         'length' => '255',
-        'description' => t('The menu path that will invoke this task.'),
+        'description' => 'The menu path that will invoke this task.',
       ),
       'access' => array(
         'type' => 'text',
         'size' => 'big',
-        'description' => t('Access configuration for this path.'),
+        'description' => 'Access configuration for this path.',
         'not null' => TRUE,
         'serialize' => TRUE,
       ),
       'multiple' => array(
         'type' => 'int',
         'size' => 'tiny',
-        'description' => t('True if the UI is set up to allow multiple handlers per page.'),
+        'description' => 'True if the UI is set up to allow multiple handlers per page.',
         'default' => 0,
       ),
       'menu' => array(
         'type' => 'text',
         'size' => 'big',
-        'description' => t('Serialized configuration of Drupal menu visibility settings for this item.'),
+        'description' => 'Serialized configuration of Drupal menu visibility settings for this item.',
         'not null' => TRUE,
         'serialize' => TRUE,
       ),
       'arguments' => array(
         'type' => 'text',
         'size' => 'big',
-        'description' => t('Configuration of arguments for this menu item.'),
+        'description' => 'Configuration of arguments for this menu item.',
+        'not null' => TRUE,
+        'serialize' => TRUE,
+      ),
+      'conf' => array(
+        'type' => 'text',
+        'size' => 'big',
+        'description' => 'Serialized configuration of the page, if needed.',
         'not null' => TRUE,
         'serialize' => TRUE,
       ),
@@ -171,3 +183,27 @@ function delegator_uninstall() {
   drupal_uninstall_schema('delegator');
 }
 
+/**
+ * Update delegator page to include a little more data.
+ */
+function delegator_update_6100() {
+  $ret = array();
+  $type = array(
+    'type' => 'varchar',
+    'length' => '255',
+    'description' => 'What type of page this is, so that we can use the same mechanism for creating tighter UIs for targeted pages.',
+    'initial' => 'custom',
+  );
+  $conf = array(
+    'type' => 'text',
+    'size' => 'big',
+    'description' => 'Serialized configuration of the page, if needed.',
+    'not null' => TRUE,
+    'serialize' => TRUE,
+    'initial' => serialize(array()),
+  );
+  db_add_field($ret, 'delegator_pages', 'type', $type);
+  db_add_field($ret, 'delegator_pages', 'conf', $conf);
+
+  return $ret;
+}
diff --git a/delegator/delegator.module b/delegator/delegator.module
index bf8e2c59..8ced9df4 100644
--- a/delegator/delegator.module
+++ b/delegator/delegator.module
@@ -35,6 +35,14 @@ function delegator_theme() {
       'arguments' => array('form' => NULL),
       'file' => 'delegator.admin.inc',
     ),
+    'delegator_admin_lock' => array(
+      'arguments' => array('lock' => array(), 'task_name' => NULL),
+      'file' => 'delegator.admin.inc',
+    ),
+    'delegator_admin_changed' => array(
+      'arguments' => array(),
+      'file' => 'delegator.admin.inc',
+    ),
   );
 
   // Allow task plugins to have theme registrations by passing through:
diff --git a/delegator/plugins/tasks/page.admin.inc b/delegator/plugins/tasks/page.admin.inc
index af36f95c..f8591bec 100644
--- a/delegator/plugins/tasks/page.admin.inc
+++ b/delegator/plugins/tasks/page.admin.inc
@@ -156,13 +156,13 @@ function delegator_page_menu(&$items, $task) {
 
     $menu_path = implode('/', $path);
 
-    $items[$menu_path] = delegator_page_menu_item($subtask->menu, $access_arguments, $page_arguments, $load_arguments);
+    $items[$menu_path] = delegator_page_menu_item($task, $subtask->menu, $access_arguments, $page_arguments, $load_arguments);
 
     // Add a parent menu item if one is configured.
     if ($subtask->menu['type'] == 'default tab' && $subtask->menu['parent']['type'] != 'none') {
       array_pop($path);
       $parent_path = implode('/', $path);
-      $items[$parent_path] = delegator_page_menu_item($subtask->menu['parent'], $access_arguments, $page_arguments, $load_arguments);
+      $items[$parent_path] = delegator_page_menu_item($task, $subtask->menu['parent'], $access_arguments, $page_arguments, $load_arguments);
     }
   }
 }
@@ -185,11 +185,11 @@ function delegator_page_menu(&$items, $task) {
  * @param $load_arguments
  *   Arguments to send to the arg loader; should be the subtask id and '%index'.
  */
-function delegator_page_menu_item($menu, $access_arguments, $page_arguments, $load_arguments) {
+function delegator_page_menu_item($task, $menu, $access_arguments, $page_arguments, $load_arguments) {
   $item = array(
     'access callback' => 'ctools_access_menu',
     'access arguments' => $access_arguments,
-    'page callback' => 'delegator_page_execute',
+    'page callback' => isset($task['page callback']) ? $task['page callback'] : 'delegator_page_execute',
     'page arguments' => $page_arguments,
     'load arguments' => $load_arguments,
     'file' => 'plugins/tasks/page.inc',
@@ -238,6 +238,8 @@ function delegator_page_get_page_cache($name) {
     $cache = delegator_page_load($name);
   }
 
+  $cache->locked = ctools_object_cache_test('delegator_page', $name);
+
   return $cache;
 }
 
@@ -245,8 +247,13 @@ function delegator_page_get_page_cache($name) {
  * Store changes to a task handler in the object cache.
  */
 function delegator_page_set_page_cache($page) {
+  if (!empty($page->locked)) {
+    return;
+  }
+
   $name = isset($page->new) || !isset($page->name) ? '::new' : $page->name;
   ctools_include('object-cache');
+  $page->changed = TRUE;
   $cache = ctools_object_cache_set('delegator_page', $name, $page);
 }
 
@@ -282,6 +289,34 @@ function delegator_page_get_named_arguments($path) {
   return $arguments;
 }
 
+/**
+ * Draw the "this task is locked from editing" box.
+ */
+function theme_delegator_page_lock($lock, $page_name) {
+  $account  = user_load($lock->uid);
+  $name     = theme('username', $account);
+  $lock_age = format_interval(time() - $lock->updated);
+  $break    = url('admin/build/pages/break-lock/' . $page_name, array('query' => array('destination' => $_GET['q'], 'cancel' => $_GET['q'])));
+
+  ctools_add_css('ctools');
+  $output = '<div class="ctools-locked">';
+  $output .= t('This page is being edited by user !user, and is therefore locked from editing by others. This lock is !age old. Click here to <a href="!break">break this lock</a>.', array('!user' => $name, '!age' => $lock_age, '!break' => $break));
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * Draw the "you have unsaved changes and this task is locked." message.
+ */
+function theme_delegator_page_changed() {
+  ctools_add_css('ctools');
+  $output = '<div class="ctools-owns-lock">';
+  $output .= t('You have modified this page but the changes have not yet been permanently saved. It will be locked for editing by others until you update or cancel these changes.');
+  $output .= '</div>';
+
+  return $output;
+}
+
 /**
  * Page callback to add a subtask.
  */
@@ -334,6 +369,7 @@ function delegator_page_edit_subtask($page_name, $step = NULL) {
     'path' => "admin/build/pages/edit/$page_name/%step",
     'show trail' => FALSE,
     'show return' => TRUE,
+    'show cancel' => TRUE,
     'return path' => 'admin/build/pages',
   ) + delegator_page_edit_form_info();
 
@@ -355,6 +391,13 @@ function delegator_page_edit_subtask($page_name, $step = NULL) {
     drupal_redirect_form(array(), $form_state['redirect']);
   }
 
+  if (!empty($page->locked)) {
+    $output = theme('delegator_page_lock', $page->locked, $page_name) . $output;
+  }
+  else if (!empty($page->changed)) {
+    $output = theme('delegator_page_changed') . $output;
+  }
+
   return $output;
 }
 
@@ -535,6 +578,11 @@ function delegator_page_form_basic_validate(&$form, &$form_state) {
  * Store the values from the basic settings form.
  */
 function delegator_page_form_basic_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   if (!isset($form_state['page']->pid) && empty($form_state['page']->import)) {
     $form_state['page']->name = $form_state['values']['name'];
   }
@@ -687,6 +735,11 @@ function delegator_page_form_menu(&$form, &$form_state) {
  * Submit handler for the menu form for add/edit page task.
  */
 function delegator_page_form_menu_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   $form_state['page']->menu = $form_state['values']['menu'];
 }
 
@@ -714,6 +767,11 @@ function delegator_page_form_access(&$form, &$form_state) {
  * Submit handler to deal with access control changes.
  */
 function delegator_page_form_access_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   $form_state['page']->access['logic'] = $form_state['values']['logic'];
 }
 
@@ -991,6 +1049,11 @@ function delegator_page_argument_form_change(&$form, &$form_state) {
  * Submit handler to change an argument.
  */
 function delegator_page_argument_form_change_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   $page     = &$form_state['page'];
   $keyword  = &$form_state['keyword'];
   $argument = $form_state['values']['argument'];
@@ -1100,13 +1163,17 @@ function delegator_page_argument_form_settings_validate(&$form, &$form_state) {
  * Submit handler for argument settings.
  */
 function delegator_page_argument_form_settings_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
     $function($form, $form_state);
   }
 
   $page = &$form_state['page'];
   $keyword = &$form_state['keyword'];
-
   // Copy the form to our temporary location which will get moved again when
   // finished. Yes, finished is always next but finish can happen from other
   // locations so we funnel through that path rather than duplicate.
@@ -1169,6 +1236,11 @@ function delegator_page_argument_form_multiple(&$form, &$form_state) {
  * Submit handler for the multiple form.
  */
 function delegator_page_argument_form_multiple_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   $form_state['page']->multiple = $form_state['values']['multiple'];
 
   // The task handler will be created in the _finish hook.
@@ -1196,9 +1268,6 @@ function delegator_page_break_lock_subtask(&$form_state, $name) {
     return array('message' => array('#value' => t('There is no lock on this page to break.')));
   }
 
-  $task = delegator_get_task($page->task);
-  delegator_set_trail($task);
-
   $cancel = 'admin/build/pages';
   if (!empty($_REQUEST['cancel'])) {
     $cancel = $_REQUEST['cancel'];
@@ -1446,12 +1515,16 @@ function delegator_page_disable_subtask($name) {
 function delegator_page_delete_subtask($form_state, $name) {
   // This ensures the task .inc file is loaded
   $task = delegator_get_task('page');
-  $page = delegator_page_load($name);
+  $page = delegator_page_get_page_cache($name);
 
   if (!$page) {
     return drupal_not_found();
   }
 
+  if (!empty($page->locked)) {
+    return array('locked' => array('#value' => theme('delegator_page_lock', $page->locked, $name)));
+  }
+
   $form_state['page'] = $page;
   $form = array();
 
@@ -1479,6 +1552,11 @@ function delegator_page_delete_subtask($form_state, $name) {
  * Submit handler to delete a view.
  */
 function delegator_page_delete_subtask_submit(&$form, &$form_state) {
+  if ($form_state['page']->locked) {
+    drupal_set_message(t('Unable to update page due to lock.'), 'error');
+    return;
+  }
+
   delegator_page_delete($form_state['page']);
   drupal_set_message(t('The page has been deleted.'));
   $form_state['redirect'] = 'admin/build/pages';
diff --git a/delegator/plugins/tasks/page.inc b/delegator/plugins/tasks/page.inc
index bc237cfe..d5f82082 100644
--- a/delegator/plugins/tasks/page.inc
+++ b/delegator/plugins/tasks/page.inc
@@ -49,6 +49,10 @@ function delegator_page_delegator_tasks() {
           'class' => 'delegator-page-storage',
         ),
       ),
+      'page type' => 'custom',
+      // What page callback will execute this page. If it has handlers then
+      // delegator_page_execute should be the default.
+      'page callback' => 'delegator_page_execute',
       // context only items
       'handler type' => 'context',
       'get arguments' => 'delegator_page_get_arguments',
@@ -61,7 +65,7 @@ function delegator_page_delegator_tasks() {
  * Return a list of all subtasks.
  */
 function delegator_page_subtasks($task) {
-  $pages = delegator_page_load_all();
+  $pages = delegator_page_load_all('custom');
   $return = array();
   foreach ($pages as $name => $page) {
     $return[$name] = delegator_page_build_subtask($task, $page);
@@ -191,11 +195,19 @@ function delegator_page_build_subtask($task, $page) {
  * Delegated implementation of hook_theme().
  */
 function delegator_page_theme(&$items, $task) {
-  $items['delegator_page_form_argument_table'] = array(
-    'arguments' => array('form' => NULL),
+  $base = array(
     'file' => 'page.admin.inc',
     'path' => drupal_get_path('module', 'delegator') . '/plugins/tasks',
   );
+  $items['delegator_page_form_argument_table'] = $base + array(
+    'arguments' => array('form' => NULL),
+  );
+  $items['delegator_page_lock'] = $base + array(
+    'arguments' => array('lock' => array(), 'task_name' => NULL),
+  );
+  $items['delegator_page_changed'] = $base + array(
+    'arguments' => array(),
+  );
 }
 
 /**
@@ -370,9 +382,14 @@ function delegator_page_load($name) {
 /**
  * Load all page subtasks.
  */
-function delegator_page_load_all() {
+function delegator_page_load_all($type = NULL) {
   ctools_include('export');
-  return ctools_export_load_object('delegator_pages');
+  if (empty($type)) {
+    return ctools_export_load_object('delegator_pages');
+  }
+  else {
+    return ctools_export_load_object('delegator_pages', 'conditions', array('type' => $type));
+  }
 }
 
 /**
diff --git a/includes/export.inc b/includes/export.inc
index 233b232b..8c141a99 100644
--- a/includes/export.inc
+++ b/includes/export.inc
@@ -40,7 +40,7 @@ define('EXPORT_IN_CODE', 0x02);
  *   A string to notify the loader what the argument is
  *   - all: load all items. This is the default. $args is unused.
  *   - names: $args will be an array of specific named objects to load.
- *   - condition: $args will be a keyed array of conditions. The conditions
+ *   - conditions: $args will be a keyed array of conditions. The conditions
  *       must be in the schema for this table or errors will result.
  * @param $args
  *   An array of arguments whose actual use is defined by the $type argument.
-- 
GitLab