core/modules/big_pipe/src/Render/BigPipe.php | 32 +++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/core/modules/big_pipe/src/Render/BigPipe.php b/core/modules/big_pipe/src/Render/BigPipe.php index 5e3cc12..5b45678 100644 --- a/core/modules/big_pipe/src/Render/BigPipe.php +++ b/core/modules/big_pipe/src/Render/BigPipe.php @@ -538,15 +538,41 @@ protected function renderPlaceholder($placeholder, array $placeholder_render_arr protected function getPlaceholderOrder($html) { $fragments = explode('
', $fragment, 2); $placeholder = $t[0]; - $order[] = $placeholder; + $placeholders[] = $placeholder; } + $placeholders = array_unique($placeholders); + + // The 'status messages' placeholder' needs to be special cased, because it + // depends on global state that can be modified when other placeholders are + // being rendered: any code can add messages to render. + // This violates the principle that each lazy builder must be able to render + // itself in isolation, and therefore in any order. However, we cannot + // change the way drupal_set_message() works in the Drupal 8 cycle. So we + // have to accommodate its special needs. + // Allowing placeholders to be rendered in a particular order (in this case: + // last) would violate this isolation principle. Thus a monopoly is granted + // to this one special case, with this hard-coded solution. + // @see \Drupal\Core\Render\Element\StatusMessages + // @see \Drupal\Core\Render\Renderer::replacePlaceholders() + // @see https://www.drupal.org/node/2712935#comment-11368923 + $possible_message_placeholders = [ + 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=a8c34b5e', + 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]=status&token=a26f536e', + 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]=warning&token=67320bbd', + 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]=error&token=35b549cb', + ]; - return array_unique($order); + // Render placeholders in the appropriate order. + $ordered_placeholders = array_merge( + array_diff($placeholders, $possible_message_placeholders), + array_intersect($placeholders, $possible_message_placeholders) + ); + return $ordered_placeholders; } }