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

View file

@ -0,0 +1,81 @@
<?php
/**
* The base plugin to handle access control.
*
* @ingroup views_access_plugins
*/
class views_plugin_access extends views_plugin {
/**
* Initialize the plugin.
*
* @param $view
* The view object.
* @param $display
* The display handler.
*/
function init(&$view, &$display) {
$this->view = &$view;
$this->display = &$display;
$this->options = array();
if (is_object($display->handler)) {
// Note: The below is read only.
$this->options = $display->handler->get_option('access');
}
}
/**
* Retrieve the default options when this is a new access
* control plugin
*/
function option_defaults(&$options) { }
/**
* Provide the default form for setting options.
*/
function options_form(&$form, &$form_state) { }
/**
* Provide the default form form for validating options
*/
function options_validate(&$form, &$form_state) { }
/**
* Provide the default form form for submitting options
*/
function options_submit(&$form, &$form_state) { }
/**
* Return a string to display as the clickable title for the
* access control.
*/
function summary_title() {
return t('Unknown');
}
/**
* Determine if the current user has access or not.
*/
function access($account) {
// default to no access control.
return TRUE;
}
/**
* Determine the access callback and arguments.
*
* This information will be embedded in the menu in order to reduce
* performance hits during menu item access testing, which happens
* a lot.
*
* @return an array; the first item should be the function to call,
* and the second item should be an array of arguments. The first
* item may also be TRUE (bool only) which will indicate no
* access control.)
*/
function get_access_callback() {
// default to no access control.
return TRUE;
}
}

View file

