Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\EventSubscriber; | |
4 | |
5 use Drupal\Component\Utility\Html; | |
6 use Drupal\Core\Ajax\AjaxResponse; | |
7 use Drupal\Core\Render\AttachmentsResponseProcessorInterface; | |
8 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
9 use Symfony\Component\HttpKernel\Event\FilterResponseEvent; | |
10 use Symfony\Component\HttpKernel\Event\GetResponseEvent; | |
11 use Symfony\Component\HttpKernel\KernelEvents; | |
12 | |
13 /** | |
14 * Response subscriber to handle AJAX responses. | |
15 */ | |
16 class AjaxResponseSubscriber implements EventSubscriberInterface { | |
17 | |
18 /** | |
19 * The AJAX response attachments processor service. | |
20 * | |
21 * @var \Drupal\Core\Render\AttachmentsResponseProcessorInterface | |
22 */ | |
23 protected $ajaxResponseAttachmentsProcessor; | |
24 | |
25 /** | |
26 * Constructs an AjaxResponseSubscriber object. | |
27 * | |
28 * @param \Drupal\Core\Render\AttachmentsResponseProcessorInterface $ajax_response_attachments_processor | |
29 * The AJAX response attachments processor service. | |
30 */ | |
31 public function __construct(AttachmentsResponseProcessorInterface $ajax_response_attachments_processor) { | |
32 $this->ajaxResponseAttachmentsProcessor = $ajax_response_attachments_processor; | |
33 } | |
34 | |
35 /** | |
36 * Request parameter to indicate that a request is a Drupal Ajax request. | |
37 */ | |
38 const AJAX_REQUEST_PARAMETER = '_drupal_ajax'; | |
39 | |
40 /** | |
41 * Sets the AJAX parameter from the current request. | |
42 * | |
43 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event | |
44 * The response event, which contains the current request. | |
45 */ | |
46 public function onRequest(GetResponseEvent $event) { | |
47 // Pass to the Html class that the current request is an Ajax request. | |
48 if ($event->getRequest()->request->get(static::AJAX_REQUEST_PARAMETER)) { | |
49 Html::setIsAjax(TRUE); | |
50 } | |
51 } | |
52 | |
53 /** | |
54 * Renders the ajax commands right before preparing the result. | |
55 * | |
56 * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event | |
57 * The response event, which contains the possible AjaxResponse object. | |
58 */ | |
59 public function onResponse(FilterResponseEvent $event) { | |
60 $response = $event->getResponse(); | |
61 if ($response instanceof AjaxResponse) { | |
62 $this->ajaxResponseAttachmentsProcessor->processAttachments($response); | |
63 | |
64 // IE 9 does not support XHR 2 (http://caniuse.com/#feat=xhr2), so | |
65 // for that browser, jquery.form submits requests containing a file upload | |
66 // via an IFRAME rather than via XHR. Since the response is being sent to | |
67 // an IFRAME, it must be formatted as HTML. Specifically: | |
68 // - It must use the text/html content type or else the browser will | |
69 // present a download prompt. Note: This applies to both file uploads | |
70 // as well as any ajax request in a form with a file upload form. | |
71 // - It must place the JSON data into a textarea to prevent browser | |
72 // extensions such as Linkification and Skype's Browser Highlighter | |
73 // from applying HTML transformations such as URL or phone number to | |
74 // link conversions on the data values. | |
75 // | |
76 // Since this affects the format of the output, it could be argued that | |
77 // this should be implemented as a separate Accept MIME type. However, | |
78 // that would require separate variants for each type of AJAX request | |
79 // (e.g., drupal-ajax, drupal-dialog, drupal-modal), so for expediency, | |
80 // this browser workaround is implemented via a GET or POST parameter. | |
81 // | |
82 // @see http://malsup.com/jquery/form/#file-upload | |
83 // @see https://www.drupal.org/node/1009382 | |
84 // @see https://www.drupal.org/node/2339491 | |
85 // @see Drupal.ajax.prototype.beforeSend() | |
86 $accept = $event->getRequest()->headers->get('accept'); | |
87 | |
88 if (strpos($accept, 'text/html') !== FALSE) { | |
89 $response->headers->set('Content-Type', 'text/html; charset=utf-8'); | |
90 | |
91 // Browser IFRAMEs expect HTML. Browser extensions, such as Linkification | |
92 // and Skype's Browser Highlighter, convert URLs, phone numbers, etc. | |
93 // into links. This corrupts the JSON response. Protect the integrity of | |
94 // the JSON data by making it the value of a textarea. | |
95 // @see http://malsup.com/jquery/form/#file-upload | |
96 // @see https://www.drupal.org/node/1009382 | |
97 $response->setContent('<textarea>' . $response->getContent() . '</textarea>'); | |
98 } | |
99 | |
100 // User-uploaded files cannot set any response headers, so a custom header | |
101 // is used to indicate to ajax.js that this response is safe. Note that | |
102 // most Ajax requests bound using the Form API will be protected by having | |
103 // the URL flagged as trusted in Drupal.settings, so this header is used | |
104 // only for things like custom markup that gets Ajax behaviors attached. | |
105 $response->headers->set('X-Drupal-Ajax-Token', 1); | |
106 } | |
107 } | |
108 | |
109 /** | |
110 * {@inheritdoc} | |
111 */ | |
112 public static function getSubscribedEvents() { | |
113 $events[KernelEvents::RESPONSE][] = ['onResponse', -100]; | |
114 $events[KernelEvents::REQUEST][] = ['onRequest', 50]; | |
115 | |
116 return $events; | |
117 } | |
118 | |
119 } |