X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=inline;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FRouting%2FRequestFormatRouteFilter.php;h=fad7bc04659f0ef4dedc87741a08eae75bfcb79b;hb=refs%2Fheads%2Fd864;hp=dbfb801b7856de897ef08c887f79690da9612017;hpb=af6d1fb995500ae68849458ee10d66abbdcfb252;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php b/web/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php index dbfb801b7..fad7bc046 100644 --- a/web/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php +++ b/web/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php @@ -2,8 +2,10 @@ namespace Drupal\Core\Routing; +use Drupal\Core\Url; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; +use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** @@ -17,7 +19,14 @@ class RequestFormatRouteFilter implements FilterInterface { public function filter(RouteCollection $collection, Request $request) { // Determine the request format. $default_format = static::getDefaultFormat($collection); - $format = $request->getRequestFormat($default_format); + // If the request does not specify a format then use the default. + if (is_null($request->getRequestFormat(NULL))) { + $format = $default_format; + $request->setRequestFormat($default_format); + } + else { + $format = $request->getRequestFormat($default_format); + } $routes_with_requirement = []; $routes_without_requirement = []; @@ -52,7 +61,18 @@ class RequestFormatRouteFilter implements FilterInterface { // 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("No route found for the specified format $format."); + $available_formats = static::getAvailableFormats($collection); + $not_acceptable = new NotAcceptableHttpException("No route found for the specified format $format. Supported formats: " . implode(', ', $available_formats) . '.'); + if ($available_formats) { + $links = []; + foreach ($available_formats as $available_format) { + $url = Url::fromUri($request->getUri(), ['query' => ['_format' => $available_format]])->toString(TRUE)->getGeneratedUrl(); + $content_type = $request->getMimeType($available_format); + $links[] = "<$url>; rel=\"alternate\"; type=\"$content_type\""; + } + $not_acceptable->setHeaders(['Link' => implode(', ', $links)]); + } + throw $not_acceptable; } /** @@ -60,7 +80,9 @@ class RequestFormatRouteFilter implements FilterInterface { * * By default, use 'html' as the default format. But when there's only a * single route match, and that route specifies a '_format' requirement - * listing a single format, then use that as the default format. + * listing a single format, then use that as the default format. Also, if + * there are multiple routes which all require the same single format then + * use it. * * @param \Symfony\Component\Routing\RouteCollection $collection * The route collection to filter. @@ -69,15 +91,32 @@ class RequestFormatRouteFilter implements FilterInterface { * The default format. */ protected static function getDefaultFormat(RouteCollection $collection) { - $default_format = 'html'; - if ($collection->count() === 1) { - $only_route = $collection->getIterator()->current(); - $required_format = $only_route->getRequirement('_format'); - if (strpos($required_format, '|') === FALSE) { - $default_format = $required_format; - } - } - return $default_format; + $formats = static::getAvailableFormats($collection); + + // The default format is 'html' unless ALL routes require the same format. + return count($formats) === 1 + ? reset($formats) + : 'html'; + } + + /** + * Gets the set of formats across all routes in the collection. + * + * @param \Symfony\Component\Routing\RouteCollection $collection + * The route collection to filter. + * + * @return string[] + * All available formats. + */ + protected static function getAvailableFormats(RouteCollection $collection) { + $all_formats = array_reduce($collection->all(), function (array $carry, Route $route) { + // Routes without a '_format' requirement are assumed to require HTML. + $route_formats = !$route->hasRequirement('_format') + ? ['html'] + : explode('|', $route->getRequirement('_format')); + return array_merge($carry, $route_formats); + }, []); + return array_unique(array_filter($all_formats)); } }