@ -0,0 +1,10 @@
<?php
/**
* Access plugin that provides no access control at all.
*/
class views_plugin_access_none extends views_plugin_access {
function summary_title() {
return t('Unrestricted');
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* Access plugin that provides permission-based access control.
*/
class views_plugin_access_perm extends views_plugin_access {
function access($account) {
return views_check_perm($this->options['perm'], $account);
}
function get_access_callback() {
return array('views_check_perm', array($this->options['perm']));
}
function summary_title() {
return t($this->options['perm']);
}
function option_defaults(&$options) {
$options['perm'] = 'access content';
}
function options_form(&$form, &$form_state) {
$perms = array();
// Get list of permissions
foreach (module_list(FALSE, FALSE, TRUE) as $module) {
if ($permissions = module_invoke($module, 'perm')) {
$perms[$module] = drupal_map_assoc($permissions);
}
}
$form['perm'] = array(
'#type' => 'select',
'#options' => $perms,
'#title' => t('Permission'),
'#default_value' => $this->options['perm'],
'#description' => t('Only users with the selected permission flag will be able to access this display. Note that users with "access all views" can see any view, regardless of other permissions.'),
);
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* Access plugin that provides role-based access control.
*/
class views_plugin_access_role extends views_plugin_access {
function access($account) {
return views_check_roles(array_filter($this->options['role']), $account);
}
function get_access_callback() {
return array('views_check_roles', array(array_filter($this->options['role'])));
}
function summary_title() {
$count = count($this->options['role']);
if ($count < 1) {
return t('No role(s) selected');
}
else if ($count > 1) {
return t('Multiple roles');
}
else {
$rids = views_ui_get_roles();
$rid = reset($this->options['role']);
return $rids[$rid];
}
}
function option_defaults(&$options) {
$options['role'] = array();
}
function options_form(&$form, &$form_state) {
$form['role'] = array(
'#type' => 'checkboxes',
'#title' => t('Role'),
'#default_value' => $this->options['role'],
'#options' => views_ui_get_roles(),
'#description' => t('Only the checked roles will be able to access this display. Note that users with "access all views" can see any view, regardless of role.'),
);
}
function options_validate(&$form, &$form_state) {
if (!array_filter($form_state['values']['access_options']['role'])) {
form_error($form['role'], t('You must select at least one role if type is "by role"'));
}
}
function options_submit(&$form, &$form_state) {
// I hate checkboxes.
$form_state['values']['access_options']['role'] = array_filter($form_state['values']['access_options']['role']);
}
}

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains the fixed argument default plugin.
*/
/**
* @defgroup views_argument_default_plugins Views' argument default plugins
* @{
*
* Allow specialized methods of filling in arguments when they aren't
* provided.
*
* @see hook_views_plugins
*/
/**
* The fixed argument default handler; also used as the base.
*/
class views_plugin_argument_default extends views_plugin {
var $option_name = 'default_argument_fixed';
/**
* Initialize this plugin with the view and the argument
* it is linked to.
*/
function init(&$view, &$argument, $id = NULL) {
$this->view = &$view;
$this->argument = &$argument;
$this->id = $id;
}
/**
* Determine if the administrator has the privileges to use this
* plugin
*/
function access() { return TRUE; }
function argument_form(&$form, &$form_state) {
$form[$this->option_name] = array(
'#type' => 'textfield',
'#title' => t('Default argument'),
'#default_value' => $this->get_argument(),
'#process' => array('views_process_dependency'),
'#dependency' => array(
'radio:options[default_action]' => array('default'),
'radio:options[default_argument_type]' => array($this->id)
),
'#dependency_count' => 2,
);
// Only do this if using one simple standard form gadget
$this->check_access($form);
}
/**
* If we don't have access to the form but are showing it anyway, ensure that
* the form is safe and cannot be changed from user input.
*/
function check_access(&$form) {
if (!$this->access()) {
$form[$this->option_name]['#disabled'] = TRUE;
$form[$this->option_name]['#value'] = $form[$this->option_name]['#default_value'];
$form[$this->option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the default argument type, this setting will be lost and you will NOT be able to get it back.') . '</strong>';
}
}
/**
* Return the default argument.
*/
function get_argument() {
return isset($this->argument->options[$this->option_name]) ? $this->argument->options[$this->option_name] : '';
}
}
/**
* @}
*/

View file

@ -0,0 +1,51 @@
<?php
/**
* @file
* Contains the php code argument default plugin.
*/
/**
* Default argument plugin to provide a PHP code block.
*/
class views_plugin_argument_default_php extends views_plugin_argument_default {
var $option_name = 'default_argument_php';
function argument_form(&$form, &$form_state) {
$form[$this->option_name] = array(
'#type' => 'textarea',
'#title' => t('PHP argument code'),
'#default_value' => $this->get_argument(TRUE), // the true forces it raw.
'#process' => array('views_process_dependency'),
'#description' => t('Enter PHP code that returns a value to use for this argument. Do not use &lt;?php ?&gt;. You must return only a single value for just this argument.'),
'#dependency' => array(
'radio:options[default_action]' => array('default'),
'radio:options[default_argument_type]' => array($this->id)
),
'#dependency_count' => 2,
);
$this->check_access($form);
}
/**
* Only let users with PHP block visibility permissions set/modify this
* default plugin.
*/
function access() {
return user_access('use PHP for block visibility');
}
function get_argument($raw = FALSE) {
if ($raw) {
return parent::get_argument();
}
// set up variables to make it easier to reference during the argument.
$view = &$this->view;
$argument = &$this->argument;
ob_start();
$result = eval($this->argument->options[$this->option_name]);
ob_end_clean();
return $result;
}
}

View file

@ -0,0 +1,70 @@
<?php
/**
* @file
* Contains the base argument validator plugin.
*/
/**
* @defgroup views_argument_validate_plugins Views' argument validate plugins
* @{
*
* Allow specialized methods of validating arguments.
*
* @see hook_views_plugins
*/
/**
* Base argument validator plugin to provide basic functionality.
*
* @ingroup views_argument_validate_plugins
*/
class views_plugin_argument_validate extends views_plugin {
var $option_name = 'validate_argument';
/**
* Initialize this plugin with the view and the argument
* it is linked to.
*/
function init(&$view, &$argument, $id = NULL) {
$this->view = &$view;
$this->argument = &$argument;
$this->id = $id;
}
/**
* Determine if the administrator has the privileges to use this
* plugin
*/
function access() { return TRUE; }
function argument_form(&$form, &$form_state) {
}
/**
* If we don't have access to the form but are showing it anyway, ensure that
* the form is safe and cannot be changed from user input.
*/
function check_access(&$form) {
if (!$this->access()) {
$form[$this->option_name]['#disabled'] = TRUE;
$form[$this->option_name]['#value'] = $form[$this->option_name]['#default_value'];
$form[$this->option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the validator, this setting will be lost and you will NOT be able to get it back.') . '</strong>';
}
}
/**
* Return the validate argument.
*/
function get_argument() {
return isset($this->argument->options[$this->option_name]) ? $this->argument->options[$this->option_name] : '';
}
function validate_form(&$form, &$form_state) { }
function validate_argument($arg) { return TRUE; }
}
/**
* @}
*/

View file

@ -0,0 +1,27 @@
<?php
/**
* @file
* Contains the numeric argument validator plugin.
*/
/**
* Validate whether an argument is numeric or not.
*
* @ingroup views_argument_validate_plugins
*/
class views_plugin_argument_validate_numeric extends views_plugin_argument_validate {
var $option_name = 'validate_argument_numeric';
/**
* Only let users with PHP block visibility permissions set/modify this
* validate plugin.
*/
function access() {
return !empty($this->argument->definition['numeric']);
}
function validate_argument($argument) {
return is_numeric($argument);
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* @file
* Contains the php code argument validator plugin.
*/
/**
* Provide PHP code to validate whether or not an argument is ok.
*
* @ingroup views_argument_validate_plugins
*/
class views_plugin_argument_validate_php extends views_plugin_argument_validate {
var $option_name = 'validate_argument_php';
function validate_form(&$form, &$form_state) {
$form[$this->option_name] = array(
'#type' => 'textarea',
'#title' => t('PHP validate code'),
'#default_value' => $this->get_argument(),
'#description' => t('Enter PHP code that returns TRUE or FALSE. No return is the same as FALSE, so be SURE to return something if you do not want to declare the argument invalid. Do not use &lt;?php ?&gt;. The argument to validate will be "$argument" and the view will be "$view". You may change the argument by setting "$handler->argument".'),
'#process' => array('views_process_dependency'),
'#dependency' => array('edit-options-validate-type' => array($this->id)),
);
$this->check_access($form);
}
/**
* Only let users with PHP block visibility permissions set/modify this
* validate plugin.
*/
function access() {
return user_access('use PHP for block visibility');
}
function validate_argument($argument) {
// set up variables to make it easier to reference during the argument.
$view = &$this->view;
$handler = &$this->argument;
ob_start();
$result = eval($this->argument->options[$this->option_name]);
ob_end_clean();
return $result;
}
}

View file

@ -0,0 +1,299 @@
<?php
/**
* The base plugin to handle caching.
*
* @ingroup views_cache_plugins
*/
class views_plugin_cache extends views_plugin {
/**
* Contains all data that should be written/read from cache.
*/
var $storage = array();
/**
* What table to store data in.
*/
var $table = 'cache_views_data';
/**
* Initialize the plugin.
*
* @param $view
* The view object.
* @param $display
* The display handler.
*/
function init(&$view, &$display) {
$this->view = &$view;
$this->display = &$display;
$this->options = array();
if (is_object($display->handler)) {
// Note: The below is read only.
$this->options = $display->handler->get_option('cache');
}
}
/**
* Retrieve the default options when this is a new access
* control plugin
*/
function option_defaults(&$options) { }
/**
* Return a string to display as the clickable title for the
* access control.
*/
function summary_title() {
return t('Unknown');
}
/**
* Determine the expiration time of the cache type, or NULL if no expire.
*
* Plugins must override this to implement expiration.
*
* @param $type
* The cache type, either 'query', 'result' or 'output'.
*/
function cache_expire($type) { }
/**
* Determine expiration time in the cache table of the cache type
* or CACHE_PERMANENT if item shouldn't be removed automatically from cache.
*
* Plugins must override this to implement expiration in the cache table.
*
* @param $type
* The cache type, either 'query', 'result' or 'output'.
*/
function cache_set_expire($type) {
return CACHE_PERMANENT;
}
/**
* Save data to the cache.
*
* A plugin should override this to provide specialized caching behavior.
*/
function cache_set($type) {
switch ($type) {
case 'query':
// Not supported currently, but this is certainly where we'd put it.
break;
case 'results':
$data = array(
'result' => $this->view->result,
'total_rows' => $this->view->total_rows,
'pager' => $this->view->pager,
);
cache_set($this->get_results_key(), $data, $this->table, $this->cache_set_expire($type));
break;
case 'output':
$this->gather_headers();
$this->storage['output'] = $this->view->display_handler->output;
cache_set($this->get_output_key(), $this->storage, $this->table, $this->cache_set_expire($type));
break;
}
}
/**
* Retrieve data from the cache.
*
* A plugin should override this to provide specialized caching behavior.
*/
function cache_get($type) {
$cutoff = $this->cache_expire($type);
switch ($type) {
case 'query':
// Not supported currently, but this is certainly where we'd put it.
return FALSE;
case 'results':
// Values to set: $view->result, $view->total_rows, $view->execute_time,
// $view->pager['current_page'].
if ($cache = cache_get($this->get_results_key(), $this->table)) {
if (!$cutoff || $cache->created > $cutoff) {
$this->view->result = $cache->data['result'];
$this->view->total_rows = $cache->data['total_rows'];
$this->view->pager = $cache->data['pager'];
$this->view->execute_time = 0;
return TRUE;
}
}
return FALSE;
case 'output':
if ($cache = cache_get($this->get_output_key(), $this->table)) {
if (!$cutoff || $cache->created > $cutoff) {
$this->storage = $cache->data;
$this->view->display_handler->output = $cache->data['output'];
$this->restore_headers();
return TRUE;
}
}
return FALSE;
}
}
/**
* Clear out cached data for a view.
*
* We're just going to nuke anything related to the view, regardless of display,
* to be sure that we catch everything. Maybe that's a bad idea.
*/
function cache_flush() {
cache_clear_all($this->view->name . ':', $this->table, TRUE);
}
/**
* Post process any rendered data.
*
* This can be valuable to be able to cache a view and still have some level of
* dynamic output. In an ideal world, the actual output will include HTML
* comment based tokens, and then the post process can replace those tokens.
*
* Example usage. If it is known that the view is a node view and that the
* primary field will be a nid, you can do something like this:
*
* <!--post-FIELD-NID-->
*
* And then in the post render, create an array with the text that should
* go there:
*
* strtr($output, array('<!--post-FIELD-1-->', 'output for FIELD of nid 1');
*
* All of the cached result data will be available in $view->result, as well,
* so all ids used in the query should be discoverable.
*/
function post_render(&$output) { }
/**
* Start caching javascript, css and other out of band info.
*
* This takes a snapshot of the current system state so that we don't
* duplicate it. Later on, when gather_headers() is run, this information
* will be removed so that we don't hold onto it.
*/
function cache_start() {
$this->storage['head'] = drupal_set_html_head();
$this->storage['css'] = drupal_add_css();
foreach (array('header', 'footer') as $scope) {
$this->storage['js'][$scope] = drupal_add_js(NULL, NULL, $scope);
}
}
/**
* Gather out of band data, compare it to what we started with and store the difference.
*/
function gather_headers() {
// Simple replacement for head
$this->storage['head'] = str_replace($this->storage['head'], '', drupal_set_html_head());
// Slightly less simple for CSS:
$css = drupal_add_css();
$start = $this->storage['css'];
$this->storage['css'] = array();
foreach ($css as $media => $medias) {
foreach ($medias as $type => $types) {
foreach ($types as $path => $preprocess) {
if (!isset($start[$media][$type][$path])) {
$this->storage['css'][] = array($path, $type, $media, $preprocess);
}
}
}
}
$js = array();
// A little less simple for js
foreach (array('header', 'footer') as $scope) {
$js[$scope] = drupal_add_js(NULL, NULL, $scope);
}
$start = $this->storage['js'];
$this->storage['js'] = array();
foreach ($js as $scope => $scopes) {
foreach ($scopes as $type => $types) {
foreach ($types as $id => $info) {
if (!isset($start[$scope][$type][$id])) {
switch ($type) {
case 'setting':
$this->storage['js'][] = array($info, $type, $scope);
break;
case 'inline':
$this->storage['js'][] = array($info['code'], $type, $scope, $info['defer']);
break;
default:
$this->storage['js'][] = array($id, $type, $scope, $info['defer'], $info['cache']);
}
}
}
}
}
}
/**
* Restore out of band data saved to cache. Copied from Panels.
*/
function restore_headers() {
if (!empty($this->storage['head'])) {
drupal_set_html_head($this->storage['head']);
}
if (!empty($this->storage['css'])) {
foreach ($this->storage['css'] as $args) {
call_user_func_array('drupal_add_css', $args);
}
}
if (!empty($this->storage['js'])) {
foreach ($this->storage['js'] as $args) {
call_user_func_array('drupal_add_js', $args);
}
}
}
function get_results_key() {
global $user;
if (!isset($this->_results_key)) {
$key_data = array(
'build_info' => $this->view->build_info,
'roles' => array_keys($user->roles),
'super-user' => $user->uid == 1, // special caching for super user.
'language' => $GLOBALS['language'],
);
foreach (array('exposed_info', 'page', 'sort', 'order') as $key) {
if (isset($_GET[$key])) {
$key_data[$key] = $_GET[$key];
}
}
$this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data));
}
return $this->_results_key;
}
function get_output_key() {
global $user;
if (!isset($this->_output_key)) {
$key_data = array(
'result' => $this->view->result,
'roles' => array_keys($user->roles),
'super-user' => $user->uid == 1, // special caching for super user.
'theme' => $GLOBALS['theme'],
'language' => $GLOBALS['language'],
);
$this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . md5(serialize($key_data));
}
return $this->_output_key;
}
}

View file

@ -0,0 +1,18 @@
<?php
/**
* Caching plugin that provides no caching at all.
*/
class views_plugin_cache_none extends views_plugin_cache {
function cache_start() { /* do nothing */ }
function summary_title() {
return t('None');
}
function cache_get($type) {
return FALSE;
}
function cache_set($type) { }
}

View file

@ -0,0 +1,55 @@
<?php
/**
* Simple caching of query results for Views displays.
*/
class views_plugin_cache_time extends views_plugin_cache {
function option_defaults(&$options) {
$options['results_lifespan'] = 3600;
$options['output_lifespan'] = 3600;
}
function options_form(&$form, &$form_state) {
$options = array(60, 300, 1800, 3600, 21600, 518400);
$options = drupal_map_assoc($options, 'format_interval');
$options = array(-1 => t('Never cache')) + $options;
$form['results_lifespan'] = array(
'#type' => 'select',
'#title' => t('Query results'),
'#description' => t('The length of time raw query results should be cached.'),
'#options' => $options,
'#default_value' => $this->options['results_lifespan'],
);
$form['output_lifespan'] = array(
'#type' => 'select',
'#title' => t('Rendered output'),
'#description' => t('The length of time rendered HTML output should be cached.'),
'#options' => $options,
'#default_value' => $this->options['output_lifespan'],
);
}
function summary_title() {
return format_interval($this->options['results_lifespan'], 1) . '/' . format_interval($this->options['output_lifespan'], 1);
}
function cache_expire($type) {
if ($lifespan = $this->options[$type . '_lifespan']) {
$cutoff = time() - $lifespan;
return $cutoff;
}
else {
return FALSE;
}
}
function cache_set_expire($type) {
if ($lifespan = $this->options[$type . '_lifespan']) {
return time() + $lifespan;
}
else {
return CACHE_PERMANENT;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,278 @@
<?php
/**
* @file
* Contains the attachment display plugin.
*/
/**
* The plugin that handles an attachment display.
*
* Attachment displays are secondary displays that are 'attached' to a primary
* display. Effectively they are a simple way to get multiple views within
* the same view. They can share some information.
*
* @ingroup views_display_plugins
*/
class views_plugin_display_attachment extends views_plugin_display {
function option_definition () {
$options = parent::option_definition();
$options['attachment_position'] = array('default' => 'before');
$options['inherit_arguments'] = array('default' => TRUE);
$options['inherit_exposed_filters'] = array('default' => FALSE);
$options['inherit_pager'] = array('default' => FALSE);
$options['render_pager'] = array('default' => TRUE);
$options['displays'] = array('default' => array());
return $options;
}
function execute() {
return $this->view->render($this->display->id);
}
function attachment_positions($position = NULL) {
$positions = array(
'before' => t('Before'),
'after' => t('After'),
'both' => t('Both'),
);
if ($position) {
return $positions[$position];
}
return $positions;
}
/**
* Provide the summary for attachment options in the views UI.
*
* This output is returned as an array.
*/
function options_summary(&$categories, &$options) {
// It is very important to call the parent function here:
parent::options_summary($categories, $options);
$categories['attachment'] = array(
'title' => t('Attachment settings'),
);
$options['inherit_arguments'] = array(
'category' => 'attachment',
'title' => t('Inherit arguments'),
'value' => $this->get_option('inherit_arguments') ? t('Yes') : t('No'),
);
$options['inherit_exposed_filters'] = array(
'category' => 'attachment',
'title' => t('Inherit exposed filters'),
'value' => $this->get_option('inherit_exposed_filters') ? t('Yes') : t('No'),
);
$options['inherit_pager'] = array(
'category' => 'attachment',
'title' => t('Inherit pager'),
'value' => $this->get_option('inherit_pager') ? t('Yes') : t('No'),
);
$options['render_pager'] = array(
'category' => 'attachment',
'title' => t('Render pager'),
'value' => $this->get_option('render_pager') ? t('Yes') : t('No'),
);
$options['attachment_position'] = array(
'category' => 'attachment',
'title' => t('Position'),
'value' => $this->attachment_positions($this->get_option('attachment_position')),
);
$displays = array_filter($this->get_option('displays'));
if (count($displays) > 1) {
$attach_to = t('Multiple displays');
}
else if (count($displays) == 1) {
$display = array_shift($displays);
if (!empty($this->view->display[$display])) {
$attach_to = check_plain($this->view->display[$display]->display_title);
}
}
if (!isset($attach_to)) {
$attach_to = t('None');
}
$options['displays'] = array(
'category' => 'attachment',
'title' => t('Attach to'),
'value' => $attach_to,
);
}
/**
* Provide the default form for setting options.
*/
function options_form(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_form($form, $form_state);
switch ($form_state['section']) {
case 'inherit_arguments':
$form['#title'] .= t('Inherit arguments');
$form['inherit_arguments'] = array(
'#type' => 'checkbox',
'#title' => t('Inherit'),
'#description' => t('Should this display inherit its arguments from the parent display to which it is attached?'),
'#default_value' => $this->get_option('inherit_arguments'),
);
break;
case 'inherit_exposed_filters':
$form['#title'] .= t('Inherit exposed filters');
$form['inherit_exposed_filters'] = array(
'#type' => 'checkbox',
'#title' => t('Inherit'),
'#description' => t('Should this display inherit its exposed filter values from the parent display to which it is attached?'),
'#default_value' => $this->get_option('inherit_exposed_filters'),
);
break;
case 'inherit_pager':
$form['#title'] .= t('Inherit pager');
$form['inherit_pager'] = array(
'#type' => 'checkbox',
'#title' => t('Inherit'),
'#description' => t('Should this display inherit its paging values from the parent display to which it is attached? Note that this will provide unexpected results if the number of items to display do not match.'),
'#default_value' => $this->get_option('inherit_pager'),
);
break;
case 'render_pager':
$form['#title'] .= t('Render pager');
$form['render_pager'] = array(
'#type' => 'checkbox',
'#title' => t('Render'),
'#description' => t('Should this display render the pager values? If not it can inherit from the parent...'),
'#default_value' => $this->get_option('render_pager'),
);
break;
case 'attachment_position':
$form['#title'] .= t('Position');
$form['attachment_position'] = array(
'#type' => 'radios',
'#description' => t('Attach before or after the parent display?'),
'#options' => $this->attachment_positions(),
'#default_value' => $this->get_option('attachment_position'),
);
break;
case 'displays':
$form['#title'] .= t('Attach to');
$displays = array();
foreach ($this->view->display as $display_id => $display) {
if (!empty($display->handler) && $display->handler->accept_attachments()) {
$displays[$display_id] = $display->display_title;
}
}
$form['displays'] = array(
'#type' => 'checkboxes',
'#description' => t('Select which display or displays this should attach to.'),
'#options' => $displays,
'#default_value' => $this->get_option('displays'),
);
break;
}
}
/**
* Perform any necessary changes to the form values prior to storage.
* There is no need for this function to actually store the data.
*/
function options_submit(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_submit($form, $form_state);
switch ($form_state['section']) {
case 'inherit_arguments':
case 'inherit_pager':
case 'render_pager':
case 'inherit_exposed_filters':
case 'attachment_position':
case 'displays':
$this->set_option($form_state['section'], $form_state['values'][$form_state['section']]);
break;
}
}
/**
* Attach to another view.
*/
function attach_to($display_id) {
$displays = $this->get_option('displays');
if (empty($displays[$display_id])) {
return;
}
if (!$this->access()) {
return;
}
// Get a fresh view because our current one has a lot of stuff on it because it's
// already been executed.
$view = $this->view->clone_view();
$view->original_args = $view->args;
$args = $this->get_option('inherit_arguments') ? $this->view->args : array();
$view->set_arguments($args);
$view->set_display($this->display->id);
if ($this->get_option('inherit_pager')) {
$view->display_handler->use_pager = $this->view->display[$display_id]->handler->use_pager();
$view->display_handler->set_option('pager_element', $this->view->display[$display_id]->handler->get_option('pager_element'));
}
// because of this, it is very very important that displays that can accept
// attachments not also be attachments, or this could explode messily.
$attachment = $view->execute_display($this->display->id, $args);
switch ($this->get_option('attachment_position')) {
case 'before':
$this->view->attachment_before .= $attachment;
break;
case 'after':
$this->view->attachment_after .= $attachment;
break;
case 'both':
$this->view->attachment_before .= $attachment;
$this->view->attachment_after .= $attachment;
break;
}
$view->destroy();
}
/**
* Attachment displays only use exposed widgets if
* they are set to inherit the exposed filter settings
* of their parent display.
*/
function uses_exposed() {
if (!empty($this->options['inherit_exposed_filters']) && parent::uses_exposed()) {
return TRUE;
}
return FALSE;
}
/**
* If an attachment is set to inherit the exposed filter
* settings from its parent display, then don't render and
* display a second set of exposed filter widgets.
*/
function displays_exposed() {
return $this->options['inherit_exposed_filters'] ? FALSE : TRUE;
}
function use_pager() {
return !empty($this->use_pager);
}
function render_pager() {
return !empty($this->use_pager) && $this->get_option('render_pager');
}
}

View file

@ -0,0 +1,192 @@
<?php
/**
* @file
* Contains the block display plugin.
*/
/**
* The plugin that handles a block.
*
* @ingroup views_display_plugins
*/
class views_plugin_display_block extends views_plugin_display {
function option_definition() {
$options = parent::option_definition();
$options['block_description'] = array('default' => '', 'translatable' => TRUE);
$options['block_caching'] = array('default' => BLOCK_NO_CACHE);
return $options;
}
/**
* The default block handler doesn't support configurable items,
* but extended block handlers might be able to do interesting
* stuff with it.
*/
function execute_hook_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
$delta = $this->view->name . '-' . $this->display->id;
$desc = $this->get_option('block_description');
if (empty($desc)) {
$desc = t('@view: @display', array('@view' => $this->view->name, '@display' => $this->display->display_title));
}
return array(
$delta => array(
'info' => $desc,
'cache' => $this->get_cache_type()
)
);
}
}
/**
* The display block handler returns the structure necessary for a block.
*/
function execute() {
// Prior to this being called, the $view should already be set to this
// display, and arguments should be set on the view.
$info['content'] = $this->view->render();
$info['subject'] = filter_xss_admin($this->view->get_title());
if (!empty($this->view->result) || $this->get_option('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
return $info;
}
}
/**
* Provide the summary for page options in the views UI.
*
* This output is returned as an array.
*/
function options_summary(&$categories, &$options) {
// It is very important to call the parent function here:
parent::options_summary($categories, $options);
$categories['block'] = array(
'title' => t('Block settings'),
);
$block_description = strip_tags($this->get_option('block_description'));
if (empty($block_description)) {
$block_description = t('None');
}
if (strlen($block_description) > 16) {
$block_description = drupal_substr($block_description, 0, 16) . '...';
}
$options['block_description'] = array(
'category' => 'block',
'title' => t('Admin'),
'value' => $block_description,
);
$cache_type = $this->get_option('block_caching');
if (empty($cache_type)) {
$cache_type = BLOCK_NO_CACHE;
}
$types = $this->block_caching_modes();
$options['block_caching'] = array(
'category' => 'block',
'title' => t('Caching'),
'value' => $types[$this->get_cache_type()],
);
}
/**
* Provide a list of core's block caching modes.
*/
function block_caching_modes() {
return array(
BLOCK_NO_CACHE => t('Do not cache'),
BLOCK_CACHE_GLOBAL => t('Cache once for everything (global)'),
BLOCK_CACHE_PER_PAGE => t('Per page'),
BLOCK_CACHE_PER_ROLE => t('Per role'),
BLOCK_CACHE_PER_ROLE | BLOCK_CACHE_PER_PAGE => t('Per role per page'),
BLOCK_CACHE_PER_USER => t('Per user'),
BLOCK_CACHE_PER_USER | BLOCK_CACHE_PER_PAGE => t('Per user per page'),
);
}
/**
* Provide a single method to figure caching type, keeping a sensible default
* for when it's unset.
*/
function get_cache_type() {
$cache_type = $this->get_option('block_caching');
if (empty($cache_type)) {
$cache_type = BLOCK_NO_CACHE;
}
return $cache_type;
}
/**
* Provide the default form for setting options.
*/
function options_form(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_form($form, $form_state);
switch ($form_state['section']) {
case 'block_description':
$form['#title'] .= t('Block admin description');
$form['block_description'] = array(
'#type' => 'textfield',
'#description' => t('This will appear as the name of this block in administer >> site building >> blocks.'),
'#default_value' => $this->get_option('block_description'),
);
break;
case 'block_caching':
$form['#title'] .= t('Block caching type');
$form['block_caching'] = array(
'#type' => 'radios',
'#description' => t("This sets the default status for Drupal's built-in block caching method; this requires that caching be turned on in block administration, and be careful because you have little control over when this cache is flushed."),
'#options' => $this->block_caching_modes(),
'#default_value' => $this->get_cache_type(),
);
break;
}
}
/**
* Perform any necessary changes to the form values prior to storage.
* There is no need for this function to actually store the data.
*/
function options_submit(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_submit($form, $form_state);
switch ($form_state['section']) {
case 'block_description':
$this->set_option('block_description', $form_state['values']['block_description']);
break;
case 'block_caching':
$this->set_option('block_caching', $form_state['values']['block_caching']);
$this->save_block_cache($form_state['view']->name.'-'.$form_state['display_id'], $form_state['values']['block_caching']);
break;
}
}
/**
* Block views use exposed widgets only if AJAX is set.
*/
function uses_exposed() {
if ($this->use_ajax()) {
return parent::uses_exposed();
}
return FALSE;
}
/**
* Save the block cache setting in the blocks table if this block allready
* exists in the blocks table. Dirty fix untill http://drupal.org/node/235673 gets in.
*/
function save_block_cache($delta, $cache_setting) {
if ($bid = db_fetch_object(db_query("SELECT bid, cache FROM {blocks} WHERE module = 'views' AND delta = '%s'", $delta))) {
db_query("UPDATE {blocks} set cache = %d WHERE module = 'views' AND delta = '%s'", $cache_setting, $delta);
}
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
* @file
* Contains the default display plugin.
*/
/**
* A plugin to handle defaults on a view.
*
* @ingroup views_display_plugins
*/
class views_plugin_display_default extends views_plugin_display {
/**
* Determine if this display is the 'default' display which contains
* fallback settings
*/
function is_default_display() { return TRUE; }
/**
* The default execute handler fully renders the view.
*
* For the simplest use:
* @code
* $output = $view->execute_display('default', $args);
* @endcode
*
* For more complex usages, a view can be partially built:
* @code
* $view->set_arguments($args);
* $view->build('default'); // Build the query
* $view->execute(); // Run the query
* $output = $view->render(); // Render the view
* @endcode
*
* If short circuited at any point, look in $view->build_info for
* information about the query. After execute, look in $view->result
* for the array of objects returned from db_query.
*
* You can also do:
* @code
* $view->set_arguments($args);
* $output = $view->render('default'); // Render the view
* @endcode
*
* This illustrates that render is smart enough to call build and execute
* if these items have not already been accomplished.
*
* Note that execute also must accomplish other tasks, such
* as setting page titles, breadcrumbs, and generating exposed filter
* data if necessary.
*/
function execute() {
return $this->view->render($this->display->id);
}
}

View file

@ -0,0 +1,205 @@
<?php
/**
* @file
* Contains the feed display plugin.
*/
/**
* The plugin that handles a feed, such as RSS or atom.
*
* For the most part, feeds are page displays but with some subtle differences.
*
* @ingroup views_display_plugins
*/
class views_plugin_display_feed extends views_plugin_display_page {
function uses_breadcrumb() { return FALSE; }
function get_style_type() { return 'feed'; }
/**
* Feeds do not go through the normal page theming mechanism. Instead, they
* go through their own little theme function and then return NULL so that
* Drupal believes that the page has already rendered itself...which it has.
*/
function execute() {
$output = $this->view->render();
if (empty($output)) {
return drupal_not_found();
}
print $output;
}
function preview() {
if (!empty($this->view->live_preview)) {
return '<pre>' . check_plain($this->view->render()) . '</pre>';
}
return $this->view->render();
}
/**
* Instead of going through the standard views_view.tpl.php, delegate this
* to the style handler.
*/
function render() {
return $this->view->style_plugin->render($this->view->result);
}
function defaultable_sections($section = NULL) {
if (in_array($section, array('style_options', 'style_plugin', 'row_options', 'row_plugin',))) {
return FALSE;
}
$sections = parent::defaultable_sections($section);
// Tell views our sitename_title option belongs in the title section.
if ($section == 'title') {
$sections[] = 'sitename_title';
}
elseif (!$section) {
$sections['title'][] = 'sitename_title';
}
return $sections;
}
function option_definition() {
$options = parent::option_definition();
$options['displays'] = array('default' => array());
// Overrides for standard stuff:
$options['style_plugin']['default'] = 'rss';
$options['style_options']['default'] = array('mission_description' => FALSE, 'description' => '');
$options['sitename_title']['default'] = FALSE;
$options['row_plugin']['default'] = '';
$options['defaults']['default']['style_plugin'] = FALSE;
$options['defaults']['default']['style_options'] = FALSE;
$options['defaults']['default']['row_plugin'] = FALSE;
$options['defaults']['default']['row_options'] = FALSE;
return $options;
}
function options_summary(&$categories, &$options) {
// It is very important to call the parent function here:
parent::options_summary($categories, $options);
// Since we're childing off the 'page' type, we'll still *call* our
// category 'page' but let's override it so it says feed settings.
$categories['page'] = array(
'title' => t('Feed settings'),
);
if ($this->get_option('sitename_title')) {
$options['title']['value'] = t('Using the site name');
}
// I don't think we want to give feeds menus directly.
unset($options['menu']);
$displays = array_filter($this->get_option('displays'));
if (count($displays) > 1) {
$attach_to = t('Multiple displays');
}
else if (count($displays) == 1) {
$display = array_shift($displays);
if (!empty($this->view->display[$display])) {
$attach_to = check_plain($this->view->display[$display]->display_title);
}
}
if (!isset($attach_to)) {
$attach_to = t('None');
}
$options['displays'] = array(
'category' => 'page',
'title' => t('Attach to'),
'value' => $attach_to,
);
}
/**
* Provide the default form for setting options.
*/
function options_form(&$form, &$form_state) {
// It is very important to call the parent function here.
parent::options_form($form, $form_state);
switch ($form_state['section']) {
case 'title':
$title = $form['title'];
// A little juggling to move the 'title' field beyond our checkbox.
unset($form['title']);
$form['sitename_title'] = array(
'#type' => 'checkbox',
'#title' => t('Use the site name for the title'),
'#default_value' => $this->get_option('sitename_title'),
);
$form['title'] = $title;
$form['title']['#process'] = array('views_process_dependency');
$form['title']['#dependency'] = array('edit-sitename-title' => array(FALSE));
break;
case 'displays':
$form['#title'] .= t('Attach to');
$displays = array();
foreach ($this->view->display as $display_id => $display) {
if (!empty($display->handler) && $display->handler->accept_attachments()) {
$displays[$display_id] = $display->display_title;
}
}
$form['displays'] = array(
'#type' => 'checkboxes',
'#description' => t('The feed icon will be available only to the selected displays.'),
'#options' => $displays,
'#default_value' => $this->get_option('displays'),
);
break;
case 'path':
$form['path']['#description'] = t('This view will be displayed by visiting this path on your site. It is recommended that the path be something like "path/%/%/feed" or "path/%/%/rss.xml", putting one % in the path for each argument you have defined in the view.');
}
}
/**
* Perform any necessary changes to the form values prior to storage.
* There is no need for this function to actually store the data.
*/
function options_submit(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_submit($form, $form_state);
switch ($form_state['section']) {
case 'title':
$this->set_option('sitename_title', $form_state['values']['sitename_title']);
break;
case 'displays':
$this->set_option($form_state['section'], $form_state['values'][$form_state['section']]);
break;
}
}
/**
* Attach to another view.
*/
function attach_to($display_id) {
$displays = $this->get_option('displays');
if (empty($displays[$display_id])) {
return;
}
// Defer to the feed style; it may put in meta information, and/or
// attach a feed icon.
$plugin = $this->get_plugin();
if ($plugin) {
$clone = $this->view->clone_view();
$clone->set_display($this->display->id);
$clone->build_title();
$plugin->attach_to($display_id, $this->get_path(), $clone->get_title());
// Clean up
$clone->destroy();
unset($clone);
}
}
function uses_link_display() {
return TRUE;
}
}

View file

@ -0,0 +1,509 @@
<?php
/**
* @file
* Contains the page display plugin.
*/
/**
* The plugin that handles a full page.
*
* @ingroup views_display_plugins
*/
class views_plugin_display_page extends views_plugin_display {
/**
* The page display has a path.
*/
function has_path() { return TRUE; }
function uses_breadcrumb() { return TRUE; }
function option_definition() {
$options = parent::option_definition();
$options['path'] = array('default' => '');
$options['menu'] = array(
'contains' => array(
'type' => array('default' => 'none'),
// Do not translate menu and title as menu system will.
'title' => array('default' => '', 'translatable' => FALSE),
'description' => array('default' => '', 'translatable' => FALSE),
'weight' => array('default' => 0),
'name' => array('default' => variable_get('menu_default_node_menu', 'navigation')),
),
);
$options['tab_options'] = array(
'contains' => array(
'type' => array('default' => 'none'),
// Do not translate menu and title as menu system will.
'title' => array('default' => '', 'translatable' => FALSE),
'description' => array('default' => '', 'translatable' => FALSE),
'weight' => array('default' => 0),
'name' => array('default' => 'navigation'),
),
);
return $options;
}
/**
* Add this display's path information to Drupal's menu system.
*/
function execute_hook_menu($callbacks) {
$items = array();
// Replace % with the link to our standard views argument loader
// views_arg_load -- which lives in views.module
$bits = explode('/', $this->get_option('path'));
$page_arguments = array($this->view->name, $this->display->id);
$view_arguments = $this->get_option('arguments');
// Replace % with %views_arg for menu autoloading and add to the
// page arguments so the argument actually comes through.
foreach($bits as $pos => $bit) {
if ($bit == '%') {
$argument = array_shift($view_arguments);
if ($argument['validate_type'] != 'none') {
$bits[$pos] = '%views_arg';
}
$page_arguments[] = $pos;
}
}
$path = implode('/', $bits);
$access_plugin = $this->get_access_plugin();
if (!isset($access_plugin)) {
$access_plugin = views_get_plugin('access', 'none');
}
if ($path) {
$items[$path] = array(
// default views page entry
'page callback' => 'views_page',
'page arguments' => $page_arguments,
// Default access check (per display)
'access callback' => 'views_access',
'access arguments' => array($access_plugin->get_access_callback()),
// Identify URL embedded arguments and correlate them to a handler
'load arguments' => array($this->view->name, $this->display->id, '%index'),
);
$menu = $this->get_option('menu');
if (empty($menu)) {
$menu = array('type' => 'none');
}
// Set the title and description if we have one.
if ($menu['type'] != 'none') {
$items[$path]['title'] = $menu['title'];
$items[$path]['description'] = $menu['description'];
}
if (isset($menu['weight'])) {
$items[$path]['weight'] = intval($menu['weight']);
}
switch ($menu['type']) {
case 'none':
default:
$items[$path]['type'] = MENU_CALLBACK;
break;
case 'normal':
$items[$path]['type'] = MENU_NORMAL_ITEM;
// Insert item into the proper menu
$items[$path]['menu_name'] = $menu['name'];
break;
case 'tab':
$items[$path]['type'] = MENU_LOCAL_TASK;
break;
case 'default tab':
$items[$path]['type'] = MENU_DEFAULT_LOCAL_TASK;
break;
}
// If this is a 'default' tab, check to see if we have to create teh
// parent menu item.
if ($menu['type'] == 'default tab') {
$tab_options = $this->get_option('tab_options');
if (!empty($tab_options['type']) && $tab_options['type'] != 'none') {
$bits = explode('/', $path);
// Remove the last piece.
$bit = array_pop($bits);
// we can't do this if they tried to make the last path bit variable.
// @todo: We can validate this.
if ($bit != '%views_arg' && !empty($bits)) {
$default_path = implode('/', $bits);
$items[$default_path] = array(
// default views page entry
'page callback' => 'views_page',
'page arguments' => $page_arguments,
// Default access check (per display)
'access callback' => 'views_access',
'access arguments' => array($access_plugin->get_access_callback()),
// Identify URL embedded arguments and correlate them to a handler
'load arguments' => array($this->view->name, $this->display->id, '%index'),
'title' => $tab_options['title'],
'description' => $tab_options['description'],
'menu_name' => $tab_options['name'],
);
switch ($tab_options['type']) {
default:
case 'normal':
$items[$default_path]['type'] = MENU_NORMAL_ITEM;
break;
case 'tab':
$items[$default_path]['type'] = MENU_LOCAL_TASK;
break;
}
if (isset($tab_options['weight'])) {
$items[$default_path]['weight'] = intval($tab_options['weight']);
}
}
}
}
}
return $items;
}
/**
* The display page handler returns a normal view, but it also does
* a drupal_set_title for the page, and does a views_set_page_view
* on the view.
*/
function execute() {
// Let the world know that this is the page view we're using.
views_set_page_view($this);
// Prior to this being called, the $view should already be set to this
// display, and arguments should be set on the view.
$this->view->build();
if (!empty($this->view->build_info['fail'])) {
return drupal_not_found();
}
$this->view->get_breadcrumb(TRUE);
// And the title, which is much easier.
drupal_set_title(filter_xss_admin($this->view->get_title()));
// And now render the view.
return $this->view->render();
}
/**
* Provide the summary for page options in the views UI.
*
* This output is returned as an array.
*/
function options_summary(&$categories, &$options) {
// It is very important to call the parent function here:
parent::options_summary($categories, $options);
$categories['page'] = array(
'title' => t('Page settings'),
);
$path = strip_tags($this->get_option('path'));
if (empty($path)) {
$path = t('None');
}
if (strlen($path) > 16) {
$path = substr($path, 0, 16) . '...';
}
$options['path'] = array(
'category' => 'page',
'title' => t('Path'),
'value' => $path,
);
$menu = $this->get_option('menu');
if (!is_array($menu)) {
$menu = array('type' => 'none');
}
switch($menu['type']) {
case 'none':
default:
$menu_str = t('No menu');
break;
case 'normal':
$menu_str = t('Normal: @title', array('@title' => $menu['title']));
break;
case 'tab':
case 'default tab':
$menu_str = t('Tab: @title', array('@title' => $menu['title']));
break;
}
if (strlen($menu_str) > 16) {
$menu_str = substr($menu_str, 0, 16) . '...';
}
$options['menu'] = array(
'category' => 'page',
'title' => t('Menu'),
'value' => $menu_str,
);
// This adds a 'Settings' link to the style_options setting if the style has options.
if ($menu['type'] == 'default tab') {
$options['menu']['links']['tab_options'] = t('Change settings for the parent menu');
}
}
/**
* Provide the default form for setting options.
*/
function options_form(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_form($form, $form_state);
switch ($form_state['section']) {
case 'path':
$form['#title'] .= t('The menu path or URL of this view');
$form['#help_topic'] = 'path';
$form['path'] = array(
'#type' => 'textfield',
'#description' => t('This view will be displayed by visiting this path on your site. You may use "%" in your URL to represent values that will be used for arguments: For example, "node/%/feed".'),
'#default_value' => $this->get_option('path'),
'#field_prefix' => '<span dir="ltr">' . url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='),
'#field_suffix' => '</span>&lrm;',
'#attributes' => array('dir'=>'ltr'),
);
break;
case 'menu':
$form['#title'] .= t('Menu item entry');
$form['#help_topic'] = 'menu';
$form['menu'] = array(
'#prefix' => '<div class="clear-block">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
$menu = $this->get_option('menu');
if (empty($menu)) {
$menu = array('type' => 'none', 'title' => '', 'weight' => 0);
}
$form['menu']['type'] = array(
'#prefix' => '<div class="views-left-30">',
'#suffix' => '</div>',
'#title' => t('Type'),
'#type' => 'radios',
'#options' => array(
'none' => t('No menu entry'),
'normal' => t('Normal menu entry'),
'tab' => t('Menu tab'),
'default tab' => t('Default menu tab')
),
'#default_value' => $menu['type'],
);
$form['menu']['title'] = array(
'#prefix' => '<div class="views-left-50">',
'#title' => t('Title'),
'#type' => 'textfield',
'#default_value' => $menu['title'],
'#description' => t('If set to normal or tab, enter the text to use for the menu item.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')),
);
$form['menu']['description'] = array(
'#title' => t('Description'),
'#type' => 'textfield',
'#default_value' => $menu['description'],
'#description' => t("If set to normal or tab, enter the text to use for the menu item's description."),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')),
);
$form['menu']['name-warning'] = array(
'#type' => 'markup',
'#prefix' => '<div class="warning">',
'#value' => t("Warning: Changing this item's menu will not work reliably in Drupal 6.4 or earlier. Please upgrade your copy of Drupal at !url.", array('!url' => l('drupal.org', 'http://drupal.org/project/Drupal+project'))),
'#suffix' => '</div>',
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:menu[type]' => array('normal')),
'#access' => version_compare(VERSION, '6.5', '<'),
);
// Only display the menu selector if menu module is enabled.
if (module_exists('menu')) {
$form['menu']['name'] = array(
'#title' => t('Menu'),
'#type' => 'select',
'#options' => menu_get_menus(),
'#default_value' => $menu['name'],
'#description' => t('Insert item into an available menu.'), //
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:menu[type]' => array('normal')),
);
}
else {
$form['menu']['name'] = array(
'#type' => 'value',
'#value' => $menu['name'],
);
$form['menu']['markup'] = array(
'#value' => t('Menu selection requires the activation of menu module.'),
);
}
$form['menu']['weight'] = array(
'#suffix' => '</div>',
'#title' => t('Weight'),
'#type' => 'textfield',
'#default_value' => isset($menu['weight']) ? $menu['weight'] : 0,
'#description' => t('The lower the weight the higher/further left it will appear.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')),
);
break;
case 'tab_options':
$form['#title'] .= t('Default tab options');
$tab_options = $this->get_option('tab_options');
if (empty($tab_options)) {
$tab_options = array('type' => 'none', 'title' => '', 'weight' => 0);
}
$form['tab_markup'] = array(
'#prefix' => '<div class="form-item description">',
'#suffix' => '</div>',
'#value' => t('When providing a menu item as a tab, Drupal needs to know what the parent menu item of that tab will be. Sometimes the parent will already exist, but other times you will need to have one created. The path of a parent item will always be the same path with the last part left off. i.e, if the path to this view is <em>foo/bar/baz</em>, the parent path would be <em>foo/bar</em>.'),
);
$form['tab_options'] = array(
'#prefix' => '<div class="clear-block">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
$form['tab_options']['type'] = array(
'#prefix' => '<div class="views-left-25">',
'#suffix' => '</div>',
'#title' => t('Parent menu item'),
'#type' => 'radios',
'#options' => array('none' => t('Already exists'), 'normal' => t('Normal menu item'), 'tab' => t('Menu tab')),
'#default_value' => $tab_options['type'],
);
$form['tab_options']['title'] = array(
'#prefix' => '<div class="views-left-75">',
'#title' => t('Title'),
'#type' => 'textfield',
'#default_value' => $tab_options['title'],
'#description' => t('If creating a parent menu item, enter the title of the item.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:tab_options[type]' => array('normal', 'tab')),
);
$form['tab_options']['description'] = array(
'#title' => t('Description'),
'#type' => 'textfield',
'#default_value' => $tab_options['description'],
'#description' => t('If creating a parent menu item, enter the description of the item.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:tab_options[type]' => array('normal', 'tab')),
);
// Only display the menu selector if menu module is enabled.
if (module_exists('menu')) {
$form['tab_options']['name'] = array(
'#title' => t('Menu'),
'#type' => 'select',
'#options' => menu_get_menus(),
'#default_value' => $tab_options['name'],
'#description' => t('Insert item into an available menu.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:tab_options[type]' => array('normal')),
);
}
else {
$form['tab_options']['name'] = array(
'#type' => 'value',
'#value' => $tab_options['name'],
);
$form['tab_options']['markup'] = array(
'#value' => t('Menu selection requires the activation of menu module.'),
);
}
$form['tab_options']['weight'] = array(
'#suffix' => '</div>',
'#title' => t('Tab weight'),
'#type' => 'textfield',
'#default_value' => $tab_options['weight'],
'#size' => 5,
'#description' => t('If the parent menu item is a tab, enter the weight of the tab. The lower the number, the more to the left it will be.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('radio:tab_options[type]' => array('tab')),
);
break;
}
}
function options_validate(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_validate($form, $form_state);
switch ($form_state['section']) {
case 'path':
if (strpos($form_state['values']['path'], '$arg') !== FALSE) {
form_error($form['path'], t('"$arg" is no longer supported. Use % instead.'));
}
if (strpos($form_state['values']['path'], '%') === 0) {
form_error($form['path'], t('"%" may not be used for the first segment of a path.'));
}
// automatically remove '/' from path.
$form_state['values']['path'] = trim($form_state['values']['path'], '/');
break;
case 'menu':
$path = $this->get_option('path');
if ($form_state['values']['menu']['type'] == 'normal' && strpos($path, '%') !== FALSE) {
form_error($form['menu']['type'], t('Views cannot create normal menu items for paths with a % in them.'));
}
if ($form_state['values']['menu']['type'] == 'default tab' || $form_state['values']['menu']['type'] == 'tab') {
$bits = explode('/', $path);
$last = array_pop($bits);
if ($last == '%') {
form_error($form['menu']['type'], t('A display whose path ends with a % cannot be a tab.'));
}
}
if ($form_state['values']['menu']['type'] != 'none' && empty($form_state['values']['menu']['title'])) {
form_error($form['menu']['title'], t('Title is required for this menu type.'));
}
break;
}
}
function options_submit(&$form, &$form_state) {
// It is very important to call the parent function here:
parent::options_submit($form, $form_state);
switch ($form_state['section']) {
case 'path':
$this->set_option('path', $form_state['values']['path']);
break;
case 'menu':
$this->set_option('menu', $form_state['values']['menu']);
// send ajax form to options page if we use it.
if ($form_state['values']['menu']['type'] == 'default tab') {
views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('tab_options'));
}
break;
case 'tab_options':
$this->set_option('tab_options', $form_state['values']['tab_options']);
break;
}
}
function validate() {
$errors = parent::validate();
$menu = $this->get_option('menu');
if (!empty($menu['type']) && $menu['type'] != 'none' && empty($menu['title'])) {
$errors[] = t('Display @display is set to use a menu but the menu title is not set.', array('@display' => $this->display->display_title));
}
if ($menu['type'] == 'default tab') {
$tab_options = $this->get_option('tab_options');
if (!empty($tab_options['type']) && $tab_options['type'] != 'none' && empty($tab_options['title'])) {
$errors[] = t('Display @display is set to use a parent menu but the parent menu title is not set.', array('@display' => $this->display->display_title));
}
}
return $errors;
}
}

View file

@ -0,0 +1,139 @@
<?php
/**
* @file
* Contains the base row style plugin.
*/
/**
* @defgroup views_row_plugins Views' row plugins
* @{
*
* Row plugins control how Views outputs an individual record. They are
* tightly coupled to style plugins, in that a style plugin is what calls
* the row plugin.
*
* @see hook_views_plugins
*/
/**
* Default plugin to view a single row of a table. This is really just a wrapper around
* a theme function.
*
* @ingroup views_row_plugins
*/
class views_plugin_row extends views_plugin {
/**
* Initialize the row plugin.
*/
function init(&$view, &$display, $options = NULL) {
$this->view = &$view;
$this->display = &$display;
// Overlay incoming options on top of defaults
$this->unpack_options($this->options, isset($options) ? $options : $display->handler->get_option('row_options'));
}
function uses_fields() {
return !empty($this->definition['uses fields']);
}
function option_definition() {
$options = parent::option_definition();
if (isset($this->base_table)) {
$options['relationship'] = array('default' => 'none');
}
return $options;
}
/**
* Provide a form for setting options.
*/
function options_form(&$form, &$form_state) {
if (isset($this->base_table)) {
$view = &$form_state['view'];
// A whole bunch of code to figure out what relationships are valid for
// this item.
$relationships = $view->display_handler->get_option('relationships');
$relationship_options = array();
foreach ($relationships as $relationship) {
$relationship_handler = views_get_handler($relationship['table'], $relationship['field'], 'relationship');
// If this relationship is valid for this type, add it to the list.
$data = views_fetch_data($relationship['table']);
$base = $data[$relationship['field']]['relationship']['base'];
if ($base == $this->base_table) {
$relationship_handler->init($view, $relationship);
$relationship_options[$relationship['id']] = $relationship_handler->label();
}
}
if (!empty($relationship_options)) {
$relationship_options = array_merge(array('none' => t('Do not use a relationship')), $relationship_options);
$rel = empty($this->options['relationship']) ? 'none' : $this->options['relationship'];
if (empty($relationship_options[$rel])) {
// Pick the first relationship.
$rel = key($relationship_options);
}
$form['relationship'] = array(
'#type' => 'select',
'#title' => t('Relationship'),
'#options' => $relationship_options,
'#default_value' => $rel,
);
}
else {
$form['relationship'] = array(
'#type' => 'value',
'#value' => 'none',
);
}
}
}
/**
* Validate the options form.
*/
function options_validate(&$form, &$form_state) { }
/**
* Perform any necessary changes to the form values prior to storage.
* There is no need for this function to actually store the data.
*/
function options_submit(&$form, &$form_state) { }
function query() {
if (isset($this->base_table) && isset($this->options['relationship']) && isset($this->view->relationship[$this->options['relationship']])) {
$relationship = $this->view->relationship[$this->options['relationship']];
$this->field_alias = $this->view->query->add_field($relationship->alias, $this->base_field);
}
else {
$this->field_alias = $this->view->base_field;
}
}
/**
* Allow the style to do stuff before each row is rendered.
*
* @param $result
* The full array of results from the query.
*/
function pre_render($result) { }
/**
* Render a row object. This usually passes through to a theme template
* of some form, but not always.
*/
function render($row) {
return theme($this->theme_functions(), $this->view, $this->options, $row, $this->field_alias);
}
}
/**
* @}
*/

View file

@ -0,0 +1,67 @@
<?php
/**
* @file
* Contains the base row style plugin.
*/
/**
* The basic 'fields' row plugin
*
* This displays fields one after another, giving options for inline
* or not.
*
* @ingroup views_row_plugins
*/
class views_plugin_row_fields extends views_plugin_row {
function option_definition() {
$options = parent::option_definition();
$options['inline'] = array('default' => array());
$options['separator'] = array('default' => '');
$options['hide_empty'] = array('default' => FALSE);
return $options;
}
/**
* Provide a form for setting options.
*/
function options_form(&$form, &$form_state) {
$options = $this->display->handler->get_field_labels();
if (empty($this->options['inline'])) {
$this->options['inline'] = array();
}
$form['inline'] = array(
'#type' => 'checkboxes',
'#title' => t('Inline fields'),
'#options' => $options,
'#default_value' => $this->options['inline'],
'#description' => t('Inline fields will be displayed next to each other rather than one after another.'),
);
$form['separator'] = array(
'#title' => t('Separator'),
'#type' => 'textfield',
'#size' => 10,
'#default_value' => isset($this->options['separator']) ? $this->options['separator'] : '',
'#description' => t('The separator may be placed between inline fields to keep them from squishing up next to each other. You can use HTML in this field.'),
);
$form['hide_empty'] = array(
'#type' => 'checkbox',
'#title' => t('Hide empty fields'),
'#default_value' => $this->options['hide_empty'],
'#description' => t('Do not display fields, labels or markup for fields that are empty.'),
);
}
/**
* Perform any necessary changes to the form values prior to storage.
* There is no need for this function to actually store the data.
*/
function options_submit(&$form, &$form_state) {
$form_state['values']['row_options']['inline'] = array_filter($form_state['values']['row_options']['inline']);
}
}

View file

@ -0,0 +1,274 @@
<?php
/**
* @defgroup views_style_plugins Views' style plugins
* @{
* Style plugins control how a view is rendered. For example, they
* can choose to display a collection of fields, node_view() output,
* table output, or any kind of crazy output they want.
*
* Many style plugins can have an optional 'row' plugin, that displays
* a single record. Not all style plugins can utilize this, so it is
* up to the plugin to set this up and call through to the row plugin.
*
* @see hook_views_plugins
*/
/**
* Base class to define a style plugin handler.
*/
class views_plugin_style extends views_plugin {
/**
* Initialize a style plugin.
*
* @param $view
* @param $display
* @param $options
* The style options might come externally as the style can be sourced
* from at least two locations. If it's not included, look on the display.
*/
function init(&$view, &$display, $options = NULL) {
$this->view = &$view;
$this->display = &$display;
// Overlay incoming options on top of defaults
$this->unpack_options($this->options, isset($options) ? $options : $display->handler->get_option('style_options'));
if ($this->uses_row_plugin() && $display->handler->get_option('row_plugin')) {
$this->row_plugin = $display->handler->get_plugin('row');
}
$this->options += array(
'grouping' => '',
);
$this->definition += array(
'uses grouping' => TRUE,
);
}
function destroy() {
parent::destroy();
if (isset($this->row_plugin)) {
$this->row_plugin->destroy();
}
}
/**
* Return TRUE if this style also uses a row plugin.
*/
function uses_row_plugin() {
return !empty($this->definition['uses row plugin']);
}
/**
* Return TRUE if this style also uses fields.
*/
function uses_fields() {
// If we use a row plugin, ask the row plugin. Chances are, we don't
// care, it does.
if ($this->uses_row_plugin() && !empty($this->row_plugin)) {
return $this->row_plugin->uses_fields();
}
// Otherwise, maybe we do.
return !empty($this->definition['uses fields']);
}
function option_definition() {
$options = parent::option_definition();
$options['grouping'] = array('default' => '');
return $options;
}
function options_form(&$form, &$form_state) {
// Only fields-based views can handle grouping. Style plugins can also exclude
// themselves from being groupable by setting their "use grouping" definiton
// key to FALSE.
// @TODO: Document "uses grouping" in docs.php when docs.php is written.
if ($this->uses_fields() && $this->definition['uses grouping']) {
$options = array('' => t('- None -'));
$options += $this->display->handler->get_field_labels();
// If there are no fields, we can't group on them.
if (count($options) > 1) {
$form['grouping'] = array(
'#type' => 'select',
'#title' => t('Grouping field'),
'#options' => $options,
'#default_value' => $this->options['grouping'],
'#description' => t('You may optionally specify a field by which to group the records. Leave blank to not group.'),
);
}
}
}
/**
* Called by the view builder to see if this style handler wants to
* interfere with the sorts. If so it should build; if it returns
* any non-TRUE value, normal sorting will NOT be added to the query.
*/
function build_sort() { return TRUE; }
/**
* Called by the view builder to let the style build a second set of
* sorts that will come after any other sorts in the view.
*/
function build_sort_post() { }
/**
* Allow the style to do stuff before each row is rendered.
*
* @param $result
* The full array of results from the query.
*/
function pre_render($result) {
if (!empty($this->row_plugin)) {
$this->row_plugin->pre_render($result);
}
}
/**
* Render the display in this style.
*/
function render() {
if ($this->uses_row_plugin() && empty($this->row_plugin)) {
vpr('views_plugin_style_default: Missing row plugin');
return;
}
// Group the rows according to the grouping field, if specified.
$sets = $this->render_grouping($this->view->result, $this->options['grouping']);
// Render each group separately and concatenate. Plugins may override this
// method if they wish some other way of handling grouping.
$output = '';
foreach ($sets as $title => $records) {
if ($this->uses_row_plugin()) {
$rows = array();
foreach ($records as $row_index => $row) {
$this->view->row_index = $row_index;
$rows[] = $this->row_plugin->render($row);
}
}
else {
$rows = $records;
}
$output .= theme($this->theme_functions(), $this->view, $this->options, $rows, $title);
}
unset($this->view->row_index);
return $output;
}
/**
* Group records as needed for rendering.
*
* @param $records
* An array of records from the view to group.
* @param $grouping_field
* The field id on which to group. If empty, the result set will be given
* a single group with an empty string as a label.
* @return
* The grouped record set.
*/
function render_grouping($records, $grouping_field = '') {
// Make sure fields are rendered
$this->render_fields($this->view->result);
$sets = array();
if ($grouping_field) {
foreach ($records as $index => $row) {
$grouping = '';
// Group on the rendered version of the field, not the raw. That way,
// we can control any special formatting of the grouping field through
// the admin or theme layer or anywhere else we'd like.
if (isset($this->view->field[$grouping_field])) {
$grouping = $this->get_field($index, $grouping_field);
if ($this->view->field[$grouping_field]->options['label']) {
$grouping = $this->view->field[$grouping_field]->options['label'] . ': ' . $grouping;
}
}
$sets[$grouping][$index] = $row;
}
}
else {
// Create a single group with an empty grouping field.
$sets[''] = $records;
}
return $sets;
}
/**
* Render all of the fields for a given style and store them on the object.
*
* @param $result
* The result array from $view->result
*/
function render_fields($result) {
if (!$this->uses_fields()) {
return;
}
if (isset($this->rendered_fields)) {
return $this->rendered_fields;
}
$this->view->row_index = 0;
$keys = array_keys($this->view->field);
foreach ($result as $count => $row) {
$this->view->row_index = $count;
foreach ($keys as $id) {
$this->rendered_fields[$count][$id] = $this->view->field[$id]->theme($row);
}
}
unset($this->view->row_index);
}
/**
* Get a rendered field.
*
* @param $index
* The index count of the row.
* @param $field
* The id of the field.
*/
function get_field($index, $field) {
if (!isset($this->rendered_fields)) {
$this->render_fields($this->view->result);
}
if (isset($this->rendered_fields[$index][$field])) {
return $this->rendered_fields[$index][$field];
}
}
function validate() {
$errors = parent::validate();
if ($this->uses_row_plugin()) {
$plugin = $this->display->handler->get_plugin('row');
if (empty($plugin)) {
$errors[] = t('Style @style requires a row style but the row plugin is invalid.', array('@style' => $this->definition['title']));
}
else {
$result = $plugin->validate();
if (!empty($result) && is_array($result)) {
$errors = array_merge($errors, $result);
}
}
}
return $errors;
}
function query() {
parent::query();
if (isset($this->row_plugin)) {
$this->row_plugin->query();
}
}
}
/**
* @}
*/

View file

@ -0,0 +1,24 @@
<?php
/**
* @file
* Contains the default style plugin.
*/
/**
* Default style plugin to render rows one after another with no
* decorations.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_default extends views_plugin_style {
/**
* Set default options
*/
function options(&$options) {
parent::options($options);
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
}
}

View file

@ -0,0 +1,60 @@
<?php
/**
* @file
* Contains the grid style plugin.
*/
/**
* Style plugin to render each item in a grid cell.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_grid extends views_plugin_style {
/**
* Set default options
*/
function option_definition() {
$options = parent::option_definition();
$options['columns'] = array('default' => '4');
$options['alignment'] = array('default' => 'horizontal');
$options['fill_single_line'] = array('default' => TRUE);
$options['summary'] = array('default' => '');
return $options;
}
/**
* Render the given style.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['columns'] = array(
'#type' => 'textfield',
'#title' => t('Number of columns'),
'#default_value' => $this->options['columns'],
);
$form['alignment'] = array(
'#type' => 'radios',
'#title' => t('Alignment'),
'#options' => array('horizontal' => t('Horizontal'), 'vertical' => t('Vertical')),
'#default_value' => $this->options['alignment'],
'#description' => t('Horizontal alignment will place items starting in the upper left and moving right. Vertical alignment will place items starting in the upper left and moving down.'),
);
$form['fill_single_line'] = array(
'#type' => 'checkbox',
'#title' => t('Fill up single line'),
'#description' => t('If you disable this option a grid with only one row will have the amount of items as tds. If you disable it this can cause problems with your css.'),
'#default_value' => !empty($this->options['fill_single_line']),
);
$form['summary'] = array(
'#type' => 'textfield',
'#title' => t('Table summary'),
'#description' => t('This value will be displayed as table-summary attribute in the html. Set this for better accessiblity of your site.'),
'#default_value' => $this->options['summary'],
);
}
}

View file

@ -0,0 +1,155 @@
<?php
/**
* @file
* Contains the table style plugin.
*/
/**
* Style plugin to render each item as a row in a table.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_jump_menu extends views_plugin_style {
function option_definition() {
$options = parent::option_definition();
$options['hide'] = array('default' => FALSE);
$options['path'] = array('default' => '');
$options['text'] = array('default' => 'Go', 'translatable' => TRUE);
$options['choose'] = array('default' => '- Choose -', 'translatable' => TRUE);
$options['default_value'] = array('default' => FALSE);
return $options;
}
/**
* Render the given style.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$handlers = $this->display->handler->get_handlers('field');
if (empty($handlers)) {
$form['error_markup'] = array(
'#value' => t('You need at least one field before you can configure your jump menu settings'),
'#prefix' => '<div class="error form-item description">',
'#suffix' => '</div>',
);
return;
}
$form['markup'] = array(
'#value' => t('To properly configure a jump menu, you must select one field that will represent the path to utilize. You should then set that field to exclude. All other displayed fields will be part of the menu. Please note that all HTML will be stripped from this output as select boxes cannot show HTML.'),
'#prefix' => '<div class="form-item description">',
'#suffix' => '</div>',
);
foreach ($handlers as $id => $handler) {
$options[$id] = $handler->ui_name();
}
$form['path'] = array(
'#type' => 'select',
'#title' => t('Path field'),
'#options' => $options,
'#default_value' => $this->options['path'],
);
$form['hide'] = array(
'#type' => 'checkbox',
'#title' => t('Hide the "Go" button.'),
'#default_value' => !empty($this->options['hide']),
'#description' => t('If hidden, this button will only be hidden for users with javascript and the page will automatically jump when the select is changed.'),
);
$form['text'] = array(
'#type' => 'textfield',
'#title' => t('Button text'),
'#default_value' => $this->options['text'],
);
$form['choose'] = array(
'#type' => 'textfield',
'#title' => t('Choose text'),
'#default_value' => $this->options['choose'],
'#description' => t('The text that will appear as the selected option in the jump menu.'),
);
$form['default_value'] = array(
'#type' => 'checkbox',
'#title' => t('Select the current argument.'),
'#default_value' => !empty($this->options['default_value']),
'#description' => t('If checked, the current path will be displayed as the default option in the jump menu, if applicable.'),
);
}
/**
* Render the display in this style.
*
* This is overridden so that we can render our grouping specially.
*/
function render() {
$sets = $this->render_grouping($this->view->result, $this->options['grouping']);
// Turn this all into an $options array for the jump menu.
$this->view->row_index = 0;
$options = array();
$paths = array();
foreach ($sets as $title => $records) {
foreach ($records as $row_index => $row) {
$this->view->row_index = $row_index;
$path = html_entity_decode(strip_tags($this->get_field($this->view->row_index, $this->options['path'])), ENT_QUOTES);
// Putting a '/' in front messes up url() so let's take that out
// so users don't shoot themselves in the foot.
if (strpos($path, '/') === 0) {
$path = substr($path, 1);
}
// use parse_url() to preserve query and fragment in case the user
// wants to do fun tricks.
$url = parse_url($path);
$url_options = array();
if (isset($url['query'])) {
$path = strtr($path, array('?' . $url['query'] => ''));
$url_options['query'] = $url['query'];
}
if (isset($url['fragment'])) {
$path = strtr($path, array('#' . $url['fragment'] => ''));
$url_options['fragment'] = $url['fragment'];
}
$path = url($path, $url_options);
$field = html_entity_decode(strip_tags($this->row_plugin->render($row)), ENT_QUOTES);
if ($title) {
$options[$title][$path] = $field;
}
else {
$options[$path] = $field;
}
$paths[$path] = $path;
$this->view->row_index++;
}
}
unset($this->view->row_index);
$default_value = '';
if ($this->options['default_value'] && !empty($paths[url($_GET['q'])])) {
$default_value = url($_GET['q']);
}
ctools_include('jump-menu');
$settings = array(
'hide' => $this->options['hide'],
'button' => $this->options['text'],
'choose' => $this->options['choose'],
'default_value' => $default_value,
);
return drupal_get_form('ctools_jump_menu', $options, $settings);
}
function render_set($title, $records) {
$options = array();
$fields = $this->rendered_fields;
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* @file
* Contains the list style plugin.
*/
/**
* Style plugin to render each item in an ordered or unordered list.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_list extends views_plugin_style {
/**
* Set default options
*/
function option_definition() {
$options = parent::option_definition();
$options['type'] = array('default' => 'ul');
return $options;
}
/**
* Render the given style.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['type'] = array(
'#type' => 'radios',
'#title' => t('List type'),
'#options' => array('ul' => t('Unordered list'), 'ol' => t('Ordered list')),
'#default_value' => $this->options['type'],
);
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
* @file
* Contains the RSS style plugin.
*/
/**
* Default style plugin to render an RSS feed.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_rss extends views_plugin_style {
function attach_to($display_id, $path, $title) {
$display = $this->view->display[$display_id]->handler;
$url_options = array();
$input = $this->view->get_exposed_input();
if ($input) {
$url_options['query'] = $input;
}
$url = url($this->view->get_url(NULL, $path), $url_options);
if ($display->has_path()) {
if (empty($this->preview)) {
drupal_add_feed($url, $title);
}
}
else {
if (empty($this->view->feed_icon)) {
$this->view->feed_icon = '';
}
$this->view->feed_icon .= theme('feed_icon', $url, $title);
drupal_add_link(array(
'rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => $title,
'href' => $url
));
}
}
function option_definition() {
$options = parent::option_definition();
$options['description'] = array('default' => '', 'translatable' => TRUE);
$options['mission_description'] = array('default' => '', 'translatable' => TRUE);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['mission_description'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['mission_description']),
'#title' => t('Use the site mission for the description'),
);
$form['description'] = array(
'#type' => 'textfield',
'#title' => t('RSS description'),
'#default_value' => $this->options['description'],
'#description' => t('This will appear in the RSS feed itself.'),
'#process' => array('views_process_dependency'),
'#dependency' => array('edit-style-options-override' => array(FALSE)),
);
}
/**
* Return an array of additional XHTML elements to add to the channel.
*
* @return
* An array that can be passed to format_xml_elements().
*/
function get_channel_elements() {
return array();
}
function render() {
if (empty($this->row_plugin)) {
vpr('views_plugin_style_default: Missing row plugin');
return;
}
$rows = '';
// This will be filled in by the row plugin and is used later on in the
// theming output.
$this->namespaces = array();
// Fetch any additional elements for the channel and merge in their
// namespaces.
$this->channel_elements = $this->get_channel_elements();
foreach ($this->channel_elements as $element) {
if (isset($element['namespace'])) {
$this->namespaces = array_merge($this->namespaces, $element['namespace']);
}
}
foreach ($this->view->result as $row_index => $row) {
$this->view->row_index = $row_index;
$rows .= $this->row_plugin->render($row);
}
$output = theme($this->theme_functions(), $this->view, $this->options, $rows);
unset($this->view->row_index);
return $output;
}
}

View file

@ -0,0 +1,69 @@
<?php
/**
* @file
* Contains the default summary style plugin, which displays items in an HTML list.
*/
/**
* The default style plugin for summaries.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_summary extends views_plugin_style {
function option_definition() {
$options = parent::option_definition();
$options['base_path'] = array('default' => '');
$options['count'] = array('default' => TRUE);
$options['override'] = array('default' => FALSE);
$options['items_per_page'] = array('default' => 25);
return $options;
}
function query() {
if (!empty($this->options['override'])) {
$this->view->set_items_per_page(intval($this->options['items_per_page']));
}
}
function options_form(&$form, &$form_state) {
$form['base_path'] = array(
'#type' => 'textfield',
'#title' => t('Base path'),
'#default_value' => $this->options['base_path'],
'#description' => t('Define the base path for links in this summary
view, i.e. http://example.com/<strong>your_view_path/archive</strong>.
Do not include beginning and ending forward slash. If this value
is empty, views will use the first path found as the base path,
in page displays, or / if no path could be found.'),
);
$form['count'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['count']),
'#title' => t('Display record count with link'),
);
$form['override'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['override']),
'#title' => t('Override number of items to display'),
);
$form['items_per_page'] = array(
'#type' => 'textfield',
'#title' => t('Items to display'),
'#default_value' => $this->options['items_per_page'],
'#process' => array('views_process_dependency'),
'#dependency' => array('edit-style-options-override' => array(TRUE)),
);
}
function render() {
$rows = array();
foreach ($this->view->result as $row) {
// @todo: Include separator as an option.
$rows[] = $row;
}
return theme($this->theme_functions(), $this->view, $this->options, $rows);
}
}

View file

@ -0,0 +1,123 @@
<?php
/**
* @file
* Contains the default summary style plugin, which displays items in an HTML list.
*/
/**
* The default style plugin for summaries.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_summary_jump_menu extends views_plugin_style {
function option_definition() {
$options = parent::option_definition();
$options['base_path'] = array('default' => '');
$options['count'] = array('default' => TRUE);
$options['hide'] = array('default' => FALSE);
$options['text'] = array('default' => 'Go', 'translatable' => TRUE);
$options['choose'] = array('default' => '- Choose -', 'translatable' => TRUE);
$options['default_value'] = array('default' => FALSE);
return $options;
}
function query() {
// We can't have an offset without a limit, so provide a very large limit instead.
if (!empty($this->display->handler->options['offset'])) {
$this->view->set_items_per_page(999999);
}
else {
$this->view->set_items_per_page(0);
$this->view->set_use_pager(0);
}
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['base_path'] = array(
'#type' => 'textfield',
'#title' => t('Base path'),
'#default_value' => $this->options['base_path'],
'#description' => t('Define the base path for links in this summary
view, i.e. http://example.com/<strong>your_view_path/archive</strong>.
Do not include beginning and ending forward slash. If this value
is empty, views will use the first path found as the base path,
in page displays, or / if no path could be found.'),
);
$form['count'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['count']),
'#title' => t('Display record count with link'),
);
$form['hide'] = array(
'#type' => 'checkbox',
'#title' => t('Hide the "Go" button.'),
'#default_value' => !empty($this->options['hide']),
'#description' => t('If hidden, this button will only be hidden for users with javascript and the page will automatically jump when the select is changed.'),
);
$form['text'] = array(
'#type' => 'textfield',
'#title' => t('Button text'),
'#default_value' => $this->options['text'],
);
$form['choose'] = array(
'#type' => 'textfield',
'#title' => t('Choose text'),
'#default_value' => $this->options['choose'],
'#description' => t('The text that will appear as the selected option in the jump menu.'),
);
$form['default_value'] = array(
'#type' => 'checkbox',
'#title' => t('Select the current argument.'),
'#default_value' => !empty($this->options['default_value']),
'#description' => t('If checked, the current argument setting will be displayed as the default option in the jump menu, if applicable.'),
);
}
function render() {
$argument = $this->view->argument[$this->view->build_info['summary_level']];
$url_options = array();
if (!empty($this->view->exposed_raw_input)) {
$url_options['query'] = $this->view->exposed_raw_input;
}
$options = array();
$default_value = '';
foreach ($this->view->result as $id => $row) {
$args = $this->view->args;
$args[$argument->position] = $argument->summary_argument($row);
$base_path = NULL;
if (!empty($argument->options['style_options']['base_path'])) {
$base_path = $argument->options['style_options']['base_path'];
}
$path = url($this->view->get_url($args, $base_path), $url_options);
$options[$path] = strip_tags($argument->summary_name($row));
if (!empty($this->options['count'])) {
$options[$path] .= ' (' . intval($row->{$argument->count_alias}) . ')';
}
if ($this->options['default_value'] && $_GET['q'] == $this->view->get_url($args)) {
$default_value = $path;
}
}
ctools_include('jump-menu');
$settings = array(
'hide' => $this->options['hide'],
'button' => $this->options['text'],
'choose' => $this->options['choose'],
'default_value' => $default_value,
);
return drupal_get_form('ctools_jump_menu', $options, $settings);
}
}

View file

@ -0,0 +1,34 @@
<?php
/**
* @file
* Contains the unformatted summary style plugin.
*/
/**
* The default style plugin for summaries.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_summary_unformatted extends views_plugin_style_summary {
function option_definition() {
$options = parent::option_definition();
$options['inline'] = array('default' => FALSE);
$options['separator'] = array('default' => '');
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['inline'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['inline']),
'#title' => t('Display items inline'),
);
$form['separator'] = array(
'#type' => 'textfield',
'#title' => t('Separator'),
'#default_value' => $this->options['separator'],
);
}
}

View file

@ -0,0 +1,254 @@
<?php
/**
* @file
* Contains the table style plugin.
*/
/**
* Style plugin to render each item as a row in a table.
*
* @ingroup views_style_plugins
*/
class views_plugin_style_table extends views_plugin_style {
function option_definition() {
$options = parent::option_definition();
$options['columns'] = array('default' => array());
$options['default'] = array('default' => '');
$options['info'] = array('default' => array());
$options['override'] = array('default' => TRUE);
$options['sticky'] = array('default' => FALSE);
$options['order'] = array('default' => 'asc');
$options['summary'] = array('default' => '');
return $options;
}
/**
* Determine if we should provide sorting based upon $_GET inputs.
*/
function build_sort() {
if (!isset($_GET['order']) && ($this->options['default'] == -1 || empty($this->view->field[$this->options['default']]))) {
return TRUE;
}
// If a sort we don't know anything about gets through, exit gracefully.
if (isset($_GET['order']) && empty($this->view->field[$_GET['order']])) {
return TRUE;
}
// Let the builder know whether or not we're overriding the default sorts.
return empty($this->options['override']);
}
/**
* Add our actual sort criteria
*/
function build_sort_post() {
if (!isset($_GET['order'])) {
// check for a 'default' clicksort. If there isn't one, exit gracefully.
if (empty($this->options['default'])) {
return;
}
$sort = $this->options['default'];
$this->order = !empty($this->options['order']) ? $this->options['order'] : 'asc';
}
else {
$sort = $_GET['order'];
// Store the $order for later use.
$this->order = !empty($_GET['sort']) ? strtolower($_GET['sort']) : 'asc';
}
// If a sort we don't know anything about gets through, exit gracefully.
if (empty($this->view->field[$sort])) {
return;
}
// Ensure $this->order is valid.
if ($this->order != 'asc' && $this->order != 'desc') {
$this->order = 'asc';
}
// Store the $sort for later use.
$this->active = $sort;
// Tell the field to click sort.
$this->view->field[$sort]->click_sort($this->order);
}
/**
* Normalize a list of columns based upon the fields that are
* available. This compares the fields stored in the style handler
* to the list of fields actually in the view, removing fields that
* have been removed and adding new fields in their own column.
*
* - Each field must be in a column.
* - Each column must be based upon a field, and that field
* is somewhere in the column.
* - Any fields not currently represented must be added.
* - Columns must be re-ordered to match the fields.
*
* @param $columns
* An array of all fields; the key is the id of the field and the
* value is the id of the column the field should be in.
* @param $fields
* The fields to use for the columns. If not provided, they will
* be requested from the current display. The running render should
* send the fields through, as they may be different than what the
* display has listed due to access control or other changes.
*/
function sanitize_columns($columns, $fields = NULL) {
$sanitized = array();
if ($fields === NULL) {
$fields = $this->display->handler->get_option('fields');
}
// Preconfigure the sanitized array so that the order is retained.
foreach ($fields as $field => $info) {
// Set to itself so that if it isn't touched, it gets column
// status automatically.
$sanitized[$field] = $field;
}
foreach ($columns as $field => $column) {
// first, make sure the field still exists.
if (!isset($sanitized[$field])) {
continue;
}
// If the field is the column, mark it so, or the column
// it's set to is a column, that's ok
if ($field == $column || $columns[$column] == $column && !empty($sanitized[$column])) {
$sanitized[$field] = $column;
}
// Since we set the field to itself initially, ignoring
// the condition is ok; the field will get its column
// status back.
}
return $sanitized;
}
/**
* Render the given style.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$handlers = $this->display->handler->get_handlers('field');
if (empty($handlers)) {
$form['error_markup'] = array(
'#value' => t('You need at least one field before you can configure your table settings'),
'#prefix' => '<div class="error form-item description">',
'#suffix' => '</div>',
);
return;
}
$form['override'] = array(
'#type' => 'checkbox',
'#title' => t('Override normal sorting if click sorting is used'),
'#default_value' => !empty($this->options['override']),
);
$form['sticky'] = array(
'#type' => 'checkbox',
'#title' => t('Enable Drupal style "sticky" table headers (Javascript)'),
'#default_value' => !empty($this->options['sticky']),
'#description' => t('(Sticky header effects will not be active for preview below, only on live output.)'),
);
$form['order'] = array(
'#type' => 'select',
'#title' => t('Default sort order'),
'#options' => array('asc' => t('Ascending'), 'desc' => t('Descending')),
'#default_value' => $this->options['order'],
'#description' => t('If a default sort order is selected, what order should it use by default.'),
);
$form['summary'] = array(
'#type' => 'textfield',
'#title' => t('Table summary'),
'#description' => t('This value will be displayed as table-summary attribute in the html. Set this for better accessiblity of your site.'),
'#default_value' => $this->options['summary'],
);
// Note: views UI registers this theme handler on our behalf. Your module
// will have to register your theme handlers if you do stuff like this.
$form['#theme'] = 'views_ui_style_plugin_table';
$columns = $this->sanitize_columns($this->options['columns']);
// Create an array of allowed columns from the data we know:
$field_names = $this->display->handler->get_field_labels();
if (isset($this->options['default'])) {
$default = $this->options['default'];
if (!isset($columns[$default])) {
$default = -1;
}
}
else {
$default = -1;
}
foreach ($columns as $field => $column) {
$safe = str_replace(array('][', '_', ' '), '-', $field);
// the $id of the column for dependency checking.
$id = 'edit-style-options-columns-' . $safe;
$form['columns'][$field] = array(
'#type' => 'select',
'#options' => $field_names,
'#default_value' => $column,
);
if ($handlers[$field]->click_sortable()) {
$form['info'][$field]['sortable'] = array(
'#type' => 'checkbox',
'#default_value' => !empty($this->options['info'][$field]['sortable']),
'#process' => array('views_process_dependency'),
'#dependency' => array($id => array($field)),
);
// Provide an ID so we can have such things.
$radio_id = form_clean_id('edit-default-' . $field);
$form['default'][$field] = array(
'#type' => 'radio',
'#return_value' => $field,
'#parents' => array('style_options', 'default'),
'#id' => $radio_id,
// because 'radio' doesn't fully support '#id' =(
'#attributes' => array('id' => $radio_id),
'#default_value' => $default,
'#process' => array('views_process_dependency'),
'#dependency' => array($id => array($field)),
);
}
$form['info'][$field]['separator'] = array(
'#type' => 'textfield',
'#size' => 10,
'#default_value' => isset($this->options['info'][$field]['separator']) ? $this->options['info'][$field]['separator'] : '',
'#process' => array('views_process_dependency'),
'#dependency' => array($id => array($field)),
);
// markup for the field name
$form['info'][$field]['name'] = array(
'#value' => $field_names[$field],
);
}
// Provide a radio for no default sort
$form['default'][-1] = array(
'#type' => 'radio',
'#return_value' => -1,
'#parents' => array('style_options', 'default'),
'#id' => 'edit-default-0',
'#default_value' => $default,
);
$form['description_markup'] = array(
'#prefix' => '<div class="description form-item">',
'#suffix' => '</div>',
'#value' => t('Place fields into columns; you may combine multiple fields into the same column. If you do, the separator in the column specified will be used to separate the fields. Check the sortable box to make that column click sortable, and check the default sort radio to determine which column will be sorted by default, if any. You may control column order and field labels in the fields section.'),
);
}
}