Commit 22ca1c9c authored by catch's avatar catch

Issue #1985406 by jhedstrom, alexpott, Dave Reid, olli: #states not supported...

Issue #1985406 by jhedstrom, alexpott, Dave Reid, olli: #states not supported for elements in formatter settings being displayed on Views field handler form
parent ff20a6fa
<?php
/**
* @file
* Contains \Drupal\Core\Form\FormHelper.
*/
namespace Drupal\Core\Form;
use Drupal\Core\Render\Element;
/**
* Provides helpers to operate on forms.
*
* @ingroup form_api
*/
class FormHelper {
/**
* Rewrite #states selectors.
*
* @param array $elements
* A renderable array element having a #states property.
* @param string $search
* A partial or entire jQuery selector string to replace in #states.
* @param string $replace
* The string to replace all instances of $search with.
*
* @see drupal_process_states()
*/
public static function rewriteStatesSelector(array &$elements, $search, $replace) {
if (!empty($elements['#states'])) {
foreach ($elements['#states'] as $state => $ids) {
static::processStatesArray($elements['#states'][$state], $search, $replace);
}
}
foreach (Element::children($elements) as $key) {
static::rewriteStatesSelector($elements[$key], $search, $replace);
}
}
/**
* Helper function for self::rewriteStatesSelector().
*
* @param array $conditions
* States conditions array.
* @param string $search
* A partial or entire jQuery selector string to replace in #states.
* @param string $replace
* The string to replace all instances of $search with.
*/
protected static function processStatesArray(array &$conditions, $search, $replace) {
// Retrieve the keys to make it easy to rename a key without changing the
// order of an array.
$keys = array_keys($conditions);
$update_keys = FALSE;
foreach ($conditions as $id => $values) {
if (strpos($id, $search) !== FALSE) {
$update_keys = TRUE;
$new_id = str_replace($search, $replace, $id);
// Replace the key and keep the array in the same order.
$index = array_search($id, $keys, TRUE);
$keys[$index] = $new_id;
}
elseif (is_array($values)) {
static::processStatesArray($conditions[$id], $search, $replace);
}
}
// Updates the states conditions keys if necessary.
if ($update_keys) {
$conditions = array_combine($keys, array_values($conditions));
}
}
}
......@@ -15,6 +15,7 @@
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\FormatterPluginManager;
use Drupal\Core\Form\FormHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
......@@ -508,6 +509,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$settings_form = array('#value' => array());
if ($formatter = $this->formatterPluginManager->getInstance($options)) {
$settings_form = $formatter->settingsForm($form, $form_state);
// Convert field UI selector states to work in the Views field form.
FormHelper::rewriteStatesSelector($settings_form, "fields[{$field->getName()}][settings_edit_form]", 'options');
}
$form['settings'] = $settings_form;
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\views\Plugin\views\filter;
use Drupal\Core\Form\FormHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\views\Plugin\CacheablePluginInterface;
......@@ -979,39 +980,30 @@ protected function buildExposedFiltersGroupForm(&$form, FormStateInterface $form
$row['operator']['#title'] = '';
$this->valueForm($row, $form_state);
// Fix the dependencies to update value forms when operators
// changes. This is needed because forms are inside a new form and
// their ids changes. Dependencies are used when operator changes
// from to 'Between', 'Not Between', etc, and two or more widgets
// are displayed.
$without_children = TRUE;
foreach (Element::children($row['value']) as $children) {
$has_state = FALSE;
$states = array();
foreach ($row['value'][$children]['#states']['visible'] as $key => $state) {
if (isset($state[':input[name="options[operator]"]'])) {
$has_state = TRUE;
$states[$key] = $state[':input[name="options[operator]"]']['value'];
}
}
if ($has_state) {
foreach ($states as $key => $state) {
$row['value'][$children]['#states']['visible'][] = array(
':input[name="options[group_info][group_items][' . $item_id . '][operator]"]' => array('value' => $state),
);
unset($row['value'][$children]['#states']['visible'][$key]);
}
$row['value'][$children]['#title'] = '';
if (!empty($this->options['group_info']['group_items'][$item_id]['value'][$children])) {
$row['value'][$children]['#default_value'] = $this->options['group_info']['group_items'][$item_id]['value'][$children];
// Fix the dependencies to update value forms when operators changes. This
// is needed because forms are inside a new form and their IDs changes.
// Dependencies are used when operator changes from to 'Between',
// 'Not Between', etc, and two or more widgets are displayed.
FormHelper::rewriteStatesSelector($row['value'], ':input[name="options[operator]"]', ':input[name="options[group_info][group_items][' . $item_id . '][operator]"]');
// Set default values.
$children = Element::children($row['value']);
if (!empty($children)) {
foreach ($children as $child) {
foreach ($row['value'][$child]['#states']['visible'] as $state) {
if (isset($state[':input[name="options[group_info][group_items][' . $item_id . '][operator]"]'])) {
$row['value'][$child]['#title'] = '';
if (!empty($this->options['group_info']['group_items'][$item_id]['value'][$child])) {
$row['value'][$child]['#default_value'] = $this->options['group_info']['group_items'][$item_id]['value'][$child];
}
// Exit this loop and process the next child element.
break;
}
}
}
$without_children = FALSE;
}
if ($without_children) {
else {
if (isset($this->options['group_info']['group_items'][$item_id]['value']) && $this->options['group_info']['group_items'][$item_id]['value'] != '') {
$row['value']['#default_value'] = $this->options['group_info']['group_items'][$item_id]['value'];
}
......
<?php
/**
* @file
* Contains \Drupal\system\Tests\Form\FormHelperTest.
*/
namespace Drupal\Tests\Core\Form;
use Drupal\Core\Form\FormHelper;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Form\FormHelper
* @group Form
*/
class FormHelperTest extends UnitTestCase {
/**
* Tests rewriting the #states selectors.
*
* @covers ::rewriteStatesSelector
*/
function testRewriteStatesSelector() {
// Simple selectors.
$value = array('value' => 'medium');
$form['foo']['#states'] = array(
'visible' => array(
'select[name="fields[foo-id][settings_edit_form][settings][image_style]"]' => $value,
),
);
FormHelper::rewriteStatesSelector($form, 'fields[foo-id][settings_edit_form]', 'options');
$expected_selector = 'select[name="options[settings][image_style]"]';
$this->assertSame($form['foo']['#states']['visible'][$expected_selector], $value, 'The #states selector was not properly rewritten.');
// Complex selectors.
$form = array();
$form['bar']['#states'] = array(
'visible' => array(
array(
':input[name="menu[type]"]' => array('value' => 'normal'),
),
array(
':input[name="menu[type]"]' => array('value' => 'tab'),
),
':input[name="menu[type]"]' => array('value' => 'default tab'),
),
// Example from https://www.drupal.org/node/1464758
'disabled' => array(
'[name="menu[options][dependee_1]"]' => array('value' => 'ON'),
array(
array('[name="menu[options][dependee_2]"]' => array('value' => 'ON')),
array('[name="menu[options][dependee_3]"]' => array('value' => 'ON')),
),
array(
array('[name="menu[options][dependee_4]"]' => array('value' => 'ON')),
'xor',
array('[name="menu[options][dependee_5]"]' => array('value' => 'ON')),
),
),
);
$expected['bar']['#states'] = array(
'visible' => array(
array(
':input[name="options[type]"]' => array('value' => 'normal'),
),
array(
':input[name="options[type]"]' => array('value' => 'tab'),
),
':input[name="options[type]"]' => array('value' => 'default tab'),
),
'disabled' => array(
'[name="options[options][dependee_1]"]' => array('value' => 'ON'),
array(
array('[name="options[options][dependee_2]"]' => array('value' => 'ON')),
array('[name="options[options][dependee_3]"]' => array('value' => 'ON')),
),
array(
array('[name="options[options][dependee_4]"]' => array('value' => 'ON')),
'xor',
array('[name="options[options][dependee_5]"]' => array('value' => 'ON')),
),
),
);
FormHelper::rewriteStatesSelector($form, 'menu', 'options');
$this->assertSame($expected, $form, 'The #states selectors were properly rewritten.');
}
}
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