Now all modules are in core modules folder

This commit is contained in:
Manuel Cillero 2017-08-08 12:14:45 +02:00
parent 5ba1cdfa0b
commit 05b6a91b0c
1907 changed files with 0 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,178 @@
<?php
/**
* @file ajax.inc
*
* Handles the server side AJAX interactions of Views.
*
* @defgroup ajax Views ajax library
* @{
*/
/**
* 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']) ? $_REQUEST['view_path'] : NULL;
$dom_id = isset($_REQUEST['view_dom_id']) ? intval($_REQUEST['view_dom_id']) : NULL;
$pager_element = isset($_REQUEST['pager_element']) ? intval($_REQUEST['pager_element']) : NULL;
views_include('ajax');
$object = new stdClass();
$object->status = FALSE;
$object->display = '';
$arg = explode('/', $_REQUEST['view_path']);
if ($arg[0] == 'admin' || (variable_get('node_admin_theme', '0') && $arg[0] == 'node' && ($arg[1] == 'add' || $arg[2] == 'edit'))) {
global $custom_theme;
$custom_theme = variable_get('admin_theme', '0');
drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
}
// Load the view.
if ($view = views_get_view($name)) {
if ($view->access($display_id)) {
// Fix 'q' for paging.
if (!empty($path)) {
$_GET['q'] = $path;
}
// Override the display's pager_element with the one actually used.
if (isset($pager_element)) {
$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;
$object->status = TRUE;
$object->display .= $view->preview($display_id, $args);
// Get the title after the preview call, to let it set
// up both the view's current display and arguments
$object->title = $view->get_title();
// Register the standard JavaScript callback.
$object->__callbacks = array('Drupal.Views.Ajax.ajaxViewResponse');
// Allow other modules to extend the data returned.
drupal_alter('ajax_data', $object, 'views', $view);
}
}
$messages = theme('status_messages');
$object->messages = $messages ? '<div class="views-messages">' . $messages . '</div>' : '';
views_ajax_render($object);
}
}
/**
* Simple render function to make sure output is what we want.
*
* This function renders an object into JSON, and that object contains
* commands to the ajax response parser on the other side. The actual
* commands that can be sent are completely dependent upon the client
* javascript parser, which can be anything, but this function assumes
* that 'display', at least, will be displayed in some kind of ajax
* spot or popup.
*/
function views_ajax_render($output = NULL, $title = NULL, $url = NULL, $js = NULL) {
if (empty($output)) {
$output->display = t('Server reports invalid input error.');
$output->title = t('Error');
}
elseif (!is_object($output)) {
$temp = new stdClass();
$temp->display = $output;
$temp->title = $title;
$temp->url = $url;
$output = $temp;
}
if (!empty($js)) {
$output->js = $js;
}
drupal_json($output);
exit;
}
/**
* 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) {
// This won't override settings already in.
$form_state += array(
'rerender' => FALSE,
'no_redirect' => !empty($form_state['ajax']),
);
$output = drupal_build_form($form_id, $form_state);
if (!empty($form_state['ajax']) && empty($form_state['executed'])) {
// If the form didn't execute and we're using ajax, build up a
// json command object to render.
$object = new stdClass();
$object->display = '';
if ($messages = theme('status_messages')) {
$object->display = '<div class="views-messages">' . $messages . '</div>';
}
$object->display .= $output;
$object->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';
$object->title = theme('advanced_help_topic', $module, $form_state['help_topic']) . $object->title;
}
$object->url = empty($form_state['url']) ? url($_GET['q'], array('absolute' => TRUE)) : $form_state['url'];
$object->js = empty($form_state['js settings']) ? NULL : $form_state['js settings'];
if (!empty($form_state['#section'])) {
$object->hilite = '.' . views_ui_item_css($form_state['#section']);
}
$output = $object;
}
// 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 tags. We only autocomplete the last tag.
$array = drupal_explode_tags($string);
// Fetch last tag
$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_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $last_string, 0, 10);
while ($account = db_fetch_object($result)) {
$n = $account->name;
// Commas and quotes in terms are special cases, so encode 'em.
if (strpos($account->name, ',') !== FALSE || strpos($account->name, '"') !== FALSE) {
$n = '"' . str_replace('"', '""', $account->name) . '"';
}
$matches[$prefix . $n] = check_plain($account->name);
}
}
drupal_json($matches);
}
/**
* @}
*/

View file

@ -0,0 +1,108 @@
<?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) {
$message = '';
if (count($messages) > 1) {
$message = theme('item_list', $messages);
}
else if ($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);
}
/**
* Implementation of 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');
}
return $ret;
}

View file

@ -0,0 +1,127 @@
<?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();
/**
* Information about options for all kinds of purposes will be held here.
* @code
* 'option_name' => array(
* - 'default' => default value,
* - 'translatable' => TRUE/FALSE (wrap in t() on export if true),
* - 'contains' => array of items this contains, with its own defaults, etc.
* If contains is set, the default will be ignored and assumed to
* be array()
*
* ),
* @endcode
* Each option may have any of the following functions:
* - export_option_OPTIONNAME -- Special export handling if necessary.
* - translate_option_OPTIONNAME -- Special handling for translating data
* within the option, if necessary.
*/
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.
*/
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, $check = TRUE) {
if ($check && !is_array($options)) {
return;
}
if (!isset($definition)) {
$definition = $this->option_definition();
}
foreach ($options as $key => $value) {
if (is_array($value)) {
if (!isset($storage[$key]) || !is_array($storage[$key])) {
$storage[$key] = array();
}
$this->unpack_options($storage[$key], $value, isset($definition[$key]['contains']) ? $definition[$key]['contains'] : array(), FALSE);
}
else if (!empty($definition[$key]['translatable']) && !empty($value)) {
$storage[$key] = t($value);
}
else {
$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);
}
}
}

View file

@ -0,0 +1,293 @@
<?php
/**
* @file cache.inc
*
* Functions to load Views' data so that it knows what is available to
* build queries from.
*/
/**
* Load views files on behalf of modules.
*/
function _views_include_handlers() {
views_module_include('views.inc');
}
/**
* Load default views files on behalf of modules.
*/
function _views_include_default_views() {
views_module_include('views_default.inc');
}
/**
* Fetch Views' data from the cache
*/
function _views_fetch_data($table = NULL) {
static $cache = NULL;
if (!isset($cache)) {
$start = views_microtime();
// NOTE: This happens whether we retrieve them from cache or otherwise.
views_include_handlers();
$data = views_cache_get('views_data', TRUE);
if (!empty($data->data)) {
$cache = $data->data;
}
if (empty($cache)) {
$cache = module_invoke_all('views_data');
foreach (module_implements('views_data_alter') as $module) {
$function = $module . '_views_data_alter';
$function($cache);
}
views_cache_set('views_data', $cache, TRUE);
}
vpr('Views data build time: ' . (views_microtime() - $start) * 1000 . ' ms');
}
if (!$table) {
return $cache;
}
if (isset($cache[$table])) {
return $cache[$table];
}
// Return an empty array if there is no match.
return array();
}
/**
* Fetch the plugin data from cache.
*/
function _views_fetch_plugin_data($type = NULL, $plugin = NULL) {
static $cache = NULL;
if (!isset($cache)) {
$start = views_microtime();
views_include_handlers();
$cache = views_discover_plugins();
vpr('Views plugins build time: ' . (views_microtime() - $start) * 1000 . ' ms');
}
if (!$type && !$plugin) {
return $cache;
}
else if (!$plugin) {
// Not in the if above so the else below won't run
if (isset($cache[$type])) {
return $cache[$type];
}
}
else if (isset($cache[$type][$plugin])) {
return $cache[$type][$plugin];
}
// Return an empty array if there is no match.
return array();
}
/**
* Scan all modules for default views and rebuild the default views cache.
*
* @return An associative array of all known default views.
*/
function _views_discover_default_views() {
static $cache = NULL;
if (!isset($cache)) {
$index = views_cache_get('views_default_views_index', TRUE);
// Retrieve each cached default view
if (isset($index->data) && is_array($index->data)) {
$cache = array();
foreach ($index->data as $view_name) {
$data = views_cache_get('views_default:' . $view_name, TRUE);
if (isset($data->data) && is_object($data->data)) {
$cache[$view_name] = $data->data;
}
}
}
// If missing index, rebuild the cache
else {
views_include_default_views();
$cache = array();
foreach(module_implements('views_default_views') as $module) {
$results = call_user_func($module . "_views_default_views");
if (!empty($results) && is_array($results)) {
foreach($results as $name => $view) {
// Only views with a sufficiently high api version are eligible.
if (!empty($view->api_version) && $view->api_version >= 2) {
// Do not cache dead handlers.
$view->destroy();
if (!isset($cache[$name])) {
$cache[$name] = $view;
}
else {
watchdog('view', "View name '@name' is already taken", array('@name' => $name), WATCHDOG_ERROR);
}
}
}
}
}
// Allow modules to modify default views before they are cached.
drupal_alter('views_default_views', $cache);
// Cache the index
$index = array_keys($cache);
views_cache_set('views_default_views_index', $index, TRUE);
// Cache each view
foreach ($cache as $name => $view) {
views_cache_set('views_default:' . $name, $view, TRUE);
}
}
}
return $cache;
}
/**
* 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 $cid
* The cache ID of the data to retrieve.
* @param $use_language
* If TRUE, the data will be requested specific to the currently active language.
*/
function views_cache_get($cid, $use_language = FALSE) {
global $language;
if (variable_get('views_skip_cache', FALSE)) {
return 0;
}
if ($use_language) {
$cid .= ':' . $language->language;
}
return cache_get($cid, 'cache_views');
}
/**
* @defgroup views_object_cache Non-volatile cache storage
* @{
* The non-volatile object cache is used to store an object while it is
* being edited, so that we don't have to save until we're completely
* done. The cache should be 'cleaned' on a regular basis, meaning to
* remove old objects from the cache, but otherwise the data in this
* cache must remain stable, as it includes unsaved changes.
*/
/**
* Get an object from the non-volatile Views cache.
*
* This function caches in memory as well, so that multiple calls to this
* will not result in multiple database reads.
*
* @param $obj
* A 32 character or less string to define what kind of object is being
* stored; primarily this is used to prevent collisions.
* @param $name
* The name of the view (or other object) being stored.
* @param $skip_cache
* Skip the memory cache, meaning this must be read from the db again.
*
* @return
* The data that was cached.
*/
function views_object_cache_get($obj, $name, $skip_cache = FALSE) {
static $cache = array();
$key = "$obj:$name";
if ($skip_cache) {
unset($cache[$key]);
}
if (!array_key_exists($key, $cache)) {
$data = db_fetch_object(db_query("SELECT * FROM {views_object_cache} WHERE sid = '%s' AND obj = '%s' AND name = '%s'", session_id(), $obj, $name));
if ($data) {
$cache[$key] = unserialize($data->data);
}
}
return isset($cache[$key]) ? $cache[$key] : NULL;
}
/**
* Store an object in the non-volatile Views cache.
*
* @param $obj
* A 32 character or less string to define what kind of object is being
* stored; primarily this is used to prevent collisions.
* @param $name
* The name of the view (or other object) being stored.
* @param $cache
* The object to be cached. This will be serialized prior to writing.
*/
function views_object_cache_set($obj, $name, $cache) {
views_object_cache_clear($obj, $name);
db_query("INSERT INTO {views_object_cache} (sid, obj, name, data, updated) VALUES ('%s', '%s', '%s', '%s', %d)", session_id(), $obj, $name, serialize($cache), time());
}
/**
* Remove an object from the non-volatile Views cache
*
* @param $obj
* A 32 character or less string to define what kind of object is being
* stored; primarily this is used to prevent collisions.
* @param $name
* The name of the view (or other object) being stored.
*/
function views_object_cache_clear($obj, $name) {
db_query("DELETE FROM {views_object_cache} WHERE sid = '%s' AND obj = '%s' AND name = '%s'", session_id(), $obj, $name);
}
/**
* Remove all objects in the object cache that are older than the
* specified age.
*
* @param $age
* The minimum age of objects to remove, in seconds. For example, 86400 is
* one day. Defaults to 7 days.
*/
function views_object_cache_clean($age = NULL) {
if (empty($age)) {
$age = 86400 * 7; // 7 days
}
db_query("DELETE FROM {views_object_cache} WHERE updated < %d", time() - $age);
}
/**
* @}
*/

