Commit 5ac4f2b0 authored by Riccardo Padovani's avatar Riccardo Padovani

Updated module ctools to 7.x-1.6

parent 3e677343
......@@ -3,6 +3,9 @@ Current API Version: 2.0.8
Please note that the API version is an internal number and does not match release numbers. It is entirely possible that releases will not increase the API version number, and increasing this number too often would burden contrib module maintainers who need to keep up with API changes.
This file contains a log of changes to the API.
API Version 2.0.9
Changed import permissions to use the new 'use ctools import' permission.
API Version 2.0.8
Introduce ctools_class_add().
Introduce ctools_class_remove().
......
......@@ -3,10 +3,12 @@ description = Performs bulk exporting of data objects known about by Chaos tools
core = 7.x
dependencies[] = ctools
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -2,13 +2,16 @@ name = Chaos tools
description = A library of helpful tools by Merlin of Chaos.
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
files[] = includes/context.inc
files[] = includes/css-cache.inc
files[] = includes/math-expr.inc
files[] = includes/stylizer.inc
files[] = tests/css_cache.test
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -40,7 +40,19 @@ function ctools_requirements($phase) {
* Implements hook_schema().
*/
function ctools_schema() {
return ctools_schema_2();
return ctools_schema_3();
}
/**
* Version 3 of the CTools schema.
*/
function ctools_schema_3() {
$schema = ctools_schema_2();
// update the 'obj' field to be 128 bytes long:
$schema['ctools_object_cache']['fields']['obj']['length'] = 128;
return $schema;
}
/**
......@@ -141,6 +153,21 @@ function ctools_schema_1() {
return $schema;
}
/**
* Implements hook_install().
*/
function ctools_install() {
// Activate our custom cache handler for the CSS cache.
variable_set('cache_class_cache_ctools_css', 'CToolsCssCache');
}
/**
* Implements hook_uninstall().
*/
function ctools_uninstall() {
variable_del('cache_class_cache_ctools_css');
}
/**
* Enlarge the ctools_object_cache.name column to prevent truncation and weird
* errors.
......@@ -217,3 +244,22 @@ function ctools_update_6008() {
)
);
}
/**
* Enable the custom CSS cache handler.
*/
function ctools_update_7000() {
variable_set('cache_class_cache_ctools_css', 'CToolsCssCache');
}
/**
* Increase the length of the ctools_object_cache.obj column.
*/
function ctools_update_7001() {
db_change_field('ctools_object_cache', 'obj', 'obj', array(
'type' => 'varchar',
'length' => '128',
'not null' => TRUE,
'description' => 'The type of the object this cache is attached to; this essentially represents the owner so that several sub-systems can use this cache.',
));
}
......@@ -9,7 +9,21 @@
* must be implemented in the module file.
*/
define('CTOOLS_API_VERSION', '2.0.7');
define('CTOOLS_API_VERSION', '2.0.8');
/**
* The current working ctools version.
*
* In a release, it should be 7.x-1.x, which should match what drush make will
* create. In a dev format, it should be 7.x-1.(x+1)-dev, which will allow
* modules depending on new features in ctools to depend on ctools > 7.x-1.x.
*
* To define a specific version of CTools as a dependency for another module,
* simply include a dependency line in that module's info file, e.g.:
* ; Requires CTools v7.x-1.4 or newer.
* dependencies[] = ctools (>=1.4)
*/
define('CTOOLS_MODULE_VERSION', '7.x-1.6');
/**
* Test the CTools API version.
......@@ -536,6 +550,19 @@ function ctools_menu() {
return $items;
}
/**
* Implements hook_permission().
*/
function ctools_permission() {
return array(
'use ctools import' => array(
'title' => t('Use CTools importer'),
'description' => t('The import functionality allows users to execute arbitrary PHP code, so extreme caution must be taken.'),
'restrict access' => TRUE,
),
);
}
/**
* Implementation of hook_cron. Clean up old caches.
*/
......@@ -546,19 +573,12 @@ function ctools_cron() {
}
/**
* Ensure the CTools CSS cache is flushed whenever hook_flush_caches is invoked.
* Implements hook_flush_caches().
*/
function ctools_flush_caches() {
// Do not actually flush caches if running on cron. Drupal uses this hook
// in an inconsistent fashion and it does not necessarily mean to *flush*
// caches when running from cron. Instead it's just getting a list of cache
// tables and may not do any flushing.
if (!empty($GLOBALS['locks']['cron'])) {
return;
}
ctools_include('css');
ctools_css_flush_caches();
// Only return the CSS cache bin if it has been activated, to avoid
// drupal_flush_all_caches() from trying to truncate a non-existing table.
return variable_get('cache_class_cache_ctools_css', FALSE) ? array('cache_ctools_css') : array();
}
/**
......@@ -638,7 +658,26 @@ function ctools_preprocess_node(&$vars) {
}
}
/**
* Implements hook_page_alter().
*
* Last ditch attempt to remove sidebar regions if the "no blocks"
* functionality has been activated.
*
* @see ctools_block_list_alter().
*/
function ctools_page_alter(&$page) {
$check = drupal_static('ctools_set_no_blocks', TRUE);
if (!$check) {
foreach ($page as $region_id => $region) {
// @todo -- possibly we can set configuration for this so that users can
// specify which blocks will not get rendered.
if (strpos($region_id, 'sidebar') !== FALSE) {
unset($page[$region_id]);
}
}
}
$page['#post_render'][] = 'ctools_page_token_processing';
}
......@@ -786,6 +825,15 @@ function ctools_js_load($js) {
return 0;
}
/**
* Provides the default value for %ctools_js.
*
* This allows drupal_valid_path() to work with %ctools_js.
*/
function ctools_js_to_arg($arg) {
return empty($arg) || $arg == '%' ? 'nojs' : $arg;
}
/**
* Menu _load hook.
*
......@@ -905,11 +953,25 @@ function ctools_block_list_alter(&$blocks) {
}
/**
* Implement hook_modules_enabled to clear static caches for detecting new plugins
* Implements hook_modules_enabled().
*
* Clear caches for detecting new plugins.
*/
function ctools_modules_enabled($modules) {
ctools_include('plugins');
ctools_get_plugins_reset();
cache_clear_all('ctools_plugin_files:', 'cache', TRUE);
}
/**
* Implements hook_modules_disabled().
*
* Clear caches for removing disabled plugins.
*/
function ctools_modules_disabled($modules) {
ctools_include('plugins');
ctools_get_plugins_reset();
cache_clear_all('ctools_plugin_files:', 'cache', TRUE);
}
/**
......
......@@ -2,11 +2,12 @@ name = Custom rulesets
description = Create custom, exportable, reusable access rulesets for applications like Panels.
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
name = Chaos Tools (CTools) AJAX Example
description = Shows how to use the power of Chaos AJAX.
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
core = 7.x
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -2,11 +2,12 @@ name = Custom content panes
description = Create custom, exportable, reusable content panes for applications like Panels.
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
name = Chaos Tools (CTools) Plugin Example
description = Shows how an external module can provide ctools plugins (for Panels, etc.).
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
dependencies[] = panels
dependencies[] = page_manager
dependencies[] = advanced_help
core = 7.x
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -244,6 +244,7 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) {
* The content as rendered by the plugin. This content should be an array
* with the following possible keys:
* - title: The safe to render title of the content.
* - title_heading: The title heading.
* - content: The safe to render HTML content.
* - links: An array of links associated with the content suitable for
* theme('links').
......@@ -299,6 +300,7 @@ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $arg
$keywords['%title'] = empty($content->title) ? '' : $content->title;
$content->original_title = $keywords['%title'];
$content->title = $conf['override_title_text'];
$content->title_heading = isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2';
}
if (!empty($content->title)) {
......@@ -504,8 +506,26 @@ function ctools_content_configure_form_defaults($form, &$form_state) {
'#size' => 35,
'#id' => 'override-title-textfield',
'#dependency' => array('override-title-checkbox' => array(1)),
'#dependency_type' => 'disable',
'#dependency_type' => 'hidden',
);
$form['override_title_heading'] = array(
'#type' => 'select',
'#default_value' => isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2',
'#options' => array(
'h1' => t('h1'),
'h2' => t('h2'),
'h3' => t('h3'),
'h4' => t('h4'),
'h5' => t('h5'),
'h6' => t('h6'),
'div' => t('div'),
'span' => t('span'),
),
'#id' => 'override-title-heading',
'#dependency' => array('override-title-checkbox' => array(1)),
'#dependency_type' => 'hidden',
);
$form['aligner_stop'] = array(
'#markup' => '</div>',
);
......@@ -536,6 +556,7 @@ function ctools_content_configure_form_defaults_submit(&$form, &$form_state) {
if (isset($form_state['values']['override_title'])) {
$form_state['conf']['override_title'] = $form_state['values']['override_title'];
$form_state['conf']['override_title_text'] = $form_state['values']['override_title_text'];
$form_state['conf']['override_title_heading'] = $form_state['values']['override_title_heading'];
}
}
......
......@@ -27,6 +27,9 @@ function ctools_content_autocomplete_entity($type, $string = '') {
if ($string != '') {
global $user;
$entity_info = entity_get_info($type);
if ($type == 'node') {
$entity_info['entity keys']['bundle field'] = 'type';
}
// We must query all ids, because if every one of the 10 don't have access
// the user may never be able to autocomplete a node title.
......@@ -56,6 +59,7 @@ function ctools_content_autocomplete_entity($type, $string = '') {
}
else {
$matches[$result['label'] . " [id: $entity_id]"] = '<span class="autocomplete_title">' . check_plain($result['label']) . '</span>';
$matches[$result['label'] . " [id: $entity_id]"] .= isset($result['bundle field']) ? ' <span class="autocomplete_bundle">(' . check_plain($result['bundle field']) . ')</span>' : '';
}
}
......@@ -83,6 +87,11 @@ function _ctools_buildQuery($entity_type, $entity_info, $match = NULL, $match_op
$query->fields($base_table, array($entity_info['entity keys']['label']));
}
// Add bundle field to the query, if it exists.
if (isset($entity_info['entity keys']['bundle field'])) {
$query->fields($base_table, array($entity_info['entity keys']['bundle field']));
}
// Add a generic entity access tag to the query.
$query->addTag('ctools');
......@@ -131,6 +140,7 @@ function _ctools_getReferencableEntities($entity_type, $entity_info, $match = NU
foreach ($results as $record) {
$options[$record->{$entity_info['entity keys']['id']}] = array(
'label' => isset($entity_info['entity keys']['label']) ? check_plain($record->{$entity_info['entity keys']['label']}) : $record->{$entity_info['entity keys']['id']},
'bundle field' => isset($entity_info['entity keys']['bundle field']) ? check_plain($record->{$entity_info['entity keys']['bundle field']}) : '',
);
}
}
......
......@@ -416,13 +416,14 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
ctools_cache_operation($mechanism, $cache_key, 'finalize', $object);
// Very irritating way to update the form for our contexts.
$arg_form_state = array(
$arg_form_state = form_state_defaults() + array(
'values' => array(),
'programmed' => FALSE,
'process_input' => FALSE,
'complete form' => array(),
);
$rel_form_state = $arg_form_state;
$arg_form = array(
'#post' => array(),
'#programmed' => FALSE,
......@@ -469,7 +470,7 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
$output = array();
if (!empty($available_relationships)) {
ctools_context_add_item_table_buttons('relationship', $mechanism, $rel_form, $available_relationships);
$rel_form = form_builder('dummy_form_id', $rel_form, $arg_form_state);
$rel_form = form_builder('dummy_form_id', $rel_form, $rel_form_state);
$output[] = ajax_command_replace('div#ctools-relationships-table div.buttons', drupal_render($rel_form));
}
......@@ -591,8 +592,16 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k
$output = array();
$output[] = ctools_modal_command_dismiss();
$arg_form_state = form_state_defaults() + array(
'values' => array(),
'process_input' => FALSE,
'complete form' => array(),
);
$arg_form = array(
'#post' => array(),
'#parents' => array(),
'#array_parents' => array(),
'#programmed' => FALSE,
'#tree' => FALSE,
);
......
......@@ -169,7 +169,12 @@ class ctools_context_required {
function select($contexts, $context) {
if (!is_array($contexts)) {
$contexts = array($contexts);
if (is_object($contexts) && $contexts instanceof ctools_context) {
$contexts = array($contexts->id => $contexts);
}
else {
$contexts = array($contexts);
}
}
// If we had requested a $context but that $context doesn't exist
......@@ -328,13 +333,15 @@ function _ctools_context_selector($contexts, $required, $default, $num = 0) {
$title = $num ? t('Context %count', array('%count' => $num)) : t('Context');
}
return array(
$form = array(
'#type' => 'select',
'#options' => $options,
'#title' => $title,
'#default_value' => $default,
);
}
return $form;
}
/**
......@@ -1587,7 +1594,9 @@ function ctools_access_add_restrictions($settings, $contexts) {
$required_context = isset($plugin['required context']) ? $plugin['required context'] : array();
$context = isset($test['context']) ? $test['context'] : array();
$contexts = ctools_context_select($contexts, $required_context, $context);
$function($test['settings'], $contexts);
if ($contexts !== FALSE) {
$function($test['settings'], $contexts);
}
}
}
}
<?php
/**
* @file
* Custom cache implementation for the CTools CSS cache.
*/
class CToolsCssCache implements DrupalCacheInterface {
/**
* {@inheritdoc}
*/
public function clear($cid = NULL, $wildcard = FALSE) {
// Only clear the caches if the wildcard is set, this ensures that the cache
// is only cleared when the full caches are cleared manually (eg by invoking
// drupal_flush_all_caches()), and not on a cron run.
// @see drupal_flush_all_caches()
// @see system_cron()
if ($wildcard) {
ctools_include('css');
ctools_css_flush_caches();
}
}
/**
* {@inheritdoc}
*/
public function get($cid) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getMultiple(&$cids) {
return array();
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function set($cid, $data, $expire = CACHE_PERMANENT) {
}
}
......@@ -79,6 +79,19 @@ function ctools_fields_get_field_formatter_settings_form($field, $formatter_type
$instance = ctools_fields_fake_field_instance($field['field_name'], $view_mode, $formatter_type, $conf['formatter_settings']);
$settings_form = $function($field, $instance, $view_mode, $form, $form_state);
if ($settings_form) {
// Allow other modules to alter the formatter settings form.
$context = array(
'module' => $formatter['module'],
'formatter' => $formatter,
'field' => $field,
'instance' => $instance,
'view_mode' => $view_mode,
'form' => $form,
'form_state' => $form_state,
);
drupal_alter('field_formatter_settings_form', $settings_form, $context);
$settings_form['#tree'] = TRUE;
$form['ctools_field_list']['#value'][] = $field;
$form += $settings_form;
}
......
......@@ -187,7 +187,7 @@ function ctools_modal_text_button($text, $dest, $alt, $class = '') {
/**
* Wrap a form so that we can use it properly with AJAX. Essentially if the
* form wishes to render, it automatically does that, otherwise it returns
* so we can see submission results.
* the render array so we can see submission results.
* @param array $form
* An associative array containing the structure of the form.
......@@ -201,9 +201,9 @@ function ctools_modal_text_button($text, $dest, $alt, $class = '') {
* is set, this will use ctools_modal_form_render so it will be
* a $command object suitable for ajax_render already.
*
* The return will be NULL if the form was successfully submitted unless
* you specifically set re_render = TRUE. If ajax is set the
* form will never be redirected.
* If the form was not rendered, the raw render array will be returned.
*
* If ajax is set the form will never be redirected.
*/
function ctools_modal_form_wrapper($form_id, &$form_state) {
// Since this will run again on form rebuild while still in the modal, prevent
......@@ -220,7 +220,7 @@ function ctools_modal_form_wrapper($form_id, &$form_state) {
);
$output = drupal_build_form($form_id, $form_state);
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
return ctools_modal_form_render($form_state, $output);
}
......
......@@ -214,7 +214,12 @@ function ctools_plugin_api_get_hook($owner, $api) {
function ctools_get_plugins($module, $type, $id = NULL) {
// Store local caches of plugins and plugin info so we don't have to do full
// lookups everytime.
$plugins = &drupal_static('ctools_plugins', array());
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array());
}
$plugins = &$drupal_static_fast['plugins'];
$info = ctools_plugin_get_plugin_type_info();
// Bail out noisily if an invalid module/type combination is requested.
......@@ -423,25 +428,15 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
// store static of plugin arrays for reference because they can't be reincluded.
static $plugin_arrays = array();
// If we're being asked for all plugins of a type, skip any caching
// we may have done because this is an admin task and it's ok to
// spend the extra time.
if (!isset($filename)) {
$all_files[$info['module']][$info['type']] = NULL;
}
if (!isset($all_files[$info['module']][$info['type']])) {
// If a filename was set, we will try to load our list of files from
// cache. This is considered normal operation and we try to reduce
// the time spent finding files.
if (isset($filename)) {
$cache = cache_get("ctools_plugin_files:$info[module]:$info[type]");
if ($cache) {
$all_files[$info['module']][$info['type']] = $cache->data;
}
}
if (!isset($all_files[$info['module']][$info['type']])) {
$cache = cache_get("ctools_plugin_files:$info[module]:$info[type]");
if ($cache) {
$all_files[$info['module']][$info['type']] = $cache->data;
}
// Do not attempt any file scan even if the cached entry was empty.
// A NULL entry here would mean the plugin just does not exists, and we
// cannot afford to run file scan on production sites normal run.
elseif (!isset($all_files[$info['module']][$info['type']])) {
$all_files[$info['module']][$info['type']] = array();
// Load all our plugins.
$directories = ctools_plugin_get_directories($info);
......@@ -683,7 +678,7 @@ function ctools_plugin_process($info, $module, $identifier, $path, $file = NULL,
if (!function_exists($function)) {
return NULL;
}
$result = $function();
$result = $function($info);
if (!isset($result) || !is_array($result)) {
return NULL;
}
......
......@@ -274,7 +274,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
if (!empty($form_info['show trail'])) {
ctools_add_css('wizard');
$form['ctools_trail'] = array(
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail)),
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail, 'form_info' => $form_info)),
'#weight' => -1000,
);
}
......
......@@ -7,19 +7,16 @@
function ctools_wizard_theme(&$theme) {
$theme['ctools_wizard_trail'] = array(
'variables' => array('trail' => NULL),
'variables' => array('trail' => NULL, 'form_info' => NULL, 'divider' => ' » '),
'file' => 'includes/wizard.theme.inc',
);
}
/**
* Themable display of the 'breadcrumb' trail to show the order of the
* forms.
* Themable display of the 'breadcrumb' trail to show the order of the forms.
*/
function theme_ctools_wizard_trail($vars) {
$trail = $vars['trail'];
if (!empty($trail)) {
return '<div class="wizard-trail">' . implode(' » ', $trail) . '</div>';
if (!empty($vars['trail'])) {
return '<div class="wizard-trail">' . implode($vars['divider'], $vars['trail']) . '</div>';
}
}
......@@ -40,7 +40,7 @@
Drupal.CTools.dependent.autoAttach = function() {
// Clear active bindings and triggers.
for (i in Drupal.CTools.dependent.activeTriggers) {
$(Drupal.CTools.dependent.activeTriggers[i]).unbind('change');
$(Drupal.CTools.dependent.activeTriggers[i]).unbind('change.ctools-dependent');
}
Drupal.CTools.dependent.activeTriggers = [];
Drupal.CTools.dependent.activeBindings = {};
......@@ -194,7 +194,7 @@
}
}
$(trigger_id).change(function() {
$(trigger_id).bind('change.ctools-dependent', function() {
// Trigger the internal change function
// the attr('id') is used because closures are more confusing
changeTrigger(trigger_id, bind_id);
......@@ -215,7 +215,7 @@
// is a sort of hacked one that's faster but much less flexible.
$("select.ctools-master-dependent")
.once('ctools-dependent')
.change(function() {
.bind('change.ctools-dependent', function() {
var val = $(this).val();
if (val == 'all') {
$('.ctools-dependent-all').show(0);
......@@ -225,7 +225,7 @@
$('.ctools-dependent-' + val).show(0);
}
})
.trigger('change');
.trigger('change.ctools-dependent');
}
}
})(jQuery);
......@@ -379,9 +379,9 @@
css.filter = 'alpha(opacity=' + (100 * css.opacity) + ')';
content.hide();
// if we already ahve a modalContent, remove it
if ( $('#modalBackdrop')) $('#modalBackdrop').remove();
if ( $('#modalContent')) $('#modalContent').remove();
// If we already have modalContent, remove it.
if ($('#modalBackdrop').length) $('#modalBackdrop').remove();
if ($('#modalContent').length) $('#modalContent').remove();
// position code lifted from http://www.quirksmode.org/viewport/compatibility.html
if (self.pageYOffset) { // all except Explorer
......@@ -421,12 +421,17 @@
return true;
}
}
if( $(target).filter('*:visible').parents('#modalContent').size()) {
// allow the event only if target is a visible child node of #modalContent
if ($(target).is('#modalContent, body') || $(target).filter('*:visible').parents('#modalContent').length) {
// Allow the event only if target is a visible child node
// of #modalContent.
return true;
}
if ( $('#modalContent')) $('#modalContent').get(0).focus();
return false;
else {
$('#modalContent').focus();
}
event.preventDefault();
};
$('body').bind( 'focus', modalEventHandler );
$('body').bind( 'keypress', modalEventHandler );
......@@ -477,6 +482,16 @@
// Move and resize the modalBackdrop and modalContent on resize of the window
modalContentResize = function(){
// position code lifted from http://www.quirksmode.org/viewport/compatibility.html
if (self.pageYOffset) { // all except Explorer
var wt = self.pageYOffset;
} else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
var wt = document.documentElement.scrollTop;
} else if (document.body) { // all other Explorers
var wt = document.body.scrollTop;
}
// Get our heights
var docHeight = $(document).height();
var docWidth = $(document).width();
......@@ -486,7 +501,7 @@
// Get where we should move content to
var modalContent = $('#modalContent');
var mdcTop = ( winHeight / 2 ) - ( modalContent.outerHeight() / 2);
var mdcTop = wt + ( winHeight / 2 ) - ( modalContent.outerHeight() / 2);
var mdcLeft = ( winWidth / 2 ) - ( modalContent.outerWidth() / 2);
// Apply the changes
......
......@@ -95,6 +95,7 @@ function page_manager_list_page($js = NULL) {
$header = array(
array('data' => t('Type'), 'class' => array('page-manager-page-type')),
array('data' => t('Module'), 'class' => array('page-manager-page-module')),
array('data' => t('Name'), 'class' => array('page-manager-page-name')),
array('data' => t('Title'), 'class' => array('page-manager-page-title')),
array('data' => t('Path'), 'class' => array('page-manager-page-path')),
......@@ -175,9 +176,18 @@ function page_manager_get_pages($tasks, &$pages, $task_id = NULL) {
$row = array('data' => array(), 'class' => $class, 'title' => strip_tags($task['admin description']));
$type = isset($task['admin type']) ? $task['admin type'] : t('System');
if (isset($task['module'])) {
$module = $task['module'];
}
elseif (isset($task['subtask']->export_module)) {
$module = $task['subtask']->export_module;
}
else {
$module = '';
}
$pages['types'][$type] = $type;
$row['data']['type'] = array('data' => $type, 'class' => array('page-manager-page-type'));
$row['data']['module'] = array('data' => $module, 'class' => array('page-manager-page-module'));
$row['data']['name'] = array('data' => $task_name, 'class' => array('page-manager-page-name'));
$row['data']['title'] = array('data' => $task['admin title'], 'class' => array('page-manager-page-title'));
$row['data']['path'] = array('data' => $visible_path, 'class' => array('page-manager-page-path'));
......@@ -401,7 +411,7 @@ function page_manager_list_pages_form_submit(&$form, &$form_state) {
* Render the edit page for a a page, custom or system.
*/
function page_manager_edit_page($page) {
drupal_set_title($page->subtask['admin title']);
drupal_set_title($page->subtask['admin title'], PASS_THROUGH);
// Provide and process the save page form before anything else.
$form_state = array('page' => &$page);
$built_form = drupal_build_form('page_manager_save_page_form', $form_state);
......@@ -464,7 +474,7 @@ function page_manager_edit_page_operation() {
return;
}
drupal_set_title($page->subtask['admin title']);
drupal_set_title($page->subtask['admin title'], PASS_THROUGH);
return $output;
}
......@@ -577,8 +587,8 @@ function page_manager_get_operations($page, $operations = NULL) {
),
);
// Restrict variant import to users who can already execute arbitrary PHP
if (user_access('use PHP for settings')) {
// Restrict variant import due to security implications.
if (user_access('use ctools import')) {
$result['actions']['children']['import'] = array(
'title' => t('Import variant'),
'description' => t('Add a new variant to this page from code exported from another page.'),
......@@ -1308,6 +1318,7 @@ function page_manager_handler_add_submit(&$form, &$form_state) {
else {
$handler->conf['title'] = $plugin['title'];
}
$handler->conf['name'] = $form_state['values']['name'];
$cache->new_handler = $handler;
// Figure out which forms to present them with
......@@ -1398,6 +1409,21 @@ function page_manager_handler_add_form($form, $form_state, $features = array())
'#title' => t('Title'),
'#description' => t('Administrative title of this variant. If you leave blank it will be automatically assigned.'),
);
$form['name'] = array(
'#type' => 'machine_name',
'#title' => t('Machine name'),
'#required' => FALSE,
'#description' => t("A unique machine-readable name for this variant. It must only contain lowercase letters, numbers, and underscores. This name will be used when exporting the variant. If left empty the variant's name will be used instead."),
'#size' => 32,
'#maxlength' => 32,
'#machine_name' => array(
'exists' => 'page_manager_handler_check_machine_name',
'source' => array('title'),
),
'#field_prefix' => '<span dir="ltr">' . $task['name'] . '__',
'#field_suffix' => '</span>&lrm;',
);
}
$form['handler'] = array(
......@@ -1436,6 +1462,15 @@ function page_manager_handler_add_form($form, $form_state, $features = array())
return $form;
}
/*
* Check if handler's machine-name is unique
*/
function page_manager_handler_check_machine_name($name, $element, $form_state) {
$name = $form_state['task']['name'] . '__' . $name;
return count(ctools_export_load_object('page_manager_handlers', 'names', array($name)));
}
/**
* Rearrange the order of variants.
*/
......@@ -1446,15 +1481,16 @@ function page_manager_handler_import($form, &$form_state) {
'#description' => t('Enter the name of the new variant.'),
);
if (user_access('use PHP for settings')) {
if (user_access('use ctools import')) {
$form['object'] = array(
'#type' => 'textarea',
'#title' => t('Paste variant code here'),
'#rows' => 15,
);
}
// Users ordinarily can't get here without the PHP block visibility perm.
// In case they somehow do, though, disable the form widget for extra safety.
// Users ordinarily can't get here without the 'import' permission, due to
// security implications. In case they somehow do, though, disable the form
// widget for extra safety.
else {
$form['shoveoff'] = array(
'#markup' => '<div>' . t('You do not have sufficient permissions to perform this action.') . '</div>',
......@@ -1468,7 +1504,7 @@ function page_manager_handler_import($form, &$form_state) {
* Make sure that an import actually provides a handler.
*/
function page_manager_handler_import_validate($form, &$form_state) {
if (!user_access('use PHP for settings')) {
if (!user_access('use ctools import')) {
form_error($form['shoveoff'], t('You account permissions do not permit you to import.'));
return;
}
......
......@@ -3,10 +3,11 @@ description = Provides a UI and API to manage pages within the site.
core = 7.x
dependencies[] = ctools
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -213,6 +213,30 @@ function page_manager_menu_alter(&$items) {
}
}
// Override the core node revisions display to use the configured Page
// display handler.
if (!variable_get('page_manager_node_view_disabled', TRUE) && isset($items['node/%node/revisions/%/view'])) {
// Abstract the basic settings.
$item = array(
// Handle the page arguments.
'load arguments' => array(3),
'page arguments' => array(1, TRUE),
// Replace the normal node_show call with Page Manager's node view.
'page callback' => 'page_manager_node_view_page',
// Provide the correct path to the Page Manager file.
'file' => 'node_view.inc',
'file path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks',
);
// Re-build the menu item using the normal values from node.module.
$items['node/%node/revisions/%/view'] = array(
'title' => 'Revisions',
'access callback' => '_node_revision_access',
'access arguments' => array(1),
) + $item;
}
return $items;
}
......@@ -416,16 +440,17 @@ function page_manager_cache_load($task_name) {
*/
function page_manager_handler_get_name($task_name, $handlers, $handler) {
$base = str_replace('-', '_', $task_name);
// Generate a unique name. Unlike most named objects, we don't let people choose
// names for task handlers because they mostly don't make sense.
$base .= '_' . $handler->handler;
// Once we have a base, check to see if it is used. If it is, start counting up.
$name = $base;
$count = 1;
// If taken
while (isset($handlers[$name])) {
$name = $base . '_' . ++$count;
// Optional machine name.
if (!empty($handler->conf['name'])) {
$name = $base . '__' . $handler->conf['name'];
}
// If no machine name was provided, generate a unique name.
else {
$base .= '__' . $handler->handler;
// Use the ctools uuid generator to generate a unique id.
$name = $base . '_' . ctools_uuid_generate();
}
return $name;
......
......@@ -224,6 +224,23 @@ function page_manager_http_response_edit_settings($form, &$form_state) {
'#description' => t('Administrative title of this variant.'),
);
$name = isset($conf['name']) ? $conf['name'] : FALSE;
$form['name'] = array(
'#type' => 'machine_name',
'#title' => t('Machine name'),
'#required' => FALSE,
'#default_value' => $name,
'#description' => t("A unique machine-readable name for this variant. It must only contain lowercase letters, numbers, and underscores. This name will be used when exporting the variant. If left empty the variant's name will be used instead."),
'#size' => 32,
'#maxlength' => 32,
'#machine_name' => array(
'exists' => 'page_manager_handler_check_machine_name',
'source' => array('title'),
),
'#field_prefix' => '<span dir="ltr">' . $form_state['task_name'] . '__',
'#field_suffix' => '</span>&lrm;',
);
$form['code'] = array(
'#title' => t('Response code'),
'#type' => 'select',
......@@ -244,7 +261,19 @@ function page_manager_http_response_edit_settings($form, &$form_state) {
}
function page_manager_http_response_edit_settings_submit($form, &$form_state) {
$machine_name = $form_state['handler']->name;
$name = $form_state['task_id'] . '__' . $form_state['values']['name'];
// If new name doesn't equal machine name, we need to update and redirect.
if ($machine_name !== $name) {
$form_state['new trail'] = $form_state['trail'];
$delta = array_search($machine_name, $form_state['new trail']);
$form_state['new trail'][$delta] = $name;
$form_state['handler']->name = $name;
}
$form_state['handler']->conf['title'] = $form_state['values']['title'];
$form_state['handler']->conf['name'] = $form_state['values']['name'];
$form_state['handler']->conf['code'] = $form_state['values']['code'];
$form_state['handler']->conf['destination'] = $form_state['values']['destination'];
}
......
......@@ -67,7 +67,7 @@ function page_manager_comment_reply_page($node, $pid = NULL){
}
$output = ctools_context_handler_render($task, '', $contexts, array($node, $pid));
if ($output != FALSE) {
if ($output !== FALSE) {
return $output;
}
......
......@@ -126,7 +126,7 @@ function page_manager_node_add($type) {
'language' => LANGUAGE_NONE,
);
drupal_set_title(t('Create @name', array('@name' => $types[$type]->name)));
drupal_set_title(t('Create @name', array('@name' => $types[$type]->name)), PASS_THROUGH);
return page_manager_node_edit($node);
}
......
......@@ -78,6 +78,10 @@ function page_manager_node_view_menu_alter(&$items, $task) {
* node view, which is node_page_view().
*/
function page_manager_node_view_page($node) {
// Prep the node to be displayed so all of the regular hooks are triggered.
// Also save the output for later, in case it is needed.
$default_output = node_page_view($node);
// Load my task plugin
$task = page_manager_get_task('node_view');
......@@ -85,32 +89,26 @@ function page_manager_node_view_page($node) {
ctools_include('context');
ctools_include('context-task-handler');
// We need to mimic Drupal's behavior of setting the node title here.
drupal_set_title($node->title);
$uri = entity_uri('node', $node);
// Set the node path as the canonical URL to prevent duplicate content.
drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
// Set the non-aliased path as a default shortlink.
drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
// Load all contexts.
$contexts = ctools_context_handler_get_task_contexts($task, '', array($node));
// Build the full output using the configured CTools plugin.
$output = ctools_context_handler_render($task, '', $contexts, array($node->nid));
if ($output != FALSE) {
if ($output !== FALSE) {
node_tag_new($node);
return $output;
}
$function = 'node_page_view';
// Try loading an override plugin.
foreach (module_implements('page_manager_override') as $module) {
$call = $module . '_page_manager_override';
if (($rc = $call('node_view')) && function_exists($rc)) {
$function = $rc;
break;
return $rc($node);
}
}
// Otherwise, fall back.
return $function($node);
// Otherwise, fall back to the default output generated by node_page_view().
return $default_output;
}
/**
......
......@@ -38,7 +38,7 @@ function page_manager_page_menu(&$items, $task) {
) + $base;
if ($access_callback == 'user_access') {
$items['admin/structure/pages/import']['access callback'] = 'ctools_access_multiperm';
$items['admin/structure/pages/import']['access arguments'][] = 'use PHP for settings';
$items['admin/structure/pages/import']['access arguments'][] = 'use ctools import';
}
// AJAX callbacks for argument modal.
......@@ -769,12 +769,12 @@ function page_manager_page_form_menu($form, &$form_state) {
);
}
$form['menu']['parent']['weight'] = array(
'#title' => t('Tab weight'),
'#title' => t('Parent weight'),
'#type' => 'textfield',
'#default_value' => $menu['parent']['weight'],
'#size' => 5,
'#description' => t('If the parent menu item is a tab, enter the weight of the tab. The lower the number, the more to the left it will be.'),
'#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('tab')),
'#description' => t('Enter the weight of the parent item. The lower the number, the more to the left it will be.'),
'#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('tab', 'normal')),
'#dependency_count' => 2,
);
......
......@@ -97,8 +97,8 @@ function page_manager_user_edit_page($account, $category = 'account') {
$output = ctools_context_handler_render($task, '', $contexts, array($account->uid));
if (is_array($output)) {
$output = drupal_render($output);
}
if ($output != FALSE) {
}
if ($output !== FALSE) {
return $output;
}
......@@ -119,7 +119,7 @@ function page_manager_user_edit_page($account, $category = 'account') {
//call drupal_build_form.
$form_state = array();
$form_id = 'user_profile_form';
$args = array($account);
$args = array($account, $category);
$form_state['build_info']['args'] = $args;
form_load_include($form_state, 'inc', 'user', 'user.pages');
$output = drupal_build_form($form_id, $form_state);
......
......@@ -81,7 +81,7 @@ function page_manager_user_view_page($account) {
user_build_content($account);
$output = ctools_context_handler_render($task, '', $contexts, array($account->uid));
if ($output != FALSE) {
if ($output !== FALSE) {
return $output;
}
......
<?php
/**
* @file
* Plugin to provide access control based on whether a node belongs to a book.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
if (module_exists('book')) {
$plugin = array(
'title' => t("Book: node is in a book"),
'description' => t('Control access based upon a node belonging to a book.'),
'callback' => 'ctools_book_node_ctools_access_check',
'default' => array('book' => array()),
'settings form' => 'ctools_book_node_ctools_access_settings',
'settings form submit' => 'ctools_book_node_ctools_access_settings_submit',
'summary' => 'ctools_book_node_ctools_access_summary',
'required context' => new ctools_context_required(t('Node'), 'node'),
);
}
/**
* Settings form for the 'by book_node' access plugin.
*/
function ctools_book_node_ctools_access_settings($form, &$form_state, $conf) {
$options = array(
'any' => t('In any book'),
);
$books = book_get_books();
foreach ($books as $bid => $book) {
$options[$bid] = $book['title'];
}
$form['settings']['book'] = array(
'#title' => t('Book'),
'#type' => 'checkboxes',
'#options' => $options,
'#description' => t('Pass only if the node belongs to one of the selected books'),
'#default_value' => $conf['book'],
'#required' => TRUE,
);
return $form;
}
/**
* Check for access.
*/
function ctools_book_node_ctools_access_check($conf, $context) {
// As far as I know there should always be a context at this point, but this
// is safe.
if (empty($context) || empty($context->data) || empty($context->data->book)) {
return FALSE;
}
if ($conf['book']['any']) {
return !empty($context->data->book);
}
foreach ($conf['book'] as $bid => $value) {
if ($bid == 'any') {
continue;
}
if ($value && ($bid == $context->data->book['bid'])) {
return TRUE;
}
}
return FALSE;
}
/**
* Provide a summary description based upon the checked node_languages.
*/
function ctools_book_node_ctools_access_summary($conf, $context) {
if ($conf['book']['any']) {
return t('@identifier belongs to a book', array('@identifier' => $context->identifier));
}
$books = array();
foreach ($conf['book'] as $bid => $value) {
if ($value) {
$node = node_load($bid);
$books[] = $node->title;
}
}
if (count($books) == 1) {
return t('@identifier belongs to the book "@book"', array('@book' => $books[0], '@identifier' => $context->identifier));
}
return t('@identifier belongs in multiple books', array('@identifier' => $context->identifier));
}
......@@ -16,8 +16,8 @@ $plugin = array(
'get child' => 'ctools_entity_field_value_ctools_access_get_child',
'get children' => 'ctools_entity_field_value_ctools_access_get_children',
);
function ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $child) {
function ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $child) {
$plugins = &drupal_static(__FUNCTION__, array());
if (empty($plugins[$parent . ':' . $child])) {
list($entity_type, $bundle_type, $field_name) = explode(':', $child);
......@@ -48,7 +48,6 @@ function ctools_entity_field_value_ctools_access_get_children($plugin, $parent)
}
function _ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $entity_type, $bundle_type, $field_name, $entity = NULL, $bundle = NULL, $field = NULL) {
// check that the entity, bundle and field arrays have a value.
// If not, load theme using machine names.
if (empty($entity)) {
......@@ -86,12 +85,34 @@ function ctools_entity_field_value_ctools_access_settings($form, &$form_state, $
$instance = $instances[$field_name];
$field = field_info_field_by_id($instance['field_id']);
foreach ($field['columns'] as $column => $attributes) {
$columns[] = _field_sql_storage_columnname($field_name, $column);
$columns[$column] = _field_sql_storage_columnname($field_name, $column);
}
ctools_include('fields');
$entity = (object)array(
$entity_info['entity keys']['bundle'] => $bundle_type,
);
foreach ($columns as $column => $sql_column) {
if (isset($conf[$sql_column])) {
if (is_array($conf[$sql_column])) {
foreach ($conf[$sql_column] as $delta => $conf_value) {
if (is_numeric($delta)) {
if (is_array($conf_value)) {
$entity->{$field_name}[LANGUAGE_NONE][$delta][$column] = $conf_value[$column];
}
else {
$entity->{$field_name}[LANGUAGE_NONE][$delta][$column] = $conf_value;
}
}
}
}
else {
$entity->{$field_name}[LANGUAGE_NONE][0][$column] = $conf[$sql_column];
}
}
}
$form['#parents'] = array('settings');
$langcode = field_valid_language(NULL);
$form['settings'] += (array) ctools_field_invoke_field($instance, 'form', $entity_type, $entity, $form, $form_state, array('default' => TRUE, 'language' => $langcode));
// weight is really not important once this is populated and will only interfere with the form layout.
......@@ -99,26 +120,9 @@ function ctools_entity_field_value_ctools_access_settings($form, &$form_state, $
unset($form['settings'][$element]['#weight']);
}
// Need more logic here to handle compound fields.
foreach ($columns as $column) {
if (isset($conf[$column]) && is_array($conf[$column])) {
foreach ($conf[$column] as $delta => $conf_value) {
if (is_numeric($delta) && is_array($conf_value)) {
$form['settings'][$field_name][LANGUAGE_NONE][$delta]['value']['#default_value'] = $conf_value['value'];
}
}
}
else {
$form['settings'][$field_name][LANGUAGE_NONE]['#default_value'] = $conf[$column];
}
}
return $form;
}
/**
* Compress the entity bundles allowed to the minimum.
*/
function ctools_entity_field_value_ctools_access_settings_submit($form, &$form_state) {
$plugin = $form_state['plugin'];
list($parent, $entity_type, $bundle_type, $field_name) = explode(':', $plugin['name']);
......@@ -128,18 +132,77 @@ function ctools_entity_field_value_ctools_access_settings_submit($form, &$form_s
$instance = $instances[$field_name];
$field = field_info_field_by_id($instance['field_id']);
foreach ($field['columns'] as $column => $attributes) {
$columns[] = _field_sql_storage_columnname($field_name, $column);
$columns[$column] = _field_sql_storage_columnname($field_name, $column);
}
$items = _ctools_entity_field_value_get_proper_form_items($field, $form_state['values']['settings'][$field_name][$langcode], array_keys($columns));
foreach ($columns as $column => $sql_column) {
$column_items = _ctools_entity_field_value_filter_items_by_column($items, $column);
$form_state['values']['settings'][$sql_column] = $column_items;
}
$form_state['values']['settings'][$field_name][$langcode] = $items;
}
function _ctools_entity_field_value_get_proper_form_items($field, $form_items, $columns) {
$items = array();
if (!is_array($form_items)) { // Single value item.
foreach ($columns as $column) {
$items[0][$column] = $form_items;
}
return $items;
}
foreach ($form_items as $delta => $value) {
$item = array();
if (is_numeric($delta)) { // Array of field values.
if (!is_array($value)) { // Single value in array.
foreach ($columns as $column) {
$item[$column] = $value;
}
}
else { // Value has colums.
foreach ($columns as $column) {
$item[$column] = isset($value[$column]) ? $value[$column] : '';
}
}
}
$items[] = $item;
}
// Check if $form_items is an array of columns.
$item = array();
$has_columns = FALSE;
foreach ($columns as $column) {
$form_state['values']['settings'][$column] = $form_state['input']['settings'][$field_name][$langcode];
if (isset($form_items[$column])) {
$has_columns = TRUE;
$item[$column] = $form_items[$column];
}
else {
$item[$column] = '';
}
}
if ($has_columns) {
$items[] = $item;
}
// Remove empty values.
$items = _field_filter_items($field, $items);
return $items;
}
function _ctools_entity_field_value_filter_items_by_column($items, $column) {
$column_items = array();
foreach ($items as $delta => $values) {
$column_items[$delta] = isset($values[$column]) ? $values[$column] : '';
}
return $column_items;
}
/**
* Check for access.
*/
function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin) {
if (!isset($context->data)) {
if ((!is_object($context)) || (empty($context->data))) {
// If the context doesn't exist -- for example, a newly added entity
// reference is used as a pane visibility criteria -- we deny access.
return FALSE;
......@@ -166,16 +229,27 @@ function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin)
// Check field value.
foreach ($field_items as $field_value) {
foreach ($field_value as $field_column => $value) {
// Iterate through config values.
foreach ($conf_value_array as $conf_value) {
// Iterate through config values.
foreach ($conf_value_array as $conf_value) {
$match = FALSE;
foreach ($field_value as $field_column => $value) {
// Check access only for stored in config column values.
if (isset($conf_value[$field_column]) && $value == $conf_value[$field_column]) {
return TRUE;
if (isset($conf_value[$field_column])) {
if ($value == $conf_value[$field_column]) {
$match = TRUE;
}
else {
$match = FALSE;
break;
}
}
}
if ($match) {
return TRUE;
}
}
}
return FALSE;
}
}
......@@ -184,7 +258,7 @@ function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin)
function _ctools_entity_field_value_ctools_access_get_conf_field_values($values, $langcode = LANGUAGE_NONE) {
if (!is_array($values) || !isset($values[$langcode])) {
return;
return NULL;
}
$conf_values = array();
......@@ -207,41 +281,130 @@ function ctools_entity_field_value_ctools_access_summary($conf, $context, $plugi
$entity = (object)array(
$entity_info['entity keys']['bundle'] => $bundle_type,
);
$string = '';
$keys = array();
$values = array();
$value_keys = array();
$keyed_elements = array();
foreach ($field['columns'] as $column => $attributes) {
$conf_key = _field_sql_storage_columnname($field_name, $column);
if (count($field['columns']) > 1) {
// Add some sort of handling for compound fields
}
else {
if (isset($conf[$conf_key])) {
$entity->{$field_name}[LANGUAGE_NONE][] = array($column => $conf[$conf_key]);
$keyed_elements["@{$column}_value"] = array();
if (isset($conf[$conf_key])) {
if (is_array($conf[$conf_key])) {
$i = 0;
foreach ($conf[$conf_key] as $conf_value) {
if (!is_array($conf_value)) {
$entity->{$field_name}[LANGUAGE_NONE][$i][$column] = $conf_value;
$keyed_elements["@{$column}_value"][$i] = array('#markup' => $conf_value);
}
elseif (isset($conf_value[$column])) {
$entity->{$field_name}[LANGUAGE_NONE][$i][$column] = $conf_value[$column];
$keyed_elements["@{$column}_value"][$i] = array('#markup' => $conf_value[$column]);
}
$i++;
}
}
else {
$entity->{$field_name}[LANGUAGE_NONE][0][$column] = $conf[$conf_key];
$keyed_elements["@{$column}_value"][0] = array('#markup' => $conf[$conf_key]);
}
}
$string .= " @{$column} equals @{$column}_value";
$keys['@' . $column] = $column;
$values["@{$column}_value"] = $conf[$conf_key];
$value_keys[] = "@{$column}_value";
}
$elements = array();
$items = isset($entity->{$field_name}[LANGUAGE_NONE]) ? $entity->{$field_name}[LANGUAGE_NONE] : array();
$view_mode = 'full';
$null = NULL;
$options = array('language' => LANGUAGE_NONE);
ctools_include('fields');
$display = field_get_display($instance, $view_mode, $entity);
$display = field_get_display($instance, $view_mode, $entity);
if (!isset($display['module'])) {
$display['module'] = $field['module'];
}
if (isset($display['module'])) {
$display['type'] = 'list_default';
$function = $display['module'] . '_field_formatter_view';
$items = isset($entity->{$field_name}[LANGUAGE_NONE]) ? $entity->{$field_name}[LANGUAGE_NONE] : array();
// Choose simple formatter for well known cases.
switch ($display['module']) {
case 'text':
$display['type'] = 'text_default';
break;
case 'list':
$display['type'] = 'list_default';
if ($field['type'] == 'list_boolean') {
$allowed_values = list_allowed_values($field, $instance, $entity_type, $entity);
foreach ($items as $item) {
if (isset($allowed_values[$item['value']])) {
if ($allowed_values[$item['value']] == '') {
$display['type'] = 'list_key';
break;
}
}
else {
$display['type'] = 'list_key';
}
}
}
break;
case 'taxonomy':
$display['type'] = 'taxonomy_term_reference_plain';
break;
case 'entityreference':
$display['type'] = 'entityreference_label';
break;
default :
// Use field instance formatter setting.
break;
}
$function = $display['module'] . '_field_formatter_view';
if (function_exists($function)) {
$elements = $function($entity_type, $entity, $field, $instance, LANGUAGE_NONE, $items, $display);
$entity_group = array(0 => $entity);
$item_group = array(0 => $items);
$instance_group = array(0 => $instance);
field_default_prepare_view($entity_type, $entity_group, $field, $instance_group, LANGUAGE_NONE, $item_group, $display);
$elements = $function($entity_type, $entity, $field, $instance, LANGUAGE_NONE, $item_group[0], $display);
}
$value_keys = array_keys($values);
foreach ($value_keys as $key => $value) {
$values[$value] = isset($elements[$key]['#markup']) ? $elements[$key]['#markup'] : '';
}
if (count($elements) > 0) {
foreach ($field['columns'] as $column => $attributes) {
if (count($field['columns']) == 1) {
$keyed_elements["@{$column}_value"] = $elements;
}
}
}
$values = array_merge($keys, $values);
return t($string, $values);
$values = array();
foreach ($value_keys as $key) {
$output = array();
$elements = $keyed_elements[$key];
if (is_array($elements)) {
foreach ($elements as $element_key => $element) {
if (is_numeric($element_key)) {
$value_str= strip_tags(drupal_render($element));
if (strlen($value_str) > 0) {
$output[] = $value_str;
}
}
}
}
else {
$value_str = strip_tags(drupal_render($elements));
if (strlen($value_str) > 0) {
$output[] = $value_str;
}
}
$value = implode(', ', $output);
if ($value !== '') {
$values[$key] = implode(', ', $output);
}
}
$string = '';
$value_count = count($values);
foreach ($keys as $key_name => $column) {
if (isset($values[$key_name . '_value'])) {
$string .= ($value_count > 1) ? " @{$column} = @{$column}_value" : "@{$column}_value";
}
}
return t('@field is set to "!value"', array('@field' => $instance['label'], '!value' => format_string($string, array_merge($keys, $values))));
}
<?php
/**
* @file
* Plugin to provide access control based upon node comment status.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t("Node: comments are open"),
'description' => t('Control access by the nodes comment status.'),
'callback' => 'ctools_node_comment_ctools_access_check',
'summary' => 'ctools_node_comment_ctools_access_summary',
'required context' => new ctools_context_required(t('Node'), 'node'),
);
/**
* Checks for access.
*/
function ctools_node_comment_ctools_access_check($conf, $context) {
return (!empty($context->data) && $context->data->comment == 2);
}
/**
* Provides a summary description based upon the checked node_status.
*/
function ctools_node_comment_ctools_access_summary($conf, $context) {
return t('Returns true if the nodes comment status is "open".');
}
......@@ -59,7 +59,7 @@ function ctools_string_length_ctools_access_check($conf, $context) {
return $length < $conf['length'];
case '<=':
return $length <= $conf['length'];
case '==':
case '=':
return $length == $conf['length'];
case '!=':
return $length != $conf['length'];
......@@ -68,6 +68,8 @@ function ctools_string_length_ctools_access_check($conf, $context) {
case '>=':
return $length >= $conf['length'];
}
// Invalid Operator sent, return FALSE.
return FALSE;
}
/**
......
......@@ -16,6 +16,10 @@ $plugin = array(
'context' => 'ctools_argument_entity_id_context',
'get child' => 'ctools_argument_entity_id_get_child',
'get children' => 'ctools_argument_entity_id_get_children',
'default' => array(
'entity_id' => ''
),
'placeholder form' => 'ctools_argument_entity_id_ctools_argument_placeholder',
);
function ctools_argument_entity_id_get_child($plugin, $parent, $child) {
......@@ -57,6 +61,18 @@ function ctools_argument_entity_id_context($arg = NULL, $conf = NULL, $empty = F
}
if (!is_numeric($arg)) {
$preg_matches = array();
$match = preg_match('/\[id: (\d+)\]/', $arg, $preg_matches);
if (!$match) {
$match = preg_match('/^id: (\d+)/', $arg, $preg_matches);
}
if ($match) {
$id = $preg_matches[1];
}
if (is_numeric($id)) {
return ctools_context_create('entity:' . $entity_type, $id);
}
return FALSE;
}
......@@ -68,3 +84,59 @@ function ctools_argument_entity_id_context($arg = NULL, $conf = NULL, $empty = F
return ctools_context_create('entity:' . $entity_type, $entity[$arg]);
}
function ctools_argument_entity_id_settings_form(&$form, &$form_state, $conf) {
$plugin = &$form_state['plugin'];
$form['settings']['entity'] = array(
'#title' => t('Enter the title or ID of a @entity entity', array('@entity' => $plugin['keyword'])),
'#type' => 'textfield',
'#maxlength' => 512,
'#autocomplete_path' => 'ctools/autocomplete/' . $plugin['keyword'],
'#weight' => -10,
);
if (!empty($conf['entity_id'])) {
$info = entity_load($plugin['keyword'], array($conf['entity_id']));
$info = $info[$conf['entity_id']];
if ($info) {
$entity = entity_get_info($plugin['keyword']);
$uri = entity_uri($plugin['keyword'], $info);
if (is_array($uri) && $entity['entity keys']['label']) {
$link = l(t("'%title' [%type id %id]", array('%title' => $info->{$entity['entity keys']['label']}, '%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), $uri['path'], array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE));
}
elseif (is_array($uri)) {
$link = l(t("[%type id %id]", array('%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), $uri['path'], array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE));
}
elseif ($entity['entity keys']['label']) {
$link = l(t("'%title' [%type id %id]", array('%title' => $info->{$entity['entity keys']['label']}, '%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), file_create_url($uri), array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE));
}
else {
$link = t("[%type id %id]", array('%type' => $plugin['keyword'], '%id' => $conf['entity_id']));
}
$form['settings']['entity']['#description'] = t('Currently set to !link', array('!link' => $link));
}
}
$form['settings']['entity_id'] = array(
'#type' => 'value',
'#value' => $conf['entity_id'],
);
$form['settings']['entity_type'] = array(
'#type' => 'value',
'#value' => $plugin['keyword'],
);
return $form;
}
function ctools_argument_entity_id_ctools_argument_placeholder($conf) {
$conf = array(
'#title' => t('Enter the title or ID of a @entity entity', array('@entity' => $conf['keyword'])),
'#type' => 'textfield',
'#maxlength' => 512,
'#autocomplete_path' => 'ctools/autocomplete/' . $conf['keyword'],
'#weight' => -10,
);
return $conf;
}
......@@ -148,16 +148,19 @@ function ctools_block_content_type_render($subtype, $conf) {
$block = module_invoke($module, 'block_view', $delta);
if (!empty($info)) {
// Valid PHP function names cannot contain hyphens.
$block_delta = str_replace('-', '_', $delta);
// Allow modules to modify the block before it is viewed, via either
// hook_block_view_alter() or hook_block_view_MODULE_DELTA_alter().
drupal_alter(array('block_view', "block_view_{$module}_{$delta}"), $block, $info);
drupal_alter(array('block_view', "block_view_{$module}_{$block_delta}"), $block, $info);
}
$block = (object) $block;
if (empty($block)) {
return;
}
$block = (object) $block;
$block->module = $module;
$block->delta = $delta;
......
<?php
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'single' => TRUE,
'title' => t('Comment links'),
'icon' => 'icon_comment.png',
'description' => t('Comment links of the referenced comment.'),
'required context' => new ctools_context_required(t('Comment'), 'entity:comment'),
'category' => t('Comment'),
'defaults' => array(
'override_title' => FALSE,
'override_title_text' => '',
'build_mode' => '',
),
);
/**
* Output function for the comment links.
*/
function ctools_comment_links_content_type_render($subtype, $conf, $panel_args, $context) {
if (!empty($context) && empty($context->data)) {
return;
}
$comment = isset($context->data) ? clone($context->data) : NULL;
$block = new stdClass();
$block->module = 'comment';
$block->delta = $comment->cid;
if (empty($comment)) {
$block->delta = 'placeholder';
$block->subject = t('Comment subject.');
$block->content = t('Comment links go here.');
}
else {
$node = node_load($comment->nid);
$block->subject = $comment->subject;
comment_build_content($comment, $node, $conf['build_mode']);
$block->content = $comment->content['links'];
}
return $block;
}
/**
* Returns an edit form for the custom type.
*/
function ctools_comment_links_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$entity = entity_get_info('comment');
$build_mode_options = array();
foreach ($entity['view modes'] as $mode => $option) {
$build_mode_options[$mode] = $option['label'];
}
$form['build_mode'] = array(
'#title' => t('Build mode'),
'#type' => 'select',
'#description' => t('Select a build mode for this comment.'),
'#options' => $build_mode_options,
'#default_value' => $conf['build_mode'],
);
return $form;
}
function ctools_comment_links_content_type_edit_form_submit($form, &$form_state) {
// Copy everything from our defaults.
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
function ctools_comment_links_content_type_admin_title($subtype, $conf, $context) {
return t('"@s" links', array('@s' => $context->identifier));
}
......@@ -118,6 +118,8 @@ function ctools_entity_field_content_type_render($subtype, $conf, $panel_args, $
$field_settings = array(
'label' => $label,
'type' => $conf['formatter'],
// Pass all entity field panes settings to field display settings.
'pane_settings' => $conf,
);
// Get the field output, and the title.
......@@ -127,33 +129,19 @@ function ctools_entity_field_content_type_render($subtype, $conf, $panel_args, $
$all_values = field_get_items($entity_type, $entity, $field_name, $language);
if (!is_array($all_values)) {
$all_values = array();
// Do not render if the field is empty.
return;
}
// Reverse values.
if (isset($conf['delta_reversed']) && $conf['delta_reversed']) {
$all_values = array_reverse($all_values);
$all_values = array_reverse($all_values, TRUE);
}
if (isset($conf['delta_limit'])) {
$delta_limit = $conf['delta_limit'];
$offset = intval($conf['delta_offset']);
$total = count($all_values);
if ($delta_limit == 0) {
$delta_limit = $total - $offset;
}
$new_values = array();
for ($i = 0; $i < $delta_limit; $i++) {
$new_delta = $offset + $i;
if (isset($all_values[$new_delta])) {
$new_values[] = $all_values[$new_delta];
}
}
$all_values = $new_values;
$limit = !empty($conf['delta_limit']) ? $conf['delta_limit'] : NULL;
$all_values = array_slice($all_values, $offset, $limit, TRUE);
}
$clone = clone $entity;
......@@ -263,10 +251,21 @@ function ctools_entity_field_content_type_formatter_styles_submit($form, &$form_
}
/**
* Returns the administrative title for a type.
*/
* Returns the administrative title for a type.
*/
function ctools_entity_field_content_type_admin_title($subtype, $conf, $context) {
list($bundle, $field_name) = explode(':', $subtype);
ctools_include('fields');
return t('"@s" @field', array('@s' => $context->identifier, '@field' => ctools_field_label($field_name)));
if (is_object($context) && isset($context->identifier)) {
$identifier = $context->identifier;
}
else {
$type = 'ctools_entity_field_content_type_admin_title';
$message = t('Context is missing for field: @name', array('@name' => $subtype));
$variables = array($subtype, $conf, $context);
watchdog($type, $message, $variables, $severity = WATCHDOG_NOTICE);
$identifier = t('Unknown');
}
return t('"@s" @field', array('@s' => $identifier, '@field' => ctools_field_label($field_name)));
}
......@@ -11,7 +11,7 @@
* by the system that includes this file.
*/
$plugin = array(
'title' => t('Node'),
'title' => t('Existing node'),
'single' => TRUE,
'defaults' => array(
'nid' => '',
......@@ -20,7 +20,6 @@ $plugin = array(
'identifier' => '',
'build_mode' => 'teaser',
),
'title' => t('Existing node'),
'icon' => 'icon_node.png',
'description' => t('Add a node from your site as content.'),
'category' => t('Custom'),
......
<?php
if (module_exists('comment')) {
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'single' => TRUE,
'title' => t('Comments and comment form.'),
'icon' => 'icon_node.png',
'description' => t('The comments and comment form for the referenced node.'),
'required context' => new ctools_context_required(t('Node'), 'node'),
'category' => t('Node'),
'defaults' => array(
'mode' => variable_get('comment_default_mode', COMMENT_MODE_THREADED),
'comments_per_page' => variable_get('comment_default_per_page', '50'),
),
);
}
/**
* Render the node comments.
*/
function ctools_node_comment_wrapper_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$block = new stdClass();
$block->module = 'comments';
$block->delta = $node->nid;
$renderable = array(
'#theme' => 'comment_wrapper__node_' . $node->type,
'#node' => $node,
'comments' => array(),
'comment_form' => array(),
);
// Add in the comments.
if (($node->comment_count && user_access('access comments')) || user_access('administer comments')) {
$mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED);
$comments_per_page = variable_get('comment_default_per_page_' . $node->type, 50);
if ($cids = comment_get_thread($node, $mode, $comments_per_page)) {
$comments = comment_load_multiple($cids);
comment_prepare_thread($comments);
$build = comment_view_multiple($comments, $node);
$build['pager']['#theme'] = 'pager';
$renderable['comments'] = $build;
}
}
// Stuff in the comment form.
if ($node->comment == COMMENT_NODE_OPEN) {
if (user_access('post comments')) {
$comment = new stdClass();
$comment->nid = $node->nid;
$comment->pid = NULL;
$form_state = array(
'ctools comment alter' => TRUE,
'node' => $node,
'build_info' => array(
'args' => array(
$comment,
),
),
);
$renderable['comment_form'] = drupal_build_form('comment_node_' . $node->type . '_form', $form_state);
}
else if (!empty($conf['anon_links'])) {
$renderable['comment_form'] = theme('comment_post_forbidden', array('node' => $node));
}
}
$block->content = drupal_render($renderable);
return $block;
}
/**
* Returns an edit form for the comment wrapper.
*/
function ctools_node_comment_wrapper_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$form['mode'] = array(
'#type' => 'select',
'#title' => t('Mode'),
'#default_value' => $conf['mode'],
'#options' => _comment_get_modes(),
'#weight' => 1,
);
foreach (_comment_per_page() as $i) {
$options[$i] = t('!a comments per page', array('!a' => $i));
}
$form['comments_per_page'] = array('#type' => 'select',
'#title' => t('Pager'),
'#default_value' => $conf['comments_per_page'],
'#options' => $options,
'#weight' => 3,
);
return $form;
}
/**
* Submit handler for the comment wrapper settings form.
*/
function ctools_node_comment_wrapper_content_type_edit_form_submit($form, &$form_state) {
// Copy everything from our defaults.
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
/**
* Returns the administrative title.
*/
function ctools_node_comment_wrapper_content_type_admin_title($subtype, $conf, $context) {
return t('Comments and comment form');
}
......@@ -20,7 +20,7 @@ $plugin = array(
* Render the custom content type.
*/
function ctools_node_updated_content_type_render($subtype, $conf, $panel_args, $context) {
if (empty($context) || empty($context->data)) {
if (empty($context) || empty($context->data) || empty($context->data->nid)) {
return;
}
......
......@@ -7,18 +7,48 @@
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
* Plugins are described by creating a $plugin array which will be used by the
* system that includes this file.
*/
$plugin = array(
'title' => t('Site name'),
'single' => TRUE,
'icon' => 'icon_page.png',
'description' => t('The name of the site.'),
'description' => t('The name of the site, optionally links to the front page.'),
'category' => t('Page elements'),
'render last' => TRUE,
'defaults' => array(
'linked' => FALSE,
),
);
/**
* Settings form for the Site Name pane.
*/
function ctools_page_site_name_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$form['linked'] = array(
'#title' => t('Linked'),
'#description' => t('Link the site name to the home page.'),
'#type' => 'checkbox',
'#default_value' => isset($conf['linked']) ? $conf['linked'] : FALSE,
);
return $form;
}
/**
* The submit form stores the data in $conf.
*/
function ctools_page_site_name_content_type_edit_form_submit($form, &$form_state) {
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
if (isset($form_state['values'][$key])) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
}
/**
* Output function for the 'page_site_name' content type.
*
......@@ -26,7 +56,13 @@ $plugin = array(
*/
function ctools_page_site_name_content_type_render($subtype, $conf, $panel_args) {
$block = new stdClass();
$block->content = filter_xss_admin(variable_get('site_name', 'Drupal'));
// Optionally link the site name to the homepage.
if (!empty($conf['linked'])) {
$block->content = l($block->content, '<front>');
}
return $block;
}
......@@ -11,7 +11,13 @@ $plugin = array(
'description' => t('Terms related to an existing term; may be child, siblings or top level.'),
'required context' => new ctools_context_required(t('Term'), array('term', 'taxonomy_term')),
'category' => t('Taxonomy term'),
'defaults' => array('title' => '', 'type' => 'child', 'list_type' => 'ul', 'path' => 'taxonomy/term'),
'defaults' => array(
'title' => '',
'type' => 'child',
'include_current_term' => FALSE,
'list_type' => 'ul',
'path' => 'taxonomy/term',
),
);
function ctools_term_list_content_type_render($subtype, $conf, $panel_args, $context) {
......@@ -40,6 +46,9 @@ function ctools_term_list_content_type_render($subtype, $conf, $panel_args, $con
case 'child':
default:
if (!empty($conf['include_current_term'])) {
$terms[] = $term;
}
$terms = taxonomy_get_children($term->tid);
break;
......@@ -49,6 +58,9 @@ function ctools_term_list_content_type_render($subtype, $conf, $panel_args, $con
case 'parent':
$terms = taxonomy_get_parents($term->tid);
if (!empty($conf['include_current_term'])) {
$terms[] = $term;
}
$block->title = count($terms) == 1 ? t('Parent term') : t('Parent terms');
break;
......@@ -116,6 +128,20 @@ function ctools_term_list_content_type_edit_form($form, &$form_state) {
'#suffix' => '</div>',
);
$form['include_current_term'] = array(
'#type' => 'checkbox',
'#title' => t('Include the current term in the list'),
'#default_value' => !empty($conf['include_current_term']),
'#prefix' => '<div class="clearfix no-float">',
'#suffix' => '</div>',
'#states' => array(
'invisible' => array(
':input[name="type"], unique1' => array('!value' => 'child'),
':input[name="type"], unique2' => array('!value' => 'parent'),
),
),
);
$form['list_type'] = array(
'#type' => 'select',
'#title' => t('List type'),
......
<?php
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'single' => TRUE,
'title' => t('Term name'),
'icon' => 'icon_term.png',
'description' => t('The name of this taxonomy term.'),
'required context' => new ctools_context_required(t('Term'), array('term', 'taxonomy_term')),
'category' => t('Taxonomy term'),
'defaults' => array(
'link' => TRUE,
'markup' => 'none',
'id' => '',
'class' => '',
),
);
/**
* Render the custom content type.
*/
function ctools_term_name_content_type_render($subtype, $conf, $panel_args, $context) {
if (empty($context) || empty($context->data)) {
return;
}
// Get a shortcut to the term.
$term = $context->data;
// Load the vocabulary.
$vocab = taxonomy_vocabulary_load($term->vid);
// Generate the title
$content = !empty($conf['link']) ? l($term->name, 'taxonomy/term/' . $term->tid) : check_plain($term->name);
// Build any surrounding markup if so configured
if (isset($conf['markup']) && $conf['markup'] != 'none') {
$markup = '<' . $conf['markup'];
if (!empty($conf['id'])) {
$markup .= ' id="' . $conf['id'] . '"';
}
if (!empty($conf['class'])) {
$markup .= ' class="' . $conf['class'] . '"';
}
$markup .= '>' . $content . '</' . $conf['markup'] . '>' . "\n";
$content = $markup;
}
// Build the content type block.
$block = new stdClass();
$block->module = 'term_name';
$block->title = t('Name');
$block->content = $content;
$block->delta = $term->tid;
return $block;
}
/**
* Returns an edit form for custom type settings.
*/
function ctools_term_name_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$form['markup'] = array(
'#title' => t('Title tag'),
'#type' => 'select',
'#options' => array(
'none' => t('- No tag -'),
'h1' => t('h1'),
'h2' => t('h2'),
'h3' => t('h3'),
'h4' => t('h4'),
'h5' => t('h5'),
'h6' => t('h6'),
'div' => t('div'),
),
'#default_value' => $conf['markup'],
);
$form['id'] = array(
'#title' => t('CSS id to use'),
'#type' => 'textfield',
'#default_value' => $conf['id'],
);
$form['class'] = array(
'#title' => t('CSS class to use'),
'#type' => 'textfield',
'#default_value' => $conf['class'],
);
$form['link'] = array(
'#title' => t('Link to term'),
'#type' => 'checkbox',
'#default_value' => $conf['link'],
'#description' => t('Check here to make the name link to the term page.'),
);
return $form;
}
/**
* Submit handler for the custom type settings form.
*/
function ctools_term_name_content_type_edit_form_submit($form, &$form_state) {
// Copy everything from our defaults.
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
/**
* Returns the administrative title for a type.
*/
function ctools_term_name_content_type_admin_title($subtype, $conf, $context) {
return t('"@s" name', array('@s' => $context->identifier));
}
<?php
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'single' => TRUE,
'title' => t('User links'),
'icon' => 'icon_user.png',
'description' => t('User links of the referenced user.'),
'required context' => new ctools_context_required(t('User'), 'user'),
'category' => t('User'),
'defaults' => array(
'override_title' => FALSE,
'override_title_text' => '',
'build_mode' => '',
),
);
/**
* Output function for the user links.
*/
function ctools_user_links_content_type_render($subtype, $conf, $panel_args, $context) {
if (!empty($context) && empty($context->data)) {
return;
}
$account = clone $context->data;
$block = new stdClass();
$block->module = 'user';
$block->delta = $account->uid;
if (empty($account)) {
$block->delta = 'placeholder';
$block->subject = t('User name.');
$block->content = t('User links go here.');
}
else {
$block->subject = $account->name;
user_build_content($account, $conf['build_mode']);
if (!empty($account->content['links'])) {
$block->content = $account->content['links'];
}
else {
$block->content = '';
}
}
return $block;
}
/**
* Returns an edit form for the custom type.
*/
function ctools_user_links_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$entity = entity_get_info('user');
$build_mode_options = array();
foreach ($entity['view modes'] as $mode => $option) {
$build_mode_options[$mode] = $option['label'];
}
$form['build_mode'] = array(
'#title' => t('Build mode'),
'#type' => 'select',
'#description' => t('Select a build mode for this user.'),
'#options' => $build_mode_options,
'#default_value' => $conf['build_mode'],
);
return $form;
}
function ctools_user_links_content_type_edit_form_submit($form, &$form_state) {
// Copy everything from our defaults.
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
function ctools_user_links_content_type_admin_title($subtype, $conf, $context) {
return t('"@s" links', array('@s' => $context->identifier));
}
......@@ -22,6 +22,7 @@ $plugin = array(
'convert list' => array(
'raw' => t('Raw string'),
'html_safe' => t('HTML-safe string'),
'uppercase_words_html_safe' => t('Uppercase words HTML-safe string'),
),
'convert' => 'ctools_context_string_convert',
'placeholder form' => array(
......@@ -62,6 +63,8 @@ function ctools_context_string_convert($context, $type) {
return $context->data;
case 'html_safe':
return check_plain($context->data);
case 'uppercase_words_html_safe':
return ucwords(str_replace('-', ' ', check_plain($context->data)));
}
}
......
......@@ -88,7 +88,7 @@ function ctools_context_user_settings_form($form, &$form_state) {
if (!empty($conf['uid'])) {
$info = user_load($conf['uid']);
if ($info) {
$form['user']['#description'] = t('Currently set to !link', array('!link' => theme('username', $info)));
$form['user']['#description'] = t('Currently set to !link', array('!link' => theme('username', array('account' => $info))));
}
}
......
......@@ -121,7 +121,7 @@ class ctools_export_ui {
switch ($op) {
case 'import':
return user_access('use PHP for settings');
return user_access('use ctools import');
case 'revert':
return ($item->export_type & EXPORT_IN_DATABASE) && ($item->export_type & EXPORT_IN_CODE);
case 'delete':
......@@ -639,7 +639,7 @@ class ctools_export_ui {
}
function add_page($js, $input, $step = NULL) {
drupal_set_title($this->get_page_title('add'));
drupal_set_title($this->get_page_title('add'), PASS_THROUGH);
// If a step not set, they are trying to create a new item. If a step
// is set, they're in the process of creating an item.
......@@ -676,7 +676,7 @@ class ctools_export_ui {
* Main entry point to edit an item.
*/
function edit_page($js, $input, $item, $step = NULL) {
drupal_set_title($this->get_page_title('edit', $item));
drupal_set_title($this->get_page_title('edit', $item), PASS_THROUGH);
// Check to see if there is a cached item to get if we're using the wizard.
if (!empty($this->plugin['use wizard'])) {
......@@ -712,7 +712,7 @@ class ctools_export_ui {
* Main entry point to clone an item.
*/
function clone_page($js, $input, $original, $step = NULL) {
drupal_set_title($this->get_page_title('clone', $original));
drupal_set_title($this->get_page_title('clone', $original), PASS_THROUGH);
// If a step not set, they are trying to create a new clone. If a step
// is set, they're in the process of cloning an item.
......@@ -1218,7 +1218,7 @@ class ctools_export_ui {
* Page callback to display export information for an exportable item.
*/
function export_page($js, $input, $item) {
drupal_set_title($this->get_page_title('export', $item));
drupal_set_title($this->get_page_title('export', $item), PASS_THROUGH);
return drupal_get_form('ctools_export_form', ctools_export_crud_export($this->plugin['schema'], $item), t('Export'));
}
......@@ -1226,7 +1226,7 @@ class ctools_export_ui {
* Page callback to import information for an exportable item.
*/
function import_page($js, $input, $step = NULL) {
drupal_set_title($this->get_page_title('import'));
drupal_set_title($this->get_page_title('import'), PASS_THROUGH);
// Import is basically a multi step wizard form, so let's go ahead and
// use CTools' wizard.inc for it.
......@@ -1339,7 +1339,7 @@ function _ctools_export_ui_add_form_files($form, &$form_state) {
*
* This simply loads the object defined in the plugin and hands it off.
*/
function ctools_export_ui_list_form($form, $form_state) {
function ctools_export_ui_list_form($form, &$form_state) {
$form_state['object']->list_form($form, $form_state);
return $form;
}
......
......@@ -2,12 +2,13 @@ name = Stylizer
description = Create custom styles for applications such as Panels.
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
dependencies[] = color
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -3,9 +3,11 @@ description = Controls access to context based upon term depth
core = 7.x
dependencies[] = ctools
package = Chaos tool suite
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
<?php
/**
* @file
* Tests the custom CSS cache handler.
*/
/**
* Tests the custom CSS cache handler.
*/
class CtoolsObjectCache extends DrupalWebTestCase {
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Ctools CSS cache',
'description' => 'Tests the custom CSS cache handler.',
'group' => 'Chaos Tools Suite',
);
}
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp('ctools');
}
/**
* Tests the custom CSS cache handler.
*
* @see https://drupal.org/node/1313368
*/
public function testCssCache() {
// Create a CSS cache entry.
$filename = ctools_css_cache('body { color: red; }');
// Perform a cron run. The CSS cache entry should not be removed.
$this->cronRun();
$this->assertTrue(file_exists($filename), 'The CSS cache is not cleared after performing a cron run.');
// Manually clear the caches. The CSS cache entry should be removed.
drupal_flush_all_caches();
$this->assertFalse(file_exists($filename), 'The CSS cache is cleared after clearing all caches.');
}
}
......@@ -2,14 +2,15 @@ name = CTools export test
description = CTools export test module
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
hidden = TRUE
files[] = ctools_export.test
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
name = Chaos tools plugins test
description = Provides hooks for testing ctools plugins.
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
core = 7.x
dependencies[] = ctools
files[] = ctools.plugins.test
......@@ -11,9 +12,9 @@ files[] = math_expression.test
files[] = math_expression_stack.test
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -63,18 +63,6 @@ function views_content_views_content_type_content_types($plugin) {
return $types;
}
/**
* Return a single content type.
*/
function views_content_views_content_type_content_type($subtype, $plugin) {
$view = views_get_view($name);
if (empty($view)) {
return;
}
return _views_content_views_content_type($view);
}
/**
* Create the content type info array to give back to ctools for a given display.
*/
......
......@@ -274,6 +274,11 @@ function views_content_views_panes_content_type_render($subtype, $conf, $panel_a
}
if ($allow['exposed_form'] && !empty($conf['exposed'])) {
foreach ($conf['exposed'] as $filter_name => $filter_value) {
if (!is_array($filter_value)) {
$conf['exposed'][$filter_name] = ctools_context_keyword_substitute($filter_value, array(), $contexts);
}
}
$view->set_exposed_input($conf['exposed']);
}
......@@ -284,6 +289,11 @@ function views_content_views_panes_content_type_render($subtype, $conf, $panel_a
return;
}
// Add contextual links to the output.
$block = (array) $block;
views_add_block_contextual_links($block, $view, $display, 'panel_pane');
$block = (object) $block;
$block->title = $view->get_title();
if (empty($view->total_rows) || $view->total_rows <= $view->get_items_per_page()) {
......@@ -313,7 +323,7 @@ function views_content_views_panes_add_defaults(&$conf, $view) {
$conf += array(
'link_to_view' => $view->display_handler->get_option('link_to_view'),
'more_link' => $view->display_handler->get_option('more_link'),
'more_link' => $view->display_handler->get_option('use_more'),
'feed_icons' => FALSE,
'use_pager' => $pager['type'] != 'none' && $pager['type'] != 'some',
'pager_id' => isset($pager['options']['id']) ? $pager['options']['id'] : 0,
......@@ -408,7 +418,7 @@ function views_content_views_panes_content_type_edit_form($form, &$form_state) {
$form['fields_override'][$field] = array(
'#type' => 'checkbox',
'#title' => $title,
'#default_value' => isset($conf['fields_override'][$field]) ? $conf['fields_override'][$field] : TRUE,
'#default_value' => isset($conf['fields_override'][$field]) ? $conf['fields_override'][$field] : !$handler->options['exclude'],
);
}
}
......@@ -602,7 +612,7 @@ function views_content_views_panes_content_type_admin_info($subtype, $conf, $con
$argument_input = $view->display_handler->get_option('argument_input');
foreach ($conf['arguments'] as $key => $value) {
if(!empty($value)){
if (!empty($value)){
$label = $argument_input[$key]['label'];
$info[] = $label . ': ' . $value;
}
......
......@@ -13,7 +13,7 @@ $plugin = array(
'title' => t('Term from view'),
'keyword' => 'term',
'description' => t('Extract a term context from a view context of the base type term.'),
'required context' => new ctools_context_required(t('View'), 'view', array('base' => 'term_data')),
'required context' => new ctools_context_required(t('View'), 'view', array('base' => 'taxonomy_term_data')),
'context' => 'views_content_term_from_view_context',
'edit form' => 'views_content_term_from_view_settings_form',
'edit form validate' => 'views_content_term_from_view_settings_form_validate',
......@@ -26,7 +26,7 @@ $plugin = array(
function views_content_term_from_view_context($context, $conf, $placeholder = FALSE) {
// If unset it wants a generic, unfilled context, which is just NULL.
if (empty($context->data) || $placeholder) {
return ctools_context_create_empty('term', NULL);
return ctools_context_create_empty('entity:taxonomy_term', NULL);
}
$view = views_content_context_get_view($context);
// Ensure the view executes, but we don't need its output.
......@@ -36,11 +36,11 @@ function views_content_term_from_view_context($context, $conf, $placeholder = FA
if (isset($view->result[$row])) {
$tid = $view->result[$row]->{$view->base_field};
if ($tid) {
$term = taxonomy_get_term($tid);
return ctools_context_create('term', $term);
$term = taxonomy_term_load($tid);
return ctools_context_create('entity:taxonomy_term', $term);
}
}
return ctools_context_create_empty('term', NULL);
return ctools_context_create_empty('entity:taxonomy_term', NULL);
}
/**
......
......@@ -25,6 +25,7 @@ function views_content_views_plugins() {
'use more' => TRUE,
'accept attachments' => TRUE,
'help topic' => 'display-pane',
'contextual links locations' => array('panel_pane'),
),
'ctools_context' => array(
'title' => t('Context'),
......
......@@ -5,13 +5,14 @@ dependencies[] = ctools
dependencies[] = views
core = 7.x
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
files[] = plugins/views/views_content_plugin_display_ctools_context.inc
files[] = plugins/views/views_content_plugin_display_panel_pane.inc
files[] = plugins/views/views_content_plugin_style_ctools_context.inc
; Information added by Drupal.org packaging script on 2014-11-19
version = "7.x-1.5"
; Information added by Drupal.org packaging script on 2015-01-28
version = "7.x-1.6"
core = "7.x"
project = "ctools"
datestamp = "1416423525"
datestamp = "1422471484"
......@@ -281,3 +281,17 @@ function _views_content_get_context_from_display($view, $id, $parent, $required
'view display id' => $id,
);
}
/**
* Implements hook_get_pane_links_alter().
*/
function views_content_get_pane_links_alter(&$links, $pane, $content_type) {
if ($pane->type === 'views_panes') {
list($view_name, $display_name) = explode('-', $pane->subtype);
$destination = array('destination' => current_path());
$links['top'][] = array(
'title' => t('Edit view'),
'href' => url('admin/structure/views/view/' . $view_name . '/edit/' . $display_name, array('query' => $destination, 'absolute' => TRUE)),
);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment