first import
This commit is contained in:
5461
sites/all/modules/views/includes/admin.inc
Normal file
5461
sites/all/modules/views/includes/admin.inc
Normal file
File diff suppressed because it is too large
Load Diff
376
sites/all/modules/views/includes/ajax.inc
Normal file
376
sites/all/modules/views/includes/ajax.inc
Normal file
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handles the server side AJAX interactions of Views.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ajax Views AJAX library
|
||||
* @{
|
||||
* Handles the server side AJAX interactions of Views.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback to load a view via AJAX.
|
||||
*/
|
||||
function views_ajax() {
|
||||
if (isset($_REQUEST['view_name']) && isset($_REQUEST['view_display_id'])) {
|
||||
$name = $_REQUEST['view_name'];
|
||||
$display_id = $_REQUEST['view_display_id'];
|
||||
$args = isset($_REQUEST['view_args']) && $_REQUEST['view_args'] !== '' ? explode('/', $_REQUEST['view_args']) : array();
|
||||
$path = isset($_REQUEST['view_path']) ? rawurldecode($_REQUEST['view_path']) : NULL;
|
||||
$dom_id = isset($_REQUEST['view_dom_id']) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $_REQUEST['view_dom_id']) : NULL;
|
||||
$pager_element = isset($_REQUEST['pager_element']) ? intval($_REQUEST['pager_element']) : NULL;
|
||||
|
||||
$commands = array();
|
||||
|
||||
// Remove all of this stuff from $_GET so it doesn't end up in pagers and tablesort URLs.
|
||||
foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) {
|
||||
if (isset($_GET[$key])) {
|
||||
unset($_GET[$key]);
|
||||
}
|
||||
if (isset($_REQUEST[$key])) {
|
||||
unset($_REQUEST[$key]);
|
||||
}
|
||||
if (isset($_POST[$key])) {
|
||||
unset($_POST[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the view.
|
||||
$view = views_get_view($name);
|
||||
if ($view && $view->access($display_id)) {
|
||||
// Fix 'q' for paging.
|
||||
if (!empty($path)) {
|
||||
$_GET['q'] = $path;
|
||||
}
|
||||
|
||||
// Add all $_POST data, because AJAX is always a post and many things,
|
||||
// such as tablesorts, exposed filters and paging assume $_GET.
|
||||
$_GET = $_POST + $_GET;
|
||||
|
||||
// Overwrite the destination.
|
||||
// @see drupal_get_destination()
|
||||
$origin_destination = $path;
|
||||
$query = drupal_http_build_query($_REQUEST);
|
||||
if ($query != '') {
|
||||
$origin_destination .= '?' . $query;
|
||||
}
|
||||
$destination = &drupal_static('drupal_get_destination');
|
||||
$destination = array('destination' => $origin_destination);
|
||||
|
||||
// Override the display's pager_element with the one actually used.
|
||||
if (isset($pager_element)) {
|
||||
$commands[] = views_ajax_command_scroll_top('.view-dom-id-' . $dom_id);
|
||||
$view->display[$display_id]->handler->set_option('pager_element', $pager_element);
|
||||
}
|
||||
// Reuse the same DOM id so it matches that in Drupal.settings.
|
||||
$view->dom_id = $dom_id;
|
||||
|
||||
$commands[] = ajax_command_replace('.view-dom-id-' . $dom_id, $view->preview($display_id, $args));
|
||||
}
|
||||
drupal_alter('views_ajax_data', $commands, $view);
|
||||
return array('#type' => 'ajax', '#commands' => $commands);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal AJAX 'viewsSetForm' command.
|
||||
*
|
||||
* @param $output
|
||||
* The form to display in the modal.
|
||||
* @param $title
|
||||
* The title.
|
||||
* @param $url
|
||||
* An optional URL.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_set_form($output, $title, $url = NULL) {
|
||||
$command = array(
|
||||
'command' => 'viewsSetForm',
|
||||
'output' => $output,
|
||||
'title' => $title,
|
||||
);
|
||||
if (isset($url)) {
|
||||
$command['url'] = $url;
|
||||
}
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal AJAX 'viewsDismissForm' command.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_dismiss_form() {
|
||||
$command = array(
|
||||
'command' => 'viewsDismissForm',
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal AJAX 'viewsHilite' command.
|
||||
*
|
||||
* @param $selector
|
||||
* The selector to highlight
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_hilite($selector) {
|
||||
return array(
|
||||
'command' => 'viewsHilite',
|
||||
'selector' => $selector,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal AJAX 'addTab' command.
|
||||
*
|
||||
* @param $id
|
||||
* The DOM ID.
|
||||
* @param $title
|
||||
* The title.
|
||||
* @param $body
|
||||
* The body.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_add_tab($id, $title, $body) {
|
||||
$command = array(
|
||||
'command' => 'viewsAddTab',
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to top of the current view.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_scroll_top($selector) {
|
||||
$command = array(
|
||||
'command' => 'viewsScrollTop',
|
||||
'selector' => $selector,
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows Save and Cancel buttons.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_show_buttons() {
|
||||
$command = array(
|
||||
'command' => 'viewsShowButtons',
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the Views live preview.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_trigger_preview() {
|
||||
$command = array(
|
||||
'command' => 'viewsTriggerPreview',
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the page title.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*/
|
||||
function views_ajax_command_replace_title($title) {
|
||||
$command = array(
|
||||
'command' => 'viewsReplaceTitle',
|
||||
'title' => $title,
|
||||
'siteName' => variable_get('site_name', 'Drupal'),
|
||||
);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an AJAX error.
|
||||
*/
|
||||
function views_ajax_error($message) {
|
||||
$commands = array();
|
||||
$commands[] = views_ajax_command_set_form($message, t('Error'));
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around drupal_build_form to handle some AJAX stuff automatically.
|
||||
* This makes some assumptions about the client.
|
||||
*/
|
||||
function views_ajax_form_wrapper($form_id, &$form_state) {
|
||||
ctools_include('dependent');
|
||||
|
||||
// This won't override settings already in.
|
||||
$form_state += array(
|
||||
'rerender' => FALSE,
|
||||
'no_redirect' => !empty($form_state['ajax']),
|
||||
'no_cache' => TRUE,
|
||||
'build_info' => array(
|
||||
'args' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
$form = drupal_build_form($form_id, $form_state);
|
||||
$output = drupal_render($form);
|
||||
|
||||
// These forms have the title built in, so set the title here:
|
||||
if (empty($form_state['ajax']) && !empty($form_state['title'])) {
|
||||
drupal_set_title($form_state['title']);
|
||||
drupal_add_css(drupal_get_path('module', 'views_ui') . '/css/views-admin.css');
|
||||
}
|
||||
|
||||
if (!empty($form_state['ajax']) && (empty($form_state['executed']) || !empty($form_state['rerender']))) {
|
||||
// If the form didn't execute and we're using ajax, build up a
|
||||
// Ajax command list to execute.
|
||||
$commands = array();
|
||||
|
||||
$display = '';
|
||||
if ($messages = theme('status_messages')) {
|
||||
$display = '<div class="views-messages">' . $messages . '</div>';
|
||||
}
|
||||
$display .= $output;
|
||||
|
||||
$title = empty($form_state['title']) ? '' : $form_state['title'];
|
||||
if (!empty($form_state['help_topic'])) {
|
||||
$module = !empty($form_state['help_module']) ? $form_state['help_module'] : 'views';
|
||||
if (module_exists('advanced_help')) {
|
||||
$title = theme('advanced_help_topic', array('module' => $module, 'topic' => $form_state['help_topic'])) . $title;
|
||||
}
|
||||
}
|
||||
|
||||
$url = empty($form_state['url']) ? url($_GET['q'], array('absolute' => TRUE)) : $form_state['url'];
|
||||
|
||||
$commands[] = views_ajax_command_set_form($display, $title, $url);
|
||||
|
||||
if (!empty($form_state['#section'])) {
|
||||
$commands[] = views_ajax_command_hilite('.' . drupal_clean_css_identifier($form_state['#section']));
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
// These forms have the title built in, so set the title here:
|
||||
if (empty($form_state['ajax']) && !empty($form_state['title'])) {
|
||||
drupal_set_title($form_state['title']);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Page callback for views user autocomplete
|
||||
*/
|
||||
function views_ajax_autocomplete_user($string = '') {
|
||||
// The user enters a comma-separated list of user name. We only autocomplete the last name.
|
||||
$array = drupal_explode_tags($string);
|
||||
|
||||
// Fetch last name
|
||||
$last_string = trim(array_pop($array));
|
||||
$matches = array();
|
||||
if ($last_string != '') {
|
||||
$prefix = count($array) ? implode(', ', $array) . ', ' : '';
|
||||
|
||||
if (strpos('anonymous', strtolower($last_string)) !== FALSE) {
|
||||
$matches[$prefix . 'Anonymous'] = 'Anonymous';
|
||||
}
|
||||
|
||||
$result = db_select('users', 'u')
|
||||
->fields('u', array('uid', 'name'))
|
||||
->condition('u.name', db_like($last_string) . '%', 'LIKE')
|
||||
->range(0, 10)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
|
||||
foreach ($result as $account) {
|
||||
$n = $account;
|
||||
// Commas and quotes in terms are special cases, so encode 'em.
|
||||
if (strpos($account, ',') !== FALSE || strpos($account, '"') !== FALSE) {
|
||||
$n = '"' . str_replace('"', '""', $account) . '"';
|
||||
}
|
||||
$matches[$prefix . $n] = check_plain($account);
|
||||
}
|
||||
}
|
||||
|
||||
drupal_json_output($matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback for views taxonomy autocomplete.
|
||||
*
|
||||
* @param $vid
|
||||
* The vocabulary id of the tags which should be returned.
|
||||
*
|
||||
* @param $tags_typed
|
||||
* The typed string of the user.
|
||||
*
|
||||
* @see taxonomy_autocomplete()
|
||||
*/
|
||||
function views_ajax_autocomplete_taxonomy($vid, $tags_typed = '') {
|
||||
// The user enters a comma-separated list of tags. We only autocomplete the last tag.
|
||||
$tags_typed = drupal_explode_tags($tags_typed);
|
||||
$tag_last = drupal_strtolower(array_pop($tags_typed));
|
||||
|
||||
$matches = array();
|
||||
if ($tag_last != '') {
|
||||
|
||||
$query = db_select('taxonomy_term_data', 't');
|
||||
$query->addTag('translatable');
|
||||
$query->addTag('term_access');
|
||||
|
||||
// Do not select already entered terms.
|
||||
if (!empty($tags_typed)) {
|
||||
$query->condition('t.name', $tags_typed, 'NOT IN');
|
||||
}
|
||||
// Select rows that match by term name.
|
||||
$tags_return = $query
|
||||
->fields('t', array('tid', 'name'))
|
||||
->condition('t.vid', $vid)
|
||||
->condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')
|
||||
->range(0, 10)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
|
||||
$prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
|
||||
|
||||
$term_matches = array();
|
||||
foreach ($tags_return as $tid => $name) {
|
||||
$n = $name;
|
||||
// Term names containing commas or quotes must be wrapped in quotes.
|
||||
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
|
||||
$n = '"' . str_replace('"', '""', $name) . '"';
|
||||
}
|
||||
// Add term name to list of matches.
|
||||
$term_matches[$prefix . $n] = check_plain($name);
|
||||
}
|
||||
}
|
||||
|
||||
drupal_json_output($term_matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
122
sites/all/modules/views/includes/analyze.inc
Normal file
122
sites/all/modules/views/includes/analyze.inc
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the view analyze tool code.
|
||||
*
|
||||
* This tool is a small plugin manager to perform analysis on a view and
|
||||
* report results to the user. This tool is meant to let modules that
|
||||
* provide data to Views also help users properly use that data by
|
||||
* detecting invalid configurations. Views itself comes with only a
|
||||
* small amount of analysis tools, but more could easily be added either
|
||||
* by modules or as patches to Views itself.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Analyze a review and return the results.
|
||||
*
|
||||
* @return
|
||||
* An array of analyze results organized into arrays keyed by 'ok',
|
||||
* 'warning' and 'error'.
|
||||
*/
|
||||
function views_analyze_view(&$view) {
|
||||
$view->init_display();
|
||||
$messages = module_invoke_all('views_analyze', $view);
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the analyze result into a message string.
|
||||
*
|
||||
* This is based upon the format of drupal_set_message which uses separate
|
||||
* boxes for "ok", "warning" and "error".
|
||||
*/
|
||||
function views_analyze_format_result($view, $messages) {
|
||||
if (empty($messages)) {
|
||||
$messages = array(views_ui_analysis(t('View analysis can find nothing to report.'), 'ok'));
|
||||
}
|
||||
|
||||
$types = array('ok' => array(), 'warning' => array(), 'error' => array());
|
||||
foreach ($messages as $message) {
|
||||
if (empty($types[$message['type']])) {
|
||||
$types[$message['type']] = array();
|
||||
}
|
||||
$types[$message['type']][] = $message['message'];
|
||||
}
|
||||
|
||||
$output = '';
|
||||
foreach ($types as $type => $messages) {
|
||||
$type .= ' messages';
|
||||
$message = '';
|
||||
if (count($messages) > 1) {
|
||||
$message = theme('item_list', array('items' => $messages));
|
||||
}
|
||||
elseif ($messages) {
|
||||
$message = array_shift($messages);
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
$output .= "<div class=\"$type\">$message</div>";
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an analysis message.
|
||||
*
|
||||
* This tool should be called by any module responding to the analyze hook
|
||||
* to properly format the message. It is usually used in the form:
|
||||
* @code
|
||||
* $ret[] = views_ui_analysis(t('This is the message'), 'ok');
|
||||
* @endcode
|
||||
*
|
||||
* The 'ok' status should be used to provide information about things
|
||||
* that are acceptable. In general analysis isn't interested in 'ok'
|
||||
* messages, but instead the 'warning', which is a category for items
|
||||
* that may be broken unless the user knows what he or she is doing,
|
||||
* and 'error' for items that are definitely broken are much more useful.
|
||||
*
|
||||
* @param $messages
|
||||
* The message to report.
|
||||
* @param $type
|
||||
* The type of message. This should be "ok", "warning" or "error". Other
|
||||
* values can be used but how they are treated by the output routine
|
||||
* is undefined.
|
||||
*/
|
||||
function views_ui_analysis($message, $type = 'error') {
|
||||
return array('message' => $message, 'type' => $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_views_analyze().
|
||||
*
|
||||
* This is the basic views analysis that checks for very minimal problems.
|
||||
* There are other analysis tools in core specific sections, such as
|
||||
* node.views.inc as well.
|
||||
*/
|
||||
function views_ui_views_analyze($view) {
|
||||
$ret = array();
|
||||
// Check for something other than the default display:
|
||||
if (count($view->display) < 2) {
|
||||
$ret[] = views_ui_analysis(t('This view has only a default display and therefore will not be placed anywhere on your site; perhaps you want to add a page or a block display.'), 'warning');
|
||||
}
|
||||
// You can give a page display the same path as an alias existing in the
|
||||
// system, so the alias will not work anymore. Report this to the user,
|
||||
// because he probably wanted something else.
|
||||
foreach ($view->display as $id => $display) {
|
||||
if (empty($display->handler)) {
|
||||
continue;
|
||||
}
|
||||
if ($display->handler->has_path() && $path = $display->handler->get_option('path')) {
|
||||
$normal_path = drupal_get_normal_path($path);
|
||||
if ($path != $normal_path) {
|
||||
$ret[] = views_ui_analysis(t('You have configured display %display with a path which is an path alias as well. This might lead to unwanted effects so better use an internal path.', array('%display' => $display->display_title)), 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
359
sites/all/modules/views/includes/base.inc
Normal file
359
sites/all/modules/views/includes/base.inc
Normal file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides the basic object definitions used by plugins and handlers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Basic definition for many views objects.
|
||||
*/
|
||||
class views_object {
|
||||
/**
|
||||
* Except for displays, options for the object will be held here.
|
||||
*/
|
||||
var $options = array();
|
||||
|
||||
/**
|
||||
* The top object of a view.
|
||||
*
|
||||
* @var view
|
||||
*/
|
||||
var $view = NULL;
|
||||
|
||||
/**
|
||||
* Handler's definition
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $definition;
|
||||
|
||||
/**
|
||||
* Information about options for all kinds of purposes will be held here.
|
||||
* @code
|
||||
* 'option_name' => array(
|
||||
* - 'default' => default value,
|
||||
* - 'translatable' => (optional) TRUE/FALSE (wrap in t() on export if true),
|
||||
* - 'contains' => (optional) array of items this contains, with its own
|
||||
* defaults, etc. If contains is set, the default will be ignored and
|
||||
* assumed to be array().
|
||||
* - 'bool' => (optional) TRUE/FALSE Is the value a boolean value. This will
|
||||
* change the export format to TRUE/FALSE instead of 1/0.
|
||||
* - 'export' => (optional) FALSE or a callback for special export handling
|
||||
* if necessary.
|
||||
* - 'unpack_translatable' => (optional) callback for special handling for
|
||||
* translating data within the option, if necessary.
|
||||
* ),
|
||||
*
|
||||
* @return array
|
||||
* Returns the options of this handler/plugin.
|
||||
*
|
||||
* @see views_object::export_option()
|
||||
* @see views_object::export_option_always()
|
||||
* @see views_object::unpack_translatable()
|
||||
*/
|
||||
function option_definition() { return array(); }
|
||||
|
||||
/**
|
||||
* Views handlers use a special construct function so that we can more
|
||||
* easily construct them with variable arguments.
|
||||
*/
|
||||
function construct() { $this->set_default_options(); }
|
||||
|
||||
/**
|
||||
* Set default options on this object. Called by the constructor in a
|
||||
* complex chain to deal with backward compatibility.
|
||||
*
|
||||
* @deprecated since views2
|
||||
*/
|
||||
function options(&$options) { }
|
||||
|
||||
/**
|
||||
* Set default options.
|
||||
* For backward compatibility, it sends the options array; this is a
|
||||
* feature that will likely disappear at some point.
|
||||
*/
|
||||
function set_default_options() {
|
||||
$this->_set_option_defaults($this->options, $this->option_definition());
|
||||
|
||||
// Retained for complex defaults plus backward compatibility.
|
||||
$this->options($this->options);
|
||||
}
|
||||
|
||||
function _set_option_defaults(&$storage, $options, $level = 0) {
|
||||
foreach ($options as $option => $definition) {
|
||||
if (isset($definition['contains']) && is_array($definition['contains'])) {
|
||||
$storage[$option] = array();
|
||||
$this->_set_option_defaults($storage[$option], $definition['contains'], $level++);
|
||||
}
|
||||
elseif (!empty($definition['translatable']) && !empty($definition['default'])) {
|
||||
$storage[$option] = t($definition['default']);
|
||||
}
|
||||
else {
|
||||
$storage[$option] = isset($definition['default']) ? $definition['default'] : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack options over our existing defaults, drilling down into arrays
|
||||
* so that defaults don't get totally blown away.
|
||||
*/
|
||||
function unpack_options(&$storage, $options, $definition = NULL, $all = TRUE, $check = TRUE, $localization_keys = array()) {
|
||||
if ($check && !is_array($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($definition)) {
|
||||
$definition = $this->option_definition();
|
||||
}
|
||||
|
||||
if (!empty($this->view)) {
|
||||
// Ensure we have a localization plugin.
|
||||
$this->view->init_localization();
|
||||
|
||||
// Set up default localization keys. Handlers and such set this for us
|
||||
if (empty($localization_keys) && isset($this->localization_keys)) {
|
||||
$localization_keys = $this->localization_keys;
|
||||
}
|
||||
// but plugins don't because there isn't a common init() these days.
|
||||
else if (!empty($this->is_plugin)) {
|
||||
if ($this->plugin_type != 'display') {
|
||||
$localization_keys = array($this->view->current_display);
|
||||
$localization_keys[] = $this->plugin_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
// Ignore arrays with no definition.
|
||||
if (!$all && empty($definition[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($storage[$key]) || !is_array($storage[$key])) {
|
||||
$storage[$key] = array();
|
||||
}
|
||||
|
||||
// If we're just unpacking our known options, and we're dropping an
|
||||
// unknown array (as might happen for a dependent plugin fields) go
|
||||
// ahead and drop that in.
|
||||
if (!$all && isset($definition[$key]) && !isset($definition[$key]['contains'])) {
|
||||
$storage[$key] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->unpack_options($storage[$key], $value, isset($definition[$key]['contains']) ? $definition[$key]['contains'] : array(), $all, FALSE, array_merge($localization_keys, array($key)));
|
||||
}
|
||||
// Don't localize strings during editing. When editing, we need to work with
|
||||
// the original data, not the translated version.
|
||||
else if (empty($this->view->editing) && !empty($definition[$key]['translatable']) && !empty($value) || !empty($definition['contains'][$key]['translatable']) && !empty($value)) {
|
||||
if (!empty($this->view) && $this->view->is_translatable()) {
|
||||
// Allow other modules to make changes to the string before it's
|
||||
// sent for translation.
|
||||
// The $keys array is built from the view name, any localization keys
|
||||
// sent in, and the name of the property being processed.
|
||||
$format = NULL;
|
||||
if (isset($definition[$key]['format_key']) && isset($options[$definition[$key]['format_key']])) {
|
||||
$format = $options[$definition[$key]['format_key']];
|
||||
}
|
||||
$translation_data = array(
|
||||
'value' => $value,
|
||||
'format' => $format,
|
||||
'keys' => array_merge(array($this->view->name), $localization_keys, array($key)),
|
||||
);
|
||||
$storage[$key] = $this->view->localization_plugin->translate($translation_data);
|
||||
}
|
||||
// Otherwise, this is a code-based string, so we can use t().
|
||||
else {
|
||||
$storage[$key] = t($value);
|
||||
}
|
||||
}
|
||||
else if ($all || !empty($definition[$key])) {
|
||||
$storage[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the handler know what its full definition is.
|
||||
*/
|
||||
function set_definition($definition) {
|
||||
$this->definition = $definition;
|
||||
if (isset($definition['field'])) {
|
||||
$this->real_field = $definition['field'];
|
||||
}
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
if (isset($this->view)) {
|
||||
unset($this->view);
|
||||
}
|
||||
|
||||
if (isset($this->display)) {
|
||||
unset($this->display);
|
||||
}
|
||||
|
||||
if (isset($this->query)) {
|
||||
unset($this->query);
|
||||
}
|
||||
}
|
||||
|
||||
function export_options($indent, $prefix) {
|
||||
$output = '';
|
||||
foreach ($this->option_definition() as $option => $definition) {
|
||||
$output .= $this->export_option($indent, $prefix, $this->options, $option, $definition, array());
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function export_option($indent, $prefix, $storage, $option, $definition, $parents) {
|
||||
// Do not export options for which we have no settings.
|
||||
if (!isset($storage[$option])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($definition['export'])) {
|
||||
if ($definition['export'] === FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special handling for some items
|
||||
if (method_exists($this, $definition['export'])) {
|
||||
return $this->{$definition['export']}($indent, $prefix, $storage, $option, $definition, $parents);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the current option to the parents tree.
|
||||
$parents[] = $option;
|
||||
$output = '';
|
||||
|
||||
// If it has child items, export those separately.
|
||||
if (isset($definition['contains'])) {
|
||||
foreach ($definition['contains'] as $sub_option => $sub_definition) {
|
||||
$output .= $this->export_option($indent, $prefix, $storage[$option], $sub_option, $sub_definition, $parents);
|
||||
}
|
||||
}
|
||||
// Otherwise export just this item.
|
||||
else {
|
||||
$default = isset($definition['default']) ? $definition['default'] : NULL;
|
||||
$value = $storage[$option];
|
||||
if (isset($definition['bool'])) {
|
||||
$value = (bool) $value;
|
||||
}
|
||||
|
||||
if ($value !== $default) {
|
||||
$output .= $indent . $prefix . "['" . implode("']['", $parents) . "'] = ";
|
||||
if (isset($definition['bool'])) {
|
||||
$output .= empty($storage[$option]) ? 'FALSE' : 'TRUE';
|
||||
}
|
||||
else {
|
||||
$output .= views_var_export($storage[$option], $indent);
|
||||
}
|
||||
|
||||
$output .= ";\n";
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always exports the option, regardless of the default value.
|
||||
*/
|
||||
function export_option_always($indent, $prefix, $storage, $option, $definition, $parents) {
|
||||
// If there is no default, the option will always be exported.
|
||||
unset($definition['default']);
|
||||
// Unset our export method to prevent recursion.
|
||||
unset($definition['export']);
|
||||
return $this->export_option($indent, $prefix, $storage, $option, $definition, $parents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks each handler to store translatable texts.
|
||||
*/
|
||||
function unpack_translatables(&$translatable, $parents = array()) {
|
||||
foreach ($this->option_definition() as $option => $definition) {
|
||||
$this->unpack_translatable($translatable, $this->options, $option, $definition, $parents, array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack a single option definition.
|
||||
*
|
||||
* This function run's through all suboptions recursive.
|
||||
*
|
||||
* @param $translatable
|
||||
* Stores all available translatable items.
|
||||
* @param $storage
|
||||
* @param $option
|
||||
* @param $definition
|
||||
* @param $parents
|
||||
* @param $keys
|
||||
*/
|
||||
function unpack_translatable(&$translatable, $storage, $option, $definition, $parents, $keys = array()) {
|
||||
// Do not export options for which we have no settings.
|
||||
if (!isset($storage[$option])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special handling for some items
|
||||
if (isset($definition['unpack_translatable']) && method_exists($this, $definition['unpack_translatable'])) {
|
||||
return $this->{$definition['unpack_translatable']}($translatable, $storage, $option, $definition, $parents, $keys);
|
||||
}
|
||||
|
||||
if (isset($definition['translatable'])) {
|
||||
if ($definition['translatable'] === FALSE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the current option to the parents tree.
|
||||
$parents[] = $option;
|
||||
|
||||
// If it has child items, unpack those separately.
|
||||
if (isset($definition['contains'])) {
|
||||
foreach ($definition['contains'] as $sub_option => $sub_definition) {
|
||||
$translation_keys = array_merge($keys, array($sub_option));
|
||||
$this->unpack_translatable($translatable, $storage[$option], $sub_option, $sub_definition, $parents, $translation_keys);
|
||||
}
|
||||
}
|
||||
|
||||
// @todo Figure out this double definition stuff.
|
||||
$options = $storage[$option];
|
||||
if (is_array($options)) {
|
||||
foreach ($options as $key => $value) {
|
||||
$translation_keys = array_merge($keys, array($key));
|
||||
if (is_array($value)) {
|
||||
$this->unpack_translatable($translatable, $options, $key, $definition, $parents, $translation_keys);
|
||||
}
|
||||
else if (!empty($definition[$key]['translatable']) && !empty($value)) {
|
||||
// Build source data and add to the array
|
||||
$format = NULL;
|
||||
if (isset($definition['format_key']) && isset($options[$definition['format_key']])) {
|
||||
$format = $options[$definition['format_key']];
|
||||
}
|
||||
$translatable[] = array(
|
||||
'value' => $value,
|
||||
'keys' => $translation_keys,
|
||||
'format' => $format,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!empty($definition['translatable']) && !empty($options)) {
|
||||
$value = $options;
|
||||
// Build source data and add to the array
|
||||
$format = NULL;
|
||||
if (isset($definition['format_key']) && isset($options[$definition['format_key']])) {
|
||||
$format = $options[$definition['format_key']];
|
||||
}
|
||||
$translatable[] = array(
|
||||
'value' => $value,
|
||||
'keys' => isset($translation_keys) ? $translation_keys : $parents,
|
||||
'format' => $format,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
193
sites/all/modules/views/includes/cache.inc
Normal file
193
sites/all/modules/views/includes/cache.inc
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Load Views' data so that it knows what is available to build queries from.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch Views' data from the cache
|
||||
*
|
||||
* @param $move
|
||||
* Under certain circumstances it makes sense to not get the moved table, but the old one.
|
||||
* One example is views_get_handler.
|
||||
*/
|
||||
function _views_fetch_data($table = NULL, $move = TRUE, $reset = FALSE) {
|
||||
$cache = &drupal_static(__FUNCTION__ . '_cache');
|
||||
$recursion_protection = &drupal_static(__FUNCTION__ . '_recursion_protected');
|
||||
$fully_loaded = &drupal_static(__FUNCTION__ . '_fully_loaded');
|
||||
if ($reset) {
|
||||
$cache = NULL;
|
||||
$fully_loaded = FALSE;
|
||||
}
|
||||
if ($table) {
|
||||
if (!isset($cache[$table])) {
|
||||
$cid = 'views_data:' . $table;
|
||||
$data = views_cache_get($cid, TRUE);
|
||||
if (!empty($data->data)) {
|
||||
$cache[$table] = $data->data;
|
||||
}
|
||||
else {
|
||||
// No cache entry, rebuild.
|
||||
$cache = _views_fetch_data_build();
|
||||
$fully_loaded = TRUE;
|
||||
}
|
||||
}
|
||||
if (isset($cache[$table])) {
|
||||
if (isset($cache[$table]['moved to']) && $move) {
|
||||
$moved_table = $cache[$table]['moved to'];
|
||||
if (!empty($recursion_protection[$table])) {
|
||||
// recursion detected!
|
||||
return NULL;
|
||||
}
|
||||
$recursion_protection[$table] = TRUE;
|
||||
$data = _views_fetch_data($moved_table);
|
||||
$recursion_protection = array();
|
||||
return $data;
|
||||
}
|
||||
return $cache[$table];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!$fully_loaded) {
|
||||
$data = views_cache_get('views_data', TRUE);
|
||||
if (!empty($data->data)) {
|
||||
$cache = $data->data;
|
||||
}
|
||||
|
||||
if (empty($cache)) {
|
||||
$cache = _views_fetch_data_build();
|
||||
}
|
||||
$fully_loaded = TRUE;
|
||||
}
|
||||
return $cache;
|
||||
}
|
||||
// Return an empty array if there is no match.
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and set the views data cache if empty.
|
||||
*/
|
||||
function _views_fetch_data_build() {
|
||||
views_include_handlers();
|
||||
$cache = module_invoke_all('views_data');
|
||||
foreach (module_implements('views_data_alter') as $module) {
|
||||
$function = $module . '_views_data_alter';
|
||||
$function($cache);
|
||||
}
|
||||
_views_data_process_entity_types($cache);
|
||||
|
||||
// Keep a record with all data.
|
||||
views_cache_set('views_data', $cache, TRUE);
|
||||
// Save data in seperate cache entries.
|
||||
foreach ($cache as $key => $data) {
|
||||
$cid = 'views_data:' . $key;
|
||||
views_cache_set($cid, $data, TRUE);
|
||||
}
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Links tables having an 'entity type' specified to the respective generic entity-type tables.
|
||||
*/
|
||||
function _views_data_process_entity_types(&$data) {
|
||||
foreach ($data as $table_name => $table_info) {
|
||||
// Add in a join from the entity-table if an entity-type is given.
|
||||
if (!empty($table_info['table']['entity type'])) {
|
||||
$entity_table = 'views_entity_' . $table_info['table']['entity type'];
|
||||
|
||||
$data[$entity_table]['table']['join'][$table_name] = array(
|
||||
'left_table' => $table_name,
|
||||
);
|
||||
$data[$entity_table]['table']['entity type'] = $table_info['table']['entity type'];
|
||||
// Copy over the default table group if we have none yet.
|
||||
if (!empty($table_info['table']['group']) && empty($data[$entity_table]['table']['group'])) {
|
||||
$data[$entity_table]['table']['group'] = $table_info['table']['group'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the plugin data from cache.
|
||||
*/
|
||||
function _views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) {
|
||||
static $cache = NULL;
|
||||
if (!isset($cache) || $reset) {
|
||||
$start = microtime(TRUE);
|
||||
views_include('plugins');
|
||||
views_include_handlers();
|
||||
|
||||
$cache = views_discover_plugins();
|
||||
|
||||
}
|
||||
|
||||
if (!$type && !$plugin) {
|
||||
return $cache;
|
||||
}
|
||||
elseif (!$plugin) {
|
||||
// Not in the if above so the else below won't run
|
||||
if (isset($cache[$type])) {
|
||||
return $cache[$type];
|
||||
}
|
||||
}
|
||||
elseif (isset($cache[$type][$plugin])) {
|
||||
return $cache[$type][$plugin];
|
||||
}
|
||||
|
||||
// Return an empty array if there is no match.
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cached item in the views cache.
|
||||
*
|
||||
* This is just a convenience wrapper around cache_set().
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID of the data to store.
|
||||
* @param $data
|
||||
* The data to store in the cache. Complex data types will be automatically serialized before insertion.
|
||||
* Strings will be stored as plain text and not serialized.
|
||||
* @param $use_language
|
||||
* If TRUE, the data will be cached specific to the currently active language.
|
||||
*/
|
||||
function views_cache_set($cid, $data, $use_language = FALSE) {
|
||||
global $language;
|
||||
|
||||
if (variable_get('views_skip_cache', FALSE)) {
|
||||
return;
|
||||
}
|
||||
if ($use_language) {
|
||||
$cid .= ':' . $language->language;
|
||||
}
|
||||
|
||||
cache_set($cid, $data, 'cache_views');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return data from the persistent views cache.
|
||||
*
|
||||
* This is just a convenience wrapper around cache_get().
|
||||
*
|
||||
* @param int $cid
|
||||
* The cache ID of the data to retrieve.
|
||||
* @param bool $use_language
|
||||
* If TRUE, the data will be requested specific to the currently active language.
|
||||
*
|
||||
* @return stdClass|bool
|
||||
* The cache or FALSE on failure.
|
||||
*/
|
||||
function views_cache_get($cid, $use_language = FALSE) {
|
||||
global $language;
|
||||
|
||||
if (variable_get('views_skip_cache', FALSE)) {
|
||||
return FALSE;
|
||||
}
|
||||
if ($use_language) {
|
||||
$cid .= ':' . $language->language;
|
||||
}
|
||||
|
||||
return cache_get($cid, 'cache_views');
|
||||
}
|
1713
sites/all/modules/views/includes/handlers.inc
Normal file
1713
sites/all/modules/views/includes/handlers.inc
Normal file
File diff suppressed because it is too large
Load Diff
584
sites/all/modules/views/includes/plugins.inc
Normal file
584
sites/all/modules/views/includes/plugins.inc
Normal file
@@ -0,0 +1,584 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Built in plugins for Views output handling.
|
||||
*/
|
||||
|
||||
// @todo: Remove this once update.php can use the registry
|
||||
views_include('base');
|
||||
|
||||
/**
|
||||
* Implements hook_views_plugins().
|
||||
*/
|
||||
function views_views_plugins() {
|
||||
$js_path = drupal_get_path('module', 'ctools') . '/js';
|
||||
$plugins = array(
|
||||
// display, style, row, argument default, argument validator and access.
|
||||
'display' => array(
|
||||
// Default settings for all display plugins.
|
||||
'default' => array(
|
||||
'title' => t('Master'),
|
||||
'help' => t('Default settings for this view.'),
|
||||
'handler' => 'views_plugin_display_default',
|
||||
'theme' => 'views_view',
|
||||
'no ui' => TRUE,
|
||||
'no remove' => TRUE,
|
||||
'js' => array('misc/form.js', 'misc/collapse.js', 'misc/textarea.js', 'misc/tabledrag.js', 'misc/autocomplete.js', "$js_path/dependent.js"),
|
||||
'use ajax' => TRUE,
|
||||
'use pager' => TRUE,
|
||||
'use more' => TRUE,
|
||||
'accept attachments' => TRUE,
|
||||
'help topic' => 'display-default',
|
||||
),
|
||||
'page' => array(
|
||||
'title' => t('Page'),
|
||||
'help' => t('Display the view as a page, with a URL and menu links.'),
|
||||
'handler' => 'views_plugin_display_page',
|
||||
'theme' => 'views_view',
|
||||
'uses hook menu' => TRUE,
|
||||
'contextual links locations' => array('page'),
|
||||
'use ajax' => TRUE,
|
||||
'use pager' => TRUE,
|
||||
'use more' => TRUE,
|
||||
'accept attachments' => TRUE,
|
||||
'admin' => t('Page'),
|
||||
'help topic' => 'display-page',
|
||||
),
|
||||
'block' => array(
|
||||
'title' => t('Block'),
|
||||
'help' => t('Display the view as a block.'),
|
||||
'handler' => 'views_plugin_display_block',
|
||||
'theme' => 'views_view',
|
||||
'uses hook block' => TRUE,
|
||||
'contextual links locations' => array('block'),
|
||||
'use ajax' => TRUE,
|
||||
'use pager' => TRUE,
|
||||
'use more' => TRUE,
|
||||
'accept attachments' => TRUE,
|
||||
'admin' => t('Block'),
|
||||
'help topic' => 'display-block',
|
||||
),
|
||||
'attachment' => array(
|
||||
'title' => t('Attachment'),
|
||||
'help' => t('Attachments added to other displays to achieve multiple views in the same view.'),
|
||||
'handler' => 'views_plugin_display_attachment',
|
||||
'theme' => 'views_view',
|
||||
'contextual links locations' => array(),
|
||||
'use ajax' => TRUE,
|
||||
'use pager' => FALSE,
|
||||
'use more' => TRUE,
|
||||
'accept attachments' => FALSE,
|
||||
'help topic' => 'display-attachment',
|
||||
),
|
||||
'feed' => array(
|
||||
'title' => t('Feed'),
|
||||
'help' => t('Display the view as a feed, such as an RSS feed.'),
|
||||
'handler' => 'views_plugin_display_feed',
|
||||
'uses hook menu' => TRUE,
|
||||
'use ajax' => FALSE,
|
||||
'use pager' => FALSE,
|
||||
'accept attachments' => FALSE,
|
||||
'admin' => t('Feed'),
|
||||
'help topic' => 'display-feed',
|
||||
),
|
||||
'embed' => array(
|
||||
'title' => t('Embed'),
|
||||
'help' => t('Provide a display which can be embedded using the views api.'),
|
||||
'handler' => 'views_plugin_display_embed',
|
||||
'theme' => 'views_view',
|
||||
'uses hook menu' => FALSE,
|
||||
'use ajax' => TRUE,
|
||||
'use pager' => TRUE,
|
||||
'accept attachments' => FALSE,
|
||||
'admin' => t('Embed'),
|
||||
'no ui' => !variable_get('views_ui_display_embed', FALSE),
|
||||
),
|
||||
),
|
||||
'display_extender' => array(
|
||||
// Default settings for all display_extender plugins.
|
||||
'default' => array(
|
||||
'title' => t('Empty display extender'),
|
||||
'help' => t('Default settings for this view.'),
|
||||
'handler' => 'views_plugin_display_extender',
|
||||
// You can force the plugin to be enabled
|
||||
'enabled' => FALSE,
|
||||
'no ui' => TRUE,
|
||||
),
|
||||
),
|
||||
'style' => array(
|
||||
// Default settings for all style plugins.
|
||||
'default' => array(
|
||||
'title' => t('Unformatted list'),
|
||||
'help' => t('Displays rows one after another.'),
|
||||
'handler' => 'views_plugin_style_default',
|
||||
'theme' => 'views_view_unformatted',
|
||||
'uses row plugin' => TRUE,
|
||||
'uses row class' => TRUE,
|
||||
'uses grouping' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-unformatted',
|
||||
),
|
||||
'list' => array(
|
||||
'title' => t('HTML list'),
|
||||
'help' => t('Displays rows as an HTML list.'),
|
||||
'handler' => 'views_plugin_style_list',
|
||||
'theme' => 'views_view_list',
|
||||
'uses row plugin' => TRUE,
|
||||
'uses row class' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-list',
|
||||
),
|
||||
'grid' => array(
|
||||
'title' => t('Grid'),
|
||||
'help' => t('Displays rows in a grid.'),
|
||||
'handler' => 'views_plugin_style_grid',
|
||||
'theme' => 'views_view_grid',
|
||||
'uses fields' => FALSE,
|
||||
'uses row plugin' => TRUE,
|
||||
'uses row class' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-grid',
|
||||
),
|
||||
'table' => array(
|
||||
'title' => t('Table'),
|
||||
'help' => t('Displays rows in a table.'),
|
||||
'handler' => 'views_plugin_style_table',
|
||||
'theme' => 'views_view_table',
|
||||
'uses row plugin' => FALSE,
|
||||
'uses row class' => TRUE,
|
||||
'uses fields' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-table',
|
||||
),
|
||||
'default_summary' => array(
|
||||
'title' => t('List'),
|
||||
'help' => t('Displays the default summary as a list.'),
|
||||
'handler' => 'views_plugin_style_summary',
|
||||
'theme' => 'views_view_summary',
|
||||
'type' => 'summary', // only shows up as a summary style
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'style-summary',
|
||||
),
|
||||
'unformatted_summary' => array(
|
||||
'title' => t('Unformatted'),
|
||||
'help' => t('Displays the summary unformatted, with option for one after another or inline.'),
|
||||
'handler' => 'views_plugin_style_summary_unformatted',
|
||||
'theme' => 'views_view_summary_unformatted',
|
||||
'type' => 'summary', // only shows up as a summary style
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'style-summary-unformatted',
|
||||
),
|
||||
'rss' => array(
|
||||
'title' => t('RSS Feed'),
|
||||
'help' => t('Generates an RSS feed from a view.'),
|
||||
'handler' => 'views_plugin_style_rss',
|
||||
'theme' => 'views_view_rss',
|
||||
'uses row plugin' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'feed',
|
||||
'help topic' => 'style-rss',
|
||||
),
|
||||
),
|
||||
'row' => array(
|
||||
'fields' => array(
|
||||
'title' => t('Fields'),
|
||||
'help' => t('Displays the fields with an optional template.'),
|
||||
'handler' => 'views_plugin_row_fields',
|
||||
'theme' => 'views_view_fields',
|
||||
'uses fields' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-row-fields',
|
||||
),
|
||||
'rss_fields' => array(
|
||||
'title' => t('Fields'),
|
||||
'help' => t('Display fields as RSS items.'),
|
||||
'handler' => 'views_plugin_row_rss_fields',
|
||||
'theme' => 'views_view_row_rss',
|
||||
'uses fields' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'feed',
|
||||
'help topic' => 'style-row-fields',
|
||||
),
|
||||
),
|
||||
'argument default' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_argument_default',
|
||||
'parent' => '',
|
||||
),
|
||||
'fixed' => array(
|
||||
'title' => t('Fixed value'),
|
||||
'handler' => 'views_plugin_argument_default_fixed',
|
||||
),
|
||||
'php' => array(
|
||||
'title' => t('PHP Code'),
|
||||
'handler' => 'views_plugin_argument_default_php',
|
||||
),
|
||||
'raw' => array(
|
||||
'title' => t('Raw value from URL'),
|
||||
'handler' => 'views_plugin_argument_default_raw',
|
||||
),
|
||||
),
|
||||
'argument validator' => array(
|
||||
'php' => array(
|
||||
'title' => t('PHP Code'),
|
||||
'handler' => 'views_plugin_argument_validate_php',
|
||||
),
|
||||
'numeric' => array(
|
||||
'title' => t('Numeric'),
|
||||
'handler' => 'views_plugin_argument_validate_numeric',
|
||||
),
|
||||
),
|
||||
'access' => array(
|
||||
'none' => array(
|
||||
'title' => t('None'),
|
||||
'help' => t('Will be available to all users.'),
|
||||
'handler' => 'views_plugin_access_none',
|
||||
'help topic' => 'access-none',
|
||||
),
|
||||
'role' => array(
|
||||
'title' => t('Role'),
|
||||
'help' => t('Access will be granted to users with any of the specified roles.'),
|
||||
'handler' => 'views_plugin_access_role',
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'access-role',
|
||||
),
|
||||
'perm' => array(
|
||||
'title' => t('Permission'),
|
||||
'help' => t('Access will be granted to users with the specified permission string.'),
|
||||
'handler' => 'views_plugin_access_perm',
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'access-perm',
|
||||
),
|
||||
),
|
||||
'query' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_query',
|
||||
'parent' => '',
|
||||
),
|
||||
'views_query' => array(
|
||||
'title' => t('SQL Query'),
|
||||
'help' => t('Query will be generated and run using the Drupal database API.'),
|
||||
'handler' => 'views_plugin_query_default'
|
||||
),
|
||||
),
|
||||
'cache' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_cache',
|
||||
'parent' => '',
|
||||
),
|
||||
'none' => array(
|
||||
'title' => t('None'),
|
||||
'help' => t('No caching of Views data.'),
|
||||
'handler' => 'views_plugin_cache_none',
|
||||
'help topic' => 'cache-none',
|
||||
),
|
||||
'time' => array(
|
||||
'title' => t('Time-based'),
|
||||
'help' => t('Simple time-based caching of data.'),
|
||||
'handler' => 'views_plugin_cache_time',
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'cache-time',
|
||||
),
|
||||
),
|
||||
'exposed_form' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_exposed_form',
|
||||
'parent' => '',
|
||||
),
|
||||
'basic' => array(
|
||||
'title' => t('Basic'),
|
||||
'help' => t('Basic exposed form'),
|
||||
'handler' => 'views_plugin_exposed_form_basic',
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'exposed-form-basic',
|
||||
),
|
||||
'input_required' => array(
|
||||
'title' => t('Input required'),
|
||||
'help' => t('An exposed form that only renders a view if the form contains user input.'),
|
||||
'handler' => 'views_plugin_exposed_form_input_required',
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'exposed-form-input-required',
|
||||
),
|
||||
),
|
||||
'pager' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_pager',
|
||||
'parent' => '',
|
||||
),
|
||||
'none' => array(
|
||||
'title' => t('Display all items'),
|
||||
'help' => t("Display all items that this view might find"),
|
||||
'handler' => 'views_plugin_pager_none',
|
||||
'help topic' => 'pager-none',
|
||||
'uses options' => TRUE,
|
||||
'type' => 'basic',
|
||||
),
|
||||
'some' => array(
|
||||
'title' => t('Display a specified number of items'),
|
||||
'help' => t('Display a limited number items that this view might find.'),
|
||||
'handler' => 'views_plugin_pager_some',
|
||||
'help topic' => 'pager-some',
|
||||
'uses options' => TRUE,
|
||||
'type' => 'basic',
|
||||
),
|
||||
'full' => array(
|
||||
'title' => t('Paged output, full pager'),
|
||||
'short title' => t('Full'),
|
||||
'help' => t('Paged output, full Drupal style'),
|
||||
'handler' => 'views_plugin_pager_full',
|
||||
'help topic' => 'pager-full',
|
||||
'uses options' => TRUE,
|
||||
),
|
||||
'mini' => array(
|
||||
'title' => t('Paged output, mini pager'),
|
||||
'short title' => t('Mini'),
|
||||
'help' => t('Use the mini pager output.'),
|
||||
'handler' => 'views_plugin_pager_mini',
|
||||
'help topic' => 'pager-mini',
|
||||
'uses options' => TRUE,
|
||||
'parent' => 'full',
|
||||
),
|
||||
),
|
||||
'localization' => array(
|
||||
'parent' => array(
|
||||
'no ui' => TRUE,
|
||||
'handler' => 'views_plugin_localization',
|
||||
'parent' => '',
|
||||
),
|
||||
'none' => array(
|
||||
'title' => t('None'),
|
||||
'help' => t('Do not pass admin strings for translation.'),
|
||||
'handler' => 'views_plugin_localization_none',
|
||||
'help topic' => 'localization-none',
|
||||
),
|
||||
'core' => array(
|
||||
'title' => t('Core'),
|
||||
'help' => t("Use Drupal core t() function. Not recommended, as it doesn't support updates to existing strings."),
|
||||
'handler' => 'views_plugin_localization_core',
|
||||
'help topic' => 'localization-core',
|
||||
),
|
||||
),
|
||||
);
|
||||
// Add a help message pointing to the i18views module if it is not present.
|
||||
if (!module_exists('i18nviews')) {
|
||||
$plugins['localization']['core']['help'] .= ' ' . t('If you need to translate Views labels into other languages, consider installing the <a href="!path">Internationalization</a> package\'s Views translation module.', array('!path' => url('http://drupal.org/project/i18n', array('absolute' => TRUE))));
|
||||
}
|
||||
|
||||
if (module_invoke('ctools', 'api_version', '1.3')) {
|
||||
$plugins['style']['jump_menu_summary'] = array(
|
||||
'title' => t('Jump menu'),
|
||||
'help' => t('Puts all of the results into a select box and allows the user to go to a different page based upon the results.'),
|
||||
'handler' => 'views_plugin_style_summary_jump_menu',
|
||||
'theme' => 'views_view_summary_jump_menu',
|
||||
'type' => 'summary', // only shows up as a summary style
|
||||
'uses options' => TRUE,
|
||||
'help topic' => 'style-summary-jump-menu',
|
||||
);
|
||||
$plugins['style']['jump_menu'] = array(
|
||||
'title' => t('Jump menu'),
|
||||
'help' => t('Puts all of the results into a select box and allows the user to go to a different page based upon the results.'),
|
||||
'handler' => 'views_plugin_style_jump_menu',
|
||||
'theme' => 'views_view_jump_menu',
|
||||
'uses row plugin' => TRUE,
|
||||
'uses fields' => TRUE,
|
||||
'uses options' => TRUE,
|
||||
'type' => 'normal',
|
||||
'help topic' => 'style-jump-menu',
|
||||
);
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and return a list of all plugins available in the system.
|
||||
*
|
||||
* @return Nested array of plugins, grouped by type.
|
||||
*/
|
||||
function views_discover_plugins() {
|
||||
$cache = array('display' => array(), 'style' => array(), 'row' => array(), 'argument default' => array(), 'argument validator' => array(), 'access' => array(), 'cache' => array(), 'exposed_form' => array());
|
||||
// Get plugins from all mdoules.
|
||||
foreach (module_implements('views_plugins') as $module) {
|
||||
$function = $module . '_views_plugins';
|
||||
$result = $function();
|
||||
if (!is_array($result)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$module_dir = isset($result['module']) ? $result['module'] : $module;
|
||||
// Setup automatic path/file finding for theme registration
|
||||
if ($module_dir == 'views') {
|
||||
$theme_path = drupal_get_path('module', $module_dir) . '/theme';
|
||||
$theme_file = 'theme.inc';
|
||||
$path = drupal_get_path('module', $module_dir) . '/plugins';
|
||||
}
|
||||
else {
|
||||
$theme_path = $path = drupal_get_path('module', $module_dir);
|
||||
$theme_file = "$module.views.inc";
|
||||
}
|
||||
|
||||
foreach ($result as $type => $info) {
|
||||
if ($type == 'module') {
|
||||
continue;
|
||||
}
|
||||
foreach ($info as $plugin => $def) {
|
||||
$def['module'] = $module_dir;
|
||||
if (!isset($def['theme path'])) {
|
||||
$def['theme path'] = $theme_path;
|
||||
}
|
||||
if (!isset($def['theme file'])) {
|
||||
$def['theme file'] = $theme_file;
|
||||
}
|
||||
if (!isset($def['path'])) {
|
||||
$def['path'] = $path;
|
||||
}
|
||||
if (!isset($def['file'])) {
|
||||
$def['file'] = $def['handler'] . '.inc';
|
||||
}
|
||||
if (!isset($def['parent'])) {
|
||||
$def['parent'] = 'parent';
|
||||
}
|
||||
// Set the internal name to be able to read it out later.
|
||||
$def['name'] = $plugin;
|
||||
|
||||
// merge the new data in
|
||||
$cache[$type][$plugin] = $def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let other modules modify the plugins.
|
||||
drupal_alter('views_plugins', $cache);
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class to provide interface common to all plugins.
|
||||
*/
|
||||
class views_plugin extends views_object {
|
||||
/**
|
||||
* The top object of a view.
|
||||
*
|
||||
* @var view
|
||||
*/
|
||||
var $view = NULL;
|
||||
|
||||
/**
|
||||
* The current used views display.
|
||||
*
|
||||
* @var views_display
|
||||
*/
|
||||
var $display = NULL;
|
||||
|
||||
/**
|
||||
* The plugin type of this plugin, for example style or query.
|
||||
*/
|
||||
var $plugin_type = NULL;
|
||||
|
||||
/**
|
||||
* The plugin name of this plugin, for example table or full.
|
||||
*/
|
||||
var $plugin_name = NULL;
|
||||
|
||||
/**
|
||||
* Init will be called after construct, when the plugin is attached to a
|
||||
* view and a display.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide a form to edit options for this plugin.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
// Some form elements belong in a fieldset for presentation, but can't
|
||||
// be moved into one because of the form_state['values'] hierarchy. Those
|
||||
// elements can add a #fieldset => 'fieldset_name' property, and they'll
|
||||
// be moved to their fieldset during pre_render.
|
||||
$form['#pre_render'][] = 'views_ui_pre_render_add_fieldset_markup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the options form.
|
||||
*/
|
||||
function options_validate(&$form, &$form_state) { }
|
||||
|
||||
/**
|
||||
* Handle any special handling on the validate form.
|
||||
*/
|
||||
function options_submit(&$form, &$form_state) { }
|
||||
|
||||
/**
|
||||
* Add anything to the query that we might need to.
|
||||
*/
|
||||
function query() { }
|
||||
|
||||
/**
|
||||
* Provide a full list of possible theme templates used by this style.
|
||||
*/
|
||||
function theme_functions() {
|
||||
return views_theme_functions($this->definition['theme'], $this->view, $this->display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a list of additional theme functions for the theme information page
|
||||
*/
|
||||
function additional_theme_functions() {
|
||||
$funcs = array();
|
||||
if (!empty($this->definition['additional themes'])) {
|
||||
foreach ($this->definition['additional themes'] as $theme => $type) {
|
||||
$funcs[] = views_theme_functions($theme, $this->view, $this->display);
|
||||
}
|
||||
}
|
||||
return $funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the plugin is correct and can be saved.
|
||||
*
|
||||
* @return
|
||||
* An array of error strings to tell the user what is wrong with this
|
||||
* plugin.
|
||||
*/
|
||||
function validate() { return array(); }
|
||||
|
||||
/**
|
||||
* Returns the summary of the settings in the display.
|
||||
*/
|
||||
function summary_title() {
|
||||
return t('Settings');
|
||||
}
|
||||
/**
|
||||
* Return the human readable name of the display.
|
||||
*
|
||||
* This appears on the ui beside each plugin and beside the settings link.
|
||||
*/
|
||||
function plugin_title() {
|
||||
if (isset($this->definition['short title'])) {
|
||||
return check_plain($this->definition['short title']);
|
||||
}
|
||||
return check_plain($this->definition['title']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enabled display extenders.
|
||||
*/
|
||||
function views_get_enabled_display_extenders() {
|
||||
$enabled = array_filter(variable_get('views_display_extenders', array()));
|
||||
$options = views_fetch_plugin_names('display_extender');
|
||||
foreach ($options as $name => $plugin) {
|
||||
$enabled[$name] = $name;
|
||||
}
|
||||
|
||||
return $enabled;
|
||||
}
|
2657
sites/all/modules/views/includes/view.inc
Normal file
2657
sites/all/modules/views/includes/view.inc
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user