From 7b9c39c07720cb416247dc3016f4aed8c643e1e7 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Tue, 7 Jul 2015 18:00:16 +0100 Subject: [PATCH] Issue #2527606 by dawehner, plach, catch, mpdonadio, Wim Leers, xjm, Fabianx: Uncaught PHP Exception LogicException when editing Views --- .../Plugin/views/field/FieldPluginBase.php | 14 ++++++++++---- .../views_ui/src/Form/Ajax/ViewsFormBase.php | 17 ++++++++++++++++- .../modules/views_ui/src/Tests/UITestBase.php | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index f17df188766..3d1775d1e83 100644 --- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -875,10 +875,16 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf $this->documentSelfTokens($options[t('Fields')]); // Default text. - $output = '

' . $this->t('You must add some additional fields to this display before using this field. These fields may be marked as Exclude from display if you prefer. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.') . '

'; + + $output = []; + $output[] = [ + '#markup' => '

' . $this->t('You must add some additional fields to this display before using this field. These fields may be marked as Exclude from display if you prefer. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.') . '

', + ]; // We have some options, so make a list. if (!empty($options)) { - $output = '

' . $this->t("The following replacement tokens are available for this field. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.") . '

'; + $output[] = [ + '#markup' => '

' . $this->t("The following replacement tokens are available for this field. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.") . '

', + ]; foreach (array_keys($options) as $type) { if (!empty($options[$type])) { $items = array(); @@ -890,7 +896,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf '#items' => $items, '#list_type' => $type, ); - $output .= $this->getRenderer()->render($item_list); + $output[] = $item_list; } } } @@ -901,7 +907,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf $form['alter']['help'] = array( '#type' => 'details', '#title' => $this->t('Replacement patterns'), - '#value' => SafeMarkup::set($output), + '#value' => $output, '#states' => array( 'visible' => array( array( diff --git a/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php b/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php index 3c0e43517c3..d9c5dfc6324 100644 --- a/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php +++ b/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php @@ -12,6 +12,8 @@ use Drupal\Core\Ajax\OpenModalDialogCommand; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\Core\Render\RenderContext; use Drupal\views_ui\ViewUI; use Drupal\views\ViewEntityInterface; use Drupal\views\Ajax; @@ -205,8 +207,21 @@ abstract class ViewsFormBase extends FormBase implements ViewsFormInterface { } $form_state->disableCache(); - $form = \Drupal::formBuilder()->buildForm($form_class, $form_state); + // Builds the form in a render context in order to ensure that cacheable + // metadata is bubbled up. + $render_context = new RenderContext(); + $callable = function () use ($form_class, &$form_state) { + return \Drupal::formBuilder()->buildForm($form_class, $form_state); + }; + $form = $renderer->executeInRenderContext($render_context, $callable); + + if (!$render_context->isEmpty()) { + BubbleableMetadata::createFromRenderArray($form) + ->merge($render_context->pop()) + ->applyTo($form); + } $output = $renderer->renderRoot($form); + drupal_process_attached($form); // These forms have the title built in, so set the title here: diff --git a/core/modules/views_ui/src/Tests/UITestBase.php b/core/modules/views_ui/src/Tests/UITestBase.php index 1fe0cec1016..19d77e08396 100644 --- a/core/modules/views_ui/src/Tests/UITestBase.php +++ b/core/modules/views_ui/src/Tests/UITestBase.php @@ -74,4 +74,23 @@ abstract class UITestBase extends ViewTestBase { return $default; } + /** + * {@inheritdoc} + */ + protected function drupalGet($path, array $options = array(), array $headers = array()) { + $url = $this->buildUrl($path, $options); + + // Ensure that each nojs page is accessible via ajax as well. + if (strpos($url, 'nojs') !== FALSE) { + $url = str_replace('nojs', 'ajax', $url); + $result = $this->drupalGet($url, $options, $headers); + $this->assertResponse(200); + $this->assertHeader('Content-Type', 'application/json'); + $this->assertTrue(json_decode($result), 'Ensure that the AJAX request returned valid content.'); + } + + return parent::drupalGet($path, $options, $headers); + } + + }