Issue #1966424 by tim.plunkett, dawehner, damiankloip: Allow Views handlers to be optional.

8.0.x
webchick 2013-04-14 13:15:54 -07:00
parent 9bf03a6c3d
commit c95875b0ae
13 changed files with 146 additions and 32 deletions

View File

@ -873,7 +873,7 @@ abstract class HandlerBase extends PluginBase {
// Create a new handler and unpack the options from the form onto it. We
// can use that for storage.
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
$handler = views_get_handler($item, $handler_type, $override);
$handler->init($executable, $executable->display_handler, $item);
// Add the incoming options to existing options because items using

View File

@ -876,8 +876,7 @@ abstract class DisplayPluginBase extends PluginBase {
$handler_type = $type;
}
$handler = views_get_handler($info['table'], $info['field'], $handler_type, $override);
if ($handler) {
if ($handler = views_get_handler($info, $handler_type, $override)) {
// Special override for area types so they know where they come from.
if ($handler instanceof AreaPluginBase) {
$handler->areaType = $type;

View File

@ -83,7 +83,7 @@ class InputRequired extends ExposedFormPluginBase {
'content' => $this->options['text_input_required'],
'format' => $this->options['text_input_required_format'],
);
$handler = views_get_handler('views', 'area', 'area');
$handler = views_get_handler($options, 'area');
$handler->init($this->view, $options);
$this->displayHandler->handlers['empty'] = array(
'area' => $handler,

View File

@ -71,7 +71,7 @@ abstract class RowPluginBase extends PluginBase {
$relationship_options = array();
foreach ($relationships as $relationship) {
$relationship_handler = views_get_handler($relationship['table'], $relationship['field'], 'relationship');
$relationship_handler = views_get_handler($relationship, 'relationship');
// If this relationship is valid for this type, add it to the list.
$data = Views::viewsData()->get($relationship['table']);

View File

@ -25,7 +25,7 @@ class GroupByNumeric extends SortPluginBase {
parent::init($view, $display, $options);
// Initialize the original handler.
$this->handler = views_get_handler($options['table'], $options['field'], 'sort');
$this->handler = views_get_handler($options, 'sort');
$this->handler->init($view, $display, $options);
}

View File

@ -525,15 +525,21 @@ class FieldUnitTest extends ViewUnitTestBase {
*/
public function testClickSortable() {
// Test that click_sortable is TRUE by default.
$plugin = views_get_handler('views_test_data', 'name', 'field');
$item = array(
'table' => 'views_test_data',
'field' => 'name',
);
$plugin = views_get_handler($item, 'field');
$this->assertTrue($plugin->click_sortable(), 'TRUE as a default value is correct.');
// Test that click_sortable is TRUE by when set TRUE in the data.
$plugin = views_get_handler('views_test_data', 'id', 'field');
$item['field'] = 'id';
$plugin = views_get_handler($item, 'field');
$this->assertTrue($plugin->click_sortable(), 'TRUE as a views data value is correct.');
// Test that click_sortable is FALSE by when set FALSE in the data.
$plugin = views_get_handler('views_test_data', 'job', 'field');
$item['field'] = 'job';
$plugin = views_get_handler($item, 'field');
$this->assertFalse($plugin->click_sortable(), 'FALSE as a views data value is correct.');
}

View File

@ -72,11 +72,15 @@ class HandlerAllTest extends HandlerTestBase {
foreach ($info as $field => $field_info) {
// Table is a reserved key for the metainformation.
if ($field != 'table' && !in_array("$base_table:$field", $exclude)) {
$item = array(
'table' => $base_table,
'field' => $field,
);
foreach ($object_types as $type) {
if (isset($field_info[$type]['id'])) {
$options = array();
if ($type == 'filter') {
$handler = views_get_handler($base_table, $field, $type);
$handler = views_get_handler($item, $type);
if ($handler instanceof InOperator) {
$options['value'] = array(1);
}

View File

@ -101,7 +101,11 @@ class HandlerTest extends ViewTestBase {
$null = NULL;
$this->assertEqual($empty_stdclass, HandlerBase::breakPhraseString('', $null));
$handler = views_get_handler('node', 'title', 'argument');
$item = array(
'table' => 'node',
'field' => 'title',
);
$handler = views_get_handler($item, 'argument');
$this->assertEqual($handler, HandlerBase::breakPhraseString('', $handler), 'The breakPhraseString() method works correctly.');
// test ors
@ -156,7 +160,11 @@ class HandlerTest extends ViewTestBase {
// check defaults
$this->assertEqual($empty_stdclass, HandlerBase::breakPhrase('', $null));
$handler = views_get_handler('node', 'title', 'argument');
$item = array(
'table' => 'node',
'field' => 'title',
);
$handler = views_get_handler($item, 'argument');
$this->assertEqual($handler, HandlerBase::breakPhrase('', $handler), 'The breakPhrase() method works correctly.');
// Generate three random numbers which can be used below;

View File

@ -10,6 +10,7 @@ namespace Drupal\views\Tests;
/**
* Tests basic functions from the Views module.
*/
use Drupal\views\Plugin\views\filter\Standard;
use Drupal\views\Views;
class ModuleTest extends ViewUnitTestBase {
@ -21,6 +22,15 @@ class ModuleTest extends ViewUnitTestBase {
*/
public static $testViews = array('test_view_status');
/**
* Stores the last triggered error, for example via debug().
*
* @var string
*
* @see \Drupal\views\Tests\ModuleTest::errorHandler()
*/
protected $lastErrorMessage;
public static function getInfo() {
return array(
'name' => 'Views Module tests',
@ -31,11 +41,17 @@ class ModuleTest extends ViewUnitTestBase {
/**
* Tests the views_get_handler method.
*
* @see views_get_handler()
*/
function testviews_get_handler() {
public function testViewsGetHandler() {
$types = array('field', 'area', 'filter');
foreach ($types as $type) {
$handler = views_get_handler($this->randomName(), $this->randomName(), $type);
$item = array(
'table' => $this->randomName(),
'field' => $this->randomName(),
);
$handler = views_get_handler($item, $type);
$this->assertEqual('Drupal\views\Plugin\views\\' . $type . '\Broken', get_class($handler), t('Make sure that a broken handler of type: @type are created', array('@type' => $type)));
}
@ -44,9 +60,13 @@ class ModuleTest extends ViewUnitTestBase {
foreach ($test_tables as $table => $fields) {
foreach ($fields as $field) {
$data = $views_data[$table][$field];
$item = array(
'table' => $table,
'field' => $field,
);
foreach ($data as $id => $field_data) {
if (!in_array($id, array('title', 'help'))) {
$handler = views_get_handler($table, $field, $id);
$handler = views_get_handler($item, $id);
$this->assertInstanceHandler($handler, $table, $field, $id);
}
}
@ -54,8 +74,73 @@ class ModuleTest extends ViewUnitTestBase {
}
// Test the override handler feature.
$handler = views_get_handler('views_test_data', 'job', 'filter', 'standard');
$this->assertEqual('Drupal\\views\\Plugin\\views\\filter\\Standard', get_class($handler));
$item = array(
'table' => 'views_test_data',
'field' => 'job',
);
$handler = views_get_handler($item, 'filter', 'standard');
$this->assertTrue($handler instanceof Standard);
// Test non-existent tables/fields.
set_error_handler(array($this, 'customErrorHandler'));
$item = array(
'table' => 'views_test_data',
'field' => 'field_invalid',
);
views_get_handler($item, 'field');
$this->assertTrue(strpos($this->lastErrorMessage, format_string("Missing handler: @table @field @type", array('@table' => 'views_test_data', '@field' => 'field_invalid', '@type' => 'field'))) !== FALSE, 'An invalid field name throws a debug message.');
unset($this->lastErrorMessage);
$item = array(
'table' => 'table_invalid',
'field' => 'id',
);
views_get_handler($item, 'filter');
$this->assertEqual(strpos($this->lastErrorMessage, format_string("Missing handler: @table @field @type", array('@table' => 'table_invalid', '@field' => 'id', '@type' => 'filter'))) !== FALSE, 'An invalid table name throws a debug message.');
unset($this->lastErrorMessage);
$item = array(
'table' => 'table_invalid',
'field' => 'id',
'optional' => FALSE,
);
views_get_handler($item, 'filter');
$this->assertEqual(strpos($this->lastErrorMessage, format_string("Missing handler: @table @field @type", array('@table' => 'table_invalid', '@field' => 'id', '@type' => 'filter'))) !== FALSE, 'An invalid table name throws a debug message.');
unset($this->lastErrorMessage);
$item = array(
'table' => 'table_invalid',
'field' => 'id',
'optional' => TRUE,
);
views_get_handler($item, 'filter');
$this->assertFalse($this->lastErrorMessage, "An optional handler does not throw a debug message.");
unset($this->lastErrorMessage);
restore_error_handler();
}
/**
* Defines an error handler which is used in the test.
*
* @param int $error_level
* The level of the error raised.
* @param string $message
* The error message.
* @param string $filename
* The filename that the error was raised in.
* @param int $line
* The line number the error was raised at.
* @param array $context
* An array that points to the active symbol table at the point the error
* occurred.
*
* Because this is registered in set_error_handler(), it has to be public.
* @see set_error_handler()
*/
public function customErrorHandler($error_level, $message, $filename, $line, $context) {
$this->lastErrorMessage = $message;
}
/**

View File

@ -880,21 +880,26 @@ function views_library_info() {
/**
* Fetch a handler from the data cache.
*
* @param $table
* The name of the table this handler is from.
* @param $field
* The name of the field this handler is from.
* @param $type
* @param array $item
* An associative array representing the handler to be retrieved:
* - table: The name of the table containing the handler.
* - field: The name of the field the handler represents.
* - optional: (optional) Whether or not this handler is optional. If a
* handler is missing and not optional, a debug message will be displayed.
* Defaults to FALSE.
* @param string $type
* The type of handler. i.e, sort, field, argument, filter, relationship
* @param $override
* Override the actual handler object with this class. Used for
* aggregation when the handler is redirected to the aggregation
* handler.
* @param string|null $override
* (optional) Override the actual handler object with this plugin ID. Used for
* aggregation when the handler is redirected to the aggregation handler.
*
* @return views_handler
* An instance of a handler object. May be views_handler_broken.
*/
function views_get_handler($table, $field, $type, $override = NULL) {
function views_get_handler($item, $type, $override = NULL) {
$table = $item['table'];
$field = $item['field'];
$optional = isset($item['optional']) ? $item['optional'] : FALSE;
// Get the plugin manager for this type.
$manager = Views::pluginManager($type);;
$data = Views::viewsData()->get($table);
@ -931,8 +936,11 @@ function views_get_handler($table, $field, $type, $override = NULL) {
}
}
if (!$optional) {
debug(t("Missing handler: @table @field @type", array('@table' => $table, '@field' => $field, '@type' => $type)));
}
// Finally, use the 'broken' handler.
debug(t("Missing handler: @table @field @type", array('@table' => $table, '@field' => $field, '@type' => $type)));
return $manager->createInstance('broken');
}

View File

@ -96,7 +96,7 @@ class ConfigItem extends ViewsFormBase {
if ($type == 'relationship' && $id == $relationship['id']) {
break;
}
$relationship_handler = views_get_handler($relationship['table'], $relationship['field'], 'relationship');
$relationship_handler = views_get_handler($relationship, 'relationship');
// ignore invalid/broken relationships.
if (empty($relationship_handler)) {
continue;
@ -225,7 +225,7 @@ class ConfigItem extends ViewsFormBase {
// Create a new handler and unpack the options from the form onto it. We
// can use that for storage.
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
$handler = views_get_handler($item, $handler_type, $override);
$handler->init($executable, $executable->display_handler, $item);
// Add the incoming options to existing options because items using

View File

@ -99,7 +99,7 @@ class ConfigItemGroup extends ViewsFormBase {
$type = $form_state['type'];
$id = $form_state['id'];
$handler = views_get_handler($item['table'], $item['field'], $type);
$handler = views_get_handler($item, $type);
$executable = $form_state['view']->get('executable');
$handler->init($executable, $executable->display_handler, $item);

View File

@ -458,7 +458,11 @@ class ViewUI implements ViewStorageInterface {
if (isset($types[$type]['type'])) {
$key = $types[$type]['type'];
}
$handler = views_get_handler($table, $field, $key);
$item = array(
'table' => $table,
'field' => $field,
);
$handler = views_get_handler($item, $key);
if ($this->executable->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
$this->addFormToStack('config-item-group', $form_state['display_id'], $type, $id);
}