contrib modules security updates

This commit is contained in:
Bachir Soussi Chiadmi 2016-10-13 12:10:40 +02:00
parent ffd758abc9
commit 747127f643
732 changed files with 67976 additions and 23207 deletions

View File

@ -2,7 +2,8 @@
Block Class
http://drupal.org/project/block_class
-----
Block Class was developed and is maintained by Four Kitchens <http://fourkitchens.com>.
Block Class was developed and is maintained by Four Kitchens
<http://fourkitchens.com>.
=====
@ -10,4 +11,5 @@ Installation
-----
1. Enable the module
2. To add a class to a block, simply visit that block's configuration page at Administration > Structure > Blocks
2. To add a class to a block, simply visit that block's configuration page at
Administration > Structure > Blocks

View File

@ -1,74 +0,0 @@
<?php
/**
* Implements hook_features_export_options().
*/
function block_class_features_export_options() {
$query = db_select('block_class', 'bc');
$query->addExpression("CONCAT(bc.module, ':', bc.delta)");
$blocks = $query->execute()->fetchAllKeyed(0, 0);
natcasesort($blocks);
return $blocks;
}
/**
* Implements hook_features_export().
*/
function block_class_features_export($data, &$export, $module_name = '') {
$pipe = array();
$export['dependencies']['features'] = 'features';
$export['dependencies']['block_class'] = 'block_class';
foreach ($data as $component) {
$export['features']['block_class'][$component] = $component;
}
return $pipe;
}
/**
* Implements hook_features_export_render().
*/
function block_class_features_export_render($module, $data) {
$query = db_select('block_class', 'bc');
$query->addExpression("CONCAT(bc.module, ':', bc.delta)", 'id');
$query->addField('bc', 'css_class');
$classes = $query->execute()->fetchAllKeyed(1, 0);
$code = array();
foreach ($data as $id) {
if (isset($classes[$id])) {
list($module, $delta) = explode(':', $id);
$css_classes = $classes[$id];
$code[$id] = compact('module', 'delta', 'css_classes');
}
}
$code = " return ". features_var_export($code, ' ') .";";
return array('block_class_features_default_class' => $code);
}
/**
* Implements hook_features_revert().
*/
function block_class_features_revert($module) {
block_class_features_rebuild($module);
}
/**
* Implements hook_features_rebuild().
*/
function block_class_features_rebuild($module) {
$blocks = module_invoke($module, 'block_class_features_default_class');
if ($blocks) {
foreach($blocks as $block) {
db_delete('block_class')->condition('module', $block['module'])->condition('delta', $block['delta'])->execute();
if (!empty($block['css_classes'])) {
$id = db_insert('block_class')->fields(array('module' => $block['module'], 'delta' => $block['delta'], 'css_class' => $block['css_classes']))->execute();
}
}
}
}

View File

@ -2,12 +2,15 @@ name = Block Class
description = Allows assigning CSS classes to blocks.
core = 7.x
files[] = block_class.install
files[] = block_class.module
dependencies[] = block
files[] = block_class.test
test_dependencies[] = context
test_dependencies[] = features (2.x)
test_dependencies[] = features_extra
; Information added by drupal.org packaging script on 2012-10-04
version = "7.x-1.2+3-dev"
; Information added by Drupal.org packaging script on 2015-12-18
version = "7.x-2.3"
core = "7.x"
project = "block_class"
datestamp = "1349309175"
datestamp = "1450415951"

View File

@ -6,102 +6,146 @@
*/
/**
* Implementation of hook_schema().
* Implements hook_install().
*/
function block_class_schema() {
$schema['block_class'] = array(
'fields' => array(
'module' => array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
'description' => 'The module to which the block belongs.',
),
'delta' => array(
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
'description' => "The ID of the module's block.",
),
'css_class' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'String containing the classes for the block.',
),
),
'primary key' => array('module', 'delta'),
);
function block_class_install() {
$schema['block'] = array();
block_class_schema_alter($schema);
foreach ($schema['block']['fields'] as $field => $spec) {
if (db_field_exists('block', $field)) {
watchdog('system', 'Module install: Attempt to recreate field: "%field", when it already exists.', array('%field' => $field), WATCHDOG_WARNING);
}
else {
db_add_field('block', $field, $spec);
}
}
}
return $schema;
/**
* Implements hook_uninstall().
*/
function block_class_uninstall() {
$schema['block'] = array();
block_class_schema_alter($schema);
foreach ($schema['block']['fields'] as $field => $specs) {
db_drop_field('block', $field);
}
}
/**
* Implements hook_schema_alter().
*
* Other modules, such as i18n_block also modify the block database table.
*/
function block_class_schema_alter(&$schema) {
if (isset($schema['block'])) {
$schema['block']['fields']['css_class'] = array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'String containing the classes for the block.',
);
}
}
/**
* Alters the structure of {block_class} schema.
*/
function block_class_update_7100() {
// Update the schema.
db_drop_primary_key('block_class');
// Check if the block_class table exists to prevent installation profiles
// from running this update for versions without the block_class table.
if (db_table_exists('block_class')) {
// Update the schema.
db_drop_primary_key('block_class');
db_change_field('block_class', 'module', 'module',
array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'The module to which the block belongs.',
)
);
db_change_field('block_class', 'module', 'module',
array(
'type' => 'varchar',
'length' => '64',
'not null' => TRUE,
'default' => '',
'description' => 'The module to which the block belongs.',
)
);
db_change_field('block_class', 'delta', 'delta',
array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => "The ID of the module's block.",
)
);
db_change_field('block_class', 'delta', 'delta',
array(
'type' => 'varchar',
'length' => '32',
'not null' => TRUE,
'default' => '',
'description' => "The ID of the module's block.",
)
);
db_change_field('block_class', 'css_class', 'css_class',
array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'String containing the classes for the block.',
)
);
db_change_field('block_class', 'css_class', 'css_class',
array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'String containing the classes for the block.',
)
);
// Restore the primary key.
db_add_primary_key('block_class', array('module', 'delta'));
// Restore the primary key.
db_add_primary_key('block_class', array('module', 'delta'));
}
}
/**
* Fix too long primary key length in {block_class}.
*/
function block_class_update_7101() {
// Drop current primary key.
db_drop_primary_key('block_class');
// Ensure the block_class table exists, which is not true for all versions.
if (db_table_exists('block_class')) {
// Drop current primary key.
db_drop_primary_key('block_class');
db_change_field('block_class', 'module', 'module', array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
'description' => 'The module to which the block belongs.',
));
db_change_field('block_class', 'delta', 'delta', array(
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
'description' => "The ID of the module's block.",
));
db_change_field('block_class', 'module', 'module', array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
'description' => 'The module to which the block belongs.',
));
db_change_field('block_class', 'delta', 'delta', array(
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
'description' => "The ID of the module's block.",
));
// Create new primary key.
db_add_primary_key('block_class', array('module', 'delta'));
// Create new primary key.
db_add_primary_key('block_class', array('module', 'delta'));
}
}
/**
* Migration from block_class table to new field css_class in core block table.
*/
function block_class_update_7103() {
if (!db_field_exists('block', 'block_class')) {
$schema['block'] = array();
block_class_schema_alter($schema);
foreach ($schema['block']['fields'] as $field => $specs) {
db_add_field('block', $field, $specs);
}
}
if (db_table_exists('block_class')) {
// Migrate all existing records from block_class table to block table.
$result = db_query('SELECT css_class, module, delta FROM {block_class}');
while ($record = $result->fetchObject()) {
db_update('block')
->fields(array('css_class' => $record->css_class))
->condition('module', $record->module)
->condition('delta', $record->delta)
->execute();
}
// Remove the block_class table.
db_drop_table('block_class');
}
}

View File

