diff --git a/ctools.module b/ctools.module index c9649fbdaed025fe96f2af297962fd4334c4af19..4a8a6cf7d96ac7e5e2a215f59ce5a9dba9865dd5 100644 --- a/ctools.module +++ b/ctools.module @@ -345,3 +345,18 @@ function ctools_flush_caches() { ctools_include('css'); ctools_css_flush_caches(); } + +/** + * Check to see if the incoming menu item is js capable or not. + * + * This can be used as %ctools_js as part of a path in hook menu. CTools + * ajax functions will automatically change the phrase 'nojs' to 'ajax' + * when it attaches ajax to a link. This can be used to autodetect if + * that happened. + */ +function ctools_js_load($js) { + if ($js == 'ajax') { + return TRUE; + } + return 0; +} diff --git a/delegator/css/page-task.css b/delegator/css/page-task.css deleted file mode 100644 index e36d4f3667a315ef87be846eb9023261440a8bd1..0000000000000000000000000000000000000000 --- a/delegator/css/page-task.css +++ /dev/null @@ -1,22 +0,0 @@ -/* $Id$ */ - -.delegator-page-operations .ctools-dropdown-link-wrapper, -th.delegator-page-operations { - text-align: right; -} - -td.delegator-page-operations { - width: 175px; -} - -.delegator-disabled { - color: #ccc; -} - -.delegator-page-title { - width: 20%; -} - -.delegator-page-path { - width: 20%; -} diff --git a/delegator/css/task-handlers.css b/delegator/css/task-handlers.css deleted file mode 100644 index f90eed90955dc9dc3af2a36094687f98058c1f7e..0000000000000000000000000000000000000000 --- a/delegator/css/task-handlers.css +++ /dev/null @@ -1,84 +0,0 @@ -/* $Id$ */ - -.delegator-operations { - text-align: right; -} - -.delegator-breadcrumb { - font-size: 120%; -} - -.delegator-current { - font-weight: bold; -} - -.delegator-locked { - color: red; - border: 1px solid red; - padding: 1em; -} - -.delegator-owns-lock { - background: #FFFFDD none repeat scroll 0 0; - border: 1px solid #F0C020; - padding: 1em; -} - -.delegator-operations div { - display: inline; -} - -.delegator-disabled { - color: #ccc; -} - -.delegator-operations select { - width: 10em; -} - -.delegator-changed-col { - width: .1em; - white-space: nowrap; - margin: 0; -} - -.delegator-changed-col .tabledrag-changed { - position: relative; - top: .2em; - font-size: 150%; -} - -#delegator-task-list-arrange a.tabledrag-handle { - padding-right: .75em; -} - -#delegator-task-list-arrange td { - vertical-align: top; -} - -#delegator-task-list-arrange tr.delegator-collapsible td { - padding-left: 4em; -} - -#delegator-task-list-arrange tr.draggable .ctools-collapsible-content { - display: none; -} - -/* -#delegator-task-list-arrange tr.delegator-collapsible div.ctools-collapsible-content { - display: block; -} -*/ - -html.js .delegator-operations { - width: 170px; -} - -div.delegator-task-handler-operations { - display: none; -} - -html.js div.delegator-task-handler-operations { - display: block; -} - diff --git a/delegator/delegator.admin.inc b/delegator/delegator.admin.inc index af0536de485e5fbde7cad37c7db6b78c9d4784ea..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/delegator/delegator.admin.inc +++ b/delegator/delegator.admin.inc @@ -1,1369 +0,0 @@ -handlers = array(); - foreach ($task_handlers as $id => $handler) { - $cache->handlers[$id]['name'] = $id; - $cache->handlers[$id]['weight'] = $handler->weight; - $cache->handlers[$id]['changed'] = FALSE; - $cache->handlers[$id]['disabled'] = !empty($handler->disabled); - } - $cache->locked = ctools_object_cache_test('delegator_handlers', $key); - } - - // Sort the new cache. - uasort($cache->handlers, '_delegator_admin_task_cache_sort'); - - return $cache; -} - -/** - * Store information about task handlers in the object cache. - * - * This object should have already been retrieved or created by - * delegator_admin_get_task_cache(). - */ -function delegator_admin_set_task_cache($task, $subtask_id, $cache) { - if ($cache->locked) { - drupal_set_message(t('Unable to update task due to lock.'), 'error'); - return; - } - - // We only bother if something has been marked changed. This keeps us from - // locking when we should not. - $changed = FALSE; - if (!empty($cache->working)) { - $changed = TRUE; - } - else { - foreach ($cache->handlers as $handler) { - if (!empty($handler['changed'])) { - $changed = TRUE; - break; - } - } - } - - if (!$changed) { - // We may have cancelled a working copy. We'll actually clear cache in this - // instance. - delegator_admin_clear_task_cache($task, $subtask_id); - return; - } - - // First, sort the cache object. - uasort($cache->handlers, '_delegator_admin_task_cache_sort'); - - // 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); -} - -/** - * Reset information about the task handlers for a given task. - */ -function delegator_admin_clear_task_cache($task, $subtask_id) { - ctools_include('object-cache'); - $key = delegator_make_task_name($task['name'], $subtask_id); - ctools_object_cache_clear('delegator_handlers', $key); -} - -/** - * Get the cached changes to a given task handler. - */ -function delegator_admin_get_task_handler_cache($name) { - ctools_include('object-cache'); - return ctools_object_cache_get('delegator_task_handler', $name); -} - -/** - * Store changes to a task handler in the object cache. - */ -function delegator_admin_set_task_handler_cache($handler, $working = FALSE) { - $name = $handler->name; - - if ($working) { - $name = delegator_make_task_name($handler->task, $handler->subtask) . '-working'; - } - - ctools_include('object-cache'); - $cache = ctools_object_cache_set('delegator_task_handler', $name, $handler); -} - -/** - * Remove an item from the object cache. - */ -function delegator_admin_clear_task_handler_cache($name) { - ctools_include('object-cache'); - ctools_object_cache_clear('delegator_task_handler', $name); -} - -/** - * Write a new handler to the database. - */ -function delegator_admin_new_task_handler($handler, $task_name, $task, $subtask_id, $cache, $plugin) { - // Store the new handler. - if (!$cache->locked) { - delegator_admin_set_task_handler_cache($handler, TRUE); - } - - $cache->handlers[$handler->name] = array( - 'name' => $handler->name, - 'weight' => $handler->weight, - 'changed' => DGA_CHANGED_CACHED, - 'disabled' => FALSE, - ); - $cache->working = $handler->name; - - // Store the changed task handler list. - delegator_admin_set_task_cache($task, $subtask_id, $cache); - - // If the task handler plugin specifies an add form, set a redirect. - if (isset($plugin['add forms'])) { - // Get the beginning of the array. - reset($plugin['add forms']); - list($id, $title) = each($plugin['add forms']); - return "admin/build/delegator/$task_name/add/$handler->name/$id"; - } - else { - return "admin/build/delegator/$task_name"; - } -} - -/** - * Used as a callback to uasort to sort the task cache by weight. - * - * The 'name' field is used as a backup when weights are the same, which - * can happen when multiple modules put items out there at the same - * weight. - */ -function _delegator_admin_task_cache_sort($a, $b) { - if ($a['weight'] < $b['weight']) { - return -1; - } - elseif ($a['weight'] > $b['weight']) { - return 1; - } - elseif ($a['name'] < $b['name']) { - return -1; - } - elseif ($a['name'] > $b['name']) { - return 1; - } - - return 0; -} - -/** - * Find the right handler to use for an id during the edit process. - * - * When editing, a handler may be stored in cache. It may also be - * reverted and unsaved, which can cause issues all their own. This - * function can be used to find the right handler to use in these cases. - */ -function delegator_admin_find_handler($id, $cache, $task_name, $task_handlers = array()) { - // Use the one from the database or an updated one in cache? - if (isset($cache->working) && $cache->working == $id) { - $handler = delegator_admin_get_task_handler_cache($task_name . '-working'); - } - else if ($cache->handlers[$id]['changed'] & DGA_CHANGED_CACHED) { - $handler = delegator_admin_get_task_handler_cache($id); - } - else { - // Special case: Reverted handlers get their defaults back. - if ($cache->handlers[$id]['changed'] & DGA_CHANGED_DELETED) { - ctools_include('export'); - $handler = ctools_get_default_object('delegator_handlers', $id); - } - else if (!empty($task_handlers)) { - $handler = $task_handlers[$id]; - } - else { - list($task_id, $subtask_id) = delegator_get_task_id($task_name); - $task = delegator_get_task($task_id); - $handler = delegator_load_task_handler($task, $subtask_id, $id); - } - } - - return $handler; -} - -/** - * Page callback to administer a particular task. - */ -function delegator_administer_task($task_name) { - list($task_id, $subtask_id) = delegator_get_task_id($task_name); - - $task = delegator_get_task($task_id); - if (!$task) { - return drupal_not_found(); - } - - $subtask = delegator_get_task_subtask($task, $subtask_id); - - // Subtasks marked as single tasks won't see this page, so redirect - // to wherever the subtask wants to be administered from. - if (!empty($subtask['single task'])) { - $task_type = delegator_get_task_type($task['task type']); - return drupal_goto($task_type['admin path']); - } - - $task_handlers = delegator_load_task_handlers($task, $subtask_id); - delegator_set_trail($task); - - $form_state = array( - 'task_name' => $task_name, - 'task_id' => $task_id, - 'task' => $task, - 'subtask' => $subtask, - 'subtask_id' => $subtask_id, - 'task_handlers' => $task_handlers, - 'cache' => delegator_admin_get_task_cache($task, $subtask_id, $task_handlers), - ); - - ctools_include('form'); - return ctools_build_form('delegator_admin_list_form', $form_state); -} - -/** - * Form to administer task handlers assigned to a task. - */ -function delegator_admin_list_form(&$form_state) { - $task = &$form_state['task']; - $subtask = &$form_state['subtask']; - $task_handlers = &$form_state['task_handlers']; - $cache = &$form_state['cache']; - - // Get a list of possible task handlers for this task. - $task_handler_plugins = delegator_get_task_handler_plugins($task); - - if (isset($task['description'])) { - $form['description'] = array( - '#prefix' => '
$handler->name
field of your import to have a unique name.'), 'warning');
-
- $old_handler = delegator_admin_find_handler($handler->name, $cache, $form_state['task_name']);
- $handler->export_type = $old_handler->export_type | EXPORT_IN_DATABASE;
- }
-
- $form_state['cache'] = $cache;
- $form_state['handler'] = $handler;
-}
-
-/**
- * Submit handler to import an existing page.
- */
-function delegator_admin_import_task_handler_submit($form, &$form_state) {
- // Use the one from the database or an updated one in cache?
- $handler = &$form_state['handler'];
- $cache = &$form_state['cache'];
-
- delegator_admin_set_task_handler_cache($handler);
-
- $cache->handlers[$handler->name] = array(
- 'name' => $handler->name,
- 'weight' => $handler->weight,
- 'changed' => DGA_CHANGED_CACHED,
- 'disabled' => FALSE,
- );
- $cache->last_touched = $handler->name;
-
- delegator_admin_set_task_cache($form_state['task'], $handler->subtask, $cache);
- $form_state['redirect'] = 'admin/build/delegator/' . $form_state['task_name'];
-}
-
diff --git a/delegator/delegator.info b/delegator/delegator.info
deleted file mode 100644
index a6773305f922806996888238d76610076a1608e2..0000000000000000000000000000000000000000
--- a/delegator/delegator.info
+++ /dev/null
@@ -1,5 +0,0 @@
-; $Id$
-name = Delegator
-description = Provides a UI and API to select which handlers will perform tasks.
-core = 6.x
-dependencies[] = ctools
diff --git a/delegator/delegator.module b/delegator/delegator.module
index 317ea3c9660002cb77bd95b130c84acabba9c802..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/delegator/delegator.module
+++ b/delegator/delegator.module
@@ -1,888 +0,0 @@
- array(
- '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:
- $tasks = delegator_get_tasks();
-
- // Provide menu items for each task.
- foreach ($tasks as $task_id => $task) {
- if ($function = ctools_plugin_get_function($task, 'hook theme')) {
- $function($items, $task);
- }
- }
-
- return $items;
-}
-
-/**
- * Implementation of hook_ctools_plugin_dierctory() to let the system know
- * we implement task and task_handler plugins.
- */
-function delegator_ctools_plugin_directory($module, $plugin) {
- if ($module == 'delegator') {
- return 'plugins/' . $plugin;
- }
-}
-
-/**
- * Implementation of hook_menu.
- *
- * Get a list of all tasks and delegate to them.
- */
-function delegator_menu() {
- $items = array();
-
- // Task types get menu entries so they can set up their own administrative
- // areas.
- $task_types = delegator_get_task_types();
-
- foreach ($task_types as $id => $task_type) {
- if ($function = ctools_plugin_get_function($task_type, 'hook menu')) {
- $function($items, $task_type);
- }
- }
-
- $tasks = delegator_get_tasks();
-
- // Provide menu items for each task.
- foreach ($tasks as $task_id => $task) {
- $handlers = delegator_get_task_handler_plugins($task);
- delegator_menu_task_items($items, $task_id, $task, $handlers);
-
- // And for those that provide subtasks, provide menu items for them, as well.
- foreach (delegator_get_task_subtasks($task) as $subtask_id => $subtask) {
- delegator_menu_task_items($items, $task_id, $subtask, $handlers, $subtask_id);
- }
- }
-
- return $items;
-}
-
-/**
- * Implementation of hook_menu_alter.
- *
- * Get a list of all tasks and delegate to them.
- */
-function delegator_menu_alter(&$items) {
- $tasks = delegator_get_tasks();
-
- foreach ($tasks as $task) {
- if ($function = ctools_plugin_get_function($task, 'hook menu alter')) {
- $function($items, $task);
- }
- // let the subtasks alter the menu items too.
- foreach (delegator_get_task_subtasks($task) as $subtask_id => $subtask) {
- if ($function = ctools_plugin_get_function($subtask, 'hook menu alter')) {
- $function($items, $subtask);
- }
- }
- }
-
- return $items;
-}
-
-/**
- * Generate a menu item for a given task and subtask combination.
- */
-function delegator_menu_task_items(&$items, $task_id, $task, $handlers, $subtask_id = NULL) {
- // If using a subtask, attach the subtask id to the name we use.
- $task_name = $task_id . ($subtask_id ? '-' . $subtask_id : '');
-
- // Allow the task to add its own menu items.
- if ($function = ctools_plugin_get_function($task, 'hook menu')) {
- $function($items, $task);
- }
-
- // Set up access permissions.
- $access_callback = isset($task['admin access callback']) ? $task['admin access callback'] : 'user_access';
- $access_arguments = isset($task['admin access arguments']) ? $task['admin access arguments'] : array('administer delegator');
-
- $base = array(
- 'access callback' => $access_callback,
- 'access arguments' => $access_arguments,
- 'file' => 'delegator.admin.inc',
- );
-
- if (isset($task['admin title'])) {
- $items['admin/build/delegator/' . $task_name] = array(
- 'title' => $task['admin title'],
- 'description' => isset($task['admin description']) ? $task['admin description'] : '',
- 'page callback' => 'delegator_administer_task',
- 'page arguments' => array($task_name),
- 'type' => MENU_CALLBACK,
- ) + $base;
- }
-
- // Form to add new items to this task.
- $items['admin/build/delegator/' . $task_name . '/add/%/%'] = array(
- 'page callback' => 'delegator_administer_task_handler_add',
- 'page arguments' => array($task_name, 5, 6),
- ) + $base;
-
- // Form to add export a handler
- $items['admin/build/delegator/' . $task_name . '/export/%'] = array(
- 'page callback' => 'delegator_administer_task_handler_export',
- 'page arguments' => array($task_name, 5),
- ) + $base;
-
- // Form to break a lock on this task.
- $items['admin/build/delegator/' . $task_name . '/break-lock'] = array(
- 'title' => 'Break lock',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('delegator_administer_break_lock', $task_name),
- 'type' => MENU_CALLBACK,
- ) + $base;
-
- // Form to import a task handler for this task.
- $items['admin/build/delegator/' . $task_name . '/import'] = array(
- 'title' => 'Import',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('delegator_admin_import_task_handler', $task_name),
- 'type' => MENU_CALLBACK,
- ) + $base;
-
- foreach ($handlers as $handler_id => $handler) {
- if (isset($handler['edit forms'])) {
- $weight = 0;
- $default_task = FALSE;
- foreach ($handler['edit forms'] as $form_id => $form_title) {
- if (!$default_task) {
- $default_task = TRUE;
- // The first edit form is the default for tabs, so it gets a bit
- // of special treatment here. It gets the parent menu declaration
- // which is just a callback, and it gets its main entry declared
- // as the default local task.
- $items["admin/build/delegator/$task_name/$handler_id/%"] = array(
- 'title' => t('Edit'),
- 'page callback' => 'delegator_administer_task_handler_edit',
- 'page arguments' => array($task_name, $handler_id, 5, $form_id),
- 'type' => MENU_CALLBACK,
- ) + $base;
- $type = MENU_DEFAULT_LOCAL_TASK;
- }
- else {
- $type = $form_title ? MENU_LOCAL_TASK : MENU_CALLBACK;
- }
- // Handler to edit delegator task handlers. May exist in its own UI.
- $items["admin/build/delegator/$task_name/$handler_id/%/$form_id"] = array(
- 'title' => $form_title,
- 'page callback' => 'delegator_administer_task_handler_edit',
- 'page arguments' => array($task_name, $handler_id, 5, $form_id),
- // This allows an empty form title to provide a hidden form
- // which is useful for doing more branch-like multi-step
- // functionality.
- 'type' => $type,
- 'weight' => $weight++,
- ) + $base;
- }
- }
- }
-}
-
-// --------------------------------------------------------------------------
-// Database routines
-
-/**
- * Load a single task handler by name.
- *
- * Handlers can come from multiple sources; either the database or by normal
- * export method, which is handled by the ctools library, but handlers can
- * also be bundled with task/subtask. We have to check there and perform
- * overrides as appropriate.
- *
- * Handlers bundled with the task are of a higher priority than default
- * handlers provided by normal code, and are of a lower priority than
- * the database, so we have to check the source of handlers when we have
- * multiple to choose from.
- */
-function delegator_load_task_handler($task, $subtask_id, $name) {
- ctools_include('export');
- $result = ctools_export_load_object('delegator_handlers', 'names', array($name));
- $handlers = delegator_get_default_task_handlers($task, $subtask_id);
- return delegator_compare_task_handlers($result, $handlers, $name);
-}
-
-/**
- * Load all task handlers for a given task/subtask.
- */
-function delegator_load_task_handlers($task, $subtask_id = NULL, $default_handlers = NULL) {
- ctools_include('export');
- $conditions = array(
- 'task' => $task['name'],
- );
-
- if (isset($subtask_id)) {
- $conditions['subtask'] = $subtask_id;
- }
-
- $handlers = ctools_export_load_object('delegator_handlers', 'conditions', $conditions);
- $defaults = isset($default_handlers) ? $default_handlers : delegator_get_default_task_handlers($task, $subtask_id);
- foreach ($defaults as $name => $default) {
- $result = delegator_compare_task_handlers($handlers, $defaults, $name);
-
- if ($result) {
- $handlers[$name] = $result;
- // Ensure task and subtask are correct, because it's easy to change task
- // names when editing a default and fail to do it on the associated handlers.
- $result->task = $task['name'];
- $result->subtask = $subtask_id;
- }
- }
-
- // Override weights from the weight table.
- if ($handlers) {
- $names = array();
- $placeholders = array();
- foreach ($handlers as $handler) {
- $names[] = $handler->name;
- $placeholders[] = "'%s'";
- }
-
- $result = db_query("SELECT name, weight FROM {delegator_weights} WHERE name IN (" . implode(', ', $placeholders) . ")", $names);
- while ($weight = db_fetch_object($result)) {
- $handlers[$weight->name]->weight = $weight->weight;
- }
- }
-
- return $handlers;
-}
-
-/**
- * Get the default task handlers from a task, if they exist.
- *
- * Tasks can contain 'default' task handlers which are provided by the
- * default task. Because these can come from either the task or the
- * subtask, the logic is abstracted to reduce code duplication.
- */
-function delegator_get_default_task_handlers($task, $subtask_id) {
- // Load default handlers that are provied by the task/subtask itself.
- $handlers = array();
- if ($subtask_id) {
- $subtask = delegator_get_task_subtask($task, $subtask_id);
- if (isset($subtask['default handlers'])) {
- $handlers = $subtask['default handlers'];
- }
- }
- else if (isset($task['default handlers'])) {
- $handlers = $task['default handlers'];
- }
-
- return $handlers;
-}
-
-/**
- * Compare a single task handler from two lists and provide the correct one.
- *
- * Task handlers can be gotten from multiple sources. As exportable objects,
- * they can be provided by default hooks and the database. But also, because
- * they are tightly bound to tasks, they can also be provided by default
- * tasks. This function reconciles where to pick up a task handler between
- * the exportables list and the defaults provided by the task itself.
- *
- * @param $result
- * A list of handlers provided by export.inc
- * @param $handlers
- * A list of handlers provided by the default task.
- * @param $name
- * Which handler to compare.
- * @return
- * Which handler to use, if any. May be NULL.
- */
-function delegator_compare_task_handlers($result, $handlers, $name) {
- // Compare our special default handler against the actual result, if
- // any, and do the right thing.
- if (!isset($result[$name]) && isset($handlers[$name])) {
- $handlers[$name]->type = t('Default');
- $handlers[$name]->export_type = EXPORT_IN_CODE;
- return $handlers[$name];
- }
- else if (isset($result[$name]) && !isset($handlers[$name])) {
- return $result[$name];
- }
- else if (isset($result[$name]) && isset($handlers[$name])) {
- if ($result[$name]->export_type & EXPORT_IN_DATABASE) {
- $result[$name]->type = t('Overridden');
- $result[$name]->export_type = $result[$name]->export_type | EXPORT_IN_CODE;
- return $result[$name];
- }
- else {
- // In this case, our default is a higher priority than the standard default.
- $handlers[$name]->type = t('Default');
- $handlers[$name]->export_type = EXPORT_IN_CODE;
- return $handlers[$name];
- }
- }
-}
-
-/**
- * Load all task handlers for a given task and subtask and sort them.
- */
-function delegator_load_sorted_handlers($task, $subtask_id = NULL, $enabled = FALSE) {
- $handlers = delegator_load_task_handlers($task, $subtask_id);
- if ($enabled) {
- foreach ($handlers as $id => $handler) {
- if (!empty($handler->disabled)) {
- unset($handlers[$id]);
- }
- }
- }
- uasort($handlers, '_delegator_sort_task_handlers');
- return $handlers;
-}
-
-/**
- * Callback for uasort to sort task handlers.
- *
- * Task handlers are sorted by weight then by name.
- */
-function _delegator_sort_task_handlers($a, $b) {
- if ($a->weight < $b->weight) {
- return -1;
- }
- elseif ($a->weight > $b->weight) {
- return 1;
- }
- elseif ($a->name < $b->name) {
- return -1;
- }
- elseif ($a->name > $b->name) {
- return 1;
- }
-
- return 0;
-}
-
-/**
- * Write a task handler to the database.
- */
-function delegator_save_task_handler(&$handler) {
- $update = (isset($handler->did)) ? array('did') : array();
- // Let the task handler respond to saves:
- if ($function = ctools_plugin_load_function('delegator', 'task_handlers', $handler->handler, 'save')) {
- $function($handler, $update);
- }
-
- drupal_write_record('delegator_handlers', $handler, $update);
- db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name);
-
- // If this was previously a default handler, we may have to write task handlers.
- if (!$update) {
- // @todo wtf was I going to do here?
- }
- return $handler;
-}
-
-/**
- * Remove a task handler.
- */
-function delegator_delete_task_handler($handler) {
- // Let the task handler respond to saves:
- if ($function = ctools_plugin_load_function('delegator', 'task_handlers', $handler->handler, 'delete')) {
- $function($handler);
- }
- db_query("DELETE FROM {delegator_handlers} WHERE name = '%s'", $handler->name);
- db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name);
-}
-
-/**
- * Export a task handler into code suitable for import or use as a default
- * task handler.
- */
-function delegator_export_task_handler($handler, $indent = '') {
- ctools_include('export');
- ctools_include('plugins');
- $handler = drupal_clone($handler);
-
- $append = '';
- if ($function = ctools_plugin_load_function('delegator', 'task_handlers', $handler->handler, 'export')) {
- $append = $function($handler, $indent);
- }
-
- $output = ctools_export_object('delegator_handlers', $handler, $indent);
- $output .= $append;
-
- return $output;
-}
-
-/**
- * Create a new task handler object.
- *
- * @param $task
- * The task this task handler is for.
- * @param $subtask_id
- * The subtask this task handler is for.
- * @param $plugin
- * The plugin this task handler is created from.
- * @param $weight
- * The weight to give this new task handler.
- * @param $cache
- * The task cache if the task is currently being edited. This must be used
- * if task handlers already exist as it is used to determine a unique name
- * and without this naming collisions could occur.
- */
-function delegator_new_task_handler($task, $subtask_id, $plugin, $weight = 0, $cache = NULL) {
- // Generate a unique name. Unlike most named objects, we don't let people choose
- // names for task handlers because they mostly don't make sense.
- $base = $task['name'];
- if ($subtask_id) {
- $base .= '_' . $subtask_id;
- }
- $base .= '_' . $plugin['name'];
-
- // Once we have a base, check to see if it is used. If it is, start counting up.
- $name = $base;
- $count = 1;
- // If taken
- while (isset($cache->handlers[$name])) {
- $name = $base . '_' . ++$count;
- }
-
- // Create a new, empty handler object.
- $handler = new stdClass;
- $handler->title = '';
- $handler->task = $task['name'];
- $handler->subtask = $subtask_id;
- $handler->name = $name;
- $handler->handler = $plugin['name'];
- $handler->weight = $weight;
- $handler->conf = array();
-
- // These are provided by the core export API provided by ctools and we
- // set defaults here so that we don't cause notices. Perhaps ctools should
- // provide a way to do this for us so we don't have to muck with it.
- $handler->export_type = EXPORT_IN_DATABASE;
- $handler->type = t('Local');
-
- if (isset($plugin['default conf'])) {
- if (is_array($plugin['default conf'])) {
- $handler->conf = $plugin['default conf'];
- }
- else if (function_exists($plugin['default conf'])) {
- $handler->conf = $plugin['default conf']($handler, $task, $subtask_id);
- }
- }
-
- return $handler;
-}
-
-/**
- * Set an overidden weight for a task handler.
- *
- * We do this so that in-code task handlers don't need to get written
- * to the database just because they have their weight changed.
- */
-function delegator_update_task_handler_weight($handler, $weight) {
- db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name);
- db_query("INSERT INTO {delegator_weights} (name, weight) VALUES ('%s', %d)", $handler->name, $weight);
-}
-
-/**
- * Shortcut function to get task type plugins.
- */
-function delegator_get_task_types() {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'task_types');
-}
-
-/**
- * Shortcut function to get a task type plugin.
- */
-function delegator_get_task_type($id) {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'task_types', $id);
-}
-
-/**
- * Shortcut function to get task plugins.
- */
-function delegator_get_tasks() {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'tasks');
-}
-
-/**
- * Shortcut function to get a task plugin.
- */
-function delegator_get_task($id) {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'tasks', $id);
-}
-
-/**
- * Get all tasks for a given type.
- */
-function delegator_get_tasks_by_type($type) {
- ctools_include('plugins');
- $all_tasks = ctools_get_plugins('delegator', 'tasks');
- $tasks = array();
- foreach ($all_tasks as $id => $task) {
- if (isset($task['task type']) && $task['task type'] == $type) {
- $tasks[$id] = $task;
- }
- }
-
- return $tasks;
-}
-
-/**
- * Fetch all subtasks for a delegator task.
- *
- * @param $task
- * A loaded $task plugin object.
- */
-function delegator_get_task_subtasks($task) {
- if (empty($task['subtasks'])) {
- return array();
- }
-
- if ($function = ctools_plugin_get_function($task, 'subtasks callback')) {
- return $function($task);
- }
-}
-
-/**
- * Fetch all subtasks for a delegator task.
- *
- * @param $task
- * A loaded $task plugin object.
- * @param $subtask_id
- * The subtask ID to load.
- */
-function delegator_get_task_subtask($task, $subtask_id) {
- if (empty($task['subtasks'])) {
- return;
- }
-
- if ($function = ctools_plugin_get_function($task, 'subtask callback')) {
- return $function($task, $subtask_id);
- }
-}
-
-/**
- * Shortcut function to get task handler plugins.
- */
-function delegator_get_task_handlers() {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'task_handlers');
-}
-
-/**
- * Shortcut function to get a task handler plugin.
- */
-function delegator_get_task_handler($id) {
- ctools_include('plugins');
- return ctools_get_plugins('delegator', 'task_handlers', $id);
-}
-
-/**
- * Retrieve a list of all applicable task handlers for a given task.
- *
- * This looks at the $task['handler type'] and compares that to $task_handler['handler type'].
- * If the task has no type, the id of the task is used instead.
- */
-function delegator_get_task_handler_plugins($task) {
- $type = isset($task['handler type']) ? $task['handler type'] : $task['name'];
- $name = $task['name'];
-
- $handlers = array();
- $task_handlers = delegator_get_task_handlers();
- foreach ($task_handlers as $id => $handler) {
- $task_type = is_array($handler['handler type']) ? $handler['handler type'] : array($handler['handler type']);
- if (in_array($type, $task_type) || in_array($name, $task_type)) {
- $handlers[$id] = $handler;
- }
- }
-
- return $handlers;
-}
-
-/**
- * Get the title for a given handler.
- *
- * If the plugin has no 'admin title' function, the generic title of the
- * plugin is used instead.
- */
-function delegator_get_handler_title($plugin, $handler, $task, $subtask_id) {
- $function = ctools_plugin_get_function($plugin, 'admin title');
- if ($function) {
- return $function($handler, $task, $subtask_id);
- }
- else {
- return $plugin['title'];
- }
-}
-
-/**
- * Get the admin summary (additional info) for a given handler.
- */
-function delegator_get_handler_summary($plugin, $handler, $task, $subtask_id) {
- if ($function = ctools_plugin_get_function($plugin, 'admin summary')) {
- return $function($handler, $task, $subtask_id);
- }
-}
-
-/**
- * Split a task name into a task id and subtask id, if applicable.
- */
-function delegator_get_task_id($task_name) {
- if (strpos($task_name, '-') !== FALSE) {
- return explode('-', $task_name, 2);
- }
- else {
- return array($task_name, NULL);
- }
-}
-
-/**
- * Turn a task id + subtask_id into a task name.
- */
-function delegator_make_task_name($task_id, $subtask_id) {
- if ($subtask_id) {
- return $task_id . '-' . $subtask_id;
- }
- else {
- return $task_id;
- }
-}
-
-/**
- * Delegator for arg load function because menu system will not load extra
- * files for these; they must be in a .module.
- */
-function dp_arg_load($value, $subtask, $argument) {
- require_once './' . drupal_get_path('module', 'delegator') . '/plugins/tasks/page.inc';
- return _dp_arg_load($value, $subtask, $argument);
-}
-
-/**
- * Possibly provide a default value so that variable items can appear in visible menus.
- */
-function dp_arg_to_arg($bit, $map, $index) {
-/*
- Reference code.
-
- $start = microtime();
- $introspect = debug_backtrace();
- dsm(microtime() - $start);
- foreach ($introspect as $call) {
- if ($call['function'] == '_menu_link_translate') {
- dsm(array($map, $call['args']['0']));
- }
- }
-*/
-}
-
-
-/**
- * Get the render function for a handler.
- */
-function delegator_get_renderer($handler) {
- return ctools_plugin_load_function('delegator', 'task_handlers', $handler->handler, 'render');
-}
-
-/**
- * Callback for access control ajax form on behalf of page.inc task.
- *
- * Returns the cached access config and contexts used.
- */
-function delegator_page_ctools_access_get($argument) {
- ctools_include('context');
- $task = delegator_get_task('page');
-
- require_once './' . drupal_get_path('module', 'delegator') . '/plugins/tasks/page.admin.inc';
- $page = delegator_page_get_page_cache($argument);
-
- $contexts = array();
- // Load contexts based on argument data:
- if ($arguments = _delegator_page_get_arguments($page)) {
- $contexts = ctools_context_get_placeholders_from_argument($arguments);
- }
-
- return array($page->access, $contexts);
-}
-
-/**
- * Callback for access control ajax form on behalf of page.inc task.
- *
- * Writes the changed access to the cache.
- */
-function delegator_page_ctools_access_set($argument, $access) {
- $page = delegator_page_get_page_cache($argument);
- $page->access = $access;
- delegator_page_set_page_cache($page);
-}
-
-/**
- * Callback for access control ajax form on behalf of context task handler.
- *
- * Returns the cached access config and contexts used.
- */
-function delegator_task_handler_ctools_access_get($argument) {
- ctools_include('context');
- require_once './' . drupal_get_path('module', 'delegator') . '/delegator.admin.inc';
-
- list($task_name, $name) = explode('*', $argument);
- list($task_id, $subtask_id) = delegator_get_task_id($task_name);
- $task = delegator_get_task($task_id);
- $cache = delegator_admin_get_task_cache($task, $subtask_id);
-
- $handler = delegator_admin_find_handler($name, $cache, $task_name);
-
- if (!isset($handler->conf['access'])) {
- $handler->conf['access'] = array();
- }
-
- ctools_include('context-task-handler');
-
- $contexts = ctools_context_handler_get_all_contexts($task, $subtask_id, $handler);
-
- return array($handler->conf['access'], $contexts);
-}
-
-/**
- * Callback for access control ajax form on behalf of context task handler.
- *
- * Writes the changed access to the cache.
- */
-function delegator_task_handler_ctools_access_set($argument, $access) {
- list($task_name, $name) = explode('*', $argument);
- list($task_id, $subtask_id) = delegator_get_task_id($task_name);
- $task = delegator_get_task($task_id);
- $cache = delegator_admin_get_task_cache($task, $subtask_id);
-
- $handler = delegator_admin_find_handler($name, $cache, $task_name);
-
- $handler->conf['access'] = $access;
- delegator_admin_set_task_handler_cache($handler, TRUE);
- // Make sure the cache is aware that we're editing this item:
- if (!isset($cache->working) || $cache->working != $handler->name) {
- $cache->working = $handler->name;
- delegator_admin_set_task_cache($task, $subtask_id, $cache);
- }
-}
-
-/**
- * Load a context from an argument for a given page task.
- *
- * This is used as a menu callback to translate arguments and that is why it is
- * here in the .module file.
- *
- * @param $value
- * The incoming argument value.
- * @param $subtask
- * The subtask id.
- * @param $argument
- * The numeric position of the argument in the path, counting from 0.
- *
- * @return
- * A context item if one is configured, the argument if one is not, or
- * FALSE if restricted or invalid.
- */
-function _dp_arg_load($value, $subtask, $argument) {
- $page = delegator_page_load($subtask);
- if (!$page) {
- return FALSE;
- }
-
- $path = explode('/', $page->path);
- if (empty($path[$argument])) {
- return FALSE;
- }
-
- $keyword = substr($path[$argument], 1);
- if (empty($page->arguments[$keyword])) {
- return $value;
- }
-
- $page->arguments[$keyword]['keyword'] = $keyword;
-
- ctools_include('context');
- $context = ctools_context_get_context_from_argument($page->arguments[$keyword], $value);
-
- // convert false equivalents to false.
- return $context ? $context : FALSE;
-}
-
-/**
- * Reset the active menu trail to the trail specified by the task type.
- *
- * The task type can specify an 'admin path'. If it does,
- * 'admin/build/delegator' will be removed from the active trail and replaced
- * with whatever is in the admin path; that way task types can provide
- * their own administration.
- */
-function delegator_set_trail($task, $task_name = NULL) {
- $task_type = delegator_get_task_type($task['task type']);
- if (empty($task_type['admin path'])) {
- return;
- }
-
-
- ctools_include('menu');
- $trail = menu_get_active_trail();
- $remove = ctools_get_menu_trail('admin/build/delegator');
- foreach ($remove as $info) {
- foreach ($trail as $id => $crumb) {
- if ($crumb['href'] == $info['href']) {
- unset($trail[$id]);
- }
- }
- }
-
- if ($task_name) {
- // Clean up broken 'Edit' link that Drupal leaves behind.
- $trail = array_values($trail);
- if (isset($trail[0]) && $trail[0]['title'] == t('Edit')) {
- unset($trail[0]);
- }
-
- array_unshift($trail, menu_get_item('admin/build/delegator/' . $task_name));
- }
-
- $trail = array_merge(ctools_get_menu_trail($task_type['admin path']), $trail);
- menu_set_active_trail($trail);
-}
diff --git a/delegator/images/configure.png b/delegator/images/configure.png
deleted file mode 100644
index e23d67cc04b84880d0437e23ffcba837d2dc4121..0000000000000000000000000000000000000000
Binary files a/delegator/images/configure.png and /dev/null differ
diff --git a/delegator/images/delete.png b/delegator/images/delete.png
deleted file mode 100644
index 5f0cf695b0cac487efecfd7eae66e7492a2ba306..0000000000000000000000000000000000000000
Binary files a/delegator/images/delete.png and /dev/null differ
diff --git a/delegator/js/task-handlers.js b/delegator/js/task-handlers.js
deleted file mode 100644
index 809f7effa833306b7c8ac96e4ddf1bfdb8d7538c..0000000000000000000000000000000000000000
--- a/delegator/js/task-handlers.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// $Id$
-
-Drupal.behaviors.zzGoLastDelegatorTaskList = function(context) {
- var id = 'delegator-task-list-arrange';
-
- /**
- * There's no way from PHP to tell the tabledrag code to turn on the
- * 'table has changed' code. So what we do is look for a particular
- * class and if so, invoke it. We also look to see if we should
- * hilite a particular row as the 'previous' drag.
- */
- if ($('#' + id, context).hasClass('changed') && Drupal.tableDrag[id]) {
- Drupal.tableDrag[id].changed = true;
- $(Drupal.theme('tableDragChangedWarning')).insertAfter(Drupal.tableDrag[id].table);
- if ($('#' + id + ' .delegator-changed', context).size() != 0) {
- var $row = $('#' + id + ' .delegator-changed', context);
- $row.removeClass('delegator-changed').addClass('drag-previous');
- Drupal.tableDrag[id].oldRowElement = $row;
- }
- }
-
- $('.delegator-operations select:not(.delegator-processed)', context).each(function() {
- var $select = $(this);
- var $next = $(this).parent().next('input');
- $next.hide();
- $(this).hide();
-
- $dropdown = $(this).parent().siblings('.ctools-dropdown');
-
- $('.ctools-dropdown-container a', $dropdown).click(function() {
- var val = $(this).attr('href').replace(/^.*[\/\\](\?q=)?/g, '');
-
- // ignore empty
- if (!val) {
- return false;
- }
-
- // force confirm on delete
- if (val == 'delete' && !confirm(Drupal.t('Remove this task?'))) {
- return false;
- }
-
- $select.val(val);
- $next.trigger('click');
- return false;
- });
- });
-}
-
-Drupal.Delegator = {};
-
-Drupal.Delegator.CollapsibleCallback = function($container, handle, content, toggle) {
- var $parent = $container.parents('tr.draggable');
- var id = $parent.attr('id') + '-collapse';
- if (toggle.hasClass('ctools-toggle-collapsed')) {
- // Force any other item to close, like an accordion:
- $('#delegator-task-list-arrange .ctools-toggle:not(.ctools-toggle-collapsed)').trigger('click');
- // Closed, about to be opened.
- var tr = '' . check_plain(var_export($active, 1)) . ''; + $output .= '
' . check_plain(var_export($operation, 1)) . ''; + $return = array( + 'title' => t('Test data'), + 'content' => t('If this were finished, you would see useful output here. It is not, so you do not.') . $output + ); + } + + if (isset($js_settings)) { + $return['js settings'] = $js_settings; + } + + $return['active'] = $active; + return $return; +} + +/** + * Callback generated when the add page process is finished. + */ +function page_manager_edit_page_finish(&$form_state) { + if (empty($form_state['operation']['silent'])) { + drupal_set_message(t('The page has been updated. Changes will not be permanent until you save.')); + $path = array(); + foreach ($form_state['trail'] as $operation) { + $path[] = $operation; + $form_state['page']->changes[implode('/', $path)] = TRUE; + } + } + + // If a handler was modified, set it to changed so we know to overwrite it. + if (isset($form_state['handler_id'])) { + $form_state['page']->handler_info[$form_state['handler_id']]['changed'] |= PAGE_MANAGER_CHANGED_CACHED; + } + + // While we make buttons go away on locked pages, it is still possible to + // have a lock a appear while you were editing, and have your changes + // disappear. This at least warns the user that this has happened. + if (!empty($page->locked)) { + drupal_set_message(t('Unable to update changes due to lock.')); + } + + if (empty($form_state['do not cache'])) { + page_manager_set_page_cache($form_state['page']); + } + + if (isset($form_state['new trail']) && empty($form_state['ajax'])) { + $form_state['redirect'] = 'admin/build/pages/nojs/operation/' . $form_state['page']->task_name . '/' . implode('/', $form_state['new trail']); + } +} + +/** + * Callback generated when the 'next' button is clicked. + * + * All we do here is store the cache. + */ +function page_manager_edit_page_next(&$form_state) { + page_manager_set_page_cache($form_state['page']); +} + +/** + * Callback generated when the 'cancel' button is clicked. + * + * All we do here is clear the cache. + */ +function page_manager_edit_page_cancel(&$form_state) { + return; +} + +/** + * Render an operations array. + * + * This renders an array of operations into a series of nested UL statements, + * with ajax automatically on unless specified otherwise. Operations will + * automatically have the URLs generated nested. + * + * Each operation should have a 'type', which tells the renderer how to deal + * with it: + * - 'operation': An AJAX link to render. This is the default and is + * assumed if a type is not specified. Other fields for the operation: + * - - 'title': The text to display. Can be an image. Must be pre-sanitized. + * - - 'description': Text to place in the hover box over the link using the + * title attribute. + * - - 'arguments': Anything optional to put at the end of the URL. + * - - 'path': If set, overrides the default path. + * - - 'no operations': If set, the path will not have operations appended. + * - - 'no task': If set, the path will not have the task id. + * - - 'no link': If set, this item will just be text, not a link. + * - - 'ajax': If set to TRUE, ajax will be used. The default is TRUE. + * - - 'class': An optional class to specify for the link. + * - - 'form': The form to display for this operation, if using a single form. + * - - 'forms': An array of forms that must be paired with 'order' of this + * operation uses multiple forms. See wizard tool for details. + * - - 'order': The form order to use for multiple forms. See wizard tool for + * details. + * - - 'form info': Form info overrides for the wizard. See the wizard tool + * for available settings + * - 'group': + * - - 'title': The title of the link. May be HTML. + * - - 'title class': A class to apply to the title. + * - - 'children': An array of more operations that this group represents. + * All operations within this group will have this group's ID as part + * of the AJAX url to make it easier to find. + * - - 'class': A class to apply to the UL of the children. + * - - 'collapsible': If TRUE the collapsible tool will be used. + */ +function page_manager_render_operations(&$page, $operations, $active_trail, $attributes, $location, $parents = array()) { + if (!isset($output[$location])) { + $output[$location] = ''; + } + + $keys = array_keys($operations); + $first = array_shift($keys); + $last = array_pop($keys); + + // Make sure the 'first' and 'last' operations are part of THIS nav tree: + while ($keys && isset($operations[$first]['location']) && $operations[$first]['location'] != $location) { + $first = array_shift($keys); + } + while ($keys && isset($operations[$last]['location']) && $operations[$last]['location'] != $location) { + $last = array_pop($keys); + } + + $active = reset($active_trail); + foreach ($operations as $id => $operation) { + $current_path = ''; + if ($parents) { + $current_path .= implode('/', $parents) . '/'; + } + $current_path .= $id; + + if (empty($operation['type'])) { + $operation['type'] = 'operation'; + } + + // We only render an li for things in the same nav tree. + if (empty($operation['location']) || $operation['location'] == $location) { + $class = $attributes['class']; + if ($id == $first) { + $class .= ' operation-first'; + } + else if ($id == $last) { + $class .= ' operation-last'; + } + + if (empty($operation['silent']) && !empty($page->changes[$current_path])) { + $class .= $operation['type'] == 'group' ? ' changed-group' : ' changed'; + } + else { + $class .= ' not-changed'; + } + + if ($active == $id) { + $class .= $operation['type'] == 'group' ? ' active-group' : ' active'; + } + else { + $class .= ' not-active'; + } + + $output[$location] .= '
' . $text . '
', + ); + +} + +/** + * Submit handler to delete a view. + */ +function page_manager_handler_delete_submit(&$form, &$form_state) { + $form_state['page']->handler_info[$form_state['handler_id']]['changed'] |= PAGE_MANAGER_CHANGED_DELETED; + $form_state['new trail'] = array('summary'); +} + +/** + * Entry point to export a page. + */ +function page_manager_handler_export(&$form, &$form_state) { + $export = page_manager_export_task_handler($form_state['handler']); + + $lines = substr_count($export, "\n"); + $form['code'] = array( + '#type' => 'textarea', + '#default_value' => $export, + '#rows' => $lines, + ); + + unset($form['buttons']); +} + +/** + * Rearrange the order of variants. + */ +function page_manager_handler_clone(&$form, &$form_state) { + // This provides its own button because it does something totally different. + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Variant name'), + '#description' => t('Enter the name of the new variant.'), + ); +} + +/** + * Clone an existing task handler into a new handler. + */ +function page_manager_handler_clone_submit($form, &$form_state) { + $handler = $form_state['handler']; + page_manager_handler_add_to_page($form_state['page'], $handler, $form_state['values']['title']); + + $plugin = page_manager_get_task_handler($handler->handler); + // It has no forms at all. Add the variant and go to its first operation. + $keys = array_keys($plugin['operations']); + $form_state['new trail'] = array('handlers', $name, reset($keys)); +} + +/** + * Form to enable a handler. + */ +function page_manager_handler_enable(&$form, &$form_state) { + $form['markup'] = array( + '#value' => t('This variant is currently disabled. Enabling it will make it available in your system. This will not take effect until you save this page.'), + ); +} + +/** + * Enable the page after it has been confirmed. + */ +function page_manager_handler_enable_submit(&$form, &$form_state) { + $form_state['handler']->disabled = FALSE; + $form_state['page']->handler_info[$form_state['handler_id']]['disabled'] = FALSE; + $form_state['page']->handler_info[$form_state['handler_id']]['changed'] |= PAGE_MANAGER_CHANGED_STATUS; + $form_state['new trail'] = array('handlers', $form_state['handler_id'], 'disable'); +} + +/** + * Form to disable a page. + */ +function page_manager_handler_disable(&$form, &$form_state) { + $form['markup'] = array( + '#value' => t('This variant is currently enabled. Disabling it will make it unavailable in your system, and it will not be used. This will not take effect until you save this page.'), + ); +} + +/** + * Form to disable a page. + */ +function page_manager_handler_summary(&$form, &$form_state) { + $handler = $form_state['handler']; + $page = $form_state['page']; + $plugin = page_manager_get_task_handler($handler->handler); + + $form['markup'] = array( + '#value' => page_manager_get_handler_summary($plugin, $handler, $page->task, $page->subtask_id), + ); +} + +/** + * Disable the page after it has been confirmed. + */ +function page_manager_handler_disable_submit(&$form, &$form_state) { + $form_state['handler']->disabled = TRUE; + $form_state['page']->handler_info[$form_state['handler_id']]['disabled'] = TRUE; + $form_state['page']->handler_info[$form_state['handler_id']]['changed'] |= PAGE_MANAGER_CHANGED_STATUS; + $form_state['new trail'] = array('handlers', $form_state['handler_id'], 'enable'); +} + +/** + * Break the lock on a page so that it can be edited. + */ +function page_manager_break_lock(&$form, &$form_state) { + $form['markup'] = array( + '#value' => t('Breaking the lock on this page will discard any pending changes made by the locking user. Are you REALLY sure you want to do this?') + ); +} + +/** + * Submit to break the lock on a page. + */ +function page_manager_break_lock_submit(&$form, &$form_state) { + $page = &$form_state['page']; + $form_state['page']->locked = FALSE; + ctools_object_cache_clear_all('page_manager_page', $page->task_name); + $form_state['do not cache'] = TRUE; + $form_state['new trail'] = array('summary'); + drupal_set_message(t('The lock has been cleared and all changes discarded. You may now make changes to this page.')); +} + +/** + * Print the summary information for a page. + */ +function page_manager_page_summary(&$form, &$form_state) { + $page = $form_state['page']; + if (isset($form_state['subtask']['description'])) { + $form['description'] = array( + '#value' => filter_xss_admin($form_state['subtask']['description']), + ); + } +} \ No newline at end of file diff --git a/page_manager/page_manager.info b/page_manager/page_manager.info new file mode 100644 index 0000000000000000000000000000000000000000..b0a573e8d05a556296fa0ab6d932f101be15f0be --- /dev/null +++ b/page_manager/page_manager.info @@ -0,0 +1,5 @@ +; $Id$ +name = Page manager +description = Provides a UI and API to manage pages within the site. +core = 6.x +dependencies[] = ctools diff --git a/page_manager/page_manager.install b/page_manager/page_manager.install new file mode 100644 index 0000000000000000000000000000000000000000..81dd65fbcc55fac95040c9f58de55ef356cc6ed7 --- /dev/null +++ b/page_manager/page_manager.install @@ -0,0 +1,217 @@ + array( + 'identifier' => 'handler', + 'api' => array( + 'owner' => 'page_manager', + 'api' => 'pages_default', + 'minimum_version' => 1, + 'current_version' => 1, + ), + ), + 'fields' => array( + 'did' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'Primary ID field for the table. Not used for anything except internal lookups.', + 'no export' => TRUE, + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '255', + 'description' => 'Unique ID for this task handler. Used to identify it programmatically.', + ), + 'task' => array( + 'type' => 'varchar', + 'length' => '64', + 'description' => 'ID of the task this handler is for.', + ), + 'subtask' => array( + 'type' => 'varchar', + 'length' => '64', + 'description' => 'ID of the subtask this handler is for.', + 'not null' => TRUE, + 'default' => '', + ), + 'handler' => array( + 'type' => 'varchar', + 'length' => '64', + 'description' => 'ID of the task handler being used.', + ), + 'weight' => array( + 'type' => 'int', + 'description' => 'The order in which this handler appears. Lower numbers go first.', + ), + 'conf' => array( + 'type' => 'text', + 'size' => 'big', + 'description' => 'Serialized configuration of the handler, if needed.', + 'not null' => TRUE, + 'serialize' => TRUE, + 'object default' => array(), + ), + ), + 'primary key' => array('did'), + 'unique keys' => array( + 'name' => array('name'), + ), + 'indexes' => array('fulltask' => array('task', 'subtask', 'weight')), + ); + + $schema['page_manager_weights'] = array( + 'description' => 'Contains override weights for page_manager handlers that are in code.', + 'fields' => array( + 'name' => array( + 'type' => 'varchar', + 'length' => '255', + 'description' => 'Unique ID for this task handler. Used to identify it programmatically.', + 'not null' => TRUE, + 'default' => '', + ), + 'weight' => array( + 'type' => 'int', + 'description' => 'The order in which this handler appears. Lower numbers go first.', + ), + ), + 'primary key' => array('name'), + 'indexes' => array( + 'weights' => array('name', 'weight'), + ), + ); + + $schema['page_manager_pages'] = array( + 'description' => 'Contains page subtasks for implementing pages with arbitrary tasks.', + 'export' => array( + 'identifier' => 'page', + 'api' => array( + 'owner' => 'page_manager', + 'api' => 'pages_default', + 'minimum_version' => 1, + 'current_version' => 1, + ), + ), + 'fields' => array( + 'pid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'Primary ID field for the table. Not used for anything except internal lookups.', + 'no export' => TRUE, + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '255', + 'description' => 'Unique ID for this subtask. Used to identify it programmatically.', + ), + 'task' => array( + 'type' => 'varchar', + 'length' => '64', + 'description' => 'What type of page this is, so that we can use the same mechanism for creating tighter UIs for targeted pages.', + 'default' => 'page', + ), + 'admin_title' => array( + 'type' => 'varchar', + 'length' => '255', + 'description' => 'Human readable title for this page subtask.', + ), + 'path' => array( + 'type' => 'varchar', + 'length' => '255', + 'description' => 'The menu path that will invoke this task.', + ), + 'access' => array( + 'type' => 'text', + 'size' => 'big', + 'description' => 'Access configuration for this path.', + 'not null' => TRUE, + 'serialize' => TRUE, + 'object default' => array(), + ), + 'menu' => array( + 'type' => 'text', + 'size' => 'big', + 'description' => 'Serialized configuration of Drupal menu visibility settings for this item.', + 'not null' => TRUE, + 'serialize' => TRUE, + 'object default' => array(), + ), + 'arguments' => array( + 'type' => 'text', + 'size' => 'big', + 'description' => 'Configuration of arguments for this menu item.', + 'not null' => TRUE, + 'serialize' => TRUE, + 'object default' => array(), + ), + 'conf' => array( + 'type' => 'text', + 'size' => 'big', + 'description' => 'Serialized configuration of the page, if needed.', + 'not null' => TRUE, + 'serialize' => TRUE, + 'object default' => array(), + ), + ), + 'primary key' => array('pid'), + 'unique keys' => array( + 'name' => array('name'), + ), + 'indexes' => array('task' => array('task')), + ); + + return $schema; +} + +/** + * Implementation of hook_install(). + */ +function page_manager_install() { + drupal_install_schema('page_manager'); + + // If we're swapping over from delegator module, take away its tables. + // Take THAT, delegator! + if (db_table_exists('{delegator_pages}')) { + db_query("INSERT INTO {page_manager_pages} (SELECT pid, name, task, admin_title, path, access, menu, arguments, conf FROM {delegator_pages})"); + db_query("INSERT INTO {page_manager_handlers} (SELECT * FROM {delegator_handlers})"); + db_query("INSERT INTO {page_manager_weights} (SELECT * FROM {delegator_weights})"); + + db_drop_table('{delegator_pages}'); + db_drop_table('{delegator_handlers}'); + db_drop_table('{delegator_weights}'); + } + + db_query("UPDATE {system} SET weight = 99 WHERE name = 'page_manager'"); +} + +/** + * Implementation of hook_uninstall(). + */ +function page_manager_uninstall() { + drupal_uninstall_schema('page_manager'); +} + +function page_manager_update_6101() { + $ret = array(); + return $ret; +} diff --git a/page_manager/page_manager.module b/page_manager/page_manager.module new file mode 100644 index 0000000000000000000000000000000000000000..09257051fe08adba44329e238503de1514b0355d --- /dev/null +++ b/page_manager/page_manager.module @@ -0,0 +1,884 @@ + array('use page manager'), + 'file' => 'page_manager.admin.inc', + ); + + $items['admin/build/pages'] = array( + 'title' => 'Pages', + 'description' => 'Add, edit and remove overridden system pages and user defined pages from the system.', + 'page callback' => 'page_manager_list_page', + ) + $base; + + $items['admin/build/pages/list'] = array( + 'title' => 'List', + 'page callback' => 'page_manager_list_page', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ) + $base; + + $items['admin/build/pages/edit/%page_manager_cache'] = array( + 'title' => 'Edit', + 'page callback' => 'page_manager_edit_page', + 'page arguments' => array(4), + 'type' => MENU_CALLBACK, + ) + $base; + + $items['admin/build/pages/%ctools_js/operation/%page_manager_cache'] = array( + 'page callback' => 'page_manager_edit_page_operation', + 'page arguments' => array(3, 5), + 'type' => MENU_CALLBACK, + ) + $base; + + $tasks = page_manager_get_tasks(); + + // Provide menu items for each task. + foreach ($tasks as $task_id => $task) { + $handlers = page_manager_get_task_handler_plugins($task); + // Allow the task to add its own menu items. + if ($function = ctools_plugin_get_function($task, 'hook menu')) { + $function($items, $task); + } + + // And for those that provide subtasks, provide menu items for them, as well. + foreach (page_manager_get_task_subtasks($task) as $subtask_id => $subtask) { + // Allow the task to add its own menu items. + if ($function = ctools_plugin_get_function($task, 'hook menu')) { + $function($items, $subtask); + } + } + } + + return $items; +} + +/** + * Implementation of hook_menu_alter. + * + * Get a list of all tasks and delegate to them. + */ +function page_manager_menu_alter(&$items) { + $tasks = page_manager_get_tasks(); + + foreach ($tasks as $task) { + if ($function = ctools_plugin_get_function($task, 'hook menu alter')) { + $function($items, $task); + } + // let the subtasks alter the menu items too. + foreach (page_manager_get_task_subtasks($task) as $subtask_id => $subtask) { + if ($function = ctools_plugin_get_function($subtask, 'hook menu alter')) { + $function($items, $subtask); + } + } + } + + return $items; +} + +/* + * Implementation of hook_theme() + */ +function page_manager_theme() { + $base = array( + 'path' => drupal_get_path('module', 'page_manager') . '/theme', + 'file' => 'page_manager.theme.inc', + ); + + $items = array( + 'page_manager_list_pages_form' => array( + 'arguments' => array('form' => NULL), + ) + $base, + 'page_manager_handler_rearrange' => array( + 'arguments' => array('form' => NULL), + ) + $base, + 'page_manager_edit_page' => array( + 'template' => 'page-manager-edit-page', + 'arguments' => array('page' => NULL, 'save' => NULL, 'operations' => array(), 'content' => array()), + ) + $base, + 'page_manager_lock' => array( + 'arguments' => array('page' => array()), + ) + $base, + 'page_manager_changed' => array( + 'arguments' => array('text' => NULL, 'description' => NULL), + ) + $base, + ); + + // Allow task plugins to have theme registrations by passing through: + $tasks = page_manager_get_tasks(); + + // Provide menu items for each task. + foreach ($tasks as $task_id => $task) { + if ($function = ctools_plugin_get_function($task, 'hook theme')) { + $function($items, $task); + } + } + + return $items; +} + +// -------------------------------------------------------------------------- +// Page caching +// +// The page cache is used to store a page temporarily, using the ctools object +// cache. When loading from the page cache, it will either load the cached +// version, or if there is not one, load the real thing and create a cache +// object which can then be easily stored. + +/** + * Get the cached changes to a given task handler. + */ +function page_manager_get_page_cache($task_name) { + ctools_include('object-cache'); + $cache = ctools_object_cache_get('page_manager_page', $task_name); + if (!$cache) { + $cache = new stdClass(); + $cache->task_name = $task_name; + list($cache->task_id, $cache->subtask_id) = page_manager_get_task_id($cache->task_name); + + $cache->task = page_manager_get_task($cache->task_id); + if (empty($cache->task)) { + return FALSE; + } + + if ($cache->subtask_id) { + $cache->subtask = page_manager_get_task_subtask($cache->task, $cache->subtask_id); + if (empty($cache->subtask)) { + return FALSE; + } + } + else { + $cache->subtask = $cache->task; + } + + $cache->handlers = page_manager_load_sorted_handlers($cache->task, $cache->subtask_id); + $cache->handler_info = array(); + foreach ($cache->handlers as $id => $handler) { + $cache->handler_info[$id] = array( + 'weight' => $handler->weight, + 'changed' => FALSE, + 'name' => $id, + ); + } + } + else { + // ensure the task is loaded. + page_manager_get_task($cache->task_id); + } + + if ($task_name != '::new') { + $cache->locked = ctools_object_cache_test('page_manager_page', $task_name); + } + else { + $cache->locked = FALSE; + } + + return $cache; +} + +/** + * Store changes to a task handler in the object cache. + */ +function page_manager_set_page_cache($page) { + if (!empty($page->locked)) { + return; + } + + if (empty($page->task_name)) { + return; + } + + ctools_include('object-cache'); + $page->changed = TRUE; + $cache = ctools_object_cache_set('page_manager_page', $page->task_name, $page); +} + +/** + * Remove an item from the object cache. + */ +function page_manager_clear_page_cache($name) { + ctools_include('object-cache'); + ctools_object_cache_clear('page_manager_page', $name); +} + +/** + * Write all changes from the page cache and clear it out. + */ +function page_manager_save_page_cache($cache) { + // Save the subtask: + if ($function = ctools_plugin_get_function($cache->task, 'save subtask callback')) { + $function($cache->subtask); + } + + // Iterate through handlers and save/delete/update as necessary. + // Go through each of the task handlers, check to see if it needs updating, + // and update it if so. + foreach ($cache->handler_info as $id => $info) { + $handler = &$cache->handlers[$id]; + // If it has been marked for deletion, delete it. + + if ($info['changed'] & PAGE_MANAGER_CHANGED_DELETED) { + page_manager_delete_task_handler($handler); + } + // If it has been somehow edited (or added), write the cached version + elseif ($info['changed'] & PAGE_MANAGER_CHANGED_CACHED) { + // Make sure we get updated weight from the form for this. + $handler->weight = $info['weight']; + page_manager_save_task_handler($handler); + } + // Otherwise, check to see if it has moved and, if so, update the weight. + elseif ($info['weight'] != $handler->weight) { + // Theoretically we could only do this for in code objects, but since our + // load mechanism checks for all, this is less database work. + page_manager_update_task_handler_weight($handler, $info['weight']); + } + + // Set enable/disabled status. + if ($info['changed'] & PAGE_MANAGER_CHANGED_STATUS) { + ctools_include('export'); + ctools_export_set_object_status($cache->handlers[$id], $info['disabled']); + } + } + + page_manager_clear_page_cache($cache->task_name); + + if (!empty($cache->path_changed) || !empty($cache->new)) { + // Force a menu rebuild to make sure the menu entries are set. + menu_rebuild(); + } +} + +/** + * Menu callback to load a page manager cache object for menu callbacks. + */ +function page_manager_cache_load($task_name) { + return page_manager_get_page_cache($task_name); +} + +/** + * Generate a unique name for a task handler. + * + * Task handlers need to be named but they aren't allowed to set their own + * names. Instead, they are named based upon their parent task and type. + */ +function page_manager_handler_get_name($task_name, $handlers, $handler) { + $base = str_replace('-', '_', $task_name); + // Generate a unique name. Unlike most named objects, we don't let people choose + // names for task handlers because they mostly don't make sense. + $base .= '_' . $handler->handler; + + // Once we have a base, check to see if it is used. If it is, start counting up. + $name = $base; + $count = 1; + // If taken + while (isset($handlers[$name])) { + $name = $base . '_' . ++$count; + } + + return $name; +} + +/** + * Import a handler into a page. + * + * This is used by both import and clone, since clone just exports the + * handler and immediately imports it. + */ +function page_manager_handler_add_to_page(&$page, $handler, $title = NULL) { + $last = end($page->handler_info); + $handler->weight = $last ? $last['weight'] + 1 : 0; + $handler->task = $page->task_id; + $handler->subtask = $page->subtask_id; + $handler->export_type = EXPORT_IN_DATABASE; + $handler->type = t('Normal'); + + if ($title) { + $handler->conf['title'] = $title; + } + + $name = page_manager_handler_get_name($page->task_name, $page->handlers, $handler); + + $handler->name = $name; + + $page->handlers[$name] = $handler; + $page->handler_info[$name] = array( + 'weight' => $handler->weight, + 'name' => $handler->name, + 'changed' => PAGE_MANAGER_CHANGED_CACHED, + ); +} + +// -------------------------------------------------------------------------- +// Database routines +// +// This includes fetching plugins and plugin info as well as specialized +// fetch methods to get groups of task handlers per task. + +/** + * Load a single task handler by name. + * + * Handlers can come from multiple sources; either the database or by normal + * export method, which is handled by the ctools library, but handlers can + * also be bundled with task/subtask. We have to check there and perform + * overrides as appropriate. + * + * Handlers bundled with the task are of a higher priority than default + * handlers provided by normal code, and are of a lower priority than + * the database, so we have to check the source of handlers when we have + * multiple to choose from. + */ +function page_manager_load_task_handler($task, $subtask_id, $name) { + ctools_include('export'); + $result = ctools_export_load_object('delegator_handlers', 'names', array($name)); + $handlers = page_manager_get_default_task_handlers($task, $subtask_id); + return page_manager_compare_task_handlers($result, $handlers, $name); +} + +/** + * Load all task handlers for a given task/subtask. + */ +function page_manager_load_task_handlers($task, $subtask_id = NULL, $default_handlers = NULL) { + ctools_include('export'); + $conditions = array( + 'task' => $task['name'], + ); + + if (isset($subtask_id)) { + $conditions['subtask'] = $subtask_id; + } + + $handlers = ctools_export_load_object('delegator_handlers', 'conditions', $conditions); + $defaults = isset($default_handlers) ? $default_handlers : page_manager_get_default_task_handlers($task, $subtask_id); + foreach ($defaults as $name => $default) { + $result = page_manager_compare_task_handlers($handlers, $defaults, $name); + + if ($result) { + $handlers[$name] = $result; + // Ensure task and subtask are correct, because it's easy to change task + // names when editing a default and fail to do it on the associated handlers. + $result->task = $task['name']; + $result->subtask = $subtask_id; + } + } + + // Override weights from the weight table. + if ($handlers) { + $names = array(); + $placeholders = array(); + foreach ($handlers as $handler) { + $names[] = $handler->name; + $placeholders[] = "'%s'"; + } + + $result = db_query("SELECT name, weight FROM {delegator_weights} WHERE name IN (" . implode(', ', $placeholders) . ")", $names); + while ($weight = db_fetch_object($result)) { + $handlers[$weight->name]->weight = $weight->weight; + } + } + + return $handlers; +} + +/** + * Get the default task handlers from a task, if they exist. + * + * Tasks can contain 'default' task handlers which are provided by the + * default task. Because these can come from either the task or the + * subtask, the logic is abstracted to reduce code duplication. + */ +function page_manager_get_default_task_handlers($task, $subtask_id) { + // Load default handlers that are provied by the task/subtask itself. + $handlers = array(); + if ($subtask_id) { + $subtask = page_manager_get_task_subtask($task, $subtask_id); + if (isset($subtask['default handlers'])) { + $handlers = $subtask['default handlers']; + } + } + else if (isset($task['default handlers'])) { + $handlers = $task['default handlers']; + } + + return $handlers; +} + +/** + * Compare a single task handler from two lists and provide the correct one. + * + * Task handlers can be gotten from multiple sources. As exportable objects, + * they can be provided by default hooks and the database. But also, because + * they are tightly bound to tasks, they can also be provided by default + * tasks. This function reconciles where to pick up a task handler between + * the exportables list and the defaults provided by the task itself. + * + * @param $result + * A list of handlers provided by export.inc + * @param $handlers + * A list of handlers provided by the default task. + * @param $name + * Which handler to compare. + * @return + * Which handler to use, if any. May be NULL. + */ +function page_manager_compare_task_handlers($result, $handlers, $name) { + // Compare our special default handler against the actual result, if + // any, and do the right thing. + if (!isset($result[$name]) && isset($handlers[$name])) { + $handlers[$name]->type = t('Default'); + $handlers[$name]->export_type = EXPORT_IN_CODE; + return $handlers[$name]; + } + else if (isset($result[$name]) && !isset($handlers[$name])) { + return $result[$name]; + } + else if (isset($result[$name]) && isset($handlers[$name])) { + if ($result[$name]->export_type & EXPORT_IN_DATABASE) { + $result[$name]->type = t('Overridden'); + $result[$name]->export_type = $result[$name]->export_type | EXPORT_IN_CODE; + return $result[$name]; + } + else { + // In this case, our default is a higher priority than the standard default. + $handlers[$name]->type = t('Default'); + $handlers[$name]->export_type = EXPORT_IN_CODE; + return $handlers[$name]; + } + } +} + +/** + * Load all task handlers for a given task and subtask and sort them. + */ +function page_manager_load_sorted_handlers($task, $subtask_id = NULL, $enabled = FALSE) { + $handlers = page_manager_load_task_handlers($task, $subtask_id); + if ($enabled) { + foreach ($handlers as $id => $handler) { + if (!empty($handler->disabled)) { + unset($handlers[$id]); + } + } + } + uasort($handlers, 'page_manager_sort_task_handlers'); + return $handlers; +} + +/** + * Callback for uasort to sort task handlers. + * + * Task handlers are sorted by weight then by name. + */ +function page_manager_sort_task_handlers($a, $b) { + if ($a->weight < $b->weight) { + return -1; + } + elseif ($a->weight > $b->weight) { + return 1; + } + elseif ($a->name < $b->name) { + return -1; + } + elseif ($a->name > $b->name) { + return 1; + } + + return 0; +} + +/** + * Write a task handler to the database. + */ +function page_manager_save_task_handler(&$handler) { + $update = (isset($handler->did)) ? array('did') : array(); + // Let the task handler respond to saves: + if ($function = ctools_plugin_load_function('page_manager', 'task_handlers', $handler->handler, 'save')) { + $function($handler, $update); + } + + drupal_write_record('delegator_handlers', $handler, $update); + db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name); + + // If this was previously a default handler, we may have to write task handlers. + if (!$update) { + // @todo wtf was I going to do here? + } + return $handler; +} + +/** + * Remove a task handler. + */ +function page_manager_delete_task_handler($handler) { + // Let the task handler respond to saves: + if ($function = ctools_plugin_load_function('page_manager', 'task_handlers', $handler->handler, 'delete')) { + $function($handler); + } + db_query("DELETE FROM {delegator_handlers} WHERE name = '%s'", $handler->name); + db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name); +} + +/** + * Export a task handler into code suitable for import or use as a default + * task handler. + */ +function page_manager_export_task_handler($handler, $indent = '') { + ctools_include('export'); + ctools_include('plugins'); + $handler = drupal_clone($handler); + + $append = ''; + if ($function = ctools_plugin_load_function('page_manager', 'task_handlers', $handler->handler, 'export')) { + $append = $function($handler, $indent); + } + + $output = ctools_export_object('delegator_handlers', $handler, $indent); + $output .= $append; + + return $output; +} + +/** + * Create a new task handler object. + * + * @param $plugin + * The plugin this task handler is created from. + */ +function page_manager_new_task_handler($plugin) { + // Generate a unique name. Unlike most named objects, we don't let people choose + // names for task handlers because they mostly don't make sense. + + // Create a new, empty handler object. + $handler = new stdClass; + $handler->title = $plugin['title']; + $handler->task = NULL; + $handler->subtask = NULL; + $handler->name = NULL; + $handler->handler = $plugin['name']; + $handler->weight = 0; + $handler->conf = array(); + + // These are provided by the core export API provided by ctools and we + // set defaults here so that we don't cause notices. Perhaps ctools should + // provide a way to do this for us so we don't have to muck with it. + $handler->export_type = EXPORT_IN_DATABASE; + $handler->type = t('Local'); + + if (isset($plugin['default conf'])) { + if (is_array($plugin['default conf'])) { + $handler->conf = $plugin['default conf']; + } + else if (function_exists($plugin['default conf'])) { + $handler->conf = $plugin['default conf']($handler); + } + } + + return $handler; +} + +/** + * Set an overidden weight for a task handler. + * + * We do this so that in-code task handlers don't need to get written + * to the database just because they have their weight changed. + */ +function page_manager_update_task_handler_weight($handler, $weight) { + db_query("DELETE FROM {delegator_weights} WHERE name = '%s'", $handler->name); + db_query("INSERT INTO {delegator_weights} (name, weight) VALUES ('%s', %d)", $handler->name, $weight); +} + + +/** + * Shortcut function to get task plugins. + */ +function page_manager_get_tasks() { + ctools_include('plugins'); + return ctools_get_plugins('page_manager', 'tasks'); +} + +/** + * Shortcut function to get a task plugin. + */ +function page_manager_get_task($id) { + ctools_include('plugins'); + return ctools_get_plugins('page_manager', 'tasks', $id); +} + +/** + * Get all tasks for a given type. + */ +function page_manager_get_tasks_by_type($type) { + ctools_include('plugins'); + $all_tasks = ctools_get_plugins('page_manager', 'tasks'); + $tasks = array(); + foreach ($all_tasks as $id => $task) { + if (isset($task['task type']) && $task['task type'] == $type) { + $tasks[$id] = $task; + } + } + + return $tasks; +} + +/** + * Fetch all subtasks for a page managertask. + * + * @param $task + * A loaded $task plugin object. + */ +function page_manager_get_task_subtasks($task) { + if (empty($task['subtasks'])) { + return array(); + } + + if ($function = ctools_plugin_get_function($task, 'subtasks callback')) { + return $function($task); + } +} + +/** + * Fetch all subtasks for a page managertask. + * + * @param $task + * A loaded $task plugin object. + * @param $subtask_id + * The subtask ID to load. + */ +function page_manager_get_task_subtask($task, $subtask_id) { + if (empty($task['subtasks'])) { + return; + } + + if ($function = ctools_plugin_get_function($task, 'subtask callback')) { + return $function($task, $subtask_id); + } +} + +/** + * Shortcut function to get task handler plugins. + */ +function page_manager_get_task_handlers() { + ctools_include('plugins'); + return ctools_get_plugins('page_manager', 'task_handlers'); +} + +/** + * Shortcut function to get a task handler plugin. + */ +function page_manager_get_task_handler($id) { + ctools_include('plugins'); + return ctools_get_plugins('page_manager', 'task_handlers', $id); +} + +/** + * Retrieve a list of all applicable task handlers for a given task. + * + * This looks at the $task['handler type'] and compares that to $task_handler['handler type']. + * If the task has no type, the id of the task is used instead. + */ +function page_manager_get_task_handler_plugins($task, $all = FALSE) { + $type = isset($task['handler type']) ? $task['handler type'] : $task['name']; + $name = $task['name']; + + $handlers = array(); + $task_handlers = page_manager_get_task_handlers(); + foreach ($task_handlers as $id => $handler) { + $task_type = is_array($handler['handler type']) ? $handler['handler type'] : array($handler['handler type']); + if (in_array($type, $task_type) || in_array($name, $task_type)) { + if ($all || !empty($handler['visible'])) { + $handlers[$id] = $handler; + } + } + } + + return $handlers; +} + +/** + * Get the title for a given handler. + * + * If the plugin has no 'admin title' function, the generic title of the + * plugin is used instead. + */ +function page_manager_get_handler_title($plugin, $handler, $task, $subtask_id) { + $function = ctools_plugin_get_function($plugin, 'admin title'); + if ($function) { + return $function($handler, $task, $subtask_id); + } + else { + return $plugin['title']; + } +} + +/** + * Get the admin summary (additional info) for a given handler. + */ +function page_manager_get_handler_summary($plugin, $handler, $task, $subtask_id) { + if ($function = ctools_plugin_get_function($plugin, 'admin summary')) { + return $function($handler, $task, $subtask_id); + } +} + +/** + * Split a task name into a task id and subtask id, if applicable. + */ +function page_manager_get_task_id($task_name) { + if (strpos($task_name, '-') !== FALSE) { + return explode('-', $task_name, 2); + } + else { + return array($task_name, NULL); + } +} + +/** + * Turn a task id + subtask_id into a task name. + */ +function page_manager_make_task_name($task_id, $subtask_id) { + if ($subtask_id) { + return $task_id . '-' . $subtask_id; + } + else { + return $task_id; + } +} + +/** + * Get the render function for a handler. + */ +function page_manager_get_renderer($handler) { + return ctools_plugin_load_function('page_manager', 'task_handlers', $handler->handler, 'render'); +} + +// -------------------------------------------------------------------------- +// Functions existing on behalf of tasks and task handlers + + +/** + * Page managerfor arg load function because menu system will not load extra + * files for these; they must be in a .module. + */ +function pm_arg_load($value, $subtask, $argument) { + page_manager_get_task('page'); + return _pm_arg_load($value, $subtask, $argument); +} + +/** + * Callback for access control ajax form on behalf of page.inc task. + * + * Returns the cached access config and contexts used. + */ +function page_manager_page_ctools_access_get($argument) { + $page = page_manager_get_page_cache($argument); + + $contexts = array(); + + // Load contexts based on argument data: + if ($arguments = _page_manager_page_get_arguments($page->subtask['subtask'])) { + $contexts = ctools_context_get_placeholders_from_argument($arguments); + } + + return array($page->subtask['subtask']->access, $contexts); +} + +/** + * Callback for access control ajax form on behalf of page.inc task. + * + * Writes the changed access to the cache. + */ +function page_manager_page_ctools_access_set($argument, $access) { + $page = page_manager_get_page_cache($argument); + $page->subtask['subtask']->access = $access; + page_manager_set_page_cache($page); +} + +/** + * Callback for access control ajax form on behalf of context task handler. + * + * Returns the cached access config and contexts used. + */ +function page_manager_task_handler_ctools_access_get($argument) { + list($task_name, $name) = explode('*', $argument); + $page = page_manager_get_page_cache($task_name); + $handler = &$page->handlers[$name]; + + if (!isset($handler->conf['access'])) { + $handler->conf['access'] = array(); + } + + ctools_include('context-task-handler'); + + $contexts = ctools_context_handler_get_all_contexts($page->task, $page->subtask, $handler); + + return array($handler->conf['access'], $contexts); +} + +/** + * Callback for access control ajax form on behalf of context task handler. + * + * Writes the changed access to the cache. + */ +function page_manager_task_handler_ctools_access_set($argument, $access) { + list($task_name, $name) = explode('*', $argument); + $page = page_manager_get_page_cache($task_name); + $handler = &$page->handlers[$name]; + + $handler->conf['access'] = $access; + page_manager_set_page_cache($page); +} + diff --git a/delegator/plugins/tasks/node_edit.inc b/page_manager/plugins/tasks/node_edit.inc similarity index 70% rename from delegator/plugins/tasks/node_edit.inc rename to page_manager/plugins/tasks/node_edit.inc index cb4e0fcfe613b7e807dde63cece6fa0ad16f5167..29526cd94ba70ec9b60d99537dc34466afb3204d 100644 --- a/delegator/plugins/tasks/node_edit.inc +++ b/page_manager/plugins/tasks/node_edit.inc @@ -2,10 +2,10 @@ // $Id$ /** - * Specialized implementation of hook_delegator_tasks(). See api-task.html for + * Specialized implementation of hook_page_manager_task_tasks(). See api-task.html for * more information. */ -function delegator_node_edit_delegator_tasks() { +function page_manager_node_edit_page_manager_tasks() { return array( // This is a 'page' task and will fall under the page admin UI 'task type' => 'page', @@ -16,31 +16,31 @@ function delegator_node_edit_delegator_tasks() { 'admin description' => 'Overrides for the built in node edit handler at node/%node/edit.', 'admin path' => 'node/%node/edit', - // Callback to add items to the delegator task administration form: - 'task admin' => 'delegator_node_edit_task_admin', + // Callback to add items to the page managertask administration form: + 'task admin' => 'page_manager_node_edit_task_admin', // 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', + 'hook menu' => 'page_manager_node_edit_menu', + 'hook menu alter' => 'page_manager_node_edit_menu_alter', // This is task uses 'context' handlers and must implement these to give the // handler data it needs. 'handler type' => 'context', - 'get arguments' => 'delegator_node_edit_get_arguments', - 'get context placeholders' => 'delegator_node_edit_get_contexts', + 'get arguments' => 'page_manager_node_edit_get_arguments', + 'get context placeholders' => 'page_manager_node_edit_get_contexts', ); } /** - * Callback defined by delegator_node_edit_delegator_tasks(). + * Callback defined by page_manager_node_edit_page_manager_tasks(). * * Alter the node edit input so that node edit comes to us rather than the * normal node edit process. */ -function delegator_node_edit_menu_alter(&$items, $task) { +function page_manager_node_edit_menu_alter(&$items, $task) { // Override the node edit handler for our purpose. - if ($items['node/%node/edit']['page callback'] == 'node_page_edit' || variable_get('delegator_override_anyway', FALSE)) { - $items['node/%node/edit']['page callback'] = 'delegator_node_edit'; + if ($items['node/%node/edit']['page callback'] == 'node_page_edit' || variable_get('page_manager_override_anyway', FALSE)) { + $items['node/%node/edit']['page callback'] = 'page_manager_node_edit'; $items['node/%node/edit']['file path'] = $task['path']; $items['node/%node/edit']['file'] = $task['file']; } @@ -52,7 +52,7 @@ function delegator_node_edit_menu_alter(&$items, $task) { continue; } - $items[$path]['page callback'] = 'delegator_node_add'; + $items[$path]['page callback'] = 'page_manager_node_add'; $items[$path]['file path'] = $task['path']; $items[$path]['file'] = $task['file']; // Why str_replace things back? @@ -63,10 +63,10 @@ function delegator_node_edit_menu_alter(&$items, $task) { /** * Warn if we are unable to override the taxonomy term page. */ -function delegator_node_edit_task_admin(&$form, &$form_state) { +function page_manager_node_edit_task_admin(&$form, &$form_state) { $callback = db_result(db_query("SELECT page_callback FROM {menu_router} WHERE path = 'node/%/edit'")); - if ($callback != 'delegator_node_edit') { - drupal_set_message(t('Delegator module is unable to override node/%node/edit because some other module already has overridden with %callback. Delegator will not be able to handle this page.', array('%callback' => $callback)), 'warning'); + if ($callback != 'page_manager_node_edit') { + drupal_set_message(t('Page managermodule is unable to override node/%node/edit because some other module already has overridden with %callback. Page managerwill not be able to handle this page.', array('%callback' => $callback)), 'warning'); } } @@ -77,9 +77,9 @@ function delegator_node_edit_task_admin(&$form, &$form_state) { * to run with it. If no one does, it passes through to Drupal core's * node edit, which is node_page_edit(). */ -function delegator_node_edit($node) { +function page_manager_node_edit($node) { // Load my task plugin - $task = delegator_get_task('node_edit'); + $task = page_manager_get_task('node_edit'); // Load the node into a context. ctools_include('context'); @@ -102,13 +102,13 @@ function delegator_node_edit($node) { /** * Callback to handle the process of adding a node. * - * This creates a basic $node and passes that off to delegator_node_edit(). + * This creates a basic $node and passes that off to page_manager_node_edit(). * It is modeled after Drupal's node_add() function. * * Unlike node_add() we do not need to check node_access because that was * already checked by the menu system. */ -function delegator_node_add($type) { +function page_manager_node_add($type) { global $user; $types = node_get_types(); @@ -122,7 +122,7 @@ function delegator_node_add($type) { ); drupal_set_title(t('Create @name', array('@name' => $types[$type]->name))); - return delegator_node_edit($node); + return page_manager_node_edit($node); } /** @@ -131,7 +131,7 @@ function delegator_node_add($type) { * Since this is the node edit 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) { +function page_manager_node_edit_get_arguments($task, $subtask_id) { return array( array( 'keyword' => 'node', @@ -146,7 +146,7 @@ function delegator_node_edit_get_arguments($task, $subtask_id) { /** * 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)); +function page_manager_node_edit_get_contexts($task, $subtask_id) { + return ctools_context_get_placeholders_from_argument(page_manager_node_edit_get_arguments($task, $subtask_id)); } diff --git a/delegator/plugins/tasks/node_view.inc b/page_manager/plugins/tasks/node_view.inc similarity index 62% rename from delegator/plugins/tasks/node_view.inc rename to page_manager/plugins/tasks/node_view.inc index 679e228e428eab328d5558f74da82e7757c11854..975af5422956cdae600e1756de53b59b296692af 100644 --- a/delegator/plugins/tasks/node_view.inc +++ b/page_manager/plugins/tasks/node_view.inc @@ -5,51 +5,51 @@ * @file * Handle the 'node view' override task. * - * This plugin overrides node/%node and reroutes it to the delegator, where + * This plugin overrides node/%node and reroutes it to the page manager, where * a list of tasks can be used to service this request based upon criteria * supplied by access plugins. */ /** - * Specialized implementation of hook_delegator_tasks(). See api-task.html for + * Specialized implementation of hook_page_manager_task_tasks(). See api-task.html for * more information. */ -function delegator_node_view_delegator_tasks() { +function page_manager_node_view_page_manager_tasks() { return array( // This is a 'page' task and will fall under the page admin UI 'task type' => 'page', - 'title' => t('Node view'), + 'title' => t('Node template'), 'description' => t('The node view task allows you to control what handler will handle the job of rendering a node view at the path node/%node. If no handler is set or matches the criteria, the default Drupal node renderer will be used.'), 'admin title' => 'Node view', // translated by menu system 'admin description' => 'Overrides for the built in node view handler at node/%node.', 'admin path' => 'node/%node', - // Callback to add items to the delegator task administration form: - 'task admin' => 'delegator_node_view_task_admin', + // Callback to add items to the page managertask administration form: + 'task admin' => 'page_manager_node_view_task_admin', // Menu hooks so that we can alter the node/%node menu entry to point to us. - 'hook menu' => 'delegator_node_view_menu', - 'hook menu alter' => 'delegator_node_view_menu_alter', + 'hook menu' => 'page_manager_node_view_menu', + 'hook menu alter' => 'page_manager_node_view_menu_alter', // This is task uses 'context' handlers and must implement these to give the // handler data it needs. 'handler type' => 'context', - 'get arguments' => 'delegator_node_view_get_arguments', - 'get context placeholders' => 'delegator_node_view_get_contexts', + 'get arguments' => 'page_manager_node_view_get_arguments', + 'get context placeholders' => 'page_manager_node_view_get_contexts', ); } /** - * Callback defined by delegator_node_view_delegator_tasks(). + * Callback defined by page_manager_node_view_page_manager_tasks(). * * Alter the node view input so that node view comes to us rather than the * normal node view process. */ -function delegator_node_view_menu_alter(&$items, $task) { +function page_manager_node_view_menu_alter(&$items, $task) { // Override the node view handler for our purpose. - if ($items['node/%node']['page callback'] == 'node_page_view' || variable_get('delegator_override_anyway', FALSE)) { - $items['node/%node']['page callback'] = 'delegator_node_view'; + if ($items['node/%node']['page callback'] == 'node_page_view' || variable_get('page_manager_override_anyway', FALSE)) { + $items['node/%node']['page callback'] = 'page_manager_node_view'; $items['node/%node']['file path'] = $task['path']; $items['node/%node']['file'] = $task['file']; } @@ -59,10 +59,10 @@ function delegator_node_view_menu_alter(&$items, $task) { /** * Warn if we are unable to override the taxonomy term page. */ -function delegator_node_view_task_admin(&$form, &$form_state) { +function page_manager_node_view_task_admin(&$form, &$form_state) { $callback = db_result(db_query("SELECT page_callback FROM {menu_router} WHERE path = 'node/%'")); - if ($callback != 'delegator_node_view') { - drupal_set_message(t('Delegator module is unable to override node/%node because some other module already has overridden with %callback. Delegator will not be able to handle this page.', array('%callback' => $callback)), 'warning'); + if ($callback != 'page_manager_node_view') { + drupal_set_message(t('Page managermodule is unable to override node/%node because some other module already has overridden with %callback. Page managerwill not be able to handle this page.', array('%callback' => $callback)), 'warning'); } } @@ -73,9 +73,9 @@ function delegator_node_view_task_admin(&$form, &$form_state) { * 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_view($node) { +function page_manager_node_view($node) { // Load my task plugin - $task = delegator_get_task('node_view'); + $task = page_manager_get_task('node_view'); // Load the node into a context. ctools_include('context'); @@ -89,8 +89,8 @@ function delegator_node_view($node) { } $function = 'node_page_view'; - foreach (module_implements('delegator_override') as $module) { - $call = $module . '_delegator_override'; + foreach (module_implements('page_manager_override') as $module) { + $call = $module . '_page_manager_override'; if (($rc = $call('node_view')) && function_exists($rc)) { $function = $rc; break; @@ -107,7 +107,7 @@ function delegator_node_view($node) { * 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_view_get_arguments($task, $subtask_id) { +function page_manager_node_view_get_arguments($task, $subtask_id) { return array( array( 'keyword' => 'node', @@ -122,7 +122,7 @@ function delegator_node_view_get_arguments($task, $subtask_id) { /** * Callback to get context placeholders provided by this handler. */ -function delegator_node_view_get_contexts($task, $subtask_id) { - return ctools_context_get_placeholders_from_argument(delegator_node_view_get_arguments($task, $subtask_id)); +function page_manager_node_view_get_contexts($task, $subtask_id) { + return ctools_context_get_placeholders_from_argument(page_manager_node_view_get_arguments($task, $subtask_id)); } diff --git a/page_manager/plugins/tasks/page.admin.inc b/page_manager/plugins/tasks/page.admin.inc new file mode 100644 index 0000000000000000000000000000000000000000..7b65531af612591f876f73bb5c6432dd68501ac8 --- /dev/null +++ b/page_manager/plugins/tasks/page.admin.inc @@ -0,0 +1,1439 @@ + $access_callback, + 'access arguments' => $access_arguments, + 'file' => 'plugins/tasks/page.admin.inc', + ); + + $items['admin/build/pages/add'] = array( + 'title' => 'Add custom page', + 'page callback' => 'page_manager_page_add_subtask', + 'page arguments' => array(), + 'type' => MENU_LOCAL_TASK, + ) + $base; + + $items['admin/build/pages/import'] = array( + 'title' => 'Import page', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('page_manager_page_import_subtask', 'page'), + 'type' => MENU_LOCAL_TASK, + ) + $base; + + // AJAX callbacks for argument modal. + $items['admin/build/pages/argument'] = array( + 'page callback' => 'page_manager_page_subtask_argument_ajax', + 'type' => MENU_CALLBACK, + ) + $base; + + // Add menu entries for each subtask + foreach (page_manager_page_load_all() as $subtask_id => $subtask) { + if (!empty($subtask->disabled)) { + continue; + } + + if (!isset($subtask->access['type'])) { + $subtask->access['type'] = 'none'; + } + if (!isset($subtask->access['settings'])) { + $subtask->access['settings'] = NULL; + } + + $path = array(); + $page_arguments = array($subtask_id); + $access_arguments = array($subtask->access); + $load_arguments = array($subtask_id, '%index'); + + // Replace named placeholders with our own placeholder to load contexts. + $position = 0; + foreach (explode('/', $subtask->path) as $bit) { + // Remove things like double slashes completely. + if (!isset($bit) || $bit === '') { + continue; + } + + if ($bit[0] == '%' && $bit != '%') { + // If an argument, swap it out with our argument loader and make sure + // the argument gets passed through to the page callback. + $path[] = '%pm_arg'; + $page_arguments[] = $position; + $access_arguments[] = $position; + } + else if ($bit[0] != '!') { + $path[] = $bit; + } + + // Increment position. We do it like this to skip empty items that + // could happen from erroneous paths like: this///that + $position++; + } + + $menu_path = implode('/', $path); + + $items[$menu_path] = page_manager_page_menu_item($task, $subtask->menu, $access_arguments, $page_arguments, $load_arguments); + + // Add a parent menu item if one is configured. + if (isset($subtask->menu['type']) && $subtask->menu['type'] == 'default tab' && $subtask->menu['parent']['type'] != 'none') { + array_pop($path); + $parent_path = implode('/', $path); + $items[$parent_path] = page_manager_page_menu_item($task, $subtask->menu['parent'], $access_arguments, $page_arguments, $load_arguments); + } + } +} + +/** + * Create a menu item for page manager pages. + * + * @param $menu + * The configuration to use. It will contain a type, and depending on the + * type may also contain weight, title and name. These are presumed to have + * been configured from the UI. + * @param $access_arguments + * Arguments that go with ctools_access_menu; it should be loaded with + * the access plugin type, settings, and positions of any arguments that + * may produce contexts. + * @param $page_arguments + * This should be seeded with the subtask name for easy loading and like + * the access arguments above should contain positions of arguments so + * that the menu system passes contexts through. + * @param $load_arguments + * Arguments to send to the arg loader; should be the subtask id and '%index'. + */ +function page_manager_page_menu_item($task, $menu, $access_arguments, $page_arguments, $load_arguments) { + $item = array( + 'access callback' => 'ctools_access_menu', + 'access arguments' => $access_arguments, + 'page callback' => 'page_manager_page_execute', + 'page arguments' => $page_arguments, + 'load arguments' => $load_arguments, + 'file' => 'plugins/tasks/page.inc', + ); + + if (isset($menu['title'])) { + $item['title'] = $menu['title']; + } + if (isset($menu['weight'])) { + $item['weight'] = $menu['weight']; + } + + if (empty($menu['type'])) { + $menu['type'] = 'none'; + } + + switch ($menu['type']) { + case 'none': + default: + $item['type'] = MENU_CALLBACK; + break; + + case 'normal': + $item['type'] = MENU_NORMAL_ITEM; + // Insert item into the proper menu + $item['menu_name'] = $menu['name']; + break; + + case 'tab': + $item['type'] = MENU_LOCAL_TASK; + break; + + case 'default tab': + $item['type'] = MENU_DEFAULT_LOCAL_TASK; + break; + } + + return $item; +} + +/** + * Page callback to add a subtask. + */ +function page_manager_page_add_subtask($task_name = NULL, $step = NULL) { + $task = page_manager_get_task('page'); + + $form_info = array( + 'id' => 'page_manager_add_page', + 'show trail' => TRUE, + 'show back' => TRUE, + 'show return' => FALSE, + 'next callback' => 'page_manager_page_add_subtask_next', + 'finish callback' => 'page_manager_page_add_subtask_finish', + 'return callback' => 'page_manager_page_add_subtask_finish', + 'cancel callback' => 'page_manager_page_add_subtask_cancel', + 'add order' => array( + 'basic' => t('Basic settings'), + 'argument' => t('Argument settings'), + 'access' => t('Access control'), + 'menu' => t('Menu settings'), + 'multiple' => t('Task handlers'), + ), + 'forms' => array( + 'basic' => array( + 'form id' => 'page_manager_page_form_basic', + ), + 'access' => array( + 'form id' => 'page_manager_page_form_access', + ), + 'menu' => array( + 'form id' => 'page_manager_page_form_menu', + ), + 'argument' => array( + 'form id' => 'page_manager_page_form_argument', + ), + 'multiple' => array( + 'form id' => 'page_manager_page_argument_form_multiple', + ), + ), + ); + + if ($task_name) { + $page = page_manager_get_page_cache($task_name); + if (empty($page)) { + return drupal_not_found(); + } + + $form_info['path'] = "admin/build/pages/add/$task_name/%step"; + + $handler_plugin = page_manager_get_task_handler($page->handler); + + $form_info['forms'] += $handler_plugin['forms']; + + if (isset($page->forms)) { + foreach ($page->forms as $id) { + if (isset($form_info['add order'][$id])) { + $form_info['order'][$id] = $form_info['add order'][$id]; + } + else if (isset($handler_plugin['add features'][$id])) { + $form_info['order'][$id] = $handler_plugin['add features'][$id]; + } + else if (isset($handler_plugin['required forms'][$id])) { + $form_info['order'][$id] = $handler_plugin['required forms'][$id]; + } + } + } + else { + $form_info['order'] = $form_info['add order']; + } + + // This means we just submitted our form from the default list + // of steps, which we've traded in for a newly generated list of + // steps above. We need to translate this 'next' step into what + // our questions determined would be next. + if ($step == 'next') { + $keys = array_keys($form_info['order']); + // get rid of 'basic' from the list of forms. + array_shift($keys); + $step = array_shift($keys); + + // If $step == 'basic' at this point, we were not presented with any + // additional forms at all. Let's just save and go! + if ($step == 'basic') { + page_manager_save_page_cache($page); + // Redirect to the new page's task handler editor. + drupal_goto('admin/build/pages/edit/' . $page->task_name); + } + } + } + else { + $new_page = page_manager_page_new(); + $new_page->name = NULL; + + $page = new stdClass(); + page_manager_page_new_page_cache($new_page, $page); + $form_info['path'] = 'admin/build/pages/add/%task_name/%step'; + $form_info['show trail'] = FALSE; + $form_info['order'] = array( + 'basic' => t('Basic settings'), + 'next' => t('A meaningless second page'), + ); + } + + ctools_include('wizard'); + $form_state = array( + 'task' => $task, + 'subtask' => $page->subtask, + 'page' => &$page, + 'type' => 'add', + 'task_id' => 'page', + 'task_name' => $page->task_name, + 'creating' => TRUE, + ); + + if (!empty($page->handlers)) { + $keys = array_keys($page->handlers); + $key = array_shift($keys); + $form_state['handler'] = &$page->handlers[$key]; + } + + $output = ctools_wizard_multistep_form($form_info, $step, $form_state); + + if (!$output) { + // redirect. + drupal_redirect_form(array(), $form_state['redirect']); + } + + return $output; +} + +/** + * Callback generated when the add page process is finished. + */ +function page_manager_page_add_subtask_finish(&$form_state) { + $page = &$form_state['page']; + // Redirect to the new page's task handler editor. + $form_state['redirect'] = 'admin/build/pages/edit/' . $page->task_name; + return; +} + +/** + * Callback generated when the 'next' button is clicked. + * + * All we do here is store the cache. + */ +function page_manager_page_add_subtask_next(&$form_state) { + if (empty($form_state['task_name']) || $form_state['task_name'] == 'page') { + // We may not have known the path to go next, because we didn't yet know the + // task name. This fixes that. + $form_state['form_info']['path'] = str_replace('%task_name', $form_state['page']->task_name, $form_state['form_info']['path']); + + $form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']); + } + + // Update the cache with changes. + page_manager_set_page_cache($form_state['page']); +} + +/** + * Callback generated when the 'cancel' button is clicked. + * + * All we do here is clear the cache. + */ +function page_manager_page_add_subtask_cancel(&$form_state) { + // Wipe all our stored changes. + if (isset($form_state['page']->task_name)) { + page_manager_clear_page_cache($form_state['page']->task_name); + } +} + +/** + * Basic settings form for a page manager page. + */ +function page_manager_page_form_basic(&$form, &$form_state) { + $page = &$form_state['page']->subtask['subtask']; + $task = $form_state['task']; + + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Name'), + '#description' => t('The machine readable name of this page. It must be unique, and it must contain only alphanumeric characters and underscores. Once created, you will not be able to change this value!'), + '#default_value' => $page->name, + ); + + if (isset($page->pid) || empty($form_state['creating'])) { + $form['name']['#disabled'] = TRUE; + $form['name']['#value'] = $page->name; + } + + $form['admin_title'] = array( + '#type' => 'textfield', + '#title' => t('Administrative title'), + '#description' => t('The name of this page. This will appear in the administrative interface to easily identify it.'), + '#default_value' => $page->admin_title, + ); + + // path + $form['path'] = array( + '#type' => 'textfield', + '#title' => t('Path'), + '#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, + ); + + if (!isset($page->pid) && !empty($form_state['creating'])) { + $features['default'] = array( + 'access' => t('Access control'), + 'menu' => t('Visible menu item'), + ); + + module_load_include('inc', 'page_manager', 'page_manager.admin'); + page_manager_handler_add_form($form, $form_state, $features); + } + +} + +function page_manager_page_form_basic_validate_filter($value) { + return $value === -1; +} + +/** + * Validate the basic form. + */ +function page_manager_page_form_basic_validate(&$form, &$form_state) { + // Ensure path is unused by other pages. + $page = $form_state['page']->subtask['subtask']; + $name = !empty($form_state['values']['name']) ? $form_state['values']['name'] : $page->name; + if (empty($name)) { + form_error($form['name'], t('Name is required.')); + } + + // If this is new, make sure the name is unique: + if (empty($page->name)) { + $test = page_manager_page_load($name); + if ($test) { + form_error($form['name'], t('That name is used by another page: @page', array('@page' => $test->admin_title))); + } + + // Ensure name fits the rules: + if (preg_match('/[^a-zA-Z0-9_]/', $form_state['values']['name'])) { + form_error($form['name'], t('Page name must be alphanumeric or underscores only.')); + } + } + + $pages = page_manager_page_load_all(); + foreach ($pages as $test) { + if ($test->name != $name && $test->path == $form_state['values']['path'] && empty($test->disabled)) { + form_error($form['path'], t('That path is used by another page: @page', array('@page' => $test->admin_title))); + } + } + + // Ensure path is unused by things NOT pages. We do the double check because + // we're checking against our page callback. + $path = array(); + if (empty($form_state['values']['path'])) { + form_error($form['path'], t('Path is required.')); + // stop processing here if there is no path. + return; + } + + $found = FALSE; + $error = FALSE; + foreach (explode('/', $form_state['values']['path']) as $bit) { + if (!isset($bit) || $bit === '') { + continue; + } + + 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; + } + } + + $path = implode('/', $path); + $result = db_query("SELECT * FROM {menu_router} WHERE path = '%s'", $path); + while ($router = db_fetch_object($result)) { + if ($router->page_callback != 'page_manager_page_execute') { + form_error($form['path'], t('That path is already in used. This system cannot override existing paths.')); + } + } + + // Ensure the path is not already an alias + // @todo + + // Ensure path is properly formed. + $args = page_manager_page_get_named_arguments($form_state['values']['path']); + if ($invalid_args = array_filter($args, 'page_manager_page_form_basic_validate_filter')) { + foreach ($invalid_args as $arg => $position) { + form_error($form['path'], t('Duplicated argument %arg', array('%arg' => $arg))); + } + } + + if (isset($args['%'])) { + form_error($form['path'], t('Invalid arg %. All arguments must be named with keywords.')); + } + + $form_state['arguments'] = $args; +} + +/** + * Store the values from the basic settings form. + */ +function page_manager_page_form_basic_submit(&$form, &$form_state) { + $page = &$form_state['page']->subtask['subtask']; + $cache = &$form_state['page']; + + // If this is a new thing, then we have to do a bunch of setup to create + // the cache record with the right ID and some basic data that we could + // not know until we asked the user some questions. + if (!isset($page->pid) && !empty($form_state['creating'])) { + // Update the data with our new name. + $page->name = $form_state['values']['name']; + $form_state['page']->task_name = page_manager_make_task_name($form_state['task_id'], $page->name); + $cache->handler = $form_state['values']['handler']; + $cache->subtask_id = $page->name; + $plugin = page_manager_get_task_handler($cache->handler); + + // Create a new handler. + $handler = page_manager_new_task_handler($plugin); + $title = !empty($form_state['values']['title']) ? $form_state['values']['title'] : $plugin['title']; + page_manager_handler_add_to_page($cache, $handler, $title); + + // Figure out which forms to present them with + $cache->forms = array(); + $cache->forms[] = 'basic'; // This one is always there. + if (!empty($form_state['arguments'])) { + $cache->forms[] = 'argument'; + } + + $features = $form_state['values']['features']; + $cache->forms = array_merge($cache->forms, array_keys(array_filter($features['default']))); + if (isset($features[$form_state['values']['handler']])) { + $cache->forms = array_merge($cache->forms, array_keys(array_filter($features[$form_state['values']['handler']]))); + } + + if (isset($plugin['required forms'])) { + $cache->forms = array_merge($cache->forms, array_keys($plugin['required forms'])); + } + } + + $page->admin_title = $form_state['values']['admin_title']; + if ($page->path != $form_state['values']['path']) { + $page->path = $form_state['values']['path']; + $cache->path_changed = TRUE; + } +} + +/** + * Form to handle menu item controls. + */ +function page_manager_page_form_menu(&$form, &$form_state) { + ctools_include('dependent'); + $form['menu'] = array( + '#prefix' => '' . $text . '
', + ); + + if (empty($form_state['page']->locked)) { + unset($form['buttons']); + $form['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + ); + } +} + +/** + * Submit handler to delete a view. + */ +function page_manager_page_form_delete_submit(&$form, &$form_state) { + page_manager_page_delete($form_state['page']->subtask['subtask']); + drupal_set_message(t('The page has been deleted.')); + $form_state['redirect'] = 'admin/build/pages'; +} diff --git a/page_manager/plugins/tasks/page.inc b/page_manager/plugins/tasks/page.inc new file mode 100644 index 0000000000000000000000000000000000000000..62d1f805b0b06d20c53c1fa0b48c71fe355028a8 --- /dev/null +++ b/page_manager/plugins/tasks/page.inc @@ -0,0 +1,540 @@ + t('Custom pages'), + 'description' => t('Administrator created pages that have a URL path, access control and entries in the Drupal menu system.'), + 'subtasks' => TRUE, + 'subtask callback' => 'page_manager_page_subtask', + 'subtasks callback' => 'page_manager_page_subtasks', + 'save subtask callback' => 'page_manager_page_save_subtask', + 'hook menu' => array( + 'file' => 'page.admin.inc', + 'path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks', + 'function' => 'page_manager_page_menu', + ), + 'hook theme' => 'page_manager_page_theme', + // page only items + 'task type' => 'page', + 'operations' => array( + array( + 'title' => t('Import'), + 'href' => 'admin/build/pages/import', + ), + array( + 'title' => t('Add custom page'), + 'href' => 'admin/build/pages/add', + ), + ), + 'columns' => array( + 'storage' => array( + 'label' => t('Storage'), + 'class' => 'page-manager-page-storage', + ), + ), + 'page type' => 'custom', + + // context only items + 'handler type' => 'context', + 'get arguments' => array( + 'file' => 'page.admin.inc', + 'path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks', + 'function' => 'page_manager_page_get_arguments', + ), + 'get context placeholders' => 'page_manager_page_get_contexts', + 'access restrictions' => 'page_manager_page_access_restrictions', + 'uses handlers' => TRUE, + ); +} + +/** + * Task callback to get all subtasks. + * + * Return a list of all subtasks. + */ +function page_manager_page_subtasks($task) { + $pages = page_manager_page_load_all($task['name']); + $return = array(); + foreach ($pages as $name => $page) { + $return[$name] = page_manager_page_build_subtask($task, $page); + } + + return $return; +} + +/** + * Callback to return a single subtask. + */ +function page_manager_page_subtask($task, $subtask_id) { + $page = page_manager_page_load($subtask_id); + if ($page) { + return page_manager_page_build_subtask($task, $page); + } +} + +/** + * Call back from the administrative system to save a page. + * + * We get the $subtask as created by page_manager_page_build_subtask. + */ +function page_manager_page_save_subtask($subtask) { + $page = &$subtask['subtask']; + + // Ensure $page->arguments contains only real arguments: + $arguments = page_manager_page_get_named_arguments($page->path); + $args = array(); + foreach ($arguments as $keyword => $position) { + if (isset($page->arguments[$keyword])) { + $args[$keyword] = $page->arguments[$keyword]; + } + else { + $args[$keyword] = array( + 'id' => '', + 'identifier' => '', + 'argument' => '', + 'settings' => array(), + ); + } + } + $page->arguments = $args; + // Create a real object from the cache + page_manager_page_save($page); +} + +/** + * Build a subtask array for a given page. + */ +function page_manager_page_build_subtask($task, $page) { + $operations = array(); + $operations['settings'] = array( + 'type' => 'group', + 'class' => 'operations-settings', + 'title' => t('Settings'), + 'children' => array(), + ); + + $settings = &$operations['settings']['children']; + + $settings['basic'] = array( + 'title' => t('Basic'), + 'description' => t('Edit name, path and other basic settings for the page.'), + 'form' => 'page_manager_page_form_basic', + ); + + if (!page_manager_page_get_named_arguments($page->path)) { + $settings['argument'] = array( + 'title' => t('Argument contexts'), + 'description' => t('Set up contexts for the arguments on this page.'), + 'form' => 'page_manager_page_form_argument', + ); + } + + $settings['access'] = array( + 'title' => t('Access'), + 'description' => t('Control what users can access this page.'), + 'form' => 'page_manager_page_form_access', + ); + + $settings['menu'] = array( + 'title' => t('Menu'), + 'description' => t('Provide this page a visible menu or a menu tab.'), + 'form' => 'page_manager_page_form_menu', + ); + + $operations['actions']['children']['clone'] = array( + 'title' => t('Clone'), + 'description' => t('Make a copy of this page'), + 'form' => 'page_manager_page_form_clone', + ); + $operations['actions']['children']['export'] = array( + 'title' => t('Export'), + 'description' => t('Export this page as code that can be imported or embedded into a module.'), + 'form' => 'page_manager_page_form_export', + ); + if ($page->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) { + $operations['actions']['children']['delete'] = array( + 'title' => t('Revert'), + 'description' => t('Remove all changes to this page and revert to the version in code.'), + 'form' => 'page_manager_page_form_delete', + ); + } + else if ($page->export_type != EXPORT_IN_CODE) { + $operations['actions']['children']['delete'] = array( + 'title' => t('Delete'), + 'description' => t('Remove this page from your system completely.'), + 'form' => 'page_manager_page_form_delete', + ); + } + + if (!empty($page->disabled)) { + $operations['actions']['children']['enable'] = array( + 'title' => t('Enable'), + 'description' => t('Activate this page so that it will be in use in your system.'), + 'form' => 'page_manager_page_form_enable', + 'ajax' => FALSE, + 'form info' => array( + 'finish text' => t('Enable'), + ), + ); + } + else { + $operations['actions']['children']['disable'] = array( + 'title' => t('Disable'), + 'description' => t('De-activate this page. The data will remain but the page will not be in use on your system.'), + 'form' => 'page_manager_page_form_disable', + 'ajax' => FALSE, + 'form info' => array( + 'finish text' => t('Disable'), + ), + ); + } + + $subtask = array( + 'name' => $page->name, + 'admin title' => $page->admin_title, + 'admin path' => $page->path, + 'admin type' => t('Custom'), + 'subtask' => $page, + 'operations' => $operations, + 'operations include' => array( + 'file' => 'page.admin.inc', + 'path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks', + ), + 'single task' => empty($page->multiple), + 'row class' => empty($page->disabled) ? 'page-manager-enabled' : 'page-manager-disabled', + 'storage' => $page->type, + ); + + // default handlers may appear from a default subtask. + if (isset($page->default_handlers)) { + $subtask['default handlers'] = $page->default_handlers; + } + return $subtask; +} + +/** + * Delegated implementation of hook_theme(). + */ +function page_manager_page_theme(&$items, $task) { + $base = array( + 'file' => 'page.admin.inc', + 'path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks', + ); + $items['page_manager_page_form_argument_table'] = $base + array( + 'arguments' => array('form' => NULL), + ); + $items['page_manager_page_lock'] = $base + array( + 'arguments' => array('lock' => array(), 'task_name' => NULL), + ); + $items['page_manager_page_changed'] = $base + array( + 'arguments' => array(), + ); +} + +// -------------------------------------------------------------------------- +// Page execution functions + +/** + * Execute a page task. + * + * This is the callback to entries in the Drupal menu system created by the + * page task. + * + * @param $subtask_id + * The name of the page task used. + * @param ... + * A number of context objects as specified by the user when + * creating named arguments in the path. + */ +function page_manager_page_execute($subtask_id) { + $page = page_manager_page_load($subtask_id); + $task = page_manager_get_task($page->task); + $subtask = page_manager_get_task_subtask($task, $subtask_id); + + // Turn the contexts into a properly keyed array. + $contexts = array(); + $args = array(); + foreach (func_get_args() as $count => $arg) { + if (is_object($arg) && get_class($arg) == 'ctools_context') { + $contexts[$arg->id] = $arg; + $args[] = $arg->original_argument; + } + else if ($count) { + $args[] = $arg; + } + } + + $count = 0; + $names = page_manager_page_get_named_arguments($page->path); + $bits = explode('/', $page->path); + + if ($page->arguments) { + 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++; + } + } + + // Add a fake tab for 'View' so that edit tabs can be added. + if (user_access('administer page manager') && (!isset($page->menu['type']) || !in_array($page->menu['type'], array('tab', 'default tab')))) { + ctools_include('menu'); + ctools_menu_add_tab(array( + 'title' => t('View'), + 'href' => $_GET['q'], + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + )); + } + + + 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, $contexts, $args); + if ($output === FALSE) { + return drupal_not_found(); + } + + return $output; +} + +// -------------------------------------------------------------------------- +// Context type callbacks + +/** + * Return a list of arguments used by this task. + */ +function page_manager_page_get_arguments($task, $subtask) { + return _page_manager_page_get_arguments($subtask['subtask']); +} + +function _page_manager_page_get_arguments($page) { + $arguments = array(); + if (!empty($page->arguments)) { + foreach ($page->arguments as $keyword => $argument) { + if (isset($argument['name'])) { + $argument['keyword'] = $keyword; + $arguments[$keyword] = $argument; + } + } + } + return $arguments; +} + +/** + * Get a group of context placeholders for the arguments. + */ +function page_manager_page_get_contexts($task, $subtask) { + ctools_include('context'); + return ctools_context_get_placeholders_from_argument(page_manager_page_get_arguments($task, $subtask)); +} + +/** + * Return a list of arguments used by this task. + */ +function page_manager_page_access_restrictions($task, $subtask, $contexts) { + $page = $subtask['subtask']; + return ctools_access_add_restrictions($page->access, $contexts); +} + +// -------------------------------------------------------------------------- +// Page task database info. + +/** + * Create a new page with defaults appropriately set from schema. + */ +function page_manager_page_new() { + ctools_include('export'); + return ctools_export_new_object('page_manager_pages'); +} + +/** + * Load a single page subtask. + */ +function page_manager_page_load($name) { + ctools_include('export'); + $result = ctools_export_load_object('page_manager_pages', 'names', array($name)); + if (isset($result[$name])) { + return $result[$name]; + } +} + +/** + * Load all page subtasks. + */ +function page_manager_page_load_all($task = NULL) { + ctools_include('export'); + + if (empty($task)) { + return ctools_export_load_object('page_manager_pages'); + } + else { + return ctools_export_load_object('page_manager_pages', 'conditions', array('task' => $task)); + } +} + +/** + * Write a page subtask to the database. + */ +function page_manager_page_save(&$page) { + $update = (isset($page->pid)) ? array('pid') : array(); + $task = page_manager_get_task($page->task); + + if ($function = ctools_plugin_get_function($task, 'save')) { + $function($page, $update); + } + drupal_write_record('page_manager_pages', $page, $update); + + // If this was a default page we may need to write default task + // handlers that we provided as well. + if (!$update && isset($page->default_handlers)) { + $handlers = page_manager_load_task_handlers(page_manager_get_task('page'), $page->name); + foreach ($page->default_handlers as $name => $handler) { + if (!isset($handlers[$name]) || !($handlers[$name]->export_type & EXPORT_IN_DATABASE)) { + // Make sure this is right, as exports can wander a bit. + $handler->subtask = $page->name; + page_manager_save_task_handler($handler); + } + } + } + return $page; +} + +/** + * Remove a page subtask. + */ +function page_manager_page_delete($page) { + $task = page_manager_get_task($page->task); + if ($function = ctools_plugin_get_function($task, 'delete')) { + $function($page); + } + if (!empty($task['uses handlers'])) { + $handlers = page_manager_load_task_handlers($task, $page->name); + foreach ($handlers as $handler) { + page_manager_delete_task_handler($handler); + } + } + db_query("DELETE FROM {page_manager_pages} WHERE name = '%s'", $page->name); +} + +/** + * Export a page subtask. + */ +function page_manager_page_export($page, $with_handlers = FALSE, $indent = '') { + $task = page_manager_get_task($page->task); + $append = ''; + + if ($function = ctools_plugin_get_function($task, 'export')) { + $append = $function($page, $indent); + } + + ctools_include('export'); + $output = ctools_export_object('page_manager_pages', $page, $indent); + $output .= $append; + + if ($with_handlers) { + if (is_array($with_handlers)) { + $handlers = $with_handlers; + } + else { + $handlers = page_manager_load_task_handlers(page_manager_get_task('page'), $page->name); + } + $output .= $indent . '$page->default_handlers = array();' . "\n"; + foreach ($handlers as $handler) { + $output .= page_manager_export_task_handler($handler, $indent); + $output .= $indent . '$page->default_handlers[$handler->name] = $handler;' . "\n"; + } + } + return $output; +} + +/** + * Get a list of named arguments in a page managerpage 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 page_manager_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; +} + +/** + * Load a context from an argument for a given page task. + * + * This is used as a menu callback to translate arguments and that is why it is + * here in the .module file. + * + * @param $value + * The incoming argument value. + * @param $subtask + * The subtask id. + * @param $argument + * The numeric position of the argument in the path, counting from 0. + * + * @return + * A context item if one is configured, the argument if one is not, or + * FALSE if restricted or invalid. + */ +function _pm_arg_load($value, $subtask, $argument) { + $page = page_manager_page_load($subtask); + if (!$page) { + return FALSE; + } + + $path = explode('/', $page->path); + if (empty($path[$argument])) { + return FALSE; + } + + $keyword = substr($path[$argument], 1); + if (empty($page->arguments[$keyword])) { + return $value; + } + + $page->arguments[$keyword]['keyword'] = $keyword; + + ctools_include('context'); + $context = ctools_context_get_context_from_argument($page->arguments[$keyword], $value); + + // convert false equivalents to false. + return $context ? $context : FALSE; +} diff --git a/delegator/plugins/tasks/term_view.inc b/page_manager/plugins/tasks/term_view.inc similarity index 62% rename from delegator/plugins/tasks/term_view.inc rename to page_manager/plugins/tasks/term_view.inc index a78120ccf938bca1feccdcb83985219630b8dca4..4cc101f81f2a7dda87af42ca1ec6c5115013e3cf 100644 --- a/delegator/plugins/tasks/term_view.inc +++ b/page_manager/plugins/tasks/term_view.inc @@ -5,16 +5,16 @@ * @file * Handle the 'term view' override task. * - * This plugin overrides term/%term and reroutes it to the delegator, where + * This plugin overrides term/%term and reroutes it to the page manager, where * a list of tasks can be used to service this request based upon criteria * supplied by access plugins. */ /** - * Specialized implementation of hook_delegator_tasks(). See api-task.html for + * Specialized implementation of hook_page_manager_task_tasks(). See api-task.html for * more information. */ -function delegator_term_view_delegator_tasks() { +function page_manager_term_view_page_manager_tasks() { if (module_exists('taxonomy')) { return array( // This is a 'page' task and will fall under the page admin UI @@ -27,61 +27,45 @@ function delegator_term_view_delegator_tasks() { 'admin path' => 'taxonomy/term/%term', // Menu hooks so that we can alter the term/%term menu entry to point to us. - 'hook menu' => 'delegator_term_view_menu', - 'hook menu alter' => 'delegator_term_view_menu_alter', + 'hook menu' => 'page_manager_term_view_menu', + 'hook menu alter' => 'page_manager_term_view_menu_alter', // Provide a setting to the primary settings UI for Panels - 'admin settings' => 'delegator_term_view_admin_settings', + 'admin settings' => 'page_manager_term_view_admin_settings', - // Callback to add items to the delegator task administration form: - 'task admin' => 'delegator_term_view_task_admin', + // Callback to add items to the page managertask administration form: + 'task admin' => 'page_manager_term_view_task_admin', // This is task uses 'context' handlers and must implement these to give the // handler data it needs. 'handler type' => 'context', - 'get arguments' => 'delegator_term_view_get_arguments', - 'get context placeholders' => 'delegator_term_view_get_contexts', + 'get arguments' => 'page_manager_term_view_get_arguments', + 'get context placeholders' => 'page_manager_term_view_get_contexts', // Allow additional operations 'operations' => array( - array( - 'title' => t('Task handlers'), - 'href' => "admin/build/delegator/term_view", - ), - array( + 'settings' => array( 'title' => t('Settings'), - 'href' => "admin/build/delegator/term_view/settings", + 'description' => t('Update settings specific to the taxonomy term view.'), ), + // This lets it automatically add relevant information for task handlers. + 'handlers' => array('type' => 'handlers'), ), ); } } /** - * Create the term view settings page menu item. - */ -function delegator_term_view_menu(&$items, $task) { - $items['admin/build/delegator/term_view/settings'] = array( - 'page callback' => 'drupal_get_form', - 'page arguments' => array('delegator_term_view_settings'), - 'file path' => $task['path'], - 'file' => $task['file'], - 'access arguments' => array('administer delegator'), - 'type' => MENU_CALLBACK, - ); -} - -/** - * Callback defined by delegator_term_view_delegator_tasks(). + * Callback defined by page_manager_term_view_page_manager_tasks(). * * Alter the term view input so that term view comes to us rather than the * normal term view process. */ -function delegator_term_view_menu_alter(&$items, $task) { +function page_manager_term_view_menu_alter(&$items, $task) { // Override the term view handler for our purpose, but only if someone else // has not already done so. - if ($items['taxonomy/term/%']['page callback'] == 'taxonomy_term_page' || variable_get('delegator_override_anyway', FALSE)) { - $items['taxonomy/term/%']['page callback'] = 'delegator_term_view'; + if ($items['taxonomy/term/%']['page callback'] == 'taxonomy_term_page' || variable_get('page_manager_override_anyway', FALSE)) { + $items['taxonomy/term/%']['page callback'] = 'page_manager_term_view'; $items['taxonomy/term/%']['file path'] = $task['path']; $items['taxonomy/term/%']['file'] = $task['file']; } @@ -90,10 +74,10 @@ function delegator_term_view_menu_alter(&$items, $task) { /** * Warn if we are unable to override the taxonomy term page. */ -function delegator_term_view_task_admin(&$form, &$form_state) { +function page_manager_term_view_task_admin(&$form, &$form_state) { $callback = db_result(db_query("SELECT page_callback FROM {menu_router} WHERE path = 'taxonomy/term/%'")); - if ($callback != 'delegator_term_view') { - drupal_set_message(t('Delegator module is unable to override taxonomy/term/% because some other module already has overridden with %callback. Delegator will not be able to handle this page.', array('%callback' => $callback)), 'warning'); + if ($callback != 'page_manager_term_view') { + drupal_set_message(t('Page managermodule is unable to override taxonomy/term/% because some other module already has overridden with %callback. Page managerwill not be able to handle this page.', array('%callback' => $callback)), 'warning'); } } @@ -104,12 +88,12 @@ function delegator_term_view_task_admin(&$form, &$form_state) { * to run with it. If no one does, it passes through to Drupal core's * term view, which is term_page_view(). */ -function delegator_term_view($terms, $depth = 0, $op = 'page') { +function page_manager_term_view($terms, $depth = 0, $op = 'page') { // While we ordinarily should never actually get feeds through here, // just in case if ($op != 'feed') { // Load my task plugin - $task = delegator_get_task('term_view'); + $task = page_manager_get_task('term_view'); // Load the term into a context. ctools_include('context'); @@ -120,7 +104,7 @@ function delegator_term_view($terms, $depth = 0, $op = 'page') { } // Add a fake tab for 'View' so that edit tabs can be added. - if (user_access('administer delegator')) { + if (user_access('administer page manager')) { ctools_include('menu'); ctools_menu_add_tab(array( 'title' => t('View'), @@ -159,13 +143,13 @@ function delegator_term_view($terms, $depth = 0, $op = 'page') { * Since this is the term view and there is no UI on the arguments, we * create dummy arguments that contain the needed data. */ -function delegator_term_view_get_arguments($task, $subtask_id) { +function page_manager_term_view_get_arguments($task, $subtask_id) { return array( array( 'keyword' => 'term', - 'identifier' => variable_get('delegator_term_view_type', 'multiple') == 'multiple' ? t('Term(s) being viewed') : t('Term being viewed'), + 'identifier' => variable_get('page_manager_term_view_type', 'multiple') == 'multiple' ? t('Term(s) being viewed') : t('Term being viewed'), 'id' => 1, - 'name' => variable_get('delegator_term_view_type', 'multiple') == 'multiple' ? 'terms' : 'term', + 'name' => variable_get('page_manager_term_view_type', 'multiple') == 'multiple' ? 'terms' : 'term', 'settings' => array('input_form' => 'tid'), 'default' => '404', ), @@ -182,27 +166,26 @@ function delegator_term_view_get_arguments($task, $subtask_id) { /** * Callback to get context placeholders provided by this handler. */ -function delegator_term_view_get_contexts($task, $subtask_id) { - return ctools_context_get_placeholders_from_argument(delegator_term_view_get_arguments($task, $subtask_id)); +function page_manager_term_view_get_contexts($task, $subtask_id) { + return ctools_context_get_placeholders_from_argument(page_manager_term_view_get_arguments($task, $subtask_id)); } /** * Settings page for this item. */ -function delegator_term_view_settings() { - $task = delegator_get_task('term_view'); - delegator_set_trail($task); +function page_manager_term_view_settings() { + $task = page_manager_get_task('term_view'); $form = array(); // This passes thru because the setting can also appear on the main Panels // settings form. - delegator_term_view_admin_settings($form); - $form['delegator_term_view_type'] = array( + page_manager_term_view_admin_settings($form); + $form['page_manager_term_view_type'] = array( '#type' => 'radios', '#title' => t('Allow multiple terms'), '#options' => array('single' => t('Single term'), 'multiple' => t('Multiple terms')), '#description' => t('By default, Drupal allows multiple terms as an argument by separating them with commas or plus signs. If you set this to single, that feature will be disabled.'), - '#default_value' => variable_get('delegator_term_view_type', 'multiple'), + '#default_value' => variable_get('page_manager_term_view_type', 'multiple'), ); return system_settings_form($form); @@ -211,13 +194,13 @@ function delegator_term_view_settings() { /** * Provide a setting to the Panels administrative form. */ -function delegator_term_view_admin_settings(&$form) { - $form['delegator_term_view_type'] = array( +function page_manager_term_view_admin_settings(&$form) { + $form['page_manager_term_view_type'] = array( '#type' => 'radios', '#title' => t('Allow multiple terms on taxonomy/term/%term'), '#options' => array('single' => t('Single term'), 'multiple' => t('Multiple terms')), '#description' => t('By default, Drupal allows multiple terms as an argument by separating them with commas or plus signs. If you set this to single, that feature will be disabled.'), - '#default_value' => variable_get('delegator_term_view_type', 'multiple'), + '#default_value' => variable_get('page_manager_term_view_type', 'multiple'), ); } diff --git a/delegator/plugins/tasks/user_view.inc b/page_manager/plugins/tasks/user_view.inc similarity index 63% rename from delegator/plugins/tasks/user_view.inc rename to page_manager/plugins/tasks/user_view.inc index 83f9045495f61400cfb0d8767426ed3a6745e26c..3236ac72aff1251fc8a2bd35fb0d74d191b77b73 100644 --- a/delegator/plugins/tasks/user_view.inc +++ b/page_manager/plugins/tasks/user_view.inc @@ -2,43 +2,43 @@ // $Id$ /** - * Specialized implementation of hook_delegator_tasks(). See api-task.html for + * Specialized implementation of hook_page_manager_task_tasks(). See api-task.html for * more information. */ -function delegator_user_view_delegator_tasks() { +function page_manager_user_view_page_manager_tasks() { return array( // This is a 'page' task and will fall under the page admin UI 'task type' => 'page', - 'title' => t('User view'), + 'title' => t('User profile template'), 'description' => t('The user view task allows you to control which modules serve requests made to user/%. By default, the core user module will show the user account page. The first task that matches the user will be used to display the user. If no task handlers exist, or if none of the existing task handlers are configured to handle the currently requested user, then the request falls back to the default Drupal user view mechanism.'), 'admin title' => 'User view', // translated by menu system 'admin description' => 'Overrides for the built in user handler, allowing customized user output.', 'admin path' => 'user/%user', - // Callback to add items to the delegator task administration form: - 'task admin' => 'delegator_term_view_task_admin', + // Callback to add items to the page managertask administration form: + 'task admin' => 'page_manager_term_view_task_admin', - 'hook menu' => 'delegator_user_view_menu', - 'hook menu alter' => 'delegator_user_view_menu_alter', + 'hook menu' => 'page_manager_user_view_menu', + 'hook menu alter' => 'page_manager_user_view_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_user_view_get_arguments', - 'get context placeholders' => 'delegator_user_view_get_contexts', + 'get arguments' => 'page_manager_user_view_get_arguments', + 'get context placeholders' => 'page_manager_user_view_get_contexts', ); } /** - * Callback defined by delegator_user_view_delegator_tasks(). + * Callback defined by page_manager_user_view_page_manager_tasks(). * * Alter the user view input so that user view comes to us rather than the * normal user view process. */ -function delegator_user_view_menu_alter(&$items, $task) { +function page_manager_user_view_menu_alter(&$items, $task) { // Override the user view handler for our purpose. - if ($items['user/%user_uid_optional']['page callback'] == 'user_view' || variable_get('delegator_override_anyway', FALSE)) { - $items['user/%user_uid_optional']['page callback'] = 'delegator_user_view'; + if ($items['user/%user_uid_optional']['page callback'] == 'user_view' || variable_get('page_manager_override_anyway', FALSE)) { + $items['user/%user_uid_optional']['page callback'] = 'page_manager_user_view'; $items['user/%user_uid_optional']['file path'] = $task['path']; $items['user/%user_uid_optional']['file'] = $task['file']; } @@ -47,10 +47,10 @@ function delegator_user_view_menu_alter(&$items, $task) { /** * Warn if we are unable to override the taxonomy term page. */ -function delegator_user_view_task_admin(&$form, &$form_state) { +function page_manager_user_view_task_admin(&$form, &$form_state) { $callback = db_result(db_query("SELECT page_callback FROM {menu_router} WHERE path = 'user/%'")); - if ($callback != 'delegator_user_view') { - drupal_set_message(t('Delegator module is unable to override user/%user because some other module already has overridden with %callback. Delegator will not be able to handle this page.', array('%callback' => $callback)), 'warning'); + if ($callback != 'page_manager_user_view') { + drupal_set_message(t('Page managermodule is unable to override user/%user because some other module already has overridden with %callback. Page managerwill not be able to handle this page.', array('%callback' => $callback)), 'warning'); } } @@ -61,9 +61,9 @@ function delegator_user_view_task_admin(&$form, &$form_state) { * to run with it. If no one does, it passes through to Drupal core's * user view, which is user_page_view(). */ -function delegator_user_view($account) { +function page_manager_user_view($account) { // Load my task plugin: - $task = delegator_get_task('user_view'); + $task = page_manager_get_task('user_view'); // Load the account into a context. ctools_include('context'); @@ -86,7 +86,7 @@ function delegator_user_view($account) { * 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_user_view_get_arguments($task, $subtask_id) { +function page_manager_user_view_get_arguments($task, $subtask_id) { return array( array( 'keyword' => 'user', @@ -101,7 +101,7 @@ function delegator_user_view_get_arguments($task, $subtask_id) { /** * Callback to get context placeholders provided by this handler. */ -function delegator_user_view_get_contexts($task, $subtask_id) { - return ctools_context_get_placeholders_from_argument(delegator_user_view_get_arguments($task, $subtask_id)); +function page_manager_user_view_get_contexts($task, $subtask_id) { + return ctools_context_get_placeholders_from_argument(page_manager_user_view_get_arguments($task, $subtask_id)); } diff --git a/page_manager/theme/page-manager-edit-page.tpl.php b/page_manager/theme/page-manager-edit-page.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..65b066704298eb5f69e2b9262aa4cef80e58e4ed --- /dev/null +++ b/page_manager/theme/page-manager-edit-page.tpl.php @@ -0,0 +1,49 @@ + +