Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / modules / rest / src / Plugin / views / display / RestExport.php
index 2b59af51185dcf06550cc0f84334f576246e25a3..52daee05f040fea0df626f50d9c292f00be32669 100644 (file)
@@ -70,7 +70,7 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
    *
    * @var string
    */
-  protected $mimeType;
+  protected $mimeType = 'application/json';
 
   /**
    * The renderer.
@@ -109,6 +109,13 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
    */
   protected $authenticationProviders;
 
+  /**
+   * The serialization format providers, keyed by format.
+   *
+   * @var string[]
+   */
+  protected $formatProviders;
+
   /**
    * Constructs a RestExport object.
    *
@@ -126,8 +133,10 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
    *   The renderer.
    * @param string[] $authentication_providers
    *   The authentication providers, keyed by ID.
+   * @param string[] $serializer_format_providers
+   *   The serialization format providers, keyed by format.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, RendererInterface $renderer, array $authentication_providers) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, RendererInterface $renderer, array $authentication_providers, array $serializer_format_providers) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state);
 
     $this->renderer = $renderer;
@@ -139,6 +148,7 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
     $this->authenticationProviderIds = array_keys($authentication_providers);
     // For BC reasons we keep around authenticationProviders as before.
     $this->authenticationProviders = $authentication_providers;
+    $this->formatProviders = $serializer_format_providers;
   }
 
   /**
@@ -152,8 +162,8 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
       $container->get('router.route_provider'),
       $container->get('state'),
       $container->get('renderer'),
-      $container->getParameter('authentication_providers')
-
+      $container->getParameter('authentication_providers'),
+      $container->getParameter('serializer.format_providers')
     );
   }
   /**
@@ -162,21 +172,22 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
   public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
     parent::initDisplay($view, $display, $options);
 
+    // If the default 'json' format is not selected as a format option in the
+    // view display, fallback to the first format available for the default.
+    if (!empty($options['style']['options']['formats']) && !isset($options['style']['options']['formats'][$this->getContentType()])) {
+      $default_format = reset($options['style']['options']['formats']);
+      $this->setContentType($default_format);
+    }
+
+    // Only use the requested content type if it's not 'html'. This allows
+    // still falling back to the default for things like views preview.
     $request_content_type = $this->view->getRequest()->getRequestFormat();
-    // 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') {
+
+    if ($request_content_type !== 'html') {
       $this->setContentType($request_content_type);
     }
-    // If the requested content type is 'html' and the default 'json' is not
-    // selected as a format option in the view display, fallback to the first
-    // format in the array.
-    elseif (!empty($options['style']['options']['formats']) && !isset($options['style']['options']['formats'][$this->getContentType()])) {
-      $this->setContentType(reset($options['style']['options']['formats']));
-    }
 
-    $this->setMimeType($this->view->getRequest()->getMimeType($this->contentType));
+    $this->setMimeType($this->view->getRequest()->getMimeType($this->getContentType()));
   }
 
   /**
@@ -350,17 +361,21 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
 
     if ($route = $collection->get("view.$view_id.$display_id")) {
       $style_plugin = $this->getPlugin('style');
-      // REST exports should only respond to get methods.
+
+      // REST exports should only respond to GET methods.
       $route->setMethods(['GET']);
 
-      // Format as a string using pipes as a delimiter.
-      if ($formats = $style_plugin->getFormats()) {
-        // Allow a REST Export View to be returned with an HTML-only accept
-        // format. That allows browsers or other non-compliant systems to access
-        // the view, as it is unlikely to have a conflicting HTML representation
-        // anyway.
-        $route->setRequirement('_format', implode('|', $formats + ['html']));
+      $formats = $style_plugin->getFormats();
+
+      // If there are no configured formats, add all formats that serialization
+      // is known to support.
+      if (!$formats) {
+        $formats = $this->getFormatOptions();
       }
+
+      // Format as a string using pipes as a delimiter.
+      $route->setRequirement('_format', implode('|', $formats));
+
       // Add authentication to the route if it was set. If no authentication was
       // set, the default authentication will be used, which is cookie based by
       // default.
@@ -444,15 +459,15 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
       $build['#suffix'] = '</pre>';
       unset($build['#markup']);
     }
-    elseif ($this->view->getRequest()->getFormat($this->view->element['#content_type']) !== 'html') {
-      // This display plugin is primarily for returning non-HTML formats.
-      // However, we still invoke the renderer to collect cacheability metadata.
-      // Because the renderer is designed for HTML rendering, it filters
-      // #markup for XSS unless it is already known to be safe, but that filter
-      // only works for HTML. Therefore, we mark the contents as safe to bypass
-      // the filter. So long as we are returning this in a non-HTML response
-      // (checked above), this is safe, because an XSS attack only works when
-      // executed by an HTML agent.
+    else {
+      // This display plugin is for returning non-HTML formats. However, we
+      // still invoke the renderer to collect cacheability metadata. Because the
+      // renderer is designed for HTML rendering, it filters #markup for XSS
+      // unless it is already known to be safe, but that filter only works for
+      // HTML. Therefore, we mark the contents as safe to bypass the filter. So
+      // long as we are returning this in a non-HTML response,
+      // this is safe, because an XSS attack only works when executed by an HTML
+      // agent.
       // @todo Decide how to support non-HTML in the render API in
       //   https://www.drupal.org/node/2501313.
       $build['#markup'] = ViewsRenderPipelineMarkup::create($build['#markup']);
@@ -492,4 +507,15 @@ class RestExport extends PathPluginBase implements ResponseDisplayPluginInterfac
     return $dependencies;
   }
 
+  /**
+   * Returns an array of format options.
+   *
+   * @return string[]
+   *   An array of format options. Both key and value are the same.
+   */
+  protected function getFormatOptions() {
+    $formats = array_keys($this->formatProviders);
+    return array_combine($formats, $formats);
+  }
+
 }