Пример #1
0
 /**
  * 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 JSON-type response is a JSON string, so just wrap it into a
  * Response object.
  *
  * @param Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
  *   The Event to process.
  */
 public function onView(GetResponseForControllerResultEvent $event)
 {
     $request = $event->getRequest();
     // For a master request, we process the result and wrap it as needed.
     // For a subrequest, all we want is the string value.  We assume that
     // is just an HTML string from a controller, so wrap that into a response
     // object.  The subrequest's response will get dissected and placed into
     // the larger page as needed.
     if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
         $method = 'on' . $this->negotiation->getContentType($request);
         if (method_exists($this, $method)) {
             $event->setResponse($this->{$method}($event));
         } else {
             $event->setResponse(new Response('Not Acceptable', 406));
         }
     } else {
         // This is a new-style Symfony-esque subrequest, which means we assume
         // the body is not supposed to be a complete page but just a page
         // fragment.
         $page_result = $event->getControllerResult();
         if ($page_result instanceof HtmlPage || $page_result instanceof Response) {
             return $page_result;
         }
         if (!is_array($page_result)) {
             $page_result = array('#markup' => $page_result);
         }
         // If no title was returned fall back to one defined in the route.
         if (!isset($page_result['#title'])) {
             $page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
         }
         $event->setResponse(new Response(drupal_render_root($page_result)));
     }
 }
 /**
  * Loads all non-admin routes right before the actual page is rendered.
  *
  * @param \Symfony\Component\HttpKernel\Event\KernelEvent $event
  *   The event to process.
  */
 public function onRequest(KernelEvent $event)
 {
     // Just preload on normal HTML pages, as they will display menu links.
     if ($this->negotiation->getContentType($event->getRequest()) == 'html') {
         $this->loadNonAdminRoutes();
     }
 }
 /**
  * Sets the derived request format on the request.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
  *   The event to process.
  */
 public function onRequestDeriveFormat(GetResponseEvent $event)
 {
     $request = $event->getRequest();
     if (!$request->attributes->get('_format')) {
         $request->setRequestFormat($this->negotiation->getContentType($request));
     }
 }
Пример #4
0
 /**
  * {@inheritdoc}
  */
 public function filter(RouteCollection $collection, Request $request)
 {
     // Generates a list of Symfony formats matching the acceptable MIME types.
     // @todo replace by proper content negotiation library.
     $acceptable_mime_types = $request->getAcceptableContentTypes();
     $acceptable_formats = array_filter(array_map(array($request, 'getFormat'), $acceptable_mime_types));
     $primary_format = $this->contentNegotiation->getContentType($request);
     foreach ($collection as $name => $route) {
         // _format could be a |-delimited list of supported formats.
         $supported_formats = array_filter(explode('|', $route->getRequirement('_format')));
         if (empty($supported_formats)) {
             // No format restriction on the route, so it always matches. Move it to
             // the end of the collection by re-adding it.
             $collection->add($name, $route);
         } elseif (in_array($primary_format, $supported_formats)) {
             // Perfect match, which will get a higher priority by leaving the route
             // on top of the list.
         } elseif (in_array('*/*', $acceptable_mime_types) || array_intersect($acceptable_formats, $supported_formats)) {
             // Move it to the end of the list.
             $collection->add($name, $route);
         } else {
             // Remove the route if it does not match at all.
             $collection->remove($name);
         }
     }
     if (count($collection)) {
         return $collection;
     }
     // We do not throw a
     // \Symfony\Component\Routing\Exception\ResourceNotFoundException here
     // because we don't want to return a 404 status code, but rather a 406.
     throw new NotAcceptableHttpException(String::format('No route found for the specified formats @formats.', array('@formats' => implode(' ', $acceptable_mime_types))));
 }
Пример #5
0
 /**
  * {@inheritdoc}
  */
 public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
 {
     foreach ($this->formats as $format => $mime_type) {
         $request->setFormat($format, $mime_type);
     }
     $request->setRequestFormat($this->negotiator->getContentType($request));
     return $this->app->handle($request, $type, $catch);
 }
Пример #6
0
 /**
  * {@inheritdoc}
  */
 public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
 {
     // Register available mime types.
     foreach ($this->formats as $format => $mime_type) {
         $request->setFormat($format, $mime_type);
     }
     // Determine the request format using the negotiator.
     $request->setRequestFormat($this->negotiator->getContentType($request));
     return $this->app->handle($request, $type, $catch);
 }
