Issue #1929014 by damiankloip: Fix views rest export plugin render values and add option to output raw values.

8.0.x
catch 2013-04-09 21:32:06 +01:00
parent e287c9de95
commit 90abea77fc
4 changed files with 105 additions and 48 deletions

View File

@ -40,15 +40,26 @@ class DataFieldRow extends RowPluginBase {
*/ */
protected $replacementAliases = array(); protected $replacementAliases = array();
/**
* Stores an array of options to determine if the raw field output is used.
*
* @var array
*/
protected $rawOutputOptions = array();
/** /**
* Overrides \Drupal\views\Plugin\views\row\RowPluginBase::init(). * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::init().
*/ */
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options); parent::init($view, $display, $options);
if (!empty($this->options['aliases'])) { if (!empty($this->options['field_options'])) {
$options = (array) $this->options['field_options'];
// Prepare a trimmed version of replacement aliases. // Prepare a trimmed version of replacement aliases.
$this->replacementAliases = array_filter(array_map('trim', (array) $this->options['aliases'])); $aliases = static::extractFromOptionsArray('alias', $options);
$this->replacementAliases = array_filter(array_map('trim', $aliases));
// Prepare an array of raw output field options.
$this->rawOutputOptions = static::extractFromOptionsArray('raw_output', $options);
} }
} }
@ -57,7 +68,7 @@ class DataFieldRow extends RowPluginBase {
*/ */
protected function defineOptions() { protected function defineOptions() {
$options = parent::defineOptions(); $options = parent::defineOptions();
$options['aliases'] = array('default' => array()); $options['field_options'] = array('default' => array());
return $options; return $options;
} }
@ -69,21 +80,29 @@ class DataFieldRow extends RowPluginBase {
public function buildOptionsForm(&$form, &$form_state) { public function buildOptionsForm(&$form, &$form_state) {
parent::buildOptionsForm($form, $form_state); parent::buildOptionsForm($form, $form_state);
$form['aliases'] = array( $form['field_options'] = array(
'#type' => 'fieldset', '#type' => 'table',
'#title' => t('Field ID aliases'), '#header' => array(t('Field'), t('Alias'), t('Raw output')),
'#description' => t('Rename views default field IDs in the output data.'), '#empty' => t('You have no fields. Add some to your view.'),
'#tree' => TRUE, '#tree' => TRUE,
); );
$options = $this->options['field_options'];
if ($fields = $this->view->display_handler->getOption('fields')) { if ($fields = $this->view->display_handler->getOption('fields')) {
foreach ($fields as $id => $field) { foreach ($fields as $id => $field) {
$form['aliases'][$id] = array( $form['field_options'][$id]['field'] = array(
'#markup' => $id,
);
$form['field_options'][$id]['alias'] = array(
'#type' => 'textfield', '#type' => 'textfield',
'#title' => $id, '#default_value' => isset($options[$id]['alias']) ? $options[$id]['alias'] : '',
'#default_value' => isset($this->options['aliases'][$id]) ? $this->options['aliases'][$id] : '',
'#element_validate' => array(array($this, 'validateAliasName')), '#element_validate' => array(array($this, 'validateAliasName')),
); );
$form['field_options'][$id]['raw_output'] = array(
'#type' => 'checkbox',
'#default_value' => isset($options[$id]['raw_output']) ? $options[$id]['raw_output'] : '',
);
} }
} }
} }
@ -101,10 +120,12 @@ class DataFieldRow extends RowPluginBase {
* Overrides \Drupal\views\Plugin\views\row\RowPluginBase::validateOptionsForm(). * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::validateOptionsForm().
*/ */
public function validateOptionsForm(&$form, &$form_state) { public function validateOptionsForm(&$form, &$form_state) {
$aliases = $form_state['values']['row_options']['aliases']; // Collect an array of aliases to validate.
$aliases = static::extractFromOptionsArray('alias', $form_state['values']['row_options']['field_options']);
// If array filter returns empty, no values have been entered. Unique keys // If array filter returns empty, no values have been entered. Unique keys
// should only be validated if we have some. // should only be validated if we have some.
if (array_filter($aliases) && (array_unique($aliases) !== $aliases)) { if (($filtered = array_filter($aliases)) && (array_unique($filtered) !== $filtered)) {
form_set_error('aliases', t('All field aliases must be unique')); form_set_error('aliases', t('All field aliases must be unique'));
} }
} }
@ -116,14 +137,14 @@ class DataFieldRow extends RowPluginBase {
$output = array(); $output = array();
foreach ($this->view->field as $id => $field) { foreach ($this->view->field as $id => $field) {
// If we don't have a field alias, Just try to get the rendered output // If this is not unknown and the raw output option has been set, just get
// from the field. // the raw value.
if ($field->field_alias == 'unknown') { if (($field->field_alias != 'unknown') && !empty($this->rawOutputOptions[$id])) {
$value = $field->render($row); $value = $field->sanitizeValue($field->get_value($row), 'xss_admin');
} }
// Get the value directly from the result row. // Otherwise, pass this through the field render() method.
else { else {
$value = $row->{$field->field_alias}; $value = $field->render($row);
} }
$output[$this->getFieldKeyAlias($id)] = $value; $output[$this->getFieldKeyAlias($id)] = $value;
@ -149,4 +170,21 @@ class DataFieldRow extends RowPluginBase {
return $id; return $id;
} }
/**
* Extracts a set of option values from a nested options array.
*
* @param string $key
* The key to extract from each array item.
* @param array $options
* The options array to return values from.
*
* @return array
* A regular one dimensional array of values.
*/
protected static function extractFromOptionsArray($key, $options) {
return array_map(function($item) use ($key) {
return isset($item[$key]) ? $item[$key] : NULL;
}, $options);
}
} }

View File

@ -82,12 +82,7 @@ class StyleSerializerTest extends PluginTestBase {
foreach ($view->result as $row) { foreach ($view->result as $row) {
$expected_row = array(); $expected_row = array();
foreach ($view->field as $id => $field) { foreach ($view->field as $id => $field) {
if ($field->field_alias == 'unknown') { $expected_row[$id] = $field->render($row);
$expected_row[$id] = $field->render($row);
}
else {
$expected_row[$id] = $row->{$field->field_alias};
}
} }
$expected[] = $expected_row; $expected[] = $expected_row;
} }
@ -146,7 +141,7 @@ class StyleSerializerTest extends PluginTestBase {
// Test an empty string for an alias, this should not be used. This also // Test an empty string for an alias, this should not be used. This also
// tests that the form can be submitted with no aliases. // tests that the form can be submitted with no aliases.
$this->drupalPost($row_options, array('row_options[aliases][name]' => ''), t('Apply')); $this->drupalPost($row_options, array('row_options[field_options][name][alias]' => ''), t('Apply'));
$this->drupalPost(NULL, array(), t('Save')); $this->drupalPost(NULL, array(), t('Save'));
$view = views_get_view('test_serializer_display_field'); $view = views_get_view('test_serializer_display_field');
@ -157,13 +152,7 @@ class StyleSerializerTest extends PluginTestBase {
foreach ($view->result as $row) { foreach ($view->result as $row) {
$expected_row = array(); $expected_row = array();
foreach ($view->field as $id => $field) { foreach ($view->field as $id => $field) {
// Original field key is expected. $expected_row[$id] = $field->render($row);
if ($field->field_alias == 'unknown') {
$expected_row[$id] = $field->render($row);
}
else {
$expected_row[$id] = $row->{$field->field_alias};
}
} }
$expected[] = $expected_row; $expected[] = $expected_row;
} }
@ -172,35 +161,34 @@ class StyleSerializerTest extends PluginTestBase {
$this->assertIdentical($this->drupalGetAJAX('test/serialize/field'), $expected); $this->assertIdentical($this->drupalGetAJAX('test/serialize/field'), $expected);
// Test a random aliases for fields, they should be replaced. // Test a random aliases for fields, they should be replaced.
$random_name = $this->randomName(); $alias_map = array(
// Use # to produce an invalid character for the validation. 'name' => $this->randomName(),
$invalid_random_name = '#' . $this->randomName(); // Use # to produce an invalid character for the validation.
$edit = array('row_options[aliases][name]' => $random_name, 'row_options[aliases][nothing]' => $invalid_random_name); 'nothing' => '#' . $this->randomName(),
'created' => 'created',
);
$edit = array('row_options[field_options][name][alias]' => $alias_map['name'], 'row_options[field_options][nothing][alias]' => $alias_map['nothing']);
$this->drupalPost($row_options, $edit, t('Apply')); $this->drupalPost($row_options, $edit, t('Apply'));
$this->assertText(t('The machine-readable name must contain only letters, numbers, dashes and underscores.')); $this->assertText(t('The machine-readable name must contain only letters, numbers, dashes and underscores.'));
$random_name_custom = $this->randomName(); // Change the map alias value to a valid one.
$edit = array('row_options[aliases][name]' => $random_name, 'row_options[aliases][nothing]' => $random_name_custom); $alias_map['nothing'] = $this->randomName();
$edit = array('row_options[field_options][name][alias]' => $alias_map['name'], 'row_options[field_options][nothing][alias]' => $alias_map['nothing']);
$this->drupalPost($row_options, $edit, t('Apply')); $this->drupalPost($row_options, $edit, t('Apply'));
$this->drupalPost(NULL, array(), t('Save')); $this->drupalPost(NULL, array(), t('Save'));
$view = views_get_view('test_serializer_display_field'); $view = views_get_view('test_serializer_display_field');
$view->setDisplay('ws_endpoint_1'); $view->setDisplay('rest_export_1');
$this->executeView($view); $this->executeView($view);
$expected = array(); $expected = array();
foreach ($view->result as $row) { foreach ($view->result as $row) {
$expected_row = array(); $expected_row = array();
foreach ($view->field as $id => $field) { foreach ($view->field as $id => $field) {
// This will be the custom field. $expected_row[$alias_map[$id]] = $field->render($row);
if ($field->field_alias == 'unknown') {
$expected_row[$random_name_custom] = $field->render($row);
}
// This will be the name field.
else {
$expected_row[$random_name] = $row->{$field->field_alias};
}
} }
$expected[] = $expected_row; $expected[] = $expected_row;
} }
@ -208,4 +196,30 @@ class StyleSerializerTest extends PluginTestBase {
$this->assertIdentical($this->drupalGetAJAX('test/serialize/field'), $expected); $this->assertIdentical($this->drupalGetAJAX('test/serialize/field'), $expected);
} }
/**
* Tests the raw output options for row field rendering.
*/
public function testFieldRawOutput() {
$this->drupalLogin($this->adminUser);
// Test the UI settings for adding field ID aliases.
$this->drupalGet('admin/structure/views/view/test_serializer_display_field/edit/rest_export_1');
$row_options = 'admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/row_options';
$this->assertLinkByHref($row_options);
// Test an empty string for an alias, this should not be used. This also
// tests that the form can be submitted with no aliases.
$this->drupalPost($row_options, array('row_options[field_options][created][raw_output]' => '1'), t('Apply'));
$this->drupalPost(NULL, array(), t('Save'));
$view = views_get_view('test_serializer_display_field');
$view->setDisplay('rest_export_1');
$this->executeView($view);
// Just test the raw 'created' value against each row.
foreach ($this->drupalGetAJAX('test/serialize/field') as $index => $values) {
$this->assertIdentical($values['created'], $view->result[$index]->views_test_data_created, 'Expected raw created value found.');
}
}
} }

View File

@ -45,6 +45,11 @@ display:
alter_text: '1' alter_text: '1'
text: TEST text: TEST
plugin_id: custom plugin_id: custom
created:
id: created
table: views_test_data
field: created
plugin_id: date
sorts: sorts:
created: created:
id: created id: created

View File

@ -208,7 +208,7 @@ abstract class HandlerBase extends PluginBase {
* @return string * @return string
* Returns the safe value. * Returns the safe value.
*/ */
protected function sanitizeValue($value, $type = NULL) { public function sanitizeValue($value, $type = NULL) {
switch ($type) { switch ($type) {
case 'xss': case 'xss':
$value = filter_xss($value); $value = filter_xss($value);