'context',
'visible' => TRUE, // may be added up front.
// Administrative fields.
'title' => t('Panel'),
'admin summary' =>'panels_panel_context_admin_summary',
'admin title' => 'panels_panel_context_title',
'operations' => array(
'settings' => array(
'title' => t('General'),
'description' => t('Change general settings about this variant.'),
'form' => 'panels_panel_context_edit_settings',
),
'criteria' => array(
'title' => t('Selection rules'),
'description' => t('Control the criteria used to decide whether or not this variant is used.'),
'ajax' => FALSE,
'form' => array(
'order' => array(
'form' => t('Selection rules'),
),
'forms' => array(
'form' => array(
'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
'form id' => 'ctools_context_handler_edit_criteria',
),
),
),
),
'context' => array(
'title' => t('Contexts'),
'ajax' => FALSE,
'description' => t('Add additional context objects to this variant that can be used by the content.'),
'form' => array(
'order' => array(
'form' => t('Context'),
),
'forms' => array(
'form' => array(
'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
'form id' => 'ctools_context_handler_edit_context',
),
),
),
),
'layout' => array(
'title' => t('Layout'),
'description' => t('Change the layout of this panel.'),
// No AJAX so we get our CSS loaded.
'ajax' => FALSE,
'form' => array(
'order' => array(
'choose' => t('Change layout'),
'move' => t('Move content from old layout'),
),
'forms' => array(
'choose' => array(
'form id' => 'panels_panel_context_edit_layout',
),
'move' => array(
'include' => array(
drupal_get_path('module', 'panels') . '/includes/display-layout.inc',
),
'form id' => 'panels_panel_context_edit_move',
'submit' => 'panels_change_layout_submit',
),
),
),
),
'content' => array(
'title' => t('Content'),
'description' => t('Add content items and change their location with a drag and drop interface.'),
'ajax' => FALSE,
'form' => array(
'order' => array(
'form' => t('Content'),
),
'forms' => array(
'form' => array(
'include' => array(
drupal_get_path('module', 'panels') . '/includes/display-edit.inc',
),
'form id' => 'panels_panel_context_edit_content',
'no blocks' => TRUE,
),
),
),
),
'preview' => array(
'title' => t('Preview'),
'description' => t('Get a preview of what this variant will look like.'),
'form' => 'panels_panel_context_edit_preview',
'ajax' => FALSE,
'silent' => TRUE,
'form info' => array('finish text' => t('Preview')),
'no update and save' => TRUE,
),
),
'tab operation' => 'panels_panel_context_tab_operation',
// Callback to render the data.
'render' => 'panels_panel_context_render',
// Callback to return addressable data
'addressable callback' => 'panels_panel_context_get_addressable',
// Various callbacks for operations performed on the handler to ensure
// related data is updated properly.
'save' => 'panels_panel_context_save',
'delete' => 'panels_panel_context_delete',
'export' => 'panels_panel_context_export',
'clone' => 'panels_panel_context_clone',
'add features' => array(
'criteria' => t('Selection rules'),
'context' => t('Contexts'),
),
// Where to go when finished.
'add finish' => 'content',
'required forms' => array(
'choose' => t('Choose layout'),
'settings' => t('Panel settings'),
'content' => t('Panel content'),
),
'edit forms' => array(
'content' => t('Panel content'),
'criteria' => t('Selection rules'),
'settings' => t('General'),
'context' => t('Contexts'),
'layout' => t('Change layout'),
'move' => '', // no title makes it a 'hidden' edit form.
),
'forms' => array(
'settings' => array(
'form id' => 'panels_panel_context_edit_settings',
),
'choose' => array(
'form id' => 'panels_panel_context_edit_choose',
'no back validate' => TRUE,
),
'layout' => array(
'no return' => TRUE,
'form id' => 'panels_panel_context_edit_layout',
),
'move' => array(
'include' => array(
drupal_get_path('module', 'panels') . '/includes/display-layout.inc',
),
'form id' => 'panels_panel_context_edit_move',
'submit' => 'panels_change_layout_submit',
),
'content' => array(
'include' => array(
drupal_get_path('module', 'panels') . '/includes/display-edit.inc',
),
'form id' => 'panels_panel_context_edit_content',
'no blocks' => TRUE,
),
'context' => array(
'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
'form id' => 'ctools_context_handler_edit_context',
),
'criteria' => array(
'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
'form id' => 'ctools_context_handler_edit_criteria',
),
),
'default conf' => array(
'title' => t('Panel'),
'no_blocks' => FALSE,
'pipeline' => variable_get('panels_renderer_default', 'standard'),
'body_classes_to_remove' => '',
'body_classes_to_add' => '',
'css_id' => '',
'css' => '',
'contexts' => array(),
'relationships' => array(),
),
);
/**
* Provide the operation trail for the 'Edit panel' link.
*
* When editing the panel, go directly to the content tab.
*/
function panels_panel_context_tab_operation($handler, $contexts, $args) {
return array('handlers', $handler->name, 'content');
}
/**
* Get the display for a task handler.
*
* There are three methods that the display can be found.
* - In the database. $handler->conf['did'] will be set in this case,
* and $handler->conf['display'] won't be.
* - In $handler->conf['display'], with $handler->conf['did'] empty. This
* will be true for a default/imported task handler as well as a handler
* that has just been created but has not yet been saved.
* - in $handler->conf['display'] with $handler->conf['did' populated. This
* simply means that the display has been modified and is awaiting
* save. The modified one should always be used for editing purposes.
* - If none of the above is true, then a new display needs to be created
* for the handler and pla
*/
function &panels_panel_context_get_display(&$handler) {
if (isset($handler->conf['display'])) {
return $handler->conf['display'];
}
if (isset($handler->conf['did'])) {
$handler->conf['display'] = panels_load_display($handler->conf['did']);
// Check for a valid display. If no valid display can be loaded, something
// is wrong and we'll create a new one.
if (!empty($handler->conf['display'])) {
return $handler->conf['display'];
}
}
$handler->conf['display'] = panels_new_display();
return $handler->conf['display'];
}
/**
* Build the cache key so that the editor and IPE can properly find
* everything needed for this display.
*/
function panels_panel_context_cache_key($task_name, $handler_id, $args) {
$arguments = array();
foreach ($args as $arg) {
// Sadly things like panels everywhere actually use non-string arguments
// and they basically can't be represented here. Luckily, PE also does
// not use a system where this matters, so replace its args with a 0
// for a placeholder.
if (is_string($arg)) {
$arguments[] = $arg;
}
else {
$arguments[] = '0';
}
}
$cache_key = 'panel_context:' . $task_name . '::' . $handler_id . '::' . implode('\\', $arguments) . '::';
return $cache_key;
}
/**
* Check selection rules and, if passed, render the contexts.
*/
function panels_panel_context_render($handler, $base_contexts, $args, $test = TRUE) {
// Go through arguments and see if they match.
ctools_include('context');
ctools_include('context-task-handler');
ctools_include('plugins', 'panels');
// Add my contexts
$contexts = ctools_context_handler_get_handler_contexts($base_contexts, $handler);
// Test.
if ($test && !ctools_context_handler_select($handler, $contexts)) {
return;
}
if (isset($handler->handler)) {
ctools_context_handler_pre_render($handler, $contexts, $args);
}
// Load the display
$display = panels_panel_context_get_display($handler);
$display->context = $contexts;
$display->args = $args;
$page_css_id = ctools_context_keyword_substitute($handler->conf['css_id'], array(), $contexts);
$display->css_id = check_plain($page_css_id);
$task_name = page_manager_make_task_name($handler->task, $handler->subtask);
$display->cache_key = panels_panel_context_cache_key($task_name, $handler->name, $args);
// Check to see if there is any CSS.
if (!empty($handler->conf['css'])) {
ctools_include('css');
$css_id = 'panel_context:' . $handler->name;
$filename = ctools_css_retrieve($css_id);
if (!$filename) {
// Add keywords from context
$css = ctools_context_keyword_substitute($handler->conf['css'], array(), $contexts, array('css safe' => TRUE));
$filename = ctools_css_store($css_id, $css);
}
drupal_add_css($filename);
}
// With an argument, this actually sets the display.
panels_get_current_page_display($display);
$renderer = panels_get_renderer($handler->conf['pipeline'], $display);
// If the IPE is enabled, but the user does not have access to edit
// load the standard renderer instead.
$parents = class_parents($renderer);
if (!empty($parents['panels_renderer_editor']) && !user_access('user page manager') && !user_access('use ipe with page manager')) {
$renderer = panels_get_renderer_handler('standard', $display);
}
// Remove and add body element classes
$panel_body_css = &drupal_static('panel_body_css');
if (isset($handler->conf['body_classes_to_remove'])) {
$classes = ctools_context_keyword_substitute($handler->conf['body_classes_to_remove'], array(), $contexts, array('css safe' => TRUE));
if (!isset($panel_body_css['body_classes_to_remove'])) {
$panel_body_css['body_classes_to_remove'] = check_plain($classes);
}
else{
$panel_body_css['body_classes_to_remove'] .= ' ' . check_plain($classes);
}
}
if (isset($handler->conf['body_classes_to_add'])) {
$classes = ctools_context_keyword_substitute($handler->conf['body_classes_to_add'], array(), $contexts, array('css safe' => TRUE));
if (!isset($panel_body_css['body_classes_to_add'])) {
$panel_body_css['body_classes_to_add'] = check_plain($classes);
}
else {
$panel_body_css['body_classes_to_add'] .= ' '. check_plain($classes);
}
}
$info = array(
'content' => panels_render_display($display, $renderer),
'no_blocks' => !empty($handler->conf['no_blocks']),
);
$info['title'] = $display->get_title();
return $info;
}
/**
* Callback to allow the handler to react to being saved.
*
* When a handler with a display is saved, two things have to happen.
* First, we have to save the display so that it becomes a real display,
* not the fake one we started with. Second, we have to cache
* any CSS that the display is using. This CSS can get re-cached
* later if the file disappears, but it's imperative that we do it here
* to make sure that old, dirty CSS cache gets removed.
*/
function panels_panel_context_save(&$handler, $update) {
// Only save the display if we believe it has been modified.
if (isset($handler->conf['display'])) {
panels_save_display($handler->conf['display']);
$handler->conf['did'] = $handler->conf['display']->did;
unset($handler->conf['display']);
}
// Delete any previous CSS cache file.
ctools_include('css');
ctools_css_clear('panel_context:' . $handler->name);
if (isset($page->conf['temp_layout'])) {
unset($page->conf['temp_layout']);
}
}
/**
* Special handling for exporting a panel task handler.
*
* When a panel is exported, we need to export the display separately
* rather than just letting its object be unpacked, which does not work
* very well.
*/
function panels_panel_context_export(&$handler, $indent) {
$display = panels_panel_context_get_display($handler);
foreach (array('display', 'did', 'css_cache', 'temp_layout') as $item) {
if (isset($handler->conf[$item])) {
unset($handler->conf[$item]);
}
}
$output = panels_export_display($display, $indent);
$output .= $indent . '$handler->conf[\'display\'] = $display' . ";\n";
return $output;
}
/**
* When a handler is cloned, we have to clone the display.
*/
function panels_panel_context_clone(&$handler) {
$old_display = panels_panel_context_get_display($handler);
$code = panels_export_display($old_display);
eval($code);
foreach (array('display', 'did', 'css_cache', 'temp_layout') as $item) {
if (isset($handler->conf[$item])) {
unset($handler->conf[$item]);
}
}
$display = (object) array(
'did' => 'new',
'uuid' => ctools_uuid_generate(),
);
$handler->conf['display'] = $display;
}
/**
* Callback to delete the display when a handler is deleted.
*/
function panels_panel_context_delete(&$handler) {
if (!empty($handler->conf['did'])) {
panels_delete_display($handler->conf['did']);
}
}
/**
* Set up a title for the panel based upon the selection rules.
*/
function panels_panel_context_title($handler, $task, $subtask) {
if (isset($handler->conf['title'])) {
return check_plain($handler->conf['title']);
}
else {
return t('Panel');
}
}
/**
* Provide a nice little summary of what's in a panel.
*
* The task handler manager provides a summary of a given handler in a
* collapsible div. This callback provides that. For a Panel, we
* provide a summary of the layout type and content on one side, and
* a summary of the contexts in use on the other.
*/
function panels_panel_context_admin_summary($handler, $task, $subtask, $page, $show_title = TRUE) {
$task_name = page_manager_make_task_name($task['name'], $subtask['name']);
$output = '';
$display = panels_panel_context_get_display($handler);
ctools_include('plugins', 'panels');
ctools_include('context');
ctools_include('context-task-handler');
// Get the operations
$operations = page_manager_get_operations($page);
// Get operations for just this handler.
$operations = $operations['handlers']['children'][$handler->name]['children']['actions']['children'];
$args = array('handlers', $handler->name, 'actions');
$rendered_operations = page_manager_render_operations($page, $operations, array(), array('class' => array('actions')), 'actions', $args);
$layout = panels_get_layout($display->layout);
$plugin = page_manager_get_task_handler($handler->handler);
$object = ctools_context_handler_get_task_object($task, $subtask, $handler);
$display->context = ctools_context_load_contexts($object, TRUE);
$access = ctools_access_group_summary(!empty($handler->conf['access']) ? $handler->conf['access'] : array(), $display->context);
if ($access) {
$access = t('This panel will be selected if @conditions.', array('@conditions' => $access));
}
else {
$access = t('This panel will always be selected.');
}
$rows = array();
$type = $handler->type == t('Default') ? t('In code') : $handler->type;
$rows[] = array(
array('class' => t('page-summary-label'), 'data' => t('Storage')),
array('class' => t('page-summary-data'), 'data' => $type),
array('class' => t('page-summary-operation'), 'data' => ''),
);
if (!empty($handler->disabled)) {
$link = l(t('Enable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'enable')));
$text = t('Disabled');
}
else {
$link = l(t('Disable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'disable')));
$text = t('Enabled');
}
$rows[] = array(
array('class' => t('page-summary-label'), 'data' => t('Status')),
array('class' => t('page-summary-data'), 'data' => $text),
array('class' => t('page-summary-operation'), 'data' => $link),
);
$link = l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'criteria')));
$rows[] = array(
array('class' => t('page-summary-label'), 'data' => t('Selection rule')),
array('class' => t('page-summary-data'), 'data' => $access),
array('class' => t('page-summary-operation'), 'data' => $link),
);
$link = l(t('Change layout'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'layout')));
$link .= '
' . l(t('Edit content'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'content')));
$link .= '
' . l(t('Preview'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'preview')));
$rows[] = array(
array('class' => t('page-summary-label'), 'data' => t('Layout')),
array('class' => t('page-summary-data'), 'data' => check_plain($layout['title'])),
array('class' => t('page-summary-operation'), 'data' => $link),
);
$content_link = ' [' . l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'content'))) . ']';
$context_link = ' [' . l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'context'))) . ']';
$info = theme('table', array('rows' => $rows, 'attributes' => array('class' => 'page-manager-handler-summary')));
$title = $handler->conf['title'];
if ($title != t('Panel')) {
$title = t('Panel: @title', array('@title' => $title));
}
$output .= '