/** * Processes attachments for HtmlResponse responses. * * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event * The event to process. */ public function onRespond(FilterResponseEvent $event) { $response = $event->getResponse(); if (!$response instanceof HtmlResponse) { return; } $event->setResponse($this->htmlResponseAttachmentsProcessor->processAttachments($response)); }
/** * Renders the ajax commands right before preparing the result. * * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event * The response event, which contains the possible AjaxResponse object. */ public function onResponse(FilterResponseEvent $event) { $response = $event->getResponse(); if ($response instanceof AjaxResponse) { $this->ajaxResponseAttachmentsProcessor->processAttachments($response); // IE 9 does not support XHR 2 (http://caniuse.com/#feat=xhr2), so // for that browser, jquery.form submits requests containing a file upload // via an IFRAME rather than via XHR. Since the response is being sent to // an IFRAME, it must be formatted as HTML. Specifically: // - It must use the text/html content type or else the browser will // present a download prompt. Note: This applies to both file uploads // as well as any ajax request in a form with a file upload form. // - It must place the JSON data into a textarea to prevent browser // extensions such as Linkification and Skype's Browser Highlighter // from applying HTML transformations such as URL or phone number to // link conversions on the data values. // // Since this affects the format of the output, it could be argued that // this should be implemented as a separate Accept MIME type. However, // that would require separate variants for each type of AJAX request // (e.g., drupal-ajax, drupal-dialog, drupal-modal), so for expediency, // this browser workaround is implemented via a GET or POST parameter. // // @see http://malsup.com/jquery/form/#file-upload // @see https://www.drupal.org/node/1009382 // @see https://www.drupal.org/node/2339491 // @see Drupal.ajax.prototype.beforeSend() $accept = $event->getRequest()->headers->get('accept'); if (strpos($accept, 'text/html') !== FALSE) { $response->headers->set('Content-Type', 'text/html; charset=utf-8'); // Browser IFRAMEs expect HTML. Browser extensions, such as Linkification // and Skype's Browser Highlighter, convert URLs, phone numbers, etc. // into links. This corrupts the JSON response. Protect the integrity of // the JSON data by making it the value of a textarea. // @see http://malsup.com/jquery/form/#file-upload // @see https://www.drupal.org/node/1009382 $response->setContent('<textarea>' . $response->getContent() . '</textarea>'); } // User-uploaded files cannot set any response headers, so a custom header // is used to indicate to ajax.js that this response is safe. Note that // most Ajax requests bound using the Form API will be protected by having // the URL flagged as trusted in Drupal.settings, so this header is used // only for things like custom markup that gets Ajax behaviors attached. $response->headers->set('X-Drupal-Ajax-Token', 1); } }
/** * {@inheritdoc} */ public function renderBarePage(array $content, $title, $page_theme_property, array $page_additions = []) { $attributes = ['class' => [str_replace('_', '-', $page_theme_property)]]; $html = ['#type' => 'html', '#attributes' => $attributes, 'page' => ['#type' => 'page', '#theme' => $page_theme_property, '#title' => $title, 'content' => $content] + $page_additions]; // For backwards compatibility. // @todo In Drupal 9, add a $show_messages function parameter. if (!isset($page_additions['#show_messages']) || $page_additions['#show_messages'] === TRUE) { $html['page']['highlighted'] = ['#type' => 'status_messages']; } // Add the bare minimum of attachments from the system module and the // current maintenance theme. system_page_attachments($html['page']); $this->renderer->renderRoot($html); $response = new HtmlResponse(); $response->setContent($html); // Process attachments, because this does not go via the regular render // pipeline, but will be sent directly. $response = $this->htmlResponseAttachmentsProcessor->processAttachments($response); return $response; }
/** * {@inheritdoc} */ public function processAttachments(AttachmentsInterface $response) { // @todo Convert to assertion once https://www.drupal.org/node/2408013 lands if (!$response instanceof HtmlResponse) { throw new \InvalidArgumentException('\\Drupal\\Core\\Render\\HtmlResponse instance expected.'); } // First, render the actual placeholders; this will cause the BigPipe // placeholder strategy to generate BigPipe placeholders. We need those to // exist already so that we can extract BigPipe placeholders. This is hence // a bit of unfortunate but necessary duplication. // @see \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy // (Note this is copied verbatim from // \Drupal\Core\Render\HtmlResponseAttachmentsProcessor::processAttachments) try { $response = $this->renderPlaceholders($response); } catch (EnforcedResponseException $e) { return $e->getResponse(); } // Extract BigPipe placeholders; HtmlResponseAttachmentsProcessor does not // know (nor need to know) how to process those. $attachments = $response->getAttachments(); $big_pipe_placeholders = []; $big_pipe_nojs_placeholders = []; if (isset($attachments['big_pipe_placeholders'])) { $big_pipe_placeholders = $attachments['big_pipe_placeholders']; unset($attachments['big_pipe_placeholders']); } if (isset($attachments['big_pipe_nojs_placeholders'])) { $big_pipe_nojs_placeholders = $attachments['big_pipe_nojs_placeholders']; unset($attachments['big_pipe_nojs_placeholders']); } $response->setAttachments($attachments); // Call HtmlResponseAttachmentsProcessor to process all other attachments. $this->htmlResponseAttachmentsProcessor->processAttachments($response); // Restore BigPipe placeholders. $attachments = $response->getAttachments(); if (count($big_pipe_placeholders)) { $attachments['big_pipe_placeholders'] = $big_pipe_placeholders; } if (count($big_pipe_nojs_placeholders)) { $attachments['big_pipe_nojs_placeholders'] = $big_pipe_nojs_placeholders; } $response->setAttachments($attachments); return $response; }
/** * {@inheritdoc} */ public function processAttachments(AttachmentsInterface $response) { assert('$response instanceof \\Drupal\\Core\\Render\\HtmlResponse'); // First, render the actual placeholders; this will cause the BigPipe // placeholder strategy to generate BigPipe placeholders. We need those to // exist already so that we can extract BigPipe placeholders. This is hence // a bit of unfortunate but necessary duplication. // @see \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy // (Note this is copied verbatim from // \Drupal\Core\Render\HtmlResponseAttachmentsProcessor::processAttachments) try { $response = $this->renderPlaceholders($response); } catch (EnforcedResponseException $e) { return $e->getResponse(); } // Extract BigPipe placeholders; HtmlResponseAttachmentsProcessor does not // know (nor need to know) how to process those. $attachments = $response->getAttachments(); $big_pipe_placeholders = []; $big_pipe_nojs_placeholders = []; if (isset($attachments['big_pipe_placeholders'])) { $big_pipe_placeholders = $attachments['big_pipe_placeholders']; unset($attachments['big_pipe_placeholders']); } if (isset($attachments['big_pipe_nojs_placeholders'])) { $big_pipe_nojs_placeholders = $attachments['big_pipe_nojs_placeholders']; unset($attachments['big_pipe_nojs_placeholders']); } $html_response = clone $response; $html_response->setAttachments($attachments); // Call HtmlResponseAttachmentsProcessor to process all other attachments. $processed_html_response = $this->htmlResponseAttachmentsProcessor->processAttachments($html_response); // Restore BigPipe placeholders. $attachments = $processed_html_response->getAttachments(); $big_pipe_response = clone $processed_html_response; if (count($big_pipe_placeholders)) { $attachments['big_pipe_placeholders'] = $big_pipe_placeholders; } if (count($big_pipe_nojs_placeholders)) { $attachments['big_pipe_nojs_placeholders'] = $big_pipe_nojs_placeholders; } $big_pipe_response->setAttachments($attachments); return $big_pipe_response; }