all contrib module security updates done

This commit is contained in:
2020-09-24 22:47:32 +02:00
parent 7d87153100
commit 0fbb9c4610
1612 changed files with 116663 additions and 32269 deletions
@@ -1,4 +1,5 @@
<?php
/**
* @file
* Theme function for wrapping menu local actions.
@@ -30,4 +31,4 @@ function theme_ctools_menu_local_actions_wrapper($variables) {
}
return '<ul class="action-links">' . $links . '</ul>';
}
}
@@ -1,6 +1,10 @@
<?php
// Set this so we can tell that the file has been included at some point.
/**
* @file
* Set this so we can tell that the file has been included at some point.
*/
define('CTOOLS_AJAX_INCLUDED', 1);
/**
@@ -49,6 +53,34 @@ function ctools_ajax_text_button($text, $dest, $alt, $class = '', $type = 'use-a
return l($text, $dest, array('html' => TRUE, 'attributes' => array('class' => array($type, $class), 'title' => $alt)));
}
/**
* Render an icon and related text as a link. This will automatically apply an AJAX class
* to the link and add the appropriate javascript to make this happen.
*
* Note: 'html' => true so be sure any text is vetted! Chances are these kinds of buttons will
* not use user input so this is a very minor concern.
*
* @param $text
* The text that will be displayed as the link.
* @param $image
* The icon image to include in the link.
* @param $dest
* The destination of the link.
* @param $alt
* The title text of the link.
* @param $class
* Any class to apply to the link. @todo this should be a options array.
* @param $type
* A type to use, in case a different behavior should be attached. Defaults
* to ctools-use-ajax.
*/
function ctools_ajax_icon_text_button($text, $image, $dest, $alt, $class = '', $type = 'use-ajax') {
drupal_add_library('system', 'drupal.ajax');
$rendered_image = theme('image', array('path' => $image));
$link_content = $rendered_image . "<span>" . $text . "</span>";
return l($link_content, $dest, array('html' => TRUE, 'attributes' => array('class' => array($type, $class), 'title' => $alt)));
}
/**
* Set a single property to a value, on all matched elements.
*
@@ -57,17 +89,17 @@ function ctools_ajax_text_button($text, $dest, $alt, $class = '', $type = 'use-a
* @param $name
* The name or key: of the data attached to this selector.
* @param $value
* The value of the data.
* The value of the data.
*/
function ctools_ajax_command_attr($selector, $name, $value) {
ctools_add_js('ajax-responder');
return array(
'command' => 'attr',
'selector' => $selector,
'name' => $name,
'value' => $value,
);
}
'command' => 'attr',
'selector' => $selector,
'name' => $name,
'value' => $value,
);
}
/**
* Force a client-side redirect.
@@ -126,4 +158,3 @@ function ctools_ajax_render_error($error = '') {
print ajax_render($commands);
exit;
}
@@ -2,7 +2,6 @@
/**
* @file
*
* Plugins to handle cache-indirection.
*
* Simple plugin management to allow clients to more tightly control where
@@ -52,7 +51,6 @@
* @param string $mechanism
* A string containing the plugin name, and an optional data element to
* send to the plugin separated by two colons.
*
* @param string $key
* The key used to identify the cache.
*
@@ -70,7 +68,6 @@ function ctools_cache_get($mechanism, $key) {
* @param string $mechanism
* A string containing the plugin name, and an optional data element to
* send to the plugin separated by two colons.
*
* @param string $key
* The key used to identify the cache.
*
@@ -88,7 +85,6 @@ function ctools_cache_set($mechanism, $key, $object) {
* @param string $mechanism
* A string containing the plugin name, and an optional data element to
* send to the plugin separated by two colons.
*
* @param string $key
* The key used to identify the cache.
*/
@@ -108,13 +104,10 @@ function ctools_cache_clear($mechanism, $key) {
* @param string $mechanism
* A string containing the plugin name, and an optional data element to
* send to the plugin separated by two colons.
*
* @param string $key
* The key used to identify the cache.
*
* @param string $op
* The operation to call, such as 'break' or 'finalize'.
*
* @param mixed $object
* The cache data being operated on, in case it is necessary. This is
* optional so no references should be used.
@@ -150,7 +143,7 @@ function ctools_cache_operation($mechanism, $key, $op, $object = NULL) {
*/
function ctools_cache_find_plugin($mechanism) {
if (strpos($mechanism, '::') !== FALSE) {
// use explode(2) to ensure that the data can contain double
// Use explode(2) to ensure that the data can contain double
// colons, just in case.
list($name, $data) = explode('::', $mechanism, 2);
}
@@ -1,5 +1,4 @@
<?php
// $Id $
/**
* @file
@@ -21,7 +20,7 @@
/**
* Matches Unicode character classes.
*
* See: http://www.unicode.org/Public/UNIDATA/UCD.html#General_Category_Values
* See: http://www.unicode.org/Public/UNIDATA/UCD.html#General_Category_Values.
*
* The index only contains the following character classes:
* Lu Letter, Uppercase
@@ -129,13 +128,13 @@ function ctools_cleanstring($string, $settings = array()) {
$output = transliteration_get($output);
}
// Reduce to the subset of ASCII96 letters and numbers
// Reduce to the subset of ASCII96 letters and numbers.
if ($settings['reduce ascii']) {
$pattern = '/[^a-zA-Z0-9\/]+/';
$output = preg_replace($pattern, $settings['separator'], $output);
}
// Get rid of words that are on the ignore list
// Get rid of words that are on the ignore list.
if (!empty($settings['ignore words'])) {
$ignore_re = '\b' . preg_replace('/,/', '\b|\b', $settings['ignore words']) . '\b';
@@ -159,14 +158,14 @@ function ctools_cleanstring($string, $settings = array()) {
else {
$seppattern = '\\' . $settings['separator'];
}
// Trim any leading or trailing separators (note the need to
// Trim any leading or trailing separators (note the need to.
$output = preg_replace("/^$seppattern+|$seppattern+$/", '', $output);
// Replace multiple separators with a single one
// Replace multiple separators with a single one.
$output = preg_replace("/$seppattern+/", $settings['separator'], $output);
}
// Enforce the maximum component length
// Enforce the maximum component length.
if (!empty($settings['max length'])) {
$output = ctools_cleanstring_truncate($output, $settings['max length'], $settings['separator']);
}
@@ -188,12 +187,14 @@ function ctools_cleanstring($string, $settings = array()) {
* A string which contains the word boundary such as - or _.
*
* @return
* The string truncated below the maxlength.
* The string truncated below the maxlength.
*/
function ctools_cleanstring_truncate($string, $length, $separator) {
if (drupal_strlen($string) > $length) {
$string = drupal_substr($string, 0, $length + 1); // leave one more character
if ($last_break = strrpos($string, $separator)) { // space exists AND is not on position 0
// Leave one more character.
$string = drupal_substr($string, 0, $length + 1);
// Space exists AND is not on position 0.
if ($last_break = strrpos($string, $separator)) {
$string = substr($string, 0, $last_break);
}
else {
@@ -30,8 +30,8 @@ function ctools_collapsible_theme(&$items) {
* Text to put in the handle/title area of the div.
* @param $content
* Text to put in the content area of the div, this is what will get
* collapsed
* @param $collapsed = FALSE
* collapsed.
* @param $collapsed
* If true, this div will start out collapsed.
*/
function theme_ctools_collapsible($vars) {
@@ -56,8 +56,8 @@ function theme_ctools_collapsible($vars) {
* Text to put in the handle/title area of the div.
* @param $content
* Text to put in the content area of the div, this is what will get
* collapsed
* @param $collapsed = FALSE
* collapsed.
* @param $collapsed
* If true, this div will start out collapsed.
*/
function theme_ctools_collapsible_remembered($vars) {
@@ -76,4 +76,3 @@ function theme_ctools_collapsible_remembered($vars) {
return $output;
}
@@ -86,7 +86,7 @@ function ctools_content_process(&$plugin, $info) {
/**
* Fetch metadata on a specific content_type plugin.
*
* @param $content type
* @param mixed $content
* Name of a panel content type.
*
* @return
@@ -146,7 +146,7 @@ function ctools_content_get_subtypes($type) {
if (is_array($function)) {
$subtypes = $function;
}
else if (function_exists($function)) {
elseif (function_exists($function)) {
// Cast to array to prevent errors from non-array returns.
$subtypes = (array) $function($plugin);
}
@@ -155,6 +155,11 @@ function ctools_content_get_subtypes($type) {
// Walk through the subtypes and ensure minimal settings are
// retained.
foreach ($subtypes as $id => $subtype) {
// Ensure that the 'subtype_id' value exists.
if (!isset($subtype['subtype_id'])) {
$subtypes[$id]['subtype_id'] = $id;
}
// Use exact name since this is a modify by reference.
ctools_content_prepare_subtype($subtypes[$id], $plugin);
}
@@ -202,6 +207,13 @@ function ctools_content_get_subtype($type, $subtype_id) {
}
if ($subtype) {
// Ensure that the 'subtype_id' value exists. This is also done in
// ctools_content_get_subtypes(), but it wouldn't be called if the plugin
// provides the subtype through its own function.
if (!isset($subtype['subtype_id'])) {
$subtype['subtype_id'] = $subtype_id;
}
ctools_content_prepare_subtype($subtype, $plugin);
}
return $subtype;
@@ -217,6 +229,7 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) {
}
}
// Trigger hook_ctools_content_subtype_alter().
drupal_alter('ctools_content_subtype', $subtype, $plugin);
}
@@ -241,9 +254,10 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) {
* Any incoming content, if this display is a wrapper.
*
* @return
* The content as rendered by the plugin. This content should be an array
* with the following possible keys:
* The content as rendered by the plugin, or NULL.
* This content should be an object with the following possible properties:
* - title: The safe to render title of the content.
* - title_heading: The title heading.
* - content: The safe to render HTML content.
* - links: An array of links associated with the content suitable for
* theme('links').
@@ -293,21 +307,22 @@ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $arg
$content->subtype = $subtype;
}
// Override the title if configured to
// Override the title if configured to.
if (!empty($conf['override_title'])) {
// Give previous title as an available substitution here.
$keywords['%title'] = empty($content->title) ? '' : $content->title;
$content->original_title = $keywords['%title'];
$content->title = $conf['override_title_text'];
$content->title_heading = isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2';
}
if (!empty($content->title)) {
// Perform substitutions
// Perform substitutions.
if (!empty($keywords) || !empty($context)) {
$content->title = ctools_context_keyword_substitute($content->title, $keywords, $context);
}
// Sterilize the title
// Sterilize the title.
$content->title = filter_xss_admin($content->title);
// If a link is specified, populate.
@@ -318,7 +333,7 @@ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $arg
else {
$url = $content->title_link;
}
// set defaults so we don't bring up notices
// Set defaults so we don't bring up notices.
$url += array('href' => '', 'attributes' => array(), 'query' => array(), 'fragment' => '', 'absolute' => NULL, 'html' => TRUE);
$content->title = l($content->title, $url['href'], $url);
}
@@ -339,7 +354,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);
}
@@ -362,7 +386,7 @@ function ctools_content_admin_title($type, $subtype, $conf, $context = NULL) {
if (is_array($type)) {
$plugin = $type;
}
else if (is_string($type)) {
elseif (is_string($type)) {
$plugin = ctools_get_content_type($type);
}
else {
@@ -380,10 +404,10 @@ function ctools_content_admin_title($type, $subtype, $conf, $context = NULL) {
return $function($subtype, $conf, $pane_context);
}
else if (isset($plugin['admin title'])) {
elseif (isset($plugin['admin title'])) {
return $plugin['admin title'];
}
else if (isset($plugin['title'])) {
elseif (isset($plugin['title'])) {
return $plugin['title'];
}
}
@@ -418,7 +442,7 @@ function ctools_content_get_defaults($plugin, $subtype) {
if (isset($plugin['defaults'])) {
$defaults = $plugin['defaults'];
}
else if (isset($subtype['defaults'])) {
elseif (isset($subtype['defaults'])) {
$defaults = $subtype['defaults'];
}
if (isset($defaults)) {
@@ -427,7 +451,7 @@ function ctools_content_get_defaults($plugin, $subtype) {
return $return;
}
}
else if (is_array($defaults)) {
elseif (is_array($defaults)) {
return $defaults;
}
}
@@ -461,7 +485,7 @@ function ctools_content_admin_info($type, $subtype, $conf, $context = NULL) {
if (empty($output) || !is_object($output)) {
$output = new stdClass();
// replace the _ with " " for a better output
// Replace the _ with " " for a better output.
$subtype = check_plain(str_replace("_", " ", $subtype));
$output->title = $subtype;
$output->content = t('No info available.');
@@ -470,7 +494,7 @@ function ctools_content_admin_info($type, $subtype, $conf, $context = NULL) {
}
/**
* Add the default FAPI elements to the content type configuration form
* Add the default FAPI elements to the content type configuration form.
*/
function ctools_content_configure_form_defaults($form, &$form_state) {
$plugin = $form_state['plugin'];
@@ -504,8 +528,26 @@ function ctools_content_configure_form_defaults($form, &$form_state) {
'#size' => 35,
'#id' => 'override-title-textfield',
'#dependency' => array('override-title-checkbox' => array(1)),
'#dependency_type' => 'disable',
'#dependency_type' => 'hidden',
);
$form['override_title_heading'] = array(
'#type' => 'select',
'#default_value' => isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2',
'#options' => array(
'h1' => t('h1'),
'h2' => t('h2'),
'h3' => t('h3'),
'h4' => t('h4'),
'h5' => t('h5'),
'h6' => t('h6'),
'div' => t('div'),
'span' => t('span'),
),
'#id' => 'override-title-heading',
'#dependency' => array('override-title-checkbox' => array(1)),
'#dependency_type' => 'hidden',
);
$form['aligner_stop'] = array(
'#markup' => '</div>',
);
@@ -536,6 +578,7 @@ function ctools_content_configure_form_defaults_submit(&$form, &$form_state) {
if (isset($form_state['values']['override_title'])) {
$form_state['conf']['override_title'] = $form_state['values']['override_title'];
$form_state['conf']['override_title_text'] = $form_state['values']['override_title_text'];
$form_state['conf']['override_title_heading'] = $form_state['values']['override_title_heading'];
}
}
@@ -568,7 +611,7 @@ function ctools_content_form($op, $form_info, &$form_state, $plugin, $subtype_na
if (!empty($subtype['add form'])) {
_ctools_content_create_form_info($form_info, $subtype['add form'], $subtype, $subtype, $op);
}
else if (!empty($plugin['add form'])) {
elseif (!empty($plugin['add form'])) {
_ctools_content_create_form_info($form_info, $plugin['add form'], $plugin, $subtype, $op);
}
}
@@ -578,7 +621,7 @@ function ctools_content_form($op, $form_info, &$form_state, $plugin, $subtype_na
if (!empty($subtype['edit form'])) {
_ctools_content_create_form_info($form_info, $subtype['edit form'], $subtype, $subtype, $op);
}
else if (!empty($plugin['edit form'])) {
elseif (!empty($plugin['edit form'])) {
_ctools_content_create_form_info($form_info, $plugin['edit form'], $plugin, $subtype, $op);
}
}
@@ -597,7 +640,7 @@ function _ctools_content_create_form_info(&$form_info, $info, $plugin, $subtype,
if (empty($subtype['title'])) {
$title = t('Configure');
}
else if ($op == 'add') {
elseif ($op == 'add') {
$title = t('Configure new !subtype_title', array('!subtype_title' => $subtype['title']));
}
else {
@@ -612,7 +655,7 @@ function _ctools_content_create_form_info(&$form_info, $info, $plugin, $subtype,
),
);
}
else if (is_array($info)) {
elseif (is_array($info)) {
$form_info['order'] = array();
$form_info['forms'] = array();
$count = 0;
@@ -663,7 +706,7 @@ function ctools_content_get_available_types($contexts = NULL, $has_content = FAL
foreach ($plugins as $id => $plugin) {
foreach (ctools_content_get_subtypes($plugin) as $subtype_id => $subtype) {
// exclude items that require content if we're saying we don't
// Exclude items that require content if we're saying we don't
// provide it.
if (!empty($subtype['requires content']) && !$has_content) {
continue;
@@ -687,6 +730,11 @@ function ctools_content_get_available_types($contexts = NULL, $has_content = FAL
}
}
// Check if the content type provides an access callback.
if (isset($subtype['create content access']) && function_exists($subtype['create content access']) && !$subtype['create content access']($plugin, $subtype)) {
continue;
}
// If we made it through all the tests, then we can use this content.
$available[$id][$subtype_id] = $subtype;
}
@@ -698,7 +746,6 @@ function ctools_content_get_available_types($contexts = NULL, $has_content = FAL
* Get an array of all content types that can be fed into the
* display editor for the add content list, regardless of
* availability.
*
*/
function ctools_content_get_all_types() {
$plugins = ctools_get_content_types();
@@ -23,68 +23,156 @@ function ctools_content_menu(&$items) {
/**
* Helper function for autocompletion of entity titles.
*/
function ctools_content_autocomplete_entity($type, $string = '') {
$entity = entity_get_info($type);
function ctools_content_autocomplete_entity($entity_type, $string = '') {
if ($string != '') {
// @todo verify the query logic here, it's untested.
// Set up the query
$query = db_select($entity['base table'], 'b');
if ($entity['entity keys']['label']) {
$query->fields('b', array($entity['entity keys']['id'], $entity['entity keys']['label']))->range(0, 10);
}
else {
$query->fields('b', array($entity['entity keys']['id']))->range(0, 10);
$entity_info = entity_get_info($entity_type);
if (!module_exists('entity')) {
module_load_include('inc', 'ctools', 'includes/entity-access');
_ctools_entity_access($entity_info, $entity_type);
}
// We must query all ids, because if every one of the 10 don't have access
// the user may never be able to autocomplete a node title.
$preg_matches = array();
$matches = array();
$match = preg_match('/\[id: (\d+)\]/', $string, $preg_matches);
if (!$match) {
$match = preg_match('/^id: (\d+)/', $string, $preg_matches);
}
// If an ID match was found, use that ID rather than the whole string.
if ($match) {
$query->condition('b.' . $entity['entity keys']['id'], $preg_matches[1]);
}
elseif ($entity['entity keys']['label']) {
$query->condition('b.' . $entity['entity keys']['label'], '%' . db_like($string) . '%', 'LIKE');
}
$matches = array();
if ($type == 'node') {
if (!user_access('bypass node access')) {
// If the user is able to view their own unpublished nodes, allow them
// to see these in addition to published nodes.
if (user_access('view own unpublished content')) {
$query->condition(db_or()
->condition('b.status', NODE_PUBLISHED)
->condition('b.uid', $GLOBALS['user']->uid)
);
}
else {
// If not, restrict the query to published nodes.
$query->condition('b.status', NODE_PUBLISHED);
}
}
$query->addTag('node_access');
$query->join('users', 'u', 'b.uid = u.uid');
$query->addField('u', 'name', 'name');
foreach ($query->execute() as $nodeish) {
$name = empty($nodeish->name) ? variable_get('anonymous', t('Anonymous')) : check_plain($nodeish->name);
$matches[$nodeish->title . " [id: $nodeish->nid]"] = '<span class="autocomplete_title">' . check_plain($nodeish->title) . '</span> <span class="autocomplete_user">(' . t('by @user', array('@user' => $name)) . ')</span>';
}
$entity_id = $preg_matches[1];
$results = _ctools_getReferencableEntities($entity_type, $entity_info, $entity_id, '=', 1);
}
else {
foreach ($query->execute() as $item) {
$id = $item->{$entity['entity keys']['id']};
if ($entity['entity keys']['label']) {
$matches[$item->{$entity['entity keys']['label']} . " [id: $id]"] = '<span class="autocomplete_title">' . check_plain($item->{$entity['entity keys']['label']}) . '</span>';
}
else {
$matches["[id: $id]"] = '<span class="autocomplete_title">' . check_plain($item->{$entity['entity keys']['id']}) . '</span>';
}
// We cannot find results if the entity doesn't have a label to search.
if (!isset($entity_info['entity keys']['label'])) {
drupal_json_output(array("[id: NULL]" => '<span class="autocomplete_title">' . t('Entity Type !entity_type does not support autocomplete search.', array('!entity_type' => $entity_type)) . '</span>'));
return;
}
$results = _ctools_getReferencableEntities($entity_type, $entity_info, $string, 'LIKE', 10);
}
foreach ($results as $entity_id => $result) {
$matches[$result['label'] . " [id: $entity_id]"] = '<span class="autocomplete_title">' . check_plain($result['label']) . '</span>';
$matches[$result['label'] . " [id: $entity_id]"] .= isset($result['bundle']) ? ' <span class="autocomplete_bundle">(' . check_plain($result['bundle']) . ')</span>' : '';
}
drupal_json_output($matches);
}
}
/**
* Use EntityReference_SelectionHandler_Generic class to build our search query.
*/
function _ctools_buildQuery($entity_type, $entity_info, $match = NULL, $match_operator = 'CONTAINS') {
$base_table = $entity_info['base table'];
$label_key = $entity_info['entity keys']['label'];
$query = db_select($base_table)
->fields($base_table, array($entity_info['entity keys']['id']));
if (isset($match)) {
if (isset($label_key)) {
$query->condition($base_table . '.' . $label_key, '%' . $match . '%', $match_operator);
}
// This should never happen, but double check just in case.
else {
return array();
}
}
// Add a generic entity access tag to the query.
$query->addTag('ctools');
// We have to perform two checks. First check is a query alter (with tags)
// in an attempt to only return results that have access. However, this is
// not full-proof since entities many not implement hook_access query tag.
// This is why we have a second check after entity load, before we display
// the label of an entity.
if ($entity_type == 'comment') {
// Adding the 'comment_access' tag is sadly insufficient for comments: core
// requires us to also know about the concept of 'published' and
// 'unpublished'.
if (!user_access('administer comments')) {
$query->condition('comment.status', COMMENT_PUBLISHED);
}
// Join to a node if the user does not have node access bypass permissions
// to obey node published permissions.
if (!user_access('bypass node access')) {
$node_alias = $query->innerJoin('node', 'n', '%alias.nid = comment.nid');
$query->condition($node_alias . '.status', NODE_PUBLISHED);
}
$query->addTag('node_access');
}
else {
$query->addTag($entity_type . '_access');
}
// Add the sort option.
if (isset($label_key)) {
$query->orderBy($base_table . '.' . $label_key, 'ASC');
}
return $query;
}
/**
* Private function to get referencable entities. Based on code from the
* Entity Reference module.
*/
function _ctools_getReferencableEntities($entity_type, $entity_info, $match = NULL, $match_operator = 'LIKE', $limit = 0) {
global $user;
$account = $user;
$options = array();
// We're an entity ID, return the id.
if (is_numeric($match) && $match_operator == '=') {
if ($entity = array_shift(entity_load($entity_type, array($match)))) {
if (isset($entity_info['access callback']) && function_exists($entity_info['access callback'])) {
if ($entity_info['access callback']('view', $entity, $account, $entity_type)) {
$label = entity_label($entity_type, $entity);
return array(
$match => array(
'label' => !empty($label) ? $label : $entity->{$entity_info['entity keys']['id']},
'bundle' => !empty($entity_info['entity keys']['bundle']) ? check_plain($entity->{$entity_info['entity keys']['bundle']}) : NULL,
),
);
}
}
}
// If you don't have access, or an access callback or a valid entity, just
// Return back the Entity ID.
return array(
$match => array(
'label' => $match,
'bundle' => NULL,
),
);
}
// We have matches, build a query to fetch the result.
if ($query = _ctools_buildQuery($entity_type, $entity_info, $match, $match_operator)) {
if ($limit > 0) {
$query->range(0, $limit);
}
$results = $query->execute();
if (!empty($results)) {
foreach ($results as $record) {
$entities = entity_load($entity_type, array($record->{$entity_info['entity keys']['id']}));
$entity = array_shift($entities);
if (isset($entity_info['access callback']) && function_exists($entity_info['access callback'])) {
if ($entity_info['access callback']('view', $entity, $account, $entity_type)) {
$label = entity_label($entity_type, $entity);
$options[$record->{$entity_info['entity keys']['id']}] = array(
'label' => !empty($label) ? $label : $entity->{$entity_info['entity keys']['id']},
'bundle' => !empty($entity_info['entity keys']['bundle']) ? check_plain($entity->{$entity_info['entity keys']['bundle']}) : NULL,
);
}
}
}
}
return $options;
}
return array();
}
@@ -14,4 +14,4 @@ function ctools_content_plugin_type(&$items) {
'path' => drupal_get_path('module', 'ctools') . '/includes',
),
);
}
}
@@ -245,10 +245,10 @@ function ctools_access_admin_form_submit($form, &$form_state) {
// --------------------------------------------------------------------------
// AJAX menu entry points.
/**
* AJAX callback to add a new access test to the list.
*/
function ctools_access_ajax_add($fragment = NULL, $name = NULL) {
ctools_include('ajax');
ctools_include('modal');
@@ -263,7 +263,7 @@ function ctools_access_ajax_add($fragment = NULL, $name = NULL) {
ctools_ajax_render_error();
}
// Separate the fragment into 'module' and 'argument'
// Separate the fragment into 'module' and 'argument'.
if (strpos($fragment, '-') === FALSE) {
$module = $fragment;
$argument = NULL;
@@ -279,7 +279,7 @@ function ctools_access_ajax_add($fragment = NULL, $name = NULL) {
list($access, $contexts) = $function($argument);
// Make sure we have the logged in user context
// Make sure we have the logged in user context.
if (!isset($contexts['logged-in-user'])) {
$contexts['logged-in-user'] = ctools_access_get_loggedin_context();
}
@@ -306,6 +306,9 @@ function ctools_access_ajax_add($fragment = NULL, $name = NULL) {
);
$output = ctools_modal_form_wrapper('ctools_access_ajax_edit_item', $form_state);
$access = $form_state['access'];
$access['plugins'][$id] = $form_state['test'];
if (!isset($output[0])) {
$function = $module . '_ctools_access_set';
if (function_exists($function)) {
@@ -333,7 +336,7 @@ function ctools_access_ajax_edit($fragment = NULL, $id = NULL) {
ctools_ajax_render_error();
}
// Separate the fragment into 'module' and 'argument'
// Separate the fragment into 'module' and 'argument'.
if (strpos($fragment, '-') === FALSE) {
$module = $fragment;
$argument = NULL;
@@ -353,7 +356,7 @@ function ctools_access_ajax_edit($fragment = NULL, $id = NULL) {
ctools_ajax_render_error();
}
// Make sure we have the logged in user context
// Make sure we have the logged in user context.
if (!isset($contexts['logged-in-user'])) {
$contexts['logged-in-user'] = ctools_access_get_loggedin_context();
}
@@ -367,12 +370,14 @@ function ctools_access_ajax_edit($fragment = NULL, $id = NULL) {
'contexts' => $contexts,
'title' => t('Edit criteria'),
'ajax' => TRUE,
'ajax' => TRUE,
'modal' => TRUE,
'modal return' => TRUE,
);
$output = ctools_modal_form_wrapper('ctools_access_ajax_edit_item', $form_state);
$access = $form_state['access'];
$access['plugins'][$id] = $form_state['test'];
if (!isset($output[0])) {
$function = $module . '_ctools_access_set';
if (function_exists($function)) {
@@ -452,7 +457,7 @@ function ctools_access_ajax_delete($fragment = NULL, $id = NULL) {
ajax_render_error();
}
// Separate the fragment into 'module' and 'argument'
// Separate the fragment into 'module' and 'argument'.
if (strpos($fragment, '-') === FALSE) {
$module = $fragment;
$argument = NULL;
@@ -472,7 +477,7 @@ function ctools_access_ajax_delete($fragment = NULL, $id = NULL) {
unset($access['plugins'][$id]);
}
// re-cache
// re-cache.
$function = $module . '_ctools_access_set';
if (function_exists($function)) {
$function($argument, $access);
@@ -376,11 +376,11 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
'path' => "ctools/context/ajax/add/$mechanism/$type/$cache_key/$name/%step",
'show cancel' => TRUE,
'default form' => 'ctools_edit_context_form_defaults',
'auto caching' => TRUE,
'auto cache' => TRUE,
'cache mechanism' => $mechanism,
'cache key' => $cache_key,
// This is stating what the cache will be referred to in $form_state
'cache storage' => 'object',
'cache location' => 'object',
);
if ($type == 'requiredcontext') {
@@ -395,7 +395,7 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
if (!empty($form_state['cancel'])) {
$output = array(ctools_modal_command_dismiss());
}
else if (!empty($form_state['complete'])) {
elseif (!empty($form_state['complete'])) {
// Successful submit -- move temporary data to location.
// Create a reference to the place our context lives. Since this is fairly
@@ -416,12 +416,20 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
ctools_cache_operation($mechanism, $cache_key, 'finalize', $object);
// Very irritating way to update the form for our contexts.
$arg_form_state = array('values' => array());
$arg_form_state = form_state_defaults() + array(
'values' => array(),
'process_input' => FALSE,
'complete form' => array(),
);
$rel_form_state = $arg_form_state;
$arg_form = array(
'#post' => array(),
'#programmed' => FALSE,
'#tree' => FALSE,
'#parents' => array(),
'#array_parents' => array(),
);
// Build a chunk of the form to merge into the displayed form
@@ -446,6 +454,8 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
'#post' => array(),
'#programmed' => FALSE,
'#tree' => FALSE,
'#parents' => array(),
'#array_parents' => array(),
);
$rel_form['relationship'] = array(
@@ -460,7 +470,7 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke
$output = array();
if (!empty($available_relationships)) {
ctools_context_add_item_table_buttons('relationship', $mechanism, $rel_form, $available_relationships);
$rel_form = form_builder('dummy_form_id', $rel_form, $arg_form_state);
$rel_form = form_builder('dummy_form_id', $rel_form, $rel_form_state);
$output[] = ajax_command_replace('div#ctools-relationships-table div.buttons', drupal_render($rel_form));
}
@@ -551,11 +561,11 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k
'path' => "ctools/context/ajax/configure/$mechanism/$type/$cache_key/$position/%step",
'show cancel' => TRUE,
'default form' => 'ctools_edit_context_form_defaults',
'auto caching' => TRUE,
'auto cache' => TRUE,
'cache mechanism' => $mechanism,
'cache key' => $cache_key,
// This is stating what the cache will be referred to in $form_state
'cache storage' => 'object',
'cache location' => 'object',
);
if ($type == 'requiredcontext') {
@@ -570,7 +580,7 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k
if (!empty($form_state['cancel'])) {
$output = array(ctools_modal_command_dismiss());
}
else if (!empty($form_state['complete'])) {
elseif (!empty($form_state['complete'])) {
// successful submit
$ref[$position] = $conf;
if (isset($object->temporary)) {
@@ -582,8 +592,16 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k
$output = array();
$output[] = ctools_modal_command_dismiss();
$arg_form_state = form_state_defaults() + array(
'values' => array(),
'process_input' => FALSE,
'complete form' => array(),
);
$arg_form = array(
'#post' => array(),
'#parents' => array(),
'#array_parents' => array(),
'#programmed' => FALSE,
'#tree' => FALSE,
);
@@ -639,7 +657,7 @@ function ctools_context_get_defaults($plugin_definition, $object, $type) {
if (isset($plugin_definition['defaults'])) {
$defaults = $plugin_definition['defaults'];
}
else if (isset($subtype['defaults'])) {
elseif (isset($subtype['defaults'])) {
$defaults = $subtype['defaults'];
}
@@ -649,7 +667,7 @@ function ctools_context_get_defaults($plugin_definition, $object, $type) {
$conf += $settings;
}
}
else if (is_array($defaults)) {
elseif (is_array($defaults)) {
$conf += $defaults;
}
}
@@ -718,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;
@@ -734,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'];
@@ -4,9 +4,9 @@
* @file
* Support for creating 'context' type task handlers.
*
* Context task handlers expect the task to provide 0 or more contexts. The
* task handler should use those contexts as selection rules, as well as
* rendering with them.
* Context task handlers expect the task to provide 0 or more contexts. The task
* handler should use those contexts as selection rules, as well as rendering
* with them.
*
* The functions and forms in this file should be common to every context type
* task handler made.
@@ -31,6 +31,7 @@
* If TRUE then this renderer owns the page and can use theme('page')
* for no blocks; if false, output is returned regardless of any no
* blocks settings.
*
* @return
* Either the output or NULL if there was output, FALSE if no handler
* accepted the task. If $page is FALSE then the $info block is returned instead.
@@ -84,7 +85,7 @@ function ctools_context_handler_get_render_handler($task, $subtask, $handlers, $
*/
function ctools_context_handler_default_test($handler, $base_contexts, $args) {
ctools_include('context');
// Add my contexts
// Add my contexts.
$contexts = ctools_context_handler_get_handler_contexts($base_contexts, $handler);
// Test.
@@ -128,7 +129,7 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte
'contexts' => $contexts,
'task' => $task,
'subtask' => $subtask,
'handler' => $handler
'handler' => $handler,
);
drupal_alter('ctools_render', $info, $page, $context);
@@ -141,12 +142,15 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte
switch ($info['response code']) {
case 403:
return MENU_ACCESS_DENIED;
case 404:
return MENU_NOT_FOUND;
case 410:
drupal_add_http_header('Status', '410 Gone');
drupal_exit();
break;
case 301:
case 302:
case 303:
@@ -161,8 +165,8 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte
'query' => $info['query'],
'fragment' => $info['fragment'],
);
return drupal_goto($info['destination'], $options, $info['response code']);
// @todo -- should other response codes be supported here?
drupal_goto($info['destination'], $options, $info['response code']);
// @todo -- should other response codes be supported here?
}
}
@@ -222,7 +226,7 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte
}
/**
* Default function to provide contextual link for a task as defined by the handler.
* Provides contextual link for a task as defined by the handler.
*
* This provides a simple link to th main content operation and is suitable
* for most normal handlers. Setting 'contextual link' to a function overrides
@@ -241,7 +245,7 @@ function ctools_task_handler_default_contextual_link($handler, $plugin, $context
if (is_array($plugin['tab operation'])) {
$trail = $plugin['tab operation'];
}
else if (function_exists($plugin['tab operation'])) {
elseif (function_exists($plugin['tab operation'])) {
$trail = $plugin['tab operation']($handler, $contexts, $args);
}
}
@@ -251,7 +255,8 @@ function ctools_task_handler_default_contextual_link($handler, $plugin, $context
'href' => $path,
'title' => $title,
'query' => drupal_get_destination(),
));
),
);
return $links;
}
@@ -259,17 +264,22 @@ function ctools_task_handler_default_contextual_link($handler, $plugin, $context
/**
* Called to execute actions that should happen before a handler is rendered.
*/
function ctools_context_handler_pre_render($handler, $contexts, $args) { }
function ctools_context_handler_pre_render($handler, $contexts, $args) {
foreach (module_implements('ctools_context_handler_pre_render') as $module) {
$function = $module . '_ctools_context_handler_pre_render';
$function($handler, $contexts, $args);
}
}
/**
* Compare arguments to contexts for selection purposes.
*
* @param $handler
* @param object $handler
* The handler in question.
* @param $contexts
* @param object $contexts
* The context objects provided by the task.
*
* @return
* @return bool
* TRUE if these contexts match the selection rules. NULL or FALSE
* otherwise.
*/
@@ -288,12 +298,15 @@ function ctools_context_handler_select($handler, $contexts) {
* These summary strings are used to communicate to the user what
* arguments the task handlers are selecting.
*
* @param $task
* @param object $task
* The loaded task plugin.
* @param $subtask
* @param object $subtask
* The subtask id.
* @param $handler
* @param object $handler
* The handler to be checked.
*
* @return array
* Returns array of summary strings for arguments selected by task handlers.
*/
function ctools_context_handler_summary($task, $subtask, $handler) {
if (empty($handler->conf['access']['plugins'])) {
@@ -320,7 +333,6 @@ function ctools_context_handler_summary($task, $subtask, $handler) {
// the task handler, for example) but sometimes we need them separately
// (when a task has contexts loaded and is trying out the task handlers,
// for example). Therefore there are two paths we can take to getting contexts.
/**
* Load the contexts for a task, using arguments.
*
@@ -368,7 +380,7 @@ function ctools_context_handler_get_all_contexts($task, $subtask, $handler) {
* expects things in a certain, kind of clunky format.
*/
function ctools_context_handler_get_handler_object($handler) {
$object = new stdClass;
$object = new stdClass();
$object->name = $handler->name;
$object->contexts = isset($handler->conf['contexts']) ? $handler->conf['contexts'] : array();
$object->relationships = isset($handler->conf['relationships']) ? $handler->conf['relationships'] : array();
@@ -382,7 +394,7 @@ function ctools_context_handler_get_handler_object($handler) {
* arguments from the task.
*/
function ctools_context_handler_get_task_object($task, $subtask, $handler) {
$object = new stdClass;
$object = new stdClass();
$object->name = !empty($handler->name) ? $handler->name : 'temp';
$object->base_contexts = ctools_context_handler_get_base_contexts($task, $subtask, TRUE);
$object->arguments = ctools_context_handler_get_task_arguments($task, $subtask);
@@ -456,7 +468,7 @@ function ctools_context_handler_edit_criteria($form, &$form_state) {
ctools_modal_add_plugin_js(ctools_get_access_plugins());
ctools_include('context-access-admin');
$form_state['module'] = (isset($form_state['module'])) ? $form_state['module'] : 'page_manager_task_handler';
// Encode a bunch of info into the argument so we can get our cache later
// Encode a bunch of info into the argument so we can get our cache later.
$form_state['callback argument'] = $form_state['task_name'] . '*' . $form_state['handler']->name;
$form_state['access'] = $form_state['handler']->conf['access'];
$form_state['no buttons'] = TRUE;
@@ -472,7 +484,7 @@ function ctools_context_handler_edit_criteria($form, &$form_state) {
}
/**
* Submit handler for rules selection
* Submit handler for rules selection.
*/
function ctools_context_handler_edit_criteria_submit(&$form, &$form_state) {
$form_state['handler']->conf['access']['logic'] = $form_state['values']['logic'];
@@ -537,4 +549,3 @@ function ctools_context_handler_edit_context_submit(&$form, &$form_state) {
unset($form_state['page']->context_cache[$cache_name]);
}
}
File diff suppressed because it is too large Load Diff
@@ -25,7 +25,7 @@ function ctools_context_menu(&$items) {
'page callback' => 'ctools_context_ajax_item_delete',
) + $base;
// For the access system
// For the access system.
$base['file'] = 'includes/context-access-admin.inc';
$items['ctools/context/ajax/access/add'] = array(
'page callback' => 'ctools_access_ajax_add',
@@ -19,7 +19,6 @@ function ctools_context_theme(&$theme) {
);
$theme['ctools_context_item_form'] = array(
'render element' => 'form',
// 'variables' => array('form' => NULL),
'file' => 'includes/context.theme.inc',
);
$theme['ctools_context_item_row'] = array(
@@ -27,7 +26,7 @@ function ctools_context_theme(&$theme) {
'file' => 'includes/context.theme.inc',
);
// For the access plugin
// For the access plugin.
$theme['ctools_access_admin_add'] = array(
'render element' => 'form',
'file' => 'includes/context-access-admin.inc',
@@ -62,10 +61,10 @@ function theme_ctools_context_item_row($vars) {
function theme_ctools_context_item_form($vars) {
$form = $vars['form'];
$output = '';
$type = $form['#ctools_context_type'];
$module = $form['#ctools_context_module'];
$cache_key = $form['#cache_key'];
$output = '';
$type = $form['#ctools_context_type'];
$module = $form['#ctools_context_module'];
$cache_key = $form['#cache_key'];
$type_info = ctools_context_info($type);
@@ -104,17 +103,17 @@ function theme_ctools_context_item_form($vars) {
if (!empty($form['buttons'])) {
// Display the add context item.
$row = array();
$row[] = array('data' => render($form['buttons'][$type]['item']), 'class' => array('title'));
$row[] = array('data' => render($form['buttons'][$type]['add']), 'class' => array('add'), 'width' => "60%");
$output .= '<div class="buttons">';
$output .= render($form['buttons'][$type]);
$theme_vars = array();
$theme_vars['header'] = array();
$theme_vars['rows'] = array($row);
$row = array();
$row[] = array('data' => render($form['buttons'][$type]['item']), 'class' => array('title'));
$row[] = array('data' => render($form['buttons'][$type]['add']), 'class' => array('add'), 'width' => "60%");
$output .= '<div class="buttons">';
$output .= render($form['buttons'][$type]);
$theme_vars = array();
$theme_vars['header'] = array();
$theme_vars['rows'] = array($row);
$theme_vars['attributes'] = array('id' => $type . '-add-table');
$output .= theme('table', $theme_vars);
$output .= '</div>';
$output .= theme('table', $theme_vars);
$output .= '</div>';
}
if (!empty($form['description'])) {
$output .= render($form['description']);
@@ -139,7 +138,7 @@ function theme_ctools_context_list($vars) {
$description = (!empty($vars['description'])) ? $vars['description'] : NULL;
$titles = array();
$output = '';
$count = 1;
$count = 1;
$contexts = ctools_context_load_contexts($object);
@@ -209,7 +208,7 @@ function theme_ctools_context_list($vars) {
}
}
// And relationships
// And relationships.
if (!empty($object->relationships)) {
foreach ($object->relationships as $relationship) {
$output .= '<tr>';
@@ -253,15 +252,15 @@ function theme_ctools_context_list($vars) {
}
/**
* ctools_context_list() but not in a table format because tabledrag
* won't let us have tables within tables and still drag.
* The ctools_context_list() function but not in a table format because
* tabledrag won't let us have tables within tables and still drag.
*/
function theme_ctools_context_list_no_table($vars) {
$object = $vars['object'];
ctools_add_css('context');
$titles = array();
$output = '';
$count = 1;
$count = 1;
// Describe 'built in' contexts.
if (!empty($object->base_contexts)) {
foreach ($object->base_contexts as $id => $context) {
@@ -312,7 +311,7 @@ function theme_ctools_context_list_no_table($vars) {
$count++;
}
}
// And relationships
// And relationships.
if (!empty($object->relationships)) {
foreach ($object->relationships as $relationship) {
$output .= '<div class="ctools-context-holder clearfix">';
@@ -341,4 +340,3 @@ function theme_ctools_context_list_no_table($vars) {
return $output;
}
@@ -0,0 +1,52 @@
<?php
/**
* @file
* Custom cache implementation for the CTools CSS cache.
*/
class CToolsCssCache implements DrupalCacheInterface {
/**
* {@inheritdoc}
*/
public function clear($cid = NULL, $wildcard = FALSE) {
// Only clear the caches if the wildcard is set, this ensures that the cache
// is only cleared when the full caches are cleared manually (eg by invoking
// drupal_flush_all_caches()), and not on a cron run.
// @see drupal_flush_all_caches()
// @see system_cron()
if ($wildcard) {
ctools_include('css');
ctools_css_flush_caches();
}
}
/**
* {@inheritdoc}
*/
public function get($cid) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getMultiple(&$cids) {
return array();
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function set($cid, $data, $expire = CACHE_PERMANENT) {
}
}
@@ -1,6 +1,6 @@
<?php
/*
/**
* @file
* CSS filtering functions. Contains a disassembler, filter, compressor, and
* decompressor.
@@ -77,9 +77,9 @@ function ctools_css_store($id, $css, $filter = TRUE) {
$filename = ctools_css_cache($css, $filter);
db_insert('ctools_css_cache')
db_merge('ctools_css_cache')
->key(array('cid' => $id))
->fields(array(
'cid' => $id,
'filename' => $filename,
'css' => $css,
'filter' => intval($filter),
@@ -149,11 +149,11 @@ function ctools_css_clear($id) {
*
* @param $css
* A chunk of well-formed CSS text to cache.
* @param $filter
* @param bool $filter
* If TRUE the css will be filtered. If FALSE the text will be cached
* as-is.
*
* @return $filename
* @return string
* The filename the CSS will be cached in.
*/
function ctools_css_cache($css, $filter = TRUE) {
@@ -164,7 +164,6 @@ function ctools_css_cache($css, $filter = TRUE) {
// Create the css/ within the files folder.
$path = 'public://ctools/css';
if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
// if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
drupal_set_message(t('Unable to create CTools CSS cache directory. Check the permissions on your files directory.'), 'error');
return;
}
@@ -172,10 +171,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;
}
@@ -211,7 +212,7 @@ function ctools_css_filter($css, $compressed = TRUE) {
* An array of css data, as produced by @see ctools_css_disassemble()
* disassembler and the @see ctools_css_filter_css_data() filter.
*
* @return string $css
* @return string
* css optimized for human viewing.
*/
function ctools_css_assemble($css_data) {
@@ -241,7 +242,7 @@ function ctools_css_assemble($css_data) {
* An array of css data, as produced by @see ctools_css_disassemble()
* disassembler and the @see ctools_css_filter_css_data() filter.
*
* @return string $css
* @return string
* css optimized for use.
*/
function ctools_css_compress($css_data) {
@@ -277,7 +278,7 @@ function ctools_css_compress($css_data) {
* @param string $css
* A string containing the css to be disassembled.
*
* @return array $disassembled_css
* @return array
* An array of disassembled, slightly cleaned-up/formatted css statements.
*/
function ctools_css_disassemble($css) {
@@ -383,7 +384,6 @@ function _ctools_css_disassemble_declaration($declaration) {
* An array of disassembled, filtered CSS.
*/
function ctools_css_filter_css_data($css, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
//function ctools_css_filter_css_data($css, &$filtered = NULL, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
// Retrieve the default list of allowed properties if none is provided.
$allowed_properties = !empty($allowed_properties) ? $allowed_properties : ctools_css_filter_default_allowed_properties();
// Retrieve the default list of allowed values if none is provided.
@@ -391,19 +391,18 @@ function ctools_css_filter_css_data($css, $allowed_properties = array(), $allowe
// Define allowed values regex if none is provided.
$allowed_values_regex = !empty($allowed_values_regex) ? $allowed_values_regex : '/(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)/';
// Define disallowed url() value contents, if none is provided.
// $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/[url|expression]\s*\(\s*[^\s)]+?\s*\)\s*/';
$disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/(url|expression)/';
foreach ($css as $selector_str => $declaration) {
foreach ($declaration as $property => $value) {
if (!in_array($property, $allowed_properties)) {
// $filtered['properties'][$selector_str][$property] = $value;
// $filtered['properties'][$selector_str][$property] = $value;.
unset($css[$selector_str][$property]);
continue;
}
$value = str_replace('!important', '', $value);
if (preg_match($disallowed_values_regex, $value) || !(in_array($value, $allowed_values) || preg_match($allowed_values_regex, $value))) {
// $filtered['values'][$selector_str][$property] = $value;
// $filtered['values'][$selector_str][$property] = $value;.
unset($css[$selector_str][$property]);
continue;
}
@@ -44,7 +44,7 @@
*
* A fuller example, that hides the menu title when no menu is selected:
* @code
*function ctools_dependent_example() {
* function ctools_dependent_example() {
* $form = array();
* $form['menu'] = array(
* '#type' => 'fieldset',
@@ -72,12 +72,12 @@
* );
*
* return system_settings_form($form);
*}
* }
* @endcode
*
* An example for hiding checkboxes using #prefix and #suffix:
* @code
*function ctools_dependent_example_checkbox() {
* function ctools_dependent_example_checkbox() {
* $form = array();
* $form['object'] = array(
* '#type' => 'fieldset',
@@ -111,7 +111,7 @@
* );
*
* return system_settings_form($form);
*}
* }
* @endcode
*
* Deprecated:
@@ -125,7 +125,6 @@
/**
* Process callback to add dependency to form items.
*
*/
function ctools_dependent_process($element, &$form_state, &$form) {
return $element;
@@ -75,7 +75,7 @@ function theme_links__ctools_dropbutton($vars) {
if (!empty($vars['links'])) {
$is_drop_button = (count($vars['links']) > 1);
// Add needed files
// Add needed files.
if ($is_drop_button) {
ctools_add_js('dropbutton');
ctools_add_css('dropbutton');
@@ -86,7 +86,7 @@ function theme_links__ctools_dropbutton($vars) {
static $id = 0;
$id++;
// Wrapping div
// Wrapping div.
$class = 'ctools-no-js';
$class .= ($is_drop_button) ? ' ctools-dropbutton' : '';
$class .= ' ctools-button';
@@ -98,21 +98,22 @@ function theme_links__ctools_dropbutton($vars) {
$output .= '<div class="' . $class . '" id="ctools-button-' . $id . '">';
// Add a twisty if this is a dropbutton
// Add a twisty if this is a dropbutton.
if ($is_drop_button) {
$vars['title'] = ($vars['title'] ? check_plain($vars['title']) : t('open'));
$output .= '<div class="ctools-link">';
if ($vars['image']) {
$output .= '<a href="#" class="ctools-twisty ctools-image">' . $vars['title'] . '</a>';
$output .= '<a href="#" class="ctools-twisty ctools-image"><span class="element-invisible">' . $vars['title'] . '</span></a>';
}
else {
$output .= '<a href="#" class="ctools-twisty ctools-text">' . $vars['title'] . '</a>';
$output .= '<a href="#" class="ctools-twisty ctools-text"><span class="element-invisible">' . $vars['title'] . '</span></a>';
}
$output .= '</div>'; // ctools-link
// ctools-link.
$output .= '</div>';
}
// The button content
// The button content.
$output .= '<div class="ctools-content">';
// Check for attributes. theme_links expects an array().
@@ -132,12 +133,11 @@ function theme_links__ctools_dropbutton($vars) {
// Call theme_links to render the list of links.
$output .= theme_links(array('links' => $vars['links'], 'attributes' => $vars['attributes'], 'heading' => ''));
$output .= '</div>'; // ctools-content
$output .= '</div>'; // ctools-dropbutton
$output .= '</div>'; // ctools-content.
$output .= '</div>'; // ctools-dropbutton.
return $output;
}
else {
return '';
}
}
@@ -44,20 +44,21 @@ function ctools_dropdown_theme(&$items) {
/**
* Create a dropdown menu.
*
* @param $title
* The text to place in the clickable area to activate the dropdown.
* @param $links
* A list of links to provide within the dropdown, suitable for use
* in via Drupal's theme('links').
* @param $image
* If true, the dropdown link is an image and will not get extra decorations
* that a text dropdown link will.
* @param $class
* An optional class to add to the dropdown's container div to allow you
* to style a single dropdown however you like without interfering with
* other dropdowns.
* @param array $variables
* An associative array containing:
* - title: The text to place in the clickable area to activate the dropdown.
* - links: A list of links to provide within the dropdown, suitable for use
* in via Drupal's theme('links').
* - image: If true, the dropdown link is an image and will not get extra
* decorations that a text dropdown link will.
* - class: An optional class to add to the dropdown's container div to allow
* you to style a single dropdown however you like without interfering with
* other dropdowns.
*
* @return string
* Returns HTML for a language configuration form.
*/
function theme_ctools_dropdown($vars) {
function theme_ctools_dropdown($vars) {
// Provide a unique identifier for every dropdown on the page.
static $id = 0;
$id++;
@@ -67,9 +68,7 @@ function theme_ctools_dropdown($vars) {
ctools_add_js('dropdown');
ctools_add_css('dropdown');
$output = '';
$output .= '<div class="' . $class . '" id="ctools-dropdown-' . $id . '">';
$output = '<div class="' . $class . '" id="ctools-dropdown-' . $id . '">';
$output .= '<div class="ctools-dropdown-link-wrapper">';
if ($vars['image']) {
$output .= '<a href="#" class="ctools-dropdown-link ctools-dropdown-image-link">' . $vars['title'] . '</a>';
@@ -77,14 +76,13 @@ function theme_ctools_dropdown($vars) {
else {
$output .= '<a href="#" class="ctools-dropdown-link ctools-dropdown-text-link">' . check_plain($vars['title']) . '</a>';
}
$output .= '</div>'; // wrapper
$output .= '</div>';
$output .= '<div class="ctools-dropdown-container-wrapper">';
$output .= '<div class="ctools-dropdown-container">';
$output .= theme_links(array('links' => $vars['links'], 'attributes' => array(), 'heading' => ''));
$output .= '</div>'; // container
$output .= '</div>'; // container wrapper
$output .= '</div>'; // dropdown
$output .= '</div>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
@@ -0,0 +1,154 @@
<?php
/**
* @file
* Provides various callbacks for the whole core module integration.
* This is a copy of Entity API's functionality for use when Entity API isn't
* Enabled, and only works on view functions.
*/
/**
* Core hack to include entity api-esque 'access callback' functions to core
* entities without needing to rely on entity api.
* Exception: We don't touch file entity. You must have entity API enabled to
* view files.
*/
function _ctools_entity_access(&$entity_info, $entity_type) {
// If the access callback is already set, don't change anything.
if (isset($entity_info['access callback'])) {
return;
}
switch ($entity_type) {
case 'node':
// Sad panda, we don't use Entity API, lets manually add access callbacks.
$entity_info['access callback'] = 'ctools_metadata_no_hook_node_access';
break;
case 'user':
$entity_info['access callback'] = 'ctools_metadata_user_access';
break;
case 'comment':
if (module_exists('comment')) {
$entity_info['access callback'] = 'ctools_metadata_comment_access';
}
break;
case 'taxonomy_term':
if (module_exists('taxonomy')) {
$entity_info['access callback'] = 'ctools_metadata_taxonomy_access';
}
break;
case 'taxonomy_vocabulary':
if (module_exists('taxonomy')) {
$entity_info['access callback'] = 'ctools_metadata_taxonomy_access';
}
break;
}
}
/**
* Access callback for the node entity.
*
* This function does not implement hook_node_access(), thus it may not be
* called ctools_metadata_node_access().
*
* @see entity_access()
*
* @param $op
* The operation being performed. One of 'view', 'update', 'create' or
* 'delete'.
* @param $node
* A node to check access for. Must be a node object. Must have nid,
* except in the case of 'create' operations.
* @param $account
* The user to check for. Leave it to NULL to check for the global user.
*
* @throws EntityMalformedException
*
* @return bool
* TRUE if access is allowed, FALSE otherwise.
*/
function ctools_metadata_no_hook_node_access($op, $node = NULL, $account = NULL) {
// First deal with the case where a $node is provided.
if (isset($node)) {
// If a non-default revision is given, incorporate revision access.
$default_revision = node_load($node->nid);
if ($node->vid !== $default_revision->vid) {
return _node_revision_access($node, $op, $account);
}
else {
return node_access($op, $node, $account);
}
}
// No node is provided. Check for access to all nodes.
if (user_access('bypass node access', $account)) {
return TRUE;
}
if (!user_access('access content', $account)) {
return FALSE;
}
if ($op == 'view' && node_access_view_all_nodes($account)) {
return TRUE;
}
return FALSE;
}
/**
* Access callback for the user entity.
*/
function ctools_metadata_user_access($op, $entity = NULL, $account = NULL, $entity_type) {
$account = isset($account) ? $account : $GLOBALS['user'];
// Grant access to the users own user account and to the anonymous one.
if (isset($entity) && $op != 'delete' && (($entity->uid == $account->uid && $entity->uid) || (!$entity->uid && $op == 'view'))) {
return TRUE;
}
if (user_access('administer users', $account) || user_access('access user profiles', $account) && $op == 'view' && $entity->status) {
return TRUE;
}
return FALSE;
}
/**
* Access callback for the comment entity.
*/
function ctools_metadata_comment_access($op, $entity = NULL, $account = NULL) {
// When determining access to a comment, if comment has an associated node,
// the user must be able to view the node in order to access the comment.
if (isset($entity->nid)) {
if (!node_access('view', node_load($entity->nid), $account)) {
return FALSE;
}
}
// Comment administrators are allowed to perform all operations on all
// comments.
if (user_access('administer comments', $account)) {
return TRUE;
}
// Unpublished comments can never be accessed by non-admins.
if (isset($entity->status) && $entity->status == COMMENT_NOT_PUBLISHED) {
return FALSE;
}
if (user_access('access comments', $account) && $op == 'view') {
return TRUE;
}
return FALSE;
}
/**
* Access callback for the taxonomy entities.
*/
function ctools_metadata_taxonomy_access($op, $entity = NULL, $account = NULL, $entity_type) {
if ($entity_type == 'taxonomy_vocabulary') {
return user_access('administer taxonomy', $account);
}
if (user_access('administer taxonomy', $account) || user_access('access content', $account) && $op == 'view') {
return TRUE;
}
return FALSE;
}
@@ -81,7 +81,6 @@ function ctools_export_ui_process(&$plugin, $info) {
// Add some default fields that appear often in exports
// If these use different keys they can easily be specified in the
// $plugin.
if (empty($plugin['export']['admin_title']) && !empty($schema['fields']['admin_title'])) {
$plugin['export']['admin_title'] = 'admin_title';
}
@@ -297,7 +296,6 @@ function ctools_export_ui_process(&$plugin, $info) {
);
// Define strings.
// For all strings, %title may be filled in at a later time via str_replace
// since we do not know the title now.
$plugin['strings'] += array(
@@ -335,7 +333,7 @@ function ctools_export_ui_process(&$plugin, $info) {
$plugin['strings']['confirmation']['delete'] += array(
'question' => t('Are you sure you want to delete %title?'),
'information' => t('This action will permanently remove this item from your database..'),
'information' => t('This action will permanently remove this item from your database.'),
'success' => t('The item has been deleted.'),
);
@@ -414,6 +412,7 @@ function ctools_export_ui_plugin_base_path($plugin) {
* The id in the menu items from the plugin.
* @param $export_key
* The export key of the item being edited, if it exists.
*
* @return
* The menu path to the plugin's list.
*/
@@ -429,12 +428,11 @@ function ctools_export_ui_plugin_menu_path($plugin, $item_id, $export_key = NULL
* Helper function to include CTools plugins and get an export-ui exportable.
*
* @param $plugin_name
* The plugin that should be laoded.
* The plugin that should be loaded.
*/
function ctools_get_export_ui($plugin_name) {
ctools_include('plugins');
return ctools_get_plugins('ctools', 'export_ui', $plugin_name);
}
/**
@@ -456,14 +454,14 @@ function ctools_export_ui_switcher_page($plugin_name, $op) {
$args = func_get_args();
$js = !empty($_REQUEST['js']);
// Load the $plugin information
// Load the $plugin information.
$plugin = ctools_get_export_ui($plugin_name);
$handler = ctools_export_ui_get_handler($plugin);
if ($handler) {
$method = $op . '_page';
if (method_exists($handler, $method)) {
// replace the first two arguments:
// Replace the first two arguments:
$args[0] = $js;
$args[1] = $_POST;
return call_user_func_array(array($handler, $method), $args);
@@ -1,5 +1,9 @@
<?php
/**
* @file
*/
/**
* Delegated implementation of hook_menu().
*/
@@ -17,4 +17,4 @@ function ctools_export_ui_plugin_type(&$items) {
),
'classes' => array('handler'),
);
}
}
@@ -4,7 +4,7 @@
* @file
* Contains code to make it easier to have exportable objects.
*
* Documentation for exportable objects is contained in help/export.html
* Documentation for exportable objects is contained in help/export.html.
*/
/**
@@ -126,6 +126,7 @@ function ctools_export_crud_load_multiple($table, array $names) {
* If TRUE, the static cache of all objects will be flushed prior to
* loading all. This can be important on listing pages where items
* might have changed on the page load.
*
* @return
* An array of all loaded objects, keyed by the unique IDs of the export key.
*/
@@ -328,7 +329,6 @@ function ctools_export_crud_set_status($table, $object, $status) {
}
/**
* Enable a certain object.
*
@@ -426,7 +426,7 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
}
}
// Build the query
// Build the query.
$query = db_select($table, 't__0')->fields('t__0');
$alias_count = 1;
if (!empty($schema['join'])) {
@@ -451,7 +451,7 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
if ($type == 'names') {
$query->condition($export['key'], $args, 'IN');
}
else if ($type == 'conditions') {
elseif ($type == 'conditions') {
foreach ($args as $key => $value) {
if (isset($schema['fields'][$key])) {
$query->condition($key, $value);
@@ -499,7 +499,7 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
if ($defaults) {
foreach ($defaults as $object) {
if ($type == 'conditions') {
// if this does not match all of our conditions, skip it.
// If this does not match all of our conditions, skip it.
foreach ($args as $key => $value) {
if (!isset($object->$key)) {
continue 2;
@@ -509,12 +509,12 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
continue 2;
}
}
else if ($object->$key != $value) {
elseif ($object->$key != $value) {
continue 2;
}
}
}
else if ($type == 'names') {
elseif ($type == 'names') {
if (!in_array($object->{$export['key']}, $args)) {
continue;
}
@@ -561,7 +561,6 @@ function ctools_export_load_object($table, $type = 'all', $args = array()) {
}
}
// For conditions,
return $return;
}
@@ -807,10 +806,10 @@ function _ctools_export_get_some_defaults($table, $export, $names) {
function _ctools_export_unpack_object($schema, $data, $object = 'stdClass') {
if (is_string($object)) {
if (class_exists($object)) {
$object = new $object;
$object = new $object();
}
else {
$object = new stdClass;
$object = new stdClass();
}
}
@@ -873,14 +872,14 @@ function ctools_var_export($var, $prefix = '') {
$output .= $prefix . ')';
}
}
else if (is_object($var) && get_class($var) === 'stdClass') {
elseif (is_object($var) && get_class($var) === 'stdClass') {
// var_export() will export stdClass objects using an undefined
// magic method __set_state() leaving the export broken. This
// workaround avoids this by casting the object as an array for
// export and casting it back to an object when evaluated.
$output = '(object) ' . ctools_var_export((array) $var, $prefix);
}
else if (is_bool($var)) {
elseif (is_bool($var)) {
$output = $var ? 'TRUE' : 'FALSE';
}
else {
@@ -902,7 +901,8 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL,
$output = $indent . '$' . $identifier . ' = new ' . get_class($object) . "();\n";
if ($schema['export']['can disable']) {
$output .= $indent . '$' . $identifier . '->disabled = FALSE; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
$disabled = !isset($object->disabled) || $object->disabled != TRUE ? 'FALSE' : 'TRUE';
$output .= $indent . '$' . $identifier . '->disabled = ' . $disabled . '; /* Edit this to true to make a default ' . $identifier . ' disabled initially */' . "\n";
}
if (!empty($schema['export']['api']['current_version'])) {
$output .= $indent . '$' . $identifier . '->api_version = ' . $schema['export']['api']['current_version'] . ";\n";
@@ -945,14 +945,20 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL,
else {
$value = $object->$field;
if ($info['type'] == 'int') {
$value = (isset($info['size']) && $info['size'] == 'tiny') ? (bool) $value : (int) $value;
if (isset($info['size']) && $info['size'] == 'tiny') {
$info['boolean'] = (!isset($info['boolean'])) ? $schema['export']['boolean'] : $info['boolean'];
$value = ($info['boolean']) ? (bool) $value : (int) $value;
}
else {
$value = (int) $value;
}
}
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
}
}
// And bottom additions here
// And bottom additions here.
foreach ($additions2 as $field => $value) {
$output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
}
@@ -967,7 +973,12 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL,
* that it's easily available.
*/
function ctools_export_get_schema($table) {
$cache = &drupal_static(__FUNCTION__);
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
}
$cache = &$drupal_static_fast['cache'];
if (empty($cache[$table])) {
$schema = drupal_get_schema($table);
@@ -975,7 +986,7 @@ function ctools_export_get_schema($table) {
// simply hasn't been cached. If we've been asked, let's force the
// issue.
if (!$schema || empty($schema['export'])) {
// force a schema reset:
// Force a schema reset:
$schema = drupal_get_schema($table, TRUE);
}
@@ -987,7 +998,7 @@ function ctools_export_get_schema($table) {
return array();
}
// Add some defaults
// Add some defaults.
$schema['export'] += array(
'key' => 'name',
'key name' => 'Name',
@@ -1003,6 +1014,7 @@ function ctools_export_get_schema($table) {
'cache defaults' => FALSE,
'default cache bin' => 'cache',
'export type string' => 'type',
'boolean' => TRUE,
);
// If the export definition doesn't have the "primary key" then the CRUD
@@ -1094,7 +1106,7 @@ function ctools_export_set_object_status($object, $new_status = TRUE) {
$export = $schema['export'];
$status = variable_get($export['status'], array());
// Compare
// Compare.
if (!$new_status && $object->export_type & EXPORT_IN_DATABASE) {
unset($status[$object->{$export['key']}]);
}
@@ -1137,12 +1149,12 @@ function ctools_export_new_object($table, $set_defaults = TRUE) {
$schema = ctools_export_get_schema($table);
$export = $schema['export'];
$object = new $export['object'];
$object = new $export['object']();
foreach ($schema['fields'] as $field => $info) {
if (isset($info['object default'])) {
$object->$field = $info['object default'];
}
else if (isset($info['default'])) {
elseif (isset($info['default'])) {
$object->$field = $info['default'];
}
else {
@@ -1167,11 +1179,11 @@ function ctools_export_new_object($table, $set_defaults = TRUE) {
function ctools_export_to_hook_code(&$code, $table, $names = array(), $name = 'foo') {
$schema = ctools_export_get_schema($table);
$export = $schema['export'];
// Use the schema-specified function for generating hook code, if one exists
// Use the schema-specified function for generating hook code, if one exists.
if (function_exists($export['to hook code callback'])) {
$output = $export['to hook code callback']($names, $name);
}
// Otherwise, the following code generates basic hook code
// Otherwise, the following code generates basic hook code.
else {
$output = ctools_export_default_to_hook_code($schema, $table, $names, $name);
}
@@ -1215,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";
@@ -1223,6 +1235,7 @@ function ctools_export_default_to_hook_code($schema, $table, $names, $name) {
return $output;
}
/**
* Default function for listing bulk exportable objects.
*/
@@ -5,7 +5,6 @@
* Extend core fields with some helper functions to reduce code complexity within views and ctools plugins.
*/
/**
* Fake an instance of a field.
*
@@ -75,14 +74,30 @@ function ctools_fields_get_field_formatter_settings_form($field, $formatter_type
$conf['formatter_settings'] += $formatter['settings'];
}
$function = $formatter['module'] . '_field_formatter_settings_form';
$instance = ctools_fields_fake_field_instance($field['field_name'], $view_mode, $formatter_type, $conf['formatter_settings']);
if (function_exists($function)) {
$instance = ctools_fields_fake_field_instance($field['field_name'], $view_mode, $formatter_type, $conf['formatter_settings']);
$settings_form = $function($field, $instance, $view_mode, $form, $form_state);
if ($settings_form) {
$form['ctools_field_list']['#value'][] = $field;
$form += $settings_form;
}
}
if (empty($settings_form)) {
$settings_form = array();
}
// Allow other modules to alter the formatter settings form.
$context = array(
'module' => $formatter['module'],
'formatter' => $formatter,
'field' => $field,
'instance' => $instance,
'view_mode' => $view_mode,
'form' => $form,
'form_state' => $form_state,
);
drupal_alter('field_formatter_settings_form', $settings_form, $context);
$settings_form['#tree'] = TRUE;
$form['ctools_field_list']['#value'][] = $field;
$form += $settings_form;
if (isset($field['cardinality']) && $field['cardinality'] != 1) {
list($prefix, $suffix) = explode('@count', t('Skip the first @count item(s)'));
@@ -124,7 +139,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'])) {
@@ -132,7 +147,6 @@ function ctools_fields_get_field_formatter_info($fields) {
}
}
}
drupal_alter('field_formatter_info', $info);
return $info;
}
@@ -196,15 +210,15 @@ function ctools_field_label($field_name) {
* - Otherwise NULL.
* @param $options
* An associative array of additional options, with the following keys:
* - 'field_name': The name of the field whose operation should be
* - 'field_name': The name of the field whose operation should be
* invoked. By default, the operation is invoked on all the fields
* in the entity's bundle. NOTE: This option is not compatible with
* the 'deleted' option; the 'field_id' option should be used
* instead.
* - 'field_id': The id of the field whose operation should be
* - 'field_id': The id of the field whose operation should be
* invoked. By default, the operation is invoked on all the fields
* in the entity's' bundles.
* - 'default': A boolean value, specifying which implementation of
* - 'default': A boolean value, specifying which implementation of
* the operation should be invoked.
* - if FALSE (default), the field types implementation of the operation
* will be invoked (hook_field_[op])
@@ -212,10 +226,10 @@ function ctools_field_label($field_name) {
* will be invoked (field_default_[op])
* Internal use only. Do not explicitely set to TRUE, but use
* _field_invoke_default() instead.
* - 'deleted': If TRUE, the function will operate on deleted fields
* - 'deleted': If TRUE, the function will operate on deleted fields
* as well as non-deleted fields. If unset or FALSE, only
* non-deleted fields are operated on.
* - 'language': A language code or an array of language codes keyed by field
* - 'language': A language code or an array of language codes keyed by field
* name. It will be used to narrow down to a single value the available
* languages to act on.
*
@@ -328,7 +342,7 @@ function ctools_field_foreign_keys($field_name) {
$foreign_keys[$field_name] = $field['foreign keys'];
}
else {
// try to fetch foreign keys from schema, as not everything
// Try to fetch foreign keys from schema, as not everything
// stores foreign keys properly in the field info.
$module = $field['module'];
@@ -8,7 +8,6 @@
* if javascript is in use. Each item is keyed to the href that the button
* should go to. With javascript, the page is immediately redirected. Without
* javascript, the form is submitted and a drupal_goto() is given.
*
*/
/**
@@ -51,7 +50,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;
@@ -127,7 +126,7 @@ function ctools_jump_menu_submit($form, &$form_state) {
// This allows duplicate paths to be used in jump menus for multiple options.
$redirect_array = explode("::", $form_state['values']['jump']);
if(isset($redirect_array[1]) && !empty($redirect_array[1])){
if (isset($redirect_array[1]) && !empty($redirect_array[1])) {
$redirect = $redirect_array[1];
}
else {
@@ -1,5 +1,9 @@
<?php
/**
* @file
*/
/**
* Returns array of language names.
*
@@ -32,7 +36,6 @@ function ctools_language_list($field = 'name', $all = FALSE) {
* Returns an array of language names similar to ctools_language_list() except
* that additional choices have been added for ease of use.
*/
function ctools_language_list_all() {
$languages = array(
'***CURRENT_LANGUAGE***' => t("Current user's language"),
@@ -41,4 +44,4 @@ function ctools_language_list_all() {
);
$languages = array_merge($languages, ctools_language_list());
return $languages;
}
}
@@ -99,7 +99,10 @@ class ctools_math_expr {
'sqrt','abs','ln','log',
'time', 'ceil', 'floor', 'min', 'max', 'round');
function ctools_math_expr() {
/**
* ctools_math_expr constructor.
*/
function __construct() {
// make the variables a little more accurate
$this->v['pi'] = pi();
$this->v['e'] = exp(1);
@@ -271,7 +274,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.
@@ -55,9 +55,9 @@ function ctools_modal_add_js() {
'alt' => t('Close window'),
)),
'throbber' => theme('image', array(
'path' => ctools_image_path('throbber.gif'),
'title' => t('Loading...'),
'alt' => t('Loading'),
'path' => ctools_image_path('throbber.gif'),
'title' => t('Loading...'),
'alt' => t('Loading'),
)),
),
);
@@ -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');
@@ -84,7 +85,7 @@ function ctools_modal_add_plugin_js($plugins) {
if (file_exists($file)) {
$js[$file] = TRUE;
}
else if (file(exists($subtype['path'] . '/' . $file))) {
elseif (file(exists($subtype['path'] . '/' . $file))) {
$js[$subtype['path'] . '/' . $file] = TRUE;
}
}
@@ -94,7 +95,7 @@ function ctools_modal_add_plugin_js($plugins) {
if (file_exists($file)) {
$css[$file] = TRUE;
}
else if (file(exists($subtype['path'] . '/' . $file))) {
elseif (file(exists($subtype['path'] . '/' . $file))) {
$css[$subtype['path'] . '/' . $file] = TRUE;
}
}
@@ -139,7 +140,7 @@ function ctools_modal_command_dismiss() {
}
/**
* Display loading screen in the modal
* Display loading screen in the modal.
*/
function ctools_modal_command_loading() {
return array(
@@ -187,18 +188,32 @@ function ctools_modal_text_button($text, $dest, $alt, $class = '') {
/**
* Wrap a form so that we can use it properly with AJAX. Essentially if the
* form wishes to render, it automatically does that, otherwise it returns
* so we can see submission results.
* the render array so we can see submission results.
*
* @return
* @param array $form
* An associative array containing the structure of the form.
* @param array $form_state
* An associative array containing the current state of the form.
* If the 'reset_html_ids' key is set to TRUE, it will prevent HTML IDs in
* forms from being incremented.
*
* @return mixed
* The output of the form, if it was rendered. If $form_state['ajax']
* is set, this will use ctools_modal_form_render so it will be
* a $command object suitable for ajax_render already.
*
* The return will be NULL if the form was successfully submitted unless
* you specifically set re_render = TRUE. If ajax is set the
* form will never be redirected.
* If the form was not rendered, the raw render array will be returned.
*
* If ajax is set the form will never be redirected.
*/
function ctools_modal_form_wrapper($form_id, &$form_state) {
// Since this will run again on form rebuild while still in the modal, prevent
// form IDs from being incremented.
// @todo https://drupal.org/node/1305882
if (!empty($form_state['reset_html_ids']) && !empty($_POST['ajax_html_ids'])) {
unset($_POST['ajax_html_ids']);
}
// This won't override settings already in.
$form_state += array(
're_render' => FALSE,
@@ -206,8 +221,8 @@ function ctools_modal_form_wrapper($form_id, &$form_state) {
);
$output = drupal_build_form($form_id, $form_state);
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
return ctools_modal_form_render($form_state, $output);
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
return ctools_modal_form_render($form_state, $output);
}
return $output;
@@ -27,6 +27,7 @@
* defaults to session_id().
*
* @deprecated $skip_cache is deprecated in favor of drupal_static*
*
* @return
* The data that was cached.
*/
@@ -42,8 +43,11 @@ function ctools_object_cache_get($obj, $name, $skip_cache = FALSE, $sid = NULL)
}
if (!array_key_exists($key, $cache)) {
$data = db_query('SELECT * FROM {ctools_object_cache} WHERE sid = :session_id AND obj = :object AND name = :name', array(':session_id' => $sid, ':object' => $obj, ':name' => $name))
->fetchObject();
$data = db_query('SELECT * FROM {ctools_object_cache} WHERE sid = :session_id AND obj = :object AND name = :name', array(
':session_id' => $sid,
':object' => $obj,
':name' => md5($name),
))->fetchObject();
if ($data) {
$cache[$key] = unserialize($data->data);
}
@@ -83,7 +87,7 @@ function ctools_object_cache_set($obj, $name, $cache, $sid = NULL) {
->fields(array(
'sid' => $sid,
'obj' => $obj,
'name' => $name,
'name' => md5($name),
'data' => serialize($cache),
'updated' => REQUEST_TIME,
))
@@ -91,7 +95,7 @@ function ctools_object_cache_set($obj, $name, $cache, $sid = NULL) {
}
/**
* Remove an object from the non-volatile ctools cache
* Remove an object from the non-volatile ctools cache.
*
* @param $obj
* A 128 character or less string to define what kind of object is being
@@ -103,7 +107,6 @@ function ctools_object_cache_set($obj, $name, $cache, $sid = NULL) {
* defaults to session_id().
*/
function ctools_object_cache_clear($obj, $name, $sid = NULL) {
if (!$sid) {
$sid = session_id();
}
@@ -111,13 +114,12 @@ function ctools_object_cache_clear($obj, $name, $sid = NULL) {
db_delete('ctools_object_cache')
->condition('sid', $sid)
->condition('obj', $obj)
->condition('name', $name)
->condition('name', md5($name))
->execute();
// Ensure the static cache is emptied of this obj:name set.
drupal_static_reset('ctools_object_cache_get');
}
/**
* Determine if another user has a given object cached.
*
@@ -142,8 +144,11 @@ function ctools_object_cache_test($obj, $name, $sid = NULL) {
$sid = session_id();
}
return db_query('SELECT s.uid, c.updated FROM {ctools_object_cache} c INNER JOIN {sessions} s ON c.sid = s.sid WHERE s.sid <> :session_id AND c.obj = :obj AND c.name = :name ORDER BY c.updated ASC', array(':session_id' => $sid, ':obj' => $obj, ':name' => $name))
->fetchObject();
return db_query('SELECT s.uid, c.updated FROM {ctools_object_cache} c INNER JOIN {sessions} s ON c.sid = s.sid WHERE s.sid <> :session_id AND c.obj = :obj AND c.name = :name ORDER BY c.updated ASC', array(
':session_id' => $sid,
':obj' => $obj,
':name' => md5($name),
))->fetchObject();
}
/**
@@ -162,6 +167,7 @@ function ctools_object_cache_test($obj, $name, $sid = NULL) {
* An array of objects containing the UID and updated date for each name found.
*/
function ctools_object_cache_test_objects($obj, $names) {
array_walk($names, 'md5');
return db_query("SELECT c.name, s.uid, c.updated FROM {ctools_object_cache} c INNER JOIN {sessions} s ON c.sid = s.sid WHERE c.obj = :obj AND c.name IN (:names) ORDER BY c.updated ASC", array(':obj' => $obj, ':names' => $names))
->fetchAllAssoc('name');
}
@@ -180,7 +186,7 @@ function ctools_object_cache_test_objects($obj, $names) {
function ctools_object_cache_clear_all($obj, $name) {
db_delete('ctools_object_cache')
->condition('obj', $obj)
->condition('name', $name)
->condition('name', md5($name))
->execute();
// Ensure the static cache is emptied of this obj:name set.
$cache = &drupal_static('ctools_object_cache_get', array());
@@ -197,7 +203,8 @@ function ctools_object_cache_clear_all($obj, $name) {
*/
function ctools_object_cache_clean($age = NULL) {
if (empty($age)) {
$age = 86400 * 7; // 7 days
// 7 days.
$age = 86400 * 7;
}
db_delete('ctools_object_cache')
->condition('updated', REQUEST_TIME - $age, '<')
@@ -1,5 +1,9 @@
<?php
/**
* @file
*/
/**
* Fetch metadata on a specific page_wizard plugin.
*
@@ -53,7 +57,7 @@ function page_manager_get_wizard_cache($plugin) {
}
function page_manager_make_wizard_cache($plugin) {
$cache = new stdClass;
$cache = new stdClass();
$cache->plugin = $plugin;
if ($function = ctools_plugin_get_function($plugin, 'default cache')) {
$function($cache);
@@ -10,6 +10,7 @@
*
* Implementing this
*/
/**
* Get a plugin configuration form.
*
@@ -100,7 +101,7 @@ function _ctools_plugin_configure_create_form_info(&$form_info, $plugin_definiti
if (empty($plugin_definition['title'])) {
$title = t('Configure');
}
else if ($op == 'add') {
elseif ($op == 'add') {
$title = t('Configure new !plugin_title', array('!plugin_title' => $plugin_definition['title']));
}
else {
@@ -134,10 +135,10 @@ function _ctools_plugin_configure_create_form_info(&$form_info, $plugin_definiti
$form_info['forms']['form']['wrapper'] = 'ctools_plugins_default_form_wrapper';
}
}
else if (is_array($info)) {
if (empty($form_info['order'])) {
$form_info['order'] = array();
}
elseif (is_array($info)) {
if (empty($form_info['order'])) {
$form_info['order'] = array();
}
if (empty($form_info['forms'])) {
$form_info['forms'] = array();
}
@@ -2,7 +2,6 @@
/**
* @file
*
* Contains routines to organize and load plugins. It allows a special
* variation of the hook system so that plugins can be kept in separate
* .inc files, and can be either loaded all at once or loaded only when
@@ -70,7 +69,7 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
if (isset($info['version'])) {
$version = $info['version'];
}
else if (isset($info['api'])) {
elseif (isset($info['api'])) {
$version = $info['api'];
}
@@ -79,7 +78,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);
}
@@ -97,7 +98,7 @@ function ctools_plugin_api_info($owner, $api, $minimum_version, $current_version
}
// Only process if version is between minimum and current, inclusive.
if (version_compare($info['version'], $minimum_version, '>=') && version_compare($info['version'], $current_version, '<=')) {
if (version_compare($info['version'], $minimum_version, '>=') && version_compare($info['version'], $current_version, '<=')) {
if (!isset($info['path'])) {
$info['path'] = '';
}
@@ -110,7 +111,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];
@@ -149,7 +150,7 @@ function ctools_plugin_api_include($owner, $api, $minimum_version, $current_vers
if (isset($plugin_info["$api file"])) {
$file = $plugin_info["$api file"];
}
else if (isset($plugin_info['file'])) {
elseif (isset($plugin_info['file'])) {
$file = $plugin_info['file'];
}
else {
@@ -159,7 +160,7 @@ function ctools_plugin_api_include($owner, $api, $minimum_version, $current_vers
if (file_exists(DRUPAL_ROOT . "/$plugin_info[path]/$file")) {
require_once DRUPAL_ROOT . "/$plugin_info[path]/$file";
}
else if (file_exists(DRUPAL_ROOT . "/$file")) {
elseif (file_exists(DRUPAL_ROOT . "/$file")) {
require_once DRUPAL_ROOT . "/$file";
}
$already_done[$owner][$api][$module] = TRUE;
@@ -182,7 +183,7 @@ function ctools_plugin_api_get_hook($owner, $api) {
if (function_exists($function = $owner . '_' . $api . '_hook_name')) {
$hook = $function();
}
else if (function_exists($function = $owner . '_ctools_plugin_api_hook_name')) {
elseif (function_exists($function = $owner . '_ctools_plugin_api_hook_name')) {
$hook = $function();
}
@@ -198,29 +199,38 @@ function ctools_plugin_api_get_hook($owner, $api) {
/**
* Fetch a group of plugins by name.
*
* @param $module
* The name of the module that utilizes this plugin system. It will be
* used to call hook_ctools_plugin_$plugin() to get more data about the plugin.
* @param $type
* @param string $module
* The name of the module that utilizes this plugin system. It will be used to
* get more data about the plugin as defined on hook_ctools_plugin_type().
* @param string $type
* The type identifier of the plugin.
* @param $id
* @param string $id
* If specified, return only information about plugin with this identifier.
* The system will do its utmost to load only plugins with this id.
*
* @return
* An array of information arrays about the plugins received. The contents
* of the array are specific to the plugin.
* @return array
* An array of information arrays about the plugins received. The contents of
* the array are specific to the plugin.
*/
function ctools_get_plugins($module, $type, $id = NULL) {
// Store local caches of plugins and plugin info so we don't have to do full
// lookups everytime.
$plugins = &drupal_static('ctools_plugins', array());
// lookups every time.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array());
}
$plugins = &$drupal_static_fast['plugins'];
$info = ctools_plugin_get_plugin_type_info();
// Bail out noisily if an invalid module/type combination is requested.
if (!isset($info[$module][$type])) {
watchdog('ctools', 'Invalid plugin module/type combination requested: module @module and type @type', array('@module' => $module, '@type' => $type), WATCHDOG_ERROR);
return array();
// If we don't find the plugin we attempt a cache rebuild before bailing out.
$info = ctools_plugin_get_plugin_type_info(TRUE);
// Bail out noisily if an invalid module/type combination is requested.
if (!isset($info[$module][$type])) {
watchdog('ctools', 'Invalid plugin module/type combination requested: module @module and type @type', array('@module' => $module, '@type' => $type), WATCHDOG_ERROR);
return array();
}
}
// Make sure our plugins array is populated.
@@ -228,8 +238,8 @@ function ctools_get_plugins($module, $type, $id = NULL) {
$plugins[$module][$type] = array();
}
// Attempt to shortcut this whole piece of code if we already have
// the requested plugin:
// Attempt to shortcut this whole piece of code if we already have the
// requested plugin:
if ($id && array_key_exists($id, $plugins[$module][$type])) {
return $plugins[$module][$type][$id];
}
@@ -247,9 +257,9 @@ function ctools_get_plugins($module, $type, $id = NULL) {
if (!empty($cache->data)) {
// Cache load succeeded so use the cached plugin list.
$plugins[$module][$type] = $cache->data;
$plugins[$module][$type] = $cache->data;
// Set $setup to true so we know things where loaded.
$setup[$module][$type] = TRUE;
$setup[$module][$type] = TRUE;
}
else {
// Cache load failed so store that we need to build and write the cache.
@@ -264,8 +274,8 @@ function ctools_get_plugins($module, $type, $id = NULL) {
$plugins[$module][$type] = ctools_plugin_load_hooks($info[$module][$type]);
}
// Then see if we should load all files. We only do this if we
// want a list of all plugins or there was a cache miss.
// Then see if we should load all files. We only do this if we want a list of
// all plugins or there was a cache miss.
if (empty($setup[$module][$type]) && ($build_cache || !$id)) {
$setup[$module][$type] = TRUE;
$plugins[$module][$type] = array_merge($plugins[$module][$type], ctools_plugin_load_includes($info[$module][$type]));
@@ -288,9 +298,8 @@ function ctools_get_plugins($module, $type, $id = NULL) {
}
}
// If we were told earlier that this is cacheable and the cache was
// empty, give something back.
// If we were told earlier that this is cacheable and the cache was empty,
// give something back.
if ($build_cache) {
cache_set("plugins:$module:$type", $plugins[$module][$type], $info[$module][$type]['cache table']);
}
@@ -302,7 +311,7 @@ function ctools_get_plugins($module, $type, $id = NULL) {
return array_filter($plugins[$module][$type]);
}
// Check to see if we need to look for the file
// Check to see if we need to look for the file.
if (!array_key_exists($id, $plugins[$module][$type])) {
// If we can have child plugins, check to see if the plugin name is in the
// format of parent:child and break it up if it is.
@@ -343,8 +352,13 @@ function ctools_get_plugins($module, $type, $id = NULL) {
* name and each inner array keyed on plugin type name.
*/
function ctools_plugin_get_plugin_type_info($flush = FALSE) {
$info_loaded = &drupal_static('ctools_plugin_type_info_loaded', FALSE);
$all_type_info = &drupal_static('ctools_plugin_type_info', array());
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['info_loaded'] = &drupal_static('ctools_plugin_type_info_loaded', FALSE);
$drupal_static_fast['all_type_info'] = &drupal_static('ctools_plugin_type_info', array());
}
$info_loaded = &$drupal_static_fast['info_loaded'];
$all_type_info = &$drupal_static_fast['all_type_info'];
// Only trigger info loading once.
if ($info_loaded && !$flush) {
@@ -403,40 +417,31 @@ function ctools_get_plugins_reset() {
/**
* Load plugins from a directory.
*
* @param $info
* @param array $info
* The plugin info as returned by ctools_plugin_get_info()
* @param $file
* @param string $filename
* The file to load if we're looking for just one particular plugin.
*
* @return
* An array of information created for this plugin.
* @return array
* A (possibly empty) array of information created for this plugin.
*/
function ctools_plugin_load_includes($info, $filename = NULL) {
// Keep a static array so we don't hit file_scan_directory more than necessary.
$all_files = &drupal_static(__FUNCTION__, array());
// store static of plugin arrays for reference because they can't be reincluded.
// Store static of plugin arrays for reference because they can't be
// reincluded, so there is no point in using drupal_static().
static $plugin_arrays = array();
// If we're being asked for all plugins of a type, skip any caching
// we may have done because this is an admin task and it's ok to
// spend the extra time.
if (!isset($filename)) {
$all_files[$info['module']][$info['type']] = NULL;
}
if (!isset($all_files[$info['module']][$info['type']])) {
// If a filename was set, we will try to load our list of files from
// cache. This is considered normal operation and we try to reduce
// the time spent finding files.
if (isset($filename)) {
$cache = cache_get("ctools_plugin_files:$info[module]:$info[type]");
if ($cache) {
$all_files[$info['module']][$info['type']] = $cache->data;
}
$cache = cache_get("ctools_plugin_files:$info[module]:$info[type]");
if ($cache) {
$all_files[$info['module']][$info['type']] = $cache->data;
}
if (!isset($all_files[$info['module']][$info['type']])) {
// Do not attempt any file scan even if the cached entry was empty.
// A NULL entry here would mean the plugin just does not exists, and we
// cannot afford to run file scan on production sites normal run.
elseif (!isset($all_files[$info['module']][$info['type']])) {
$all_files[$info['module']][$info['type']] = array();
// Load all our plugins.
$directories = ctools_plugin_get_directories($info);
@@ -460,24 +465,23 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
}
foreach ($files as $file) {
if (!empty($info['info file'])) {
// Parse a .info file
// Parse a .info file.
$result = ctools_plugin_process_info($info, $module, $file);
}
else {
// Parse a hook.
$plugin = NULL; // ensure that we don't have something leftover from earlier.
// Ensure that we don't have something leftover from earlier.
$plugin = NULL;
if (isset($plugin_arrays[$file->uri])) {
$identifier = $plugin_arrays[$file->uri];
}
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)
// mogul_foo_borg_type()
// whose hook is named 'borg_type' should have a function named
// (deep breath) mogul_foo_borg_type().
// If, however, the .inc file set the quasi-global $plugin array, we
// can use that and not even call a function. Set the $identifier
// appropriately and ctools_plugin_process() will handle it.
@@ -490,7 +494,8 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
}
}
$result = ctools_plugin_process($info, $module, $identifier, dirname($file->uri), basename($file->uri), $file->name);
$result = ctools_plugin_process($info, $module, $identifier,
dirname($file->uri), basename($file->uri), $file->name);
}
if (is_array($result)) {
$plugins = array_merge($plugins, $result);
@@ -510,7 +515,7 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
* @param $info
* The $info array for the plugin as returned by ctools_plugin_get_info().
*
* @return array $directories
* @return array
* An array of directories to search.
*/
function ctools_plugin_get_directories($info) {
@@ -536,10 +541,9 @@ function ctools_plugin_get_directories($info) {
}
/**
* Helper function to build a ctools-friendly list of themes capable of
* providing plugins.
* Helper to build a ctools-friendly list of themes capable of providing plugins.
*
* @return array $themes
* @return array
* A list of themes that can act as plugin providers, sorted parent-first with
* the active theme placed last.
*/
@@ -550,7 +554,7 @@ function _ctools_list_themes() {
$themes = $active = array();
$all_themes = list_themes();
foreach ($all_themes as $name => $theme) {
// Only search from active themes
// Only search from active themes.
if (empty($theme->status) && $theme->name != $current) {
continue;
}
@@ -561,19 +565,19 @@ function _ctools_list_themes() {
}
}
// Construct a parent-first list of all themes
// Construct a parent-first list of all themes.
foreach ($active as $name => $theme) {
$base_themes = isset($theme->base_themes) ? $theme->base_themes : array();
$themes = array_merge($themes, $base_themes, array($name => $theme->info['name']));
}
// Put the actual theme info objects into the array
// Put the actual theme info objects into the array.
foreach (array_keys($themes) as $name) {
if (isset($all_themes[$name])) {
$themes[$name] = $all_themes[$name];
}
}
// Make sure the current default theme always gets the last word
// Make sure the current default theme always gets the last word.
if ($current_key = array_search($current, array_keys($themes))) {
$themes += array_splice($themes, $current_key, 1);
}
@@ -581,7 +585,6 @@ function _ctools_list_themes() {
return $themes;
}
/**
* Find all the base themes for the specified theme.
*
@@ -597,9 +600,10 @@ function _ctools_list_themes() {
* The name of the theme whose base we are looking for.
* @param $used_keys
* A recursion parameter preventing endless loops.
* @return
*
* @return array
* Returns an array of all of the theme's ancestors; the first element's value
* will be NULL if an error occurred.
* will be NULL if an error occurred. (Note: this is NOT $arr[0]).
*/
function ctools_find_base_themes($themes, $key, $used_keys = array()) {
$base_key = $themes[$key]->info['base theme'];
@@ -627,7 +631,6 @@ function ctools_find_base_themes($themes, $key, $used_keys = array()) {
return $current_base_theme;
}
/**
* Load plugin info for the provided hook; this is handled separately from
* plugins from files.
@@ -652,22 +655,28 @@ function ctools_plugin_load_hooks($info) {
/**
* Process a single hook implementation of a ctools plugin.
*
* @param $info
* @param array $info
* The $info array about the plugin as returned by ctools_plugin_get_info()
* @param $module
* @param string $module
* The module that implements the plugin being processed.
* @param $identifier
* The plugin identifier, which is used to create the name of the hook
* function being called.
* @param $path
* @param string|array $identifier
* Used to create the base setting of return value. If:
* - $identifier is a string, a hook name is created from this and the 'hook'
* key of the $info array, and the return value of that hook function is
* used. The hook is called like this: $identifier_$hook($info);
* - $identifier is an array, this array is used directly.
* @param string $path
* The path where files utilized by this plugin will be found.
* @param $file
* @param string $file
* The file that was loaded for this plugin, if it exists.
* @param $base
* @param string $base
* The base plugin name to use. If a file was loaded for the plugin, this
* is the plugin to assume must be present. This is used to automatically
* translate the array to make the syntax more friendly to plugin
* implementors.
*
* @return null|array
* NULL on failure, otherwise an array containing the results keyed by name.
*/
function ctools_plugin_process($info, $module, $identifier, $path, $file = NULL, $base = NULL) {
if (is_array($identifier)) {
@@ -678,7 +687,7 @@ function ctools_plugin_process($info, $module, $identifier, $path, $file = NULL,
if (!function_exists($function)) {
return NULL;
}
$result = $function();
$result = $function($info);
if (!isset($result) || !is_array($result)) {
return NULL;
}
@@ -735,9 +744,19 @@ function _ctools_process_data($result, $plugin_type_info, $module, $path, $file)
return $result;
}
/**
* Process an info file for plugin information, rather than a hook.
*
* @param array $info
* The $info array about the plugin as returned by ctools_plugin_get_info()
* @param string $module
* The module that implements the plugin being processed.
* @param object $file
* An object containing 'uri' and 'name' properties. 'uri' is the name of the
* 'info' file to process. 'name' is the plugin key-name.
*
* @return null|array
* NULL on failure, otherwise an array containing the results keyed by name.
*/
function ctools_plugin_process_info($info, $module, $file) {
$result = drupal_parse_info_file($file->uri);
@@ -764,7 +783,7 @@ function ctools_plugin_get_info($module, $type) {
* @param $function_name
* The identifier of the function. For example, 'settings form'.
*
* @return
* @return string
* The actual name of the function to call, or NULL if the function
* does not exist.
*/
@@ -781,7 +800,7 @@ function ctools_plugin_get_function($plugin_definition, $function_name) {
}
if (!isset($plugin_definition[$function_name])) {
return;
return NULL;
}
if (is_array($plugin_definition[$function_name]) && isset($plugin_definition[$function_name]['function'])) {
@@ -816,7 +835,7 @@ function ctools_plugin_get_function($plugin_definition, $function_name) {
* @param $function_name
* The identifier of the function. For example, 'settings form'.
*
* @return
* @return string
* The actual name of the function to call, or NULL if the function
* does not exist.
*/
@@ -834,7 +853,7 @@ function ctools_plugin_load_function($module, $type, $id, $function_name) {
* @param $class_name
* The identifier of the class. For example, 'handler'.
*
* @return
* @return string
* The actual name of the class to call, or NULL if the class does not exist.
*/
function ctools_plugin_get_class($plugin_definition, $class_name) {
@@ -853,11 +872,11 @@ function ctools_plugin_get_class($plugin_definition, $class_name) {
if (!isset($plugin_definition[$class_name])) {
return;
}
else if (is_string($plugin_definition[$class_name])) {
elseif (is_string($plugin_definition[$class_name])) {
// Plugin uses the string form shorthand.
$return = $plugin_definition[$class_name];
}
else if (isset($plugin_definition[$class_name]['class'])) {
elseif (isset($plugin_definition[$class_name]['class'])) {
// Plugin uses the verbose array form.
$return = $plugin_definition[$class_name]['class'];
}
@@ -879,7 +898,7 @@ function ctools_plugin_get_class($plugin_definition, $class_name) {
* @param $class_name
* The identifier of the class. For example, 'handler'.
*
* @return
* @return string
* The actual name of the class to call, or NULL if the class does not exist.
*/
function ctools_plugin_load_class($module, $type, $id, $class_name) {
@@ -2,7 +2,6 @@
/**
* @file
*
* Registry magic. In a separate file to minimize unnecessary code loading.
*/
@@ -202,7 +202,7 @@ function ctools_stylizer_get_settings_name($settings) {
}
/**
* Get the path where images will be stored for a given style plugin and settings.
* Get the path where images will be stored for a style plugin and settings.
*
* This function will make sure the path exists.
*/
@@ -249,7 +249,7 @@ class ctools_stylizer_image_processor {
if (is_string($plugin['actions']) && function_exists($plugin['actions'])) {
$actions = $plugin['actions']($plugin, $settings);
}
else if (is_array($plugin['actions'])) {
elseif (is_array($plugin['actions'])) {
$actions = $plugin['actions'];
}
@@ -318,7 +318,7 @@ class ctools_stylizer_image_processor {
function command_load($name, $file) {
$this->log("New workspace: $name (from $file)");
if (!file_exists($file)) {
// Try it relative to the plugin
// Try it relative to the plugin.
$file = $this->plugin['path'] . '/' . $file;
if (!file_exists($file)) {
$this->log("Unable to open $file");
@@ -336,7 +336,7 @@ class ctools_stylizer_image_processor {
}
/**
* Create a new workspace using the properties of an existing workspace
* Create a new workspace using the properties of an existing workspace.
*/
function command_new_from($name, $workspace) {
$this->log("New workspace: $name from existing $workspace");
@@ -372,7 +372,7 @@ class ctools_stylizer_image_processor {
function command_merge_from($workspace, $x = 0, $y = 0) {
$this->log("Merge from: $workspace ($x, $y)");
if (empty($this->workspaces[$workspace])) {
$this->log("Workspace $name does not exist.", 'error');
$this->log("Workspace $workspace does not exist.", 'error');
return;
}
@@ -382,7 +382,7 @@ class ctools_stylizer_image_processor {
function command_merge_to($workspace, $x = 0, $y = 0) {
$this->log("Merge to: $workspace ($x, $y)");
if (empty($this->workspaces[$workspace])) {
$this->log("Workspace $name does not exist.", 'error');
$this->log("Workspace $workspace does not exist.", 'error');
return;
}
@@ -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
@@ -822,7 +822,7 @@ function ctools_stylizer_add_plugin_forms(&$form_info, $plugin, $op) {
if ($op == 'add' && isset($plugin['add form'])) {
$id = $plugin['add form'];
}
else if (isset($plugin['edit form'])) {
elseif (isset($plugin['edit form'])) {
$id = $plugin['edit form'];
}
else {
@@ -25,4 +25,3 @@ function ctools_stylizer_theme(&$theme) {
'file' => 'includes/stylizer.inc',
);
}
@@ -23,22 +23,9 @@ function ctools_passthrough($module, $type, &$items) {
require_once DRUPAL_ROOT . '/' . $file->uri;
list($tool) = explode('.', $file->name, 2);
$function = $module . '_' . str_replace ('-', '_', $tool) . '_' . str_replace('-', '_', $type);
$function = $module . '_' . str_replace('-', '_', $tool) . '_' . str_replace('-', '_', $type);
if (function_exists($function)) {
$function($items);
}
}
}
/**
* Implementation of hook_theme_registry_alter()
*/
function ctools_theme_registry_alter(&$registry) {
// Move this one last last last so it can catch changes made by modules and themes.
$key = array_search('ctools_preprocess_page', $registry['page']['preprocess functions']);
if ($key) {
unset($registry['page']['preprocess functions'][$key]);
}
$registry['page']['preprocess functions'][] = 'ctools_preprocess_page';
}
@@ -0,0 +1,71 @@
<?php
/**
* @file
* Enables ctools generated modules to use UUIDs without the UUID module enabled.
* Per the ctools.module, this file only gets included if UUID doesn't exist.
*/
/**
* Pattern for detecting a valid UUID.
*/
if (!defined('UUID_PATTERN')) {
define('UUID_PATTERN', '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}');
}
/**
* Generates a UUID using the Windows internal GUID generator.
*
* @see http://php.net/com_create_guid
*/
function _ctools_uuid_generate_com() {
// Remove {} wrapper and make lower case to keep result consistent.
return drupal_strtolower(trim(com_create_guid(), '{}'));
}
/**
* Generates an universally unique identifier using the PECL extension.
*/
function _ctools_uuid_generate_pecl() {
$uuid_type = UUID_TYPE_DEFAULT;
return uuid_create($uuid_type);
}
/**
* Generates a UUID v4 using PHP code.
*
* Based on code from @see http://php.net/uniqid#65879 , but corrected.
*/
function _ctools_uuid_generate_php() {
// The field names refer to RFC 4122 section 4.1.2.
return sprintf('%04x%04x-%04x-4%03x-%04x-%04x%04x%04x',
// 32 bits for "time_low".
mt_rand(0, 65535), mt_rand(0, 65535),
// 16 bits for "time_mid".
mt_rand(0, 65535),
// 12 bits after the 0100 of (version) 4 for "time_hi_and_version".
mt_rand(0, 4095),
bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '10', 0, 2)),
// 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
// (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
// 8 bits for "clk_seq_low" 48 bits for "node".
mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535)
);
}
// This is wrapped in an if block to avoid conflicts with PECL's uuid_is_valid().
/**
* Check that a string appears to be in the format of a UUID.
*
* @param $uuid
* The string to test.
*
* @return
* TRUE if the string is well formed.
*/
if (!function_exists('uuid_is_valid')) {
function uuid_is_valid($uuid) {
return preg_match('/^' . UUID_PATTERN . '$/', $uuid);
}
}
@@ -1,5 +1,9 @@
<?php
/**
* @file
*/
/**
* Generate new context classes by argument settings on the view.
*/
@@ -47,7 +47,7 @@ function ctools_wizard_multistep_form($form_info, $step, &$form_state) {
// with form caching.
ctools_form_include($form_state, 'wizard');
// allow order array to be optional
// Allow order array to be optional.
if (empty($form_info['order'])) {
foreach ($form_info['forms'] as $step_id => $params) {
$form_info['order'][$step_id] = $params['title'];
@@ -83,7 +83,7 @@ function ctools_wizard_multistep_form($form_info, $step, &$form_state) {
$form_info['cache location'] = 'storage';
}
// If absolutely nothing was set for the cache area to work on
// If absolutely nothing was set for the cache area to work on.
if (!isset($form_state[$form_info['cache location']])) {
ctools_include('cache');
$form_state[$form_info['cache location']] = ctools_cache_get($form_info['cache mechanism'], $form_info['cache key']);
@@ -199,7 +199,7 @@ function ctools_wizard_multistep_form($form_info, $step, &$form_state) {
}
}
}
else if (isset($form_state['ajax next'])) {
elseif (isset($form_state['ajax next'])) {
// Clear a few items off the form state so we don't double post:
$next = $form_state['ajax next'];
unset($form_state['ajax next']);
@@ -274,7 +274,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
if (!empty($form_info['show trail'])) {
ctools_add_css('wizard');
$form['ctools_trail'] = array(
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail)),
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail, 'form_info' => $form_info)),
'#weight' => -1000,
);
}
@@ -299,7 +299,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
'#wizard type' => 'next',
'#weight' => -2000,
'#limit_validation_errors' => array(),
// hardcode the submit so that it doesn't try to save data.
// Hardcode the submit so that it doesn't try to save data.
'#submit' => array('ctools_wizard_submit'),
'#attributes' => $button_attributes,
);
@@ -325,19 +325,18 @@ function ctools_wizard_wrapper($form, &$form_state) {
// end of the form list (i.e, there is a next) then it's "update and return"
// to be clear. If this is the end of the path and there is no next, we
// call it 'Finish'.
// Even if there is no direct return path (some forms may not want you
// leaving in the middle) the final button is always a Finish and it does
// whatever the return action is.
if (!empty($form_info['show return']) && !empty($form_state['next'])) {
$form['buttons']['return'] = array(
'#type' => 'submit',
'#value' => $form_info['return text'],
'#value' => $form_info['return text'],
'#wizard type' => 'return',
'#attributes' => $button_attributes,
);
}
else if (empty($form_state['next']) || !empty($form_info['free trail'])) {
elseif (empty($form_state['next']) || !empty($form_info['free trail'])) {
$form['buttons']['return'] = array(
'#type' => 'submit',
'#value' => $form_info['finish text'],
@@ -352,7 +351,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
'#type' => 'submit',
'#value' => $form_info['cancel text'],
'#wizard type' => 'cancel',
// hardcode the submit so that it doesn't try to save data.
// Hardcode the submit so that it doesn't try to save data.
'#limit_validation_errors' => array(),
'#submit' => array('ctools_wizard_submit'),
'#attributes' => $button_attributes,
@@ -370,7 +369,6 @@ function ctools_wizard_wrapper($form, &$form_state) {
// Set up our submit handler after theirs. Since putting something here will
// skip Drupal's autodetect, we autodetect for it.
// We make sure ours is after theirs so that they get to change #next if
// the want to.
$form['#submit'] = array();
@@ -398,7 +396,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
$params = array($url, $options);
}
$form['#action'] = call_user_func_array('url', $params);
$form['#action'] = call_user_func_array('url', $params);
}
if (isset($info['wrapper']) && function_exists($info['wrapper'])) {
@@ -418,7 +416,7 @@ function ctools_wizard_submit(&$form, &$form_state) {
if (isset($form_state['clicked_button']['#wizard type'])) {
$type = $form_state['clicked_button']['#wizard type'];
// if AJAX enabled, we proceed slightly differently here.
// If AJAX enabled, we proceed slightly differently here.
if (!empty($form_state['ajax'])) {
if ($type == 'next') {
$form_state['ajax next'] = $form_state['clicked_button']['#next'];
@@ -428,7 +426,7 @@ function ctools_wizard_submit(&$form, &$form_state) {
if ($type == 'cancel' && isset($form_state['form_info']['cancel path'])) {
$form_state['redirect'] = $form_state['form_info']['cancel path'];
}
else if ($type == 'next') {
elseif ($type == 'next') {
$form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']);
if (!empty($_GET['destination'])) {
// We don't want drupal_goto redirect this request
@@ -437,10 +435,10 @@ function ctools_wizard_submit(&$form, &$form_state) {
unset($_GET['destination']);
}
}
else if (isset($form_state['form_info']['return path'])) {
elseif (isset($form_state['form_info']['return path'])) {
$form_state['redirect'] = $form_state['form_info']['return path'];
}
else if ($type == 'finish' && isset($form_state['form_info']['cancel path'])) {
elseif ($type == 'finish' && isset($form_state['form_info']['cancel path'])) {
$form_state['redirect'] = $form_state['form_info']['cancel path'];
}
}
@@ -469,10 +467,8 @@ function ctools_wizard_get_path($form_info, $step) {
if (!isset($path[1]) || !is_array($path[1])) {
$path[1] = array();
}
// Ensure that the query part of options is an array.
$path[1] += array('query' => array());
// Add the destination parameter, if not set already.
$path[1]['query'] += drupal_get_destination();
$path[1] += drupal_get_destination();
}
return $path;
@@ -505,15 +501,15 @@ function ctools_wizard_defaults(&$form_info) {
}
$form_info = $form_info + $defaults;
// set form callbacks if they aren't defined
// Set form callbacks if they aren't defined.
foreach ($form_info['forms'] as $step => $params) {
if (!$params['form id']) {
$form_callback = $hook . '_' . $step . '_form';
$form_info['forms'][$step]['form id'] = $form_callback;
if (empty($params['form id'])) {
$form_callback = $hook . '_' . $step . '_form';
$form_info['forms'][$step]['form id'] = $form_callback;
}
}
// set button callbacks
// Set button callbacks.
$callbacks = array(
'back callback' => '_back',
'next callback' => '_next',
@@ -523,10 +519,10 @@ function ctools_wizard_defaults(&$form_info) {
);
foreach ($callbacks as $key => $callback) {
// never overwrite if explicity defined
// Never overwrite if explicity defined.
if (empty($form_info[$key])) {
$wizard_callback = $hook . $callback;
if (function_exists($wizard_callback)) {
if (function_exists($wizard_callback)) {
$form_info[$key] = $wizard_callback;
}
}
@@ -7,19 +7,16 @@
function ctools_wizard_theme(&$theme) {
$theme['ctools_wizard_trail'] = array(
'variables' => array('trail' => NULL),
'variables' => array('trail' => NULL, 'form_info' => NULL, 'divider' => ' » '),
'file' => 'includes/wizard.theme.inc',
);
}
/**
* Themable display of the 'breadcrumb' trail to show the order of the
* forms.
* Themable display of the 'breadcrumb' trail to show the order of the forms.
*/
function theme_ctools_wizard_trail($vars) {
$trail = $vars['trail'];
if (!empty($trail)) {
return '<div class="wizard-trail">' . implode(' » ', $trail) . '</div>';
if (!empty($vars['trail'])) {
return '<div class="wizard-trail">' . implode($vars['divider'], $vars['trail']) . '</div>';
}
}