Пример #7
0
 /**
  * Handles an exception on a request.
  *
  * @param \Symfony\Component\Debug\Exception\FlattenException $exception
  *   The flattened exception.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request that generated the exception.
  *
  * @return \Symfony\Component\HttpFoundation\Response
  *   A response object.
  */
 public function execute(FlattenException $exception, Request $request)
 {
     $method = 'on' . $exception->getStatusCode() . $this->negotiation->getContentType($request);
     if (method_exists($this, $method)) {
         return $this->{$method}($exception, $request);
     }
     return new Response('A fatal error occurred: ' . $exception->getMessage(), $exception->getStatusCode(), $exception->getHeaders());
 }
 /**
  * Tests onRequest on a html request.
  */
 public function testOnRequestOnHtml()
 {
     $event = $this->getMockBuilder('\\Symfony\\Component\\HttpKernel\\Event\\KernelEvent')->disableOriginalConstructor()->getMock();
     $request = new Request();
     $event->expects($this->any())->method('getRequest')->will($this->returnValue($request));
     $this->negotiation->expects($this->once())->method('getContentType')->will($this->returnValue('html'));
     $this->routeProvider->expects($this->once())->method('getRoutesByNames')->with(array('test2'));
     $this->state->expects($this->once())->method('get')->with('routing.non_admin_routes')->will($this->returnValue(array('test2')));
     $this->preloader->onRequest($event);
 }
Пример #9
0
 /**
  * {@inheritdoc}
  */
 public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL)
 {
     parent::initDisplay($view, $display, $options);
     $request_content_type = $this->contentNegotiation->getContentType($this->view->getRequest());
     // Only use the requested content type if it's not 'html'. If it is then
     // default to 'json' to aid debugging.
     // @todo Remove the need for this when we have better content negotiation.
     if ($request_content_type != 'html') {
         $this->setContentType($request_content_type);
     }
     $this->setMimeType($this->view->getRequest()->getMimeType($this->contentType));
 }
Пример #10
0
 /**
  * Tests the getContentType() method when no priority format is found but it's an AJAX request.
  *
  * @covers ::getContentType
  */
 public function testUnknowContentTypeButAjaxRequest()
 {
     $request = new Request();
     $request->headers->set('X-Requested-With', 'XMLHttpRequest');
     $this->assertSame('ajax', $this->contentNegotiation->getContentType($request));
 }
 /**
  * Gets the error-relevant format from the request.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The request object.
  *
  * @return string
  *   The format as which to treat the exception.
  */
 protected function getFormat(Request $request)
 {
     // @todo We are trying to switch to a more robust content negotiation
     // library in https://www.drupal.org/node/1505080 that will make
     // $request->getRequestFormat() reliable as a better alternative
     // to this code. We therefore use this style for now on the expectation
     // that it will get replaced with better code later. This approach makes
     // that change easier when we get to it.
     $conneg = new ContentNegotiation();
     $format = $conneg->getContentType($request);
     // These are all JSON errors for our purposes. Any special handling for
     // them can/should happen in earlier listeners if desired.
     if (in_array($format, ['drupal_modal', 'drupal_dialog', 'drupal_ajax'])) {
         $format = 'json';
     }
     // Make an educated guess that any Accept header type that includes "json"
     // can probably handle a generic JSON response for errors. As above, for
     // any format this doesn't catch or that wants custom handling should
     // register its own exception listener.
     foreach ($request->getAcceptableContentTypes() as $mime) {
         if (strpos($mime, 'html') === FALSE && strpos($mime, 'json') !== FALSE) {
             $format = 'json';
         }
     }
     return $format;
 }
 /**
  * Handles errors for this subscriber.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
  *   The event to process.
  */
 public function onException(GetResponseForExceptionEvent $event)
 {
     $exception = $event->getException();
     // Make the exception available for example when rendering a block.
     $event->getRequest()->attributes->set('exception', FlattenException::create($exception));
     $handled_formats = $this->getHandledFormats();
     // @todo Injecting this service would force all implementing classes to also
     // handle its injection. However, we are trying to switch to a more robust
     // content negotiation library in https://www.drupal.org/node/1505080 that
     // will make $request->getRequestFormat() reliable as a better alternative
     // to this code. We therefore use this style for now on the expectation
     // that it will get replaced with better code later. That change will NOT
     // be an API change for any implementing classes.  (Whereas if we injected
     // this class it would be an API change.  That's why we're not doing it.)
     $conneg = new ContentNegotiation();
     $format = $conneg->getContentType($event->getRequest());
     if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
         $method = 'on' . $exception->getStatusCode();
         // We want to allow the method to be called and still not set a response
         // if it has additional filtering logic to determine when it will apply.
         // It is therefore the method's responsibility to set the response on the
         // event if appropriate.
         if (method_exists($this, $method)) {
             $this->{$method}($event);
         }
     }
 }