View file

@ -0,0 +1,548 @@
<?php
/**
* @file convert.inc
*
* Contains forms and routines to convert older views to newer views.
*/
/**
* Page callback for the tools - Views 1 convert page
*/
function views_ui_admin_convert() {
if (!db_table_exists('view_view')) {
return t('There are no Views 1 views stored in the database to convert.');
}
$items = array();
$sorts = array();
$header = array(
array('data' => t('View name'), 'field' => 'name', 'sort' => 'asc'),
array('data' => t('Description')),
array('data' => t('Operations')),
);
$current_views = views_get_all_views();
$result = db_query("SELECT v.* FROM {view_view} v");
while ($view = db_fetch_object($result)) {
$ops = array();
if (!isset($current_views[$view->name])) {
$ops[] = l(t('Convert'), "admin/build/views1/convert/$view->name");
}
else {
$ops[] = t('Converted');
}
$ops[] = l(t('Delete'), "admin/build/views1/delete/$view->name");
$item = array();
$item[] = check_plain($view->name);
$item[] = check_plain($view->description);
$item[] = implode(' | ', $ops);
$items[] = $item;
$ts = tablesort_init($header);
switch ($ts['sql']) {
case 'name':
default:
$sorts[] = $item[0];
break;
case 'title':
$sorts[] = $item[1];
break;
}
}
if (!empty($ts)) {
if (strtolower($ts['sort']) == 'desc') {
arsort($sorts);
}
else {
asort($sorts);
}
}
$i = array();
foreach ($sorts as $id => $title) {
$i[] = $items[$id];
}
$output = t('The table below lists Views version 1 views that are stored in the database. You can either convert them to work in Views version 2, or delete them. The views are convertible only if there is no Views 2 view with the same name.');
$output .= theme('table', $header, $i);
$output .= drupal_get_form('views_ui_convert_cleanup_form');
return $output;
}
/**
* Provide form to clean up Views 1 tables.
*/
function views_ui_convert_cleanup_form() {
$form['verify'] = array(
'#type' => 'checkbox',
'#title' => t('Remove all Views 1 tables'),
'#description' => t('Check this box and then click clean up to drop all Views 1 tables. Warning: this operation will not be reversible! Do this only if you are sure you no longer need this data.'),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Clean up'),
);
return $form;
}
function views_ui_convert_cleanup_form_submit($form, $form_state) {
if (empty($form_state['values']['verify'])) {
drupal_set_message('Please check the box to verify you want to destroy your Views 1 table data.');
return;
}
$ret = array();
if (db_table_exists('view_view')) {
db_drop_table($ret, 'view_view');
}
if (db_table_exists('view_sort')) {
db_drop_table($ret, 'view_sort');
}
if (db_table_exists('view_argument')) {
db_drop_table($ret, 'view_argument');
}
if (db_table_exists('view_tablefield')) {
db_drop_table($ret, 'view_tablefield');
}
if (db_table_exists('view_filter')) {
db_drop_table($ret, 'view_filter');
}
if (db_table_exists('view_exposed_filter')) {
db_drop_table($ret, 'view_exposed_filter');
}
drupal_set_message(t('All Views 1 tables have been removed.'));
}
/**
* Page callback for the tools - Views 1 convert page
*/
function views_ui_convert1($name) {
$old = views1_load($name);
if (!$old) {
return t('Unable to find view.');
}
$view = views1_import($old);
if ($view) {
views_ui_cache_set($view);
drupal_goto('admin/build/views/edit/' . $view->name);
}
else {
return t('Unable to convert view.');
}
}
/**
* Page to delete a Views 1 view.
*/
function views_ui_delete1_confirm(&$form_state, $vid) {
$form_state['vid'] = $vid;
$form = array();
$cancel = 'admin/build/views/tools/convert';
if (!empty($_REQUEST['cancel'])) {
$cancel = $_REQUEST['cancel'];
}
return confirm_form($form,
t('Are you sure you want to delete the view %name?', array('%name' => $view->name)),
$cancel,
t('This action cannot be undone.'),
t('Delete'),
t('Cancel'));
}
/**
* Submit handler to delete a view.
*/
function views_ui_delete1_confirm_submit(&$form, &$form_state) {
views1_delete($form_state['vid']);
drupal_set_message(t('The view has been deleted'));
$form_state['redirect'] = 'admin/build/views/tools/convert';
}
/**
* Convert a Views 1 view to a Views 2 view.
*/
function views1_import($imported) {
views_include_handlers();
views_module_include('views_convert.inc');
$view = views_new_view();
$view->name = $imported->name;
$view->description = $imported->description;
if (!empty($imported->page) && !empty($imported->url)) {
$page_display = $view->add_display('page');
}
if (!empty($imported->block)) {
$block_display = $view->add_display('block');
}
$view->init_display();
$handler = &$view->display['default']->handler;
$handler->set_option('title', $imported->page_title);
$handler->set_option('header', $imported->page_header);
$handler->set_option('header_format', $imported->page_header_format);
$handler->set_option('footer', $imported->page_footer);
$handler->set_option('footer_format', $imported->page_footer_format);
$handler->set_option('empty', $imported->page_empty);
$handler->set_option('empty_format', $imported->page_empty_format);
$handler->set_option('use_pager', $imported->use_pager);
$handler->set_option('items_per_page', $imported->nodes_per_page);
$handler->set_option('pager_element', 0);
$handler->set_option('offset', 0);
$access = array('type' => 'none', 'role' => array(), 'perm' => '');
if ($imported->access) {
$access['type'] = 'role';
$access['role'] = drupal_map_assoc($imported->access);
}
$handler->set_option('access', $access);
if (!empty($imported->page) && !empty($imported->url)) {
$handler = &$view->display[$page_display]->handler;
$url = str_replace('$arg', '%', $imported->url);
$handler->set_option('path', $url);
if ($imported->menu) {
$menu = array('type' => 'normal');
if ($imported->menu_tab) {
$menu['type'] = 'tab';
}
if ($imported->menu_tab_default) {
$menu['type'] = 'default tab';
}
$menu['title'] = $imported->menu_title ? $imported->menu_title : $imported->page_title;
$handler->set_option('menu', $menu);
if ($menu['type'] == 'default tab') {
$tab_options = array('type' => 'none');
switch ($imported->menu_tab_default_parent_type) {
case 'tab':
case 'normal':
$tab_options['type'] = $imported->menu_tab_default_parent_type;
break;
}
}
$tab_options['title'] = $imported->menu_parent_title;
$tab_options['weight'] = $imported->menu_parent_tab_weight;
$handler->set_option('tab_options', $tab_options);
}
}
views1_convert_style($view, $handler, $imported->page_type);
if (!empty($imported->block)) {
$handler = &$view->display[$block_display]->handler;
if (!empty($imported->block_title)) {
if (!empty($imported->page)) {
$handler->set_override('title');
}
$handler->set_option('title', $imported->block_title);
}
if (!empty($imported->page)) {
$handler->set_override('use_pager');
}
$handler->set_option('use_pager', FALSE);
if ($imported->nodes_per_block != $imported->nodes_per_page) {
$handler->set_option('items_per_page', $imported->nodes_per_block);
$handler->set_option('offset', 0);
}
if (empty($imported->block_use_page_header)) {
if (!empty($imported->page)) {
$handler->set_override('header');
}
if (!empty($imported->block_header)) {
$handler->set_option('header', $imported->block_header);
$handler->set_option('header_format', $imported->block_header_format);
}
}
if (empty($imported->block_use_page_footer)) {
if (!empty($imported->page)) {
$handler->set_override('footer');
}
if (!empty($imported->block_footer)) {
$handler->set_option('footer', $imported->block_footer);
$handler->set_option('footer_format', $imported->block_footer_format);
}
}
if (empty($imported->block_use_page_empty)) {
if (!empty($imported->page)) {
$handler->set_override('empty');
}
if (!empty($imported->block_empty)) {
$handler->set_option('empty', $imported->block_empty);
$handler->set_option('empty_format', $imported->block_empty_format);
}
}
$handler->set_option('use_more', $imported->block_more);
if (!empty($imported->page)) {
$handler->set_override('style_plugin');
}
views1_convert_style($view, $handler, $imported->block_type);
}
// For each of the fields, arguments, filters, and sorts in the old view,
// check if a handler for this item exists in Views 2 and add it,
// then see if any other modules want to adapt it using hook_views_convert().
foreach ($imported->field as $field) {
$id = $view->add_item('default', 'field', $field['tablename'], $field['field'], array('label' => $field['label']));
if ($view->display_handler->get_option('style_plugin') == 'table') {
$options = $view->display_handler->get_option('style_options');
if (!empty($field['sortable'])) {
$options['info'][$id]['sortable'] = TRUE;
if (!empty($field['defaultsort'])) {
$options['default'] = $id;
}
}
$view->display_handler->set_option('style_options', $options);
}
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', 'default', 'field', $view, $field, $id);
}
}
foreach ($imported->sort as $field) {
$id = $view->add_item('default', 'sort', $field['tablename'], $field['field'], array('order' => $field['sortorder']));
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', 'default', 'sort', $view, $field, $id);
}
}
$actions = array('ignore', 'not found', 'ignore', 'summary asc', 'summary asc', 'summary desc', 'summary asc', 'empty');
foreach ($imported->argument as $id => $field) {
if (!empty($imported->view_args_php)) {
$field['argoptions']['default_action'] = 'default';
$field['argoptions']['default_argument_type'] = 'php';
$field['argoptions']['default_argument_php'] = '$args = eval(\''. str_replace("'", "\\'", $imported->view_args_php) .'\');'."\n";
$field['argoptions']['default_argument_php'] .= 'if (isset($args['. $field['position'] .'])) {'."\n";
$field['argoptions']['default_argument_php'] .= ' return $args['. $field['position'] .'];'."\n";
$field['argoptions']['default_argument_php'] .= '}';
$field['argoptions']['validate_fail'] = $actions[$field['argdefault']];
}
else {
$field['argoptions']['default_action'] = $actions[$field['argdefault']];
}
if (!empty($field['title'])) {
$field['argoptions']['title'] = $field['title'];
}
if (!empty($field['wildcard'])) {
$field['argoptions']['wildcard'] = $field['wildcard'];
}
if (!empty($field['wildcard_substitution'])) {
$field['argoptions']['wildcard_substitution'] = $field['wildcard_substitution'];
}
// Arguments didn't used to be identified by table.name so we just have to
// leave that out.
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', 'default', 'argument', $view, $field, NULL);
}
}
foreach ($imported->filter as $key => $field) {
$options = $field['value'] == '' ? array() : array('value' => $field['value']);
$id = $view->add_item('default', 'filter', $field['tablename'], $field['field'], $options);
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', 'default', 'filter', $view, $field, $id);
}
// Store the id in the exposed filter if there is one.
foreach ($imported->exposed_filter as $key => $filter) {
if ($field['tablename'] == $filter['tablename'] && $field['field'] == $filter['field']) {
$imported->exposed_filter[$key]['id'] = $id;
}
}
}
// Exposed filters now get added to the filter array, not as a separate array.
$count = 0;
foreach ($imported->exposed_filter as $field) {
$id = $field['id'];
$item = $view->get_item('default', 'filter', $id);
if (views_get_handler($item['table'], $item['field'], 'filter')) {
$item['exposed'] = TRUE;
// Use the count to emulate the old, hardcoded filter naming.
$item['expose']['identifier'] = 'filter' . $count;
$item['expose']['label'] = $field['label'];
$item['expose']['operator'] = $field['operator'] ? 'op' . $count : '';
$item['expose']['optional'] = $field['optional'];
$item['expose']['single'] = $field['single'];
$view->set_item('default', 'filter', $id, $item);
}
$count++;
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', 'default', 'exposed_filter', $view, $field, $id);
}
}
return $view;
}
function views1_convert_style(&$view, &$handler, $type) {
switch ($type) {
case 'list':
$handler->set_option('style_plugin', 'list');
$handler->set_option('style_options', array('type' => 'ul'));
$handler->set_option('row_plugin', 'fields');
break;
case 'node':
$handler->set_option('row_plugin', 'node');
$handler->set_option('row_options', array('teaser' => FALSE, 'links' => TRUE));
break;
case 'teaser':
$handler->set_option('row_plugin', 'node');
$handler->set_option('row_options', array('teaser' => TRUE, 'links' => TRUE));
break;
case 'table':
$options = array();
$options['columns'] = array();
$options['default'] = '';
$options['info'] = array();
$options['override'] = FALSE;
$options['order'] = 'asc';
$handler->set_option('style_plugin', 'table');
$handler->set_option('style_options', $options);
break;
default:
// Ask around if anybody else knows.
foreach (module_implements('views_convert') as $module) {
module_invoke($module, 'views_convert', $handler->display->id, 'style', $view, $type);
}
}
}
/**
* Load a version 1 view from the database.
*
*/
function views1_load($arg) {
static $cache = array();
$which = is_numeric($arg) ? 'vid' : 'name';
if (isset($cache[$which][$arg])) {
return $cache[$which][$arg];
}
$where = (is_numeric($arg) ? "v.vid = %d" : "v.name = '%s'");
$view = db_fetch_object(db_query("SELECT v.* FROM {view_view} v WHERE $where", $arg));
if (!$view->name) {
return NULL;
}
$view->access = ($view->access ? explode(', ', $view->access) : array());
// load the sorting criteria too.
$result = db_query("SELECT * FROM {view_sort} vs WHERE vid = $view->vid ORDER BY position ASC");
$view->sort = array();
while ($sort = db_fetch_array($result)) {
if (substr($sort['field'], 0, 2) == 'n.') {
$sort['field'] = 'node' . substr($sort['field'], 1);
}
$sort['id'] = $sort['field'];
$bits = explode('.', $sort['field']);
$sort['tablename'] = $bits[0];
$sort['field'] = $bits[1];
$view->sort[$sort['position']] = $sort;
}
$result = db_query("SELECT * FROM {view_argument} WHERE vid = $view->vid ORDER BY position ASC");
$view->argument = array();
while ($arg = db_fetch_array($result)) {
$arg['id'] = $arg['type'];
$view->argument[$arg['position']] = $arg;
}
$result = db_query("SELECT * FROM {view_tablefield} WHERE vid = $view->vid ORDER BY position ASC");
$view->field = array();
while ($arg = db_fetch_array($result)) {
if ($arg['tablename'] == 'n') {
$arg['tablename'] = 'node';
}
$arg['id'] = $arg['fullname'] = "$arg[tablename].$arg[field]";
$arg['queryname'] = "$arg[tablename]_$arg[field]";
$view->field[] = $arg;
}
$result = db_query("SELECT * FROM {view_filter} WHERE vid = $view->vid ORDER BY position ASC");
// TODO - Is it safe to ignore this $filters variable? This function depends
// on lots of additional code needed to call hook_implements and construct
// all the views tables, so using it will add a lot of code to this file.
//$filters = _views_get_filters();
$view->filter = array();
while ($filter = db_fetch_array($result)) {
if (substr($filter['field'], 0, 2) == 'n.') {
$filter['field'] = 'node' . substr($filter['field'], 1);
}
if ($filter['operator'] == 'AND' ||
$filter['operator'] == 'OR' ||
$filter['operator'] == 'NOR') {
// TODO - need another way to identify this type of filter
// without being able to call hook_implements().
//|| $filters[$filter['field']]['value-type'] == 'array' ) {
if ($filter['value'] !== NULL && $filter['value'] !== '') {
$filter['value'] = explode(',', $filter['value']);
}
else {
$filter['value'] = array();
}
}
$filter['id'] = $filter['field'];
$bits = explode('.', $filter['field']);
$filter['tablename'] = $bits[0];
$filter['field'] = $bits[1];
$view->filter[$filter['position']] = $filter;
}
$result = db_query("SELECT * FROM {view_exposed_filter} WHERE vid = $view->vid ORDER BY position ASC");
$view->exposed_filter = array();
while ($arg = db_fetch_array($result)) {
$arg['id'] = $arg['field'];
$view->exposed_filter[] = $arg;
}
$cache['vid'][$view->vid] = $view;
$cache['name'][$view->name] = $view;
return $view;
}
/**
* Delete a version 1 view from the database.
*
*/
function views1_delete($arg) {
static $cache = array();
$where = (is_numeric($arg) ? "v.vid = %d" : "v.name = '%s'");
$view = db_fetch_object(db_query("SELECT v.* FROM {view_view} v WHERE $where", $arg));
if (!$view->name) {
return NULL;
}
$result = db_query("DELETE FROM {view_sort} WHERE vid = $view->vid");
$result = db_query("DELETE FROM {view_argument} WHERE vid = $view->vid");
$result = db_query("DELETE FROM {view_tablefield} WHERE vid = $view->vid");
$result = db_query("DELETE FROM {view_filter} WHERE vid = $view->vid");
$result = db_query("DELETE FROM {view_exposed_filter} WHERE vid = $view->vid");
$result = db_query("DELETE FROM {view_view} WHERE vid = $view->vid");
}

