Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ahebrank/0e205c339078396222a78668df12d10a to your computer and use it in GitHub Desktop.

Select an option

Save ahebrank/0e205c339078396222a78668df12d10a to your computer and use it in GitHub Desktop.
diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
index efadf83126..42685c79f3 100644
--- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
+++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
@@ -6,6 +6,7 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\TermStorageInterface;
+use Drupal\taxonomy\VocabularyInterface;
use Drupal\taxonomy\VocabularyStorageInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
@@ -78,7 +79,10 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
parent::init($view, $display, $options);
if (!empty($this->definition['vocabulary'])) {
- $this->options['vid'] = $this->definition['vocabulary'];
+ $this->options['vids'] = [$this->definition['vocabulary']];
+ }
+ if (empty($this->options['vids']) && !empty($this->options['vid'])) {
+ $this->options['vids'] = [$this->options['vid']];
}
}
@@ -98,13 +102,16 @@ protected function defineOptions() {
$options['type'] = ['default' => 'textfield'];
$options['limit'] = ['default' => TRUE];
- $options['vid'] = ['default' => ''];
+ $options['vids'] = ['default' => []];
$options['hierarchy'] = ['default' => FALSE];
$options['error_message'] = ['default' => TRUE];
return $options;
}
+ /**
+ * {@inheritdoc}
+ */
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
$vocabularies = $this->vocabularyStorage->loadMultiple();
$options = [];
@@ -114,18 +121,19 @@ public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
if ($this->options['limit']) {
// We only do this when the form is displayed.
- if (empty($this->options['vid'])) {
+ if (empty($this->options['vids'])) {
$first_vocabulary = reset($vocabularies);
- $this->options['vid'] = $first_vocabulary->id();
+ $this->options['vids'] = $first_vocabulary->id();
}
if (empty($this->definition['vocabulary'])) {
- $form['vid'] = [
- '#type' => 'radios',
+ $form['vids'] = [
+ '#type' => 'checkboxes',
'#title' => $this->t('Vocabulary'),
'#options' => $options,
'#description' => $this->t('Select which vocabulary to show terms for in the regular options.'),
- '#default_value' => $this->options['vid'],
+ '#default_value' => $this->options['vids'],
+ '#required' => TRUE,
];
}
}
@@ -133,7 +141,10 @@ public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
$form['type'] = [
'#type' => 'radios',
'#title' => $this->t('Selection type'),
- '#options' => ['select' => $this->t('Dropdown'), 'textfield' => $this->t('Autocomplete')],
+ '#options' => [
+ 'select' => $this->t('Dropdown'),
+ 'textfield' => $this->t('Autocomplete'),
+ ],
'#default_value' => $this->options['type'],
];
@@ -149,19 +160,31 @@ public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
];
}
+ /**
+ * {@inheritdoc}
+ */
+ public function submitExtraOptionsForm($form, FormStateInterface $form_state) {
+ $vids = $form_state->getValue(['options', 'vids']);
+ $form_state->setValue(['options', 'vids'], array_keys(array_filter($vids)));
+ }
+
protected function valueForm(&$form, FormStateInterface $form_state) {
- $vocabulary = $this->vocabularyStorage->load($this->options['vid']);
- if (empty($vocabulary) && $this->options['limit']) {
+ $vocabularies = $this->vocabularyStorage->loadMultiple($this->options['vids']);
+ if (empty($vocabularies) && $this->options['limit']) {
$form['markup'] = [
'#markup' => '<div class="js-form-item form-item">' . $this->t('An invalid vocabulary is selected. Please change it in the options.') . '</div>',
];
return;
}
+ $vocabulary_labels = array_map(function (VocabularyInterface $vocabulary) {
+ return $vocabulary->label();
+ }, $vocabularies);
+
if ($this->options['type'] == 'textfield') {
$terms = $this->value ? Term::loadMultiple(($this->value)) : [];
$form['value'] = [
- '#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
+ '#title' => $this->options['limit'] ? $this->t('Select terms from vocabularies @vocs', ['@vocs' => implode(', ', $vocabulary_labels)]) : $this->t('Select terms'),
'#type' => 'textfield',
'#default_value' => EntityAutocomplete::getEntityLabels($terms),
];
@@ -169,21 +192,26 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
if ($this->options['limit']) {
$form['value']['#type'] = 'entity_autocomplete';
$form['value']['#target_type'] = 'taxonomy_term';
- $form['value']['#selection_settings']['target_bundles'] = [$vocabulary->id()];
+ $form['value']['#selection_settings']['target_bundles'] = array_keys($vocabularies);
$form['value']['#tags'] = TRUE;
$form['value']['#process_default_value'] = FALSE;
}
}
else {
if (!empty($this->options['hierarchy']) && $this->options['limit']) {
- $tree = $this->termStorage->loadTree($vocabulary->id(), 0, NULL, TRUE);
$options = [];
-
- if ($tree) {
- foreach ($tree as $term) {
- $choice = new \stdClass();
- $choice->option = [$term->id() => str_repeat('-', $term->depth) . \Drupal::entityManager()->getTranslationFromContext($term)->label()];
- $options[] = $choice;
+ foreach ($vocabularies as $vocabulary) {
+ $tree = $this->termStorage->loadTree($vocabulary->id(), 0, NULL, TRUE);
+ if ($tree) {
+ foreach ($tree as $term) {
+ $choice = new \stdClass();
+ $choice->option = [
+ $term->id() => str_repeat('-', $term->depth) . \Drupal::entityManager()
+ ->getTranslationFromContext($term)
+ ->label()
+ ];
+ $options[] = $choice;
+ }
}
}
}
@@ -195,12 +223,18 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
->sort('weight')
->sort('name')
->addTag('taxonomy_term_access');
- if ($this->options['limit']) {
- $query->condition('vid', $vocabulary->id());
+ $conditions = $query->orConditionGroup();
+ foreach ($vocabularies as $vocabulary) {
+ if ($this->options['limit']) {
+ $conditions->condition('vid', $vocabulary->id());
+ }
}
+ $query->condition($conditions);
$terms = Term::loadMultiple($query->execute());
foreach ($terms as $term) {
- $options[$term->id()] = \Drupal::entityManager()->getTranslationFromContext($term)->label();
+ $options[$term->id()] = \Drupal::entityManager()
+ ->getTranslationFromContext($term)
+ ->label();
}
}
@@ -238,7 +272,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
}
$form['value'] = [
'#type' => 'select',
- '#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
+ '#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @vocs', ['@vocs' => implode(', ', $vocabulary_labels)]) : $this->t('Select terms'),
'#multiple' => TRUE,
'#options' => $options,
'#size' => min(9, count($options)),
@@ -365,7 +399,9 @@ public function adminSummary() {
$this->value = array_filter($this->value);
$terms = Term::loadMultiple($this->value);
foreach ($terms as $term) {
- $this->valueOptions[$term->id()] = \Drupal::entityManager()->getTranslationFromContext($term)->label();
+ $this->valueOptions[$term->id()] = \Drupal::entityManager()
+ ->getTranslationFromContext($term)
+ ->label();
}
}
return parent::adminSummary();
@@ -390,8 +426,10 @@ public function getCacheContexts() {
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
- $vocabulary = $this->vocabularyStorage->load($this->options['vid']);
- $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName();
+ $vocabularies = $this->vocabularyStorage->loadMultiple($this->options['vids']);
+ foreach ($vocabularies as $vocabulary) {
+ $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName();
+ }
foreach ($this->termStorage->loadMultiple($this->options['value']) as $term) {
$dependencies[$term->getConfigDependencyKey()][] = $term->getConfigDependencyName();
diff --git a/core/modules/taxonomy/taxonomy.post_update.php b/core/modules/taxonomy/taxonomy.post_update.php
index 12a5962783..e311452fc0 100644
--- a/core/modules/taxonomy/taxonomy.post_update.php
+++ b/core/modules/taxonomy/taxonomy.post_update.php
@@ -125,3 +125,31 @@ function taxonomy_post_update_handle_publishing_status_addition_in_views(&$sandb
return TRUE;
});
}
+
+/**
+ * Update views using taxonomy_index_tid to use vids instead of vid.
+ */
+function taxonomy_post_update_taxonomy_index_filter_multiple_vocabularies() {
+ // Load all views.
+ $views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple();
+ /** @var \Drupal\views\Entity\View[] $views */
+ foreach ($views as $view) {
+ $save = FALSE;
+ $displays = $view->get('display');
+ foreach (array_keys($displays) as $display_id) {
+ $display =& $view->getDisplay($display_id);
+ if (!empty($display['display_options']['filters'])) {
+ foreach ($display['display_options']['filters'] as &$filter) {
+ if ($filter['plugin_id'] === 'taxonomy_index_tid' && empty($filter['vids']) && !empty($filter['vid'])) {
+ $filter['vids'] = [$filter['vid']];
+ unset($filter['vid']);
+ $save = TRUE;
+ }
+ }
+ }
+ }
+ if ($save) {
+ $view->save();
+ }
+ }
+}
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
index ab5e1d8968..ed6f3585f2 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
@@ -166,7 +166,8 @@ display:
reduce_duplicates: false
type: select
limit: true
- vid: tags
+ vids:
+ - tags
hierarchy: true
error_message: true
plugin_id: taxonomy_index_tid
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
index a5c5828c2b..0fe8db8082 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
@@ -167,7 +167,8 @@ display:
reduce_duplicates: false
type: select
limit: true
- vid: tags
+ vids:
+ - tags
hierarchy: true
error_message: true
plugin_id: taxonomy_index_tid
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
index 856543adc8..0ca41c930e 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid_depth.yml
@@ -165,7 +165,8 @@ display:
reduce_duplicates: false
type: select
limit: true
- vid: views_testing_tags
+ vids:
+ - views_testing_tags
hierarchy: true
depth: -2
error_message: true
diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
index 8b1b822e3e..edf0c03ab8 100644
--- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
+++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
@@ -24,14 +24,23 @@ class TaxonomyIndexTidUiTest extends UITestBase {
*
* @var array
*/
- public static $testViews = ['test_filter_taxonomy_index_tid', 'test_taxonomy_term_name'];
+ public static $testViews = [
+ 'test_filter_taxonomy_index_tid',
+ 'test_taxonomy_term_name',
+ ];
/**
* Modules to enable.
*
* @var array
*/
- public static $modules = ['node', 'taxonomy', 'views', 'views_ui', 'taxonomy_test_views'];
+ public static $modules = [
+ 'node',
+ 'taxonomy',
+ 'views',
+ 'views_ui',
+ 'taxonomy_test_views',
+ ];
/**
* A nested array of \Drupal\taxonomy\TermInterface objects.
@@ -46,13 +55,30 @@ class TaxonomyIndexTidUiTest extends UITestBase {
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
- $this->adminUser = $this->drupalCreateUser(['administer taxonomy', 'administer views']);
+ $this->adminUser = $this->drupalCreateUser([
+ 'administer taxonomy',
+ 'administer views',
+ ]);
$this->drupalLogin($this->adminUser);
+ $this->terms = $this->createVocabularyAndTerms('tags');
+ ViewTestData::createTestViews(get_class($this), ['taxonomy_test_views']);
+
Vocabulary::create([
- 'vid' => 'tags',
- 'name' => 'Tags',
+ 'vid' => 'empty_vocabulary',
+ 'name' => 'Empty Vocabulary',
])->save();
+ }
+
+ /**
+ * Creates a vocabulary and terms for it.
+ *
+ * @param string $vocab_id
+ * The vocabulary ID.
+ *
+ * @return \Drupal\taxonomy\TermInterface[][]
+ */
+ protected function createVocabularyAndTerms($vocab_id) {
// Setup a hierarchy which looks like this:
// term 0.0
@@ -61,22 +87,18 @@ protected function setUp($import_test_views = TRUE) {
// term 2.0
// - term 2.1
// - term 2.2
+ $terms = [];
for ($i = 0; $i < 3; $i++) {
for ($j = 0; $j <= $i; $j++) {
- $this->terms[$i][$j] = $term = Term::create([
- 'vid' => 'tags',
+ $terms[$i][$j] = $term = Term::create([
+ 'vid' => $vocab_id,
'name' => "Term $i.$j",
'parent' => isset($terms[$i][0]) ? $terms[$i][0]->id() : 0,
]);
$term->save();
}
}
- ViewTestData::createTestViews(get_class($this), ['taxonomy_test_views']);
-
- Vocabulary::create([
- 'vid' => 'empty_vocabulary',
- 'name' => 'Empty Vocabulary',
- ])->save();
+ return $terms;
}
/**
@@ -126,6 +148,75 @@ public function testFilterUI() {
$this->assertIdentical($expected, $view->calculateDependencies()->getDependencies());
}
+ public function testFilterUIWithMoreVocabularies() {
+ $terms2 = $this->createVocabularyAndTerms('tags2');
+ $node_type = $this->drupalCreateContentType(['type' => 'page']);
+ // Create the tag field itself.
+ $field_name = 'taxonomy_tags';
+ $this->createEntityReferenceField('node', $node_type->id(), $field_name, NULL, 'taxonomy_term');
+ $node0 = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'taxonomy_tags' => $this->terms[0][0]->id(),
+ ]);
+ $node0->save();
+ $node1 = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'taxonomy_tags' => $terms2[0][0]->id(),
+ ]);
+ $node1->save();
+ $node2 = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'taxonomy_tags' => [$this->terms[0][0]->id(), $terms2[0][0]->id()],
+ ]);
+ $node2->save();
+ $edit = [
+ 'options[vids][tags]' => TRUE,
+ 'options[vids][tags2]' => TRUE,
+ 'options[type]' => 'textfield',
+ ];
+ $this->drupalPostForm('admin/structure/views/nojs/handler-extra/test_filter_taxonomy_index_tid/default/filter/tid', $edit, 'Apply');
+ $this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid', [], 'Expose filter');
+ $edit = [
+ 'options[operator]' => 'and',
+ 'options[value]' => '',
+ 'options[reduce_duplicates]' => TRUE
+ ];
+ $this->drupalPostForm(NULL, $edit, 'Apply');
+ $this->drupalPostForm(NULL, [], 'Save');
+ $this->drupalGet('test-filter-taxonomy-index-tid', ['query' => ['tid' => '']]);
+ $xpath = $this->xpath('//div[@class="view-content"]//a');
+ $this->assertIdentical(3, count($xpath));
+ $this->drupalGet('test-filter-taxonomy-index-tid', ['query' => ['tid' => "t1 ({$this->terms[0][0]->id()})"]]);
+ $xpath = $this->xpath('//div[@class="view-content"]//a');
+ $this->assertIdentical(2, count($xpath));
+ $xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [
+ ':href' => $node0->toUrl()->toString()
+ ]);
+ $this->assertIdentical(1, count($xpath));
+ $xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [
+ ':href' => $node2->toUrl()->toString()
+ ]);
+ $this->assertIdentical(1, count($xpath));
+ $this->drupalGet('test-filter-taxonomy-index-tid', ['query' => ['tid' => "t2 ({$terms2[0][0]->id()})"]]);
+ $xpath = $this->xpath('//div[@class="view-content"]//a');
+ $this->assertIdentical(2, count($xpath));
+ $xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [
+ ':href' => $node1->toUrl()->toString()
+ ]);
+ $this->assertIdentical(1, count($xpath));
+ $xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [
+ ':href' => $node2->toUrl()->toString()
+ ]);
+ $this->assertIdentical(1, count($xpath));
+ $this->drupalGet('test-filter-taxonomy-index-tid', ['query' => ['tid' => "t1 ({$this->terms[0][0]->id()}), t2 ({$terms2[0][0]->id()})"]]);
+ $xpath = $this->xpath('//div[@class="view-content"]//a');
+ $this->assertIdentical(1, count($xpath));
+ $xpath = $this->xpath('//div[@class="view-content"]//a[@href=:href]', [
+ ':href' => $node2->toUrl()->toString()
+ ]);
+ $this->assertIdentical(1, count($xpath));
+ }
+
/**
* Tests exposed taxonomy filters.
*/
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index b82f36d4a5..09a5bc594f 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -29,7 +29,9 @@ function views_help($route_name, RouteMatchInterface $route_match) {
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Views module provides a back end to fetch information from content, user accounts, taxonomy terms, and other entities from the database and present it to the user as a grid, HTML list, table, unformatted list, etc. The resulting displays are known generally as <em>views</em>.') . '</p>';
$output .= '<p>' . t('For more information, see the <a href=":views">online documentation for the Views module</a>.', [':views' => 'https://www.drupal.org/documentation/modules/views']) . '</p>';
- $output .= '<p>' . t('In order to create and modify your own views using the administration and configuration user interface, you will need to enable either the Views UI module in core or a contributed module that provides a user interface for Views. See the <a href=":views-ui">Views UI module help page</a> for more information.', [':views-ui' => (\Drupal::moduleHandler()->moduleExists('views_ui')) ? \Drupal::url('help.page', ['name' => 'views_ui']) : '#']) . '</p>';
+ $output .= '<p>' . t('In order to create and modify your own views using the administration and configuration user interface, you will need to enable either the Views UI module in core or a contributed module that provides a user interface for Views. See the <a href=":views-ui">Views UI module help page</a> for more information.', [
+ ':views-ui' => (\Drupal::moduleHandler()->moduleExists('views_ui')) ? \Drupal::url('help.page', ['name' => 'views_ui']) : '#'
+ ]) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Adding functionality to administrative pages') . '</dt>';
@@ -91,7 +93,12 @@ function views_theme($existing, $type, $theme, $path) {
// Our extra version of pager from pager.inc
$hooks['views_mini_pager'] = $base + [
- 'variables' => ['tags' => [], 'quantity' => 9, 'element' => 0, 'parameters' => []],
+ 'variables' => [
+ 'tags' => [],
+ 'quantity' => 9,
+ 'element' => 0,
+ 'parameters' => [],
+ ],
];
$variables = [
@@ -113,8 +120,18 @@ function views_theme($existing, $type, $theme, $path) {
'attachment_before' => [],
'attachment_after' => [],
],
- 'style' => ['view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL],
- 'row' => ['view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL],
+ 'style' => [
+ 'view' => NULL,
+ 'options' => NULL,
+ 'rows' => NULL,
+ 'title' => NULL,
+ ],
+ 'row' => [
+ 'view' => NULL,
+ 'options' => NULL,
+ 'row' => NULL,
+ 'field_alias' => NULL,
+ ],
'exposed_form' => ['view' => NULL, 'options' => NULL],
'pager' => [
'view' => NULL,
@@ -131,7 +148,13 @@ function views_theme($existing, $type, $theme, $path) {
'variables' => ['view' => NULL, 'field' => NULL, 'row' => NULL],
];
$hooks['views_view_grouping'] = $base + [
- 'variables' => ['view' => NULL, 'grouping' => NULL, 'grouping_level' => NULL, 'rows' => NULL, 'title' => NULL],
+ 'variables' => [
+ 'view' => NULL,
+ 'grouping' => NULL,
+ 'grouping_level' => NULL,
+ 'rows' => NULL,
+ 'title' => NULL,
+ ],
];
// Only display, pager, row, and style plugins can provide theme hooks.
@@ -241,9 +264,10 @@ function views_preprocess_node(&$variables) {
// If a node is being rendered in a view, and the view does not have a path,
// prevent drupal from accidentally setting the $page variable:
if (!empty($variables['view']->current_display)
- && $variables['page']
- && $variables['view_mode'] == 'full'
- && !$variables['view']->display_handler->hasPath()) {
+ && $variables['page']
+ && $variables['view_mode'] == 'full'
+ && !$variables['view']->display_handler->hasPath()
+ ) {
$variables['page'] = FALSE;
}
}
@@ -872,6 +896,23 @@ function views_view_presave(ViewEntityInterface $view) {
$displays = $view->get('display');
$changed = FALSE;
foreach ($displays as $display_name => &$display) {
+ if (isset($display['display_options']['filters'])) {
+ foreach ($display['display_options']['filters'] as $filter_name => $filter) {
+ if (isset($filter['plugin_id']) && $filter['plugin_id'] === 'boolean') {
+ $new_value = FALSE;
+ // Update all boolean and integer values to strings.
+ if ($filter['value'] === TRUE || $filter['value'] === 1) {
+ $new_value = '1';
+ }
+ elseif ($filter['value'] === FALSE || $filter['value'] === 0) {
+ $new_value = '0';
+ }
+ if ($new_value !== FALSE) {
+ $view->set("display.$display_name.display_options.filters.$filter_name.value", $new_value);
+ }
+ }
+ }
+ }
if (isset($display['display_options']['fields'])) {
foreach ($display['display_options']['fields'] as $field_name => &$field) {
if (isset($field['plugin_id']) && $field['plugin_id'] === 'entity_link') {
diff --git a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php
index 8e71123389..ff7f53ce6b 100644
--- a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php
+++ b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php
@@ -95,6 +95,10 @@ public function buildForm(array $form, FormStateInterface $form_state) {
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$form_state->get('handler')->validateExtraOptionsForm($form['options'], $form_state);
+
+ if ($form_state->getErrors()) {
+ $form_state->set('rerender', TRUE);
+ }
}
/**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment