diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 994ff18..244bf01 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -7,6 +7,7 @@ namespace Drupal\Core; +use Drupal\Core\DependencyInjection\Compiler\ViewRespondersPass; use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -51,6 +52,16 @@ class CoreBundle extends Bundle $container->register('view_subscriber', 'Drupal\Core\EventSubscriber\ViewSubscriber') ->addArgument(new Reference('content_negotiation')) ->addTag('kernel.event_subscriber'); + // Add format responders. + $container->register('html_responder', 'Drupal\Core\EventSubscriber\ViewResponder\HtmlResponder') + ->addTag('kernel.view.responder', array('format' => 'html')); + $container->register('json_responder', 'Drupal\Core\EventSubscriber\ViewResponder\JsonResponder') + ->addTag('kernel.view.responder', array('format' => 'json')); + $container->register('ajax_responder', 'Drupal\Core\EventSubscriber\ViewResponder\AjaxResponder') + ->addTag('kernel.view.responder', array('format' => 'ajax')); + $container->register('iframe_upload_responder', 'Drupal\Core\EventSubscriber\ViewResponder\IframeUploadResponder') + ->addTag('kernel.view.responder', array('format' => 'iframeupload')); + $container->register('access_subscriber', 'Drupal\Core\EventSubscriber\AccessSubscriber') ->addTag('kernel.event_subscriber'); $container->register('maintenance_mode_subscriber', 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber') @@ -83,5 +94,8 @@ class CoreBundle extends Bundle // Add a compiler pass for registering event subscribers. $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING); + + // Add a compiler pass for adding View responders. + $container->addCompilerPass(new ViewRespondersPass(), PassConfig::TYPE_AFTER_REMOVING); } } diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/ViewRespondersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/ViewRespondersPass.php new file mode 100644 index 0000000..5d802e2 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/ViewRespondersPass.php @@ -0,0 +1,32 @@ +hasDefinition('view_subscriber')) { + return; + } + + $definition = $container->getDefinition('view_subscriber'); + + foreach ($container->findTaggedServiceIds('kernel.view.responder') as $id => $attributes) { + if (!isset($attributes[0]['format'])) { + throw new \RuntimeException(sprintf('The format for the kernel.view.responder service "%s" must be set.', $id)); + } + + $definition->addMethodCall('addResponder', array($attributes[0]['format'], new Reference($id))); + } + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewResponder/AjaxResponder.php b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/AjaxResponder.php new file mode 100644 index 0000000..4220371 --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/AjaxResponder.php @@ -0,0 +1,26 @@ +getControllerResult(); + + // Construct the response content from the page callback result. + $commands = ajax_prepare_response($page_callback_result); + $json = ajax_render($commands); + + // Build the actual response object. + $response = new JsonResponse(); + $response->setContent($json); + + return $response; + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewResponder/HtmlResponder.php b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/HtmlResponder.php new file mode 100644 index 0000000..82fdeca --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/HtmlResponder.php @@ -0,0 +1,17 @@ +getControllerResult(); + return new Response(drupal_render_page($page_callback_result)); + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewResponder/IframeUploadResponder.php b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/IframeUploadResponder.php new file mode 100644 index 0000000..643adc9 --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/IframeUploadResponder.php @@ -0,0 +1,29 @@ +getControllerResult(); + + // Construct the response content from the page callback result. + $commands = ajax_prepare_response($page_callback_result); + $json = ajax_render($commands); + + // 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 http://drupal.org/node/1009382 + $html = ''; + + return new Response($html); + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewResponder/JsonResponder.php b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/JsonResponder.php new file mode 100644 index 0000000..13de0d3 --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/JsonResponder.php @@ -0,0 +1,21 @@ +getControllerResult(); + + $response = new JsonResponse(); + $response->setContent($page_callback_result); + + return $response; + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewResponder/ViewResponderInterface.php b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/ViewResponderInterface.php new file mode 100644 index 0000000..a160cba --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ViewResponder/ViewResponderInterface.php @@ -0,0 +1,13 @@ +negotiation = $negotiation; } + public function addResponder($format, ViewResponderInterface $responder) { + $this->responders[$format] = $responder; + } + /** * Processes a successful controller into an HTTP 200 response. * @@ -43,77 +50,18 @@ class ViewSubscriber implements EventSubscriberInterface { * The Event to process. */ public function onView(GetResponseForControllerResultEvent $event) { - $request = $event->getRequest(); + $content_type = $this->negotiation->getContentType($request); - $method = 'on' . $this->negotiation->getContentType($request); - - if (method_exists($this, $method)) { - $event->setResponse($this->$method($event)); + if (isset($this->responders[$content_type])) { + $responder = $this->responders[$content_type]; + $event->setResponse($responder->getResponse($event)); } else { $event->setResponse(new Response('Unsupported Media Type', 415)); } } - public function onJson(GetResponseForControllerResultEvent $event) { - $page_callback_result = $event->getControllerResult(); - - $response = new JsonResponse(); - $response->setContent($page_callback_result); - - return $response; - } - - public function onAjax(GetResponseForControllerResultEvent $event) { - $page_callback_result = $event->getControllerResult(); - - // Construct the response content from the page callback result. - $commands = ajax_prepare_response($page_callback_result); - $json = ajax_render($commands); - - // Build the actual response object. - $response = new JsonResponse(); - $response->setContent($json); - - return $response; - } - - public function onIframeUpload(GetResponseForControllerResultEvent $event) { - $page_callback_result = $event->getControllerResult(); - - // Construct the response content from the page callback result. - $commands = ajax_prepare_response($page_callback_result); - $json = ajax_render($commands); - - // 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 http://drupal.org/node/1009382 - $html = ''; - - return new Response($html); - } - - /** - * Processes a successful controller into an HTTP 200 response. - * - * Some controllers may not return a response object but simply the body of - * one. The VIEW event is called in that case, to allow us to mutate that - * body into a Response object. In particular we assume that the return from - * an HTML-type response is a render array from a legacy page callback and - * render it. - * - * @param Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event - * The Event to process. - */ - public function onHtml(GetResponseForControllerResultEvent $event) { - $page_callback_result = $event->getControllerResult(); - return new Response(drupal_render_page($page_callback_result)); - } - /** * Registers the methods in this class that should be listeners. *