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;
}
This diff is collapsed.
......@@ -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);
}
}
This diff is collapsed.
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);
}
/**
......
......@@ -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