Commit 90abea77 authored by catch's avatar catch
Browse files

Issue #1929014 by damiankloip: Fix views rest export plugin render values and...

Issue #1929014 by damiankloip: Fix views rest export plugin render values and add option to output raw values.
parent e287c9de
......@@ -40,15 +40,26 @@ class DataFieldRow extends RowPluginBase {
*/
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().
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
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.
$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 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['aliases'] = array('default' => array());
$options['field_options'] = array('default' => array());
return $options;
}
......@@ -69,21 +80,29 @@ protected function defineOptions() {
public function buildOptionsForm(&$form, &$form_state) {
parent::buildOptionsForm($form, $form_state);
$form['aliases'] = array(
'#type' => 'fieldset',
'#title' => t('Field ID aliases'),
'#description' => t('Rename views default field IDs in the output data.'),
$form['field_options'] = array(
'#type' => 'table',
'#header' => array(t('Field'), t('Alias'), t('Raw output')),
'#empty' => t('You have no fields. Add some to your view.'),
'#tree' => TRUE,
);
$options = $this->options['field_options'];
if ($fields = $this->view->display_handler->getOption('fields')) {
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',
'#title' => $id,
'#default_value' => isset($this->options['aliases'][$id]) ? $this->options['aliases'][$id] : '',
'#default_value' => isset($options[$id]['alias']) ? $options[$id]['alias'] : '',
'#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 @@ public function validateAliasName($element, &$form_state) {
* Overrides \Drupal\views\Plugin\views\row\RowPluginBase::validateOptionsForm().
*/
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
// 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'));
}
}
......@@ -116,14 +137,14 @@ public function render($row) {
$output = array();
foreach ($this->view->field as $id => $field) {
// If we don't have a field alias, Just try to get the rendered output
// from the field.
if ($field->field_alias == 'unknown') {
$value = $field->render($row);
// If this is not unknown and the raw output option has been set, just get
// the raw value.
if (($field->field_alias != 'unknown') && !empty($this->rawOutputOptions[$id])) {
$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 {
$value = $row->{$field->field_alias};
$value = $field->render($row);
}
$output[$this->getFieldKeyAlias($id)] = $value;
......@@ -149,4 +170,21 @@ public function getFieldKeyAlias($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);
}
}
......@@ -82,12 +82,7 @@ public function testSerializerResponses() {
foreach ($view->result as $row) {
$expected_row = array();
foreach ($view->field as $id => $field) {
if ($field->field_alias == 'unknown') {
$expected_row[$id] = $field->render($row);
}
else {
$expected_row[$id] = $row->{$field->field_alias};
}
$expected_row[$id] = $field->render($row);
}
$expected[] = $expected_row;
}
......@@ -146,7 +141,7 @@ public function testUIFieldAlias() {
// 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[aliases][name]' => ''), t('Apply'));
$this->drupalPost($row_options, array('row_options[field_options][name][alias]' => ''), t('Apply'));
$this->drupalPost(NULL, array(), t('Save'));
$view = views_get_view('test_serializer_display_field');
......@@ -157,13 +152,7 @@ public function testUIFieldAlias() {
foreach ($view->result as $row) {
$expected_row = array();
foreach ($view->field as $id => $field) {
// Original field key is expected.
if ($field->field_alias == 'unknown') {
$expected_row[$id] = $field->render($row);
}
else {
$expected_row[$id] = $row->{$field->field_alias};
}
$expected_row[$id] = $field->render($row);
}
$expected[] = $expected_row;
}
......@@ -172,35 +161,34 @@ public function testUIFieldAlias() {
$this->assertIdentical($this->drupalGetAJAX('test/serialize/field'), $expected);
// Test a random aliases for fields, they should be replaced.
$random_name = $this->randomName();
// Use # to produce an invalid character for the validation.
$invalid_random_name = '#' . $this->randomName();
$edit = array('row_options[aliases][name]' => $random_name, 'row_options[aliases][nothing]' => $invalid_random_name);
$alias_map = array(
'name' => $this->randomName(),
// Use # to produce an invalid character for the validation.
'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->assertText(t('The machine-readable name must contain only letters, numbers, dashes and underscores.'));
$random_name_custom = $this->randomName();
$edit = array('row_options[aliases][name]' => $random_name, 'row_options[aliases][nothing]' => $random_name_custom);
// Change the map alias value to a valid one.
$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(NULL, array(), t('Save'));
$view = views_get_view('test_serializer_display_field');
$view->setDisplay('ws_endpoint_1');
$view->setDisplay('rest_export_1');
$this->executeView($view);
$expected = array();
foreach ($view->result as $row) {
$expected_row = array();
foreach ($view->field as $id => $field) {
// This will be the custom field.
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_row[$alias_map[$id]] = $field->render($row);
}
$expected[] = $expected_row;
}
......@@ -208,4 +196,30 @@ public function testUIFieldAlias() {
$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.');
}
}
}
......@@ -45,6 +45,11 @@ display:
alter_text: '1'
text: TEST
plugin_id: custom
created:
id: created
table: views_test_data
field: created
plugin_id: date
sorts:
created:
id: created
......
......@@ -208,7 +208,7 @@ public function getField($field = NULL) {
* @return string
* Returns the safe value.
*/
protected function sanitizeValue($value, $type = NULL) {
public function sanitizeValue($value, $type = NULL) {
switch ($type) {
case 'xss':
$value = filter_xss($value);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment