Commit 14a8b0df authored by dawehner's avatar dawehner Committed by tim.plunkett

Move CTools specific integration into CTools.

parent 6a9ce89a
<?php
/**
* @file
* Definition of Drupal\views\Plugin\views\field\Math.
*/
namespace Drupal\views\Plugin\views\field;
use Drupal\ctools\MathExpression;
use Drupal\Core\Annotation\Plugin;
/**
* Render a mathematical expression as a numeric value
*
* Definition terms:
* - float: If true this field contains a decimal value. If unset this field
* will be assumed to be integer.
*
* @ingroup views_field_handlers
*
* @Plugin(
* id = "math"
* )
*/
class Math extends Numeric {
function option_definition() {
$options = parent::option_definition();
$options['expression'] = array('default' => '');
return $options;
}
function options_form(&$form, &$form_state) {
$form['expression'] = array(
'#type' => 'textarea',
'#title' => t('Expression'),
'#description' => t('Enter mathematical expressions such as 2 + 2 or sqrt(5). You may assign variables and create mathematical functions and evaluate them. Use the ; to separate these. For example: f(x) = x + 2; f(2).'),
'#default_value' => $this->options['expression'],
);
// Create a place for the help
$form['expression_help'] = array();
parent::options_form($form, $form_state);
// Then move the existing help:
$form['expression_help'] = $form['alter']['help'];
unset($form['expression_help']['#states']);
unset($form['alter']['help']);
}
function render($values) {
$tokens = array_map('floatval', $this->get_render_tokens(array()));
$value = strtr($this->options['expression'], $tokens);
$expressions = explode(';', $value);
$math = new MathExpression();
foreach ($expressions as $expression) {
if ($expression !== '') {
$value = $math->evaluate($expression);
}
}
// The rest is directly from views_handler_field_numeric but because it
// does not allow the value to be passed in, it is copied.
if (!empty($this->options['set_precision'])) {
$value = number_format($value, $this->options['precision'], $this->options['decimal'], $this->options['separator']);
}
else {
$remainder = abs($value) - intval(abs($value));
$value = $value > 0 ? floor($value) : ceil($value);
$value = number_format($value, 0, '', $this->options['separator']);
if ($remainder) {
// The substr may not be locale safe.
$value .= $this->options['decimal'] . substr($remainder, 2);
}
}
// Check to see if hiding should happen before adding prefix and suffix.
if ($this->options['hide_empty'] && empty($value) && ($value !== 0 || $this->options['empty_zero'])) {
return '';
}
// Should we format as a plural.
if (!empty($this->options['format_plural']) && ($value != 0 || !$this->options['empty_zero'])) {
$value = format_plural($value, $this->options['format_plural_singular'], $this->options['format_plural_plural']);
}
return $this->sanitize_value($this->options['prefix'] . $value . $this->options['suffix']);
}
function query() { }
}
<?php
/**
* @file
* Definition of Drupal\views\Plugin\views\style\JumpMenu.
*/
namespace Drupal\views\Plugin\views\style;
use Drupal\Core\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;
/**
* Style plugin to render each item as a row in a table.
*
* @ingroup views_style_plugins
*
* @Plugin(
* id = "jump_menu",
* title = @Translation("Jump menu"),
* help = @Translation("Puts all of the results into a select box and allows the user to go to a different page based upon the results."),
* theme = "views_view_jump_menu",
* uses_row_plugin = TRUE,
* uses_fields = TRUE,
* uses_options = TRUE,
* type = "normal",
* help_topic = "style-jump-menu"
* )
*/
class JumpMenu extends StylePluginBase {
function option_definition() {
$options = parent::option_definition();
$options['hide'] = array('default' => FALSE, 'bool' => TRUE);
$options['path'] = array('default' => '');
$options['text'] = array('default' => 'Go', 'translatable' => TRUE);
$options['choose'] = array('default' => '- Choose -', 'translatable' => TRUE);
$options['default_value'] = array('default' => FALSE, 'bool' => TRUE);
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(
'#markup' => t('You need at least one field before you can configure your jump menu settings'),
'#prefix' => '<div class="error messages">',
'#suffix' => '</div>',
);
return;
}
$form['markup'] = array(
'#markup' => 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 contextual filter value'),
'#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 = strip_tags(decode_entities($this->get_field($this->view->row_index, $this->options['path'])));
// Putting a '/' in front messes up url() so let's take that out
// so users don't shoot themselves in the foot.
$base_path = base_path();
if (strpos($path, $base_path) === 0) {
$path = drupal_substr($path, drupal_strlen($base_path));
}
// use drupal_parse_url() to preserve query and fragment in case the user
// wants to do fun tricks.
$url_options = drupal_parse_url($path);
$path = url($url_options['path'], $url_options);
$field = strip_tags(decode_entities($this->row_plugin->render($row)));
$key = md5($path . $field) . "::" . $path;
if ($title) {
$options[$title][$key] = $field;
}
else {
$options[$key] = $field;
}
$paths[$path] = $key;
$this->view->row_index++;
}
}
unset($this->view->row_index);
$default_value = '';
if ($this->options['default_value'] && !empty($paths[url(current_path())])) {
$default_value = $paths[url(current_path())];
}
ctools_include('jump-menu');
$settings = array(
'hide' => $this->options['hide'],
'button' => $this->options['text'],
'choose' => $this->options['choose'],
'default_value' => $default_value,
);
$form = drupal_get_form('ctools_jump_menu', $options, $settings);
return $form;
}
function render_set($title, $records) {
$options = array();
$fields = $this->rendered_fields;
}
}
<?php
/**
* @file
* Definition of Drupal\views\Plugin\views\style\JumpMenuStyleSummary.
*/
namespace Drupal\views\Plugin\views\style;
use Drupal\Core\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;
/**
* The default style plugin for summaries.
*
* @ingroup views_style_plugins
*
* @Plugin(
* id = "jump_menu_summary",
* title = @Translation("Jump menu"),
* help = @Translation("Puts all of the results into a select box and allows the user to go to a different page based upon the results."),
* theme = "views_view_summary_jump_menu",
* uses_options = TRUE,
* type = "summary",
* help_topic = "style-summary-jump-menu"
* )
*/
class JumpMenuSummary extends DefaultSummary {
function option_definition() {
$options = parent::option_definition();
$options['base_path'] = array('default' => '');
$options['count'] = array('default' => TRUE, 'bool' => TRUE);
$options['hide'] = array('default' => FALSE, 'bool' => TRUE);
$options['text'] = array('default' => 'Go', 'translatable' => TRUE);
$options['choose'] = array('default' => '- Choose -', 'translatable' => TRUE);
$options['default_value'] = array('default' => FALSE, 'bool' => TRUE);
return $options;
}
function query() {
// Copy the offset option.
$pager = array(
'type' => 'none',
'options' => $this->display->handler->options['pager']['options'],
);
$this->display->handler->set_option('pager', $pager);
}
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['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 contextual filter value'),
'#default_value' => !empty($this->options['default_value']),
'#description' => t('If checked, the current contextual filter value 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 = '';
$row_args = array();
foreach ($this->view->result as $id => $row) {
$row_args[$id] = $argument->summary_argument($row);
}
$argument->process_summary_arguments($row_args);
foreach ($this->view->result as $id => $row) {
$args = $this->view->args;
$args[$argument->position] = $row_args[$id];
$base_path = NULL;
if (!empty($argument->options['summary_options']['base_path'])) {
$base_path = $argument->options['summary_options']['base_path'];
}
$path = url($this->view->get_url($args, $base_path), $url_options);
$summary_value = strip_tags($argument->summary_name($row));
$key = md5($path . $summary_value) . "::" . $path;
$options[$key] = $summary_value;
if (!empty($this->options['count'])) {
$options[$key] .= ' (' . intval($row->{$argument->count_alias}) . ')';
}
if ($this->options['default_value'] && current_path() == $this->view->get_url($args)) {
$default_value = $key;
}
}
ctools_include('jump-menu');
$settings = array(
'hide' => $this->options['hide'],
'button' => $this->options['text'],
'choose' => $this->options['choose'],
'default_value' => $default_value,
);
$form = drupal_get_form('ctools_jump_menu', $options, $settings);
return drupal_render($form);
}
}
<?php
/**
* @file
* Definition of Drupal\views\Tests\Handler\FieldMathTest.
*/
namespace Drupal\views\Tests\Handler;
use Drupal\views\Tests\ViewsSqlTest;
/**
* Tests the core Drupal\views\Plugin\views\field\Math handler.
*/
class FieldMathTest extends ViewsSqlTest {
public static function getInfo() {
return array(
'name' => 'Field: Math',
'description' => 'Test the core Drupal\views\Plugin\views\field\Math handler.',
'group' => 'Views Handlers',
);
}
function viewsData() {
$data = parent::viewsData();
return $data;
}
public function testFieldCustom() {
$view = $this->getBasicView();
// Alter the text of the field to a random string.
$rand1 = rand(0, 100);
$rand2 = rand(0, 100);
$view->display['default']->handler->override_option('fields', array(
'expression' => array(
'id' => 'expression',
'table' => 'views',
'field' => 'expression',
'relationship' => 'none',
'expression' => $rand1 . ' + ' . $rand2,
),
));
$this->executeView($view);
$this->assertEqual($rand1 + $rand2, $view->style_plugin->get_field(0, 'expression'));
}
}
<?php
/**
* @file
* Definition of Drupal\views\Tests\Style\PluginStyleJumpMenuTest.
*/
namespace Drupal\views\Tests\Style;
use Drupal\views\Tests\ViewsSqlTest;
use Drupal\views\View;
/**
* Tests jump menu style functionality.
*/
class PluginStyleJumpMenuTest extends ViewsSqlTest {
public static function getInfo() {
return array(
'name' => 'Jump menu',
'description' => 'Test jump menu style functionality.',
'group' => 'Views Plugins',
);
}
public function setUp() {
parent::setUp();
$this->nodes = array();
$this->nodes['page'][] = $this->drupalCreateNode(array('type' => 'page'));
$this->nodes['page'][] = $this->drupalCreateNode(array('type' => 'page'));
$this->nodes['story'][] = $this->drupalCreateNode(array('type' => 'story'));
$this->nodes['story'][] = $this->drupalCreateNode(array('type' => 'story'));
$this->nodeTitles = array($this->nodes['page'][0]->label(), $this->nodes['page'][1]->label(), $this->nodes['story'][0]->label(), $this->nodes['story'][1]->label());
}
/**
* Tests jump menues with more then one same path but maybe differnet titles.
*/
function testDuplicatePaths() {
$view = $this->getJumpMenuView();
$view->set_display();
$view->init_handlers();
// Setup a [path] which would leed to "duplicate" paths, but still the shouldn't be used for grouping.
$view->field['nothing']->options['alter']['text'] = '[path]';
$view->preview();
$form = $view->style_plugin->render($view->result);
// As there is no grouping setup it should be 4 elements.
$this->assertEqual(count($form['jump']['#options']), 4 + 1);
// Check that all titles are part of the form as well.
$options = array_values($form['jump']['#options']);
foreach ($options as $key => $title) {
// The first one is the choose label.
if ($key == 0) {
continue;
}
$this->assertTrue($this->nodeTitles[$key - 1] == trim($title), t('Title @title should appear on the jump list, as we do not filter', array('@title' => $title)));
}
}
function getJumpMenuView() {
$view = new View();
$view->name = 'test_jump_menu';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'node';
$view->human_name = 'test_jump_menu';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['query']['options']['query_comment'] = FALSE;
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['style_plugin'] = 'jump_menu';
$handler->display->display_options['style_options']['hide'] = 0;
$handler->display->display_options['style_options']['path'] = 'nothing';
$handler->display->display_options['style_options']['default_value'] = 0;
$handler->display->display_options['row_plugin'] = 'fields';
/* Field: Content: Title */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'node';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['label'] = '';
$handler->display->display_options['fields']['title']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['title']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['title']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['title']['alter']['word_boundary'] = 0;
$handler->display->display_options['fields']['title']['alter']['ellipsis'] = 0;
$handler->display->display_options['fields']['title']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['title']['alter']['trim'] = 0;
$handler->display->display_options['fields']['title']['alter']['html'] = 0;
$handler->display->display_options['fields']['title']['hide_empty'] = 0;
$handler->display->display_options['fields']['title']['empty_zero'] = 0;
$handler->display->display_options['fields']['title']['link_to_node'] = 1;
/* Field: Content: Type */
$handler->display->display_options['fields']['type']['id'] = 'type';
$handler->display->display_options['fields']['type']['table'] = 'node';
$handler->display->display_options['fields']['type']['field'] = 'type';
$handler->display->display_options['fields']['type']['exclude'] = 1;
/* Field: Global: Custom text */
$handler->display->display_options['fields']['nothing']['id'] = 'nothing';
$handler->display->display_options['fields']['nothing']['table'] = 'views';
$handler->display->display_options['fields']['nothing']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing']['alter']['text'] = '[type]';
$handler->display->display_options['fields']['nothing']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['external'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['replace_spaces'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['trim_whitespace'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['nothing']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['nothing']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['trim'] = 0;
$handler->display->display_options['fields']['nothing']['alter']['html'] = 0;
$handler->display->display_options['fields']['nothing']['element_label_colon'] = 1;
$handler->display->display_options['fields']['nothing']['element_default_classes'] = 1;
$handler->display->display_options['fields']['nothing']['hide_empty'] = 0;
$handler->display->display_options['fields']['nothing']['empty_zero'] = 0;
$handler->display->display_options['fields']['nothing']['hide_alter_empty'] = 0;
$handler->display->display_options['fields']['nothing']['exclude'] = 1;
/* Sort criterion: Content: Post date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'node';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';
/* Filter criterion: Content: Published */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'node';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = 1;
$handler->display->display_options['filters']['status']['group'] = 0;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
return $view;
}
}
<?php
/**
* @file
* Definition of Drupal\views\Tests\WizardJumpMenuTest.
*/
namespace Drupal\views\Tests;
/**
* Tests the ability of the views wizard to create views with a jump menu style plugin.
*/
class WizardJumpMenuTest extends WizardTestBase {
public static function getInfo() {
return array(
'name' => 'Views UI wizard jump menu functionality',
'description' => 'Test the ability of the views wizard to create views with a jump menu style plugin.',
'group' => 'Views UI',
);
}
/**
* Tests the jump menu style plugin.
*/
function testJumpMenus() {
views_invalidate_cache();
// We'll run this test for several different base tables that appear in the
// wizard.
$base_table_methods = array(
'node' => 'createNodeAndGetPath',
'users' => 'createUserAndGetPath',
'comment' => 'createCommentAndGetPath',
'taxonomy_term' => 'createTaxonomyTermAndGetPath',
'file_managed' => 'createFileAndGetPath',
'node_revision' => 'createNodeRevisionAndGetPath',
);
foreach ($base_table_methods as $base_table => $method) {
// For each base table, find the path that we expect the jump menu to
// redirect us to.
$path_info = $this->{$method}();
if (is_array($path_info)) {
$path = $path_info['path'];
$options = isset($path_info['options']) ? $path_info['options'] : array();
}
else {
$path = $path_info;
$options = array();
}
// Create a page view for the specified base table that uses the jump
// menu style plugin.
$view = array();
$view['human_name'] = $this->randomName(16);
$view['name'] = strtolower($this->randomName(16));
$view['description'] = $this->randomName(16);
$view['show[wizard_key]'] = $base_table;
$view['page[create]'] = 1;
$view['page[title]'] = $this->randomName(16);
$view['page[path]'] = $this->randomName(16);
$view['page[style][style_plugin]'] = 'jump_menu';
$view['page[style][row_plugin]'] = 'fields';
$this->drupalPost('admin/structure/views/add', $view, t('Save & exit'));
// Submit the jump menu form, and check that we are redirected to the
// expected URL.
$edit = array();
$edit['jump'] = url($path, $options);
// The urls are built with :: to be able to have a unique path all the time,
// so try to find out the real path of $edit.
$view_object = views_get_view($view['name']);
if (!$view_object) {
$this->fail('The view could not be loaded.');
return;
}
$view_object->preview('page');
$form = $view_object->style_plugin->render();
$jump_options = $form['jump']['#options'];
foreach ($jump_options as $key => $title) {
if (strpos($key, $edit['jump']) !== FALSE) {