Commit db845230 authored by Riccardo Padovani's avatar Riccardo Padovani

Updated module panels to version 7.x-3.4

parent adf534e1
File mode changed from 100644 to 100755
This module provides by default the ability to translate panel display and
panel pane titles.
Further it introduced an extension to the ctools content_types plugin.
You can now define translatable settings which will be registered in i18n.
Out of the box the module extends the custom content content_type to allow
translation of the content.
Requirements:
Ctools 7.x-1.x-dev (Jan 28-2014 or newer)
Panels 7.x-3.x-dev (Jan 28-2014 or newer)
Plugin definition extension:
------------------------------
This example shows how the content_type custom is extended:
#### Default: ####
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t('Custom content'),
'no title override' => TRUE,
'defaults' => array('admin_title' => '', 'title' => '', 'body' => '', 'format' => filter_fallback_format(), 'substitute' => TRUE),
'js' => array('misc/autocomplete.js', 'misc/textarea.js', 'misc/collapse.js'),
// Make sure the edit form is only used for some subtypes.
'edit form' => '',
'add form' => '',
'edit text' => t('Edit'),
'all contexts' => TRUE,
);
#### Extended Configuration: ####
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t('Custom content'),
'no title override' => TRUE,
'defaults' => array('admin_title' => '', 'title' => '', 'body' => '', 'format' => filter_fallback_format(), 'substitute' => TRUE),
'js' => array('misc/autocomplete.js', 'misc/textarea.js', 'misc/collapse.js'),
// Make sure the edit form is only used for some subtypes.
'edit form' => '',
'add form' => '',
'edit text' => t('Edit'),
'all contexts' => TRUE,
'i18n_settings' = array(
'title',
'body' => array('format' => 'plain_text'),
'items|0|title'
),
);
The new key "i18n_settings" defines an array with the settings that are
translatable. The array contains the names of the settings, they have to be
available in the "defaults" array of the content definition. If you need to
define a format use the name of the setting as the array item key and as item
another array with the detail configuration. E.g
'i18n_settings' = array('body' => array('format' => 'plain_text'))
If i18n_settings is a string it's used as callback. The expected return is an
array equal to the one used in the fix configuration.
You can even declare nested settings as translatable, to do so use '|' as
delimiter.
E.g. 'items|0|title' is evaluated as $settings['items'][0]['title']
#### Callback: ####
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t('Custom content'),
'no title override' => TRUE,
'defaults' => array('admin_title' => '', 'title' => '', 'body' => '', 'format' => filter_fallback_format(), 'substitute' => TRUE),
'js' => array('misc/autocomplete.js', 'misc/textarea.js', 'misc/collapse.js'),
// Make sure the edit form is only used for some subtypes.
'edit form' => '',
'add form' => '',
'edit text' => t('Edit'),
'all contexts' => TRUE,
'i18n_settings' => 'ctools_custom_content_type_i18n_settings',
);
function ctools_custom_content_type_i18n_settings($conf) {
return array(
'title',
'body' => array('format' => $conf['format']),
);
}
<?php
/**
* @file
* Internationalization (i18n) hooks
*/
/**
* Implements hook_i18n_object_info().
*/
function i18n_panels_i18n_object_info() {
$info['pane_configuration'] = array(
'title' => t('Pane Configuration'),
'key' => 'uuid',
'string translation' => array(
'textgroup' => 'panels',
'type' => 'pane_configuration',
'properties' => array(
'title' => t('Pane Title'),
),
),
);
$info['display_configuration'] = array(
'title' => t('Display Configuration'),
'key' => 'uuid',
'string translation' => array(
'textgroup' => 'panels',
'type' => 'display_configuration',
'properties' => array(
'title' => t('Display Title'),
),
),
);
return $info;
}
/**
* Implements hook_i18n_string_info().
*/
function i18n_panels_i18n_string_info() {
$groups['panels'] = array(
'title' => t('Panels'),
'description' => t('Translatable panels items: display and pane configuration items. E.g. Title.'),
// This group doesn't have strings with format.
'format' => FALSE,
// This group can list all strings.
'list' => FALSE,
);
return $groups;
}
name = Panels translation
description = Supports translatable panels items.
dependencies[] = i18n
dependencies[] = panels
dependencies[] = i18n_string
dependencies[] = i18n_translation
package = Multilingual - Internationalization
core = 7.x
; Information added by Drupal.org packaging script on 2014-02-12
version = "7.x-3.4"
core = "7.x"
project = "panels"
datestamp = "1392221614"
<?php
/**
* @file
* Internationalization (i18n) submodule: Panels translation.
*/
/**
* Implements hook_requirements().
*/
function i18n_panels_requirements($phase) {
$requirements = array();
// Check only for status report, to allow update / install.
if ($phase == 'runtime') {
// Check if the panels module runs with uuids.
$requirements['uuid'] = array(
'title' => t('Panels uuid support.'),
'severity' => REQUIREMENT_OK,
'value' => t('Available'),
);
if (!db_field_exists('panels_pane', 'uuid')) {
$requirements['uuid']['severity'] = REQUIREMENT_ERROR;
$requirements['uuid']['value'] = t('Not found. Please apply the provided patches and run the update script.');
}
}
return $requirements;
}
<?php
/**
* @file
* Internationalization (i18n) submodule: Panels translation.
*/
/**
* Fetch the i18n_settings of the content type if there are any.
*
* @param stdClass $pane
* The pane to deal with.
*
* @return array|false
* Settings or FALSE if none are present.
*/
function i18n_panels_get_i18n_settings($pane) {
ctools_include('content');
$content_type = ctools_get_content_type($pane->type);
if (isset($content_type['i18n_settings'])) {
if (is_string($content_type['i18n_settings']) && function_exists($content_type['i18n_settings'])) {
$content_type['i18n_settings'] = $content_type['i18n_settings']($pane->configuration);
}
}
// Provide the override title string as translation for all panes that have
// this setting enabled.
if (isset($pane->configuration['override_title']) && $pane->configuration['override_title']) {
if (isset($content_type['i18n_settings']) && is_array($content_type['i18n_settings'])) {
$content_type['i18n_settings'][] = 'override_title_text';
}
else {
$content_type['i18n_settings'] = array('override_title_text');
}
}
return isset($content_type['i18n_settings']) ? $content_type['i18n_settings'] : FALSE;
}
/**
* Returns the translation object of the pane.
*
* @param stdClass $pane
* The pane to deal with.
*
* @return stdClass|FALSE
* Returns FALSE if no translation is necessary.
*/
function i18n_panels_get_i18n_translation_object($pane) {
$translation_object = array();
// Handle content type specific i18n settings.
if ($i18n_settings = i18n_panels_get_i18n_settings($pane)) {
// Register translatable settings.
foreach ($i18n_settings as $i18n_setting => $settings) {
if (!is_array($settings)) {
$i18n_setting = $settings;
$settings = array('format' => 'plain_text');
}
$translation_object[$i18n_setting] = NULL;
$key_exists = FALSE;
// Ensure a nested setting is "unpacked".
$config_value = drupal_array_get_nested_value($pane->configuration, explode('|', $i18n_setting), $key_exists);
// If we reached the end of the nested setting use the value as source.
if ($key_exists) {
$translation_object[$i18n_setting] = array(
'string' => $config_value,
'format' => $settings['format'],
);
$translation_object['panels_i18n_settings'][$i18n_setting] = $settings;
}
}
}
// Check if this pane has a custom title enabled.
if (!empty($pane->configuration['override_title'])) {
$translation_object['title']['string'] = $pane->configuration['override_title_text'];
}
if (!empty($translation_object)) {
return (object) $translation_object;
}
return FALSE;
}
/**
* Implements hook_panels_pane_insert().
*
* @param stdClass $pane
* The pane to deal with.
*/
function i18n_panels_panels_pane_insert($pane) {
i18n_panels_panels_pane_update($pane);
}
/**
* Implements hook_panels_pane_update().
*
* @param stdClass $pane
* The pane to deal with.
*/
function i18n_panels_panels_pane_update($pane) {
if ($translation_object = i18n_panels_get_i18n_translation_object($pane)) {
$translation_object->uuid = $pane->uuid;
$status = i18n_string_object_update('pane_configuration', $translation_object);
}
}
/**
* Implements hook_panels_pane_delete().
*
* @param array $pids
* Array with the panel ids to delete.
*/
function i18n_panels_panels_pane_delete($pids) {
if (!empty($pids)) {
// Fetch the uuids from the db.
$uuids = db_select('panels_pane')
->fields('panels_pane', array('uuid'))
->condition('pid', $pids)
->execute()
->fetchCol();
foreach ($uuids as $uuid) {
// Create dummy pane with uuid as property.
$pane = (object) array('uuid' => $uuid);
i18n_string_object_remove('pane_configuration', $pane);
}
}
}
/**
* Implements hook_panels_pane_prerender().
*
* @param stdClass $pane
* The pane to deal with.
*/
function i18n_panels_panels_pane_prerender($pane) {
// Check if this pane has translations.
if (isset($pane->uuid) && $translation_object = i18n_panels_get_i18n_translation_object($pane)) {
$translation_object->uuid = $pane->uuid;
// Send to translation.
$translation_object = i18n_string_object_translate('pane_configuration', $translation_object);
unset($translation_object->uuid, $translation_object->i18n_settings);
foreach ($translation_object as $i18n_setting => $translated_setting) {
if ($i18n_setting != 'panels_i18n_settings') {
if (is_array($translated_setting)) {
$translated_setting = $translated_setting['string'];
}
drupal_array_set_nested_value($pane->configuration, explode('|', $i18n_setting), $translated_setting);
}
}
}
}
/**
* Implements hook_panels_display_save().
*
* @param panels_display $display
* The display to deal with.
*/
function i18n_panels_panels_display_save($display) {
$status = i18n_string_object_update('display_configuration', $display);
}
/**
* Implements hook_panels_display_delete().
*
* @param int $did
* Id of the display to delete.
*/
function i18n_panels_panels_delete_display($did) {
// Fetch uuid to delete the translations.
$uuid = db_select('panels_display')
->fields('panels_display', array('uuid'))
->condition('did', $did)
->execute()
->fetchColumn();
// Build a dummy display.
$display = (object) array('uuid' => $uuid);
// Check if this display was just saved in the db.
if (!_18n_panels_is_exported_panels_display($display)) {
// If the display was just saved in the db remove all translations.
i18n_string_object_remove('display_configuration', $display);
// Remove related pane translations too.
$pids = db_select('panels_pane')
->fields('panels_pane', array('pid'))
->condition('did', $did)
->execute()
->fetchCol();
i18n_panels_panels_pane_delete($pids);
}
else {
// If the display is exported leave the translated strings but give the user
// a hint how to clean up.
drupal_set_message(
t(
'The reverted panels display(s) were exported, please run a <a href="!link">string refresh</a> to update the translatable strings.',
array('!link' => url('admin/config/regional/translate/i18n_string'))
),
'warning',
FALSE
);
}
}
/**
* Implements hook_panels_pre_render().
*
* This function must not rely on the passed $renderer parameter. The parameter
* could be empty because this function is reused in i18n_ctools_render_alter().
* @todo Check if a drupal_alter() in panels_display::get_title() is applicable.
*
* @see i18n_ctools_render_alter()
*
* @param panels_display $display
* The display to deal with.
* @param panels_renderer_standard $renderer
* The renderer to deal with.
*/
function i18n_panels_panels_pre_render(&$display, $renderer) {
// Avoid double translations.
if (!isset($display->i18n_panels_title_translated)) {
$translation = i18n_string_object_translate('display_configuration', $display);
if (is_array($translation->title)) {
$display->title = $translation->title['string'];
}
else {
$display->title = $translation->title;
}
$display->i18n_panels_title_translated = TRUE;
}
}
/**
* Implements hook_ctools_render_alter().
*
* Under some circumstances the title of the panel page is set before
* hook_panels_pre_render() is fired. Such cases can be handled with this hook.
* @todo Check if a drupal_alter() in panels_display::get_title() is applicable.
*/
function i18n_ctools_render_alter(&$info, $page, $context) {
// @todo Find a better way to detect a panels page.
if ($page === TRUE && !empty($info['content']['#display']) && $info['content']['#display'] instanceof panels_display) {
i18n_panels_panels_pre_render($info['content']['#display'], NULL);
// Set the info title. This is used to set the page title.
$info['title'] = $info['content']['#display']->get_title();
}
}
/**
* Implements hook_ctools_plugin_post_alter().
*
* Register some translatable configuration settings for plugins.
*
*/
function i18n_panels_ctools_plugin_post_alter(&$plugin, $plugin_type_info) {
if ($plugin_type_info['type'] == 'content_types') {
// Modify custom content.
if ($plugin['name'] == 'custom') {
// Register callback to get the translatable settings.
$plugin['i18n_settings'] = 'ctools_custom_content_type_i18n_settings';
}
}
}
/**
* Callback to provide the translatable settings appropriate to the config.
*
* @param array $conf
* Content type configuration.
*
* @return array
* i18n_settings configuration.
*/
function ctools_custom_content_type_i18n_settings($conf) {
return array(
'title',
'body' => array('format' => $conf['format']),
);
}
/**
* Implements hook_i18n_string_list_TEXTGROUP_alter().
*
* Necessary to support the dynamic translatable settings defined by ctools
* content types.
*/
function i18n_panels_i18n_string_list_panels_alter(&$strings, $type = NULL, $object = NULL) {
if (isset($object->panels_i18n_settings)) {
foreach ($object->panels_i18n_settings as $i18n_setting => $settings) {
if (isset($object->{$i18n_setting})) {
$strings['panels'][$type][$object->uuid][$i18n_setting] = $object->{$i18n_setting};
}
}
}
}
/**
* Implements hook_i18n_string_list().
*
* @todo Figure out a generic solution to fetch exported displays.
*/
function i18n_panels_i18n_string_list($group) {
$strings = array();
if ($group == 'panels') {
// Fetch all available displays.
$displays = _18n_panels_fetch_all_panel_displays();
foreach ($displays as $display) {
if (empty($display->uuid)) {
drupal_set_message(t('The display %display has no uuid, please resave or re-export it.', array('%display' => $display->did)), 'warning');
continue;
}
// Avoid duplicated runs _18n_panels_fetch_all_panel_displays() probably
// returns the same display twice, one for the db based and one for the
// exported one.
if (isset($strings['panels']['display_configuration'][$display->uuid])) {
continue;
}
$strings['panels']['display_configuration'][$display->uuid]['title']['string'] = $display->title;
foreach ($display->content as $pane) {
if (empty($pane->uuid)) {
// Fetch exported uuid and validate it.
$uuid = str_replace('new-', '', $pane->pid);
if (!panels_uuid_is_valid($uuid)) {
drupal_set_message(t('The pane %pane has no uuid, please resave or re-export it.', array('%pane' => $pane->pid)), 'warning');
continue;
}
$pane->uuid = $uuid;
}
if ($translation_object = i18n_panels_get_i18n_translation_object($pane)) {
// Split up all strings and add them to the list.
$pane_strings = (array) $translation_object;
unset($pane_strings['panels_i18n_settings']);
foreach ($pane_strings as $key => $pane_string) {
$strings['panels']['pane_configuration'][$pane->uuid][$key] = $pane_string;
}
}
}
}
}
return $strings;
}
/**
* Checks if the give display is exported or only stored in the db.
*
* @return boolean
* TRUE if the display is available from code.
*/
function _18n_panels_is_exported_panels_display($display) {
if (isset($display->uuid)) {
$displays = _18n_panels_fetch_all_panel_displays();
return isset($displays['exported-' . $display->uuid]);
}
return FALSE;
}
/**
* Returns a list of really all available panel displays.
*
* The list is statically cached. Use the parameter $reset to refresh the list
* during the same request.
* Probably returns the same display twice - once with the db based and once
* the exported one.
*
* @todo I bet there are better ways to solve this mess.
*
* @param boolean $reset
* Reset the static cache.
*
* @return array
* List of all panel displays.
*/
function _18n_panels_fetch_all_panel_displays($reset = FALSE) {
$displays = &drupal_static(__FUNCTION__, array());
if (!empty($displays) && !$reset) {
return $displays;
}
// Fetch db based displays.
$dids = db_select('panels_display')->fields('panels_display', array('did'))->execute()->fetchCol();
$displays = panels_load_displays($dids);
// Fetch exported displays.
ctools_include('export');
foreach (ctools_export_crud_load_all('panels_display') as $panels_display) {
if (!empty($panels_display->uuid)) {
$displays['exported-' . $panels_display->uuid] = $panels_display;
}
}
// Fetch mini panels.
$mini_panels = ctools_export_crud_load_all('panels_mini');
foreach ($mini_panels as $pane) {
if (!empty($pane->display->uuid)) {
$displays['exported-' . $pane->display->uuid] = $pane->display;
}
}
// Fetch in page manager embedded displays.
if (module_exists('page_manager')) {
module_load_include('inc', 'page_manager', 'page_manager.admin');
$tasks = page_manager_get_tasks_by_type('page');
$pages = array('operations' => array(), 'tasks' => array());
page_manager_get_pages($tasks, $pages);
foreach ($pages['tasks'] as $task) {
$page = page_manager_cache_load($task);
$task_info = page_manager_get_task_subtasks($page->task);
foreach ($page->handler_info as $id => $info) {
$page_manager_handler = $page->handlers[$id];
if ($page_manager_handler->handler == 'panel_context') {
// @todo Is there really no better way to check this?
$is_exported = ($page_manager_handler->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE) || (isset($page->subtask['storage']) && $page->subtask['storage'] == t('Overridden')));
if (!empty($page_manager_handler->conf['display'])) {
$panels_display = $page_manager_handler->conf['display'];
$displays['exported-' . $panels_display->uuid] = $panels_display;
}
elseif ($is_exported && isset($page_manager_handler->conf['did'])) {
$panels_display = panels_load_display($page_manager_handler->conf['did']);
if (isset($panels_display->uuid)) {
$displays['exported-' . $panels_display->uuid] = $panels_display;
}
}
}
}
}
}
// Fetch panelizer displays.
if (module_exists('panelizer')) {
// Fetch all default handlers.
$panelizer_defaults = ctools_export_crud_load_all('panelizer_defaults');
foreach ($panelizer_defaults as $panelizer_default) {
$displays['exported-' . $panelizer_default->display->uuid] = $panelizer_default->display;
}
}
return $displays;
}
......@@ -172,6 +172,22 @@ function panels_admin_settings_page() {
}
}
ctools_include('plugins', 'panels');
$pipelines = panels_get_renderer_pipelines();
$options = array();
foreach ($pipelines as $key => $value) {
$options[$key] = $value->admin_title;
}
if (count($options) > 1) {
$form['panels_renderer_default'] = array(
'#type' => 'select',
'#title' => t('Default renderer'),
'#options' => $options,
'#default_value' => variable_get('panels_renderer_default', 'standard'),
'#description' => t('The default renderer for new panel pages.'),
);
}
if (empty($form)) {
return array('#value' => t('There are currently no settings to change, but additional plugins or modules may provide them in the future.'));
}
......
......@@ -477,6 +477,7 @@ function panels_common_get_allowed_layout_object($module_name) {
* Get the allowed layouts for the given module.
*/
function panels_common_get_allowed_layouts($module_name) {
ctools_include('plugins', 'panels');
$available_layouts = panels_get_layouts();
if (empty($module_name)) {
return $available_layouts;
......
......@@ -173,15 +173,36 @@ class panels_cache_object {
$start = $this->js;
$this->js = array();
// Use the advanced mapping function from Drupal >= 7.23 if available.
$array_mapping_func = function_exists('drupal_array_diff_assoc_recursive') ? 'drupal_array_diff_assoc_recursive' : 'array_diff_assoc';
// If there are any differences between the old and the new javascript then
// store them to be added later.
if ($diff = array_diff_assoc($js, $start)) {
$this->js = $diff;
}
// Special case the settings key and get the difference of the data.
if ($settings_diff = array_diff_assoc($js['settings']['data'], $start['settings']['data'])) {
$this->js['settings'] = $settings_diff;
if ($diff = $array_mapping_func($js, $start)) {
// Iterate over the diff to ensure we keep the keys on merge and don't add
// unnecessary items.
foreach ($diff as $key => $diff_data) {
// Special case the settings key and get the difference of the data.
if ($key === 'settings') {
// Iterate over the diff to ensure we keep the keys on merge and don't
// add unnecessary items.
if (isset($diff[$key]['data'])) {
foreach ($diff[$key]['data'] as $settings_key => $settings_data) {
// Merge the changes with the base to get a complete settings
// array.
$this->js[$key]['data'][] = drupal_array_merge_deep($settings_data, $diff[$key]['data'][$settings_key]);
}
}
}
else {
$this->js[$key] = $diff_data;
// Check if the key was present already and if so merge the changes
// with the original data to get the full settings array.
if (isset($start[$key])) {
$this->js[$key] = drupal_array_merge_deep($start[$key], $this->js[$key]);
}
}
}
}
// And for tokens:
......@@ -213,7 +234,7 @@ class panels_cache_object {
drupal_add_js($args['data'], $args);
}
else {
foreach ($args as $setting) {
foreach ($args['data'] as $setting) {
drupal_add_js($setting, 'setting');
}
}
......
......@@ -16,7 +16,7 @@ Drupal.Panels.bindClickDelete = function(context) {
$('a.pane-delete:not(.pane-delete-processed)', context)
.addClass('pane-delete-processed')
.click(function() {
if (confirm('Remove this pane?')) {
if (confirm(Drupal.t('Remove this pane?'))) {
var id = '#' + $(this).attr('id').replace('pane-delete-', '');
$(id).remove();
Drupal.Panels.Draggable.savePositions();
......
(function ($) {
Drupal.Panels = Drupal.Panels || {};
Drupal.Panels.autoAttach = function() {
if ($.browser.msie) {
// If IE, attach a hover event so we can see our admin links.
$("div.panel-pane").hover(
function() {
$('div.panel-hide', this).addClass("panel-hide-hover"); return true;
},
function() {
$('div.panel-hide', this).removeClass("panel-hide-hover"); return true;
}
);
$("div.admin-links").hover(
function() {
$(this).addClass("admin-links-hover"); return true;
},
function(){
$(this).removeClass("admin-links-hover"); return true;
}
);
}
};
$(Drupal.Panels.autoAttach);
})(jQuery);
<?php
/**
* @file
* Hooks provided by Panels.
*/
/**
* Allow modules to provide their own caching mechanism for the display editor.
*
* @param string $argument
* The second half of the cache key. Full key module:TASK_NAME:HANDLER_NAME
* passed part: TASK_NAME:HANDLER_NAME
* @param stdClass $cache
* The display to cache.
*/
function hook_panels_cache_set($argument, $cache) {
list($handler, $item) = _panels_mini_panels_cache_get($argument);
$item->mini_panels_display_cache = $cache;
$handler->edit_cache_set_key($item, $argument);
}
/**
* Allow modules to provide their own caching mechanism for the display editor.
*
* @param string $argument
* The second half of the cache key. Full key module:TASK_NAME:HANDLER_NAME
* passed part: TASK_NAME:HANDLER_NAME
*
* @return stdClass|NULL
* The cached display or NULL if the cache wasn't hit.
*/
function hook_panels_cache_get($argument) {
ctools_include('common', 'panels');
list($handler, $item) = _panels_mini_panels_cache_get($argument);
if (isset($item->mini_panels_display_cache)) {
return $item->mini_panels_display_cache;
}
$cache = new stdClass();
$cache->display = $item->display;
$cache->display->context = ctools_context_load_contexts($item);
$cache->display->cache_key = 'panels_mini:' . $argument;
$cache->content_types = panels_common_get_allowed_types('panels_mini', $cache->display->context);
$cache->display_title = TRUE;
// @TODO support locking.
$cache->locked = FALSE;
return $cache;
}
/**
* Allow modules to provide their own caching mechanism for the display editor.
*
* @param string $argument
* The second half of the cache key. Full key module:TASK_NAME:HANDLER_NAME
* passed part: TASK_NAME:HANDLER_NAME
* @param stdClass $cache
* The display to cache.
*
* @return stdClass
* The cached display.
*/
function hook_panels_cache_save($argument, $cache) {
list($handler, $item) = _panels_mini_panels_cache_get($argument);
$item->display = $cache->display;
panels_mini_save($item);
$handler->edit_cache_clear($item);
return $item;
}
/**
* Allow modules to provide their own caching mechanism for the display editor.
*
* @param string $argument
* The second half of the cache key. Full key module:TASK_NAME:HANDLER_NAME
* passed part: TASK_NAME:HANDLER_NAME
* @param stdClass $cache
* The cached display.
*/
function hook_panels_cache_clear($argument, $cache) {
list($handler, $item) = _panels_mini_panels_cache_get($argument);
$handler->edit_cache_clear($item);
}
/**
* Allow modules to adjust the rendering array of the panels dashboard.
*
* @param array $vars
* The output variables.
*/
function hook_panels_dashboard_blocks(&$vars) {
$vars['links']['panels_node'] = array(
'title' => l(t('Panel node'), 'node/add/panel'),
'description' => t('Panel nodes are node content and appear in your searches, but are more limited than panel pages.'),
'weight' => -1,
);
}
/**
* Allow to alter the pane content to render.
*
* This happens after the keyword substitution.
*
* @param stdClass $content
* The content block to render.
* @param stdClass $pane
* The pane object.
* @param array $args
* The display arguments.
* @param array $contexts
* Array with the used contexts.
*/
function hook_panels_pane_content_alter($content, $pane, $args, $contexts) {
// Don't display titles.
unset($content->title);
}
/**
* Allow modules to provide a mechanism to break locks.
*
* @param string $argument
* The second half of the cache key. Full key module:TASK_NAME:HANDLER_NAME
* passed part: TASK_NAME:HANDLER_NAME
* @param stdClass $cache
* The cached display.
*/
function hook_panels_edit_cache_break_lock($argument, $cache) {
$cache->locked = FALSE;
}
/**
* Fired before a panels display is rendered.
*
* Last chance to modify the panels display or add output before the keyword
* substitution runs and the panels display is rendered.
*
* @param panels_display $panels_display
* The panels display that will be rendered.
* @param stdClass $renderer
* The renderer object that will be used to render.
*
* @return string
* Additional output to add before the panels display.
*/
function hook_panels_pre_render($panels_display, $renderer) {
$translation = i18n_string_object_translate('panels_display_configuration', $panels_display);
$panels_display->title = $translation->title;
}
/**
* Fired after a panels display is rendered.
*
* Allow to add additional output after the output of the panels display.
*
* @param panels_display $panels_display
* The rendered panels display.
* @param stdClass $renderer
* The used renderer object.
*
* @return string
* Additional output to add after the panels display.
*/
function hook_panels_post_render($panels_display, $renderer) {
return t('Output proudly sponsored by panels.');
}
/**
* Fired before a new pane is inserted in the storage.
*
* @param stdClass $pane
* Pane that will be rendered.
*/
function hook_panels_pane_insert($pane) {
// Check if this pane has a custom title enabled.
if (!empty($pane->configuration['override_title'])) {
$translation_object = (object) array(
'pid' => $pane->pid,
'title' => $pane->configuration['override_title_text'],
);
$status = i18n_string_object_update('panels_pane_configuration', $translation_object);
}
}
/**
* Fired before a changed pane is updated in the storage.
*
* @param stdClass $pane
* Pane that will be rendered.
*/
function hook_panels_pane_update($pane) {
// Check if this pane has a custom title enabled.
if (!empty($pane->configuration['override_title'])) {
$translation_object = (object) array(
'pid' => $pane->pid,
'title' => $pane->configuration['override_title_text'],
);
$status = i18n_string_object_update('panels_pane_configuration', $translation_object);
}
}
/**
* Fired before a panel is rendered.
*
* Last chance to modify the pane before the keyword substitution runs and the
* pane is rendered.
*
* @param stdClass $pane
* Pane that will be rendered.
*/
function hook_panels_pane_prerender($pane) {
// Check if this pane has a custom title enabled.
if (!empty($pane->configuration['override_title'])) {
$translation_object = (object) array(
'pid' => $pane->pid,
'title' => $pane->configuration['override_title_text'],
);
$translation_object = i18n_string_object_translate('panels_pane_configuration', $translation_object);
$pane->configuration['override_title_text'] = $translation_object->title;
}
}
/**
* Fired before panes are deleted.
*
* @param array $pids
* Array with the panel id's to delete.
*/
function hook_panels_pane_delete($pids) {
foreach ($pids as $pid) {
// Create dummy pane with pid as property.
$pane = (object) array('pid' => $pid);
i18n_string_object_remove('panels_pane_configuration', $pane);
}
}
/**
* Fired after a display is saved.
*
* @param panels_display $display
* The display to save.
*/
function hook_panels_display_save($display) {
i18n_string_object_update('display_configuration', $display);
}
/**
* Fired before a display is deleted.
*
* @param integer $did
* Id of the display to delete.
*/
function hook_panels_delete_display($did) {
$uuid = db_select('panels_display')
->fields('panels_display', array('uuid'))
->condition('did', $did)
->execute()
->fetchColumn();
$display = (object) array('uuid' => $uuid);
i18n_string_object_remove('display_configuration', $display);
}
......@@ -3,16 +3,16 @@ description = Core Panels display functions; provides no external UI, at least o
core = 7.x
package = "Panels"
configure = admin/structure/panels
dependencies[] = ctools
dependencies[] = ctools (>=1.4)
files[] = panels.module
files[] = includes/common.inc
files[] = includes/legacy.inc
files[] = includes/plugins.inc
files[] = plugins/views/panels_views_plugin_row_fields.inc
; Information added by drupal.org packaging script on 2012-08-18
version = "7.x-3.3"
; Information added by Drupal.org packaging script on 2014-02-12
version = "7.x-3.4"
core = "7.x"
project = "panels"
datestamp = "1345319572"
datestamp = "1392221614"
......@@ -47,7 +47,27 @@ function panels_requirements_install() {
function panels_schema() {
// This should always point to our 'current' schema. This makes it relatively easy
// to keep a record of schema as we make changes to it.
return panels_schema_4();
return panels_schema_5();
}
function panels_schema_5() {
$schema = panels_schema_4();
$schema['panels_display']['fields']['uuid'] = array(
'type' => 'char',
'length' => '36',
);
$schema['panels_display']['export']['key'] = 'uuid';
$schema['panels_display']['export']['key name'] = 'UUID';
$schema['panels_pane']['fields']['uuid'] = array(
'type' => 'char',
'length' => '36',
);
$schema['panels_pane']['export']['key'] = 'uuid';
$schema['panels_pane']['export']['key name'] = 'UUID';
return $schema;
}
function panels_schema_4() {
......@@ -331,6 +351,8 @@ function panels_schema_3() {
'primary key' => array('lid'),
);
$schema['cache_panels'] = drupal_get_schema_unprocessed('system', 'cache');
return $schema;
}
......@@ -375,3 +397,83 @@ function panels_update_7301() {
return t('panels_pane.lock field already existed, update skipped.');
}
/**
* Adding universally unique identifiers to panels.
*/
function panels_update_7302() {
// Load the schema.
$schema = panels_schema_5();
$msg = array();
// Add the uuid column to the pane table.
$table = 'panels_pane';
$field = 'uuid';
// Due to a previous failure, the column may already exist:
if (!db_field_exists($table, $field)) {
$spec = $schema[$table]['fields'][$field];
db_add_field($table, $field, $spec);
$msg[] = t('Added panels_pane.uuid column.');
}
// Add the uuid column to the display table.
$table = 'panels_display';
$field = 'uuid';
// Due to a previous failure, the column may already exist:
if (!db_field_exists($table, $field)) {
$spec = $schema[$table]['fields'][$field];
db_add_field($table, $field, $spec);
$msg[] = t('Added panels_display.uuid column.');
}
if (empty($msg)) {
$msg[] = t('UUID column already present in the panels_display & panels_pane tables.');
}
// Update all DB-based panes & displays to ensure that they all contain a UUID.
$display_dids = db_select('panels_display')
->fields('panels_display', array('did'))
->condition(db_or()
->condition('uuid', '')
->isNull('uuid')
)
->execute()
->fetchCol();
// Check the panes as well, for paranoia.
$pane_dids = db_select('panels_pane')
->distinct()
->fields('panels_pane', array('did'))
->condition(db_or()
->condition('uuid', '')
->isNull('uuid')
)
->execute()
->fetchCol();
$dids = array_unique(array_merge($display_dids, $pane_dids));
if ($displays = panels_load_displays($dids)) {
foreach ($displays as $display) {
// A display save also triggers pane saves.
panels_save_display($display);
}
$msg[] = t('Generated UUIDs for database-based panel displays and panes.');
}
else {
$msg[] = t('No database-based panel displays or panes for which to generate UUIDs.');
}
return implode("\n", $msg);
}
/**
* Add a custom cache table for Panels.
*/
function panels_update_7303() {
$table_name = 'cache_panels';
if (!db_table_exists($table_name)) {
$schema = drupal_get_schema_unprocessed('system', 'cache');
db_create_table($table_name, $schema);
}
}
......@@ -258,7 +258,6 @@ function panels_init() {
}
ctools_add_css('panels', 'panels');
ctools_add_js('panels', 'panels');
}
/**
......@@ -308,6 +307,10 @@ function panels_permission() {
'title' => t('Use panel locks'),
'description' => t('Allows a user to lock and unlock panes in a panel display.'),
),
'use ipe with page manager' => array(
'title' => t("Use the Panels In-Place Editor with Page Manager"),
'description' => t('Allows users with access to the In-Place editor to administer page manager pages. This permission is only needed for users without "use page manager" access.'),
),
);
}
......@@ -322,6 +325,13 @@ function panels_permission() {
// $legacy->determineStatus();
//}
/**
* Implements hook_flush_caches().
*/
function panels_flush_caches() {
return array('cache_panels');
}
// ---------------------------------------------------------------------------
// CTools hook implementations
//
......@@ -652,8 +662,10 @@ class panels_display {
$pane->panel = $location;
}
// Get a temporary pid for this pane.
$pane->pid = "new-" . $this->next_new_pid();
// Generate a permanent uuid for this pane, and use
// it as a temporary pid.
$pane->uuid = ctools_uuid_generate();
$pane->pid = 'new-' . $pane->uuid;
// Add the pane to the approprate spots.
$this->content[$pane->pid] = &$pane;
......@@ -667,23 +679,10 @@ class panels_display {
function clone_pane($pid) {
$pane = clone $this->content[$pid];
$pane->uuid = ctools_uuid_generate();
return $pane;
}
function next_new_pid() {
// We don't use static vars to record the next new pid because
// temporary pids can last for years in exports and in caching
// during editing.
$id = array(0);
foreach (array_keys($this->content) as $pid) {
if (!is_numeric($pid)) {
$id[] = substr($pid, 4);
}
}
$next_id = max($id);
return ++$next_id;
}
/**
* Get the title from a display.
*
......@@ -867,10 +866,13 @@ function panels_load_display($did) {
*
* @ingroup mainapi
*
* Note a new $display only receives a real did once it is run through this function.
* Until then, it uses a string placeholder, 'new', in place of a real did. The same
* applies to all new panes (whether on a new $display or not); in addition,
* panes have sequential numbers appended, of the form 'new-1', 'new-2', etc.
* Note that a new $display only receives a real did once it is run through
* this function, and likewise for the pid of any new pane.
*
* Until then, a new display uses a string placeholder, 'new', in place of
* a real did, and a new pane (whether on a new $display or not) appends a
* universally-unique identifier (which is stored permanently in the 'uuid'
* field). This format is also used in place of the real pid for exports.
*
* @param object $display instanceof panels_display \n
* The display object to be saved. Passed by reference so the caller need not use
......@@ -880,6 +882,9 @@ function panels_load_display($did) {
*/
function panels_save_display(&$display) {
$update = (isset($display->did) && is_numeric($display->did)) ? array('did') : array();
if (empty($display->uuid) || !ctools_uuid_is_valid($display->uuid)) {
$display->uuid = ctools_uuid_generate();
}
drupal_write_record('panels_display', $display, $update);
$pids = array();
......@@ -910,11 +915,26 @@ function panels_save_display(&$display) {
$pane->did = $display->did;
$old_pid = $pane->pid;
if (empty($pane->uuid) || !ctools_uuid_is_valid($pane->uuid)) {
$pane->uuid = ctools_uuid_generate();
}
drupal_write_record('panels_pane', $pane, is_numeric($pid) ? array('pid') : array());
// Allow other modules to take action after a pane is saved.
if ($pane->pid == $old_pid) {
module_invoke_all('panels_pane_update', $pane);
}
else {
module_invoke_all('panels_pane_insert', $pane);
}
if ($pane->pid != $old_pid) {
// and put it back so our pids and positions can be used
unset($display->content[$id]);
// Remove the old new-* entry from the displays content.
unset($display->content[$pid]);
// and put it back so our pids and positions can be used.
$display->content[$pane->pid] = $pane;
// If the title pane was one of our panes that just got its ID changed,
......@@ -945,6 +965,8 @@ function panels_save_display(&$display) {
$display->panels[$id] = $new_panes;
}
if (!empty($pids)) {
// Allow other modules to take action before a panes are deleted.
module_invoke_all('panels_pane_delete', $pids);
db_delete('panels_pane')->condition('pid', $pids)->execute();
}
......@@ -978,6 +1000,7 @@ function panels_delete_display($display) {
else {
$did = $display;
}
module_invoke_all('panels_delete_display', $did);
db_delete('panels_display')->condition('did', $did)->execute();
db_delete('panels_pane')->condition('did', $did)->execute();
}
......@@ -987,9 +1010,11 @@ function panels_delete_display($display) {
*
* This function is primarily intended as a mechanism for cloning displays.
* It generates an exact replica (in code) of the provided $display, with
* the exception that it replaces all ids (dids and pids) with 'new-*' values.
* Only once panels_save_display() is called on the code version of $display will
* the exported display written to the database and permanently saved.
* the exception that it replaces all ids (dids and pids) with place-holder
* values (consisting of the display or pane's uuid, with a 'new-' prefix).
*
* Only once panels_save_display() is called on the code version of $display
* will the exported display be written to the database and permanently saved.
*
* @see panels_page_export() or _panels_page_fetch_display() for sample implementations.
*
......@@ -1011,10 +1036,12 @@ function panels_delete_display($display) {
*/
function panels_export_display($display, $prefix = '') {
ctools_include('export');
if (empty($display->uuid) || !ctools_uuid_is_valid($display->uuid)) {
$display->uuid = ctools_uuid_generate();
}
$display->did = 'new-' . $display->uuid;
$output = ctools_export_object('panels_display', $display, $prefix);
$pid_counter = &drupal_static(__FUNCTION__, 0);
// Initialize empty properties.
$output .= $prefix . '$display->content = array()' . ";\n";
$output .= $prefix . '$display->panels = array()' . ";\n";
......@@ -1024,7 +1051,12 @@ function panels_export_display($display, $prefix = '') {
if (!empty($display->content)) {
$region_counters = array();
foreach ($display->content as $pane) {
$pid = 'new-' . ++$pid_counter;
if (!isset($pane->uuid) || !ctools_uuid_is_valid($pane->uuid)) {
$pane->uuid = ctools_uuid_generate();
}
$pid = 'new-' . $pane->uuid;
if ($pane->pid == $display->title_pane) {
$title_pid = $pid;
}
......@@ -1070,6 +1102,9 @@ function panels_render_display(&$display, $renderer = NULL) {
if (!empty($display->context)) {
if ($form_context = ctools_context_get_form($display->context)) {
$form_context->form['#theme'] = 'panels_render_display_form';
if (empty($form_context->form['#theme_wrappers']) || !in_array('form', $form_context->form['#theme_wrappers'])) {
$form_context['#theme_wrappers'][] = 'form';
}
$form_context->form['#display'] = &$display;
return $form_context->form;
}
......@@ -1086,10 +1121,7 @@ function panels_render_display(&$display, $renderer = NULL) {
* then operate as a theme function of the form.
*/
function theme_panels_render_display_form($vars) {
// @todo this is probably broken in D7
$render = $vars['element']['#display']->render();
$vars['element']['#children'] = $render;
return theme('form', $vars);
return $vars['element']['#display']->render();
}
// @layout
......@@ -1226,7 +1258,9 @@ function template_preprocess_panels_pane(&$vars) {
}
$element = contextual_pre_render_links($element);
$links += $element['#links'];
if(!empty($element['#links'])) {
$links += $element['#links'];
}
}
if ($links) {
......@@ -1276,7 +1310,7 @@ function template_preprocess_panels_pane(&$vars) {
// Add template file suggestion for content type and sub-type.
$vars['theme_hook_suggestions'][] = $base . $delimiter . $content->type;
$vars['theme_hook_suggestions'][] = $base . $delimiter . strtr($content->type, '-', '_') . $delimiter . strtr($content->subtype, '-', '_');
$vars['theme_hook_suggestions'][] = $base . $delimiter . strtr(ctools_cleanstring($content->type, array('lower case' => TRUE)), '-', '_') . $delimiter . strtr(ctools_cleanstring($content->subtype, array('lower case' => TRUE)), '-', '_');
$vars['pane_prefix'] = !empty($content->pane_prefix) ? $content->pane_prefix : '';
$vars['pane_suffix'] = !empty($content->pane_suffix) ? $content->pane_suffix : '';
......@@ -1526,7 +1560,7 @@ function panels_edit_cache_break_lock($cache) {
* Get display edit cache on behalf of panel context.
*
* The key is the second half of the key in this form:
* panel_context:TASK_NAME:HANDLER_NAME;
* panel_context:TASK_NAME::HANDLER_NAME::args::url;
*/
function panel_context_panels_cache_get($key) {
ctools_include('common', 'panels');
......@@ -1535,7 +1569,7 @@ function panel_context_panels_cache_get($key) {
// this loads the panel context inc even if we don't use the plugin.
$plugin = page_manager_get_task_handler('panel_context');
list($task_name, $handler_name) = explode(':', $key, 2);
list($task_name, $handler_name, $args, $q) = explode('::', $key, 4);
$page = page_manager_get_page_cache($task_name);
if (isset($page->display_cache[$handler_name])) {
return $page->display_cache[$handler_name];
......@@ -1549,8 +1583,20 @@ function panel_context_panels_cache_get($key) {
}
$cache = new stdClass();
$task = page_manager_get_task($page->task_id);
//ctools_context_handler_get_all_contexts($page->task, $page->subtask, $handler);
$arguments = array();
if ($args) {
$arguments = explode('\\', $args);
$contexts = ctools_context_handler_get_task_contexts($task, $page->subtask, $arguments);
$contexts = ctools_context_handler_get_handler_contexts($contexts, $handler);
}
else {
$contexts = ctools_context_handler_get_all_contexts($page->task, $page->subtask, $handler);
}
$cache->display = &panels_panel_context_get_display($handler);
$cache->display->context = ctools_context_handler_get_all_contexts($page->task, $page->subtask, $handler);
$cache->display->context = $contexts;
$cache->display->cache_key = 'panel_context:' . $key;
$cache->content_types = panels_common_get_allowed_types('panels_page', $cache->display->context);
$cache->display_title = TRUE;
......@@ -1563,7 +1609,7 @@ function panel_context_panels_cache_get($key) {
* Get the Page Manager cache for the panel_context plugin.
*/
function _panel_context_panels_cache_get_page_cache($key, $cache) {
list($task_name, $handler_name) = explode(':', $key, 2);
list($task_name, $handler_name, $args, $q) = explode('::', $key, 4);
$page = page_manager_get_page_cache($task_name);
$page->display_cache[$handler_name] = $cache;
if ($handler_name) {
......
div.panels-ipe-handlebar-wrapper ul {
float: right;
text-align: left;
}
div.panels-ipe-handlebar-wrapper li {
margin: 0 0 0 .5em;
float: right;
}
div.panels-ipe-draghandle span.panels-ipe-draghandle-icon {
float: left;
}
div.panels-ipe-placeholder {
text-align: right;
}
div.panels-ipe-newblock {
left: 30px;
right: auto;
}
div.panels-ipe-handlebar-wrapper li a span,
div.panels-ipe-newblock a span {
text-align: right;
}
div.panels-ipe-newblock a.style {
margin-left: .5em;
margin-right: auto;
}
.panels-ipe-editing .panels-ipe-region {
float: right;
}
/** ============================================================================
* Controller form markup
*/
.ipe-throbber {
right: 49%;
right: auto;
}
div.panels-ipe-control .form-submit {
padding: 0 34px 2px 0.8em;
}
input#panels-ipe-save,
input#panels-ipe-cancel {
background-position: 86% 0;
}
div.panels-ipe-pseudobutton-container a.panels-ipe-startedit {
padding-right: 34px;
padding-left: 10px;
background-position: 93% 9px;
}
div.panels-ipe-pseudobutton-container a.panels-ipe-change-layout {
padding-right: 34px;
padding-left: 10px;
background-position: 93% 9px;
}
......@@ -27,6 +27,7 @@ div.panels-ipe-handlebar-wrapper {
.panels-ipe-editing div.panels-ipe-portlet-wrapper {
margin-top: 1em;
border: 1px solid #CCC;
width: 100%;
}
/* Hide empty panes when not editing them. */
......@@ -163,6 +164,10 @@ div.panels-ipe-newblock {
z-index: 99;
}
div.panels-ipe-newblock li {
padding: 0;
}
div.panels-ipe-handlebar-wrapper li a,
div.panels-ipe-dragtitle span,
div.panels-ipe-newblock a,
......@@ -375,9 +380,9 @@ div.panels-ipe-control .form-submit {
padding: 0 0.8em 2px 34px;
}
input#panels-ipe-save, input#panels-ipe-cancel,
input#panels-ipe-save:hover, input#panels-ipe-cancel:hover,
input#panels-ipe-save:active, input#panels-ipe-cancel:active {
div.panels-ipe-control input.panels-ipe-save, div.panels-ipe-control input.panels-ipe-cancel,
div.panels-ipe-control input.panels-ipe-save:hover, div.panels-ipe-control input.panels-ipe-cancel:hover,
div.panels-ipe-control input.panels-ipe-save:active, div.panels-ipe-control input.panels-ipe-cancel:active {
background-repeat: no-repeat;
}
......@@ -389,7 +394,7 @@ div.panels-ipe-pseudobutton-container a {
text-decoration: none;
}
input#panels-ipe-save {
div.panels-ipe-control input.panels-ipe-save {
background-image: url(../images/icon-save.png);
background-image: url(../images/icon-save.png), linear-gradient(bottom, #383838 0%, #666666 100%);
background-image: url(../images/icon-save.png), -o-linear-gradient(bottom, #383838 0%, #666666 100%);
......@@ -406,7 +411,7 @@ input#panels-ipe-save {
);
}
input#panels-ipe-cancel {
div.panels-ipe-control input.panels-ipe-cancel {
background-image: url(../images/icon-close.png);
background-image: url(../images/icon-close.png), linear-gradient(bottom, #383838 0%, #666666 100%);
background-image: url(../images/icon-close.png), -o-linear-gradient(bottom, #383838 0%, #666666 100%);
......@@ -446,7 +451,7 @@ div.panels-ipe-pseudobutton-container a:hover {
color: #FFF;
}
input#panels-ipe-cancel:hover {
div.panels-ipe-control input.panels-ipe-cancel:hover {
background-image: url(../images/icon-close.png), linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
background-image: url(../images/icon-close.png), -o-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
background-image: url(../images/icon-close.png), -moz-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
......@@ -462,7 +467,7 @@ input#panels-ipe-cancel:hover {
);
}
input#panels-ipe-save:hover {
div.panels-ipe-control input.panels-ipe-save:hover {
background-image: url(../images/icon-save.png), linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
background-image: url(../images/icon-save.png), -o-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
background-image: url(../images/icon-save.png), -moz-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
......@@ -502,7 +507,7 @@ div.panels-ipe-pseudobutton-container a:active {
color: #CCC;
}
input#panels-ipe-cancel:active {
div.panels-ipe-control input.panels-ipe-cancel:active {
background-image: url(../images/icon-close.png), linear-gradient(bottom, #616161 0%, #333333 100%);
background-image: url(../images/icon-close.png), -o-linear-gradient(bottom, #616161 0%, #333333 100%);
background-image: url(../images/icon-close.png), -moz-linear-gradient(bottom, #616161 0%, #333333 100%);
......@@ -518,7 +523,7 @@ input#panels-ipe-cancel:active {
);
}
input#panels-ipe-save:active {
div.panels-ipe-control input.panels-ipe-save:active {
background-image: url(../images/icon-save.png), linear-gradient(bottom, #616161 0%, #333333 100%);
background-image: url(../images/icon-save.png), -o-linear-gradient(bottom, #616161 0%, #333333 100%);
background-image: url(../images/icon-save.png), -moz-linear-gradient(bottom, #616161 0%, #333333 100%);
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -15,9 +15,11 @@ Drupal.PanelsIPE = {
$('a.pane-delete:not(.pane-delete-processed)', context)
.addClass('pane-delete-processed')
.click(function() {
if (confirm('Remove this pane?')) {
if (confirm(Drupal.t('Remove this pane?'))) {
$(this).parents('div.panels-ipe-portlet-wrapper').fadeOut('medium', function() {
var $sortable = $(this).closest('.ui-sortable');
$(this).empty().remove();
$sortable.trigger('sortremove');
});
$(this).parents('div.panels-ipe-display-container').addClass('changed');
}
......@@ -34,6 +36,10 @@ Drupal.behaviors.PanelsIPE = {
$('div#panels-ipe-display-' + key + ':not(.panels-ipe-processed)')
.addClass('panels-ipe-processed')
.each(function() {
// If we're replacing an old IPE, clean it up a little.
if (Drupal.PanelsIPE.editors[key]) {
Drupal.PanelsIPE.editors[key].editing = false;
}
Drupal.PanelsIPE.editors[key] = new DrupalPanelsIPE(key);
Drupal.PanelsIPE.editors[key].showContainer();
});
......@@ -92,6 +98,22 @@ function DrupalPanelsIPE(cache_key, cfg) {
}
});
// If a user navigates away from a locked IPE, cancel the lock in the background.
$(window).bind('beforeunload', function() {
if (!ipe.editing) {
return;
}
if (ipe.topParent && ipe.topParent.hasClass('changed')) {
ipe.changed = true;
}
if (ipe.changed) {
return Drupal.t('This will discard all unsaved changes. Are you sure?');
}
});
// If a user navigates away from a locked IPE, cancel the lock in the background.
$(window).bind('unload', function() {
ipe.cancelLock(true);
......@@ -170,6 +192,7 @@ function DrupalPanelsIPE(cache_key, cfg) {
};
this.initEditing = function(formdata) {
ipe.editing = true;
ipe.topParent = $('div#panels-ipe-display-' + cache_key);
ipe.backup = this.topParent.clone();
......@@ -212,17 +235,6 @@ function DrupalPanelsIPE(cache_key, cfg) {
ipe.showForm();
ipe.topParent.addClass('panels-ipe-editing');
//Reposition the "Add new pane" button
$('.panels-ipe-newblock').each(function() {
var link_width_half = parseInt($(this).children('a').outerWidth() / 2);
$(this).css('margin-left', '-' + link_width_half + 'px');
$(this).css('margin-top', '-' + parseInt($(this).children('a').outerHeight() / 2) + 'px');
$(this).parents('.panels-ipe-placeholder').find('h3').css('width', parseInt(($(this).parents('.panels-ipe-placeholder').width() / 2) - link_width_half) + 'px');
});
};
this.hideContainer = function() {
......@@ -246,18 +258,18 @@ function DrupalPanelsIPE(cache_key, cfg) {
};
this.endEditing = function() {
ipe.editing = false;
ipe.lockPath = null;
$('.panels-ipe-form-container', ipe.control).empty();
$('.panels-ipe-form-container').empty();
// Re-show all the IPE non-editing meta-elements
$('div.panels-ipe-off').show('fast');
ipe.showButtons();
// Re-hide all the IPE meta-elements
$('div.panels-ipe-on').hide();
if (ipe.topParent) {
ipe.topParent.removeClass('panels-ipe-editing');
$('div.panels-ipe-sort-container', ipe.topParent).sortable("destroy");
}
$('.panels-ipe-editing').removeClass('panels-ipe-editing');
$('div.panels-ipe-sort-container.ui-sortable', ipe.topParent).sortable("destroy");
};
this.saveEditing = function() {
......@@ -310,7 +322,7 @@ function DrupalPanelsIPE(cache_key, cfg) {
this.createSortContainers = function() {
$('div.panels-ipe-region', this.topParent).each(function() {
$('div.panels-ipe-portlet-marker', this).parent()
$(this).children('div.panels-ipe-portlet-marker').parent()
.wrapInner('<div class="panels-ipe-sort-container" />');
// Move our gadgets outside of the sort container so that sortables
......@@ -318,9 +330,6 @@ function DrupalPanelsIPE(cache_key, cfg) {
$('div.panels-ipe-portlet-static', this).each(function() {
$(this).prependTo($(this).parent().parent());
});
// Also remove the last panel separator.
$('div.panel-separator', this).filter(':last').remove();
});
}
......@@ -334,6 +343,8 @@ $(function() {
Drupal.PanelsIPE.editors[data.key].initEditing(data.data);
Drupal.PanelsIPE.editors[data.key].lockPath = data.lockPath;
}
Drupal.attachBehaviors();
};
Drupal.ajax.prototype.commands.IPEsetLockState = function(ajax, data, status) {
......@@ -342,6 +353,12 @@ $(function() {
}
};
Drupal.ajax.prototype.commands.addNewPane = function(ajax, data, status) {
if (Drupal.PanelsIPE.editors[data.key]) {
Drupal.PanelsIPE.editors[data.key].changed = true;
}
};
Drupal.ajax.prototype.commands.cancelIPE = function(ajax, data, status) {
if (Drupal.PanelsIPE.editors[data.key]) {
Drupal.PanelsIPE.editors[data.key].cancelIPE();
......@@ -366,12 +383,45 @@ $(function() {
}
};
Drupal.ajax.prototype.commands.insertNewPane = function(ajax, data, status) {
IPEContainerSelector = '#panels-ipe-regionid-' + data.regionId + ' div.panels-ipe-sort-container';
firstPaneSelector = IPEContainerSelector + ' div.panels-ipe-portlet-wrapper:first';
// Insert the new pane before the first existing pane in the region, if
// any.
if ($(firstPaneSelector).length) {
insertData = {
'method': 'before',
'selector': firstPaneSelector,
'data': data.renderedPane,
'settings': null
}
Drupal.ajax.prototype.commands.insert(ajax, insertData, status);
}
// Else, insert it as a first child of the container. Doing so might fall
// outside of the wrapping markup for the style, but it's the best we can
// do.
else {
insertData = {
'method': 'prepend',
'selector': IPEContainerSelector,
'data': data.renderedPane,
'settings': null
}
Drupal.ajax.prototype.commands.insert(ajax, insertData, status);
}
};
/**
* Override the eventResponse on ajax.js so we can add a little extra
* behavior.
*/
Drupal.ajax.prototype.ipeReplacedEventResponse = Drupal.ajax.prototype.eventResponse;
Drupal.ajax.prototype.eventResponse = function (element, event) {
if (element.ipeCancelThis) {
element.ipeCancelThis = null;
return false;
}
if ($(this.element).attr('id') == 'panels-ipe-cancel') {
if (!Drupal.PanelsIPE.editors[this.element_settings.ipe_cache_key].cancelEditing()) {
return false;
......@@ -404,7 +454,7 @@ $(function() {
Drupal.ajax.prototype.ipeReplacedBeforeSerialize = Drupal.ajax.prototype.beforeSerialize;
Drupal.ajax.prototype.beforeSerialize = function (element_settings, options) {
if ($(this.element).attr('id') == 'panels-ipe-save') {
if ($(this.element).hasClass('panels-ipe-save')) {
Drupal.PanelsIPE.editors[this.element_settings.ipe_cache_key].saveEditing();
};
return this.ipeReplacedBeforeSerialize(element_settings, options);
......
......@@ -6,9 +6,9 @@ core = 7.x
configure = admin/structure/panels
files[] = panels_ipe.module
; Information added by drupal.org packaging script on 2012-08-18
version = "7.x-3.3"
; Information added by Drupal.org packaging script on 2014-02-12
version = "7.x-3.4"
core = "7.x"
project = "panels"
datestamp = "1345319572"
datestamp = "1392221614"
......@@ -73,18 +73,17 @@ function theme_panels_ipe_placeholder_pane($vars) {
return $output;
}
function theme_panels_ipe_pane_wrapper($vars) {
$output = $vars['output'];
function template_preprocess_panels_ipe_pane_wrapper(&$vars) {
$pane = $vars['pane'];
$display = $vars['display'];
$renderer = $vars['renderer'];
$content_type = ctools_get_content_type($pane->type);
$subtype = ctools_content_get_subtype($content_type, $pane->subtype);
$links = array();
$vars['links'] = array();
if (ctools_content_editable($content_type, $subtype, $pane->configuration)) {
$links['edit'] = array(
$vars['links']['edit'] = array(
'title' => isset($content_type['edit text']) ? '<span>' . $content_type['edit text'] . '</span>' : '<span>' . t('Settings') . '</span>',
'href' => $renderer->get_url('edit-pane', $pane->pid),
'html' => TRUE,
......@@ -98,7 +97,7 @@ function theme_panels_ipe_pane_wrapper($vars) {
// Add option to configure style in IPE
if (user_access('administer panels styles')) {
$links['style'] = array(
$vars['links']['style'] = array(
'title' => '<span>' . t('Style') . '</span>',
'href' => $renderer->get_url('style-type', 'pane', $pane->pid),
'html' => TRUE,
......@@ -111,7 +110,7 @@ function theme_panels_ipe_pane_wrapper($vars) {
// Deleting is managed entirely in the js; this is just an attachment point
// for it
$links['delete'] = array(
$vars['links']['delete'] = array(
'title' => '<span>' . t('Delete') . '</span>',
'href' => '#',
'html' => TRUE,
......@@ -122,11 +121,25 @@ function theme_panels_ipe_pane_wrapper($vars) {
),
);
$context = array(
'pane' => $pane,
'display' => $display,
'renderer' => $renderer
);
drupal_alter('panels_ipe_pane_links', $vars['links'], $context);
}
function theme_panels_ipe_pane_wrapper($vars) {
$output = $vars['output'];
$pane = $vars['pane'];
$attributes = array(
'class' => 'panels-ipe-linkbar',
);
$links = theme('links', array('links' => $links, 'attributes' => $attributes));
$links = theme('links', array('links' => $vars['links'], 'attributes' => $attributes));
if (!empty($pane->locks['type']) && $pane->locks['type'] == 'immovable') {
$links = '<div class="panels-ipe-dragbar panels-ipe-nodraghandle clearfix">' . $links . '</div>';
}
......@@ -135,6 +148,7 @@ function theme_panels_ipe_pane_wrapper($vars) {
}
$handlebar = '<div class="panels-ipe-handlebar-wrapper panels-ipe-on">' . $links . '</div>';
return $handlebar . $output;
}
......@@ -142,33 +156,53 @@ function theme_panels_ipe_region_wrapper($vars) {
return $vars['controls'] . $vars['output'];
}
function theme_panels_ipe_add_pane_button($vars) {
function template_preprocess_panels_ipe_add_pane_button(&$vars) {
$region_id = $vars['region_id'];
$display = $vars['display'];
$renderer = $vars['renderer'];
$link = '';
$vars['links'] = '';
// Add option to configure style in IPE
if (user_access('administer panels styles')) {
$link .= ' ' . l('<span>' . t('Region style') . '</span>', $renderer->get_url('style-type', 'region', $region_id), array(
$vars['links']['style'] = array(
'title' => '<span>' . t('Region style') . '</span>',
'href' => $renderer->get_url('style-type', 'region', $region_id),
'html' => TRUE,
'attributes' => array(
'class' => array('ctools-use-modal', 'style', 'panels-ipe-hide-bar'),
'class' => array('ctools-use-modal', 'panels-ipe-hide-bar', 'style'),
'title' => t('Region style'),
),
'html' => TRUE,
));
);
}
// Add option to add items in the IPE
$link .= ' ' . l('<span>' . t('Add new pane') . '</span>', $renderer->get_url('select-content', $region_id), array(
'attributes' => array(
'class' => array('ctools-use-modal', 'add', 'panels-ipe-hide-bar'),
'title' => t('Add new pane'),
),
'html' => TRUE,
));
$vars['links']['add-pane'] = array(
'title' => '<span>' . t('Add new pane') . '</span>',
'href' => $renderer->get_url('select-content', $region_id),
'attributes' => array(
'class' => array('ctools-use-modal', 'add', 'panels-ipe-hide-bar'),
'title' => t('Add new pane'),
),
'html' => TRUE,
);
$context = array(
'region_id' => $region_id,
'display' => $display,
'renderer' => $renderer,
);
drupal_alter('panels_ipe_region_links', $vars['links'], $context);
}
function theme_panels_ipe_add_pane_button($vars) {
$attributes = array(
'class' => array('panels-ipe-linkbar', 'inline'),
);
$links = theme('links', array('links' => $vars['links'], 'attributes' => $attributes));
return '<div class="panels-ipe-newblock panels-ipe-on">' . $link . '</div>';
return '<div class="panels-ipe-newblock panels-ipe-on">' . $links . '</div>';
}
/**
......
......@@ -134,15 +134,28 @@ class panels_renderer_ipe extends panels_renderer_editor {
return "<div id=\"panels-ipe-paneid-{$pane->pid}\" class=\"panels-ipe-portlet-wrapper panels-ipe-portlet-marker\">" . $output . "</div>";
}
function prepare_panes($panes) {
// Set to admin mode just for this to ensure all panes are represented.
$this->admin = TRUE;
$panes = parent::prepare_panes($panes);
$this->admin = FALSE;
}
function render_pane_content(&$pane) {
$content = parent::render_pane_content($pane);
if (!empty($pane->shown) && panels_pane_access($pane, $this->display)) {
$content = parent::render_pane_content($pane);
}
// Ensure that empty panes have some content.
if (empty($content) || empty($content->content)) {
if (empty($content)) {
$content = new stdClass();
}
// Get the administrative title.
$content_type = ctools_get_content_type($pane->type);
$title = ctools_content_admin_title($content_type, $pane->subtype, $pane->configuration, $this->display->context);
$content->content = t('Placeholder for empty "@title"', array('@title' => $title));
$content->content = t('Placeholder for empty or inaccessible "@title"', array('@title' => html_entity_decode($title, ENT_QUOTES)));
// Add these to prevent notices.
$content->type = 'panels_ipe';
$content->subtype = 'panels_ipe';
......@@ -227,6 +240,7 @@ class panels_renderer_ipe extends panels_renderer_editor {
$_POST['ajax_html_ids'] = array();
$form_state = array(
'renderer' => $this,
'display' => &$this->display,
'content_types' => $this->cache->content_types,
'rerender' => FALSE,
......@@ -244,7 +258,7 @@ class panels_renderer_ipe extends panels_renderer_editor {
'command' => 'initIPE',
'key' => $this->clean_key,
'data' => drupal_render($output),
'lockPath' => $this->get_url('unlock_ipe'),
'lockPath' => url($this->get_url('unlock_ipe')),
);
return;
}
......@@ -315,7 +329,7 @@ class panels_renderer_ipe extends panels_renderer_editor {
$this->commands[] = array(
'command' => 'IPEsetLockState',
'key' => $this->clean_key,
'lockPath' => $this->get_url('unlock_ipe'),
'lockPath' => url($this->get_url('unlock_ipe')),
);
}
......@@ -344,7 +358,7 @@ class panels_renderer_ipe extends panels_renderer_editor {
if (!empty($form_state['clicked_button']['#save-display'])) {
// Saved. Save the cache.
panels_edit_cache_save($this->cache);
$this->display->skip_cache;
$this->display->skip_cache = TRUE;
// Since the layout changed, we have to update these things in the
// renderer in order to get the right settings.
......@@ -391,8 +405,16 @@ class panels_renderer_ipe extends panels_renderer_editor {
$pane = $this->display->content[$pid];
}
$this->commands[] = ajax_command_prepend("#panels-ipe-regionid-{$pane->panel} div.panels-ipe-sort-container", $this->render_pane($pane));
$this->commands[] = array(
'command' => 'insertNewPane',
'regionId' => $pane->panel,
'renderedPane' => $this->render_pane($pane),
);
$this->commands[] = ajax_command_changed("#panels-ipe-display-{$this->clean_key}");
$this->commands[] = array(
'command' => 'addNewPane',
'key' => $this->clean_key,
);
}
}
......@@ -430,12 +452,14 @@ function panels_ipe_edit_control_form($form, &$form_state) {
'#type' => 'submit',
'#value' => t('Save'),
'#id' => 'panels-ipe-save',
'#attributes' => array('class' => array('panels-ipe-save')),
'#submit' => array('panels_edit_display_form_submit'),
'#save-display' => TRUE,
);
$form['buttons']['cancel'] = array(
'#type' => 'submit',
'#id' => 'panels-ipe-cancel',
'#attributes' => array('class' => array('panels-ipe-cancel')),
'#value' => t('Cancel'),
);
return $form;
......
......@@ -4,9 +4,9 @@ package = "Panels"
dependencies[] = panels
core = 7.x
files[] = plugins/export_ui/panels_mini_ui.class.php
; Information added by drupal.org packaging script on 2012-08-18
version = "7.x-3.3"
; Information added by Drupal.org packaging script on 2014-02-12
version = "7.x-3.4"
core = "7.x"
project = "panels"
datestamp = "1345319572"
datestamp = "1392221614"
......@@ -130,8 +130,8 @@ function panels_mini_block_view($delta = 0) {
*/
function panels_mini_block_configure($delta = 0) {
return array(
'admin-shortcut' => array(
'#value' => l(t('Manage this mini-panel'), 'admin/structure/mini-panels/' . $delta . '/edit')
'admin_shortcut' => array(
'#markup' => l(t('Manage this mini-panel'), 'admin/structure/mini-panels/list/' . $delta . '/edit')
),
);
}
......@@ -178,6 +178,44 @@ function panels_mini_block_list_alter(&$blocks) {
}
}
/**
* Implements hook_get_pane_links_alter().
*/
function panels_mini_get_pane_links_alter(&$links, $pane, $content_type) {
if ($pane->type == 'panels_mini') {
$links['top']['edit_panels_mini'] = array(
'title' => t('Edit mini panel'),
'href' => url('admin/structure/mini-panels/list/' . $pane->subtype . '/edit/content', array('absolute' => TRUE)),
'attributes' => array('target' => array('_blank')),
);
}
}
/**
* Implements hook_contextual_links_view_alter().
*/
function panels_mini_contextual_links_view_alter(&$element, $items) {
// Add contextual links to all mini panel blocks.
if (isset($element['#element']['#block']) && strpos((string) $element['#element']['#block']->bid, 'panels_mini') === 0) {
$admin_pages = array(
t('Configure mini panel settings') => 'basic',
t('Configure mini panel context') => 'context',
t('Configure mini panel layout') => 'layout',
t('Configure mini panel content') => 'content',
);
foreach ($admin_pages as $title => $tail) {
$element['#links']['mini-panels-' . $tail] = array(
'title' => $title,
'href' => 'admin/structure/mini-panels/list/' . $element['#element']['#block']->delta . '/edit/' . $tail,
'query' => drupal_get_destination(),
);
}
}
}
/**
* Statically store all used IDs to ensure all mini panels get a unique id.
*/
......@@ -285,7 +323,8 @@ function panels_mini_load_all($reset = FALSE) {
}
}
return $cache;
// Strip out NULL entries that may have been added by panels_mini_load().
return array_filter($cache);
}
/**
......
......@@ -109,6 +109,16 @@ function panels_mini_panels_mini_content_type_render($subtype, $conf, $panel_arg
$block->content = panels_render_display($mini->display);
$block->title = $mini->display->get_title();
if (user_access('administer mini panels')) {
$block->admin_links = array(
array(
'title' => t('Configure mini panel'),
'href' => "admin/structure/mini-panels/list/$subtype/edit/content",
'query' => drupal_get_destination(),
),
);
}
unset($viewing[$mini->name]);
return $block;
}
......@@ -137,3 +147,30 @@ function panels_mini_panels_mini_content_type_admin_title($subtype, $conf) {
return $title;
}
/**
* Callback to provide administrative info. Provide links to edit the mini
* panel.
*/
function panels_mini_panels_mini_content_type_admin_info($subtype, $conf) {
$mini = panels_mini_load($subtype);
if (!$mini) {
return FALSE;
}
$block = new stdClass();
$block->title = $mini->admin_title;
$admin_pages = array(
t('Settings') => 'basic',
t('Context') => 'context',
t('Layout') => 'layout',
t('Content') => 'content',
);
$links = array();
foreach ($admin_pages as $title => $tail) {
$links[] = l($title, 'admin/structure/mini-panels/list/' . $subtype . '/edit/' . $tail, array('query' => drupal_get_destination()));
}
$block->content = theme('item_list', array('items' => $links));
return $block;
}
......@@ -118,6 +118,13 @@ class panels_mini_ui extends ctools_export_ui {
// Get the basic edit form
parent::edit_form($form, $form_state);
// Set the admin title machine name length.
// We need to do this because the system block name length is
// limited to 32 chars.
$form['info']['name']['#maxlength'] = 32;
$form['info']['name']['#size'] = 34;
$form['info']['name']['#description'] .= ' ' . t('The machine name length is limited to 32 characters, due to a limitation in the core block system.');
$form['category'] = array(
'#type' => 'textfield',
'#size' => 24,
......
......@@ -6,9 +6,9 @@ configure = admin/structure/panels
core = 7.x
files[] = panels_node.module
; Information added by drupal.org packaging script on 2012-08-18
version = "7.x-3.3"
; Information added by Drupal.org packaging script on 2014-02-12
version = "7.x-3.4"
core = "7.x"
project = "panels"
datestamp = "1345319572"
datestamp = "1392221614"
......@@ -339,6 +339,7 @@ function panels_node_hook_view($node, $view_mode) {
$display->css_id = $node->panels_node['css_id'];
// TODO: Find a way to make sure this can't node_view.
$display->context = panels_node_get_context($node);
$display->cache_key = 'panels_node:' . $node->nid;
$renderer = panels_get_renderer($node->panels_node['pipeline'], $display);
$node->content['body'] = array(
'#markup' => panels_render_display($display, $renderer),
......@@ -429,3 +430,59 @@ function panels_node_panels_dashboard_blocks(&$vars) {
'weight' => -1,
);
}
// ---------------------------------------------------------------------------
// Callbacks for panel caching.
/**
* Get display edit cache for a panel node being edited.
*
* The key is the second half of the key in this form:
* panels_node:NID;
*/
function panels_node_panels_cache_get($nid) {
ctools_include('object-cache');
$cache = ctools_object_cache_get('panels_node_display_cache', $nid);
if (empty($cache)) {
$cache = new stdClass();
$node = node_load($nid);
if (empty($node)) {
return;
}
ctools_include('common', 'panels');
$cache->display = panels_load_display($node->panels_node['did']);
$cache->display->css_id = $node->panels_node['css_id'];
$cache->display->context = panels_node_get_context($node);
$cache->display->cache_key = 'panels_node:' . $node->nid;
$cache->content_types = panels_common_get_allowed_types('panels_node', $cache->display->context);
$cache->allwed_layouts = panels_common_get_allowed_layouts('panels_node');
}
return $cache;
}
/**
* Store a display edit in progress in the panels cache.
*/
function panels_node_panels_cache_set($nid, $cache) {
ctools_include('object-cache');
ctools_object_cache_set('panels_node_display_cache', $nid, $cache);
}
/**
* Clear all changes made to a display using the panels cache.
*/
function panels_node_panels_cache_clear($nid, $cache) {
ctools_include('object-cache');
ctools_object_cache_clear('panels_node_display_cache', $nid);
}
/**
* React to a cache save and save the display and clear cache.
*/
function panels_node_panels_cache_save($nid, $cache) {
panels_save_display($cache->display);
ctools_include('object-cache');
ctools_object_cache_clear('panels_node_display_cache', $nid);
}
......@@ -25,7 +25,7 @@ $plugin = array(
*/
function panels_simple_cache_get_cache($conf, $display, $args, $contexts, $pane = NULL) {
$cid = panels_simple_cache_get_id($conf, $display, $args, $contexts, $pane);
$cache = cache_get($cid, 'cache');
$cache = cache_get($cid, 'cache_panels');
if (!$cache) {
return FALSE;
}
......@@ -42,7 +42,7 @@ function panels_simple_cache_get_cache($conf, $display, $args, $contexts, $pane
*/
function panels_simple_cache_set_cache($conf, $content, $display, $args, $contexts, $pane = NULL) {
$cid = panels_simple_cache_get_id($conf, $display, $args, $contexts, $pane);
cache_set($cid, $content);
cache_set($cid, $content, 'cache_panels');
}
/**
......@@ -53,13 +53,25 @@ function panels_simple_cache_set_cache($conf, $content, $display, $args, $contex
function panels_simple_cache_clear_cache($display) {
$cid = 'panels_simple_cache';
// This is used in case this is an in-code display, which means did will be something like 'new-1'.
if (isset($display->owner) && isset($display->owner->id)) {
$cid .= ':' . $display->owner->id;
// If the panel is stored in the database it'll have a numeric did value.
if (is_numeric($display->did)) {
$cid .= ':' . $display->did;
}
// Exported panels won't have a numeric did but may have a usable cache_key.
elseif (!empty($display->cache_key)) {
$cid .= ':' . str_replace('panel_context:', '', $display->cache_key);
}
// Alternatively use the css_id.
elseif (!empty($display->css_id)) {
$cid .= ':' . $display->css_id;
}
// Failover to just appending the did, which may be the completely unusable
// string 'new'.
else {
$cid .= ':' . $display->did;
}
$cid .= ':' . $display->did;
cache_clear_all($cid, 'cache', TRUE);
cache_clear_all($cid, 'cache_panels', TRUE);
}
/**
......
......@@ -153,7 +153,7 @@ class panels_renderer_editor extends panels_renderer_standard {
$output = '<div class="' . $class . '" id="panel-pane-' . $pane->pid . '">';
if (!$block->title) {
if (empty($block->title)) {
$block->title = t('No title');
}
......@@ -186,12 +186,12 @@ class panels_renderer_editor extends panels_renderer_standard {
$style_title = isset($style['title']) ? $style['title'] : t('Default');
$style_links[] = array(
$style_links['title'] = array(
'title' => $style_title,
'attributes' => array('class' => array('panels-text')),
);
$style_links[] = array(
$style_links['change'] = array(
'title' => t('Change'),
'href' => $this->get_url('style-type', $type, $id),
'attributes' => array('class' => array('ctools-use-modal')),
......@@ -199,7 +199,7 @@ class panels_renderer_editor extends panels_renderer_standard {
$function = $type != 'pane' ? 'settings form' : 'pane settings form';
if (panels_plugin_get_function('styles', $style, $function)) {
$style_links[] = array(
$style_links['settings'] = array(
'title' => t('Settings'),
'href' => $this->get_url('style-settings', $type, $id),
'attributes' => array('class' => array('ctools-use-modal')),
......@@ -307,14 +307,14 @@ class panels_renderer_editor extends panels_renderer_standard {
$links = array();
if (!empty($pane->shown)) {
$links[] = array(
$links['top']['disabled'] = array(
'title' => t('Disable this pane'),
'href' => $this->get_url('hide', $pane->pid),
'attributes' => array('class' => array('use-ajax')),
);
}
else {
$links[] = array(
$links['top']['enable'] = array(
'title' => t('Enable this pane'),
'href' => $this->get_url('show', $pane->pid),
'attributes' => array('class' => array('use-ajax')),
......@@ -322,13 +322,13 @@ class panels_renderer_editor extends panels_renderer_standard {
}
if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
$links['panels-set-title'] = array(
$links['top']['panels-set-title'] = array(
'title' => t('&#x2713;Panel title'),
'html' => TRUE,
);
}
else {
$links['panels-set-title'] = array(
$links['top']['panels-set-title'] = array(
'title' => t('Panel title'),
'href' => $this->get_url('panel-title', $pane->pid),
'attributes' => array('class' => array('use-ajax')),
......@@ -338,7 +338,7 @@ class panels_renderer_editor extends panels_renderer_standard {
$subtype = ctools_content_get_subtype($content_type, $pane->subtype);
if (ctools_content_editable($content_type, $subtype, $pane->configuration)) {
$links[] = array(
$links['top']['settings'] = array(
'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),
'href' => $this->get_url('edit-pane', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
......@@ -346,7 +346,7 @@ class panels_renderer_editor extends panels_renderer_standard {
}
if (user_access('administer advanced pane settings')) {
$links[] = array(
$links['top']['css'] = array(
'title' => t('CSS properties'),
'href' => $this->get_url('pane-css', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
......@@ -354,26 +354,10 @@ class panels_renderer_editor extends panels_renderer_standard {
}
if (user_access('administer panels styles')) {
$links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$style_links = $this->get_style_links('pane', $pane->pid);
$links[] = array(
'title' => '<span class="dropdown-header">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),
'html' => TRUE,
'attributes' => array('class' => array('panels-sub-menu')),
);
$links['style'] = $this->get_style_links('pane', $pane->pid);
}
if (user_access('administer pane access')) {
$links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$contexts = $this->display->context;
// Make sure we have the logged in user context
if (!isset($contexts['logged-in-user'])) {
......@@ -385,7 +369,7 @@ class panels_renderer_editor extends panels_renderer_standard {
if (!empty($pane->access['plugins'])) {
foreach ($pane->access['plugins'] as $id => $test) {
$plugin = ctools_get_access_plugin($test['name']);
$access_title = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));
$access_title = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));
$access_description = ctools_access_summary($plugin, $contexts, $test);
$visibility_links[] = array(
......@@ -396,37 +380,28 @@ class panels_renderer_editor extends panels_renderer_standard {
}
}
if (empty($visibility_links)) {
$visibility_links[] = array(
$visibility_links['no_rules'] = array(
'title' => t('No rules'),
'attributes' => array('class' => array('panels-text')),
);
}
$visibility_links[] = array(
$visibility_links['add_rule'] = array(
'title' => t('Add new rule'),
'href' => $this->get_url('access-add-test', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
);
$visibility_links[] = array(
$visibility_links['settings'] = array(
'title' => t('Settings'),
'href' => $this->get_url('access-settings', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
);
$links[] = array(
'title' => '<span class="dropdown-header">' . t('Visibility rules') . '</span>' . theme_links(array('links' => $visibility_links, 'attributes' => array(), 'heading' => array())),
'html' => TRUE,
'attributes' => array('class' => array('panels-sub-menu')),
);
$links['visibility'] = $visibility_links;
}
if (user_access('use panels locks')) {
$links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$lock_type = !empty($pane->locks['type']) ? $pane->locks['type'] : 'none';
switch ($lock_type) {
case 'immovable':
......@@ -441,62 +416,44 @@ class panels_renderer_editor extends panels_renderer_standard {
break;
}
$lock_links[] = array(
$lock_links['lock'] = array(
'title' => $lock_method,
'attributes' => array('class' => array('panels-text')),
);
$lock_links[] = array(
$lock_links['change'] = array(
'title' => t('Change'),
'href' => $this->get_url('lock', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
);
$links[] = array(
'title' => '<span class="dropdown-header">' . t('Locking') . '</span>' . theme_links(array('links' => $lock_links, 'attributes' => array(), 'heading' => array())),
'html' => TRUE,
'attributes' => array('class' => array('panels-sub-menu')),
);
$links['lock'] = $lock_links;
}
if (panels_get_caches() && user_access('use panels caching features')) {
$links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$method = isset($pane->cache['method']) ? $pane->cache['method'] : 0;
$info = panels_get_cache($method);
$cache_method = isset($info['title']) ? $info['title'] : t('No caching');
$cache_links[] = array(
$cache_links['title'] = array(
'title' => $cache_method,
'attributes' => array('class' => array('panels-text')),
);
$cache_links[] = array(
$cache_links['change'] = array(
'title' => t('Change'),
'href' => $this->get_url('cache-method', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
);
if (panels_plugin_get_function('cache', $info, 'settings form')) {
$cache_links[] = array(
$cache_links['settings'] = array(
'title' => t('Settings'),
'href' => $this->get_url('cache-settings', $pane->pid),
'attributes' => array('class' => array('ctools-use-modal')),
);
}
$links[] = array(
'title' => '<span class="dropdown-header">' . t('Caching') . '</span>' . theme_links(array('links' => $cache_links, 'attributes' => array(), 'heading' => array())),
'html' => TRUE,
'attributes' => array('class' => array('panels-sub-menu')),
);
$links['cache'] = $cache_links;
}
$links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$links[] = array(
$links['bottom']['remove'] = array(
'title' => t('Remove'),
'href' => '#',
'attributes' => array(
......@@ -505,7 +462,35 @@ class panels_renderer_editor extends panels_renderer_standard {
),
);
return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-configure.png', 'panels'))), 'links' => $links, 'image' => TRUE));
// Allow others to add/remove links from pane context menu.
// Grouped by 'top', 'style', 'visibility', 'lock', 'cache' and 'bottom'
drupal_alter('get_pane_links', $links, $pane, $content_type);
$dropdown_links = $links['top'];
foreach (array(
'style' => 'Style',
'visibility' => 'Visibility rules',
'lock' => 'Locking',
'cache' => 'Caching'
) as $category => $label) {
$dropdown_links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$dropdown_links[] = array(
'title' => '<span class="dropdown-header">' . t($label) . '</span>' . theme_links(array('links' => $links[$category], 'attributes' => array(), 'heading' => array())),
'html' => TRUE,
'attributes' => array('class' => array('panels-sub-menu')),
);
}
$dropdown_links[] = array(
'title' => '<hr />',
'html' => TRUE,
);
$dropdown_links = array_merge($dropdown_links, $links['bottom']);
return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-configure.png', 'panels'))), 'links' => $dropdown_links, 'image' => TRUE));
}
// -----------------------------------------------------------------------
......@@ -581,7 +566,7 @@ class panels_renderer_editor extends panels_renderer_standard {
* @todo -- this should be in CTools.
*/
function get_category($content_type) {
if (isset($content_type['top level'])) {
if (!empty($content_type['top level'])) {
$category = 'root';
}
else if (isset($content_type['category'])) {
......@@ -656,7 +641,19 @@ class panels_renderer_editor extends panels_renderer_standard {
$content_type = ctools_get_content_type($type_name);
$subtype = ctools_content_get_subtype($content_type, $subtype_name);
if (!isset($step) || !isset($this->cache->new_pane)) {
// Determine if we are adding a different pane than previously cached. This
// is used to load the different pane into cache so that multistep forms
// have the correct context instead of a previously cached version that
// does not match the pane currently being added.
$is_different_pane = FALSE;
if (isset($this->cache) && isset($this->cache->new_pane)) {
$diff_type = $type_name != $this->cache->new_pane->type;
$diff_subtype = $subtype_name != $this->cache->new_pane->subtype;
$is_different_pane = $diff_type || $diff_subtype;
}
if (!isset($step) || !isset($this->cache->new_pane) || $is_different_pane) {
$pane = panels_new_pane($type_name, $subtype_name, TRUE);
$this->cache->new_pane = &$pane;
}
......@@ -757,6 +754,11 @@ class panels_renderer_editor extends panels_renderer_standard {
// References get blown away with AJAX caching. This will fix that.
$this->cache->display->content[$pid] = $form_state['pane'];
// Conditionally overwrite the context for this panel if present in the form state.
if (!empty($form_state['display_cache']->display->context)) {
$this->cache->display->context = $form_state['display_cache']->display->context;
}
panels_edit_cache_set($this->cache);
$this->command_update_pane($pid);
$this->commands[] = ctools_modal_command_dismiss();
......@@ -1158,7 +1160,11 @@ class panels_renderer_editor extends panels_renderer_standard {
unset($this->cache->style);
}
// $conf was a reference so it should just modify.
// Copy settings from form state back into the cache.
if(!empty($form_state['values']['settings'])) {
$this->cache->display->content[$pid]->style['settings'] = $form_state['values']['settings'];
}
panels_edit_cache_set($this->cache);
$this->commands[] = ctools_modal_command_dismiss();
......@@ -1501,6 +1507,8 @@ function panels_ajax_edit_pane_cancel(&$form_state) {
* Choose cache method form
*/
function panels_edit_cache_method_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$conf = &$form_state['conf'];
......@@ -1549,6 +1557,8 @@ function panels_edit_cache_method_form_submit($form, &$form_state) {
* Cache settings form
*/
function panels_edit_cache_settings_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$conf = &$form_state['conf'];
$pid = $form_state['pid'];
......@@ -1609,6 +1619,8 @@ function panels_edit_cache_settings_form_submit($form, &$form_state) {
* Choose style form
*/
function panels_edit_style_type_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$style = $form_state['style'];
$type = $form_state['type'];
......@@ -1659,6 +1671,8 @@ function panels_edit_style_type_form_submit($form, &$form_state) {
* Style settings form
*/
function panels_edit_style_settings_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$conf = &$form_state['conf'];
$pid = $form_state['pid'];
......@@ -1713,6 +1727,8 @@ function panels_edit_style_settings_form_submit($form, &$form_state) {
* Configure CSS on a pane form.
*/
function panels_edit_configure_pane_css_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$pane = &$form_state['pane'];
......@@ -1755,6 +1771,8 @@ function panels_edit_configure_pane_css_form_submit($form, &$form_state) {
* Configure lock on a pane form.
*/
function panels_edit_configure_pane_lock_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$pane = &$form_state['pane'];
......@@ -1830,6 +1848,8 @@ function panels_edit_configure_pane_lock_form_submit($form, &$form_state) {
* Form to control basic visibility settings.
*/
function panels_edit_configure_access_settings_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$pane = &$form_state['pane'];
......@@ -1867,6 +1887,8 @@ function panels_edit_configure_access_settings_form_submit($form, &$form_state)
* Form to add a visibility rule.
*/
function panels_edit_add_access_test_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$pane = &$form_state['pane'];
......@@ -1896,6 +1918,8 @@ function panels_edit_add_access_test_form($form, &$form_state) {
* Form to configure a visibility rule.
*/
function panels_edit_configure_access_test_form($form, &$form_state) {
ctools_form_include($form_state, 'plugins', 'panels');
form_load_include($form_state, 'php', 'panels', '/plugins/display_renderers/panels_renderer_editor.class');
$display = &$form_state['display'];
$test = &$form_state['test'];
$plugin = &$form_state['plugin'];
......
......@@ -259,6 +259,10 @@ class panels_renderer_standard {
}
}
$this->prepared['panes'] = $first + $normal + $last;
// Allow other modules the alter the prepared panes array.
drupal_alter('panels_panes_prepared', $this->prepared['panes'], $this);
return $this->prepared['panes'];
}
......@@ -404,16 +408,28 @@ class panels_renderer_standard {
*/
function add_meta() {
if (!empty($this->plugins['layout']['css'])) {
if (file_exists(path_to_theme() . '/' . $this->plugins['layout']['css'])) {
$this->add_css(path_to_theme() . '/' . $this->plugins['layout']['css']);
$css = $this->plugins['layout']['css'];
if (!is_array($css)) {
$css = array($css);
}
else {
$this->add_css($this->plugins['layout']['path'] . '/' . $this->plugins['layout']['css']);
foreach($css as $file) {
if (file_exists(path_to_theme() . '/' . $file)) {
$this->add_css(path_to_theme() . '/' . $file);
}
else {
$this->add_css($this->plugins['layout']['path'] . '/' . $file);
}
}
}
if ($this->admin && isset($this->plugins['layout']['admin css'])) {
$this->add_css($this->plugins['layout']['path'] . '/' . $this->plugins['layout']['admin css']);
$admin_css = $this->plugins['layout']['admin css'];
if (!is_array($admin_css)) {
$admin_css = array($admin_css);
}
foreach($admin_css as $file) {
$this->add_css($this->plugins['layout']['path'] . '/' . $file);
}
}
}
......@@ -436,7 +452,7 @@ class panels_renderer_standard {
break;
case 'inline':
$url = base_path() . $filename;
$this->prefix .= '<link type="text/css" rel="stylesheet" href="' . $url . '" />'."\n";
$this->prefix .= '<link type="text/css" rel="stylesheet" href="' . file_create_url($url) . '" />'."\n";
break;
}
}
......@@ -473,6 +489,8 @@ class panels_renderer_standard {
* A Panels pane object, as loaded from the database.
*/
function render_pane(&$pane) {
module_invoke_all('panels_pane_prerender', $pane);
$content = $this->render_pane_content($pane);
if ($this->display->hide_title == PANELS_TITLE_PANE && !empty($this->display->title_pane) && $this->display->title_pane == $pane->pid) {
......@@ -526,7 +544,6 @@ class panels_renderer_standard {
$this->display->context = array();
}
$content = FALSE;
$caching = !empty($pane->cache['method']) && empty($this->display->skip_cache);
if ($caching && ($cache = panels_get_cached_content($this->display, $this->display->args, $this->display->context, $pane))) {
$content = $cache->content;
......@@ -540,10 +557,6 @@ class panels_renderer_standard {
$content = ctools_content_render($pane->type, $pane->subtype, $pane->configuration, array(), $this->display->args, $this->display->context);
if (empty($content)) {
return;
}
foreach (module_implements('panels_pane_content_alter') as $module) {
$function = $module . '_panels_pane_content_alter';
$function($content, $pane, $this->display->args, $this->display->context, $this, $this->display);
......@@ -555,14 +568,17 @@ class panels_renderer_standard {
}
}
// Pass long the css_id that is usually available.
if (!empty($pane->css['css_id'])) {
$content->css_id = check_plain($pane->css['css_id']);
}
// If there's content, check if we've css configuration to add.
if (!empty($content)) {
// Pass long the css_id that is usually available.
if (!empty($pane->css['css_id'])) {
$content->css_id = check_plain($pane->css['css_id']);
}
// Pass long the css_class that is usually available.
if (!empty($pane->css['css_class'])) {
$content->css_class = check_plain($pane->css['css_class']);
// Pass long the css_class that is usually available.
if (!empty($pane->css['css_class'])) {
$content->css_class = check_plain($pane->css['css_class']);
}
}
return $content;
......
......@@ -125,9 +125,19 @@ class panels_layouts_ui extends ctools_export_ui {
function edit_form_submit(&$form, &$form_state) {
parent::edit_form_submit($form, $form_state);
// While we short circuited the main submit hook, we need to keep this one.
panels_edit_display_settings_form_submit($form, $form_state);
$form_state['item']->settings = $form_state['display']->layout_settings;
}
function edit_form_validate(&$form, &$form_state) {
parent::edit_form_validate($form, $form_state);
// While we short circuited the main validate hook, we need to keep this one.
panels_edit_display_settings_form_validate($form, $form_state);
}
function list_form(&$form, &$form_state) {
ctools_include('plugins', 'panels');
$this->builders = panels_get_layout_builders();
......
......@@ -290,9 +290,6 @@ Drupal.flexible.splitter = function($splitter) {
// if not moving the right side, adjust the parent padding instead.
splitter.parent.css('padding-left', (splitter.left_padding - moved) + 'px');
splitter.left.parent().css('margin-left', (splitter.left_parent + moved) + 'px');
if (jQuery.browser.msie) {
splitter.left.parent().css('left', splitter.currentLeft);
}
}
return false;
};
......
......@@ -747,47 +747,47 @@ function panels_flexible_render_css_group($renderer, $list, $owner_id, $type, $i
$css = array();
// Start off with some generic CSS to properly pad regions
$css['.' . $renderer->item_class['region']] = array(
$css[$owner_id . ' .' . $renderer->item_class['region']] = array(
'padding' => '0',
);
$css['.' . $renderer->item_class['region'] . '-inside'] = array(
$css[$owner_id . ' .' . $renderer->item_class['region'] . '-inside'] = array(
'padding-right' => $renderer->region_separation,
'padding-left' => $renderer->region_separation,
);
$css['.' . $renderer->item_class['region'] . '-inside-first'] = array(
$css[$owner_id . ' .' . $renderer->item_class['region'] . '-inside-first'] = array(
'padding-left' => '0',
);
$css['.' . $renderer->item_class['region'] . '-inside-last'] = array(
$css[$owner_id . ' .' . $renderer->item_class['region'] . '-inside-last'] = array(
'padding-right' => '0',
);
$css['.' . $renderer->item_class['column']] = array(
$css[$owner_id . ' .' . $renderer->item_class['column']] = array(
'padding' => '0',
);
$css['.' . $renderer->item_class['column'] . '-inside'] = array(
$css[$owner_id . ' .' . $renderer->item_class['column'] . '-inside'] = array(
'padding-right' => $renderer->column_separation,
'padding-left' => $renderer->column_separation,
);
$css['.' . $renderer->item_class['column'] . '-inside-first'] = array(
$css[$owner_id . ' .' . $renderer->item_class['column'] . '-inside-first'] = array(
'padding-left' => '0',
);
$css['.' . $renderer->item_class['column'] . '-inside-last'] = array(
$css[$owner_id . ' .' . $renderer->item_class['column'] . '-inside-last'] = array(
'padding-right' => '0',
);
// And properly pad rows too
$css['.' . $renderer->item_class['row']] = array(
$css[$owner_id . ' .' . $renderer->item_class['row']] = array(
'padding' => '0 0 ' . $renderer->row_separation . ' 0',
'margin' => '0',
);
$css['.' . $renderer->item_class['row'] . '-last'] = array(
$css[$owner_id . ' .' . $renderer->item_class['row'] . '-last'] = array(
'padding-bottom' => '0',
);
......
......@@ -31,6 +31,9 @@ function theme_panels_block_style_render_pane($vars) {
if (!empty($block->title)) {
$block->subject = $block->title;
}
if (!isset($block->subject)) {
$block->subject = '';
}
$block->region = $pane->panel;
if (!isset($block->module)) {
......
File mode changed from 100755 to 100644
......@@ -184,7 +184,7 @@ $plugin = array(
'default conf' => array(
'title' => t('Panel'),
'no_blocks' => FALSE,
'pipeline' => 'standard',
'pipeline' => variable_get('panels_renderer_default', 'standard'),
'body_classes_to_remove' => '',
'body_classes_to_add' => '',
'css_id' => '',
......@@ -238,6 +238,28 @@ function &panels_panel_context_get_display(&$handler) {
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.
*/
......@@ -267,7 +289,7 @@ function panels_panel_context_render($handler, $base_contexts, $args, $test = TR
$display->css_id = $handler->conf['css_id'];
$task_name = page_manager_make_task_name($handler->task, $handler->subtask);
$display->cache_key = 'panel_context:' . $task_name . ':' . $handler->name;
$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'])) {
......@@ -284,6 +306,13 @@ function panels_panel_context_render($handler, $base_contexts, $args, $test = TR
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');
......@@ -364,7 +393,10 @@ function panels_panel_context_export(&$handler, $indent) {
unset($handler->conf[$item]);
}
}
$display->did = 'new';
$display = (object) array(
'did' => 'new',
'uuid' => ctools_uuid_generate(),
);
$handler->conf['display'] = $display;
}
......@@ -629,7 +661,7 @@ function panels_panel_context_edit_move($form, &$form_state) {
$form_state['display'] = &panels_panel_context_get_display($form_state['handler']);
$form_state['layout'] = $form_state['handler']->conf['temp_layout'];
$form_state['cache_key'] = 'panel_context:' . $form_state['task_name'] . ':' . $form_state['handler_id'];
$form_state['cache_key'] = panels_panel_context_cache_key($form_state['task_name'], $form_state['handler_id'], array());
ctools_include('common', 'panels');
ctools_include('display-layout', 'panels');
......@@ -666,7 +698,7 @@ function panels_panel_context_edit_content($form, &$form_state) {
ctools_include('context');
ctools_include('context-task-handler');
$cache = panels_edit_cache_get('panel_context:' . $form_state['task_name'] . ':' . $form_state['handler_id']);
$cache = panels_edit_cache_get(panels_panel_context_cache_key($form_state['task_name'], $form_state['handler_id'], array()));
$form_state['renderer'] = panels_get_renderer_handler('editor', $cache->display);
$form_state['renderer']->cache = &$cache;
......@@ -868,15 +900,28 @@ function panels_panel_context_get_addressable($task, $subtask_name, $handler, $a
$display->context = $contexts;
$display->args = $arguments;
$display->css_id = $handler->conf['css_id'];
$display->cache_key = 'panel_context:' . $task->name . ':' . $handler->name;
$display->cache_key = panels_panel_context_cache_key($task->name, $handler->name, $arguments);
$renderer = panels_get_renderer($handler->conf['pipeline'], $display);
if ($type == 'content') {
$renderer->prepare();
$renderer->prepare();
if ($address) {
$pid = array_shift($address);
if (!empty($renderer->prepared['panes'][$pid])) {
return $renderer->render_pane($renderer->prepared['panes'][$pid]);
if ($type == 'content') {
return $renderer->render_pane($renderer->prepared['panes'][$pid]);
}
elseif ($type == 'pane') {
return $renderer->prepared['panes'][$pid];
}
}
}
else {
if ($type == 'content') {
return $renderer->render();
}
elseif ($type == 'renderer') {
return $renderer;
}
}
}
......@@ -137,8 +137,8 @@ class panels_views_plugin_row_fields extends views_plugin_row_fields {
// Now that we have distributed our fields, go through the regions and
// render them into the content array.
foreach ($this->region_fields as $region_id => $fields) {
$this->view->field = $fields;
foreach ($this->region_fields as $region_id => $fields_list) {
$this->view->field = $fields_list;
$content[$region_id] = theme($this->theme_functions(), array('view' => $this->view, 'options' => $this->options, 'row' => $row));
}
......
<?php
/**
* @file
* Template to control the add content individual links in the add content modal.
*/
?>
<div class="content-type-button clearfix">
<?php print $image_button; ?>
<div><?php print $text_button; ?></div>
</div>
<?php
/**
* @file
* Template to control the add content individual links in the add content modal.
*/
?>
<div class="content-type-button clearfix">
<?php print $image_button; ?>
<div><?php print $text_button; ?></div>
</div>
......@@ -20,7 +20,7 @@
<?php if ($pane_prefix): ?>
<?php print $pane_prefix; ?>
<?php endif; ?>
<div class="<?php print $classes; ?>" <?php print $id; ?>>
<div class="<?php print $classes; ?>" <?php print $id; ?> <?php print $attributes; ?>>
<?php if ($admin_links): ?>
<?php print $admin_links; ?>
<?php endif; ?>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment