updated some more modules
@@ -1,6 +1,3 @@
|
||||
Welcome to Panels 3
|
||||
|
||||
Welcome to Panels 3.
|
||||
|
||||
A little documentation should go here, but Panels 3 is alsoi a beast - you're
|
||||
best off checking the online handbook on Drupal.org, or this issue:
|
||||
http://drupal.org/node/887560.
|
||||
Documentation is available at https://www.drupal.org/node/496278
|
||||
@@ -11,7 +11,7 @@ Upgrading from Panels-6.x-3.x to Panels-7.x-3.x
|
||||
|
||||
- panels_plugin_get_function() deprecated.
|
||||
|
||||
- panels_required_context removed. These were deprecated long ago and
|
||||
- panels_required_context removed. These were deprecated long ago and
|
||||
existed only to prevent crashes.
|
||||
|
||||
- panels_optional_context removed.
|
||||
@@ -20,3 +20,13 @@ Upgrading from Panels-6.x-3.x to Panels-7.x-3.x
|
||||
|
||||
- display_renderer class is now in 'renderer', not 'handler'.
|
||||
|
||||
Upgrading task handlers from Panels 7.x-3.5 or older to Panels 7.x-3.6 and newer:
|
||||
|
||||
- You must specify a storage type for any panels display using your custom task handler.
|
||||
For examples, see panels_update_7306.
|
||||
|
||||
- When creating whatever stores the panel, a storage id and storage type must be defined.
|
||||
See panels_mini.module for examples inside panels_mini_save and panels_mini_panels_cache_get.
|
||||
|
||||
- A display access plugin must be defined.
|
||||
See panels_mini/plugins/panels_storage/panels_mini.inc for an example plugin.
|
||||
|
||||
@@ -40,11 +40,6 @@ div.panel-pane:hover div.panel-hide {
|
||||
margin-top: -1.5em;
|
||||
}
|
||||
|
||||
div.panel-pane div.node {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.panel-pane div.feed a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ div.panels-set-title-hide .panel-pane-is-title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.panel-portlet .buttons input {
|
||||
.panel-portlet .buttons input, .panel-portlet .buttons button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline;
|
||||
@@ -305,11 +305,19 @@ a.close img {
|
||||
background: url(../images/bg-content-modal.png);
|
||||
height: 100%;
|
||||
margin: -1em;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
padding-left: 175px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.panels-section-columns-quickfilter {
|
||||
padding-top: 1em;
|
||||
padding-left: 1em;
|
||||
padding-bottom: 1em;
|
||||
margin-bottom: 1em;
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.panels-section-columns {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
@@ -369,22 +377,29 @@ a.close img {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.content-type-button a {
|
||||
display: inline-block;
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
.content-type-button a:focus {
|
||||
border: 1px dotted black;
|
||||
}
|
||||
|
||||
.content-type-button img {
|
||||
border: 2px solid white;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.content-type-button img:hover {
|
||||
border: 2px solid blue;
|
||||
}
|
||||
|
||||
.content-type-button div {
|
||||
.content-type-button div,
|
||||
.content-type-button span {
|
||||
width: 85%;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
left: 2px;
|
||||
float: left;
|
||||
padding-left: 3px;
|
||||
padding-top: 5px;
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
#panels-preview .modal-throbber-wrapper {
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
<h2>Getting Started:</h2>
|
||||
<p>Layout plugins are one of the simplest and most powerful sections of the panels api. There are two different ways that a layout can be implemented via panels. Panels supports both module and theme implementations of panels. The module implementation requires that hook_ctools_plugin_directory define the directory in which your layout plugins exist. (This same hook defines the directory for all panels plugins) Alternately, if you intend on implementing a layout in a theme this can be done primary through the theme's info file. The Ctools help does a great job of actually explaining this portion of the API <a href="topic:ctools/plugins-implementing">ctools: plugins</a>.</p>
|
||||
|
||||
<p>Ctools explains even the layout hooks a little in its example, but we'll recap quickly and expand on this information. As ctools explains, the actual plugin file must be named with care as it will directly affect your naming scheme for the hook within it. This is really no different from any other hook within drupal except that we'll be using multiple replacements in this case. The function we're looking to implement is an instance of:
|
||||
<code>function YOURMODULE_PLUGINNAME_OWNERMODULE_PLUGINTYPE()</code>
|
||||
In our case we already know that the function will be:
|
||||
<code>function YOURMODULE_PLUGINNAME_panels_layouts()</code>
|
||||
This is because the plugin type we're working with is a layout, and the module that implements these layouts is the panels module. For the rest of the naming scheme "YOURMODULE" will be replaced with either the name of your module that implements this layout, or the name of the theme, and "PLUGINNAME" will be replaced with whatever the name of the plugin file is. For purposes of this example our module name us going to be "layout_sample" and our plugin will be "first_layout".</p>
|
||||
|
||||
<h2>Directory Structure:</h2>
|
||||
<p>We're going to assume that you've laid your directory structure out very similarly to how panels does it. Something like this is rather likely:
|
||||
<pre>layout_sample
|
||||
layout_sample.info
|
||||
layout_sample.module
|
||||
plugins
|
||||
layouts
|
||||
first_layout
|
||||
first_layout.css
|
||||
first_layout.inc
|
||||
first_layout.png
|
||||
layout-sample-first-layout.tpl.php</pre>
|
||||
The name of our .inc file is going to be the key to the entire layout plugin.</p>
|
||||
|
||||
<h2>The .inc File:</h2>
|
||||
<p>We will start with the first_layout.inc file as it's the most important file we're dealing with here. First_layout.inc will look similar to the following:
|
||||
<pre>function layout_sample_first_layout_panels_layouts() {
|
||||
$items['first_layout'] = array(
|
||||
'title' => t('First Layout'),
|
||||
'icon' => 'first_layout.png',
|
||||
'theme' => 'layout_sample_first_layout',
|
||||
'css' => 'first_layout.css',
|
||||
'panels' => array(
|
||||
'main' => t('Main region'),
|
||||
'right' => t('Right region'),
|
||||
),
|
||||
);
|
||||
return $items;
|
||||
}</pre>
|
||||
The include file defines all the other files that our layout will utilize in order to be truly useful. The array is fairly self explanitory but for the sake of specificity:
|
||||
<ol>
|
||||
<li><strong>Title:</strong><br />The title of our layout. (Utilized within the panels administration screens)</li>
|
||||
<li><strong>Icon:</strong><br />The graphical representation of our layout. (Utilized within the panels administration screens)</li>
|
||||
<li><strong>Theme:</strong><br />The template file of our layout. (Sharp eyed readers will note that the theme definition utilizes underscores instead of dashes, and does not have ".tpl.php" after it. This is refering to the layout-sample-first-layout.tpl.php file all the same, it is simply how the naming convention works. Utilize dashes in the tpl file name and underscores when refering to it in your include file.)</li>
|
||||
<li><strong>CSS:</strong><br />The css file to be utilized for our layout. (Utilized within the panels administration screens, AND when viewing the actual panel itself.)</li>
|
||||
<li><strong>Panels:</strong><br />Defines all the various regions within your panel. This will be further utilized within our tpl.php file.</li>
|
||||
</ol>
|
||||
There are many additional properties that can be added to the include file. For purposes of this document we'll also make mention of the 'admin css' property. 'Admin css' is especially useful when utilizing a fixed width layout with fixed with panel regions. This can break under most administrative circumstances, and panels provides you with the ability to give an additional css layout for the administrative section. It's a simple nicety and looks like this:
|
||||
<pre>function layout_sample_first_layout_panels_layouts() {
|
||||
$items['first_layout'] = array(
|
||||
'title' => t('First Layout'),
|
||||
'icon' => 'first_layout.png',
|
||||
'theme' => 'layout_sample_first_layout',
|
||||
'css' => 'first_layout.css',
|
||||
'admin css' => 'first_layout_admin.css',
|
||||
'panels' => array(
|
||||
'main' => t('Main region'),
|
||||
'right' => t('Right region'),
|
||||
),
|
||||
);
|
||||
return $items;
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>The tpl.php File:</h2>
|
||||
<p>The tpl.php file is very similar to any other template file within drupal. The difference here is that we're being passed an array of regions through $content, and we also have a css id available to us for the entire panel in the form of $css_id. The template is very straight forward and will look similar to the following:
|
||||
<pre><div class="panel-display panel-stacked-twothirds-onethird clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
|
||||
<div class="panel-panel panel-col-first panel-region-main">
|
||||
<div class="inside"><?php print $content['main']; ?></div>
|
||||
</div>
|
||||
|
||||
<div class="panel-panel panel-col-last panel-region-right">
|
||||
<div class="inside"><?php print $content['right']; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</pre>
|
||||
This is simply an example of what the html could look like. You can alter an update this html to fit your own needs.
|
||||
</p>
|
||||
|
||||
<h2>The Other Files:</h2>
|
||||
<p>The css and png files are as simple as any other css or png file you've ever utilized. Panels provides some images for its graphical representations of its layouts. I would heavily encourage you to modify these to suit your needs. The CSS files (admin and non) will be included at the appropriate times. Simply set them up to fit your purposes. If you're utilizing fixed width panel regions it's probably smart to provide an admin css file as well with your panel layout.</p>
|
||||
@@ -1,11 +1,7 @@
|
||||
<h2>Getting Started:</h2>
|
||||
<p>Layout plugins are one of the simplest and most powerful sections of the panels api. There are two different ways that a layout can be implemented via panels. Panels supports both module and theme implementations of panels. The module implementation requires that hook_ctools_plugin_directory define the directory in which your layout plugins exist. (This same hook defines the directory for all panels plugins) Alternately, if you intend on implementing a layout in a theme this can be done primary through the theme's info file. The CTools help does a great job of actually explaining this portion of the API <a href="topic:ctools/plugins-implementing">ctools: plugins</a>.</p>
|
||||
<p>Layout plugins are one of the simplest and most powerful sections of the Panels API. There are two different ways that a layout can be implemented via Panels. Panels supports both module and theme implementations of Panels. The module implementation requires that hook_ctools_plugin_directory define the directory in which your layout plugins exist. (This same hook defines the directory for all Panels plugins) Alternately, if you intend on implementing a layout in a theme this can be done primary through the theme's info file. The CTools help does a great job of actually explaining this portion of the API <a href="topic:ctools/plugins-implementing">ctools: plugins</a>.</p>
|
||||
|
||||
<p>CTools explains even the layout hooks a little in its example, but we'll recap quickly and expand on this information. As ctools explains, the actual plugin file must be named with care as it will directly affect your naming scheme for the hook within it. This is really no different from any other hook within drupal except that we'll be using multiple replacements in this case. The function we're looking to implement is an instance of:
|
||||
<code>function YOURMODULE_PLUGINNAME_OWNERMODULE_PLUGINTYPE()</code>
|
||||
In our case we already know that the function will be:
|
||||
<code>function YOURMODULE_PLUGINNAME_panels_layouts()</code>
|
||||
This is because the plugin type we're working with is a layout, and the module that implements these layouts is the panels module. For the rest of the naming scheme "YOURMODULE" will be replaced with either the name of your module that implements this layout, or the name of the theme, and "PLUGINNAME" will be replaced with whatever the name of the plugin file is. For purposes of this example our module name us going to be "layout_sample" and our plugin will be "first_layout".</p>
|
||||
<p>For purposes of this example, our module name is going to be "layout_sample" and our plugin will be "first_layout".</p>
|
||||
|
||||
<h2>Directory Structure:</h2>
|
||||
<p>We're going to assume that you've laid your directory structure out very similarly to how panels does it. Something like this is rather likely:
|
||||
@@ -21,10 +17,23 @@ This is because the plugin type we're working with is a layout, and the module t
|
||||
layout-sample-first-layout.tpl.php</pre>
|
||||
The name of our .inc file is going to be the key to the entire layout plugin.</p>
|
||||
|
||||
<h2>The .module File:</h2>
|
||||
<p>First, declare where your custom layouts reside by implementing the CTools hook <code>hook_ctools_plugin_directory()</code>:
|
||||
<pre>
|
||||
/**
|
||||
* Implements hook_ctools_plugin_directory().
|
||||
*/
|
||||
function layout_sample_ctools_plugin_directory($module, $plugin) {
|
||||
if ($module == 'panels' && $plugin == 'layouts') {
|
||||
return 'plugins/layouts';
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>The .inc File:</h2>
|
||||
<p>We will start with the first_layout.inc file as it's the most important file we're dealing with here. First_layout.inc will look similar to the following:
|
||||
<pre>
|
||||
$plugin = array(
|
||||
$plugin = array(
|
||||
'title' => t('First Layout'),
|
||||
'icon' => 'first_layout.png',
|
||||
'theme' => 'layout_sample_first_layout',
|
||||
@@ -35,15 +44,15 @@ The name of our .inc file is going to be the key to the entire layout plugin.</p
|
||||
),
|
||||
);
|
||||
</pre>
|
||||
The include file defines all the other files that our layout will utilize in order to be truly useful. The array is fairly self explanitory but for the sake of specificity:
|
||||
The include file defines all the other files that our layout will utilize in order to be truly useful. The array is fairly self explanitory but for the sake of specificity:
|
||||
<ol>
|
||||
<li><strong>Title:</strong><br />The title of our layout. (Utilized within the panels administration screens)</li>
|
||||
<li><strong>Icon:</strong><br />The graphical representation of our layout. (Utilized within the panels administration screens)</li>
|
||||
<li><strong>Theme:</strong><br />The template file of our layout. (Sharp eyed readers will note that the theme definition utilizes underscores instead of dashes, and does not have ".tpl.php" after it. This is refering to the layout-sample-first-layout.tpl.php file all the same, it is simply how the naming convention works. Utilize dashes in the tpl file name and underscores when refering to it in your include file.)</li>
|
||||
<li><strong>Theme:</strong><br />The template file of our layout. (Sharp eyed readers will note that the theme definition utilizes underscores instead of dashes, and does not have ".tpl.php" after it. This is referring to the layout-sample-first-layout.tpl.php file all the same, it is simply how the naming convention works. Utilize dashes in the tpl file name and underscores when referring to it in your include file.)</li>
|
||||
<li><strong>CSS:</strong><br />The css file to be utilized for our layout. (Utilized within the panels administration screens, AND when viewing the actual panel itself.)</li>
|
||||
<li><strong>Panels:</strong><br />Defines all the various regions within your panel. This will be further utilized within our tpl.php file.</li>
|
||||
<li><strong>Panels:</strong><br />Defines all the various regions within your panel. This will be further utilized within our tpl.php file.</li>
|
||||
</ol>
|
||||
There are many additional properties that can be added to the include file. For purposes of this document we'll also make mention of the 'admin css' property. 'Admin css' is especially useful when utilizing a fixed width layout with fixed with panel regions. This can break under most administrative circumstances, and panels provides you with the ability to give an additional css layout for the administrative section. It's a simple nicety and looks like this:
|
||||
There are many additional properties that can be added to the include file. For purposes of this document we'll also make mention of the 'admin css' property. 'Admin css' is especially useful when utilizing a fixed width layout with fixed with panel regions. This can break under most administrative circumstances, and panels provides you with the ability to give an additional css layout for the administrative section. It's a simple nicety and looks like this:
|
||||
<pre>
|
||||
$plugin = array(
|
||||
'title' => t('First Layout'),
|
||||
@@ -60,8 +69,8 @@ There are many additional properties that can be added to the include file. For
|
||||
</p>
|
||||
|
||||
<h2>The tpl.php File:</h2>
|
||||
<p>The tpl.php file is very similar to any other template file within drupal. The difference here is that we're being passed an array of regions through $content, and we also have a css id available to us for the entire panel in the form of $css_id. The template is very straight forward and will look similar to the following:
|
||||
<pre><div class="panel-display panel-stacked-twothirds-onethird clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
|
||||
<p>The tpl.php file is very similar to any other template file within drupal. The difference here is that we're being passed an array of regions through $content, and we also have a css id available to us for the entire panel in the form of $css_id. The template is very straight forward and will look similar to the following:
|
||||
<pre><div class="panel-display panel-stacked-twothirds-onethird clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
|
||||
<div class="panel-panel panel-col-first panel-region-main">
|
||||
<div class="inside"><?php print $content['main']; ?></div>
|
||||
</div>
|
||||
@@ -75,4 +84,4 @@ This is simply an example of what the html could look like. You can alter an upd
|
||||
</p>
|
||||
|
||||
<h2>The Other Files:</h2>
|
||||
<p>The css and png files are as simple as any other css or png file you've ever utilized. Panels provides some images for its graphical representations of its layouts. I would heavily encourage you to modify these to suit your needs. The CSS files (admin and non) will be included at the appropriate times. Simply set them up to fit your purposes. If you're utilizing fixed width panel regions it's probably smart to provide an admin css file as well with your panel layout.</p>
|
||||
<p>The css and png files are as simple as any other css or png file you've ever utilized. Panels provides some images for its graphical representations of its layouts. I would heavily encourage you to modify these to suit your needs. The CSS files (admin and non) will be included at the appropriate times. Simply set them up to fit your purposes. If you're utilizing fixed width panel regions it's probably smart to provide an admin css file as well with your panel layout.</p>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
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']),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
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 2016-10-16
|
||||
version = "7.x-3.8"
|
||||
core = "7.x"
|
||||
project = "panels"
|
||||
datestamp = "1476582295"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -0,0 +1,442 @@
|
||||
<?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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
|
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 216 B After Width: | Height: | Size: 216 B |
|
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 214 B |
|
Before Width: | Height: | Size: 49 B After Width: | Height: | Size: 49 B |
|
Before Width: | Height: | Size: 949 B After Width: | Height: | Size: 949 B |
|
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 795 B |
|
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |
|
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 566 B |
|
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 818 B |
|
Before Width: | Height: | Size: 1001 B After Width: | Height: | Size: 1001 B |
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 877 B After Width: | Height: | Size: 877 B |
|
Before Width: | Height: | Size: 236 B After Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 735 B After Width: | Height: | Size: 735 B |
|
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 701 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 108 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 106 B After Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 507 B |
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains template preprocess files for the add content modal themes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Preprocess the primary entry level theme.
|
||||
*/
|
||||
function template_preprocess_panels_add_content_modal(&$vars) {
|
||||
$vars['categories_array'] = array();
|
||||
|
||||
// Process the list of categories.
|
||||
foreach ($vars['categories'] as $key => $category_info) {
|
||||
// 'root' category is actually displayed under the categories, so
|
||||
// skip it.
|
||||
if ($key == 'root') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$class = 'panels-modal-add-category';
|
||||
if ($key == $vars['category']) {
|
||||
$class .= ' active';
|
||||
}
|
||||
|
||||
$url = $vars['renderer']->get_url('select-content', $vars['region'], $key);
|
||||
$vars['categories_array'][] = ctools_ajax_text_button($category_info['title'], $url, '', $class);
|
||||
}
|
||||
|
||||
// Now render the top level buttons (aka the root category) if any.
|
||||
$vars['root_content'] = '';
|
||||
if (!empty($vars['categories']['root'])) {
|
||||
foreach ($vars['categories']['root']['content'] as $content_type) {
|
||||
$vars['root_content'] .= theme('panels_add_content_link', array('renderer' => $vars['renderer'], 'region' => $vars['region'], 'content_type' => $content_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the panels add content modal.
|
||||
*
|
||||
* This is run here so that preprocess can make changes before links are
|
||||
* actually rendered.
|
||||
*/
|
||||
function template_process_panels_add_content_modal(&$vars) {
|
||||
$content = !empty($vars['categories'][$vars['category']]['content']) ? $vars['categories'][$vars['category']]['content'] : array();
|
||||
|
||||
// If no category is selected or the category is empty or our special empty
|
||||
// category render a 'header' that will appear instead of the columns.
|
||||
if (empty($vars['category']) || empty($content) || $vars['category'] == 'root') {
|
||||
$vars['header'] = t('Content options are divided by category. Please select a category from the left to proceed.');
|
||||
}
|
||||
else {
|
||||
$titles = array_keys($content);
|
||||
natcasesort($titles);
|
||||
|
||||
// This will default to 2 columns in the theme definition but could be
|
||||
// changed by a preprocess. Ensure there is at least one column.
|
||||
$columns = max(1, $vars['column_count']);
|
||||
$vars['columns'] = array_fill(1, $columns, '');
|
||||
|
||||
$col_size = count($titles) / $columns;
|
||||
$count = 0;
|
||||
foreach ($titles as $title) {
|
||||
$which = floor($count++ / $col_size) + 1;
|
||||
$vars['columns'][$which] .= theme('panels_add_content_link', array('renderer' => $vars['renderer'], 'region' => $vars['region'], 'content_type' => $content[$title]));
|
||||
}
|
||||
}
|
||||
|
||||
$vars['messages'] = theme('status_messages');
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess the add content link used in the modal.
|
||||
*/
|
||||
function template_preprocess_panels_add_content_link(&$vars) {
|
||||
$vars['title'] = filter_xss_admin($vars['content_type']['title']);
|
||||
$vars['description'] = isset($vars['content_type']['description']) ? $vars['content_type']['description'] : $vars['title'];
|
||||
$vars['icon'] = ctools_content_admin_icon($vars['content_type']);
|
||||
$vars['url'] = $vars['renderer']->get_url('add-pane', $vars['region'], $vars['content_type']['type_name'], $vars['content_type']['subtype_name']);
|
||||
$subtype_class = 'add-content-link-' . str_replace('_', '-', $vars['content_type']['subtype_name']);
|
||||
$vars['image_button'] = ctools_ajax_image_button($vars['icon'], $vars['url'], $vars['description'], $subtype_class . '-image-button panels-modal-add-config');
|
||||
$vars['text_button'] = ctools_ajax_text_button($vars['title'], $vars['url'], $vars['description'], $subtype_class . '-text-button panels-modal-add-config');
|
||||
if (function_exists('ctools_ajax_icon_text_button')) {
|
||||
$vars['icon_text_button'] = ctools_ajax_icon_text_button($vars['title'], $vars['icon'], $vars['url'], $vars['description'], $subtype_class . '-icon-text-button panels-modal-add-config');
|
||||
}
|
||||
}
|
||||
@@ -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.'));
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ class panels_allowed_layouts {
|
||||
* as allowed or not allowed on the initial call to panels_allowed_layouts::set_allowed()
|
||||
*
|
||||
*/
|
||||
function panels_allowed_layouts($start_allowed = TRUE) {
|
||||
function __construct($start_allowed = TRUE) {
|
||||
// TODO would be nice if there was a way to just fetch the names easily
|
||||
foreach ($this->list_layouts() as $layout_name) {
|
||||
$this->allowed_layout_settings[$layout_name] = $start_allowed ? 1 : 0;
|
||||
@@ -196,7 +196,7 @@ class panels_allowed_layouts {
|
||||
*/
|
||||
function save() {
|
||||
if (!is_null($this->module_name)) {
|
||||
variable_set($this->module_name . "_allowed_layouts", serialize($this));
|
||||
variable_set($this->module_name . '_allowed_layouts', serialize($this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,9 +245,19 @@ function panels_common_settings($form, &$form_state, $module_name = 'panels_comm
|
||||
}
|
||||
|
||||
$default_options['other'] = t('New content of other types');
|
||||
$form['panels_common_default'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
|
||||
$form['additional_settings'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
);
|
||||
|
||||
$form['common'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('New content behavior'),
|
||||
'#group' => 'additional_settings',
|
||||
'#weight' => -10,
|
||||
);
|
||||
$form['common']['panels_common_default'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#description' => t('Select the default behavior of new content added to the system. If checked, new content will automatically be immediately available to be added to Panels pages. If not checked, new content will not be available until specifically allowed here.'),
|
||||
'#options' => $default_options,
|
||||
'#default_value' => array_keys(array_filter($default_types)),
|
||||
@@ -262,7 +272,11 @@ function panels_common_settings($form, &$form_state, $module_name = 'panels_comm
|
||||
// each type its own checkboxes set unless it's 'single' in which
|
||||
// case it can go into our fake other set.
|
||||
$available_content_types = ctools_content_get_all_types();
|
||||
$allowed_content_types = variable_get($module_name . '_allowed_types', array());
|
||||
$allowed_content_types = db_select('panels_allowed_types', 'pat')
|
||||
->fields('pat', array('type', 'allowed'))
|
||||
->condition('module', $module_name)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
|
||||
foreach ($available_content_types as $id => $types) {
|
||||
foreach ($types as $type => $info) {
|
||||
@@ -280,18 +294,23 @@ function panels_common_settings($form, &$form_state, $module_name = 'panels_comm
|
||||
|
||||
$form['content_types'] = array(
|
||||
'#tree' => TRUE,
|
||||
'#prefix' => '<div class="clearfix">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
// cheat a bit
|
||||
$content_types['other'] = array('title' => t('Other'), 'weight' => 10);
|
||||
foreach ($content_types as $id => $info) {
|
||||
if (isset($allowed[$id])) {
|
||||
|
||||
$form['content_types'][$id] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#group' => 'additional_settings',
|
||||
'#title' => t('Allowed @s content', array('@s' => $info['title'])),
|
||||
);
|
||||
|
||||
$form['content_types'][$id]['options'] = array(
|
||||
'#prefix' => '<div class="panels-page-type-container">',
|
||||
'#suffix' => '</div>',
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Allowed @s content', array('@s' => $info['title'])),
|
||||
'#options' => $options[$id],
|
||||
'#default_value' => array_keys(array_filter($allowed[$id])),
|
||||
'#checkall' => TRUE,
|
||||
@@ -300,8 +319,14 @@ function panels_common_settings($form, &$form_state, $module_name = 'panels_comm
|
||||
}
|
||||
}
|
||||
|
||||
// Layout selection.
|
||||
panels_common_allowed_layouts_form($form, $form_state, $module_name);
|
||||
|
||||
$form['allowed'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => isset($allowed) ? array_keys($allowed) : array(),
|
||||
);
|
||||
|
||||
$form['module_name'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $module_name,
|
||||
@@ -331,8 +356,23 @@ function panels_common_settings_submit($form, &$form_state) {
|
||||
$module_name = $form_state['values']['module_name'];
|
||||
variable_set($module_name . '_default', $form_state['values']['panels_common_default']);
|
||||
if (!$form_state['skip']) {
|
||||
// merge the broken apart array neatly back together
|
||||
variable_set($module_name . '_allowed_types', call_user_func_array('array_merge', $form_state['values']['content_types']));
|
||||
// Merge the broken apart array neatly back together.
|
||||
$allowed_content_types = array();
|
||||
$content_types = $form_state['values']['allowed'];
|
||||
foreach ($content_types as $content_type) {
|
||||
$allowed_content_types = array_merge($allowed_content_types, $form_state['values']['content_types'][$content_type]['options']);
|
||||
foreach ($allowed_content_types as $type => $allowed) {
|
||||
$allowed = empty($allowed) ? 0 : 1;
|
||||
db_merge('panels_allowed_types')
|
||||
->key(array('module' => $module_name, 'type' => $type))
|
||||
->fields(array(
|
||||
'module' => $module_name,
|
||||
'type' => $type,
|
||||
'allowed' => $allowed,
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
drupal_set_message(t('Your changes have been saved.'));
|
||||
}
|
||||
@@ -342,9 +382,13 @@ function panels_common_settings_submit($form, &$form_state) {
|
||||
*/
|
||||
function panels_common_get_allowed_types($module, $contexts = array(), $has_content = FALSE, $default_defaults = array(), $default_allowed_types = array()) {
|
||||
// Get a list of all types that are available
|
||||
|
||||
$default_types = variable_get($module . '_default', $default_defaults);
|
||||
$allowed_types = variable_get($module . '_allowed_types', $default_allowed_types);
|
||||
$allowed_types = db_select('panels_allowed_types', 'pat')
|
||||
->fields('pat', array('type', 'allowed'))
|
||||
->condition('module', $module)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
$allowed_types = !empty($allowed_types) ? $allowed_types : $default_allowed_types;
|
||||
|
||||
// By default, if they haven't gone and done the initial setup here,
|
||||
// let all 'other' types (which will be all types) be available.
|
||||
@@ -391,9 +435,15 @@ function panels_common_allowed_layouts_form(&$form, &$form_state, $module_name)
|
||||
$form_state['allowed_layouts'] = &$allowed_layouts;
|
||||
|
||||
ctools_add_js('layout', 'panels');
|
||||
$form['layouts'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
|
||||
$form['layout_selection'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Select allowed layouts'),
|
||||
'#group' => 'additional_settings',
|
||||
'#weight' => 10,
|
||||
);
|
||||
$form['layout_selection']['layouts'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $options,
|
||||
'#description' => t('Check the boxes for all layouts you want to allow users choose from when picking a layout. You must allow at least one layout.'),
|
||||
'#default_value' => array_keys(array_filter($allowed_layouts->allowed_layout_settings)),
|
||||
@@ -423,7 +473,7 @@ function panels_common_allowed_layouts_form_submit($form, &$form_state) {
|
||||
* Get the allowed layout object for the given module.
|
||||
*/
|
||||
function panels_common_get_allowed_layout_object($module_name) {
|
||||
$allowed_layouts = unserialize(variable_get($module_name . "_allowed_layouts", serialize('')));
|
||||
$allowed_layouts = unserialize(variable_get($module_name . '_allowed_layouts', serialize('')));
|
||||
|
||||
// if no parameter was provided, or the variable_get failed
|
||||
if (!$allowed_layouts) {
|
||||
@@ -445,6 +495,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;
|
||||
@@ -516,16 +567,21 @@ function theme_panels_common_content_list($vars) {
|
||||
* @return
|
||||
* The rendered output.
|
||||
*/
|
||||
function panels_common_print_layout_links($layouts, $base_path, $link_options = array()) {
|
||||
function panels_common_print_layout_links($layouts, $base_path, $link_options = array(), $current_layout = NULL) {
|
||||
$output = '';
|
||||
|
||||
$categories = array();
|
||||
ctools_include('cleanstring');
|
||||
$default_category = '';
|
||||
foreach ($layouts as $id => $layout) {
|
||||
$category = ctools_cleanstring($layout['category']);
|
||||
|
||||
$categories[$category] = $layout['category'];
|
||||
$options[$category][$id] = panels_print_layout_link($id, $layout, $base_path . '/' . $id, $link_options);
|
||||
if ($id == $current_layout) {
|
||||
$default_category = $category;
|
||||
}
|
||||
|
||||
$options[$category][$id] = panels_print_layout_link($id, $layout, $base_path . '/' . $id, $link_options, $current_layout);
|
||||
}
|
||||
|
||||
$form = array();
|
||||
@@ -535,8 +591,9 @@ function panels_common_print_layout_links($layouts, $base_path, $link_options =
|
||||
'#options' => $categories,
|
||||
'#name' => 'categories',
|
||||
'#id' => 'edit-categories',
|
||||
'#value' => '',
|
||||
'#value' => $default_category,
|
||||
'#parents' => array('categories'),
|
||||
'#access' => (count($categories) > 1) ? TRUE : FALSE,
|
||||
);
|
||||
|
||||
$output .= drupal_render($form);
|
||||
@@ -557,7 +614,7 @@ function panels_common_print_layout_links($layouts, $base_path, $link_options =
|
||||
|
||||
$output .= '<div id="panels-layout-category-' . $category . '-wrapper">';
|
||||
$output .= '<div id="panels-layout-category-' . $category . '" class="form-checkboxes clearfix">';
|
||||
$output .= '<div class="panels-layouts-category">' . $categories[$category] . '</div>';
|
||||
$output .= (count($categories) > 1) ? '<div class="panels-layouts-category">' . $categories[$category] . '</div>' : '';
|
||||
|
||||
foreach ($links as $key => $link) {
|
||||
$output .= $link;
|
||||
|
||||
@@ -68,6 +68,7 @@ function panels_edit_display_form($form, &$form_state) {
|
||||
$links = $renderer->get_display_links();
|
||||
}
|
||||
else {
|
||||
$renderer->no_edit_links = TRUE;
|
||||
$links = '';
|
||||
}
|
||||
$form['hide']['display-settings'] = array(
|
||||
@@ -239,7 +240,7 @@ function panels_edit_display_settings_form($form, &$form_state) {
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $display->title,
|
||||
'#title' => t('Title'),
|
||||
'#description' => t('The title of this panel. If left blank, a default title may be used. Set to No Title if you want the title to actually be blank.'),
|
||||
'#description' => t('The title of this panel. If left blank, a default title may be used. If you want the title actually to be blank, change the "Title type" dropdown from "Manually Set" to "No Title".'),
|
||||
'#process' => array('ctools_dependent_process'),
|
||||
'#dependency' => array('edit-display-title-hide-title' => array(PANELS_TITLE_FIXED)),
|
||||
'#maxlength' => 255,
|
||||
@@ -301,7 +302,7 @@ function panels_edit_display_settings_form($form, &$form_state) {
|
||||
* Validate the layout settings form.
|
||||
*/
|
||||
function panels_edit_display_settings_form_validate($form, &$form_state) {
|
||||
if ($function = panels_plugin_get_function('layout', $form_state['layout'], 'settings validate')) {
|
||||
if ($function = panels_plugin_get_function('layouts', $form_state['layout'], 'settings validate')) {
|
||||
$function($form_state['values']['layout_settings'], $form['layout_settings'], $form_state['display'], $form_state['layout'], $form_state['display']->layout_settings);
|
||||
}
|
||||
}
|
||||
@@ -311,7 +312,7 @@ function panels_edit_display_settings_form_validate($form, &$form_state) {
|
||||
*/
|
||||
function panels_edit_display_settings_form_submit($form, &$form_state) {
|
||||
$display = &$form_state['display'];
|
||||
if ($function = panels_plugin_get_function('layout', $form_state['layout'], 'settings submit')) {
|
||||
if ($function = panels_plugin_get_function('layouts', $form_state['layout'], 'settings submit')) {
|
||||
$function($form_state['values']['layout_settings'], $display, $form_state['layout'], $display->layout_settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ function panels_choose_layout($form, &$form_state) {
|
||||
}
|
||||
}
|
||||
|
||||
ctools_add_js('panels-base', 'panels');
|
||||
ctools_add_js('layout', 'panels');
|
||||
|
||||
$form['categories'] = array(
|
||||
@@ -125,6 +126,10 @@ function panels_choose_layout($form, &$form_state) {
|
||||
);
|
||||
|
||||
foreach ($radios as $key => $choice) {
|
||||
// Set the first available layout as default value.
|
||||
if (empty($display->layout)) {
|
||||
$display->layout = $key;
|
||||
}
|
||||
// Generate the parents as the autogenerator does, so we will have a
|
||||
// unique id for each radio button.
|
||||
$form['layout'][$category][$key] = array(
|
||||
@@ -176,16 +181,54 @@ function panels_choose_layout_submit($form, &$form_state) {
|
||||
* The Drupal $form_state
|
||||
*/
|
||||
function panels_change_layout($form, &$form_state) {
|
||||
$display = &$form_state['display'];
|
||||
// Provide a temporary display and renderer.
|
||||
$form_state['layout_display'] = $display = panels_new_display();
|
||||
if (isset($form_state['cache_key'])) {
|
||||
$display->cache_key = $form_state['cache_key'];
|
||||
}
|
||||
|
||||
$new_layout = panels_get_layout($form_state['layout']);
|
||||
$new_layout_panels = panels_get_regions($new_layout, $display);
|
||||
$new_layout_regions = panels_get_regions($new_layout, $display);
|
||||
|
||||
$options = $new_layout_panels;
|
||||
$keys = array_keys($options);
|
||||
$default = current($options);
|
||||
$old_layout = panels_get_layout($form_state['display']->layout);
|
||||
$old_layout_regions = panels_get_regions($old_layout, $form_state['display']);
|
||||
|
||||
$old_layout = panels_get_layout($display->layout);
|
||||
$display->layout = $form_state['layout'];
|
||||
$renderer = panels_get_renderer_handler('editor', $display);
|
||||
|
||||
$renderer->meta_location = 'inline';
|
||||
|
||||
ctools_add_css('panels_admin', 'panels');
|
||||
ctools_add_css('panels_dnd', 'panels');
|
||||
ctools_add_css('dropdown');
|
||||
|
||||
// For every region that had content in the old layout, create a custom pane
|
||||
// in the new layout that represents that region.
|
||||
$keys = array_keys($new_layout_regions);
|
||||
$default_region = reset($keys);
|
||||
foreach ($old_layout_regions as $region_id => $region_name) {
|
||||
if (!empty($form_state['display']->panels[$region_id])) {
|
||||
$pane = panels_new_pane('custom', 'custom', TRUE);
|
||||
$pane->pid = $region_id;
|
||||
$pane->configuration['title'] = t('Panes');
|
||||
$pane->configuration['admin_title'] = $region_name;
|
||||
// Get a list of pane titles used.
|
||||
$titles = array();
|
||||
foreach ($form_state['display']->panels[$region_id] as $pid) {
|
||||
$content_type = ctools_get_content_type($form_state['display']->content[$pid]->type);
|
||||
$titles[$pid] = ctools_content_admin_title($content_type, $form_state['display']->content[$pid]->subtype, $form_state['display']->content[$pid]->configuration, $form_state['display']->context);
|
||||
}
|
||||
$pane->configuration['body'] = '<ul><li>' . implode('</li><li>', $titles) . '</li></ul>';
|
||||
|
||||
// If the region id matches, make it the same; otherwise, put it
|
||||
// in the default region.
|
||||
$pane->panel = empty($new_layout_regions[$region_id]) ? $default_region : $region_id;
|
||||
|
||||
// Add the pane to the approprate spots.
|
||||
$display->content[$pane->pid] = $pane;
|
||||
$display->panels[$pane->panel][] = $pane->pid;
|
||||
}
|
||||
}
|
||||
|
||||
$form['container'] = array(
|
||||
'#prefix' => '<div class="change-layout-display clearfix">',
|
||||
@@ -193,7 +236,7 @@ function panels_change_layout($form, &$form_state) {
|
||||
);
|
||||
|
||||
$form['container']['old_layout'] = array(
|
||||
'#markup' => panels_print_layout_icon($display->layout, $old_layout, check_plain($old_layout['title'])),
|
||||
'#markup' => panels_print_layout_icon($form_state['display']->layout, $old_layout, check_plain($old_layout['title'])),
|
||||
);
|
||||
|
||||
$form['container']['right_arrow'] = array(
|
||||
@@ -203,29 +246,17 @@ function panels_change_layout($form, &$form_state) {
|
||||
'#markup' => panels_print_layout_icon($form_state['layout'], $new_layout, check_plain($new_layout['title'])),
|
||||
);
|
||||
|
||||
$form['old'] = array(
|
||||
'#tree' => true,
|
||||
'#prefix' => '<div class="panels-layout-list">',
|
||||
'#suffix' => '</div>',
|
||||
$edit_form_state = array(
|
||||
'display' => $display,
|
||||
'renderer' => $renderer,
|
||||
'no buttons' => TRUE,
|
||||
'no preview' => TRUE,
|
||||
'no display settings' => TRUE,
|
||||
'display_title' => '',
|
||||
);
|
||||
|
||||
$old_layout_panels = panels_get_regions($old_layout, $display);
|
||||
if (empty($display->panels)) {
|
||||
$form['old'] = array(
|
||||
'#prefix' => '<div>',
|
||||
'#markup' => t('There is no content in the panel display. If there were content, you would be given an opportunity to select where in the new layout the old content would be placed. Select "Save" or "Continue" to proceed. This change will not be processed if you do not continue.'),
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($display->panels as $id => $content) {
|
||||
$form['old'][$id] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Move content in @layout to', array('@layout' => $old_layout_panels[$id])),
|
||||
'#options' => $options,
|
||||
'#default_value' => array_key_exists($id, $options) ? $id : $default,
|
||||
);
|
||||
}
|
||||
ctools_include('display-edit', 'panels');
|
||||
$form = panels_edit_display_form($form, $edit_form_state);
|
||||
|
||||
if (empty($form_state['no buttons'])) {
|
||||
$form['back'] = array(
|
||||
@@ -250,25 +281,48 @@ function panels_change_layout($form, &$form_state) {
|
||||
* This submit handler will move panes around and save the display.
|
||||
*/
|
||||
function panels_change_layout_submit($form, &$form_state) {
|
||||
$display = &$form_state['display'];
|
||||
$display = $form_state['display'];
|
||||
$layout_display = $form_state['layout_display'];
|
||||
|
||||
if (!empty($form_state['values']['old'])) {
|
||||
foreach ($form_state['values']['old'] as $id => $new_id) {
|
||||
if (isset($display->panels[$id])) {
|
||||
if (!isset($content[$new_id])) {
|
||||
$content[$new_id] = array();
|
||||
$switch = array();
|
||||
|
||||
// Calculate the pids submitted by the display and make a list of
|
||||
// translation to the regions. Remember the 'pid' of the pane
|
||||
// is the region id in the old layout.
|
||||
if (!empty($form_state['values']['panel']['pane'])) {
|
||||
foreach ($form_state['values']['panel']['pane'] as $region_id => $panes) {
|
||||
if ($panes) {
|
||||
$pids = explode(',', $panes);
|
||||
// need to filter the array, b/c passing it in a hidden field can generate trash
|
||||
foreach (array_filter($pids) as $pid) {
|
||||
$switch[$pid] = $region_id;
|
||||
}
|
||||
$content[$new_id] = array_merge($content[$new_id], $display->panels[$id]);
|
||||
}
|
||||
foreach ($content[$new_id] as $pid) {
|
||||
$display->content[$pid]->panel = $new_id;
|
||||
}
|
||||
}
|
||||
|
||||
$display->panels = $content;
|
||||
}
|
||||
|
||||
$content = array();
|
||||
foreach ($switch as $region_id => $new_region_id) {
|
||||
if (isset($display->panels[$region_id])) {
|
||||
if (!isset($content[$new_region_id])) {
|
||||
$content[$new_region_id] = array();
|
||||
}
|
||||
$content[$new_region_id] = array_merge($content[$new_region_id], $display->panels[$region_id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Go through each pane and make sure its region id is correct.
|
||||
foreach ($content as $region_id => $region) {
|
||||
foreach ($region as $pid) {
|
||||
$display->content[$pid]->panel = $region_id;
|
||||
}
|
||||
}
|
||||
|
||||
$display->panels = $content;
|
||||
|
||||
$display->layout = $form_state['layout'];
|
||||
|
||||
panels_edit_display_settings_form_submit($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -125,7 +125,7 @@ class panels_cache_object {
|
||||
/**
|
||||
* When constructed, take a snapshot of our existing out of band data.
|
||||
*/
|
||||
function panels_cache_object() {
|
||||
function __construct() {
|
||||
$this->head = drupal_add_html_head();
|
||||
$this->css = drupal_add_css();
|
||||
$this->tokens = ctools_set_page_token();
|
||||
@@ -173,22 +173,43 @@ 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:
|
||||
$tokens = ctools_set_page_token();
|
||||
foreach ($this->tokens as $token => $argument) {
|
||||
if (isset($tokens[$token])) {
|
||||
unset($tokens);
|
||||
unset($tokens[$token]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +230,11 @@ class panels_cache_object {
|
||||
}
|
||||
if (!empty($this->js)) {
|
||||
foreach ($this->js as $key => $args) {
|
||||
if ($key != 'settings') {
|
||||
if ($key !== 'settings') {
|
||||
drupal_add_js($args['data'], $args);
|
||||
}
|
||||
else {
|
||||
foreach ($args as $setting) {
|
||||
foreach ($args['data'] as $setting) {
|
||||
drupal_add_js($setting, 'setting');
|
||||
}
|
||||
}
|
||||
@@ -457,6 +478,31 @@ function panels_get_renderer_pipelines($sort = TRUE) {
|
||||
return $pipelines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch metadata on a specific panels_storage plugin.
|
||||
*
|
||||
* @param $storage
|
||||
* Name of a panel_storage plugin.
|
||||
*
|
||||
* @return
|
||||
* An array with information about the requested panels_storage plugin
|
||||
*/
|
||||
function panels_get_panels_storage_plugin($storage) {
|
||||
ctools_include('plugins');
|
||||
return ctools_get_plugins('panels', 'panels_storage', $storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch metadata for all panels_storage plugins.
|
||||
*
|
||||
* @return
|
||||
* An array of arrays with information about all available panels_storage plugins.
|
||||
*/
|
||||
function panels_get_panels_storage_plugins() {
|
||||
ctools_include('plugins');
|
||||
return ctools_get_plugins('panels', 'panels_storage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a function from a plugin, if it exists.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
@@ -80,7 +80,7 @@ Drupal.Panels.Draggable = {
|
||||
regionId: 'panel-region-',
|
||||
|
||||
// What to add to the front of a the id to get the form id for a panel
|
||||
formId: 'input#edit-',
|
||||
formId: '#edit-',
|
||||
|
||||
maxWidth: 250,
|
||||
|
||||
@@ -492,8 +492,8 @@ Drupal.behaviors.PanelsDisplayEditor = {
|
||||
Drupal.Panels.Draggable.savePositions();
|
||||
|
||||
// Bind buttons.
|
||||
$('input#panels-hide-all', context).click(Drupal.Panels.clickHideAll);
|
||||
$('input#panels-show-all', context).click(Drupal.Panels.clickShowAll);
|
||||
$('#panels-hide-all', context).click(Drupal.Panels.clickHideAll);
|
||||
$('#panels-show-all', context).click(Drupal.Panels.clickShowAll);
|
||||
|
||||
Drupal.Panels.bindClickDelete(context);
|
||||
|
||||
@@ -513,6 +513,11 @@ Drupal.behaviors.PanelsDisplayEditor = {
|
||||
$('#panels-preview').html(html);
|
||||
});
|
||||
|
||||
// Bind modal detach behaviors to cancel current form.
|
||||
$(document).bind('CToolsDetachBehaviors', function(event, context) {
|
||||
$('#edit-cancel-style', context).trigger('click');
|
||||
});
|
||||
|
||||
var setTitleClass = function () {
|
||||
if ($('#edit-display-title-hide-title').val() == 2) {
|
||||
$('#panels-dnd-main').removeClass('panels-set-title-hide');
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
Drupal.Panels = {}
|
||||
Drupal.Panels = Drupal.Panels || {};
|
||||
|
||||
Drupal.Panels.changed = function(item) {
|
||||
if (!item.is('.changed')) {
|
||||
@@ -13,6 +13,45 @@
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.Panels.AddContentModalQuickFilter = function() {
|
||||
var input_field = $('.panels-add-content-modal input[name=quickfilter]');
|
||||
input_field.data.panelsAddContentModalQuickFilter = {
|
||||
keyupTimeout: false,
|
||||
filter: function(e) {
|
||||
if (this.val().length) {
|
||||
var search_expression = this.val().toLowerCase();
|
||||
$('.panels-add-content-modal .panels-section-columns .content-type-button').each(function(i, elem) {
|
||||
if ($(elem).text().toLowerCase().search(search_expression) > -1) {
|
||||
$(elem).show();
|
||||
}
|
||||
else {
|
||||
$(elem).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
$('.panels-add-content-modal .panels-section-columns .content-type-button').show();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use timeout to reduce the iteration over the DOM tree.
|
||||
input_field.bind('keyup.AddContentModalQuickFilter', jQuery.proxy(function(e){
|
||||
var filter = $(this).data.panelsAddContentModalQuickFilter;
|
||||
if (filter.keyupTimeout) {
|
||||
window.clearTimeout(filter.timeout);
|
||||
filter.keyupTimeout = false;
|
||||
}
|
||||
// If there's only one item left and enter is hit select it right away.
|
||||
if (e.keyCode == 13 && $('.panels-add-content-modal .panels-section-columns .content-type-button:visible').length == 1) {
|
||||
$('.panels-add-content-modal .panels-section-columns .content-type-button:visible a').trigger('click');
|
||||
}
|
||||
else {
|
||||
filter.keyupTimeout = window.setTimeout(jQuery.proxy(filter.filter, this), 200);
|
||||
}
|
||||
}, input_field));
|
||||
input_field.focus();
|
||||
};
|
||||
|
||||
Drupal.Panels.restripeTable = function(table) {
|
||||
// :even and :odd are reversed because jquery counts from 0 and
|
||||
// we count from 1, so we're out of sync.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
(function ($) {
|
||||
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);
|
||||
@@ -0,0 +1,264 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -10,9 +10,17 @@ 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-01-18
|
||||
version = "7.x-3.0"
|
||||
; Tests.
|
||||
; Task handlers for entities. These inherit off one base class to make it easier
|
||||
; to repeat tests across multiple entity types.
|
||||
files[] = tests/PanelsEntityViewWebTestCase.test
|
||||
files[] = tests/PanelsNodeViewWebTestCase.test
|
||||
files[] = tests/PanelsTermViewWebTestCase.test
|
||||
files[] = tests/PanelsUserViewWebTestCase.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-10-16
|
||||
version = "7.x-3.8"
|
||||
core = "7.x"
|
||||
project = "panels"
|
||||
datestamp = "1326917446"
|
||||
datestamp = "1476582295"
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ function panels_requirements_install() {
|
||||
// Assume that if the user is running an installation profile that both
|
||||
// Panels and CTools are the same release.
|
||||
if (!(defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install')) {
|
||||
// apparently the install process doesn't include .module files,
|
||||
// Apparently the install process doesn't include .module files,
|
||||
// so we need to force the issue in order for our versioning
|
||||
// check to work.
|
||||
if (!defined('PANELS_REQUIRED_CTOOLS_API')) {
|
||||
@@ -30,24 +30,114 @@ function panels_requirements_install() {
|
||||
include_once drupal_get_path('module', 'ctools') . '/ctools.module';
|
||||
}
|
||||
if (!module_invoke('ctools', 'api_version', PANELS_REQUIRED_CTOOLS_API)) {
|
||||
$requirements['panels_ctools'] = array(
|
||||
'title' => $t('CTools API Version'),
|
||||
'value' => CTOOLS_API_VERSION,
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
'description' => t('The CTools API version is too old for Panels. Panels needs at least %version.', array('%version' => PANELS_REQUIRED_CTOOLS_API))
|
||||
);
|
||||
$requirements['panels_ctools'] = array(
|
||||
'title' => $t('CTools API Version'),
|
||||
'value' => CTOOLS_API_VERSION,
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
'description' => t('The CTools API version is too old for Panels. Panels needs at least %version.', array('%version' => PANELS_REQUIRED_CTOOLS_API)),
|
||||
);
|
||||
}
|
||||
}
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_schema().
|
||||
* Implements of hook_schema().
|
||||
*/
|
||||
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();
|
||||
// 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_9();
|
||||
}
|
||||
|
||||
function panels_schema_9() {
|
||||
$schema = panels_schema_8();
|
||||
$schema['panels_allowed_types'] = array(
|
||||
'fields' => array(
|
||||
'module' => array(
|
||||
'description' => 'The name of the module requiring allowed type settings.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'type' => array(
|
||||
'description' => 'Ctools content type to allow.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'allowed' => array(
|
||||
'description' => 'A boolean for if the type is allowed or not.',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'default' => 1,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'type_idx' => array('type'),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
function panels_schema_8() {
|
||||
$schema = panels_schema_7();
|
||||
|
||||
// Add the storage type and id columns.
|
||||
$schema['panels_display']['fields']['storage_type'] = array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'default' => '',
|
||||
);
|
||||
$schema['panels_display']['fields']['storage_id'] = array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'default' => '',
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
function panels_schema_7() {
|
||||
$schema = panels_schema_6();
|
||||
|
||||
// Update field lengths to 255 chars.
|
||||
$schema['panels_pane']['fields']['subtype']['length'] = '255';
|
||||
$schema['panels_pane']['fields']['panel']['length'] = '255';
|
||||
$schema['panels_pane']['fields']['type']['length'] = '255';
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
function panels_schema_6() {
|
||||
$schema = panels_schema_5();
|
||||
|
||||
$schema['cache_panels'] = drupal_get_schema_unprocessed('system', 'cache');
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -375,3 +465,227 @@ function panels_update_7301() {
|
||||
|
||||
return t('panels_pane.lock field already existed, update skipped.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding universally unique identifiers to panels.
|
||||
*
|
||||
* Note: This update hook is not written well. It calls apis which uses the
|
||||
* most updated drupal database, causing missing columns or tables errors. To
|
||||
* mitigate the issue, we've added updates from 7303 and 7305. Future updates
|
||||
* should go below the 7305 update.
|
||||
*
|
||||
* See https://www.drupal.org/node/2787123 for more info.
|
||||
*/
|
||||
function panels_update_7302() {
|
||||
if (!module_load_include('inc', 'ctools', 'includes/uuid')) {
|
||||
throw new DrupalUpdateException(t('Ctools UUID support not detected. You must update to a more recent version of the ctools module.'));
|
||||
}
|
||||
// Run the 7303 update first to avoid caching issues.
|
||||
// This *probably* should be placed right above update 7305, however it was
|
||||
// tested here and re-testing this update is difficult, so it stays here.
|
||||
panels_update_7303();
|
||||
|
||||
// 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));
|
||||
|
||||
// Before using panels_save_display(), we have to make sure any new fields
|
||||
// are added from future updates.
|
||||
panels_update_7305();
|
||||
|
||||
// If the Panels module is disabled we don't have access to
|
||||
// panels_load_displays().
|
||||
if (!function_exists('panels_load_displays')) {
|
||||
module_load_include('module', 'panels');
|
||||
}
|
||||
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() {
|
||||
$schema = panels_schema_6();
|
||||
|
||||
$table_name = 'cache_panels';
|
||||
if (!db_table_exists($table_name)) {
|
||||
db_create_table($table_name, $schema[$table_name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update "panels_pane" table field lengths to 255 chars.
|
||||
*/
|
||||
function panels_update_7304() {
|
||||
$schema = panels_schema_7();
|
||||
|
||||
$update_fields = array(
|
||||
'panels_pane' => array('subtype', 'panel', 'type'),
|
||||
);
|
||||
|
||||
foreach ($update_fields as $table => $fields) {
|
||||
foreach ($fields as $field_name) {
|
||||
db_change_field($table, $field_name, $field_name, $schema[$table]['fields'][$field_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "storage_type" and "storage_id" columns to "panels_display".
|
||||
*/
|
||||
function panels_update_7305() {
|
||||
$schema = panels_schema_8();
|
||||
|
||||
$new_fields = array(
|
||||
'panels_display' => array('storage_type', 'storage_id'),
|
||||
);
|
||||
|
||||
foreach ($new_fields as $table => $fields) {
|
||||
foreach ($fields as $field_name) {
|
||||
// Due to a previous failure, the column may already exist:
|
||||
if (!db_field_exists($table, $field_name)) {
|
||||
db_add_field($table, $field_name, $schema[$table]['fields'][$field_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the storage type and id on existing page manager panels displays.
|
||||
*/
|
||||
function panels_update_7306() {
|
||||
if (!db_table_exists('page_manager_handlers')) {
|
||||
return t('Skipping update - page_manager is not installed.');
|
||||
}
|
||||
|
||||
// Get all page_manager_handlers that have a panels context.
|
||||
$result = db_query("SELECT pm.name, pm.conf FROM {page_manager_handlers} pm WHERE pm.handler = 'panel_context'");
|
||||
$page_manager_panels = array();
|
||||
foreach ($result as $row) {
|
||||
$conf = unserialize($row->conf);
|
||||
if (isset($conf['did'])) {
|
||||
$page_manager_panels[$conf['did']] = $row->name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($page_manager_panels)) {
|
||||
// Check panels displays that only have empty storage types
|
||||
$result = db_query("SELECT pd.did FROM {panels_display} pd WHERE pd.did IN (:dids) AND storage_type = ''", array(':dids' => array_keys($page_manager_panels)));
|
||||
foreach ($result as $row) {
|
||||
db_update('panels_display')
|
||||
->fields(array(
|
||||
'storage_type' => 'page_manager',
|
||||
'storage_id' => $page_manager_panels[$row->did],
|
||||
))
|
||||
->condition('did', $row->did)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom table for allowed types.
|
||||
*/
|
||||
function panels_update_7307() {
|
||||
$schema = panels_schema_9();
|
||||
|
||||
$table_name = 'panels_allowed_types';
|
||||
if (!db_table_exists($table_name)) {
|
||||
db_create_table($table_name, $schema[$table_name]);
|
||||
}
|
||||
|
||||
// Read existing allowed settings and store them in a new table.
|
||||
$variables = db_select('variable', 'v')
|
||||
->fields('v', array('name'))
|
||||
->condition('name', '%' . db_like('_allowed_types'), 'LIKE')
|
||||
->execute()
|
||||
->fetchCol();
|
||||
foreach ($variables as $name) {
|
||||
$module = str_replace('_allowed_types', '', $name);
|
||||
$variable = variable_get($name);
|
||||
foreach ($variable as $type => $allowed) {
|
||||
$allowed = empty($allowed) ? 0 : 1;
|
||||
db_merge('panels_allowed_types')
|
||||
->key(array('module' => $module, 'type' => $type))
|
||||
->fields(array(
|
||||
'module' => $module,
|
||||
'type' => $type,
|
||||
'allowed' => $allowed,
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
variable_del($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename style permissions.
|
||||
*/
|
||||
function panels_update_7308() {
|
||||
$permissions = array(
|
||||
'administer panels display styles',
|
||||
'administer panels pane styles',
|
||||
'administer panels region styles',
|
||||
);
|
||||
foreach (array_keys(user_roles(TRUE, 'administer panels styles')) as $rid) {
|
||||
user_role_grant_permissions($rid, $permissions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,22 @@
|
||||
* Core functionality for the Panels engine.
|
||||
*/
|
||||
|
||||
define('PANELS_REQUIRED_CTOOLS_API', '2.0-alpha');
|
||||
define('PANELS_REQUIRED_CTOOLS_API', '2.0.9');
|
||||
|
||||
/**
|
||||
* The current working panels version.
|
||||
*
|
||||
* In a release, it should be 7.x-3.x, which should match what drush make will
|
||||
* create. In a dev format, it should be 7.x-3.(x+1)-dev, which will allow
|
||||
* modules depending on new features in panels to depend on panels > 7.x-3.x.
|
||||
*
|
||||
* To define a specific version of Panels as a dependency for another module,
|
||||
* simply include a dependency line in that module's info file, e.g.:
|
||||
* ; Requires Panels v7.x-3.4 or newer.
|
||||
* dependencies[] = panels (>=3.4)
|
||||
*/
|
||||
define('PANELS_VERSION', '7.x-3.8');
|
||||
|
||||
|
||||
define('PANELS_TITLE_FIXED', 0); // Hide title use to be true/false. So false remains old behavior.
|
||||
define('PANELS_TITLE_NONE', 1); // And true meant no title.
|
||||
@@ -37,13 +52,13 @@ function panels_theme() {
|
||||
|
||||
$theme = array();
|
||||
$theme['panels_layout_link'] = array(
|
||||
'variables' => array('title' => NULL, 'id' => NULL, 'image' => NULL, 'link' => NULL),
|
||||
'variables' => array('title' => NULL, 'id' => NULL, 'image' => NULL, 'link' => NULL, 'class' => NULL),
|
||||
);
|
||||
$theme['panels_layout_icon'] = array(
|
||||
'variables' => array('id' => NULL, 'image' => NULL, 'title' => NULL),
|
||||
);
|
||||
$theme['panels_pane'] = array(
|
||||
'variables' => array('output' => array(), 'pane' => array(), 'display' => array()),
|
||||
'variables' => array('content' => array(), 'pane' => array(), 'display' => array()),
|
||||
'path' => drupal_get_path('module', 'panels') . '/templates',
|
||||
'template' => 'panels-pane',
|
||||
);
|
||||
@@ -76,6 +91,20 @@ function panels_theme() {
|
||||
'template' => 'panels-dashboard-block',
|
||||
);
|
||||
|
||||
$theme['panels_add_content_modal'] = array(
|
||||
'variables' => array('renderer' => NULL, 'categories' => array(), 'region' => NULL, 'category' => NULL, 'column_count' => 2),
|
||||
'path' => drupal_get_path('module', 'panels') . '/templates',
|
||||
'file' => '../includes/add-content.inc',
|
||||
'template' => 'panels-add-content-modal',
|
||||
);
|
||||
|
||||
$theme['panels_add_content_link'] = array(
|
||||
'variables' => array('renderer' => NULL, 'region' => NULL, 'content_type' => NULL),
|
||||
'path' => drupal_get_path('module', 'panels') . '/templates',
|
||||
'file' => '../includes/add-content.inc',
|
||||
'template' => 'panels-add-content-link',
|
||||
);
|
||||
|
||||
// We don't need layout and style themes in maintenance mode.
|
||||
// Disabling this: See http://drupal.org/node/979912 for information.
|
||||
// if (defined('MAINTENANCE_MODE')) {
|
||||
@@ -150,7 +179,8 @@ function panels_menu() {
|
||||
$items['panels/ajax'] = array(
|
||||
'access arguments' => array('access content'),
|
||||
'page callback' => 'panels_ajax_router',
|
||||
'theme callback' => 'panels_ajax_theme_callback',
|
||||
'theme callback' => 'ajax_base_page_theme',
|
||||
'delivery callback' => 'ajax_deliver',
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
|
||||
@@ -243,7 +273,6 @@ function panels_init() {
|
||||
}
|
||||
|
||||
ctools_add_css('panels', 'panels');
|
||||
ctools_add_js('panels', 'panels');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +284,7 @@ function panels_permission() {
|
||||
return array(
|
||||
'use panels dashboard' => array(
|
||||
'title' => t("Use Panels Dashboard"),
|
||||
'description' => t("Allows a user to access the !link.", array('!link' => l('Panels Dashboard', 'admin/structure/panels'))),
|
||||
'description' => t('Allows a user to access the <a href="@url">Panels Dashboard</a>.', array('@url' => url('admin/structure/panels'))),
|
||||
),
|
||||
'view pane admin links' => array( // @todo
|
||||
'title' => t("View administrative links on Panel panes"),
|
||||
@@ -269,6 +298,15 @@ function panels_permission() {
|
||||
'title' => t("Use the Panels In-Place Editor"),
|
||||
'description' => t("Allows a user to utilize Panels' In-Place Editor."),
|
||||
),
|
||||
'change layouts in place editing' => array(
|
||||
'title' => t("Change layouts with the Panels In-Place Editor"),
|
||||
'description' => t("Allows a user to change layouts with the IPE."),
|
||||
),
|
||||
'bypass access in place editing' => array(
|
||||
'title' => t("Bypass access checks when using Panels In-Place Editor"),
|
||||
'description' => t("Allows using IPE even if user does not have additional permissions granted by other modules."),
|
||||
'restrict access' => TRUE,
|
||||
),
|
||||
'administer advanced pane settings' => array(
|
||||
'title' => t("Configure advanced settings on Panel panes"),
|
||||
'description' => t(""),
|
||||
@@ -279,8 +317,20 @@ function panels_permission() {
|
||||
),
|
||||
'administer panels styles' => array(
|
||||
'title' => t("Administer Panels styles"),
|
||||
'description' => t("DEPRECATED: Modules using this permission should use specific style permissions. See Issue #2329419 for more info."),
|
||||
),
|
||||
'administer panels display styles' => array(
|
||||
'title' => t("Administer Panels display styles"),
|
||||
'description' => t("Allows a user to administer the styles of Panel displays."),
|
||||
),
|
||||
'administer panels pane styles' => array(
|
||||
'title' => t("Administer Panels pane styles"),
|
||||
'description' => t("Allows a user to administer the styles of Panel panes."),
|
||||
),
|
||||
'administer panels region styles' => array(
|
||||
'title' => t("Administer Panels region styles"),
|
||||
'description' => t("Allows a user to administer the styles of Panel regions."),
|
||||
),
|
||||
'use panels caching features' => array(
|
||||
'title' => t("Configure caching settings on Panels"),
|
||||
'description' => t("Allows a user to configure caching on Panels displays and panes."),
|
||||
@@ -289,19 +339,21 @@ 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.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_flush_caches().
|
||||
*
|
||||
* We implement this so that we can be sure our legacy rendering state setting
|
||||
* in $conf is updated whenever caches are cleared.
|
||||
* Implements hook_flush_caches().
|
||||
*/
|
||||
//function panels_flush_caches() {
|
||||
// $legacy = panels_get_legacy_state();
|
||||
// $legacy->determineStatus();
|
||||
//}
|
||||
function panels_flush_caches() {
|
||||
if (db_table_exists('cache_panels')) {
|
||||
return array('cache_panels');
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CTools hook implementations
|
||||
@@ -358,6 +410,7 @@ function panels_ctools_plugin_type() {
|
||||
'display_renderers' => array(
|
||||
'classes' => array('renderer'),
|
||||
),
|
||||
'panels_storage' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -612,7 +665,6 @@ function panels_edit_layout($display, $finish, $destination = NULL, $allowed_lay
|
||||
|
||||
/**
|
||||
* Forms the basis of a panel display
|
||||
*
|
||||
*/
|
||||
class panels_display {
|
||||
var $args = array();
|
||||
@@ -633,8 +685,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;
|
||||
@@ -648,23 +702,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.
|
||||
*
|
||||
@@ -735,6 +776,55 @@ class panels_display {
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given user can perform the requested operation.
|
||||
*
|
||||
* @param string $op
|
||||
* An operation like: create, read, update, or delete.
|
||||
* @param object $account
|
||||
* (optional) The account to check access for.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if access is granted; otherwise FALSE.
|
||||
*/
|
||||
function access($op, $account = NULL) {
|
||||
global $user;
|
||||
|
||||
if (!$account) {
|
||||
$account = $user;
|
||||
}
|
||||
|
||||
// Even administrators need to go through the access system. However, to
|
||||
// support legacy plugins, user 1 gets full access no matter what.
|
||||
if ($account->uid == 1) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!in_array($op, array('create', 'read', 'update', 'delete', 'change layout'))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (empty($this->storage_type) || empty($this->storage_id)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($this->storage_type == 'unknown') {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$storage_plugin = panels_get_panels_storage_plugin($this->storage_type);
|
||||
if (!$storage_plugin) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$access_callback = panels_plugin_get_function('panels_storage', $storage_plugin, 'access callback');
|
||||
if (!$access_callback) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return $access_callback($this->storage_type, $this->storage_id, $op, $account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -763,10 +853,12 @@ function panels_new_pane($type, $subtype, $set_defaults = FALSE) {
|
||||
$pane->type = $type;
|
||||
$pane->subtype = $subtype;
|
||||
if ($set_defaults) {
|
||||
ctools_include('content');
|
||||
$content_type = ctools_get_content_type($type);
|
||||
$content_subtype = ctools_content_get_subtype($content_type, $subtype);
|
||||
$pane->configuration = ctools_content_get_defaults($content_type, $content_subtype);
|
||||
}
|
||||
drupal_alter('panels_new_pane', $pane);
|
||||
|
||||
return $pane;
|
||||
}
|
||||
@@ -847,10 +939,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
|
||||
@@ -860,6 +955,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();
|
||||
@@ -890,11 +988,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,
|
||||
@@ -925,6 +1038,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();
|
||||
}
|
||||
|
||||
@@ -958,6 +1073,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();
|
||||
}
|
||||
@@ -967,9 +1083,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.
|
||||
*
|
||||
@@ -991,10 +1109,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";
|
||||
@@ -1004,17 +1124,22 @@ 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;
|
||||
}
|
||||
$pane->pid = $pid;
|
||||
$output .= ctools_export_object('panels_pane', $pane, $prefix . ' ');
|
||||
$output .= "$prefix " . '$display->content[\'' . $pane->pid . '\'] = $pane' . ";\n";
|
||||
$output .= ctools_export_object('panels_pane', $pane, $prefix);
|
||||
$output .= $prefix . '$display->content[\'' . $pane->pid . '\'] = $pane' . ";\n";
|
||||
if (!isset($region_counters[$pane->panel])) {
|
||||
$region_counters[$pane->panel] = 0;
|
||||
}
|
||||
$output .= "$prefix " . '$display->panels[\'' . $pane->panel . '\'][' . $region_counters[$pane->panel]++ .'] = \'' . $pane->pid . "';\n";
|
||||
$output .= $prefix . '$display->panels[\'' . $pane->panel . '\'][' . $region_counters[$pane->panel]++ .'] = \'' . $pane->pid . "';\n";
|
||||
}
|
||||
}
|
||||
$output .= $prefix . '$display->hide_title = ';
|
||||
@@ -1050,6 +1175,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;
|
||||
}
|
||||
@@ -1066,10 +1194,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
|
||||
@@ -1108,8 +1233,9 @@ function theme_panels_layout_icon($vars) {
|
||||
function theme_panels_layout_link($vars) {
|
||||
$title = $vars['title'];
|
||||
$image = $vars['image'];
|
||||
$class = $vars['class'];
|
||||
|
||||
$output = '<div class="layout-link">';
|
||||
$output = '<div class="' . implode(' ', $class) . '">';
|
||||
$output .= $vars['image'];
|
||||
$output .= '<div>' . $vars['title'] . '</div>';
|
||||
$output .= '</div>';
|
||||
@@ -1120,16 +1246,23 @@ function theme_panels_layout_link($vars) {
|
||||
* Print the layout link. Sends out to a theme function.
|
||||
* @layout
|
||||
*/
|
||||
function panels_print_layout_link($id, $layout, $link, $options = array()) {
|
||||
function panels_print_layout_link($id, $layout, $link, $options = array(), $current_layout = FALSE) {
|
||||
if (isset($options['query']['q'])) {
|
||||
unset($options['query']['q']);
|
||||
}
|
||||
|
||||
// Setup classes for layout link, including current-layout information
|
||||
$class = array('layout-link');
|
||||
if ($current_layout == $id) {
|
||||
$options['attributes']['class'][] = 'current-layout-link';
|
||||
$class[] = 'current-layout';
|
||||
}
|
||||
|
||||
ctools_add_css('panels_admin', 'panels');
|
||||
$file = $layout['path'] . '/' . $layout['icon'];
|
||||
$image = l(theme('image', array('path' => $file)), $link, array('html' => true) + $options);
|
||||
$title = l($layout['title'], $link, $options);
|
||||
return theme('panels_layout_link', array('title' => $title, 'image' => $image));
|
||||
return theme('panels_layout_link', array('title' => $title, 'image' => $image, 'class' => $class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1176,7 +1309,7 @@ function template_preprocess_panels_pane(&$vars) {
|
||||
$vars['classes_array'] = array();
|
||||
$vars['admin_links'] = '';
|
||||
|
||||
if (user_access('access contextual links')) {
|
||||
if (module_exists('contextual') && user_access('access contextual links')) {
|
||||
$links = array();
|
||||
// These are specified by the content.
|
||||
if (!empty($content->admin_links)) {
|
||||
@@ -1185,15 +1318,22 @@ function template_preprocess_panels_pane(&$vars) {
|
||||
|
||||
// Take any that may have been in the render array we were given and
|
||||
// move them up so they appear outside the pane properly.
|
||||
if (is_array($content->content) && isset($content->content['#contextual_links']) && module_exists('contextual')) {
|
||||
if (is_array($content->content) && isset($content->content['#contextual_links'])) {
|
||||
$element = array(
|
||||
'#type' => 'contextual_links',
|
||||
'#contextual_links' => $content->content['#contextual_links'],
|
||||
);
|
||||
unset($content->content['#contextual_links']);
|
||||
|
||||
// Add content to $element array
|
||||
if (is_array($content->content)) {
|
||||
$element['#element'] = $content->content;
|
||||
}
|
||||
|
||||
$element = contextual_pre_render_links($element);
|
||||
$links += $element['#links'];
|
||||
if(!empty($element['#links'])) {
|
||||
$links += $element['#links'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($links) {
|
||||
@@ -1243,12 +1383,13 @@ 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 . $content->type . $delimiter . $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 : '';
|
||||
|
||||
$vars['title'] = !empty($content->title) ? $content->title : '';
|
||||
$vars['title_heading'] = !empty($content->title_heading) ? $content->title_heading : variable_get('override_title_heading', 'h2');
|
||||
$vars['title_attributes_array']['class'][] = 'pane-title';
|
||||
|
||||
$vars['feeds'] = !empty($content->feeds) ? implode(' ', $content->feeds) : '';
|
||||
@@ -1266,18 +1407,6 @@ function template_preprocess_panels_pane(&$vars) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu theme callback.
|
||||
*
|
||||
* This simply ensures that Panels ajax calls are rendered in the same
|
||||
* theme as the original page to prevent .css file confusion.
|
||||
*/
|
||||
function panels_ajax_theme_callback() {
|
||||
if (!empty($_POST['ajax_page_state']['theme'])) {
|
||||
return $_POST['ajax_page_state']['theme'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Route Panels' AJAX calls to the correct object.
|
||||
*
|
||||
@@ -1299,9 +1428,6 @@ function panels_ajax_router() {
|
||||
if (count($args) < 3) {
|
||||
return MENU_NOT_FOUND;
|
||||
}
|
||||
if (!empty($_POST['ajax_page_state']['theme'])) {
|
||||
$GLOBALS['custom_theme'] = $_POST['ajax_page_state']['theme'];
|
||||
}
|
||||
|
||||
ctools_include('display-edit', 'panels');
|
||||
ctools_include('plugins', 'panels');
|
||||
@@ -1339,13 +1465,22 @@ function panels_ajax_router() {
|
||||
ctools_include('cleanstring');
|
||||
$renderer->clean_key = ctools_cleanstring($cache_key);
|
||||
|
||||
$op = $renderer->get_panels_storage_op_for_ajax($method);
|
||||
if (!$cache->display->access($op)) {
|
||||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
$output = call_user_func_array(array($renderer, $method), $args);
|
||||
|
||||
if (empty($output) && !empty($renderer->commands)) {
|
||||
print ajax_render($renderer->commands);
|
||||
ajax_footer();
|
||||
return array(
|
||||
'#type' => 'ajax',
|
||||
'#commands' => $renderer->commands,
|
||||
);
|
||||
}
|
||||
else {
|
||||
return $output;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -1504,7 +1639,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');
|
||||
@@ -1513,7 +1648,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];
|
||||
@@ -1527,8 +1662,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;
|
||||
@@ -1541,7 +1688,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) {
|
||||
@@ -1634,6 +1781,32 @@ function panels_page_wizard_panels_cache_set($key, $cache) {
|
||||
page_manager_set_wizard_cache($wizard_cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_default_page_manager_handlers_alter().
|
||||
*
|
||||
* If a default Panels display has no storage type, set it.
|
||||
*/
|
||||
function panels_default_page_manager_handlers_alter(&$handlers) {
|
||||
foreach ($handlers as &$handler) {
|
||||
if ($handler->handler == 'panel_context') {
|
||||
$display =& $handler->conf['display'];
|
||||
if (empty($display->storage_type)) {
|
||||
$display->storage_type = 'page_manager';
|
||||
$display->storage_id = $handler->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_default_page_manager_pages_alter().
|
||||
*/
|
||||
function panels_default_page_manager_pages_alter(&$pages) {
|
||||
foreach ($pages as &$page) {
|
||||
panels_default_page_manager_handlers_alter($page->default_handlers);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// General utility functions
|
||||
|
||||
@@ -1697,6 +1870,105 @@ function panels_print_layout($layout, $content, $meta = 'standard') {
|
||||
return $renderer->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter callback for array_filter to remove builders from a list of layouts.
|
||||
*/
|
||||
function _panels_builder_filter($layout) {
|
||||
return empty($layout['builder']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_get_pane_links_alter().
|
||||
*
|
||||
* add links to the Panels pane dropdown menu.
|
||||
*/
|
||||
function panels_get_pane_links_alter(&$links, $pane, $content_type) {
|
||||
if ($pane->type === "block"){
|
||||
$prefixed_name = $pane->subtype;
|
||||
|
||||
// breakup the subtype string into parts.
|
||||
$exploded_subtype = explode('-', $pane->subtype);
|
||||
|
||||
// get the first part of the string.
|
||||
$subtype_prefix = $exploded_subtype[0];
|
||||
|
||||
// get the first part of the string and add a hyphen.
|
||||
$subtype_prefix_hyphen = $exploded_subtype[0] . '-';
|
||||
|
||||
// remove the prefix block- to get the name.
|
||||
$name_of_block = ltrim( $prefixed_name, $subtype_prefix_hyphen);
|
||||
|
||||
// check for user added menus created at /admin/structure/menu/add
|
||||
// menus of that type have a subtype that is prefixed with menu-menu-
|
||||
if (substr($prefixed_name, 0, 10) === "menu-menu-"){
|
||||
// remove the first prefix menu- from menu-menu- to get the name.
|
||||
$name_of_block = substr($prefixed_name, 5);
|
||||
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit block'),
|
||||
'href' => url('admin/structure/block/manage/' . $subtype_prefix . '/' . $name_of_block . '/configure', array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit menu links'),
|
||||
'href' => url('admin/structure/menu/manage/' . $name_of_block, array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
}
|
||||
|
||||
// check for module provided menu blocks like Devels or Features
|
||||
// menus of that type have a subtype that is prefixed with menu-
|
||||
elseif(substr($prefixed_name, 0, 5) === "menu-"){
|
||||
// remove the first prefix menu- to get the name.
|
||||
$name_of_block = substr($prefixed_name, 5);
|
||||
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit block'),
|
||||
'href' => url('admin/structure/block/manage/' . $subtype_prefix . '/' . $name_of_block . '/configure', array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit menu links'),
|
||||
'href' => url('admin/structure/menu/manage/' . $name_of_block, array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
}
|
||||
|
||||
// check for system blocks with menu links
|
||||
elseif(substr($prefixed_name, 0, 7) === "system-") {
|
||||
// remove the first prefix system- to get the name
|
||||
$name_of_block = substr($prefixed_name, 7);
|
||||
|
||||
$names_of_system_menus = menu_list_system_menus();
|
||||
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit block'),
|
||||
'href' => url('admin/structure/block/manage/' . $subtype_prefix . '/' . $name_of_block . '/configure', array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
|
||||
if (array_key_exists($name_of_block, $names_of_system_menus)){
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit menu links'),
|
||||
'href' => url('admin/structure/menu/manage/' . $name_of_block, array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// for all other blocks without menus
|
||||
else{
|
||||
$links['top'][] = array(
|
||||
'title' => t('Edit block'),
|
||||
'href' => url('admin/structure/block/manage/' . $subtype_prefix . '/' . $name_of_block . '/configure', array('absolute' => TRUE)),
|
||||
'attributes' => array('target' => array('_blank')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Deprecated functions
|
||||
//
|
||||
@@ -1709,3 +1981,21 @@ function panels_get_path($file, $base_path = FALSE, $module = 'panels') {
|
||||
$output = $base_path ? base_path() : '';
|
||||
return $output . drupal_get_path('module', $module) . '/' . $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default sidebar related body classes and provide own css classes
|
||||
*/
|
||||
function panels_preprocess_html(&$vars) {
|
||||
$panel_body_css = &drupal_static('panel_body_css');
|
||||
if (!empty($panel_body_css['body_classes_to_remove'])) {
|
||||
$classes_to_remove = array_filter(explode(' ', $panel_body_css['body_classes_to_remove']), 'strlen');
|
||||
foreach ($vars['classes_array'] as $key => $css_class) {
|
||||
if (in_array($css_class, $classes_to_remove)) {
|
||||
unset($vars['classes_array'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($panel_body_css['body_classes_to_add'])) {
|
||||
$vars['classes_array'][] = check_plain($panel_body_css['body_classes_to_add']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#panels-ipe-save,
|
||||
#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;
|
||||
}
|
||||
@@ -1,19 +1,33 @@
|
||||
body.panels-ipe {
|
||||
margin-bottom: 60px !important;
|
||||
}
|
||||
|
||||
/* Hide the IPE toolbar on print output. */
|
||||
@media print {
|
||||
#panels-ipe-control-container {
|
||||
display: none !important;
|
||||
}
|
||||
body.panels-ipe {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide the control container when the overlay is open. */
|
||||
html.overlay-open #panels-ipe-control-container {
|
||||
display: none !important;
|
||||
}
|
||||
html.overlay-open body.panels-ipe {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper {
|
||||
border-bottom: #898AAB solid 2px;
|
||||
border-bottom: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.panels-ipe-editing div.panels-ipe-portlet-wrapper {
|
||||
margin-top: 1em;
|
||||
border: #898AAB solid 2px;
|
||||
-moz-border-radius-bottomleft:8px;
|
||||
-moz-border-radius-bottomright:8px;
|
||||
-moz-border-radius-topleft:2px;
|
||||
-moz-border-radius-topright:2px;
|
||||
|
||||
-webkit-border-radius-bottomleft:8px;
|
||||
-webkit-border-radius-bottomright:8px;
|
||||
-webkit-border-radius-topleft:2px;
|
||||
-webkit-border-radius-topright:2px;
|
||||
border: 1px solid #CCC;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Hide empty panes when not editing them. */
|
||||
@@ -25,9 +39,12 @@ div.panels-ipe-handlebar-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.panels-ipe-editing div.panels-ipe-portlet-wrapper:hover {
|
||||
border: #FF000A solid 2px;
|
||||
border: 1px dashed #CCC;
|
||||
}
|
||||
|
||||
.panels-ipe-editing .panels-ipe-sort-container {
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.panels-ipe-editing .panels-ipe-sort-container .ui-sortable-helper {
|
||||
@@ -39,10 +56,13 @@ div.panels-ipe-handlebar-wrapper {
|
||||
}
|
||||
|
||||
.panels-ipe-editing .panels-ipe-sort-container .ui-sortable-placeholder {
|
||||
border: 2px dashed #999;
|
||||
background-color: #FFFF99;
|
||||
margin: 1em 0;
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border: 1px dotted red;
|
||||
background-color: white;
|
||||
-khtml-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper ul {
|
||||
@@ -53,42 +73,57 @@ div.panels-ipe-handlebar-wrapper ul {
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li {
|
||||
background: none repeat scroll 0 0 transparent;
|
||||
list-style: none outside none;
|
||||
margin: 0;
|
||||
background: none;
|
||||
list-style-type: none;
|
||||
list-style-image: none;
|
||||
margin: 0 .5em 0 0;
|
||||
padding: 0;
|
||||
float: left;
|
||||
font: 12px/170% Verdana,sans-serif !important;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li {
|
||||
border-top: 1px solid #CCC;
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li.first {
|
||||
border-left: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.panels-ipe-draghandle {
|
||||
background: #898AAB url(../images/dragger.png) top right no-repeat;
|
||||
cursor: move;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
div.panels-ipe-draghandle,
|
||||
div.panels-ipe-nodraghandle {
|
||||
background: #898AAB;
|
||||
height: 24px;
|
||||
background: #E9E9E9;
|
||||
background-image: linear-gradient(bottom, #D5D5D5 0%, #FCFCFC 100%);
|
||||
background-image: -o-linear-gradient(bottom, #D5D5D5 0%, #FCFCFC 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #D5D5D5 0%, #FCFCFC 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #D5D5D5 0%, #FCFCFC 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #D5D5D5 0%, #FCFCFC 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #D5D5D5),
|
||||
color-stop(1, #FCFCFC)
|
||||
);
|
||||
|
||||
padding: 8px 7px;
|
||||
}
|
||||
|
||||
div.panels-ipe-draghandle span.panels-ipe-draghandle-icon {
|
||||
display: block;
|
||||
float: right;
|
||||
cursor: move;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
padding: 0 !important; /* override button defaults */
|
||||
}
|
||||
|
||||
span.panels-ipe-draghandle-icon-inner {
|
||||
display: block;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: url(../images/icon-draggable.png) no-repeat 3px 3px;
|
||||
}
|
||||
|
||||
div.panels-ipe-placeholder {
|
||||
border: 1px solid black;
|
||||
border: 2px dashed #999;
|
||||
padding: .5em;
|
||||
position: relative;
|
||||
margin-top: .5em;
|
||||
background-color: #f6f6f6;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font: 12px/170% Verdana,sans-serif !important;
|
||||
background-color: #ECFAFF;
|
||||
color: #999;
|
||||
font: 15px/1.3em "Open Sans", "Lucida Grande", Tahoma, Verdana, sans-serif;
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
text-align: left;
|
||||
@@ -96,7 +131,10 @@ div.panels-ipe-placeholder {
|
||||
}
|
||||
|
||||
div.panels-ipe-placeholder h3 {
|
||||
font-weight: bold;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
width: 75px; /* In order to prevent the region title from running into the button, set a width. Initital width only--this will be changed by jQuery */
|
||||
margin: 1.154em 0;
|
||||
}
|
||||
|
||||
/* Hide editor-state-on elements initially */
|
||||
@@ -105,7 +143,7 @@ div.panels-ipe-placeholder h3 {
|
||||
}
|
||||
|
||||
.panels-ipe-editing .panels-ipe-on {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Show editor-state-off elements initially */
|
||||
@@ -113,27 +151,139 @@ div.panels-ipe-placeholder h3 {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li a,
|
||||
div.panels-ipe-dragtitle span,
|
||||
div.panels-ipe-newblock a {
|
||||
background-color: #f6f6f6;
|
||||
color: blue;
|
||||
display: block;
|
||||
padding: 0.1em 0.5em;
|
||||
font: 12px/170% Verdana,sans-serif !important;
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
div.panels-ipe-newblock {
|
||||
-webkit-box-shadow: 0px 0 5px 5px #ECFAFF;
|
||||
-moz-box-shadow: 0px 0 5px 5px #ECFAFF;
|
||||
box-shadow: 0px 0 5px 5px #ECFAFF;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
margin-top: -18px; /* some initial guesses to help center the add button
|
||||
panels_ipe.js will evaluate the width and get this pixel-perfect */
|
||||
margin-left: -30px;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
div.panels-ipe-newblock a {
|
||||
display: inline;
|
||||
border: 1px solid #CCC;
|
||||
color: blue;
|
||||
div.panels-ipe-newblock li {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li a,
|
||||
div.panels-ipe-dragtitle span,
|
||||
div.panels-ipe-newblock a,
|
||||
span.panels-ipe-draghandle-icon {
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
padding: 0 8px 1px;
|
||||
font: bold 12px/32px 'Open Sans', 'Lucida Sans', 'Lucida Grande', verdana sans-serif;
|
||||
text-decoration: none;
|
||||
height: 33px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
-moz-border-radius: 3px;
|
||||
-khtml-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
|
||||
background: #FAFAFA;
|
||||
background-image: linear-gradient(bottom, #E9EAEC 0%, #FAFAFA 100%);
|
||||
background-image: -o-linear-gradient(bottom, #E9EAEC 0%, #FAFAFA 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #E9EAEC 0%, #FAFAFA 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #E9EAEC 0%, #FAFAFA 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #E9EAEC 0%, #FAFAFA 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #E9EAEC),
|
||||
color-stop(1, #FAFAFA)
|
||||
);
|
||||
|
||||
-webkit-box-shadow: 0px 3px 3px 0px #d2d2d2;
|
||||
-moz-box-shadow: 0px 3px 3px 0px #d2d2d2;
|
||||
box-shadow: 0px 3px 3px 0px #d2d2d2;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li a span,
|
||||
div.panels-ipe-newblock a span {
|
||||
display: block;
|
||||
height: 32px;
|
||||
width: 18px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
text-align: left;
|
||||
text-indent: -9999em;
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li.edit a span {
|
||||
background-image: url(../images/icon-settings.png);
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li.style a span,
|
||||
div.panels-ipe-newblock a.style span {
|
||||
background-image: url(../images/icon-style.png);
|
||||
}
|
||||
|
||||
div.panels-ipe-newblock a.style {
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
div.panels-ipe-newblock a.add span {
|
||||
background-image: url(../images/icon-add.png);
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li.delete a span {
|
||||
background-image: url(../images/icon-delete.png);
|
||||
}
|
||||
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li a:hover,
|
||||
div.panels-ipe-dragtitle span:hover,
|
||||
div.panels-ipe-newblock a:hover,
|
||||
span.panels-ipe-draghandle-icon:hover,
|
||||
div.panels-ipe-handlebar-wrapper li a:focus,
|
||||
div.panels-ipe-newblock a:focus {
|
||||
background: #E6E6E6;
|
||||
background-image: linear-gradient(bottom, #C5C5C5 0%, #FAFAFA 100%);
|
||||
background-image: -o-linear-gradient(bottom, #C5C5C5 0%, #FAFAFA 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #C5C5C5 0%, #FAFAFA 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #C5C5C5 0%, #FAFAFA 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #C5C5C5 0%, #FAFAFA 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #C5C5C5),
|
||||
color-stop(1, #FAFAFA)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-handlebar-wrapper li a:active,
|
||||
div.panels-ipe-dragtitle span:active,
|
||||
div.panels-ipe-newblock a:active,
|
||||
span.panels-ipe-draghandle-icon:active {
|
||||
outline: none;
|
||||
background-image: linear-gradient(bottom, #FFFFFF 0%, #E9EAEC 100%);
|
||||
background-image: -o-linear-gradient(bottom, #FFFFFF 0%, #E9EAEC 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #FFFFFF 0%, #E9EAEC 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #FFFFFF 0%, #E9EAEC 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #FFFFFF 0%, #E9EAEC 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #FFFFFF),
|
||||
color-stop(1, #E9EAEC)
|
||||
);
|
||||
|
||||
-webkit-box-shadow: 0px 0px 0px 0px #fff;
|
||||
-moz-box-shadow: 0px 0px 0px 0px #fff;
|
||||
box-shadow: 0px 0px 0px 0px #fff;
|
||||
}
|
||||
|
||||
.panels-ipe-editing .panels-ipe-portlet-content {
|
||||
margin-bottom: 10px;
|
||||
border: transparent dotted 1px;
|
||||
margin: 10px 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -158,63 +308,270 @@ div.panels-ipe-draghandle {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* counteract panels_dnd.css - temporary */
|
||||
div.panels-ipe-display-container .panel-pane .pane-title {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/** ============================================================================
|
||||
* Controller form markup
|
||||
*/
|
||||
|
||||
div#panels-ipe-control-container {
|
||||
z-index: 100;
|
||||
z-index: 99999;
|
||||
position: fixed;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
display: none;
|
||||
background-color: #000;
|
||||
padding: 0.5em 1em;
|
||||
/*
|
||||
min-width: 9.5em;
|
||||
max-width: 14.5em;
|
||||
min-height: 2em;
|
||||
max-height: 2.5em;
|
||||
*/
|
||||
padding: 0.5em 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
-moz-border-radius-topleft:5px;
|
||||
-moz-border-radius-topright:5px;
|
||||
-moz-box-shadow: #333 0px 1px 0px;
|
||||
-webkit-border-top-left-radius:5px;
|
||||
-webkit-border-top-right-radius:5px;
|
||||
-webkit-box-shadow: #333 0px 1px 0px;
|
||||
-moz-box-shadow: 0 3px 20px #000;
|
||||
-webkit-box-shadow: 0 3px 20px #000;
|
||||
box-shadow: 0 3px 20px #000;
|
||||
}
|
||||
|
||||
div#panels-ipe-control-container .ajax-progress-throbber {
|
||||
.ipe-throbber {
|
||||
background-color: #232323;
|
||||
background-image: url("../images/loading-small.gif");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
height: 24px;
|
||||
opacity: .9;
|
||||
padding: 4px;
|
||||
width: 24px;
|
||||
/* Can't do center:50% middle: 50%, so approximate it for a typical window size. */
|
||||
left: 49%;
|
||||
position: fixed;
|
||||
top: 48.5%;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* Hide the drupal system throbber image */
|
||||
.ipe-throbber .throbber {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton {
|
||||
div.panels-ipe-pseudobutton-container,
|
||||
div.panels-ipe-control .form-submit {
|
||||
cursor: pointer;
|
||||
background-color: #333;
|
||||
font:normal 11px/15px "Lucida Grande",Tahoma,Verdana,sans-serif;
|
||||
color: #FFF;
|
||||
-moz-border-radius:5px;
|
||||
-moz-box-shadow: #333 0px 1px 0px;
|
||||
-webkit-border-radius:5px;
|
||||
-webkit-box-shadow: #333 0px 1px 0px;
|
||||
padding: 0.3em 0.8em;
|
||||
float: left;
|
||||
background: #666666;
|
||||
background-image: linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: -o-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #383838),
|
||||
color-stop(1, #666666)
|
||||
);
|
||||
border: 0;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
color: #CCC;
|
||||
display: inline-block;
|
||||
font: bold 12px/33px "Open Sans", "Lucida Grande", Tahoma, Verdana, sans-serif;
|
||||
height: 33px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
div.panels-ipe-control .form-submit {
|
||||
float: left;
|
||||
margin: 0.3em 0.5em;
|
||||
padding: 0 0.8em 2px 34px;
|
||||
}
|
||||
|
||||
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:focus, div.panels-ipe-control input.panels-ipe-cancel:focus,
|
||||
div.panels-ipe-control input.panels-ipe-save:active, div.panels-ipe-control input.panels-ipe-cancel:active {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container a {
|
||||
height: 33px;
|
||||
padding: 0 0.8em;
|
||||
display: inline-block;
|
||||
color: #CCC;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.panels-ipe-control .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%);
|
||||
background-image: url(../images/icon-save.png), -moz-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: url(../images/icon-save.png), -webkit-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: url(../images/icon-save.png), -ms-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
|
||||
background-image: url(../images/icon-save.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #383838),
|
||||
color-stop(1, #666666)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-control .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%);
|
||||
background-image: url(../images/icon-close.png), -moz-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: url(../images/icon-close.png), -webkit-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
background-image: url(../images/icon-close.png), -ms-linear-gradient(bottom, #383838 0%, #666666 100%);
|
||||
|
||||
background-image: url(../images/icon-close.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #383838),
|
||||
color-stop(1, #666666)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container:hover,
|
||||
div.panels-ipe-control .form-submit:hover,
|
||||
div.panels-ipe-pseudobutton-container:focus,
|
||||
div.panels-ipe-control .form-submit:focus {
|
||||
background: #999999;
|
||||
background-image: linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: -o-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #3D3D3D),
|
||||
color-stop(1, #999999)
|
||||
);
|
||||
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container a:hover,
|
||||
div.panels-ipe-pseudobutton-container a:focus {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
div.panels-ipe-control .panels-ipe-cancel:hover,
|
||||
div.panels-ipe-control .panels-ipe-cancel:focus {
|
||||
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%);
|
||||
background-image: url(../images/icon-close.png), -webkit-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: url(../images/icon-close.png), -ms-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
|
||||
background-image: url(../images/icon-close.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #3D3D3D),
|
||||
color-stop(1, #999999)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-control .panels-ipe-save:hover,
|
||||
div.panels-ipe-control .panels-ipe-save:focus {
|
||||
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%);
|
||||
background-image: url(../images/icon-save.png), -webkit-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
background-image: url(../images/icon-save.png), -ms-linear-gradient(bottom, #3D3D3D 0%, #999999 100%);
|
||||
|
||||
background-image: url(../images/icon-save.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #3D3D3D),
|
||||
color-stop(1, #999999)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container:active,
|
||||
div.panels-ipe-control .form-submit:active {
|
||||
background: #333;
|
||||
background-image: linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: -o-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #616161),
|
||||
color-stop(1, #333333)
|
||||
);
|
||||
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container a:active {
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
div.panels-ipe-control .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%);
|
||||
background-image: url(../images/icon-close.png), -webkit-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: url(../images/icon-close.png), -ms-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
|
||||
background-image: url(../images/icon-close.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #616161),
|
||||
color-stop(1, #333333)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-control .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%);
|
||||
background-image: url(../images/icon-save.png), -webkit-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
background-image: url(../images/icon-save.png), -ms-linear-gradient(bottom, #616161 0%, #333333 100%);
|
||||
|
||||
background-image: url(../images/icon-save.png), -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, #616161),
|
||||
color-stop(1, #333333)
|
||||
);
|
||||
}
|
||||
|
||||
div.panels-ipe-control .panels-ipe-save, div.panels-ipe-control .panels-ipe-cancel,
|
||||
div.panels-ipe-control .panels-ipe-save:hover, div.panels-ipe-control .panels-ipe-cancel:hover,
|
||||
div.panels-ipe-control .panels-ipe-save:active, div.panels-ipe-control .panels-ipe-cancel:active {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container a.panels-ipe-startedit {
|
||||
padding-left: 34px;
|
||||
background: url(../images/icon-configure.png) no-repeat 10px 9px;
|
||||
}
|
||||
|
||||
div.panels-ipe-pseudobutton-container a.panels-ipe-change-layout {
|
||||
padding-left: 34px;
|
||||
background: url(../images/icon-change-layout.png) no-repeat 10px 9px;
|
||||
}
|
||||
|
||||
div.panels-ipe-button-container {
|
||||
margin: 0.3em 0.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form#panels-ipe-edit-control-form {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.panels-ipe-dragbar-admin-title{
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 946 B After Width: | Height: | Size: 946 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 319 B |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 546 B |
|
After Width: | Height: | Size: 658 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 247 B |
|
After Width: | Height: | Size: 567 B |
|
After Width: | Height: | Size: 488 B |
|
After Width: | Height: | Size: 2.1 KiB |
@@ -2,12 +2,7 @@
|
||||
// Ensure the $ alias is owned by jQuery.
|
||||
(function($) {
|
||||
|
||||
// randomly lock a pane.
|
||||
// @debug only
|
||||
Drupal.settings.Panels = Drupal.settings.Panels || {};
|
||||
Drupal.settings.Panels.RegionLock = {
|
||||
10: { 'top': false, 'left': true, 'middle': true }
|
||||
}
|
||||
|
||||
Drupal.PanelsIPE = {
|
||||
editors: {},
|
||||
@@ -15,9 +10,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');
|
||||
}
|
||||
@@ -26,16 +23,36 @@ Drupal.PanelsIPE = {
|
||||
}
|
||||
}
|
||||
|
||||
// A ready function should be sufficient for this, at least for now
|
||||
$(function() {
|
||||
$.each(Drupal.settings.PanelsIPECacheKeys, function() {
|
||||
Drupal.PanelsIPE.editors[this] = new DrupalPanelsIPE(this, Drupal.settings.PanelsIPESettings[this]);
|
||||
Drupal.PanelsIPE.editors[this].showContainer();
|
||||
});
|
||||
});
|
||||
|
||||
Drupal.behaviors.PanelsIPE = {
|
||||
attach: function(context) {
|
||||
// Remove any old editors.
|
||||
for (var i in Drupal.PanelsIPE.editors) {
|
||||
if (Drupal.settings.PanelsIPECacheKeys.indexOf(i) === -1) {
|
||||
// Clean-up a little bit and remove it.
|
||||
Drupal.PanelsIPE.editors[i].editing = false;
|
||||
Drupal.PanelsIPE.editors[i].changed = false;
|
||||
delete Drupal.PanelsIPE.editors[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize new editors.
|
||||
for (var i in Drupal.settings.PanelsIPECacheKeys) {
|
||||
var key = Drupal.settings.PanelsIPECacheKeys[i];
|
||||
$('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();
|
||||
});
|
||||
}
|
||||
$('.panels-ipe-hide-bar').once('panels-ipe-hide-bar-processed').click(function() {
|
||||
Drupal.PanelsIPE.editors[key].hideContainer();
|
||||
});
|
||||
Drupal.PanelsIPE.bindClickDelete(context);
|
||||
}
|
||||
};
|
||||
@@ -51,8 +68,10 @@ Drupal.behaviors.PanelsIPE = {
|
||||
* discrete IPE elements. This will result in greater IPE flexibility.
|
||||
*/
|
||||
function DrupalPanelsIPE(cache_key, cfg) {
|
||||
cfg = cfg || {};
|
||||
var ipe = this;
|
||||
this.key = cache_key;
|
||||
this.lockPath = null;
|
||||
this.state = {};
|
||||
this.container = $('#panels-ipe-control-container');
|
||||
this.control = $('div#panels-ipe-control-' + cache_key);
|
||||
@@ -63,12 +82,75 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
opacity: 0.75, // opacity of sortable while sorting
|
||||
items: 'div.panels-ipe-portlet-wrapper',
|
||||
handle: 'div.panels-ipe-draghandle',
|
||||
cancel: '.panels-ipe-nodrag'
|
||||
cancel: '.panels-ipe-nodrag',
|
||||
dropOnEmpty: true
|
||||
}, cfg.sortableOptions || {});
|
||||
|
||||
this.regions = [];
|
||||
this.sortables = {};
|
||||
|
||||
$(document).bind('CToolsDetachBehaviors', function() {
|
||||
// If the IPE is off and the container is not visible, then we need
|
||||
// to reshow the container on modal close.
|
||||
if (!$('.panels-ipe-form-container', ipe.control).html() && !ipe.container.is(':visible')) {
|
||||
ipe.showContainer();
|
||||
ipe.cancelLock();
|
||||
}
|
||||
|
||||
// If the IPE is on and we've hidden the bar for a modal, we need to
|
||||
// re-display it.
|
||||
if (ipe.topParent && ipe.topParent.hasClass('panels-ipe-editing') && ipe.container.is(':not(visible)')) {
|
||||
ipe.showContainer();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
/**
|
||||
* If something caused us to abort what we were doing, send a background
|
||||
* cancel lock request to the server so that we do not leave stale locks
|
||||
* hanging around.
|
||||
*/
|
||||
this.cancelLock = function(sync) {
|
||||
// If there's a lockpath and an ajax available, inform server to clear lock.
|
||||
// We borrow the ajax options from the customize this page link.
|
||||
if (ipe.lockPath && Drupal.ajax['panels-ipe-customize-page']) {
|
||||
var ajaxOptions = {
|
||||
type: 'POST',
|
||||
url: ipe.lockPath
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
ajaxOptions.async = false;
|
||||
}
|
||||
|
||||
// Make sure we don't somehow get another one:
|
||||
ipe.lockPath = null;
|
||||
|
||||
// Send the request. This is synchronous to prevent being cancelled.
|
||||
$.ajax(ajaxOptions);
|
||||
}
|
||||
}
|
||||
|
||||
this.activateSortable = function(event, ui) {
|
||||
if (!Drupal.settings.Panels || !Drupal.settings.Panels.RegionLock) {
|
||||
// don't bother if there are no region locks in play.
|
||||
@@ -76,8 +158,7 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
}
|
||||
|
||||
var region = event.data.region;
|
||||
var $pane = $(event.srcElement).parents('.panels-ipe-portlet-wrapper');
|
||||
var paneId = $pane.attr('id').replace('panels-ipe-paneid-', '');
|
||||
var paneId = ui.item.attr('id').replace('panels-ipe-paneid-', '');
|
||||
|
||||
var disabledRegions = false;
|
||||
|
||||
@@ -109,7 +190,7 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
}
|
||||
|
||||
this.initSorting = function() {
|
||||
var $region = $(this).parent('.panels-ipe-region');
|
||||
var $region = $(this).parents('.panels-ipe-region');
|
||||
var region = $region.attr('id').replace('panels-ipe-regionid-', '');
|
||||
ipe.sortables[region] = $(this).sortable(ipe.sortableOptions);
|
||||
ipe.regions.push(region);
|
||||
@@ -117,6 +198,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();
|
||||
|
||||
@@ -137,44 +219,30 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
|
||||
$('div.panels-ipe-sort-container', ipe.topParent).bind('sortstop', this.enableRegions);
|
||||
|
||||
// Refresh the control jQuery object.
|
||||
ipe.control = $(ipe.control.selector);
|
||||
$('.panels-ipe-form-container', ipe.control).append(formdata);
|
||||
|
||||
$('input:submit:not(.ajax-processed)', ipe.control).addClass('ajax-processed').each(function() {
|
||||
$('input:submit:not(.ajax-processed), button:not(.ajax-processed)', ipe.control).addClass('ajax-processed').each(function() {
|
||||
var element_settings = {};
|
||||
|
||||
element_settings.url = $(this.form).attr('action');
|
||||
element_settings.setClick = true;
|
||||
element_settings.event = 'click';
|
||||
element_settings.progress = { 'type': 'throbber' };
|
||||
element_settings.ipe_cache_key = cache_key;
|
||||
|
||||
var base = $(this).attr('id');
|
||||
Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
|
||||
if ($(this).attr('id') == 'panels-ipe-save') {
|
||||
Drupal.ajax[base].options.beforeSerialize = function (element_settings, options) {
|
||||
ipe.saveEditing();
|
||||
return Drupal.ajax[base].beforeSerialize(element_settings, options);
|
||||
};
|
||||
Drupal.ajax[base].oldEventResponse = Drupal.ajax[base].eventResponse;
|
||||
Drupal.ajax[base].eventResponse = function (element, event) {
|
||||
var val = this.oldEventResponse(element, event);
|
||||
if (this.ajaxing) {
|
||||
ipe.hideContainer();
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
}
|
||||
if ($(this).attr('id') == 'panels-ipe-cancel') {
|
||||
Drupal.ajax[base].options.beforeSend = function () {
|
||||
return ipe.cancelEditing();
|
||||
};
|
||||
}
|
||||
Drupal.ajax[ipe.base] = new Drupal.ajax(base, this, element_settings);
|
||||
});
|
||||
|
||||
// Perform visual effects in a particular sequence.
|
||||
$('.panels-ipe-on').show('normal');
|
||||
// .show() + .hide() cannot have speeds associated with them, otherwise
|
||||
// it clears out inline styles.
|
||||
$('.panels-ipe-on').show();
|
||||
ipe.showForm();
|
||||
ipe.topParent.addClass('panels-ipe-editing');
|
||||
$('body').add(ipe.topParent).addClass('panels-ipe-editing');
|
||||
|
||||
};
|
||||
|
||||
this.hideContainer = function() {
|
||||
@@ -183,7 +251,6 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
|
||||
this.showContainer = function() {
|
||||
ipe.container.slideDown('normal');
|
||||
ipe.container.css('margin-left', '-' + parseInt(ipe.container.outerWidth() / 2) + 'px');
|
||||
};
|
||||
|
||||
this.showButtons = function() {
|
||||
@@ -198,16 +265,23 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
ipe.showContainer();
|
||||
};
|
||||
|
||||
this.endEditing = function(data) {
|
||||
$('.panels-ipe-form-container', ipe.control).empty();
|
||||
this.endEditing = function() {
|
||||
ipe.editing = false;
|
||||
ipe.lockPath = null;
|
||||
$('.panels-ipe-form-container').empty();
|
||||
// Re-show all the IPE non-editing meta-elements
|
||||
$('div.panels-ipe-off').show('fast');
|
||||
|
||||
// Refresh the container and control jQuery objects.
|
||||
ipe.container = $(ipe.container.selector);
|
||||
ipe.control = $(ipe.control.selector);
|
||||
|
||||
ipe.showButtons();
|
||||
// Re-hide all the IPE meta-elements
|
||||
$('div.panels-ipe-on').hide('fast');
|
||||
ipe.topParent.removeClass('panels-ipe-editing');
|
||||
$('div.panels-ipe-sort-container', ipe.topParent).sortable("destroy");
|
||||
$('div.panels-ipe-on').hide();
|
||||
|
||||
$('.panels-ipe-editing').removeClass('panels-ipe-editing');
|
||||
$('div.panels-ipe-sort-container.ui-sortable', ipe.topParent).sortable("destroy");
|
||||
};
|
||||
|
||||
this.saveEditing = function() {
|
||||
@@ -223,29 +297,34 @@ function DrupalPanelsIPE(cache_key, cfg) {
|
||||
val += id;
|
||||
}
|
||||
});
|
||||
$('input[name="panel[pane][' + region + ']"]', ipe.control).val(val);
|
||||
$('[name="panel[pane][' + region + ']"]', ipe.control).val(val);
|
||||
});
|
||||
}
|
||||
|
||||
this.cancelIPE = function() {
|
||||
ipe.hideContainer();
|
||||
ipe.topParent.fadeOut('medium', function() {
|
||||
ipe.topParent.replaceWith(ipe.backup.clone());
|
||||
ipe.topParent = $('div#panels-ipe-display-' + ipe.key);
|
||||
|
||||
// Processing of these things got lost in the cloning, but the classes remained behind.
|
||||
// @todo this isn't ideal but I can't seem to figure out how to keep an unprocessed backup
|
||||
// that will later get processed.
|
||||
$('.ctools-use-modal-processed', ipe.topParent).removeClass('ctools-use-modal-processed');
|
||||
$('.pane-delete-processed', ipe.topParent).removeClass('pane-delete-processed');
|
||||
ipe.topParent.fadeIn('medium');
|
||||
Drupal.attachBehaviors();
|
||||
});
|
||||
};
|
||||
|
||||
this.cancelEditing = function() {
|
||||
if (ipe.topParent.hasClass('changed')) {
|
||||
ipe.changed = true;
|
||||
}
|
||||
|
||||
if (!ipe.changed || confirm(Drupal.t('This will discard all unsaved changes. Are you sure?'))) {
|
||||
ipe.hideContainer();
|
||||
ipe.topParent.fadeOut('medium', function() {
|
||||
ipe.topParent.replaceWith(ipe.backup.clone());
|
||||
ipe.topParent = $('div#panels-ipe-display-' + ipe.key);
|
||||
|
||||
// Processing of these things got lost in the cloning, but the classes remained behind.
|
||||
// @todo this isn't ideal but I can't seem to figure out how to keep an unprocessed backup
|
||||
// that will later get processed.
|
||||
$('.ctools-use-modal-processed', ipe.topParent).removeClass('ctools-use-modal-processed');
|
||||
$('.pane-delete-processed', ipe.topParent).removeClass('pane-delete-processed');
|
||||
ipe.topParent.fadeIn('medium');
|
||||
Drupal.attachBehaviors();
|
||||
});
|
||||
this.cancelIPE();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// Cancel the submission.
|
||||
@@ -255,96 +334,159 @@ 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
|
||||
// cannot be placed after them.
|
||||
$('div.panels-ipe-portlet-static', this).each(function() {
|
||||
$(this).appendTo($(this).parent().parent());
|
||||
$(this).prependTo($(this).parent().parent());
|
||||
});
|
||||
|
||||
// Also remove the last panel separator.
|
||||
$('div.panel-separator', this).filter(':last').remove();
|
||||
|
||||
// Add a marker so we can drag things to empty containers.
|
||||
$('div.panels-ipe-sort-container', this).append('<div> </div>');
|
||||
});
|
||||
}
|
||||
|
||||
this.createSortContainers();
|
||||
|
||||
var element_settings = {
|
||||
url: ipe.cfg.formPath,
|
||||
event: 'click',
|
||||
keypress: false,
|
||||
// No throbber at all.
|
||||
progress: { 'type': 'none' }
|
||||
};
|
||||
|
||||
Drupal.ajax['ipe-ajax'] = new Drupal.ajax('ipe-ajax', $('div.panels-ipe-startedit', this.control).get(0), element_settings);
|
||||
|
||||
Drupal.ajax['ipe-ajax'].oldEventResponse = Drupal.ajax['ipe-ajax'].eventResponse;
|
||||
Drupal.ajax['ipe-ajax'].eventResponse = function (element, event) {
|
||||
this.oldEventResponse(element, event);
|
||||
if (this.ajaxing) {
|
||||
ipe.hideContainer();
|
||||
$('div.panels-ipe-off').fadeOut('normal');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
var ajaxOptions = {
|
||||
type: "POST",
|
||||
url: ,
|
||||
data: { 'js': 1 },
|
||||
global: true,
|
||||
success: Drupal.CTools.AJAX.respond,
|
||||
error: function(xhr) {
|
||||
Drupal.CTools.AJAX.handleErrors(xhr, ipe.cfg.formPath);
|
||||
},
|
||||
dataType: 'json'
|
||||
};
|
||||
|
||||
$('div.panels-ipe-startedit', this.control).click(function() {
|
||||
var $this = $(this);
|
||||
$.ajax(ajaxOptions);
|
||||
});
|
||||
*/
|
||||
};
|
||||
|
||||
$(function() {
|
||||
Drupal.ajax.prototype.commands.initIPE = function(ajax, data, status) {
|
||||
if (Drupal.PanelsIPE.editors[data.key]) {
|
||||
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) {
|
||||
if (Drupal.PanelsIPE.editors[data.key]) {
|
||||
Drupal.PanelsIPE.editors[data.key].lockPath = data.lockPath;
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
Drupal.PanelsIPE.editors[data.key].endEditing();
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.ajax.prototype.commands.unlockIPE = function(ajax, data, status) {
|
||||
if (confirm(data.message)) {
|
||||
var ajaxOptions = {
|
||||
type: "POST",
|
||||
url: data.break_path,
|
||||
data: { 'js': 1 },
|
||||
global: true,
|
||||
success: Drupal.CTools.AJAX.respond,
|
||||
error: function(xhr) {
|
||||
Drupal.CTools.AJAX.handleErrors(xhr, ipe.cfg.formPath);
|
||||
},
|
||||
dataType: 'json'
|
||||
};
|
||||
|
||||
var ajaxOptions = ajax.options;
|
||||
ajaxOptions.url = data.break_path;
|
||||
$.ajax(ajaxOptions);
|
||||
};
|
||||
}
|
||||
else {
|
||||
Drupal.PanelsIPE.editors[data.key].endEditing();
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.ajax.prototype.commands.endIPE = function(ajax, data, status) {
|
||||
if (Drupal.PanelsIPE.editors[data.key]) {
|
||||
Drupal.PanelsIPE.editors[data.key].endEditing(data);
|
||||
Drupal.PanelsIPE.editors[data.key].endEditing();
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
var retval = this.ipeReplacedEventResponse(element, event);
|
||||
if (this.ajaxing && this.element_settings.ipe_cache_key) {
|
||||
// Move the throbber so that it appears outside our container.
|
||||
if (this.progress.element) {
|
||||
$(this.progress.element).addClass('ipe-throbber').appendTo($('body'));
|
||||
}
|
||||
Drupal.PanelsIPE.editors[this.element_settings.ipe_cache_key].hideContainer();
|
||||
}
|
||||
// @TODO $('#panels-ipe-throbber-backdrop').remove();
|
||||
return retval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Override the eventResponse on ajax.js so we can add a little extra
|
||||
* behavior.
|
||||
*/
|
||||
Drupal.ajax.prototype.ipeReplacedError = Drupal.ajax.prototype.error;
|
||||
Drupal.ajax.prototype.error = function (response, uri) {
|
||||
var retval = this.ipeReplacedError(response, uri);
|
||||
if (this.element_settings.ipe_cache_key) {
|
||||
Drupal.PanelsIPE.editors[this.element_settings.ipe_cache_key].showContainer();
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.ajax.prototype.ipeReplacedBeforeSerialize = Drupal.ajax.prototype.beforeSerialize;
|
||||
Drupal.ajax.prototype.beforeSerialize = function (element_settings, options) {
|
||||
if ($(this.element).hasClass('panels-ipe-save')) {
|
||||
Drupal.PanelsIPE.editors[this.element_settings.ipe_cache_key].saveEditing();
|
||||
};
|
||||
return this.ipeReplacedBeforeSerialize(element_settings, options);
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Apply margin to bottom of the page.
|
||||
*
|
||||
* Note that directly applying marginBottom does not work in IE. To prevent
|
||||
* flickering/jumping page content with client-side caching, this is a regular
|
||||
* Drupal behavior.
|
||||
*
|
||||
* @see admin_menu.js via https://drupal.org/project/admin_menu
|
||||
*/
|
||||
Drupal.behaviors.panelsIpeMarginBottom = {
|
||||
attach: function () {
|
||||
$('body:not(.panels-ipe)').addClass('panels-ipe');
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by Panels In-Place Editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allow modules to control access to the Panels IPE.
|
||||
*
|
||||
* @param panels_display $display
|
||||
* The panels display about to be rendered.
|
||||
*
|
||||
* @return TRUE|FALSE|NULL
|
||||
* Returns TRUE to allow access, FALSE to deny, or NULL if the module
|
||||
* implementing this hook doesn't care about access for the given display.
|
||||
*/
|
||||
function hook_panels_ipe_access(panels_display $display) {
|
||||
// We only care about displays with the 'panelizer' context.
|
||||
if (!isset($display->context['panelizer'])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ($display->context['panelizer']->type[0] == 'entity:node') {
|
||||
// Allow or deny IPE access based on node type.
|
||||
return $display->context['panelizer']->data->type == 'awesome_page';
|
||||
}
|
||||
|
||||
// Otherwise, deny access to everything!
|
||||
return FALSE;
|
||||
}
|
||||
@@ -6,9 +6,9 @@ core = 7.x
|
||||
configure = admin/structure/panels
|
||||
files[] = panels_ipe.module
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-01-18
|
||||
version = "7.x-3.0"
|
||||
; Information added by Drupal.org packaging script on 2016-10-16
|
||||
version = "7.x-3.8"
|
||||
core = "7.x"
|
||||
project = "panels"
|
||||
datestamp = "1326917446"
|
||||
datestamp = "1476582295"
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ function panels_ipe_theme() {
|
||||
'variables' => array('output' => NULL, 'pane' => NULL, 'display' => NULL, 'renderer' => NULL),
|
||||
),
|
||||
'panels_ipe_region_wrapper' => array(
|
||||
'variables' => array('output' => NULL, 'region_id' => NULL, 'display' => NULL, 'renderer' => NULL),
|
||||
'variables' => array('output' => NULL, 'region_id' => NULL, 'display' => NULL, 'controls' => NULL, 'renderer' => NULL),
|
||||
),
|
||||
'panels_ipe_add_pane_button' => array(
|
||||
'variables' => array('region_id' => NULL, 'display' => NULL, 'renderer' => NULL),
|
||||
@@ -53,9 +53,6 @@ function panels_ipe_theme() {
|
||||
'panels_ipe_toolbar' => array(
|
||||
'variables' => array('buttons' => NULL),
|
||||
),
|
||||
'panels_ipe_edit_button' => array(
|
||||
'variables' => array('class' => array(), 'text' => NULL),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,67 +73,140 @@ 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(
|
||||
'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),
|
||||
$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,
|
||||
'attributes' => array(
|
||||
'class' => 'ctools-use-modal',
|
||||
'class' => array('ctools-use-modal', 'panels-ipe-hide-bar'),
|
||||
'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),
|
||||
// 'id' => "pane-edit-panel-pane-$pane->pid",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Add option to configure style in IPE
|
||||
if (user_access('administer panels pane styles')) {
|
||||
$vars['links']['style'] = array(
|
||||
'title' => '<span>' . t('Style') . '</span>',
|
||||
'href' => $renderer->get_url('style-type', 'pane', $pane->pid),
|
||||
'html' => TRUE,
|
||||
'attributes' => array(
|
||||
'class' => array('ctools-use-modal', 'panels-ipe-hide-bar'),
|
||||
'title' => t('Style'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Deleting is managed entirely in the js; this is just an attachment point
|
||||
// for it
|
||||
$links['delete'] = array(
|
||||
'title' => t('Delete'),
|
||||
$vars['links']['delete'] = array(
|
||||
'title' => '<span>' . t('Delete') . '</span>',
|
||||
'href' => '#',
|
||||
'html' => TRUE,
|
||||
'attributes' => array(
|
||||
'class' => 'pane-delete',
|
||||
'id' => "pane-delete-panel-pane-$pane->pid",
|
||||
'title' => t('Delete'),
|
||||
),
|
||||
);
|
||||
|
||||
$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'];
|
||||
$display = $vars['display'];
|
||||
|
||||
$attributes = array(
|
||||
'class' => 'panels-ipe-linkbar',
|
||||
);
|
||||
|
||||
$links = theme('links', array('links' => $links, 'attributes' => $attributes));
|
||||
$type = ctools_get_content_type($pane->type);
|
||||
$title ='<span class = "panels-ipe-dragbar-admin-title">' . ctools_content_admin_title($type, $pane->subtype, $pane->configuration, $display->context) . '</span>';
|
||||
|
||||
$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"> </div>';
|
||||
$links = '<div class="panels-ipe-dragbar panels-ipe-nodraghandle clearfix">' . $links .$title .'</div>';
|
||||
}
|
||||
else {
|
||||
$links .= '<div class="panels-ipe-dragbar panels-ipe-draghandle"> </div>';
|
||||
$links = '<div class="panels-ipe-dragbar panels-ipe-draghandle clearfix">' . $links . $title . '<span class="panels-ipe-draghandle-icon"><span class="panels-ipe-draghandle-icon-inner"></span></span></div>';
|
||||
}
|
||||
|
||||
$handlebar = '<div class="panels-ipe-handlebar-wrapper panels-ipe-on">' . $links . '</div>';
|
||||
|
||||
$handlebar = '<div class="panels-ipe-handlebar-wrapper panels-ipe-on clearfix">' . $links . '</div>';
|
||||
return $handlebar . $output;
|
||||
}
|
||||
|
||||
function theme_panels_ipe_region_wrapper($vars) {
|
||||
return $vars['output'];
|
||||
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'];
|
||||
$vars['links'] = '';
|
||||
|
||||
$attributes = array('class' => 'ctools-use-modal');
|
||||
$link = l(t('Add new pane'), $renderer->get_url('select-content', $region_id), array('attributes' => $attributes));
|
||||
return '<div class="panels-ipe-newblock panels-ipe-on panels-ipe-portlet-static">' . $link . '</div>';
|
||||
// Add option to configure style in IPE
|
||||
if (user_access('administer panels region styles')) {
|
||||
$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', 'panels-ipe-hide-bar', 'style'),
|
||||
'title' => t('Region style'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Add option to add items in the IPE
|
||||
$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">' . $links . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +221,7 @@ function panels_ipe_get_cache_key($key = NULL) {
|
||||
*/
|
||||
function panels_ipe_toolbar_add_button($cache_key, $id, $button) {
|
||||
$buttons = &drupal_static('panels_ipe_toolbar_buttons', array());
|
||||
drupal_alter('panels_ipe_button', $button, $id, $cache_key);
|
||||
$buttons[$cache_key][$id] = $button;
|
||||
}
|
||||
|
||||
@@ -176,34 +247,27 @@ function panels_ipe_page_alter(&$page) {
|
||||
|
||||
function theme_panels_ipe_toolbar($vars) {
|
||||
$buttons = $vars['buttons'];
|
||||
ctools_include('cleanstring');
|
||||
|
||||
$output = "<div id='panels-ipe-control-container' class='clearfix'>";
|
||||
foreach ($buttons as $key => $ipe_buttons) {
|
||||
$key = ctools_cleanstring($key);
|
||||
$output .= "<div id='panels-ipe-control-$key' class='panels-ipe-control'>";
|
||||
|
||||
// Controls in this container will appear when the IPE is not on.
|
||||
$output .= '<div class="panels-ipe-button-container clearfix">';
|
||||
foreach ($ipe_buttons as $button) {
|
||||
$output .= $button;
|
||||
$output .= is_string($button) ? $button : drupal_render($button);
|
||||
}
|
||||
$output .= '</div>';
|
||||
|
||||
// Controls in this container will appear when the IPE is on. It is usually
|
||||
// filled via AJAX.
|
||||
$output .= '<div class="panels-ipe-form-container clearfix"></div>';
|
||||
|
||||
$output .= '</div>';
|
||||
}
|
||||
|
||||
$output .= "</div>";
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function theme_panels_ipe_edit_button($vars) {
|
||||
$class = $vars['class'];
|
||||
$output = "<div class='$class panels-ipe-pseudobutton'>";
|
||||
$output .= " <span>" . $vars['text'] . "</span>";
|
||||
$output .= "</div>";
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,44 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
// The IPE operates in normal render mode, not admin mode.
|
||||
var $admin = FALSE;
|
||||
|
||||
// Whether or not the user has access.
|
||||
var $access = NULL;
|
||||
|
||||
function invoke_panels_ipe_access() {
|
||||
if (user_access('bypass access in place editing')) {
|
||||
return TRUE;
|
||||
}
|
||||
// Modules can return TRUE, FALSE or NULL, for allowed, disallowed,
|
||||
// or don't care - respectively. On the first FALSE, we deny access,
|
||||
// otherwise allow.
|
||||
foreach (module_invoke_all('panels_ipe_access', $this->display) as $result) {
|
||||
if ($result === FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
function access() {
|
||||
if (is_null($this->access)) {
|
||||
$this->access = $this->invoke_panels_ipe_access();
|
||||
}
|
||||
return $this->access;
|
||||
}
|
||||
|
||||
function render() {
|
||||
$output = parent::render();
|
||||
return "<div id='panels-ipe-display-{$this->clean_key}' class='panels-ipe-display-container'>$output</div>";
|
||||
if ($this->access()) {
|
||||
return "<div id='panels-ipe-display-{$this->clean_key}' class='panels-ipe-display-container'>$output</div>";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
function add_meta() {
|
||||
if (!$this->access()) {
|
||||
return parent::add_meta();
|
||||
}
|
||||
|
||||
ctools_include('display-edit', 'panels');
|
||||
ctools_include('content');
|
||||
|
||||
@@ -25,10 +57,46 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
|
||||
ctools_include('cleanstring');
|
||||
$this->clean_key = ctools_cleanstring($this->display->cache_key);
|
||||
$button = theme('panels_ipe_edit_button', array('class' => 'panels-ipe-startedit', 'text' => t('Customize this page')));
|
||||
panels_ipe_toolbar_add_button($this->clean_key, 'panels-ipe-startedit', $button);
|
||||
$button = array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Customize this page'),
|
||||
'#href' => $this->get_url('save_form'),
|
||||
'#options' => array('query' => drupal_get_destination()),
|
||||
'#id' => 'panels-ipe-customize-page',
|
||||
'#attributes' => array(
|
||||
'class' => array('panels-ipe-startedit', 'panels-ipe-pseudobutton'),
|
||||
),
|
||||
'#ajax' => array(
|
||||
'progress' => 'throbber',
|
||||
'ipe_cache_key' => $this->clean_key,
|
||||
),
|
||||
'#prefix' => '<div class="panels-ipe-pseudobutton-container">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
// panels_ipe_get_cache_key($this->clean_key);
|
||||
panels_ipe_toolbar_add_button($this->display->cache_key, 'panels-ipe-startedit', $button);
|
||||
|
||||
// @todo this actually should be an IPE setting instead.
|
||||
if (user_access('change layouts in place editing')) {
|
||||
$button = array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Change layout'),
|
||||
'#href' => $this->get_url('change_layout'),
|
||||
'#options' => array('query' => drupal_get_destination()),
|
||||
'#attributes' => array(
|
||||
'class' => array('panels-ipe-change-layout', 'panels-ipe-pseudobutton', 'ctools-modal-layout'),
|
||||
),
|
||||
'#ajax' => array(
|
||||
'progress' => 'throbber',
|
||||
'ipe_cache_key' => $this->clean_key,
|
||||
),
|
||||
|
||||
'#prefix' => '<div class="panels-ipe-pseudobutton-container">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
panels_ipe_toolbar_add_button($this->display->cache_key, 'panels-ipe-change-layout', $button);
|
||||
}
|
||||
|
||||
ctools_include('ajax');
|
||||
ctools_include('modal');
|
||||
@@ -36,22 +104,16 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
|
||||
ctools_add_css('panels_dnd', 'panels');
|
||||
ctools_add_css('panels_admin', 'panels');
|
||||
ctools_add_js('panels-base', 'panels');
|
||||
ctools_add_js('panels_ipe', 'panels_ipe');
|
||||
ctools_add_css('panels_ipe', 'panels_ipe');
|
||||
|
||||
$settings = array(
|
||||
'formPath' => url($this->get_url('save-form')),
|
||||
);
|
||||
drupal_add_js(array('PanelsIPECacheKeys' => array($this->clean_key)), 'setting');
|
||||
drupal_add_js(array('PanelsIPESettings' => array($this->clean_key => $settings)), 'setting');
|
||||
|
||||
drupal_add_library('system', 'ui.draggable');
|
||||
drupal_add_library('system', 'ui.droppable');
|
||||
drupal_add_library('system', 'ui.sortable');
|
||||
// drupal_add_js('misc/ui/jquery.ui.draggable.min.js');
|
||||
// drupal_add_js('misc/ui/jquery.ui.droppable.min.js');
|
||||
// drupal_add_js('misc/ui/jquery.ui.sortable.min.js');
|
||||
// jquery_ui_add(array('ui.draggable', 'ui.droppable', 'ui.sortable'));
|
||||
|
||||
parent::add_meta();
|
||||
}
|
||||
|
||||
@@ -66,6 +128,9 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
if (empty($output)) {
|
||||
return;
|
||||
}
|
||||
if (!$this->access()) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
// If there are region locks, add them.
|
||||
if (!empty($pane->locks['type']) && $pane->locks['type'] == 'regions') {
|
||||
@@ -107,15 +172,36 @@ 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) {
|
||||
if (!$this->access()) {
|
||||
return parent::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 (!$this->access()) {
|
||||
return 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->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';
|
||||
@@ -132,32 +218,31 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
* @param $panes
|
||||
*/
|
||||
function render_region($region_id, $panes) {
|
||||
if (!$this->access()) {
|
||||
return parent::render_region($region_id, $panes);
|
||||
}
|
||||
|
||||
// Generate this region's 'empty' placeholder pane from the IPE plugin.
|
||||
$empty_ph = theme('panels_ipe_placeholder_pane', array('region_id' => $region_id, 'region_title' => $this->plugins['layout']['regions'][$region_id]));
|
||||
|
||||
// Wrap the placeholder in some guaranteed markup.
|
||||
$panes['empty_placeholder'] = '<div class="panels-ipe-placeholder panels-ipe-on panels-ipe-portlet-marker panels-ipe-portlet-static">' . $empty_ph . "</div>";
|
||||
|
||||
// Generate this region's add new pane button. FIXME waaaaay too hardcoded
|
||||
$panes['add_button'] = theme('panels_ipe_add_pane_button', array('region_id' => $region_id, 'display' => $this->display, 'renderer' => $this));
|
||||
$control = '<div class="panels-ipe-placeholder panels-ipe-on panels-ipe-portlet-marker panels-ipe-portlet-static">' . $empty_ph . theme('panels_ipe_add_pane_button', array('region_id' => $region_id, 'display' => $this->display, 'renderer' => $this)) . "</div>";
|
||||
|
||||
$output = parent::render_region($region_id, $panes);
|
||||
$output = theme('panels_ipe_region_wrapper', array('output' => $output, 'region_id' => $region_id, 'display' => $this->display, 'renderer' => $this));
|
||||
$output = theme('panels_ipe_region_wrapper', array('output' => $output, 'region_id' => $region_id, 'display' => $this->display, 'controls' => $control, 'renderer' => $this));
|
||||
$classes = 'panels-ipe-region';
|
||||
|
||||
ctools_include('cleanstring');
|
||||
$region_id = ctools_cleanstring($region_id);
|
||||
return "<div id='panels-ipe-regionid-$region_id' class='panels-ipe-region'>$output</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX entry point to create the controller form for an IPE.
|
||||
* This is a generic lock test.
|
||||
*/
|
||||
function ajax_save_form($break = NULL) {
|
||||
function ipe_test_lock($url, $break) {
|
||||
if (!empty($this->cache->locked)) {
|
||||
if ($break != 'break') {
|
||||
$account = user_load($this->cache->locked->uid);
|
||||
$name = theme('username', array('account' => $account));
|
||||
$name = format_username($account);
|
||||
$lock_age = format_interval(time() - $this->cache->locked->updated);
|
||||
|
||||
$message = t("This panel is being edited by user !user, and is therefore locked from editing by others. This lock is !age old.\n\nClick OK to break this lock and discard any changes made by !user.", array('!user' => $name, '!age' => $lock_age));
|
||||
@@ -165,16 +250,60 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
$this->commands[] = array(
|
||||
'command' => 'unlockIPE',
|
||||
'message' => $message,
|
||||
'break_path' => url($this->get_url('save-form', 'break'))
|
||||
'break_path' => url($this->get_url($url, 'break')),
|
||||
'key' => $this->clean_key,
|
||||
);
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Break the lock.
|
||||
panels_edit_cache_break_lock($this->cache);
|
||||
}
|
||||
}
|
||||
|
||||
function get_panels_storage_op_for_ajax($method) {
|
||||
switch ($method) {
|
||||
case 'ajax_unlock_ipe':
|
||||
case 'ajax_save_form':
|
||||
return 'update';
|
||||
case 'ajax_change_layout':
|
||||
case 'ajax_set_layout':
|
||||
return 'change layout';
|
||||
}
|
||||
|
||||
return parent::get_panels_storage_op_for_ajax($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to unlock the IPE.
|
||||
*
|
||||
* This is called whenever something server side determines that editing
|
||||
* has stopped and cleans up no longer needed locks.
|
||||
*
|
||||
* It has no visible return value as this is considered a background task
|
||||
* and the client side has already given all indications that things are
|
||||
* now in a 'normal' state.
|
||||
*/
|
||||
function ajax_unlock_ipe() {
|
||||
panels_edit_cache_clear($this->cache);
|
||||
$this->commands[] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX entry point to create the controller form for an IPE.
|
||||
*/
|
||||
function ajax_save_form($break = NULL) {
|
||||
if ($this->ipe_test_lock('save-form', $break)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the $_POST['ajax_html_ids'] values to preserve
|
||||
// proper IDs on form elements when they are rebuilt
|
||||
// by the Panels IPE without refreshing the page
|
||||
$_POST['ajax_html_ids'] = array();
|
||||
|
||||
$form_state = array(
|
||||
'renderer' => $this,
|
||||
'display' => &$this->display,
|
||||
'content_types' => $this->cache->content_types,
|
||||
'rerender' => FALSE,
|
||||
@@ -186,11 +315,24 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
$output = drupal_build_form('panels_ipe_edit_control_form', $form_state);
|
||||
if (empty($form_state['executed'])) {
|
||||
// At this point, we want to save the cache to ensure that we have a lock.
|
||||
$this->cache->ipe_locked = TRUE;
|
||||
panels_edit_cache_set($this->cache);
|
||||
$this->commands[] = array(
|
||||
'command' => 'initIPE',
|
||||
'key' => $this->clean_key,
|
||||
'data' => drupal_render($output),
|
||||
'lockPath' => url($this->get_url('unlock_ipe')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if we have a lock that was broken. If so we need to
|
||||
// inform the user and abort.
|
||||
if (empty($this->cache->ipe_locked)) {
|
||||
$this->commands[] = ajax_command_alert(t('A lock you had has been externally broken, and all your changes have been reverted.'));
|
||||
$this->commands[] = array(
|
||||
'command' => 'cancelIPE',
|
||||
'key' => $this->clean_key,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -199,6 +341,13 @@ 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);
|
||||
// A rerender should fix IDs on added panes as well as ensure style changes are
|
||||
// rendered.
|
||||
$this->meta_location = 'inline';
|
||||
$this->commands[] = ajax_command_replace("#panels-ipe-display-{$this->clean_key}", panels_render_display($this->display, $this));
|
||||
$buttons = &drupal_static('panels_ipe_toolbar_buttons', array());
|
||||
$output = theme('panels_ipe_toolbar', array('buttons' => $buttons));
|
||||
$this->commands[] = ajax_command_replace('#panels-ipe-control-container', $output);
|
||||
}
|
||||
else {
|
||||
// Cancelled. Clear the cache.
|
||||
@@ -208,10 +357,97 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
$this->commands[] = array(
|
||||
'command' => 'endIPE',
|
||||
'key' => $this->clean_key,
|
||||
'data' => $output,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX entry point to create the controller form for an IPE.
|
||||
*/
|
||||
function ajax_change_layout($break = NULL) {
|
||||
if ($this->ipe_test_lock('change_layout', $break)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, we want to save the cache to ensure that we have a lock.
|
||||
$this->cache->ipe_locked = TRUE;
|
||||
panels_edit_cache_set($this->cache);
|
||||
|
||||
ctools_include('plugins', 'panels');
|
||||
ctools_include('common', 'panels');
|
||||
|
||||
// @todo figure out a solution for this, it's critical
|
||||
if (isset($this->display->allowed_layouts)) {
|
||||
$layouts = $this->display->allowed_layouts;
|
||||
}
|
||||
else {
|
||||
$layouts = panels_common_get_allowed_layouts('panels_page');
|
||||
}
|
||||
|
||||
// Filter out builders
|
||||
$layouts = array_filter($layouts, '_panels_builder_filter');
|
||||
|
||||
// Let other modules filter the layouts.
|
||||
drupal_alter('panels_layouts_available', $layouts);
|
||||
|
||||
// Define the current layout
|
||||
$current_layout = $this->plugins['layout']['name'];
|
||||
|
||||
$output = panels_common_print_layout_links($layouts, $this->get_url('set_layout'), array('attributes' => array('class' => array('use-ajax'))), $current_layout);
|
||||
|
||||
$this->commands[] = ctools_modal_command_display(t('Change layout'), $output);
|
||||
$this->commands[] = array(
|
||||
'command' => 'IPEsetLockState',
|
||||
'key' => $this->clean_key,
|
||||
'lockPath' => url($this->get_url('unlock_ipe')),
|
||||
);
|
||||
}
|
||||
|
||||
function ajax_set_layout($layout) {
|
||||
ctools_include('context');
|
||||
ctools_include('display-layout', 'panels');
|
||||
$form_state = array(
|
||||
'layout' => $layout,
|
||||
'display' => $this->display,
|
||||
'finish' => t('Save'),
|
||||
'no_redirect' => TRUE,
|
||||
);
|
||||
|
||||
// Reset the $_POST['ajax_html_ids'] values to preserve
|
||||
// proper IDs on form elements when they are rebuilt
|
||||
// by the Panels IPE without refreshing the page
|
||||
$_POST['ajax_html_ids'] = array();
|
||||
|
||||
$output = drupal_build_form('panels_change_layout', $form_state);
|
||||
$output = drupal_render($output);
|
||||
if (!empty($form_state['executed'])) {
|
||||
if (isset($form_state['back'])) {
|
||||
return $this->ajax_change_layout();
|
||||
}
|
||||
|
||||
if (!empty($form_state['clicked_button']['#save-display'])) {
|
||||
// Saved. Save the cache.
|
||||
panels_edit_cache_save($this->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.
|
||||
$layout = panels_get_layout($this->display->layout);
|
||||
$this->plugins['layout'] = $layout;
|
||||
if (!isset($layout['regions'])) {
|
||||
$this->plugins['layout']['regions'] = panels_get_regions($layout, $this->display);
|
||||
}
|
||||
|
||||
$this->meta_location = 'inline';
|
||||
|
||||
$this->commands[] = ajax_command_replace("#panels-ipe-display-{$this->clean_key}", panels_render_display($this->display, $this));
|
||||
$this->commands[] = ctools_modal_command_dismiss();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->commands[] = ctools_modal_command_display(t('Change layout'), $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a command array to redraw a pane.
|
||||
*/
|
||||
@@ -238,10 +474,16 @@ class panels_renderer_ipe extends panels_renderer_editor {
|
||||
$pane = $this->display->content[$pid];
|
||||
}
|
||||
|
||||
ctools_include('cleanstring');
|
||||
$region_id = ctools_cleanstring($pane->panel);
|
||||
$this->commands[] = ajax_command_append("#panels-ipe-regionid-$region_id 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,12 +521,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;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @file
|
||||
* Custom CSS for the Mini Panels module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Customize the CTools wizard trail / breadcrumb used on the edit pages for
|
||||
* Mini Panels as a stop-gap measure until the UX can be completely re-done.
|
||||
*/
|
||||
.wizard-trail {
|
||||
text-align: right;
|
||||
}
|
||||
@@ -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-01-18
|
||||
version = "7.x-3.0"
|
||||
; Information added by Drupal.org packaging script on 2016-10-16
|
||||
version = "7.x-3.8"
|
||||
core = "7.x"
|
||||
project = "panels"
|
||||
datestamp = "1326917446"
|
||||
datestamp = "1476582295"
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ function panels_mini_uninstall() {
|
||||
$deltas[] = $panel_mini->pid;
|
||||
}
|
||||
|
||||
if ($deltas) {
|
||||
if (db_table_exists('block') && $deltas) {
|
||||
// Delete all configured blocks.
|
||||
db_delete('block')
|
||||
->condition('module', 'panels_mini')
|
||||
@@ -122,3 +122,61 @@ function panels_mini_uninstall() {
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_update_dependencies().
|
||||
*/
|
||||
function panels_mini_update_dependencies() {
|
||||
// Update 7301 requires panels storage support
|
||||
$dependencies['panels_mini'][7301] = array(
|
||||
'panels' => 7305,
|
||||
);
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the storage type and id on existing mini panels.
|
||||
*/
|
||||
function panels_mini_update_7301() {
|
||||
if (!isset($sandbox['progress'])) {
|
||||
// Initialize batch update information.
|
||||
$sandbox['progress'] = (float)0;
|
||||
$sandbox['current_did'] = -1;
|
||||
$sandbox['max'] = db_query("SELECT COUNT(pd.did)
|
||||
FROM {panels_display} pd
|
||||
JOIN {panels_mini} pm ON pm.did = pd.did
|
||||
WHERE pd.storage_type = ''")->fetchField();
|
||||
}
|
||||
|
||||
// Set a limit of how many rows to process per batch.
|
||||
$limit = 1000;
|
||||
|
||||
// Run the query
|
||||
$result = db_query_range("SELECT pd.did, pm.name
|
||||
FROM {panels_display} pd
|
||||
JOIN {panels_mini} pm ON pm.did = pd.did
|
||||
WHERE pd.storage_type = '' AND pd.did > :current_did", 0, $limit, array(':current_did' => $sandbox['current_did']));
|
||||
|
||||
foreach ($result as $row) {
|
||||
db_update('panels_display')
|
||||
->fields(array(
|
||||
'storage_type' => 'panels_mini',
|
||||
'storage_id' => $row->name,
|
||||
))
|
||||
->condition('did', $row->did)
|
||||
->execute();
|
||||
|
||||
// Update our progress information.
|
||||
$sandbox['progress']++;
|
||||
$sandbox['current_did'] = $row->did;
|
||||
}
|
||||
|
||||
// Set the "finished" status, to tell batch engine whether this function
|
||||
// needs to run again.
|
||||
$sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']);
|
||||
|
||||
if ($sandbox['#finished']) {
|
||||
return t('Added the storage type for panels_mini to relevant panels displays');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ function panels_mini_settings() {
|
||||
// Allow the rest of the system access to mini panels
|
||||
|
||||
/**
|
||||
* Implementation of hook_block_list().
|
||||
* Implementation of hook_block_info().
|
||||
*/
|
||||
function panels_mini_block_info() {
|
||||
// Safety: go away if CTools is not at an appropriate version.
|
||||
@@ -74,7 +74,7 @@ function panels_mini_block_info() {
|
||||
|
||||
$minis = panels_mini_load_all();
|
||||
foreach ($minis as $panel_mini) {
|
||||
if (empty($panel_mini->disabled) && empty($panel_mini->requiredcontext)) {
|
||||
if (empty($panel_mini->disabled) && (module_exists('page_manager') || empty($panel_mini->requiredcontexts))) {
|
||||
$blocks[$panel_mini->name] = array(
|
||||
'info' => t('Mini panel: "@title"', array('@title' => $panel_mini->admin_title)),
|
||||
'cache' => DRUPAL_NO_CACHE,
|
||||
@@ -87,6 +87,8 @@ function panels_mini_block_info() {
|
||||
|
||||
/**
|
||||
* Implementation of hook_block_view().
|
||||
*
|
||||
* @see panels_mini_panels_mini_content_type_render().
|
||||
*/
|
||||
function panels_mini_block_view($delta = 0) {
|
||||
// static recursion protection.
|
||||
@@ -103,8 +105,18 @@ function panels_mini_block_view($delta = 0) {
|
||||
}
|
||||
|
||||
ctools_include('context');
|
||||
$panel_mini->context = $panel_mini->display->context = ctools_context_load_contexts($panel_mini);
|
||||
|
||||
$contexts = array();
|
||||
if (module_exists('page_manager') && $current_page = page_manager_get_current_page()) {
|
||||
if (!empty($current_page['contexts'])) {
|
||||
$contexts = ctools_context_match_required_contexts($panel_mini->requiredcontexts, $current_page['contexts']);
|
||||
}
|
||||
}
|
||||
drupal_alter('panels_mini_block_contexts', $contexts, $panel_mini);
|
||||
|
||||
$panel_mini->context = $panel_mini->display->context = ctools_context_load_contexts($panel_mini, FALSE, $contexts);
|
||||
$panel_mini->display->css_id = panels_mini_get_id($panel_mini->name);
|
||||
$panel_mini->display->owner = $panel_mini;
|
||||
|
||||
$block = array();
|
||||
|
||||
@@ -120,12 +132,96 @@ 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')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_list_alter().
|
||||
*
|
||||
* Remove the block if the required contexts are not available.
|
||||
*/
|
||||
function panels_mini_block_list_alter(&$blocks) {
|
||||
if (module_exists('page_manager')) {
|
||||
$current_page = page_manager_get_current_page();
|
||||
}
|
||||
|
||||
// Load add at once to save time.
|
||||
panels_mini_load_all();
|
||||
|
||||
foreach ($blocks as $key => $block) {
|
||||
if ($block->module != 'panels_mini') {
|
||||
// This block was added by a contrib module, leave it in the list.
|
||||
continue;
|
||||
}
|
||||
|
||||
$panel_mini = panels_mini_load($block->delta);
|
||||
if (empty($panel_mini)) {
|
||||
// Bail out early if the specified mini panel doesn't exist.
|
||||
unset($blocks[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($panel_mini->requiredcontexts)) {
|
||||
if (!$current_page || empty($current_page['contexts'])) {
|
||||
unset($blocks[$key]);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
$required = array();
|
||||
foreach ($panel_mini->requiredcontexts as $context) {
|
||||
$info = ctools_get_context($context['name']);
|
||||
$required[] = new ctools_context_required($context['identifier'], $info['context name']);
|
||||
}
|
||||
if (!ctools_context_match_requirements($current_page['contexts'], $required)) {
|
||||
unset($blocks[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 with bid property.
|
||||
if (isset($element['#element']['#block']) && isset($element['#element']['#block']->bid) && 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.
|
||||
*/
|
||||
@@ -163,22 +259,30 @@ function panels_mini_load($name) {
|
||||
// We use array_key_exists because failed loads will be NULL and
|
||||
// isset() will try to load it again.
|
||||
if (!array_key_exists($name, $cache)) {
|
||||
ctools_include('export');
|
||||
$result = ctools_export_load_object('panels_mini', 'names', array($name));
|
||||
if (isset($result[$name])) {
|
||||
if (empty($result[$name]->display)) {
|
||||
$result[$name]->display = panels_load_display($result[$name]->did);
|
||||
if (!empty($result[$name]->title) && empty($result[$name]->display->title)) {
|
||||
$result[$name]->display->title = $result[$name]->title;
|
||||
}
|
||||
}
|
||||
$cache[$name] = $result[$name];
|
||||
if (!empty($result[$name]->title) && empty($result[$name]->admin_title)) {
|
||||
$cache[$name]->admin_title = $result[$name]->title;
|
||||
}
|
||||
$cid = 'panels_mini_load:' . $name;
|
||||
$result = cache_get($cid, 'cache_panels');
|
||||
if (!empty($result->data)) {
|
||||
$cache[$name] = $result->data;
|
||||
}
|
||||
else {
|
||||
$cache[$name] = NULL;
|
||||
ctools_include('export');
|
||||
$result = ctools_export_load_object('panels_mini', 'names', array($name));
|
||||
if (isset($result[$name])) {
|
||||
if (empty($result[$name]->display)) {
|
||||
$result[$name]->display = panels_load_display($result[$name]->did);
|
||||
if (!empty($result[$name]->title) && empty($result[$name]->display->title)) {
|
||||
$result[$name]->display->title = $result[$name]->title;
|
||||
}
|
||||
}
|
||||
$cache[$name] = $result[$name];
|
||||
if (!empty($result[$name]->title) && empty($result[$name]->admin_title)) {
|
||||
$cache[$name]->admin_title = $result[$name]->title;
|
||||
}
|
||||
cache_set($cid, $cache[$name], 'cache_panels', CACHE_TEMPORARY);
|
||||
}
|
||||
else {
|
||||
$cache[$name] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +305,22 @@ function panels_mini_load_all($reset = FALSE) {
|
||||
if ($reset) {
|
||||
$cache = array();
|
||||
}
|
||||
else {
|
||||
$panel_names = db_select('panels_mini', 'pm')
|
||||
->fields('pm', array('name'))
|
||||
->execute();
|
||||
$cids = array();
|
||||
foreach ($panel_names as $name) {
|
||||
$cids[] = 'panels_mini_load:' . $name->name;
|
||||
}
|
||||
$output = cache_get_multiple($cids, 'cache_panels');
|
||||
foreach ($output as $mini) {
|
||||
if (!empty($mini->data)) {
|
||||
$mini = $mini->data;
|
||||
$cache[$mini->name] = $mini;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctools_include('export');
|
||||
$minis = ctools_export_load_object('panels_mini');
|
||||
@@ -233,7 +353,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,10 +362,14 @@ function panels_mini_load_all($reset = FALSE) {
|
||||
*/
|
||||
function panels_mini_save(&$mini) {
|
||||
if (!empty($mini->display)) {
|
||||
$mini->display->storage_id = $mini->name;
|
||||
$display = panels_save_display($mini->display);
|
||||
$mini->did = $display->did;
|
||||
}
|
||||
|
||||
// Clear the panels_mini_load cache.
|
||||
cache_clear_all('panels_mini_load:', 'cache_panels', TRUE);
|
||||
|
||||
$update = (isset($mini->pid) && $mini->pid != 'new') ? array('pid') : array();
|
||||
drupal_write_record('panels_mini', $mini, $update);
|
||||
|
||||
@@ -259,7 +384,7 @@ function panels_mini_delete($mini) {
|
||||
->condition('name', $mini->name)
|
||||
->execute();
|
||||
|
||||
if ($mini->type != t('Overridden')) {
|
||||
if (db_table_exists('block') && $mini->type != t('Overridden')) {
|
||||
// Also remove from block table as long as there isn't a default that may appear.
|
||||
db_delete('block')
|
||||
->condition('delta', $mini->name)
|
||||
@@ -297,6 +422,24 @@ function panels_mini_ctools_plugin_directory($module, $plugin) {
|
||||
if ($module == 'ctools' && ($plugin == 'content_types' || $plugin == 'export_ui')) {
|
||||
return 'plugins/' . $plugin;
|
||||
}
|
||||
if ($module == 'panels' && $plugin == 'panels_storage') {
|
||||
return 'plugins/' . $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_default_panels_mini_alter().
|
||||
*
|
||||
* If a default Panels display has no storage type, set it.
|
||||
*/
|
||||
function panels_default_panels_mini_alter(&$mini_panels) {
|
||||
foreach ($mini_panels as &$mini_panel) {
|
||||
$display =& $mini_panel->display;
|
||||
if (empty($display->storage_type)) {
|
||||
$display->storage_type = 'panels_mini';
|
||||
$display->storage_id = $mini_panel->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,6 +478,9 @@ function panels_mini_panels_cache_get($key) {
|
||||
$cache->display = $item->display;
|
||||
$cache->display->context = ctools_context_load_contexts($item);
|
||||
$cache->display->cache_key = 'panels_mini:' . $key;
|
||||
$cache->display->storage_type = 'panels_mini';
|
||||
// Temporary storage id that's replaced in panels_mini_save().
|
||||
$cache->display->storage_id = 'panels_mini';
|
||||
$cache->content_types = panels_common_get_allowed_types('panels_mini', $cache->display->context);
|
||||
$cache->display_title = TRUE;
|
||||
|
||||
@@ -378,6 +524,15 @@ function panels_mini_panels_cache_save($key, $cache) {
|
||||
function panels_mini_panels_cache_break_lock($key, $cache) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_panels_pre_render().
|
||||
*/
|
||||
function panels_mini_panels_pre_render($display, $renderer) {
|
||||
if (isset($display->owner->table) && $display->owner->table == 'panels_mini' && $renderer instanceof panels_renderer_standard) {
|
||||
$renderer->show_empty_layout = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_panels_dashboard_blocks().
|
||||
*
|
||||
@@ -427,3 +582,14 @@ function panels_mini_panels_dashboard_blocks(&$vars) {
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements template_preprocess_ctools_wizard_trail().
|
||||
*
|
||||
* Customize the divider used in the CTools wizard to build the edit pages for
|
||||
* Mini Panels as a stop-gap measure until the UX can be completely re-done.
|
||||
*/
|
||||
function panels_mini_preprocess_ctools_wizard_trail(&$variables) {
|
||||
$variables['divider'] = ' | ';
|
||||
drupal_add_css(drupal_get_path('module', 'panels_mini') . '/panels_mini.css');
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
@@ -4,7 +4,7 @@
|
||||
* @file
|
||||
* Contains the content type plugin for a mini panel. While this does not
|
||||
* need to be broken out into a .inc file, it's convenient that we do so
|
||||
* that we don't load code unneccessarily. Plus it demonstrates plugins
|
||||
* that we don't load code unnecessarily. Plus it demonstrates plugins
|
||||
* in modules other than Panels itself.
|
||||
*
|
||||
*/
|
||||
@@ -68,8 +68,13 @@ function _panels_mini_panels_mini_content_type_content_type($mini) {
|
||||
$type['required context'] = array();
|
||||
foreach ($mini->requiredcontexts as $context) {
|
||||
$info = ctools_get_context($context['name']);
|
||||
// TODO: allow an optional setting
|
||||
$type['required context'][] = new ctools_context_required($context['identifier'], $info['context name']);
|
||||
// Check if the required context is actually required.
|
||||
if (!empty($context['optional'])) {
|
||||
$type['required context'][] = new ctools_context_optional($context['identifier'], $info['context name']);
|
||||
}
|
||||
else {
|
||||
$type['required context'][] = new ctools_context_required($context['identifier'], $info['context name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $type;
|
||||
@@ -109,6 +114,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 +152,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,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides a panels_storage plugin for mini panels.
|
||||
*/
|
||||
|
||||
// Plugin definition
|
||||
$plugin = array(
|
||||
'access callback' => 'panels_mini_panels_storage_access',
|
||||
);
|
||||
|
||||
/**
|
||||
* Access callback for panels storage.
|
||||
*/
|
||||
function panels_mini_panels_storage_access($storage_type, $storage_id, $op, $account) {
|
||||
if ($op == 'create') {
|
||||
return user_access('create mini panels', $account);
|
||||
}
|
||||
|
||||
return user_access('administer mini panels', $account);
|
||||
}
|
||||
@@ -6,9 +6,9 @@ configure = admin/structure/panels
|
||||
core = 7.x
|
||||
files[] = panels_node.module
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-01-18
|
||||
version = "7.x-3.0"
|
||||
; Information added by Drupal.org packaging script on 2016-10-16
|
||||
version = "7.x-3.8"
|
||||
core = "7.x"
|
||||
project = "panels"
|
||||
datestamp = "1326917446"
|
||||
datestamp = "1476582295"
|
||||
|
||||
|
||||