@ -1,5 +1,15 @@
<?php
/**
* @file
* Enhanced control over the CSS Classes of any Block.
*
* Block Class allows users to add classes to any block through the block's
* configuration interface. This implementation is based on an alteration of
* the Core block database table to leverage the Core Block API functions,
* objects and structure.
*/
/**
* Implements hook_permission().
*/
@ -12,37 +22,25 @@ function block_class_permission() {
);
}
/*
/**
* Implements theme_preprocess_block().
*
* Extend block's classes with any user defined classes.
*/
function block_class_preprocess_block(&$vars) {
$block = $vars['block'];
/* The original code: */
//$classes = block_class($block);
//$vars['classes_array'] = array_merge($vars['classes_array'], explode(' ', $classes));
/* Replaced with the following so it doesn't fire that many queries if you have a lot of blocks */
static $_block_class_blocks_classes;
if (! isset ($_block_class_blocks_classes)) {
$_block_class_blocks_classes = array();
$result = db_query('SELECT css_class, module, delta FROM {block_class}');
while ($record = $result->fetchObject()) {
$_block_class_blocks_classes[$record->module][$record->delta] = $record->css_class;
if (!empty($block->css_class)) {
$classes_array = explode(' ', $block->css_class);
foreach ($classes_array as $class) {
$vars['classes_array'][] = drupal_clean_css_identifier($class, array());
}
}
if (isset($_block_class_blocks_classes[$block->module][$block->delta])) {
$classes = $_block_class_blocks_classes[$block->module][$block->delta];
$vars['classes_array'] = array_merge($vars['classes_array'], explode(' ', $classes));
}
}
/*
/**
* Implements hook_preprocess_HOOK().
*
* Extend panel block's classes with any user defined classes.
* Implements hook_preprocess_hook()
*/
function block_class_preprocess_panels_pane(&$vars) {
if ($vars['pane']->type != 'block') {
@ -52,42 +50,32 @@ function block_class_preprocess_panels_pane(&$vars) {
$block_parts = explode('-', $vars['pane']->subtype);
// Load the block based on the block parts.
$block = block_load($block_parts[0], $block_parts[1]);
// Return block_class classes as string.
$css_class = block_class($block);
// Add a generic 'module type' pane class.
$vars['classes_array'][] = drupal_html_class('pane-' . $block->module);
// Add $css_class to the $classes_array.
$vars['classes_array'][] = $css_class;
if (!empty($block->css_class)) {
$classes_array = explode(' ', $block->css_class);
foreach ($classes_array as $class) {
$vars['classes_array'][] = drupal_clean_css_identifier($class, array());
}
}
}
/**
* Return classes as string
*/
function block_class($block) {
$ret = db_query('SELECT css_class FROM {block_class} WHERE module = :module AND delta = :delta', array(':module' => $block->module, ':delta' => $block->delta))->fetchField();
return $ret ? check_plain ($ret) : '';
}
/**
* Alter block edit form
* Implements hook_form_alter().
*
* Alter block edit form to add configuration field.
*/
function block_class_form_alter(&$form, &$form_state, $form_id) {
if (user_access('administer block classes') && $form_id == 'block_admin_configure' || $form_id == 'block_add_block_form') {
$block = new stdClass;
$block->module = $form['module']['#value'];
$block->delta = $form['delta']['#value'];
$css_class = block_class($block);
// Create a more technical description for users with administer blocks permission.
$description = t('Customize the styling of this block by adding CSS classes. Separate multiple classes by spaces.');
if (user_access('administer block classes') && ($form_id == 'block_admin_configure' || $form_id == 'block_add_block_form')) {
// Load statically cached block object used to display the form.
$block = block_load($form['module']['#value'], $form['delta']['#value']);
$form['settings']['css_class'] = array(
'#type' => 'textfield',
'#title' => t('CSS class(es)'),
'#default_value' => $css_class,
'#description' => t('Separate classes with a space.'),
'#default_value' => isset($block->css_class) ? $block->css_class : '',
'#description' => t('Customize the styling of this block by adding CSS classes. Separate multiple classes by spaces.'),
'#maxlength' => 255,
);
@ -95,34 +83,24 @@ function block_class_form_alter(&$form, &$form_state, $form_id) {
}
}
/**
* Save supplied class.
* Helper function: additional submit callback for block configuration pages.
*
* Save supplied CSS classes.
*/
function block_class_form_submit($form, &$form_state) {
if ($form_state['values']['form_id'] == 'block_admin_configure' || $form_state['values']['form_id'] == 'block_add_block_form') {
if (isset($form_state['values']['css_class']) && user_access('administer blocks')) {
$module = $form_state['values']['module'];
$delta = $form_state['values']['delta'];
$class = $form_state['values']['css_class'];
db_delete('block_class')->condition('module', $module)->condition('delta', $delta)->execute();
if (!empty($class)) {
$id = db_insert('block_class')->fields(array('module' => $module, 'delta' => $delta, 'css_class' => $class))->execute();
// Only save if value has changed.
if (isset($form_state['values']['css_class']) && $form['settings']['css_class']['#default_value'] != $form_state['values']['css_class'] && user_access('administer blocks')) {
db_update('block')
->fields(array('css_class' => $form_state['values']['css_class']))
->condition('module', $form_state['values']['module'])
->condition('delta', $form_state['values']['delta'])
->execute();
// Flush all context module cache to use the updated css_class.
if (module_exists('context')) {
cache_clear_all('context', 'cache', TRUE);
}
}
}
}
/**
* Implements hook_features_api().
*/
function block_class_features_api() {
return array(
'block_class' => array(
'name' => t('Block class'),
'feature_source' => TRUE,
'default_hook' => 'block_class_features_default_class',
'file' => drupal_get_path('module', 'block_class') . '/block_class.features.inc',
),
);
}

View File

@ -0,0 +1,329 @@
<?php
/**
* @file
* Test the Block Class module.
*/
/**
* Provides common functionality for the Block Class test classes.
*/
class BlockClassTestCase extends DrupalWebTestCase {
/**
* User object to perform site browsing
* @var object
*/
protected $privilegedUser;
/**
* Machine name of the module providing the block coupled with delta.
* @var string
*/
protected $module = 'system';
/**
* Block delta as provided by its module.
* @var string
*/
protected $delta = 'main';
/**
* Permissions required by the user to perform the tests.
* @var array
*/
protected $permissions = array(
'administer blocks',
'administer block classes',
);
/**
* Enable modules and create user with specific permissions.
*
* By default Test Cases are carried on the "Main page content" Block.
*/
public function setUp() {
// Merge inherited classes modules, see FieldUITestCase for an example.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
$modules = $modules[0];
}
$modules[] = 'block_class';
parent::setUp($modules);
// Authenticate test user.
$this->privilegedUser = $this->drupalCreateUser($this->permissions);
$this->drupalLogin($this->privilegedUser);
}
/**
* Update Block CSS class and assert whether it is found when displayed.
*
* @param bool $anon
* (optional) Set to TRUE to view block with anon user, defaults to TRUE.
* @param string $module
* (optional) Machine name of the module Defaults to
* $this->module if set to NULL.
* @param string $delta
* (optional) Block delta as provided by its module. Defaults to
* $this->delta if set to NULL.
*/
public function assertUpdateBlockClass($anon = FALSE, $module = NULL, $delta = NULL) {
// Initialize $module and $delta by default if no value is provided.
if (!isset($module)) {
$module = $this->module;
}
if (!isset($delta)) {
$delta = $this->delta;
}
// Test with three random class names.
$css_classes = implode(' ', array(
$this->randomName(8),
$this->randomName(8),
$this->randomName(8),
));
// Update Block CSS class field.
$this->drupalPost("admin/structure/block/manage/$module/$delta/configure", array('css_class' => $css_classes), t('Save block'));
// Check Block configuration was saved successfully.
$this->assertText(t('The block configuration has been saved.'));
// Browse to the homepage.
$this->drupalGet('');
// Log out if the test is for anonymous user.
if ($anon) {
$this->drupalLogout();
// Browse back to the homepage.
$this->drupalGet('');
}
// Check if the Block CSS classes could be found.
$this->assertPattern('/class=\"(.*?)' . $css_classes . '(.*?)\"/', format_string('The CSS classes were found: @css_classes', array('@css_classes' => $css_classes)));
// Login again after testing with the anonumous user.
if ($anon) {
$this->drupalLogin($this->privilegedUser);
}
}
}
/**
* Test the update and display of the CSS class for a Block.
*/
class BlockClassUpdateDisplayTestCase extends BlockClassTestCase {
/**
* Implements DrupalWebTestCase::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Block CSS class update and display',
'description' => 'Test the update of a Block CSS class field and the display for the Main Page Content Block.',
'group' => 'Block Class',
);
}
/**
* Update and display a Block multiple times to ensure CSS class is found.
*
* A Block is updated and displayed several times and with logged in or
* anonymous user, with Block cache turned enabled or disabled.
*/
public function testUpdateDisplayClass() {
// Edit the block, change the class and check if the CSS classes are found.
$this->assertUpdateBlockClass();
// Now, turn on caching programmatically and set it to 15 min expiry.
variable_set('block_cache', TRUE);
variable_set('cache_lifetime', 900);
variable_set('page_cache_maximum_age', 900);
// Edit the block, change the class and check with the anonymous user.
$this->assertUpdateBlockClass(TRUE);
// Edit the block, change the class and check with the anonymous user.
$this->assertUpdateBlockClass(TRUE);
}
}
/**
* Test Block Class permissions.
*/
class BlockClassPermissionTestCase extends BlockClassTestCase {
/**
* Implements DrupalWebTestCase::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Administer block classes permission',
'description' => 'Test the permission added by the module to administer block classes.',
'group' => 'Block Class',
);
}
/**
* Enable modules and create user with specific permissions.
*/
public function setUp() {
// Remove the 'administer block classes' permission from the base class.
$this->permissions = array('administer blocks');
parent::setUp();
}
/**
* Ensure Block CSS classes field is only visible with the right permissions.
*
* Test if a user without 'administer block classes' permission has access to
* the Block CSS classes field on the block configuration page.
*/
public function testPermission() {
// Browse to the "Main page content" block editing form page.
$this->drupalGet("admin/structure/block/manage/{$this->module}/{$this->delta}/configure");
// Check that the css_class field couldn't be found.
// If the field is not found, it can't be submitted through drupalPost.
$this->assertNoFieldById('css_class', 'The Css classes field was not found on the page.');
}
}
/**
* Test Block Class integration with Context.
*/
class BlockClassContextTestCase extends BlockClassUpdateDisplayTestCase {
/**
* Implements DrupalWebTestCase::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Integration with Context',
'description' => 'Test the integration of Block Class with the Context module and the update/display of a Block CSS class.',
// Include required contributed modules context and ctools for the test.
'dependencies' => array('context', 'ctools'),
'group' => 'Block Class',
);
}
/**
* Enable modules and create user with specific permissions.
*/
public function setUp() {
// Override default module and delta to test with the "Who's online" block.
$this->module = 'user';
$this->delta = 'online';
// Include the Context module and its dependencies to be loaded.
parent::setUp('context');
// Initialize a test context with the test block.
$this->initializeContext();
}
/**
* Helper function to initialize a test Context with a test block.
*/
public function initializeContext() {
// Import a basic context exported through the admin interface.
$context = new stdClass();
$context->disabled = FALSE;
$context->api_version = 3;
$context->name = 'front';
$context->description = 'Frontpage Context';
$context->tag = '';
$context->conditions = array(
'path' => array(
'values' => array(
'<front>' => '<front>',
),
),
);
$context->reactions = array(
'block' => array(
'blocks' => array(
$this->module . '-' . $this->delta => array(
'module' => $this->module,
'delta' => $this->delta,
'region' => 'content',
'weight' => '-10',
),
),
),
);
$context->condition_mode = 0;
// Translatables
// Included for use with string extractors like potx.
t('Frontpage Context');
// Save the context.
context_save($context);
}
}
/**
* Test Block Class integration with Features through FE Block.
*/
class BlockClassFeaturesTestCase extends BlockClassTestCase {
/**
* Implements DrupalWebTestCase::getInfo().
*/
public static function getInfo() {
return array(
'name' => 'Integration with Features',
'description' => 'Test the integration of Block Class with Features through the FE Block module and the update/display of a Block CSS class.',
// Include Features related modules required for this Test Case.
'dependencies' => array('features', 'ctools', 'fe_block'),
'group' => 'Block Class',
);
}
/**
* Enable modules and create user with specific permissions.
*/
public function setUp() {
// Override default module and delta to test with the "Who's online" block.
$this->module = 'user';
$this->delta = 'online';
// Include all Features related modules and Test Helper feature.
parent::setUp('block_class_fe_block_test');
}
/**
* Test how Block Class reacts when exported to a Feature with FE Block.
*
* Helper Feature's Block configuration settings are imported, updated and
* the display is tested several times, before reverting the feature.
*/
public function testFeatureDisplayClass() {
// Block classes exported to the Test Feature module.
$test_classes = 'fe_block-class1 fe_block-class2 fe_block-class3';
// Test helper feature machine name.
$test_feature = 'block_class_fe_block_test';
// Browse to the front page and check Block's CSS classes configuration.
$this->drupalGet('');
// Check if feature's Block CSS classes could be found.
$this->assertPattern('/class=\"(.*?)' . $test_classes . '(.*?)\"/', format_string('The CSS classes from exported feature were found: @css_classes', array('@css_classes' => $test_classes)));
// Check Block's configuration form css_class field value.
$this->drupalGet("admin/structure/block/manage/{$this->module}/{$this->delta}/configure");
$this->assertFieldByName('css_class', $test_classes, format_string('The CSS classes from exported feature were found for the field <em>css_class</em> in the Block\'s configuration page: @css_classes', array('@css_classes' => $test_classes)));
// Run a standard Update/Display Test check with Anon.
$this->assertUpdateBlockClass(TRUE);
// Ensure Feature's state is overriden for 'fe_block_settings' component.
module_load_include('inc', 'features', 'features.export');
$test_feature_state = features_get_storage($test_feature);
$this->assertFalse(empty($test_feature_state), 'The state of the <em>Block Class FE Block Integration Test Helper</em> feature is <strong>Overridden</strong>.');
$test_feature_states = features_get_component_states(array($test_feature));
$this->assertFalse(empty($test_feature_states[$test_feature]['fe_block_settings']), 'The state of the <em>fe_block_settings</em> component of the <em>Block Class FE Block Integration Test Helper</em> feature is <strong>Overridden</strong>.');
// Revert feature and check again.
features_revert_module($test_feature);
// Browse to the front page and check Block's CSS classes configuration.
$this->drupalGet('');
// Check if feature's Block CSS classes could be found.
$this->assertPattern('/class=\"(.*?)' . $test_classes . '(.*?)\"/', format_string('After reverting the feature, the CSS classes from exported feature were found: @css_classes', array('@css_classes' => $test_classes)));
// Check Block's configuration form css_class field value.
$this->drupalGet("admin/structure/block/manage/{$this->module}/{$this->delta}/configure");
$this->assertFieldByName('css_class', $test_classes, format_string('After reverting the feature, the CSS classes from exported feature were found for the field <em>css_class</em> in the Block\'s configuration page: @css_classes', array('@css_classes' => $test_classes)));
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* @file
* block_class_fe_block_test.features.fe_block_settings.inc
*/
/**
* Implements hook_default_fe_block_settings().
*/
function block_class_fe_block_test_default_fe_block_settings() {
$export = array();
$export['version'] = '2.0';
$export['user-online'] = array(
'cache' => -1,
'css_class' => 'fe_block-class1 fe_block-class2 fe_block-class3',
'custom' => 0,
'delta' => 'online',
'module' => 'user',
'node_types' => array(),
'pages' => '<front>',
'roles' => array(),
'themes' => array(
'bartik' => array(
'region' => 'content',
'status' => 1,
'theme' => 'bartik',
'weight' => -7,
),
),
'title' => 'Block Class Test Who\'s Online with FE Block',
'visibility' => 1,
);
return $export;
}

View File

@ -0,0 +1,15 @@
name = Block Class FE Block Integration Test Helper
description = Helper module for testing the integration of Block Class with Features through the FE Block module.
core = 7.x
package = Features
dependencies[] = fe_block
features[fe_block_settings][] = user-online
features[features_api][] = api:2
hidden = TRUE
; Information added by Drupal.org packaging script on 2015-12-18
version = "7.x-2.3"
core = "7.x"
project = "block_class"
datestamp = "1450415951"

View File

@ -0,0 +1,5 @@
<?php
/**
* @file
* Drupal needs this blank file.
*/

View File

@ -32,15 +32,13 @@ The Colorbox module:
The Colorbox plugin:
* Supports images, image groups, slideshow, ajax, inline, and
iframed content.
* Appearance is controlled through CSS so users can restyle the box.
* Preloads background images and can preload upcoming images in a
photo group.
* Generates W3C valid XHTML and adds no JS global variables and
passes JSLint.
* Tested in Firefox 2 & 3, Safari 3 & 4, Opera 9, Chrome,
Internet Explorer 6, 7, 8.
* Supports photos, grouping, slideshow, ajax, inline, and iframed content.
* Appearance is controlled through CSS so it can be restyled.
* Preloads upcoming images in a photo group.
* Completely unobtrusive, options are set in the JS and require no
changes to existing HTML.
* Compatible with: jQuery 1.3.2+ in Firefox, Safari, Chrome, Opera,
Internet Explorer 7+.
* Released under the MIT License.
@ -91,7 +89,7 @@ Make any CSS adjustments to your "colorbox_mycolorbox.css" file.
Load images from custom links in a Colorbox:
--------------------------------------------
Add the class "colorbox" to the link and point the src to the image
Add the class "colorbox" to the link and point its href attribute to the image
you want to display in the Colorbox.

View File

@ -6,9 +6,12 @@
*
* Available variables:
* - $item: The complete item being inserted.
* - $image_path: The URL to the image.
* - $link_path: The URL to the image that Colorbox should open.
* - $url: The URL to the image.
* - $path: The URL to the image that Colorbox should open.
* - $class: A set of classes assigned to this image (if any).
* - $width: The width of the image (if known).
* - $height: The height of the image (if known).
* - $style_name: The Image style being used.
* - $gallery_id: The ID of the Colorbox gallery.
*
* Note that ALT and Title fields should not be filled in here, instead they
@ -19,6 +22,11 @@
* - __alt__: The ALT text, intended for use in the <img> tag.
* - __title__: The Title text, intended for use in the <img> tag.
* - __description__: A description of the image, sometimes used as a caption.
* - __filename__: The file name.
* - __[token]_or_filename__: Any of the above tokens if available, otherwise
* use the file's name. i.e. __title_or_filename__.
*/
?>
<a href="<?php print $link_path; ?>" title="__title__" class="colorbox colorbox-insert-image" rel="<?php print $gallery_id; ?>"><img typeof="foaf:Image" src="<?php print $image_path; ?>" alt="__alt__" title="__title__" class="<?php print $class; ?>" /></a>
<a href="<?php print $path; ?>" title="__title__" class="colorbox colorbox-insert-image" data-colorbox-gallery="<?php print $gallery_id; ?>">
<img src="<?php print $url; ?>" <?php if ($width && $height): ?>width="<?php print $width; ?>" height="<?php print $height; ?>" <?php endif; ?>alt="__alt__" title="__title__" class="<?php print $class; ?>" />
</a>

View File

@ -44,7 +44,7 @@ function colorbox_admin_settings() {
'#type' => 'checkbox',
'#title' => t('Enable Colorbox load'),
'#default_value' => variable_get('colorbox_load', 0),
'#description' => t('This enables custom links that can open forms and paths in a Colorbox. Add the class "colorbox-load" to the link and build the url like this for forms "/colorbox/form/[form_id]?destination=some_path&width=500&height=500" and like this for paths "[path]?width=500&height=500&iframe=true" or "[path]?width=500&height=500" if you don\'t want an iframe. Other modules may activate this for easy Colorbox integration.'),
'#description' => t('This enables custom links that can open forms and paths in a Colorbox. Add the class "colorbox-load" to the link and build the url like this for paths "[path]?width=500&height=500&iframe=true" or "[path]?width=500&height=500" if you don\'t want an iframe. Other modules may activate this for easy Colorbox integration.'),
);
$form['colorbox_extra_features']['colorbox_inline'] = array(
'#type' => 'checkbox',
@ -143,7 +143,7 @@ function colorbox_admin_settings() {
'#type' => 'checkbox',
'#title' => t('Overlay close'),
'#default_value' => variable_get('colorbox_overlayclose', 1),
'#description' => t('Enable closing ColorBox by clicking on the background overlay.'),
'#description' => t('Enable closing Colorbox by clicking on the background overlay.'),
);
$form['colorbox_custom_settings']['colorbox_maxwidth'] = array(
'#type' => 'textfield',
@ -177,7 +177,7 @@ function colorbox_admin_settings() {
'#type' => 'checkbox',
'#title' => t('Fixed'),
'#default_value' => variable_get('colorbox_fixed', 1),
'#description' => t('If the ColorBox should be displayed in a fixed position within the visitor\'s viewport or relative to the document.'),
'#description' => t('If the Colorbox should be displayed in a fixed position within the visitor\'s viewport or relative to the document.'),
);
$form['colorbox_custom_settings']['colorbox_slideshow_settings'] = array(
@ -198,7 +198,7 @@ function colorbox_admin_settings() {
$form['colorbox_custom_settings']['colorbox_scrolling'] = array(
'#type' => 'radios',
'#title' => t('Scrollbars'),
'#options' => array(0 => t('Off'), 1 => t('On')),
'#options' => array(1 => t('On'), 0 => t('Off')),
'#default_value' => variable_get('colorbox_scrolling', 1),
'#description' => t('If false, Colorbox will hide scrollbars for overflowing content. This could be used on conjunction with the resize method for a smoother transition if you are appending content to an already open instance of Colorbox.'),
);
@ -250,6 +250,32 @@ function colorbox_admin_settings() {
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['colorbox_advanced_settings']['colorbox_unique_token'] = array(
'#type' => 'radios',
'#title' => t('Unique per-request gallery token'),
'#options' => array(1 => t('On'), 0 => t('Off')),
'#default_value' => variable_get('colorbox_unique_token', 1),
'#description' => t('If On (default), Colorbox will add a unique per-request token to the gallery id to avoid images being added manually to galleries. The token was added as a security fix but some see the old behavoiur as an feature and this settings makes it possible to remove the token.'),
);
$form['colorbox_advanced_settings']['colorbox_mobile_detect'] = array(
'#type' => 'radios',
'#title' => t('Mobile detection'),
'#options' => array(1 => t('On'), 0 => t('Off')),
'#default_value' => variable_get('colorbox_mobile_detect', 1),
'#description' => t('If On (default), Colorbox will not be active for devices with the max width set below.'),
);
$form['colorbox_advanced_settings']['colorbox_mobile_device_width'] = array(
'#type' => 'textfield',
'#title' => t('Device with'),
'#default_value' => variable_get('colorbox_mobile_device_width', '480px'),
'#size' => 30,
'#description' => t('Set the mobile device max with. Default: 480px.'),
'#states' => array(
'visible' => array(
':input[name="colorbox_mobile_detect"]' => array('value' => '1'),
),
),
);
$form['colorbox_advanced_settings']['colorbox_caption_trim'] = array(
'#type' => 'radios',
'#title' => t('Caption shortening'),

View File

@ -10,11 +10,11 @@
*
* Implements hook_colorbox_settings_alter().
*
* @param $settings
* @param array $settings
* An associative array of Colorbox settings. See the
* @link http://colorpowered.com/colorbox/ Colorbox documentation @endlink
* for the full list of supported parameters.
* @param $style
* @param string $style
* The name of the active style plugin. If $style is 'none', no Colorbox
* theme will be loaded.
*/
@ -27,3 +27,18 @@ function hook_colorbox_settings_alter(&$settings, &$style) {
$style = 'mystyle';
}
}
/**
* Allows to override activation of Colorbox for the current URL.
*
* @param bool $active
* A boolean indicating whether colorbox should be active for the current
* URL or not.
*/
function hook_colorbox_active_alter(&$active) {
$path = drupal_get_path_alias($_GET['q']);
if (drupal_match_path($path, 'admin/config/colorbox_test')) {
// Enable colorbox for this URL.
$active = TRUE;
}
}

View File

@ -1,14 +1,14 @@
name = Colorbox
description = A light-weight, customizable lightbox plugin for jQuery 1.4.3+.
dependencies[] = libraries (2.x)
dependencies[] = libraries (>=2.x)
core = 7.x
configure = admin/config/media/colorbox
files[] = views/colorbox_handler_field_colorbox.inc
; Information added by drupal.org packaging script on 2013-02-13
version = "7.x-2.3+2-dev"
; Information added by Drupal.org packaging script on 2016-06-06
version = "7.x-2.12"
core = "7.x"
project = "colorbox"
datestamp = "1360716175"
datestamp = "1465255741"

View File

@ -14,13 +14,15 @@ function colorbox_requirements($phase) {
if ($phase == 'runtime') {
$t = get_t();
$library = libraries_detect('colorbox');
$error_type = isset($library['error']) ? drupal_ucfirst($library['error']) : '';
$error_message = isset($library['error message']) ? $library['error message'] : '';
if (empty($library['installed'])) {
$requirements['colorbox_plugin'] = array(
'title' => $t('Colorbox plugin'),
'value' => $t('At least @a', array('@a' => COLORBOX_MIN_PLUGIN_VERSION)),
'value' => $t('@e: At least @a', array('@e' => $error_type, '@a' => COLORBOX_MIN_PLUGIN_VERSION)),
'severity' => REQUIREMENT_ERROR,
'description' => $t('You need to download the !colorbox, extract the archive and place the colorbox directory in the %path directory on your server.', array('!colorbox' => l($t('Colorbox plugin'), $library['download url']), '%path' => 'sites/all/libraries')),
'description' => $t('!error You need to download the !colorbox, extract the archive and place the colorbox directory in the %path directory on your server.', array('!error' => $error_message, '!colorbox' => l($t('Colorbox plugin'), $library['download url']), '%path' => 'sites/all/libraries')),
);
}
elseif (version_compare($library['version'], COLORBOX_MIN_PLUGIN_VERSION, '>=')) {
@ -47,7 +49,7 @@ function colorbox_requirements($phase) {
* Implements hook_uninstall().
*/
function colorbox_uninstall() {
db_query("DELETE FROM {variable} WHERE name LIKE 'colorbox_%'");
db_delete('variable')->condition('name', db_like('colorbox_') . '%', 'LIKE')->execute();
}
/**

View File

@ -0,0 +1,8 @@
core = 7.x
api = 2
libraries[colorbox][type] = "libraries"
libraries[colorbox][download][type] = "file"
libraries[colorbox][download][url] = "https://github.com/jackmoore/colorbox/archive/1.x.zip"
libraries[colorbox][directory_name] = "colorbox"
libraries[colorbox][destination] = "libraries"

View File

@ -1,9 +0,0 @@
; $Id$
core = 7.x
api = 2
libraries[colorbox][download][type] = "get"
libraries[colorbox][download][url] = "http://colorpowered.com/colorbox/colorbox.zip"
libraries[colorbox][directory_name] = "colorbox"
libraries[colorbox][destination] = "libraries"

View File

@ -6,9 +6,9 @@
*/
/**
* The default path to the Colorbox directory.
* The minimum required version of the Colorbox plugin.
*/
define('COLORBOX_MIN_PLUGIN_VERSION', '1.3.21.1');
define('COLORBOX_MIN_PLUGIN_VERSION', '1.6.1');
/**
@ -32,6 +32,7 @@ function colorbox_theme() {
'widget' => NULL,
),
'template' => 'colorbox-insert-image',
'pattern' => 'colorbox_insert_image__[a-z0-9_]+',
'file' => 'colorbox.theme.inc',
),
@ -43,6 +44,7 @@ function colorbox_theme() {
'node' => NULL, // Left for legacy support.
'field' => array(),
'display_settings' => array(),
'delta' => null,
),
'file' => 'colorbox.theme.inc',
),
@ -54,8 +56,8 @@ function colorbox_theme() {
*/
function colorbox_init() {
// Do not load colorbox during the Drupal installation process, e.g. if part
// of installation profiles.
if (!drupal_installation_attempted()) {
// of installation profiles. Only add the JavaScript and CSS on specified paths.
if (!drupal_installation_attempted() && _colorbox_active()) {
_colorbox_doheader();
}
}
@ -77,10 +79,10 @@ function colorbox_libraries_info() {
$libraries['colorbox'] = array(
'name' => 'Colorbox plugin',
'vendor url' => 'http://www.jacklmoore.com/colorbox',
'download url' => 'http://www.jacklmoore.com/colorbox',
'download url' => 'https://github.com/jackmoore/colorbox/archive/1.x.zip',
'version arguments' => array(
'file' => 'jquery.colorbox-min.js',
'pattern' => '@ColorBox v([0-9\.a-z]+)@',
'pattern' => '@(?i:Colorbox)\sv?([0-9\.a-z]+)@',
'lines' => 5,
),
'files' => array(
@ -130,7 +132,7 @@ function colorbox_menu() {
/**
* Check if Colorbox should be active for the current URL.
*
* @return
* @return bool
* TRUE if Colorbox should be active for the current page.
*/
function _colorbox_active() {
@ -140,7 +142,7 @@ function _colorbox_active() {
return FALSE;
}
// Code from the block_list funtion in block.module.
// Code from the block_list function in block.module.
$path = drupal_get_path_alias($_GET['q']);
$colorbox_pages = variable_get('colorbox_pages', "admin*\nimagebrowser*\nimg_assist*\nimce*\nnode/add/*\nnode/*/edit\nprint/*\nprintpdf/*\nsystem/ajax\nsystem/ajax/*");
// Compare with the internal and path alias (if any).
@ -150,6 +152,9 @@ function _colorbox_active() {
}
$page_match = variable_get('colorbox_visibility', 0) == 0 ? !$page_match : $page_match;
// Allow other modules to change the state of colorbox for the current URL.
drupal_alter('colorbox_active', $page_match);
return $page_match;
}
@ -161,9 +166,6 @@ function _colorbox_doheader() {
if ($already_added) {
return; // Don't add the JavaScript and CSS multiple times.
}
if (!_colorbox_active()) {
return; // Don't add the JavaScript and CSS on specified paths.
}
// Insert options and translated strings as javascript settings.
if (variable_get('colorbox_custom_settings_activate', 0)) {
@ -176,10 +178,10 @@ function _colorbox_doheader() {
'slideshowSpeed' => variable_get('colorbox_slideshowspeed', 2500),
'slideshowStart' => variable_get('colorbox_text_start', 'start slideshow'),
'slideshowStop' => variable_get('colorbox_text_stop', 'stop slideshow'),
'current' => variable_get('colorbox_text_current', '{current} of {total}'),
'previous' => variable_get('colorbox_text_previous', '« Prev'),
'next' => variable_get('colorbox_text_next', 'Next »'),
'close' => variable_get('colorbox_text_close', 'Close'),
'current' => strip_tags(variable_get('colorbox_text_current', '{current} of {total}')),
'previous' => strip_tags(variable_get('colorbox_text_previous', '« Prev')),
'next' => strip_tags(variable_get('colorbox_text_next', 'Next »')),
'close' => strip_tags(variable_get('colorbox_text_close', 'Close')),
'overlayClose' => variable_get('colorbox_overlayclose', 1) ? TRUE : FALSE,
'maxWidth' => variable_get('colorbox_maxwidth', '98%'),
'maxHeight' => variable_get('colorbox_maxheight', '98%'),
@ -187,6 +189,8 @@ function _colorbox_doheader() {
'initialHeight' => variable_get('colorbox_initialheight', '250'),
'fixed' => variable_get('colorbox_fixed', 1) ? TRUE : FALSE,
'scrolling' => variable_get('colorbox_scrolling', 1) ? TRUE : FALSE,
'mobiledetect' => variable_get('colorbox_mobile_detect', 1) ? TRUE : FALSE,
'mobiledevicewidth' => variable_get('colorbox_mobile_device_width', '480px'),
);
}
else {
@ -199,6 +203,8 @@ function _colorbox_doheader() {
'maxWidth' => '98%',
'maxHeight' => '98%',
'fixed' => TRUE,
'mobiledetect' => variable_get('colorbox_mobile_detect', 1) ? TRUE : FALSE,
'mobiledevicewidth' => variable_get('colorbox_mobile_device_width', '480px'),
);
}
@ -213,7 +219,9 @@ function _colorbox_doheader() {
// Add and initialise the Colorbox plugin.
$variant = variable_get('colorbox_compression_type', 'minified');
libraries_load('colorbox', $variant);
if (module_exists('libraries')) {
libraries_load('colorbox', $variant);
}
drupal_add_js($path . '/js/colorbox.js');
// Add JS and CSS based on selected style.
@ -251,6 +259,7 @@ function colorbox_field_formatter_info() {
'field types' => array('image'),
'settings' => array(
'colorbox_node_style' => '',
'colorbox_node_style_first' => '',
'colorbox_image_style' => '',
'colorbox_gallery' => 'post',
'colorbox_gallery_custom' => '',
@ -280,6 +289,14 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $
'#options' => $image_styles_hide,
'#description' => t('Image style to use in the content.'),
);
$element['colorbox_node_style_first'] = array(
'#title' => t('Content image style for first image'),
'#type' => 'select',
'#default_value' => $settings['colorbox_node_style_first'],
'#empty_option' => t('No special style.'),
'#options' => $image_styles,
'#description' => t('Image style to use in the content for the first image.'),
);
$element['colorbox_image_style'] = array(
'#title' => t('Colorbox image style'),
'#type' => 'select',
@ -306,15 +323,12 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $
);
$element['colorbox_gallery_custom'] = array(
'#title' => t('Custom gallery'),
'#type' => 'machine_name',
'#type' => 'textfield',
'#maxlength' => 32,
'#default_value' => $settings['colorbox_gallery_custom'],
'#description' => t('All images on a page with the same gallery value (rel attribute) will be grouped together. It must only contain lowercase letters, numbers, and underscores.'),
'#description' => t('All images on a page with the same gallery value (rel attribute) will be grouped together. It must only contain lowercase letters, numbers, hyphen and underscores.'),
'#element_validate' => array('colorbox_gallery_custom_validate'),
'#required' => FALSE,
'#machine_name' => array(
'exists' => 'colorbox_gallery_exists',
'error' => t('The custom gallery field must only contain lowercase letters, numbers, and underscores.'),
),
'#states' => array(
'visible' => array(
':input[name$="[settings_edit_form][settings][colorbox_gallery]"]' => array('value' => 'custom'),
@ -335,7 +349,7 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $
'#type' => 'select',
'#default_value' => $settings['colorbox_caption'],
'#options' => $caption,
'#description' => t('Automatic will use the first none empty value of the title, the alt text and the content title.'),
'#description' => t('Automatic will use the first non-empty value of the title, the alt text and the content title.'),
);
$element['colorbox_caption_custom'] = array(
'#title' => t('Custom caption'),
@ -354,7 +368,7 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $
'#type' => 'fieldset',
'#title' => t('Replacement patterns'),
'#theme' => 'token_tree',
'#token_types' => array($instance['entity_type'], 'file'),
'#token_types' => array_merge(array_keys($field['bundles']),array('file')),
'#recursion_limit' => $recursion_limit,
'#dialog' => TRUE,
'#states' => array(
@ -380,6 +394,15 @@ function colorbox_field_formatter_settings_form($field, $instance, $view_mode, $
return $element;
}
/**
* Validate function for colorbox_gallery_custom.
*/
function colorbox_gallery_custom_validate($element, &$form_state) {
if (!empty($element['#value']) && !preg_match('!^[a-z0-9_-]+$!', $element['#value'])) {
form_error($element, t('%name must only contain lowercase letters, numbers, hyphen and underscores.', array('%name' => $element['#title'])));
}
}
/**
* Implements hook_field_formatter_settings_summary().
*/
@ -404,6 +427,10 @@ function colorbox_field_formatter_settings_summary($field, $instance, $view_mode
$summary[] = t('Content image style: Original image');
}
if (isset($image_styles[$settings['colorbox_node_style_first']])) {
$summary[] = t('Content image style of first image: @style', array('@style' => $image_styles[$settings['colorbox_node_style_first']]));
}
if (isset($image_styles[$settings['colorbox_image_style']])) {
$summary[] = t('Colorbox image style: @style', array('@style' => $image_styles[$settings['colorbox_image_style']]));
}
@ -455,6 +482,7 @@ function colorbox_field_formatter_view($entity_type, $entity, $field, $instance,
'#node' => $entity, // Left for legacy support.
'#field' => $field,
'#display_settings' => $display['settings'],
'#delta' => $delta,
);
}
}
@ -464,11 +492,14 @@ function colorbox_field_formatter_view($entity_type, $entity, $field, $instance,
/**
* Implements hook_insert_styles().
*
* @return array
*/
function colorbox_insert_styles() {
$insert_styles = array();
foreach (image_styles() as $key => $style) {
$insert_styles['colorbox__' . $key] = array('label' => t('Colorbox @style', array('@style' => $style['name'])));
$label = isset($style['label']) ? $style['label'] : $style['name'];
$insert_styles['colorbox__' . $key] = array('label' => t('Colorbox @style', array('@style' => $label)));
}
return $insert_styles;
@ -479,13 +510,13 @@ function colorbox_insert_styles() {
*/
function colorbox_insert_content($item, $style, $widget) {
list($item['module_name'], $item['style_name']) = explode('__', $style['name'], 2);
return theme('colorbox_insert_image', array('item' => $item, 'widget' => $widget));
return theme(array('colorbox_insert_image__' . str_replace('-', '_', $item['style_name']), 'colorbox_insert_image'), array('item' => $item, 'widget' => $widget));
}
/**
* Machine names normally need to be unique but that does not apply to galleries.
*
* @return
* @return false
* Always FALSE
*/
function colorbox_gallery_exists() {

View File

@ -8,15 +8,19 @@
/**
* Returns HTML for an Colorbox image field formatter.
*
* @param $variables
* @param array $variables
* An associative array containing:
* - item: An array of image data.
* - image_style: An optional image style.
* - path: An array containing the link 'path' and link 'options'.
*
* @return string
* An HTML string representing the themed output.
*
* @ingroup themeable
*/
function theme_colorbox_image_formatter($variables) {
static $gallery_token = NULL;
$item = $variables['item'];
$entity_type = $variables['entity_type'];
$entity = $variables['entity'];
@ -25,16 +29,40 @@ function theme_colorbox_image_formatter($variables) {
$image = array(
'path' => $item['uri'],
'alt' => $item['alt'],
'title' => $item['title'],
'alt' => isset($item['alt']) ? $item['alt'] : '',
'title' => isset($item['title']) ? $item['title'] : '',
'style_name' => $settings['colorbox_node_style'],
);
if ($variables['delta'] == 0 && !empty($settings['colorbox_node_style_first'])) {
$image['style_name'] = $settings['colorbox_node_style_first'];
}
if (isset($item['width']) && isset($item['height'])) {
$image['width'] = $item['width'];
$image['height'] = $item['height'];
}
if (isset($item['attributes'])) {
$image['attributes'] = $item['attributes'];
}
// Allow image attributes to be overridden.
if (isset($variables['item']['override']['attributes'])) {
foreach (array('width', 'height', 'alt', 'title') as $key) {
if (isset($variables['item']['override']['attributes'][$key])) {
$image[$key] = $variables['item']['override']['attributes'][$key];
unset($variables['item']['override']['attributes'][$key]);
}
}
if (isset($image['attributes'])) {
$image['attributes'] = $variables['item']['override']['attributes'] + $image['attributes'];
}
else {
$image['attributes'] = $variables['item']['override']['attributes'];
}
}
$entity_title = entity_label($entity_type, $entity);
switch ($settings['colorbox_caption']) {
@ -99,6 +127,16 @@ function theme_colorbox_image_formatter($variables) {
$gallery_id = '';
}
// If gallery id is not empty add unique per-request token to avoid images being added manually to galleries.
if (!empty($gallery_id) && variable_get('colorbox_unique_token', 1)) {
// Check if gallery token has already been set, we need to reuse the token for the whole request.
if (is_null($gallery_token)) {
// We use a short token since randomness is not critical.
$gallery_token = drupal_random_key(8);
}
$gallery_id = $gallery_id . '-' . $gallery_token;
}
if ($style_name = $settings['colorbox_image_style']) {
$path = image_style_url($style_name, $image['path']);
}
@ -112,13 +150,16 @@ function theme_colorbox_image_formatter($variables) {
/**
* Returns HTML for an image using a specific Colorbox image style.
*
* @param $variables
* @param array $variables
* An associative array containing:
* - image: image item as array.
* - path: The path of the image that should be displayed in the Colorbox.
* - title: The title text that will be used as a caption in the Colorbox.
* - gid: Gallery id for Colorbox image grouping.
*
* @return string
* An HTML string containing a link to the given path.
*
* @ingroup themeable
*/
function theme_colorbox_imagefield($variables) {
@ -135,45 +176,63 @@ function theme_colorbox_imagefield($variables) {
$image = theme('image', $variables['image']);
}
$options = array(
$options = drupal_parse_url($variables['path']);
$options += array(
'html' => TRUE,
'attributes' => array(
'title' => $variables['title'],
'class' => $class,
'rel' => $variables['gid'],
)
'data-colorbox-gallery' => $variables['gid'],
),
);
return l($image, $variables['path'], $options);
return l($image, $options['path'], $options);
}
/**
* Preprocess variables for the colorbox-insert-image.tpl.php file.
*
* @param array $variables
*/
function template_preprocess_colorbox_insert_image(&$variables) {
$class = array();
$file = file_load($variables['item']['fid']);
$item = $variables['item'];
$variables['file'] = file_load($item['fid']);
$variables['style_name'] = $item['style_name'];
$variables['width'] = isset($item['width']) ? $item['width'] : NULL;
$variables['height'] = isset($item['height']) ? $item['height'] : NULL;
// Determine dimensions of the image after the image style transformations.
image_style_transform_dimensions($variables['style_name'], $variables);
$class = array();
if (!empty($variables['widget']['settings']['insert_class'])) {
$class = explode(' ', $variables['widget']['settings']['insert_class']);
}
$class[] = 'image-' . $variables['item']['style_name'];
$class[] = 'image-' . $variables['style_name'];
foreach ($class as $key => $value) {
$class[$key] = drupal_html_class($value);
}
$variables['image_path'] = image_style_url($variables['item']['style_name'], $file->uri);
$variables['class'] = implode(' ', $class);
$variables['uri'] = image_style_path($variables['style_name'], $variables['file']->uri);
$absolute = isset($variables['widget']['settings']['insert_absolute']) ? $variables['widget']['settings']['insert_absolute'] : NULL;
$variables['url'] = insert_create_url($variables['uri'], $absolute, variable_get('clean_url'));
// http://drupal.org/node/1923336
if (function_exists('image_style_path_token')) {
$token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($variables['style_name'], $variables['file']->uri));
$variables['url'] .= (strpos($variables['url'], '?') !== FALSE ? '&' : '?') . drupal_http_build_query($token_query);
}
if ($style_name = variable_get('colorbox_image_style', '')) {
$variables['link_path'] = image_style_url($style_name, $file->uri);
$variables['path'] = image_style_url($style_name, $variables['file']->uri);
}
else {
$variables['link_path'] = file_create_url($file->uri);
$variables['path'] = file_create_url($variables['file']->uri);
}
$variables['class'] = implode(' ', $class);
$variables['gallery_id'] = '';
switch (variable_get('colorbox_insert_gallery', 0)) {
case 0:

View File

@ -23,7 +23,7 @@ define('COLORBOX_DOWNLOAD_PREFIX', 'colorbox-');
*
* See `drush topic docs-commands` for a list of recognized keys.
*
* @return
* @return array
* An associative array describing your command(s).
*/
function colorbox_drush_command() {
@ -49,10 +49,10 @@ function colorbox_drush_command() {
* This function is called whenever a drush user calls
* 'drush help <name-of-your-command>'
*
* @param
* @param string $section
* A string with the help section (prepend with 'drush:')
*
* @return
* @return string
* A string with the help text for your command.
*/
function colorbox_drush_help($section) {
@ -63,14 +63,14 @@ function colorbox_drush_help($section) {
}
/**
* Implements drush_MODULE_post_pm_enable().
* Implements drush_MODULE_pre_pm_enable().
*/
// function drush_colorbox_post_pm_enable() {
// $modules = func_get_args();
// if (in_array('colorbox', $modules)) {
// drush_colorbox_plugin();
// }
// }
function drush_colorbox_pre_pm_enable() {
$modules = drush_get_context('PM_ENABLE_MODULES');
if (in_array('colorbox', $modules) && !drush_get_option('skip')) {
drush_colorbox_plugin();
}
}
/**
* Command to download the Colorbox plugin.
@ -99,7 +99,7 @@ function drush_colorbox_plugin() {
$filename = basename($filepath);
$dirname = COLORBOX_DOWNLOAD_PREFIX . basename($filepath, '.zip');
// Remove any existing Colorbox plugin directory
// Remove any existing Colorbox plugin directory
if (is_dir($dirname) || is_dir('colorbox')) {
drush_delete_dir($dirname, TRUE);
drush_delete_dir('colorbox', TRUE);

View File

@ -2,19 +2,36 @@
Drupal.behaviors.initColorbox = {
attach: function (context, settings) {
if (!$.isFunction($.colorbox)) {
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
return;
}
if (settings.colorbox.mobiledetect && window.matchMedia) {
// Disable Colorbox for small screens.
var mq = window.matchMedia("(max-device-width: " + settings.colorbox.mobiledevicewidth + ")");
if (mq.matches) {
return;
}
}
// Use "data-colorbox-gallery" if set otherwise use "rel".
settings.colorbox.rel = function () {
if ($(this).data('colorbox-gallery')) {
return $(this).data('colorbox-gallery');
}
else {
return $(this).attr('rel');
}
};
$('.colorbox', context)
.once('init-colorbox')
.colorbox(settings.colorbox);
$(context).bind('cbox_complete', function () {
Drupal.attachBehaviors('#cboxLoadedContent');
});
}
};
{
$(document).bind('cbox_complete', function () {
Drupal.attachBehaviors('#cboxLoadedContent');
});
}
})(jQuery);

View File

@ -2,9 +2,18 @@
Drupal.behaviors.initColorboxInline = {
attach: function (context, settings) {
if (!$.isFunction($.colorbox)) {
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
return;
}
if (settings.colorbox.mobiledetect && window.matchMedia) {
// Disable Colorbox for small screens.
var mq = window.matchMedia("(max-device-width: " + settings.colorbox.mobiledevicewidth + ")");
if (mq.matches) {
return;
}
}
$.urlParam = function(name, url){
if (name == 'fragment') {
var results = new RegExp('(#[^&#]*)').exec(url);

View File

@ -2,9 +2,18 @@
Drupal.behaviors.initColorboxLoad = {
attach: function (context, settings) {
if (!$.isFunction($.colorbox)) {
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
return;
}
if (settings.colorbox.mobiledetect && window.matchMedia) {
// Disable Colorbox for small screens.
var mq = window.matchMedia("(max-device-width: " + settings.colorbox.mobiledevicewidth + ")");
if (mq.matches) {
return;
}
}
$.urlParams = function (url) {
var p = {},
e,

View File

@ -1,5 +1,5 @@
/**
* ColorBox Core Style:
* Colorbox Core Style:
* The following CSS is consistent between example themes and should not be altered.
*/
#colorbox, #cboxOverlay, #cboxWrapper {
@ -22,6 +22,7 @@
}
#cboxLoadedContent {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
#cboxTitle {
margin: 0;
@ -33,9 +34,26 @@
width: 100%;
height: 100%;
}
/**
* These elements are buttons, and may need to have additional
* styles reset to avoid unwanted base styles.
*/
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow {
border: 0;
padding: 0;
margin: 0;
overflow: visible;
width: auto;
background: none;
cursor: pointer;
}
/**
* Avoid outlines on :active (mouseclick),
* but preserve outlines on :focus (tabbed navigating)
*/
#cboxPrevious:active, #cboxNext:active, #cboxClose:active, #cboxSlideshow:active {
outline: 0;
}
.cboxPhoto {
float: left;
margin: auto;
@ -49,8 +67,10 @@
display: block;
border: 0;
}
/* Reset box sizing to content-box if theme is using border-box. */
#colorbox, #cboxContent, #cboxLoadedContent {
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
@ -62,8 +82,9 @@
#cboxOverlay {
background: #000;
}
#colorBox {}
#colorbox {
outline: 0;
}
#cboxWrapper {
background: #fff;
-moz-border-radius: 5px;
@ -101,7 +122,6 @@
#cboxContent {
background: #fff;
overflow: hidden;
font: 12px "Lucida Grande", Verdana, Arial, sans-serif;
}
#cboxError {
padding: 50px;
@ -118,6 +138,8 @@
color: #535353;
width: 100%;
padding: 4px 6px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#cboxCurrent {
@ -130,7 +152,7 @@
position: absolute;
bottom: 0px;
right: 30px;
background: url(images/controls.png) -75px -50px no-repeat;
background: url(images/controls.png) no-repeat -75px -50px;
width: 25px;
height: 25px;
text-indent: -9999px;
@ -142,19 +164,19 @@
position: absolute;
bottom: 0px;
right: 30px;
background: url(images/controls.png) -49px -50px no-repeat;
background: url(images/controls.png) no-repeat -25px -50px;
width: 25px;
height: 25px;
text-indent: -9999px;
}
.cboxSlideshow_off #cboxSlideshow:hover {
background-position: -25px -50px;
background-position: -49px -50px;
}
#cboxPrevious {
position: absolute;
bottom: 0;
left: 0;
background: url(images/controls.png) -75px 0px no-repeat;
background: url(images/controls.png) no-repeat -75px 0px;
width: 25px;
height: 25px;
text-indent: -9999px;
@ -166,7 +188,7 @@
position: absolute;
bottom: 0;
left: 27px;
background: url(images/controls.png) -50px 0px no-repeat;
background: url(images/controls.png) no-repeat -50px 0px;
width: 25px;
height: 25px;
text-indent: -9999px;
@ -178,13 +200,13 @@
background: #fff;
}
#cboxLoadingGraphic {
background: url(images/loading_animation.gif) center center no-repeat;
background: url(images/loading_animation.gif) no-repeat center center;
}
#cboxClose {
position: absolute;
bottom: 0;
right: 0;
background: url(images/controls.png) -25px 0px no-repeat;
background: url(images/controls.png) no-repeat -25px 0px;
width: 25px;
height: 25px;
text-indent: -9999px;

View File

@ -2,10 +2,9 @@
Drupal.behaviors.initColorboxDefaultStyle = {
attach: function (context, settings) {
$(document).bind('cbox_complete', function () {
$(context).bind('cbox_complete', function () {
// Only run if there is a title.
if ($('#cboxTitle:empty', context).length == false) {
setTimeout(function () { $('#cboxTitle', context).slideUp() }, 1500);
$('#cboxLoadedContent img', context).bind('mouseover', function () {
$('#cboxTitle', context).slideDown();
});

View File

@ -1,5 +1,5 @@
/**
* ColorBox Core Style:
* Colorbox Core Style:
* The following CSS is consistent between example themes and should not be altered.
*/
#colorbox, #cboxOverlay, #cboxWrapper {
@ -22,6 +22,7 @@
}
#cboxLoadedContent {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
#cboxTitle {
margin: 0;
@ -33,9 +34,26 @@
width: 100%;
height: 100%;
}
/**
* These elements are buttons, and may need to have additional
* styles reset to avoid unwanted base styles.
*/
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow {
border: 0;
padding: 0;
margin: 0;
overflow: visible;
width: auto;
background: none;
cursor: pointer;
}
/**
* Avoid outlines on :active (mouseclick),
* but preserve outlines on :focus (tabbed navigating)
*/
#cboxPrevious:active, #cboxNext:active, #cboxClose:active, #cboxSlideshow:active {
outline: 0;
}
.cboxPhoto {
float: left;
margin: auto;
@ -49,8 +67,10 @@
display: block;
border: 0;
}
/* Reset box sizing to content-box if theme is using border-box. */
#colorbox, #cboxContent, #cboxLoadedContent {
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
@ -62,12 +82,12 @@
#cboxOverlay {
background: #000;
}
#colorBox {}
#colorbox {
outline: 0;
}
#cboxWrapper {}
#cboxContent {
overflow: hidden;
font: 12px "Lucida Grande", Verdana, Arial, sans-serif;
}
#cboxContent, .cboxPhoto {
-webkit-border-radius: 5px;
@ -87,6 +107,7 @@
width: 100%;
padding: 4px 6px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
@ -100,12 +121,12 @@
background: #fff;
}
#cboxLoadingGraphic {
background: url(images/loading_animation.gif) center center no-repeat;
background: url(images/loading_animation.gif) no-repeat center center;
}
.cbox-close-plain {
#cboxClose.cbox-close-plain {
position: absolute;
font-size: 20px;
line-height: 18px;;
line-height: 18px;
text-align: center;
color: rgba(255, 255, 255, 0.7);
background: rgba(0, 0, 0, 0.5);

View File

@ -2,7 +2,7 @@
Drupal.behaviors.initColorboxPlainStyle = {
attach: function (context, settings) {
$(document).bind('cbox_complete', function () {
$(context).bind('cbox_complete', function () {
// Make all the controls invisible.
$('#cboxCurrent, #cboxSlideshow, #cboxPrevious, #cboxNext', context).addClass('element-invisible');
// Replace "Close" with "×" and show.
@ -24,7 +24,7 @@ Drupal.behaviors.initColorboxPlainStyle = {
}
});
});
$(document).bind('cbox_closed', function () {
$(context).bind('cbox_closed', function () {
$('#cboxClose', context).removeClass('cbox-close-plain');
});
}

View File

@ -1,5 +1,5 @@
/**
* ColorBox Core Style:
* Colorbox Core Style:
* The following CSS is consistent between example themes and should not be altered.
*/
#colorbox, #cboxOverlay, #cboxWrapper {
@ -22,6 +22,7 @@
}
#cboxLoadedContent {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
#cboxTitle {
margin: 0;
@ -33,9 +34,26 @@
width: 100%;
height: 100%;
}
/**
* These elements are buttons, and may need to have additional
* styles reset to avoid unwanted base styles.
*/
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow {
border: 0;
padding: 0;
margin: 0;
overflow: visible;
width: auto;
background: none;
cursor: pointer;
}
/**
* Avoid outlines on :active (mouseclick),
* but preserve outlines on :focus (tabbed navigating)
*/
#cboxPrevious:active, #cboxNext:active, #cboxClose:active, #cboxSlideshow:active {
outline: 0;
}
.cboxPhoto {
float: left;
margin: auto;
@ -49,8 +67,10 @@
display: block;
border: 0;
}
/* Reset box sizing to content-box if theme is using border-box. */
#colorbox, #cboxContent, #cboxLoadedContent {
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
@ -61,7 +81,6 @@
*/
#cboxOverlay {
background: #000;
opacity: 0.4 !important;
}
#colorbox {
@ -75,6 +94,7 @@
-webkit-border-bottom-right-radius: 9px;
border-bottom-left-radius: 9px;
border-bottom-right-radius: 9px;
outline: 0;
}
#colorbox, #colorbox div {
overflow: visible; /* Required by the close button. */
@ -118,7 +138,6 @@
#cboxContent {
background: #fff;
overflow: hidden;
font: 11px Arial, sans-serif;
margin-bottom: 28px;
}
#cboxError {
@ -132,8 +151,9 @@
height: 38px;
color: #313131;
padding: 0 140px 0 15px;
display: table-cell;
display: table-cell !important;
vertical-align: middle;
float: none !important;
}
#cboxCurrent {
position: absolute;
@ -158,7 +178,7 @@
position: absolute;
bottom: -26px;
right: 45px;
background: url(images/controls.png) 0 -48px no-repeat;
background: url(images/controls.png) no-repeat 0 -48px;
width: 21px;
height: 15px;
text-indent: -9999px;
@ -170,7 +190,7 @@
position: absolute;
bottom: -26px;
right: 15px;
background: url(images/controls.png) 0 -29px no-repeat;
background: url(images/controls.png) no-repeat 0 -29px;
width: 21px;
height: 15px;
text-indent: -9999px;
@ -182,13 +202,13 @@
background: #e6e6e6;
}
#cboxLoadingGraphic {
background: url(images/loading_animation.gif) center center no-repeat;
background: url(images/loading_animation.gif) no-repeat center center;
}
#cboxClose {
position: absolute;
top: -10px;
right: -10px;
background: url(images/controls.png) 0px 0px no-repeat;
background: url(images/controls.png) no-repeat 0px 0px;
width: 25px;
height: 25px;
text-indent: -9999px;

View File

@ -2,15 +2,15 @@
Drupal.behaviors.initColorboxStockholmsyndromeStyle = {
attach: function (context, settings) {
$(document).bind('cbox_open', function () {
$(context).bind('cbox_open', function () {
// Hide close button initially.
$('#cboxClose', context).css('opacity', 0);
});
$(document).bind('cbox_load', function () {
$(context).bind('cbox_load', function () {
// Hide close button. (It doesn't handle the load animation well.)
$('#cboxClose', context).css('opacity', 0);
});
$(document).bind('cbox_complete', function () {
$(context).bind('cbox_complete', function () {
// Show close button with a delay.
$('#cboxClose', context).fadeTo('fast', 0, function () {$(this).css('opacity', 1)});
});

View File

@ -109,7 +109,7 @@ If you would like to have the characters %5B and %5D please use the html entity
$form['custom_gid'] = array(
'#type' => 'textfield',
'#title' => t('Custom Colorbox gallery'),
'#description' => t('Enable Colorbox gallery with a given string as gallery. Overrides the automatically generated gallery id above.'),
'#description' => t('Enable Colorbox gallery with a given string as gallery. Overrides the automatically generated gallery id above. You may enter data from this view as per the "Replacement patterns" below.'),
'#default_value' => $this->options['custom_gid'],
'#weight' => -8,
);
@ -162,12 +162,19 @@ If you would like to have the characters %5B and %5D please use the html entity
$tokens = $this->get_render_tokens($this->options['alter']);
$popup = filter_xss_admin($this->options['popup']);
$caption = filter_xss_admin($this->options['caption']);
$gallery = filter_xss_admin($this->options['custom_gid']);
$popup = strtr($popup, $tokens);
$caption = strtr($caption, $tokens);
$gallery = drupal_html_class(strtr($gallery, $tokens));
// Return nothing if popup is empty.
if (empty($popup)) {
return;
}
$width = $this->options['width'] ? $this->options['width'] : '';
$height = $this->options['height'] ? $this->options['height'] : '';
$gallery_id = !empty($this->options['custom_gid']) ? $this->options['custom_gid'] : ($this->options['gid'] ? 'gallery-' . $this->view->name : '');
$gallery_id = !empty($gallery) ? $gallery : ($this->options['gid'] ? 'gallery-' . $this->view->name : '');
$link_text = $tokens["[{$this->options['trigger_field']}]"];
$link_options = array(
'html' => TRUE,

View File

@ -6,9 +6,9 @@ package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -2,16 +2,15 @@ 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 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -23,7 +23,7 @@ define('CTOOLS_API_VERSION', '2.0.8');
* ; Requires CTools v7.x-1.4 or newer.
* dependencies[] = ctools (>=1.4)
*/
define('CTOOLS_MODULE_VERSION', '7.x-1.7');
define('CTOOLS_MODULE_VERSION', '7.x-1.10');
/**
* Test the CTools API version.
@ -617,6 +617,27 @@ function ctools_registry_files_alter(&$files, $indexed_modules) {
return _ctools_registry_files_alter($files, $indexed_modules);
}
// -----------------------------------------------------------------------
// FAPI hooks that must be in the .module file.
/**
* Alter the comment form to get a little more control over it.
*/
function ctools_form_comment_form_alter(&$form, &$form_state) {
if (!empty($form_state['ctools comment alter'])) {
// Force the form to post back to wherever we are.
$form['#action'] = url($_GET['q'], array('fragment' => 'comment-form'));
if (empty($form['#submit'])) {
$form['#submit'] = array('comment_form_submit');
}
$form['#submit'][] = 'ctools_node_comment_form_submit';
}
}
function ctools_node_comment_form_submit(&$form, &$form_state) {
$form_state['redirect'][0] = $_GET['q'];
}
// -----------------------------------------------------------------------
// CTools hook implementations.
@ -737,6 +758,12 @@ function ctools_process(&$variables, $hook) {
$variables['classes_array'] = array_diff($variables['classes_array'], $remove_classes);
}
// Update the classes within the attributes array to match the classes array
if (isset($variables['attributes_array']['class'])) {
$variables['attributes_array']['class'] = $variables['classes_array'];
$variables['attributes'] = $variables['attributes_array'] ? drupal_attributes($variables['attributes_array']) : '';
}
// Since this runs after template_process(), we need to re-implode the
// classes array.
$variables['classes'] = implode(' ', $variables['classes_array']);
@ -1018,3 +1045,50 @@ function ctools_ctools_entity_context_alter(&$plugin, &$entity, $plugin_id) {
}
}
}
/**
* Implements hook_field_create_field().
*/
function ctools_field_create_field($field) {
ctools_flush_field_caches();
}
/**
* Implements hook_field_create_instance().
*/
function ctools_field_create_instance($instance) {
ctools_flush_field_caches();
}
/**
* Implements hook_field_delete_field().
*/
function ctools_field_delete_field($field) {
ctools_flush_field_caches();
}
/**
* Implements hook_field_delete_instance().
*/
function ctools_field_delete_instance($instance) {
ctools_flush_field_caches();
}
/**
* Implements hook_field_update_field().
*/
function ctools_field_update_field($field, $prior_field, $has_data) {
ctools_flush_field_caches();
}
/**
* Implements hook_field_update_instance().
*/
function ctools_field_update_instance($instance, $prior_instance) {
ctools_flush_field_caches();
}
/**
* Clear field related caches.
*/
function ctools_flush_field_caches() {
// Clear caches of 'Entity field' content type plugin.
cache_clear_all('ctools_entity_field_content_type_content_types', 'cache');
}

View File

@ -5,9 +5,9 @@ package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -5,9 +5,9 @@ version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
core = 7.x
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -524,7 +524,7 @@ function ctools_ajax_sample_wizard_next(&$form_state) {
}
/**
* Handle the 'finish' click on teh add/edit pane form wizard.
* Handle the 'finish' click on the add/edit pane form wizard.
*
* All we need to do is set a flag so the return can handle adding
* the pane.

View File

@ -5,9 +5,9 @@ package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -23,6 +23,22 @@ class ctools_custom_content_ui extends ctools_export_ui {
'#title' => t('Title'),
);
$form['title_heading'] = array(
'#title' => t('Title heading'),
'#type' => 'select',
'#default_value' => isset($form_state['item']->settings['title_heading']) ? $form_state['item']->settings['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'),
),
);
$form['body'] = array(
'#type' => 'text_format',
'#title' => t('Body'),
@ -43,6 +59,7 @@ class ctools_custom_content_ui extends ctools_export_ui {
// Since items in our settings are not in the schema, we have to do these manually:
$form_state['item']->settings['title'] = $form_state['values']['title'];
$form_state['item']->settings['title_heading'] = $form_state['values']['title_heading'];
$form_state['item']->settings['body'] = $form_state['values']['body']['value'];
$form_state['item']->settings['format'] = $form_state['values']['body']['format'];
$form_state['item']->settings['substitute'] = $form_state['values']['substitute'];

View File

@ -8,9 +8,9 @@ dependencies[] = page_manager
dependencies[] = advanced_help
core = 7.x
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -341,7 +341,16 @@ function ctools_content_editable($type, $subtype, $conf) {
return FALSE;
}
if ($function = ctools_plugin_get_function($subtype, 'check editable')) {
$function = FALSE;
if (!empty($subtype['check editable'])) {
$function = ctools_plugin_get_function($subtype, 'check editable');
}
elseif (!empty($type['check editable'])) {
$function = ctools_plugin_get_function($type, 'check editable');
}
if ($function) {
return $function($type, $subtype, $conf);
}

View File

@ -736,6 +736,15 @@ function ctools_edit_context_form_defaults($form, &$form_state) {
'#default_value' => $conf['keyword'],
);
if ($type_info['key'] == 'requiredcontexts') {
$form['optional'] = array(
'#type' => 'checkbox',
'#title' => t('Context is optional'),
'#default_value' => !empty($form_state['conf']['optional']),
'#description' => t('This context need not be present for the component to function.'),
);
}
$form['#submit'][] = 'ctools_edit_context_form_defaults_submit';
return $form;
@ -752,6 +761,9 @@ function ctools_edit_context_form_defaults_submit(&$form, &$form_state) {
$form_state['conf']['default'] = $form_state['values']['default'];
$form_state['conf']['title'] = $form_state['values']['title'];
}
if ($form_state['type info']['key'] == 'requiredcontexts') {
$form_state['conf']['optional'] = $form_state['values']['optional'];
}
$form_state['conf']['identifier'] = $form_state['values']['identifier'];
$form_state['conf']['keyword'] = $form_state['values']['keyword'];

View File

@ -42,7 +42,7 @@ class ctools_context {
var $restrictions = array();
var $empty = FALSE;
function ctools_context($type = 'none', $data = NULL) {
function __construct($type = 'none', $data = NULL) {
$this->type = $type;
$this->data = $data;
$this->title = t('Unknown context');
@ -119,7 +119,7 @@ class ctools_context_required {
* @param ...
* One or more keywords to use for matching which contexts are allowed.
*/
function ctools_context_required($title) {
function __construct($title) {
$args = func_get_args();
$this->title = array_shift($args);
@ -204,10 +204,6 @@ class ctools_context_required {
*/
class ctools_context_optional extends ctools_context_required {
var $required = FALSE;
function ctools_context_optional() {
$args = func_get_args();
call_user_func_array(array($this, 'ctools_context_required'), $args);
}
/**
* Add the 'empty' context which is possible for optional
@ -216,7 +212,7 @@ class ctools_context_optional extends ctools_context_required {
$context = new ctools_context('any');
$context->title = t('No context');
$context->identifier = t('No context');
$contexts = array_merge(array('empty' => $context), $contexts);
$contexts['empty'] = $context;
}
function filter($contexts) {
@ -1163,7 +1159,7 @@ function ctools_context_match_required_contexts($required, $contexts) {
}
foreach ($required as $r) {
$context = clone(array_shift($contexts));
$context = clone array_shift($contexts);
$context->identifier = $r['identifier'];
$context->page_title = isset($r['title']) ? $r['title'] : '';
$context->keyword = $r['keyword'];
@ -1505,7 +1501,7 @@ function ctools_access($settings, $contexts = array()) {
return TRUE;
}
else if (!$pass && $settings['logic'] == 'and') {
// Fail if 'and' and htis rule failed.
// Fail if 'and' and this rule failed.
return FALSE;
}
}

View File

@ -172,10 +172,12 @@ function ctools_css_cache($css, $filter = TRUE) {
// @todo Is this slow? Does it matter if it is?
$filename = $path . '/' . md5($css) . '.css';
// This will do renames if the file already exists, ensuring we don't
// accidentally overwrite other files who share the same md5. Yes this
// is a very miniscule chance but it's safe.
$filename = file_unmanaged_save_data($css, $filename);
// Generally md5 is considered unique enough to sign file downloads.
// So this replaces already existing files based on the assumption that two
// files with the same hash are identical content wise.
// If we rename, the cache folder can potentially fill up with thousands of
// files with the same content.
$filename = file_unmanaged_save_data($css, $filename, FILE_EXISTS_REPLACE);
return $filename;
}

View File

@ -1227,7 +1227,7 @@ function ctools_export_default_to_hook_code($schema, $table, $names, $name) {
$output .= " \${$export['identifier']}s = array();\n\n";
foreach ($objects as $object) {
$output .= ctools_export_crud_export($table, $object, ' ');
$output .= " \${$export['identifier']}s['" . check_plain($object->$export['key']) . "'] = \${$export['identifier']};\n\n";
$output .= " \${$export['identifier']}s['" . check_plain($object->{$export['key']}) . "'] = \${$export['identifier']};\n\n";
}
$output .= " return \${$export['identifier']}s;\n";
$output .= "}\n";

View File

@ -137,7 +137,7 @@ function ctools_fields_get_field_formatter_settings_form($field, $formatter_type
*/
function ctools_fields_get_field_formatter_info($fields) {
$info = array();
$field_info = module_invoke_all('field_formatter_info');
$field_info = field_info_formatter_types();
foreach ($fields as $field) {
foreach ($field_info as $format_name => $formatter_info) {
if (in_array($field['type'], $formatter_info['field types'])) {
@ -145,7 +145,6 @@ function ctools_fields_get_field_formatter_info($fields) {
}
}
}
drupal_alter('field_formatter_info', $info);
return $info;
}

View File

@ -51,7 +51,7 @@ function ctools_jump_menu($form, &$form_state, $select, $options = array()) {
'hide' => TRUE,
);
ctools_add_js('jump-menu');
$form['#attached']['js'][] = ctools_attach_js('jump-menu');
if (!empty($options['choose'])) {
$select = array('' => $options['choose']) + $select;

View File

@ -99,7 +99,7 @@ class ctools_math_expr {
'sqrt','abs','ln','log',
'time', 'ceil', 'floor', 'min', 'max', 'round');
function ctools_math_expr() {
function __construct() {
// make the variables a little more accurate
$this->v['pi'] = pi();
$this->v['e'] = exp(1);
@ -271,7 +271,7 @@ class ctools_math_expr {
} elseif (in_array($op, $ops) and !$expecting_op) {
return $this->trigger("unexpected operator '$op'");
} else { // I don't even want to know what you did to get here
return $this->trigger("an unexpected error occured");
return $this->trigger("an unexpected error occurred");
}
if ($index == strlen($expr)) {
if (in_array($op, $ops)) { // did we end with an operator? bad.

View File

@ -66,6 +66,7 @@ function ctools_modal_add_js() {
drupal_add_library('system', 'jquery.form');
drupal_add_library('system', 'drupal.progress');
drupal_add_library('system', 'drupal.ajax');
drupal_add_library('system', 'ui');
ctools_add_js('modal');
ctools_add_css('modal');

View File

@ -79,7 +79,9 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
}
// Only process if version is between minimum and current, inclusive.
if (version_compare($version, $minimum_version, '>=') && version_compare($version, $current_version, '<=')) {
if (($version == $minimum_version) || ($version == $current_version)
|| (version_compare($version, $minimum_version, '>=')
&& version_compare($version, $current_version, '<='))) {
if (!isset($info['path'])) {
$info['path'] = drupal_get_path('module', $module);
}
@ -110,7 +112,7 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
}
// Allow other modules to hook in.
drupal_alter($hook, $cache[$owner][$api]);
drupal_alter($hook, $cache[$owner][$api], $owner, $api);
}
return $cache[$owner][$api];
@ -213,7 +215,7 @@ 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.
// lookups every time.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array());
@ -472,7 +474,7 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
}
else {
require_once DRUPAL_ROOT . '/' . $file->uri;
include_once DRUPAL_ROOT . '/' . $file->uri;
// .inc files have a special format for the hook identifier.
// For example, 'foo.inc' in the module 'mogul' using the plugin
// whose hook is named 'borg_type' should have a function named (deep breath)

View File

@ -500,7 +500,7 @@ class ctools_stylizer_image_processor {
$palette[$luminosity_input]['green'] = $green;
$palette[$luminosity_input]['blue'] = $blue;
// Now we complete the palette, first we'll do it tothe black, and then to
// Now we complete the palette, first we'll do it to the black, and then to
// the white.
// From input to black

View File

@ -25,7 +25,8 @@ function _ctools_uuid_generate_com() {
* Generates an universally unique identifier using the PECL extension.
*/
function _ctools_uuid_generate_pecl() {
return uuid_create(UUID_TYPE_DEFAULT);
$uuid_type = UUID_TYPE_DEFAULT;
return uuid_create($uuid_type);
}
/**

View File

@ -97,7 +97,13 @@
else {
switch ($(trigger).attr('type')) {
case 'checkbox':
var val = $(trigger).attr('checked') ? true : false;
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if ($().prop) {
var val = $(trigger).prop('checked') ? true : false;
}
else {
var val = $(trigger).attr('checked') ? true : false;
}
if (val) {
$(trigger).siblings('label').removeClass('hidden-options').addClass('expanded-options');
@ -148,34 +154,41 @@
len++;
}
var object = $('#' + id + '-wrapper');
if (!object.size()) {
// Some elements can't use the parent() method or they can
// damage things. They are guaranteed to have wrappers but
// only if dependent.inc provided them. This check prevents
// problems when multiple AJAX calls cause settings to build
// up.
var $original = $('#' + id);
if ($original.is('fieldset') || $original.is('textarea')) {
continue;
}
object = $('#' + id).parent();
var $original = $('#' + id);
if ($original.is('fieldset') || $original.is('textarea')) {
continue;
}
var object = $original.parent();
if (Drupal.settings.CTools.dependent[id].type == 'disable') {
if (Drupal.settings.CTools.dependent[id].num <= len) {
// Show if the element if criteria is matched
object.attr('disabled', false);
object.addClass('dependent-options');
object.children().attr('disabled', false);
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if (typeof $().prop == 'function') {
object.prop('disabled', false);
object.addClass('dependent-options');
object.children().prop('disabled', false);
}
else {
object.attr('disabled', false);
object.addClass('dependent-options');
object.children().attr('disabled', false);
}
}
else {
// Otherwise hide. Use css rather than hide() because hide()
// does not work if the item is already hidden, for example,
// in a collapsed fieldset.
object.attr('disabled', true);
object.children().attr('disabled', true);
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if (typeof $().prop == 'function') {
object.prop('disabled', true);
object.children().prop('disabled', true);
}
else {
object.attr('disabled', true);
object.children().attr('disabled', true);
}
}
}
else {

View File

@ -48,7 +48,8 @@
modalOptions: {
opacity: .55,
background: '#fff'
}
},
modalClass: 'default'
};
var settings = {};
@ -97,8 +98,8 @@
resize();
$('span.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText);
Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed);
$('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme));
Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed, settings.modalClass);
$('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme)).addClass('ctools-modal-loading');
// Position autocomplete results based on the scroll position of the modal.
$('#modalContent .modal-content').delegate('input.form-autocomplete', 'keyup', function() {
@ -120,18 +121,18 @@
*/
Drupal.theme.prototype.CToolsModalDialog = function () {
var html = ''
html += ' <div id="ctools-modal">'
html += ' <div class="ctools-modal-content">' // panels-modal-content
html += ' <div class="modal-header">';
html += ' <a class="close" href="#">';
html += Drupal.CTools.Modal.currentSettings.closeText + Drupal.CTools.Modal.currentSettings.closeImage;
html += ' </a>';
html += ' <span id="modal-title" class="modal-title">&nbsp;</span>';
html += ' </div>';
html += ' <div id="modal-content" class="modal-content">';
html += ' </div>';
html += '<div id="ctools-modal">'
html += ' <div class="ctools-modal-content">' // panels-modal-content
html += ' <div class="modal-header">';
html += ' <a class="close" href="#">';
html += Drupal.CTools.Modal.currentSettings.closeText + Drupal.CTools.Modal.currentSettings.closeImage;
html += ' </a>';
html += ' <span id="modal-title" class="modal-title">&nbsp;</span>';
html += ' </div>';
html += ' <div id="modal-content" class="modal-content">';
html += ' </div>';
html += ' </div>';
html += '</div>';
return html;
}
@ -141,11 +142,11 @@
*/
Drupal.theme.prototype.CToolsModalThrobber = function () {
var html = '';
html += ' <div id="modal-throbber">';
html += ' <div class="modal-throbber-wrapper">';
html += Drupal.CTools.Modal.currentSettings.throbber;
html += ' </div>';
html += '<div id="modal-throbber">';
html += ' <div class="modal-throbber-wrapper">';
html += Drupal.CTools.Modal.currentSettings.throbber;
html += ' </div>';
html += '</div>';
return html;
};
@ -264,7 +265,10 @@
}
// An empty event means we were triggered via .click() and
// in jquery 1.4 this won't trigger a submit.
if (event.bubbles == undefined) {
// We also have to check jQuery version to prevent
// IE8 + jQuery 1.4.4 to break on other events
// bound to the submit button.
if (jQuery.fn.jquery === '1.4' && typeof event.bubbles === "undefined") {
$(this.form).trigger('submit');
return false;
}
@ -299,6 +303,17 @@
// Attach behaviors within a modal dialog.
var settings = response.settings || ajax.settings || Drupal.settings;
Drupal.attachBehaviors('#modalContent', settings);
if ($('#modal-content').hasClass('ctools-modal-loading')) {
$('#modal-content').removeClass('ctools-modal-loading');
}
else {
// If the modal was already shown, and we are simply replacing its
// content, then focus on the first focusable element in the modal.
// (When first showing the modal, focus will be placed on the close
// button by the show() function called above.)
$('#modal-content :focusable:first').focus();
}
}
/**
@ -349,8 +364,9 @@
* @param css obj of css attributes
* @param animation (fadeIn, slideDown, show)
* @param speed (valid animation speeds slow, medium, fast or # in ms)
* @param modalClass class added to div#modalContent
*/
Drupal.CTools.Modal.modalContent = function(content, css, animation, speed) {
Drupal.CTools.Modal.modalContent = function(content, css, animation, speed, modalClass) {
// If our animation isn't set, make it just show/pop
if (!animation) {
animation = 'show';
@ -402,9 +418,56 @@
if( docHeight < winHeight ) docHeight = winHeight;
// Create our divs
$('body').append('<div id="modalBackdrop" style="z-index: 1000; display: none;"></div><div id="modalContent" style="z-index: 1001; position: absolute;">' + $(content).html() + '</div>');
$('body').append('<div id="modalBackdrop" class="backdrop-' + modalClass + '" style="z-index: 1000; display: none;"></div><div id="modalContent" class="modal-' + modalClass + '" style="z-index: 1001; position: absolute;">' + $(content).html() + '</div>');
// Keyboard and focus event handler ensures focus stays on modal elements only
// Get a list of the tabbable elements in the modal content.
var getTabbableElements = function () {
var tabbableElements = $('#modalContent :tabbable'),
radioButtons = tabbableElements.filter('input[type="radio"]');
// The list of tabbable elements from jQuery is *almost* right. The
// exception is with groups of radio buttons. The list from jQuery will
// include all radio buttons, when in fact, only the selected radio button
// is tabbable, and if no radio buttons in a group are selected, then only
// the first is tabbable.
if (radioButtons.length > 0) {
// First, build up an index of which groups have an item selected or not.
var anySelected = {};
radioButtons.each(function () {
var name = this.name;
if (typeof anySelected[name] === 'undefined') {
anySelected[name] = radioButtons.filter('input[name="' + name + '"]:checked').length !== 0;
}
});
// Next filter out the radio buttons that aren't really tabbable.
var found = {};
tabbableElements = tabbableElements.filter(function () {
var keep = true;
if (this.type == 'radio') {
if (anySelected[this.name]) {
// Only keep the selected one.
keep = this.checked;
}
else {
// Only keep the first one.
if (found[this.name]) {
keep = false;
}
found[this.name] = true;
}
}
return keep;
});
}
return tabbableElements.get();
};
// Keyboard and focus event handler ensures only modal elements gain focus.
modalEventHandler = function( event ) {
target = null;
if ( event ) { //Mozilla
@ -428,7 +491,7 @@
return true;
}
else {
$('#modalContent').focus();
getTabbableElements()[0].focus();
}
event.preventDefault();
@ -436,6 +499,59 @@
$('body').bind( 'focus', modalEventHandler );
$('body').bind( 'keypress', modalEventHandler );
// Keypress handler Ensures you can only TAB to elements within the modal.
// Based on the psuedo-code from WAI-ARIA 1.0 Authoring Practices section
// 3.3.1 "Trapping Focus".
modalTabTrapHandler = function (evt) {
// We only care about the TAB key.
if (evt.which != 9) {
return true;
}
var tabbableElements = getTabbableElements(),
firstTabbableElement = tabbableElements[0],
lastTabbableElement = tabbableElements[tabbableElements.length - 1],
singleTabbableElement = firstTabbableElement == lastTabbableElement,
node = evt.target;
// If this is the first element and the user wants to go backwards, then
// jump to the last element.
if (node == firstTabbableElement && evt.shiftKey) {
if (!singleTabbableElement) {
lastTabbableElement.focus();
}
return false;
}
// If this is the last element and the user wants to go forwards, then
// jump to the first element.
else if (node == lastTabbableElement && !evt.shiftKey) {
if (!singleTabbableElement) {
firstTabbableElement.focus();
}
return false;
}
// If this element isn't in the dialog at all, then jump to the first
// or last element to get the user into the game.
else if ($.inArray(node, tabbableElements) == -1) {
// Make sure the node isn't in another modal (ie. WYSIWYG modal).
var parents = $(node).parents().get();
for (var i = 0; i < parents.length; ++i) {
var position = $(parents[i]).css('position');
if (position == 'absolute' || position == 'fixed') {
return true;
}
}
if (evt.shiftKey) {
lastTabbableElement.focus();
}
else {
firstTabbableElement.focus();
}
}
};
$('body').bind('keydown', modalTabTrapHandler);
// Create our content div, get the dimensions, and hide it
var modalContent = $('#modalContent').css('top','-1000px');
var mdcTop = wt + ( winHeight / 2 ) - ( modalContent.outerHeight() / 2);
@ -457,12 +573,19 @@
$(document).bind('keydown', modalEventEscapeCloseHandler);
// Per WAI-ARIA 1.0 Authoring Practices, initial focus should be on the
// close button, but we should save the original focus to restore it after
// the dialog is closed.
var oldFocus = document.activeElement;
$('.close').focus();
// Close the open modal content and backdrop
function close() {
// Unbind the events
$(window).unbind('resize', modalContentResize);
$('body').unbind( 'focus', modalEventHandler);
$('body').unbind( 'keypress', modalEventHandler );
$('body').unbind( 'keydown', modalTabTrapHandler );
$('.close').unbind('click', modalContentClose);
$('body').unbind('keypress', modalEventEscapeCloseHandler);
$(document).trigger('CToolsDetachBehaviors', $('#modalContent'));
@ -478,12 +601,19 @@
// Remove the content
$('#modalContent').remove();
$('#modalBackdrop').remove();
// Restore focus to where it was before opening the dialog
$(oldFocus).focus();
};
// Move and resize the modalBackdrop and modalContent on resize of the window
modalContentResize = function(){
// Move and resize the modalBackdrop and modalContent on window resize.
modalContentResize = function(){
// position code lifted from http://www.quirksmode.org/viewport/compatibility.html
// Reset the backdrop height/width to get accurate document size.
$('#modalBackdrop').css('height', '').css('width', '');
// 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
@ -509,8 +639,6 @@
modalContent.css('top', mdcTop + 'px').css('left', mdcLeft + 'px').show();
};
$(window).bind('resize', modalContentResize);
$('#modalContent').focus();
};
/**
@ -533,7 +661,9 @@
$(window).unbind('resize', modalContentResize);
$('body').unbind('focus', modalEventHandler);
$('body').unbind('keypress', modalEventHandler);
$('body').unbind( 'keydown', modalTabTrapHandler );
$('.close').unbind('click', modalContentClose);
$('body').unbind('keypress', modalEventEscapeCloseHandler);
$(document).trigger('CToolsDetachBehaviors', $('#modalContent'));
// jQuery magic loop through the instances and run the animations or removal.

View File

@ -0,0 +1,43 @@
/**
* @file
* Custom state for handling visibility
*/
/**
* Add a new state to Drupal #states. We use this to toggle element-invisible
* to show/hidden #states elements. This allows elements to be visible to
* screen readers.
*
* To use:
* $form['my_form_field'] = array(
* ..
* // Only show this field if 'some_other_field' is checked.
* '#states => array(
* 'show' => array(
* 'some-other-field' => array('checked' => TRUE),
* ),
* ),
* ..
* // Required to load the 'show' state handler.
* '#attached' => array(
* 'js' => array(ctools_attach_js('states-show')),
* ),
* );
*/
(function ($) {
'use strict';
Drupal.states.State.aliases.hidden = '!show';
// Show/hide form items by toggling the 'element-invisible' class. This is a
// more accessible option than the core 'visible' state.
$(document).bind('state:show', function(e) {
if (e.trigger) {
var element = $(e.target).closest('.form-item, .form-submit, .form-wrapper');
element.toggle(e.value);
e.value === true ? element.removeClass('element-invisible') : element.addClass('element-invisible');
}
});
})(jQuery);

View File

@ -5,7 +5,7 @@
Drupal.CTools.Stylizer.addFarbtastic = function(context) {
// This behavior attaches by ID, so is only valid once on a page.
if ($('ctools_stylizer_color_scheme_form .color-form.Stylizer-processed').size()) {
if ($('#ctools_stylizer_color_scheme_form .color-form.Stylizer-processed').size()) {
return;
}

View File

@ -1542,6 +1542,7 @@ function page_manager_handler_import_submit(&$form, &$form_state) {
* Rearrange the order of variants.
*/
function page_manager_handler_rearrange($form, &$form_state) {
ctools_include('context-task-handler');
$page = $form_state['page'];
$form['handlers'] = array('#tree' => TRUE);
@ -1552,9 +1553,20 @@ function page_manager_handler_rearrange($form, &$form_state) {
}
$handler = $page->handlers[$id];
$plugin = page_manager_get_task_handler($handler->handler);
$object = ctools_context_handler_get_task_object($page->task, $page->subtask, $handler);
$display = new stdClass();
$display->context = ctools_context_load_contexts($object, TRUE);
$content = page_manager_get_handler_title($plugin, $handler, $page->task, $page->subtask_id);
$access = ctools_access_group_summary(!empty($handler->conf['access']) ? $handler->conf['access'] : array(), $display->context);
if ($access) {
$access = t('This panel will be selected if @conditions.', array('@conditions' => $access));
}
else {
$access = t('This panel will always be selected.');
}
$content .= '<div>' . $access . '</div>';
$form['handlers'][$id]['title'] = array(
'#markup' => page_manager_get_handler_title($plugin, $handler, $page->task, $page->subtask_id),
'#markup' => $content,
);
$form['handlers'][$id]['weight'] = array(

View File

@ -5,9 +5,9 @@ dependencies[] = ctools
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -440,13 +440,18 @@ function page_manager_cache_load($task_name) {
*/
function page_manager_handler_get_name($task_name, $handlers, $handler) {
$base = str_replace('-', '_', $task_name);
$name = '';
// Optional machine name.
if (!empty($handler->conf['name'])) {
$name = $base . '__' . $handler->conf['name'];
if (count(ctools_export_load_object('page_manager_handlers', 'names', array($name)))) {
$name = '';
}
}
// If no machine name was provided, generate a unique name.
else {
// If no machine name was provided or the name is in use, generate a unique name.
if (empty($name)) {
$base .= '__' . $handler->handler;
// Use the ctools uuid generator to generate a unique id.
@ -472,6 +477,10 @@ function page_manager_handler_add_to_page(&$page, &$handler, $title = NULL) {
if ($title) {
$handler->conf['title'] = $title;
$handler->conf['name'] = trim(preg_replace('/[^a-z0-9_]+/', '-', strtolower($title)), '-');
}
else {
$handler->conf['name'] = '';
}
$name = page_manager_handler_get_name($page->task_name, $page->handlers, $handler);
@ -1193,7 +1202,7 @@ function page_manager_page_manager_pages_to_hook_code($names = array(), $name =
foreach ($objects as $object) {
// Have to implement our own because this export func sig requires it
$code .= $export['export callback']($object, TRUE, ' ');
$code .= " \${$export['identifier']}s['" . check_plain($object->$export['key']) . "'] = \${$export['identifier']};\n\n";
$code .= " \${$export['identifier']}s['" . check_plain($object->{$export['key']}) . "'] = \${$export['identifier']};\n\n";
}
$code .= " return \${$export['identifier']}s;\n";
$code .= "}\n";

View File

@ -108,7 +108,7 @@ function page_manager_node_edit($node) {
* Callback to handle the process of adding a node.
*
* This creates a basic $node and passes that off to page_manager_node_edit().
* It is modeled after Drupal's node_add() function.
* It is modelled after Drupal's node_add() function.
*
* Unlike node_add() we do not need to check node_access because that was
* already checked by the menu system.

View File

@ -78,10 +78,6 @@ 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');
@ -107,6 +103,9 @@ function page_manager_node_view_page($node) {
}
}
// Prepare the node to be displayed so all of the regular hooks are triggered.
$default_output = node_page_view($node);
// Otherwise, fall back to the default output generated by node_page_view().
return $default_output;
}

View File

@ -61,7 +61,7 @@ function page_manager_page_menu(&$items, $task) {
}
$path = array();
$page_arguments = array($subtask_id);
$page_arguments = array((string) $subtask_id);
$access_arguments = array($subtask->access);
$load_arguments = array($subtask_id, '%index', '%map');
@ -566,7 +566,7 @@ function page_manager_page_form_basic_validate(&$form, &$form_state) {
if (strpos($path, '%') === FALSE) {
$alias = db_query('SELECT alias, source FROM {url_alias} WHERE alias = :path', array(':path' => $path))->fetchObject();
if ($alias) {
form_error($form['path'], t('That path is currently assigned to be an alias for @alias. This system cannot override existing aliases.', array('@alias' => $alias->src)));
form_error($form['path'], t('That path is currently assigned to be an alias for @alias. This system cannot override existing aliases.', array('@alias' => $alias->source)));
}
}
else {

View File

@ -18,6 +18,7 @@ $plugin = array(
'context' => 'ctools_term_context',
'default' => array('input_form' => 'tid', 'breadcrumb' => TRUE, 'transform' => FALSE),
'settings form' => 'ctools_term_settings_form',
'settings form validate' => 'ctools_term_settings_form_validate',
'placeholder form' => 'ctools_term_ctools_argument_placeholder',
'breadcrumb' => 'ctools_term_breadcrumb',
);
@ -31,6 +32,16 @@ function ctools_term_context($arg = NULL, $conf = NULL, $empty = FALSE) {
return ctools_context_create_empty('entity:taxonomy_term');
}
if (isset($conf['vocabularies'])) {
$vocabularies = $conf['vocabularies'];
}
else {
$vids = isset($conf['vids']) ? $conf['vids'] : array();
// Convert legacy use of vids to machine names.
$vocabularies = _ctools_term_vocabulary_machine_name_convert($vids);
}
if (is_object($arg)) {
$term = $arg;
}
@ -50,12 +61,11 @@ function ctools_term_context($arg = NULL, $conf = NULL, $empty = FALSE) {
}
$terms = taxonomy_get_term_by_name($arg);
$conf['vids'] = is_array($conf['vids']) ? array_filter($conf['vids']) : NULL;
if ((count($terms) > 1) && isset($conf['vids'])) {
// If only one term is found, fall through to vocabulary check below.
if ((count($terms) > 1) && $vocabularies) {
foreach ($terms as $potential) {
foreach ($conf['vids'] as $vid => $active) {
if ($active && $potential->vid == $vid) {
foreach ($vocabularies as $machine_name) {
if ($potential->vocabulary_machine_name == $machine_name) {
$term = $potential;
// break out of the foreaches AND the case
break 3;
@ -72,7 +82,7 @@ function ctools_term_context($arg = NULL, $conf = NULL, $empty = FALSE) {
}
}
if (!empty($conf['vids']) && array_filter($conf['vids']) && empty($conf['vids'][$term->vid])) {
if ($vocabularies && !isset($vocabularies[$term->vocabulary_machine_name])) {
return NULL;
}
@ -98,13 +108,20 @@ function ctools_term_settings_form(&$form, &$form_state, $conf) {
$vocabularies = taxonomy_get_vocabularies();
$options = array();
foreach ($vocabularies as $vid => $vocab) {
$options[$vid] = $vocab->name;
$options[$vocab->machine_name] = $vocab->name;
}
$form['settings']['vids'] = array(
// Fallback on legacy 'vids', when no vocabularies are available.
if (empty($conf['vocabularies']) && !empty($conf['vids'])) {
$conf['vocabularies'] = _ctools_term_vocabulary_machine_name_convert(array_filter($conf['vids']));
unset($conf['vids']);
}
$form['settings']['vocabularies'] = array(
'#title' => t('Limit to these vocabularies'),
'#type' => 'checkboxes',
'#options' => $options,
'#default_value' => !empty($conf['vids']) ? $conf['vids'] : array(),
'#default_value' => !empty($conf['vocabularies']) ? $conf['vocabularies'] : array(),
'#description' => t('If no vocabularies are checked, terms from all vocabularies will be accepted.'),
);
@ -123,6 +140,12 @@ function ctools_term_settings_form(&$form, &$form_state, $conf) {
// return $form;
}
function ctools_term_settings_form_validate (&$form, &$form_state) {
// Filter the selected vocabularies to avoid storing redundant data.
$vocabularies = array_filter($form_state['values']['settings']['vocabularies']);
form_set_value($form['settings']['vocabularies'], $vocabularies, $form_state);
}
/**
* Form fragment to get an argument to convert a placeholder for preview.
*/
@ -161,3 +184,20 @@ function ctools_term_breadcrumb($conf, $context) {
$breadcrumb = array_merge(drupal_get_breadcrumb(), array_reverse($breadcrumb));
drupal_set_breadcrumb($breadcrumb);
}
/**
* Helper function to convert convert legacy vocabulary ids into machine names.
*
* @param array $vids
* Array of either vids.
* @return array
* A keyed array of machine names.
*/
function _ctools_term_vocabulary_machine_name_convert($vids) {
$vocabularies = taxonomy_vocabulary_load_multiple($vids);
$return = array();
foreach($vocabularies as $vocabulary) {
$return[$vocabulary->machine_name] = $vocabulary->machine_name;
}
return $return;
}

View File

@ -0,0 +1,74 @@
<?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 created date'),
'icon' => 'icon_comment.png',
'description' => t('The date the referenced comment was created.'),
'required context' => new ctools_context_required(t('Comment'), 'entity:comment'),
'category' => t('Comment'),
'defaults' => array(
'format' => 'small',
),
);
/**
* Render the custom content type.
*/
function ctools_comment_created_content_type_render($subtype, $conf, $panel_args, $context) {
if (empty($context) || empty($context->data)) {
return;
}
// Get a shortcut to the comment.
$comment = $context->data;
// Build the content type block.
$block = new stdClass();
$block->module = 'comment_created';
$block->title = t('Created date');
$block->content = format_date($comment->created, $conf['format']);
$block->delta = $comment->cid;
return $block;
}
/**
* Returns an edit form for custom type settings.
*/
function ctools_comment_created_content_type_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$date_types = array();
foreach (system_get_date_types() as $date_type => $definition) {
$date_types[$date_type] = format_date(REQUEST_TIME, $date_type);
}
$form['format'] = array(
'#title' => t('Date format'),
'#type' => 'select',
'#options' => $date_types,
'#default_value' => $conf['format'],
);
return $form;
}
/**
* Submit handler for the custom type settings form.
*/
function ctools_comment_created_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_comment_created_content_type_admin_title($subtype, $conf, $context) {
return t('"@s" created date', array('@s' => $context->identifier));
}

View File

@ -26,7 +26,7 @@ function ctools_comment_links_content_type_render($subtype, $conf, $panel_args,
return;
}
$comment = isset($context->data) ? clone($context->data) : NULL;
$comment = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'comment';
$block->delta = $comment->cid;

View File

@ -25,7 +25,7 @@ if (module_exists('comment')) {
function ctools_comment_reply_form_content_type_render($subtype, $conf, $panel_args, $context) {
$comment = ($context[1]->identifier == t('No context')) ? NULL : clone($context[1]->data);
$comment = ($context[1]->identifier == t('No context')) ? NULL : clone $context[1]->data;
$block = new stdClass();
$block->module = 'comments';
if ($comment) $block->delta = $comment->cid;

View File

@ -16,7 +16,7 @@
$plugin = array(
'title' => t('Custom content'),
'no title override' => TRUE,
'defaults' => array('admin_title' => '', 'title' => '', 'body' => '', 'format' => filter_default_format(), 'substitute' => TRUE),
'defaults' => array('admin_title' => '', 'title' => '', 'title_heading' => 'h2', 'body' => '', 'format' => filter_default_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' => '',
@ -135,6 +135,7 @@ function ctools_custom_content_type_get_conf($subtype, $conf) {
$settings = array(
'admin_title' => t('Missing/deleted content'),
'title' => '',
'title_heading' => '',
'body' => '',
'format' => filter_default_format(),
'substitute' => TRUE,
@ -180,6 +181,8 @@ function ctools_custom_content_type_render($subtype, $conf, $args, $contexts) {
$block = new stdClass();
$block->subtype = ++$delta;
$block->title = filter_xss_admin($settings['title']);
$block->title_heading = isset($settings['title_heading']) ? $settings['title_heading'] : 'h2';
// Add keyword substitutions if we were configured to do so.
$content = $settings['body'];
@ -277,10 +280,36 @@ function ctools_custom_content_type_edit_form($form, &$form_state) {
'#description' => t('This title will be used administratively to identify this pane. If blank, the regular title will be used.'),
);
// Copy over the title override settings for a title heading.
$form['aligner_start'] = array(
'#markup' => '<div class="option-text-aligner clearfix">',
);
$form['title'] = array(
'#type' => 'textfield',
'#default_value' => $settings['title'],
'#title' => t('Title'),
'#id' => 'override-title-textfield',
);
$form['title_heading'] = array(
'#type' => 'select',
'#default_value' => isset($settings['title_heading']) ? $settings['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',
);
$form['aligner_stop'] = array(
'#markup' => '</div>',
);
$form['body'] = array(

View File

@ -34,6 +34,14 @@ function ctools_entity_field_content_type_content_types() {
return $types;
}
$cache_key = 'ctools_entity_field_content_type_content_types';
if ($cache = cache_get($cache_key)) {
$types = $cache->data;
if (!empty($types)) {
return $types;
}
}
// This will hold all the individual field content types.
$context_types = array();
$entities = entity_get_info();
@ -82,6 +90,8 @@ function ctools_entity_field_content_type_content_types() {
unset($context_types[$key]['types']);
}
cache_set($cache_key, $types);
return $types;
}
@ -127,25 +137,24 @@ function ctools_entity_field_content_type_render($subtype, $conf, $panel_args, $
$field_settings['settings'] = $conf['formatter_settings'];
}
$all_values = field_get_items($entity_type, $entity, $field_name, $language);
if (!is_array($all_values)) {
// 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, TRUE);
}
if (isset($conf['delta_limit'])) {
$offset = intval($conf['delta_offset']);
$limit = !empty($conf['delta_limit']) ? $conf['delta_limit'] : NULL;
$all_values = array_slice($all_values, $offset, $limit, TRUE);
}
$clone = clone $entity;
$clone->{$field_name}[$language] = $all_values;
$all_values = field_get_items($entity_type, $entity, $field_name, $language);
if (is_array($all_values)) {
// Reverse values.
if (isset($conf['delta_reversed']) && $conf['delta_reversed']) {
$all_values = array_reverse($all_values, TRUE);
}
if (isset($conf['delta_limit'])) {
$offset = intval($conf['delta_offset']);
$limit = !empty($conf['delta_limit']) ? $conf['delta_limit'] : NULL;
$all_values = array_slice($all_values, $offset, $limit, TRUE);
}
$clone->{$field_name}[$language] = $all_values;
}
$field_output = field_view_field($entity_type, $clone, $field_name, $field_settings, $language);
if (!empty($field_output) && !empty($conf['override_title'])) {
@ -260,10 +269,7 @@ function ctools_entity_field_content_type_admin_title($subtype, $conf, $context)
$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);
watchdog('ctools_entity_field_content_type_admin_title', 'Context is missing for field: @name', array('@name' => $subtype), WATCHDOG_NOTICE);
$identifier = t('Unknown');
}

View File

@ -57,6 +57,26 @@ function ctools_entity_form_field_content_type_content_types() {
}
}
if (module_exists('field_group')) {
foreach ($entities as $entity_type => $entity) {
foreach ($entity['bundles'] as $type => $bundle) {
if ($group_info = field_group_info_groups($entity_type, $type, "form")) {
foreach ($group_info as $group_name => $group) {
if (!isset($types[$entity_type . ':' . $group_name])) {
$types[$entity_type . ':' . $group_name] = array(
'category' => t('Form'),
'icon' => 'icon_field.png',
'title' => t('Group form: @widget_label', array('@widget_label' => $group->label)),
'description' => t('Field group on the referenced entity.'),
);
}
$content_types[$entity_type . ':' . $group_name]['types'][$type] = $bundle['label'];
}
}
}
}
}
// Create the required context for each field related to the bundle types.
foreach ($types as $key => $field_content_type) {
list($entity_type, $field_name) = explode(':', $key, 2);
@ -85,16 +105,38 @@ function ctools_entity_form_field_content_type_render($subtype, $conf, $panel_ar
$ids = entity_extract_ids($entity_type, $entity);
$field = field_info_instance($entity_type, $field_name, $ids[2]);
// Do not render if the entity type does not have this field.
if (empty($field)) {
// Check for field groups.
if (empty($field) && module_exists('field_group')) {
$groups = field_group_info_groups($entity_type, $entity->type, "form");
$group = !empty($groups[$field_name]) ? $groups[$field_name] : NULL;
}
// Do not render if the entity type does not have this field or group.
if (empty($field) && empty($group)) {
return;
}
$block = new stdClass();
$block = new stdClass();
if (isset($context->form)) {
$block->content = array();
$block->content[$field_name] = $context->form[$field_name];
unset($context->form[$field_name]);
if (!empty($field)) {
$block->content[$field_name] = $context->form[$field_name];
unset($context->form[$field_name]);
}
else {
// Pre-render the form to populate field groups.
if (isset($context->form['#pre_render'])) {
foreach ($context->form['#pre_render'] as $function) {
if (function_exists($function)) {
$context->form = $function($context->form);
}
}
unset($context->form['#pre_render']);
}
$block->content[$field_name] = $context->form[$field_name];
unset($context->form[$field_name]);
}
}
else {
$block->content = t('Entity info.');

View File

@ -66,7 +66,7 @@ function ctools_node_content_type_render($subtype, $conf, $panel_args) {
// Don't store viewed node data on the node, this can mess up other
// views of the node.
$node = clone($node);
$node = clone $node;
$block->module = 'node';
$block->delta = $node->nid;

View File

@ -14,7 +14,7 @@ $plugin = array(
);
function ctools_node_attachments_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'attachments';

View File

@ -16,7 +16,7 @@ if (module_exists('book')) {
}
function ctools_node_book_children_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'book_children';

View File

@ -16,7 +16,7 @@ if (module_exists('book')) {
}
function ctools_node_book_nav_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'book_nav';

View File

@ -17,7 +17,7 @@ if (module_exists('comment')) {
}
function ctools_node_comment_form_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'comments';
$block->delta = $node->nid;
@ -77,20 +77,3 @@ function ctools_node_comment_form_content_type_edit_form_submit($form, &$form_st
}
}
/**
* Alter the comment form to get a little more control over it.
*/
function ctools_form_comment_form_alter(&$form, &$form_state) {
if (!empty($form_state['ctools comment alter'])) {
// Force the form to post back to wherever we are.
$form['#action'] = url($_GET['q'], array('fragment' => 'comment-form'));
if (empty($form['#submit'])) {
$form['#submit'] = array('comment_form_submit');
}
$form['#submit'][] = 'ctools_node_comment_form_submit';
}
}
function ctools_node_comment_form_submit(&$form, &$form_state) {
$form_state['redirect'][0] = $_GET['q'];
}

View File

@ -23,7 +23,7 @@ if (module_exists('comment')) {
* 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;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'comments';
$block->delta = $node->nid;
@ -77,7 +77,7 @@ function ctools_node_comment_wrapper_content_type_render($subtype, $conf, $panel
/**
* 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(

View File

@ -20,7 +20,7 @@ if (module_exists('comment')) {
}
function ctools_node_comments_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'comments';
$block->delta = $node->nid;

View File

@ -31,7 +31,7 @@ function ctools_node_content_content_type_render($subtype, $conf, $panel_args, $
return;
}
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'node';
$block->delta = $node->nid;

View File

@ -29,7 +29,7 @@ function ctools_node_links_content_type_render($subtype, $conf, $panel_args, $co
return;
}
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'node';
$block->delta = $node->nid;

View File

@ -18,7 +18,7 @@ $plugin = array(
* based on the module and delta supplied in the configuration.
*/
function ctools_node_type_desc_content_type_render($subtype, $conf, $panel_args, $context) {
$node = isset($context->data) ? clone($context->data) : NULL;
$node = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'node_type';

View File

@ -29,6 +29,9 @@ $plugin = array(
* Outputs the page title of the current page.
*/
function ctools_page_title_content_type_render($subtype, $conf, $panel_args) {
if (!drupal_get_title()) {
return;
}
// TODO: This should have a setting or something for the markup.
if (empty($conf['markup'])) {
$conf['markup'] = 'h1';

View File

@ -14,12 +14,12 @@ $plugin = array(
);
function ctools_term_description_content_type_render($subtype, $conf, $panel_args, $context) {
$term = isset($context->data) ? clone($context->data) : NULL;
$term = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'node_type';
$block->title = $term->name;
if ($term) {
if (!empty($term)) {
$block->title = $term->name;
$block->content = check_markup($term->description, $term->format, '', TRUE);
$block->delta = $term->tid;
@ -33,6 +33,7 @@ function ctools_term_description_content_type_render($subtype, $conf, $panel_arg
}
}
else {
$block->title = '';
$block->content = t('Term description goes here.');
$block->delta = 'unknown';
}

View File

@ -21,7 +21,7 @@ $plugin = array(
);
function ctools_term_list_content_type_render($subtype, $conf, $panel_args, $context) {
$term = isset($context->data) ? clone($context->data) : NULL;
$term = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'term-list';
$path = empty($conf['path']) ? 'taxonomy/term/%tid' : $conf['path'];

View File

@ -21,7 +21,7 @@ if (module_exists('profile') && !(defined('MAINTENANCE_MODE') && MAINTENANCE_MOD
* 'Render' callback for the 'profile fields' content type.
*/
function ctools_profile_fields_content_type_render($subtype, $conf, $panel_args, $context) {
$account = isset($context->data) ? clone($context->data) : NULL;
$account = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'profile fields';

View File

@ -20,7 +20,7 @@ $plugin = array(
* Render the user profile content type.
*/
function ctools_user_profile_content_type_render($subtype, $conf, $panel_args, $context) {
$account = isset($context->data) ? clone($context->data) : NULL;
$account = isset($context->data) ? clone $context->data : NULL;
if (!$account) {
return NULL;
}

View File

@ -13,7 +13,7 @@ $plugin = array(
);
function ctools_user_signature_content_type_render($subtype, $conf, $panel_args, $context) {
$account = isset($context->data) ? clone($context->data) : NULL;
$account = isset($context->data) ? clone $context->data : NULL;
$block = new stdClass();
$block->module = 'user-signature';

View File

@ -21,7 +21,7 @@ if (module_exists('taxonomy')) {
* list of terms for the input vocabulary.
*/
function ctools_vocabulary_terms_content_type_render($subtype, $conf, $panel_args, $context) {
$vocab = isset($context->data) ? clone($context->data) : NULL;
$vocab = isset($context->data) ? clone $context->data : NULL;
$max_depth = (!empty($conf['max_depth']) ? (int)$conf['max_depth'] : NULL);
if ($conf['tree'] == FALSE) {
$terms = taxonomy_get_tree($vocab->vid, 0, $max_depth);

View File

@ -43,7 +43,9 @@ function ctools_context_create_user($empty, $data = NULL, $conf = FALSE) {
if ($data['type'] == 'current') {
global $user;
$data = user_load($user->uid);
$data->logged_in_user = TRUE;
if (user_is_logged_in()) {
$data->logged_in_user = TRUE;
}
}
else {
$data = user_load($data['uid']);

View File

@ -34,15 +34,15 @@ function ctools_context_create_user_edit_form($empty, $user = NULL, $conf = FALS
$category = !empty($conf['category']) ? $conf['category'] : FALSE;
unset($conf['category']);
// If no category was specified, use the default 'account'.
if (!$category) {
$category = 'account';
}
// Return previously created contexts, per category.
static $created = array();
if (!empty($created[$category])) {
return $created[$category];
}
// If no category was specified, use the default 'account'.
if (!$category) {
$category = 'account';
}
$context = new ctools_context(array('form', 'user_edit', 'user_form', 'user_edit_form', 'user', 'entity:user'));
// Store this context for later.

View File

@ -724,7 +724,13 @@ class ctools_export_ui {
// Export the handler, which is a fantastic way to clean database IDs out of it.
$export = ctools_export_crud_export($this->plugin['schema'], $original);
$item = ctools_export_crud_import($this->plugin['schema'], $export);
$item->{$this->plugin['export']['key']} = 'clone_of_' . $item->{$this->plugin['export']['key']};
if (!empty($input[$this->plugin['export']['key']])) {
$item->{$this->plugin['export']['key']} = $input[$this->plugin['export']['key']];
}
else {
$item->{$this->plugin['export']['key']} = 'clone_of_' . $item->{$this->plugin['export']['key']};
}
}
// Tabs and breadcrumb disappearing, this helps alleviate through cheating.

View File

@ -185,7 +185,7 @@ function ctools_entity_from_field_context($context, $conf) {
$loaded_to_entity = array_shift($loaded_to_entity);
// Pass current user account and entity type to access callback.
if (function_exists($to_entity_info['access callback']) && !call_user_func($to_entity_info['access callback'], 'view', $loaded_to_entity, $account, $to_entity)) {
if (isset($to_entity_info['access callback']) && function_exists($to_entity_info['access callback']) && !call_user_func($to_entity_info['access callback'], 'view', $loaded_to_entity, $account, $to_entity)) {
return ctools_context_create_empty('entity:' . $to_entity, NULL);
}
else {

View File

@ -6,9 +6,9 @@ version = CTOOLS_MODULE_VERSION
dependencies[] = ctools
dependencies[] = color
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -25,28 +25,22 @@ $plugin = array(
* Settings form for the 'term depth' access plugin.
*/
function term_depth_term_depth_ctools_access_settings($form, &$form_state, $conf) {
// If no configuration was saved before, set some defaults.
if (empty($conf)) {
$conf = array(
'vid' => 0,
);
}
if (!isset($conf['vid'])) {
$conf['vid'] = 0;
}
$vocabularies = taxonomy_get_vocabularies();
$options = array();
// Loop over each of the configured vocabularies.
foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) {
$options[$vid] = $vocabulary->name;
foreach ($vocabularies as $vid => $vocab) {
$options[$vocab->machine_name] = $vocab->name;
}
$form['settings']['vid'] = array(
_term_depth_convert_config_vid_to_vocabulary_name($conf);
$form['settings']['vocabulary'] = array(
'#title' => t('Vocabulary'),
'#type' => 'select',
'#options' => $options,
'#description' => t('Select the vocabulary for this form. If there exists a parent term in that vocabulary, this access check will succeed.'),
'#id' => 'ctools-select-vid',
'#default_value' => $conf['vid'],
'#id' => 'ctools-select-vocabulary',
'#default_value' => !empty($conf['vocabulary']) ? $conf['vocabulary'] : array(),
'#required' => TRUE,
);
@ -61,15 +55,24 @@ function term_depth_term_depth_ctools_access_settings($form, &$form_state, $conf
return $form;
}
/**
* @param $conf
*/
function _term_depth_convert_config_vid_to_vocabulary_name(&$conf) {
// Fallback on legacy 'vid', when no vocabularies are available.
if (empty($conf['vocabulary']) && !empty($conf['vid'])) {
$conf['vocabulary'] = reset(_ctools_term_vocabulary_machine_name_convert(array($conf['vid'])));
unset($conf['vid']);
}
}
/**
* Submit function for the access plugins settings.
*
* We cast all settings to numbers to ensure they can be safely handled.
*/
function term_depth_term_depth_ctools_access_settings_submit($form, $form_state) {
foreach (array('depth', 'vid') as $key) {
$form_state['conf'][$key] = (integer) $form_state['values']['settings'][$key];
}
$form_state['conf']['depth'] = (integer) $form_state['values']['settings']['depth'];
$form_state['conf']['vocabulary'] = array_filter($form_state['conf']['vocabulary']);
}
/**
@ -82,10 +85,17 @@ function term_depth_term_depth_ctools_access_check($conf, $context) {
return FALSE;
}
// Get the $vid.
if (!isset($conf['vid'])) {
_term_depth_convert_config_vid_to_vocabulary_name($conf);
// Get the $vocabulary.
if (!isset($conf['vocabulary'])) {
return FALSE;
}
$vocab = taxonomy_vocabulary_machine_name_load($conf['vocabulary']);
if ($vocab->vid != $context->data->vid) {
return FALSE;
}
$depth = _term_depth($context->data->tid);
return ($depth == $conf['depth']);
@ -95,9 +105,9 @@ function term_depth_term_depth_ctools_access_check($conf, $context) {
* Provide a summary description based upon the checked terms.
*/
function term_depth_term_depth_ctools_access_summary($conf, $context) {
$vocab = taxonomy_vocabulary_load($conf['vid']);
return t('"@term" has parent in vocabulary "@vocab" at @depth', array(
_term_depth_convert_config_vid_to_vocabulary_name($conf);
$vocab = taxonomy_vocabulary_machine_name_load($conf['vocabulary']);
return t('"@term" is in vocabulary "@vocab" at depth @depth', array(
'@term' => $context->identifier,
'@vocab' => $vocab->name,
'@depth' => $conf['depth'],

View File

@ -5,9 +5,9 @@ dependencies[] = ctools
package = Chaos tool suite
version = CTOOLS_MODULE_VERSION
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -8,9 +8,9 @@ hidden = TRUE
files[] = ctools_export.test
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -12,9 +12,9 @@ files[] = math_expression.test
files[] = math_expression_stack.test
hidden = TRUE
; Information added by Drupal.org packaging script on 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

View File

@ -1,7 +1,7 @@
<?php
/**
* @file
* A cached plugin object that tests inheritence including.
* A cached plugin object that tests inheritance including.
*/
class ctoolsCachedPluginArray {}

View File

@ -1,7 +1,7 @@
<?php
/**
* @file
* A cached plugin object that tests inheritence including.
* A cached plugin object that tests inheritance including.
*/
class ctoolsCachedPluginArray2 extends ctoolsCachedPluginArray {}

View File

@ -1,7 +1,7 @@
<?php
/**
* @file
* A cached plugin object that tests inheritence including.
* A cached plugin object that tests inheritance including.
*/
class ctoolsNotCachedPluginArray extends ctoolsNotCachedPluginArray2 {}

View File

@ -321,6 +321,10 @@ function views_content_views_panes_content_type_render($subtype, $conf, $panel_a
function views_content_views_panes_add_defaults(&$conf, $view) {
$pager = $view->display_handler->get_option('pager');
if (empty($conf)) {
$conf = array();
}
$conf += array(
'link_to_view' => $view->display_handler->get_option('link_to_view'),
'more_link' => $view->display_handler->get_option('use_more'),

View File

@ -25,7 +25,7 @@ function views_content_views_plugins() {
'use more' => TRUE,
'accept attachments' => TRUE,
'help topic' => 'display-pane',
'contextual links locations' => array('panel_pane'),
'contextual links locations' => array('panel_pane', 'view'),
),
'ctools_context' => array(
'title' => t('Context'),

View File

@ -10,9 +10,9 @@ 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 2015-03-18
version = "7.x-1.7"
; Information added by Drupal.org packaging script on 2016-08-17
version = "7.x-1.10"
core = "7.x"
project = "ctools"
datestamp = "1426696183"
datestamp = "1471454104"

Some files were not shown because too many files have changed in this diff Show More