You are here

public function OEmbedIframeController::render in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/media/src/Controller/OEmbedIframeController.php \Drupal\media\Controller\OEmbedIframeController::render()

Renders an oEmbed resource.

Parameters

\Symfony\Component\HttpFoundation\Request $request: The request object.

Return value

\Symfony\Component\HttpFoundation\Response The response object.

Throws

\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException Will be thrown if the 'hash' parameter does not match the expected hash of the 'url' parameter.

1 string reference to 'OEmbedIframeController::render'
media.routing.yml in core/modules/media/media.routing.yml
core/modules/media/media.routing.yml

File

core/modules/media/src/Controller/OEmbedIframeController.php, line 121

Class

OEmbedIframeController
Controller which renders an oEmbed resource in a bare page (without blocks).

Namespace

Drupal\media\Controller

Code

public function render(Request $request) {
  $url = $request->query
    ->get('url');
  $max_width = $request->query
    ->getInt('max_width', NULL);
  $max_height = $request->query
    ->getInt('max_height', NULL);

  // Hash the URL and max dimensions, and ensure it is equal to the hash
  // parameter passed in the query string.
  $hash = $this->iFrameUrlHelper
    ->getHash($url, $max_width, $max_height);
  if (!hash_equals($hash, $request->query
    ->get('hash', ''))) {
    throw new AccessDeniedHttpException('This resource is not available');
  }

  // Return a response instead of a render array so that the frame content
  // will not have all the blocks and page elements normally rendered by
  // Drupal.
  $response = new HtmlResponse();
  $response
    ->addCacheableDependency(Url::createFromRequest($request));
  try {
    $resource_url = $this->urlResolver
      ->getResourceUrl($url, $max_width, $max_height);
    $resource = $this->resourceFetcher
      ->fetchResource($resource_url);
    $placeholder_token = Crypt::randomBytesBase64(55);

    // Render the content in a new render context so that the cacheability
    // metadata of the rendered HTML will be captured correctly.
    $element = [
      '#theme' => 'media_oembed_iframe',
      // Even though the resource HTML is untrusted, IFrameMarkup::create()
      // will create a trusted string. The only reason this is okay is
      // because we are serving it in an iframe, which will mitigate the
      // potential dangers of displaying third-party markup.
      '#media' => IFrameMarkup::create($resource
        ->getHtml()),
      '#cache' => [
        // Add the 'rendered' cache tag as this response is not processed by
        // \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse().
        'tags' => [
          'rendered',
        ],
      ],
      '#attached' => [
        'html_response_attachment_placeholders' => [
          'styles' => '<css-placeholder token="' . $placeholder_token . '">',
        ],
        'library' => [
          'media/oembed.frame',
        ],
      ],
      '#placeholder_token' => $placeholder_token,
    ];
    $content = $this->renderer
      ->executeInRenderContext(new RenderContext(), function () use ($resource, $element) {
      return $this->renderer
        ->render($element);
    });
    $response
      ->setContent($content)
      ->setAttachments($element['#attached'])
      ->addCacheableDependency($resource)
      ->addCacheableDependency(CacheableMetadata::createFromRenderArray($element));
  } catch (ResourceException $e) {

    // Prevent the response from being cached.
    $response
      ->setMaxAge(0);

    // The oEmbed system makes heavy use of exception wrapping, so log the
    // entire exception chain to help with troubleshooting.
    do {

      // @todo Log additional information from ResourceException, to help with
      // debugging, in https://www.drupal.org/project/drupal/issues/2972846.
      $this->logger
        ->error($e
        ->getMessage());
      $e = $e
        ->getPrevious();
    } while ($e);
  }
  return $response;
}