View file

@ -0,0 +1,300 @@
<?php
/**
* @file form.inc
* Views' replacements for Drupal's form functions.
*
*/
function _drupal_build_form($form_id, &$form_state) {
// Ensure that we have some defaults.
// These are defaults only; if already set they will not be overridden.
$form_state += array('storage' => NULL, 'submitted' => FALSE, 'input' => $_POST, 'method' => 'post');
$args = isset($form_state['args']) ? $form_state['args'] : array();
$cacheable = FALSE;
if (isset($_SESSION['batch_form_state'])) {
// We've been redirected here after a batch processing : the form has
// already been processed, so we grab the post-process $form_state value
// and move on to form display. See _batch_finished() function.
$form_state = $_SESSION['batch_form_state'];
unset($_SESSION['batch_form_state']);
}
else {
// If the incoming $_POST contains a form_build_id, we'll check the
// cache for a copy of the form in question. If it's there, we don't
// have to rebuild the form to proceed. In addition, if there is stored
// form_state data from a previous step, we'll retrieve it so it can
// be passed on to the form processing code.
if (isset($_POST['form_id']) && $_POST['form_id'] == $form_id && !empty($_POST['form_build_id'])) {
$form = form_get_cache($_POST['form_build_id'], $form_state);
if (!empty($form['#no_cache']) || empty($form)) {
unset($form);
}
}
// If the previous bit of code didn't result in a populated $form
// object, we're hitting the form for the first time and we need
// to build it from scratch.
if (!isset($form)) {
$form_state['post'] = $form_state['input'];
// Use a copy of the function's arguments for manipulation
$args_temp = $args;
$args_temp[0] = &$form_state;
array_unshift($args_temp, $form_id);
$form = call_user_func_array('drupal_retrieve_form', $args_temp);
$form_build_id = 'form-' . md5(mt_rand());
$form['#build_id'] = $form_build_id;
if ($form_state['method'] == 'get' && !isset($form['#method'])) {
$form['#method'] = 'get';
}
drupal_prepare_form($form_id, $form, $form_state);
// Store a copy of the unprocessed form for caching and indicate that it
// is cacheable if #cache will be set.
$original_form = $form;
$cacheable = TRUE;
unset($form_state['post']);
}
$form['#post'] = $form_state['input'];
// Now that we know we have a form, we'll process it (validating,
// submitting, and handling the results returned by its submission
// handlers. Submit handlers accumulate data in the form_state by
// altering the $form_state variable, which is passed into them by
// reference.
drupal_process_form_new($form_id, $form, $form_state);
// If we were told not to redirect, but not told to re-render, return
// here.
if (!empty($form_state['executed']) && empty($form_state['rerender'])) {
return;
}
if ($cacheable && !empty($form['#cache']) && empty($form['#no_cache'])) {
// Caching is done past drupal_process_form so #process callbacks can
// set #cache. By not sending the form state, we avoid storing
// $form_state['storage'].
form_set_cache($form_build_id, $original_form, NULL);
}
}
// Most simple, single-step forms will be finished by this point --
// drupal_process_form() usually redirects to another page (or to
// a 'fresh' copy of the form) once processing is complete. If one
// of the form's handlers has set $form_state['redirect'] to FALSE,
// the form will simply be re-rendered with the values still in its
// fields.
//
// If $form_state['storage'] or $form_state['rebuild'] have been
// set by any submit or validate handlers, however, we know that
// we're in a complex multi-part process of some sort and the form's
// workflow is NOT complete. We need to construct a fresh copy of
// the form, passing in the latest $form_state in addition to any
// other variables passed into drupal_get_form().
if (!empty($form_state['rebuild']) || !empty($form_state['storage'])) {
$form = drupal_rebuild_form_new($form_id, $form_state, $args);
}
// If we haven't redirected to a new location by now, we want to
// render whatever form array is currently in hand.
return drupal_render_form($form_id, $form);
}
/**
* Views' replacement of drupal_rebuild_form.
*
* This change merely respects a form's wishes not to be cached.
*/
function drupal_rebuild_form_new($form_id, &$form_state, $args, $form_build_id = NULL) {
// Remove the first argument. This is $form_id.when called from
// drupal_get_form and the original $form_state when called from some AHAH
// callback. Neither is needed. After that, put in the current state.
$args[0] = &$form_state;
// And the form_id.
array_unshift($args, $form_id);
$form = call_user_func_array('drupal_retrieve_form', $args);
if (!isset($form_build_id)) {
// We need a new build_id for the new version of the form.
$form_build_id = 'form-' . md5(mt_rand());
}
$form['#build_id'] = $form_build_id;
drupal_prepare_form($form_id, $form, $form_state);
if (empty($form['#no_cache'])) {
// Now, we cache the form structure so it can be retrieved later for
// validation. If $form_state['storage'] is populated, we'll also cache
// it so that it can be used to resume complex multi-step processes.
form_set_cache($form_build_id, $form, $form_state);
}
// Originally this called drupal_process_form, but all that happens there
// is form_builder and then submission; and the rebuilt form is not
// allowed to submit. Therefore, just do this:
$form['#post'] = $form_state['input'];
$form = form_builder($form_id, $form, $form_state);
return $form;
}
/**
* Views' replacement for drupal_process_form that accepts commands
* not to redirect, as well as forcing processing of 'get' method forms.
*/
function drupal_process_form_new($form_id, &$form, &$form_state) {
// submitting, and handling the results returned by its submission
// handlers. Submit handlers accumulate data in the form_state by
// altering the $form_state variable, which is passed into them by
// reference.
$form_state['values'] = array();
// With $_GET, these forms are always submitted.
if ($form_state['method'] == 'get') {
if (!isset($form['#post']['form_build_id'])) {
$form['#post']['form_build_id'] = $form['#build_id'];
}
if (!isset($form['#post']['form_id'])) {
$form['#post']['form_id'] = $form_id;
}
if (!isset($form['#post']['form_token']) && isset($form['#token'])) {
$form['#post']['form_token'] = drupal_get_token($form['#token']);
}
}
$form = form_builder($form_id, $form, $form_state);
// Only process the form if it is programmed or the form_id coming
// from the POST data is set and matches the current form_id.
if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {
drupal_validate_form_new($form_id, $form, $form_state);
// form_clean_id() maintains a cache of element IDs it has seen,
// so it can prevent duplicates. We want to be sure we reset that
// cache when a form is processed, so scenerios that result in
// the form being built behind the scenes and again for the
// browser don't increment all the element IDs needlessly.
form_clean_id(NULL, TRUE);
if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) {
$form_state['redirect'] = NULL;
form_execute_handlers('submit', $form, $form_state);
// We'll clear out the cached copies of the form and its stored data
// here, as we've finished with them. The in-memory copies are still
// here, though.
if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
cache_clear_all('form_' . $form_state['values']['form_build_id'], 'cache_form');
cache_clear_all('storage_' . $form_state['values']['form_build_id'], 'cache_form');
}
// If batches were set in the submit handlers, we process them now,
// possibly ending execution. We make sure we do not react to the batch
// that is already being processed (if a batch operation performs a
// drupal_execute).
if ($batch =& batch_get() && !isset($batch['current_set'])) {
// The batch uses its own copies of $form and $form_state for
// late execution of submit handers and post-batch redirection.
$batch['form'] = $form;
$batch['form_state'] = $form_state;
$batch['progressive'] = !$form['#programmed'];
batch_process();
// Execution continues only for programmatic forms.
// For 'regular' forms, we get redirected to the batch processing
// page. Form redirection will be handled in _batch_finished(),
// after the batch is processed.
}
// If no submit handlers have populated the $form_state['storage']
// bundle, and the $form_state['rebuild'] flag has not been set,
// we're finished and should redirect to a new destination page
// if one has been set (and a fresh, unpopulated copy of the form
// if one hasn't). If the form was called by drupal_execute(),
// however, we'll skip this and let the calling function examine
// the resulting $form_state bundle itself.
if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
if (!empty($form_state['no_redirect'])) {
$form_state['executed'] = TRUE;
}
else {
drupal_redirect_form($form, $form_state['redirect']);
}
}
}
}
}
/**
* The original version of drupal_validate_form does not have an override for
* the static check to only validate a form id once. Unfortunately, we need
* to be able to overridet his.
*/
function drupal_validate_form_new($form_id, $form, &$form_state) {
static $validated_forms = array();
if (isset($validated_forms[$form_id]) && empty($form_state['must_validate'])) {
return;
}
// If the session token was set by drupal_prepare_form(), ensure that it
// matches the current user's session.
if (isset($form['#token'])) {
if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
// Setting this error will cause the form to fail validation.
form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
}
}
_form_validate($form, $form_state, $form_id);
$validated_forms[$form_id] = TRUE;
}
/**
* Process callback to add dependency to form items.
*
* Usage:
*
* On any form item, add
* - @code '#process' => 'views_process_dependency' @endcode
* - @code '#dependency' => array('id-of-form-without-the-#' => array(list, of, values, that, make, this, gadget, visible)); @endcode
*/
function views_process_dependency($element, $edit, &$form_state, &$form) {
static $dependencies;
if (isset($element['#dependency']) && !isset($dependencies[$element['#id']])) {
if (!isset($element['#dependency_count'])) {
$element['#dependency_count'] = 1;
}
if (!empty($form_state['ajax'])) {
$form_state['js settings']['viewsAjax']['formRelationships'][$element['#id']] = array('num' => $element['#dependency_count'], 'values' => $element['#dependency']);
}
else {
views_add_js('dependent');
$options['viewsAjax']['formRelationships'][$element['#id']] = array('num' => $element['#dependency_count'], 'values' => $element['#dependency']);
drupal_add_js($options, 'setting');
}
$dependencies[$element['#id']] = TRUE;
}
return $element;
}
/**
* #process callback to see if we need to check_plain() the options.
*
* Since FAPI is inconsistent, the #options are sanitized for you in all cases
* _except_ checkboxes. We have form elements that are sometimes 'select' and
* sometimes 'checkboxes', so we need decide late in the form rendering cycle
* if the options need to be sanitized before they're rendered. This callback
* inspects the type, and if it's still 'checkboxes', does the sanitation.
*/
function views_process_check_options($element, $edit, &$form_state, &$form) {
if ($element['#type'] == 'checkboxes' || $element['#type'] == 'checkbox') {
$element['#options'] = array_map('check_plain', $element['#options']);
}
return $element;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,407 @@
<?php
/**
* @file plugins.inc
* Built in plugins for Views output handling.
*
*/
/**
* Implementation of hook_views_plugins
*/
function views_views_plugins() {
$path = drupal_get_path('module', 'views') . '/js';
$plugins = array(
'module' => 'views', // This just tells our themes are elsewhere.
'display' => array(
'parent' => array(
// this isn't really a display but is necessary so the file can
// be included.
'no ui' => TRUE,
'handler' => 'views_plugin_display',
'parent' => '',
),
'default' => array(
'title' => t('Defaults'),
'help' => t('Default settings for this view.'),
'handler' => 'views_plugin_display_default',
'theme' => 'views_view',
'no ui' => TRUE,
'no remove' => TRUE,
'js' => array('misc/collapse.js', 'misc/textarea.js', 'misc/tabledrag.js', 'misc/autocomplete.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,
'use ajax' => TRUE,
'use pager' => 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,
'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',
'use ajax' => TRUE,
'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',
'parent' => 'page', // so it knows to load the page plugin .inc file
'uses hook menu' => TRUE,
'use ajax' => FALSE,
'use pager' => FALSE,
'accept attachments' => FALSE,
'admin' => t('Feed'),
'help topic' => 'display-feed',
),
),
'style' => array(
'parent' => array(
// this isn't really a display but is necessary so the file can
// be included.
'no ui' => TRUE,
'handler' => 'views_plugin_style',
'parent' => '',
),
'default' => array(
'title' => t('Unformatted'),
'help' => t('Displays rows one after another.'),
'handler' => 'views_plugin_style_default',
'theme' => 'views_view_unformatted',
'uses row plugin' => 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 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 row plugin' => 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 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',
'parent' => 'default_summary',
'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(
'parent' => array(
// this isn't really a display but is necessary so the file can
// be included.
'no ui' => TRUE,
'handler' => 'views_plugin_row',
'parent' => '',
),
'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',
),
),
'argument default' => array(
// This type of plugin does not conform to the standard and
// uses 'fixed' as the parent rather than having a separate parent.
'fixed' => array(
'title' => t('Fixed entry'),
'handler' => 'views_plugin_argument_default',
),
'php' => array(
'title' => t('PHP Code'),
'handler' => 'views_plugin_argument_default_php',
'parent' => 'fixed',
),
),
'argument validator' => array(
'parent' => array(
'no ui' => TRUE,
'handler' => 'views_plugin_argument_validate',
'parent' => '',
),
'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(
'parent' => array(
'no ui' => TRUE,
'handler' => 'views_plugin_access',
'parent' => '',
),
'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',
),
),
'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',
),
),
);
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());
// 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';
}
// 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 {
/**
* Init will be called after construct, when the plugin is attached to a
* view and a display.
*/
function init(&$view, &$display) {
$this->view = &$view;
$this->display = &$display;
}
/**
* Provide a form to edit options for this plugin.
*/
function options_form(&$form, &$form_state) { }
/**
* 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(); }
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,192 @@
<?php
/**
* @file
*
* Classes and theme functions for rendering javascript UI tabs.
*/
/**
* Contain a set of tabs as well as the ability to render them.
*
* There are three 'areas' of a tabset.
* - title: The clickable link to display the tab area. These are always visible.
* - body: The actual HTML body of the tab. Only one body is visible at a time.
* - extra: An optional decorative area around the tabs.
*/
class views_tabset {
var $tabs = array();
var $extra = '';
var $selected = NULL;
/**
* Add a tab to the tabset.
*
* @param $name
* The name of the tab; this is the internal identifier and must be
* unique within the tabset.
* @param $title
* If given, this will be the visible title of the tab. This can also
* be set via $tabset->set(). This will be the link to click on to
* view the tab.
* @param $body
* If given, this is the body of the tab itself. It will display
* when the tab title is clicked on.
*/
function add($name, $title = '', $body = '') {
if (is_object($name) && is_subclass_of($name, 'views_tab')) {
$this->add_tab($name);
}
elseif (is_array($name)) {
foreach ($name as $real_tab) {
$this->add($real_tab);
}
}
else {
$this->add_tab(new views_tab($name, $title, $body));
}
}
/**
* Add a fully realized tab object to the tabset.
*
* @param $tab
* A fully populated views_tab object.
*/
function add_tab($tab) {
$this->tabs[$tab->name] = $tab;
}
/**
* Set the values of a tab.
*
* @param $name
* The unique identifier of the tab to set.
* @param $title
* The title of the tab; this will be clickable.
* @param $body
* The HTML body of the tab.
*/
function set($name, $title, $body = NULL) {
if (empty($this->tabs[$name])) {
return $this->add($name, $title, $body);
}
$this->tabs[$name]->title = $title;
if (isset($body)) {
$this->tabs[$name]->body = $body;
}
}
/**
* Set the body of a tab.
*/
function set_body($name, $body) {
if (empty($this->tabs[$name])) {
return $this->add($name, '', $body);
}
$this->tabs[$name]->body = $body;
}
/**
* Add text to the 'extra' region of the tabset.
*/
function add_extra($text) {
$this->extra .= $text;
}
/**
* Remove a tab.
*
* @param $tab
* May be the name of the tab or a views_tab object.
*/
function remove($tab) {
if (is_string($tab)) {
unset($this->tabs[$tab]);
}
else {
unset($this->tabs[$tab->name]);
}
}
/**
* Control which tab will be selected when it is rendered.
*/
function set_selected($name) {
$this->selected = $name;
}
/**
* Output the HTML for the tabs.
*
* @return
* HTML representation of the tabs.
*/
function render() {
views_add_js('tabs');
views_add_css('views-tabs');
if (empty($this->selected)) {
$keys = array_keys($this->tabs);
$this->selected = array_shift($keys);
}
drupal_alter('views_tabset', $this);
return theme('views_tabset', $this->tabs, $this->extra, $this->selected);
}
}
/**
* An object to represent an individual tab within a tabset.
*/
class views_tab {
var $title;
var $body;
var $name;
/**
* Construct a new tab.
*/
function views_tab($name, $title, $body = NULL) {
$this->name = $name;
$this->title = $title;
$this->body = $body;
}
/**
* Generate HTML output for a tab.
*/
function render() {
return theme('views_tab', $this->body);
}
}
/**
* Render a tabset.
*
* @todo Turn this into a template.
*/
function theme_views_tabset($tabs, $extra = NULL, $selected = NULL) {
$link_output = "<div class=\"views-tabs\"><ul id=\"views-tabset\">\n";
$tab_output = "<div class=\"views-tab-area\">\n";
foreach ($tabs as $name => $tab) {
$link_output .= '<li' . ($name == $selected ? ' class="active"': '') . '><a href="#views-tab-' . $tab->name . '" id="views-tab-title-' . $tab->name . '">' . check_plain($tab->title) . '</a></li>' . "\n";
$tab_output .= '<div id="views-tab-' . $tab->name . '" class="views-tab">' . $tab->render() . "</div>\n";
}
$link_output .= "</ul>\n";
if ($extra) {
$link_output .= "<div class=\"extra\">$extra</div>\n";
}
$link_output .= "</div>\n";
$tab_output .= "</div>\n";
return '<div class="views-tabset clear-block">' . $link_output . $tab_output . '</div>';
}
/**
* Theme a simple tab.
*/
function theme_views_tab($body) {
return $body;
}

File diff suppressed because it is too large Load diff