security update core+modules
This commit is contained in:
@ -49,6 +49,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.
|
||||
*
|
||||
|
@ -244,6 +244,7 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) {
|
||||
* The content as rendered by the plugin. This content should be an array
|
||||
* with the following possible keys:
|
||||
* - title: The safe to render title of the content.
|
||||
* - title_heading: The title heading.
|
||||
* - content: The safe to render HTML content.
|
||||
* - links: An array of links associated with the content suitable for
|
||||
* theme('links').
|
||||
@ -299,6 +300,7 @@ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $arg
|
||||
$keywords['%title'] = empty($content->title) ? '' : $content->title;
|
||||
$content->original_title = $keywords['%title'];
|
||||
$content->title = $conf['override_title_text'];
|
||||
$content->title_heading = isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2';
|
||||
}
|
||||
|
||||
if (!empty($content->title)) {
|
||||
@ -504,8 +506,26 @@ function ctools_content_configure_form_defaults($form, &$form_state) {
|
||||
'#size' => 35,
|
||||
'#id' => 'override-title-textfield',
|
||||
'#dependency' => array('override-title-checkbox' => array(1)),
|
||||
'#dependency_type' => 'disable',
|
||||
'#dependency_type' => 'hidden',
|
||||
);
|
||||
$form['override_title_heading'] = array(
|
||||
'#type' => 'select',
|
||||
'#default_value' => isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2',
|
||||
'#options' => array(
|
||||
'h1' => t('h1'),
|
||||
'h2' => t('h2'),
|
||||
'h3' => t('h3'),
|
||||
'h4' => t('h4'),
|
||||
'h5' => t('h5'),
|
||||
'h6' => t('h6'),
|
||||
'div' => t('div'),
|
||||
'span' => t('span'),
|
||||
),
|
||||
'#id' => 'override-title-heading',
|
||||
'#dependency' => array('override-title-checkbox' => array(1)),
|
||||
'#dependency_type' => 'hidden',
|
||||
);
|
||||
|
||||
$form['aligner_stop'] = array(
|
||||
'#markup' => '</div>',
|
||||
);
|
||||
@ -536,6 +556,7 @@ function ctools_content_configure_form_defaults_submit(&$form, &$form_state) {
|
||||
if (isset($form_state['values']['override_title'])) {
|
||||
$form_state['conf']['override_title'] = $form_state['values']['override_title'];
|
||||
$form_state['conf']['override_title_text'] = $form_state['values']['override_title_text'];
|
||||
$form_state['conf']['override_title_heading'] = $form_state['values']['override_title_heading'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -687,6 +708,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;
|
||||
}
|
||||
|
@ -23,53 +23,157 @@ 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') {
|
||||
$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 well known/tested entity reference code to build our search query
|
||||
* From EntityReference_SelectionHandler_Generic class
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ function ctools_content_plugin_type(&$items) {
|
||||
'cache' => FALSE,
|
||||
'process' => array(
|
||||
'function' => 'ctools_content_process',
|
||||
'file' => 'export-ui.inc',
|
||||
'file' => 'content.inc',
|
||||
'path' => drupal_get_path('module', 'ctools') . '/includes',
|
||||
),
|
||||
);
|
||||
|
@ -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') {
|
||||
@ -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') {
|
||||
@ -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,
|
||||
);
|
||||
|
@ -143,6 +143,10 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte
|
||||
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:
|
||||
@ -157,7 +161,7 @@ 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']);
|
||||
drupal_goto($info['destination'], $options, $info['response code']);
|
||||
// @todo -- should other response codes be supported here?
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,12 @@ class ctools_context_required {
|
||||
|
||||
function select($contexts, $context) {
|
||||
if (!is_array($contexts)) {
|
||||
$contexts = array($contexts);
|
||||
if (is_object($contexts) && $contexts instanceof ctools_context) {
|
||||
$contexts = array($contexts->id => $contexts);
|
||||
}
|
||||
else {
|
||||
$contexts = array($contexts);
|
||||
}
|
||||
}
|
||||
|
||||
// If we had requested a $context but that $context doesn't exist
|
||||
@ -328,13 +333,15 @@ function _ctools_context_selector($contexts, $required, $default, $num = 0) {
|
||||
$title = $num ? t('Context %count', array('%count' => $num)) : t('Context');
|
||||
}
|
||||
|
||||
return array(
|
||||
$form = array(
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
'#title' => $title,
|
||||
'#default_value' => $default,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1400,8 +1407,7 @@ function ctools_get_relevant_access_plugins($contexts) {
|
||||
* Create a context for the logged in user.
|
||||
*/
|
||||
function ctools_access_get_loggedin_context() {
|
||||
global $user;
|
||||
$context = ctools_context_create('entity:user', $user);
|
||||
$context = ctools_context_create('entity:user', array('type' => 'current'), TRUE);
|
||||
$context->identifier = t('Logged in user');
|
||||
$context->keyword = 'viewer';
|
||||
$context->id = 0;
|
||||
@ -1588,7 +1594,9 @@ function ctools_access_add_restrictions($settings, $contexts) {
|
||||
$required_context = isset($plugin['required context']) ? $plugin['required context'] : array();
|
||||
$context = isset($test['context']) ? $test['context'] : array();
|
||||
$contexts = ctools_context_select($contexts, $required_context, $context);
|
||||
$function($test['settings'], $contexts);
|
||||
if ($contexts !== FALSE) {
|
||||
$function($test['settings'], $contexts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
52
sites/all/modules/ctools/includes/css-cache.inc
Normal file
52
sites/all/modules/ctools/includes/css-cache.inc
Normal file
@ -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) {
|
||||
}
|
||||
|
||||
}
|
@ -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),
|
||||
|
@ -4,6 +4,8 @@
|
||||
* @file
|
||||
* Provide a javascript based dropbutton menu.
|
||||
*
|
||||
* An example are the edit/disable/delete links on the views listing page.
|
||||
*
|
||||
* The dropbutton menu will show up as a button with a clickable twisty pointer
|
||||
* to the right. When clicked the button will expand, showing the list of links.
|
||||
*
|
||||
|
@ -4,6 +4,9 @@
|
||||
* @file
|
||||
* Provide a javascript based dropdown menu.
|
||||
*
|
||||
* An example are the dropdown settings in the panels ui, like for adding
|
||||
* new panes.
|
||||
*
|
||||
* The dropdown menu will show up as a clickable link; when clicked,
|
||||
* a small menu will slide down beneath it, showing the list of links.
|
||||
*
|
||||
|
150
sites/all/modules/ctools/includes/entity-access.inc
Normal file
150
sites/all/modules/ctools/includes/entity-access.inc
Normal file
@ -0,0 +1,150 @@
|
||||
<?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 boolean
|
||||
* 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;
|
||||
}
|
@ -945,7 +945,13 @@ 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";
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
@ -79,6 +79,19 @@ function ctools_fields_get_field_formatter_settings_form($field, $formatter_type
|
||||
$instance = ctools_fields_fake_field_instance($field['field_name'], $view_mode, $formatter_type, $conf['formatter_settings']);
|
||||
$settings_form = $function($field, $instance, $view_mode, $form, $form_state);
|
||||
if ($settings_form) {
|
||||
// Allow other modules to alter the formatter settings form.
|
||||
$context = array(
|
||||
'module' => $formatter['module'],
|
||||
'formatter' => $formatter,
|
||||
'field' => $field,
|
||||
'instance' => $instance,
|
||||
'view_mode' => $view_mode,
|
||||
'form' => $form,
|
||||
'form_state' => $form_state,
|
||||
);
|
||||
drupal_alter('field_formatter_settings_form', $settings_form, $context);
|
||||
|
||||
$settings_form['#tree'] = TRUE;
|
||||
$form['ctools_field_list']['#value'][] = $field;
|
||||
$form += $settings_form;
|
||||
}
|
||||
|
@ -187,18 +187,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.
|
||||
|
||||
* @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
|
||||
* @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,7 +220,7 @@ function ctools_modal_form_wrapper($form_id, &$form_state) {
|
||||
);
|
||||
|
||||
$output = drupal_build_form($form_id, $form_state);
|
||||
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
|
||||
if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
|
||||
return ctools_modal_form_render($form_state, $output);
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,12 @@ function ctools_plugin_api_get_hook($owner, $api) {
|
||||
function ctools_get_plugins($module, $type, $id = NULL) {
|
||||
// Store local caches of plugins and plugin info so we don't have to do full
|
||||
// lookups everytime.
|
||||
$plugins = &drupal_static('ctools_plugins', array());
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast)) {
|
||||
$drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array());
|
||||
}
|
||||
$plugins = &$drupal_static_fast['plugins'];
|
||||
|
||||
$info = ctools_plugin_get_plugin_type_info();
|
||||
|
||||
// Bail out noisily if an invalid module/type combination is requested.
|
||||
@ -343,8 +348,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) {
|
||||
@ -418,29 +428,19 @@ function ctools_plugin_load_includes($info, $filename = NULL) {
|
||||
// store static of plugin arrays for reference because they can't be reincluded.
|
||||
static $plugin_arrays = array();
|
||||
|
||||
// If we're being asked for all plugins of a type, skip any caching
|
||||
// we may have done because this is an admin task and it's ok to
|
||||
// spend the extra time.
|
||||
if (!isset($filename)) {
|
||||
$all_files[$info['module']][$info['type']] = NULL;
|
||||
}
|
||||
|
||||
if (!isset($all_files[$info['module']][$info['type']])) {
|
||||
// If a filename was set, we will try to load our list of files from
|
||||
// cache. This is considered normal operation and we try to reduce
|
||||
// the time spent finding files.
|
||||
if (isset($filename)) {
|
||||
$cache = cache_get("ctools_plugin_files:$info[module]:$info[type]");
|
||||
if ($cache) {
|
||||
$all_files[$info['module']][$info['type']] = $cache->data;
|
||||
}
|
||||
$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);
|
||||
$extension = empty($info['info file']) ? $info['extension'] : 'info';
|
||||
$extension = (empty($info['info file']) || ($info['extension'] != 'inc')) ? $info['extension'] : 'info';
|
||||
|
||||
foreach ($directories as $module => $path) {
|
||||
$all_files[$info['module']][$info['type']][$module] = file_scan_directory($path, '/\.' . $extension . '$/', array('key' => 'name'));
|
||||
@ -678,7 +678,7 @@ function ctools_plugin_process($info, $module, $identifier, $path, $file = NULL,
|
||||
if (!function_exists($function)) {
|
||||
return NULL;
|
||||
}
|
||||
$result = $function();
|
||||
$result = $function($info);
|
||||
if (!isset($result) || !is_array($result)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -29,16 +29,3 @@ function ctools_passthrough($module, $type, &$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';
|
||||
}
|
||||
|
||||
|
67
sites/all/modules/ctools/includes/uuid.inc
Normal file
67
sites/all/modules/ctools/includes/uuid.inc
Normal file
@ -0,0 +1,67 @@
|
||||
<?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.
|
||||
*/
|
||||
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() {
|
||||
return uuid_create(UUID_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -274,7 +274,7 @@ function ctools_wizard_wrapper($form, &$form_state) {
|
||||
if (!empty($form_info['show trail'])) {
|
||||
ctools_add_css('wizard');
|
||||
$form['ctools_trail'] = array(
|
||||
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail)),
|
||||
'#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail, 'form_info' => $form_info)),
|
||||
'#weight' => -1000,
|
||||
);
|
||||
}
|
||||
|
@ -7,19 +7,16 @@
|
||||
|
||||
function ctools_wizard_theme(&$theme) {
|
||||
$theme['ctools_wizard_trail'] = array(
|
||||
'variables' => array('trail' => NULL),
|
||||
'variables' => array('trail' => NULL, 'form_info' => NULL, 'divider' => ' » '),
|
||||
'file' => 'includes/wizard.theme.inc',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Themable display of the 'breadcrumb' trail to show the order of the
|
||||
* forms.
|
||||
* Themable display of the 'breadcrumb' trail to show the order of the forms.
|
||||
*/
|
||||
function theme_ctools_wizard_trail($vars) {
|
||||
$trail = $vars['trail'];
|
||||
if (!empty($trail)) {
|
||||
return '<div class="wizard-trail">' . implode(' » ', $trail) . '</div>';
|
||||
if (!empty($vars['trail'])) {
|
||||
return '<div class="wizard-trail">' . implode($vars['divider'], $vars['trail']) . '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user