You are here

public function BackgroundImageCssController::deliver in Background Image 2.0.x

Same name and namespace in other branches
  1. 8 src/Controller/BackgroundImageCssController.php \Drupal\background_image\Controller\BackgroundImageCssController::deliver()
  2. 2.x src/Controller/BackgroundImageCssController.php \Drupal\background_image\Controller\BackgroundImageCssController::deliver()

Generates a background CSS file.

After generating an image, transfer it to the requesting agent.

Parameters

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

\Drupal\background_image\BackgroundImageInterface $background_image: The background image entity.

string $scheme: The file scheme, defaults to 'private'.

string $file: The file name to generate.

Return value

\Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response The transferred file as response or some error response.

Throws

\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException Thrown when the user does not have access to the file.

\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException Thrown when the file is still being generated.

File

src/Controller/BackgroundImageCssController.php, line 340

Class

BackgroundImageCssController
Defines a controller to serve image styles.

Namespace

Drupal\background_image\Controller

Code

public function deliver(Request $request, BackgroundImageInterface $background_image, $scheme, $file = NULL) {

  // Ensure this is a valid background image, scheme and user has permission.
  $valid = !empty($background_image) && $this->streamWrapperManager
    ->isValidScheme($scheme) && $background_image
    ->access('view');
  if (!$valid) {
    throw new AccessDeniedHttpException();
  }
  $uri = "{$scheme}://background_image/css/{$background_image->id()}/{$scheme}/{$file}";

  // If using the private scheme, let other modules provide headers and
  // control access to the file.
  $headers = [];
  if ($scheme == 'private') {
    $headers = $this
      ->moduleHandler()
      ->invokeAll('file_download', [
      $uri,
    ]);
    if (in_array(-1, $headers) || empty($headers)) {
      throw new AccessDeniedHttpException();
    }
  }

  // Don't start generating the image if the derivative already exists or if
  // generation is in progress in another thread.
  if (!file_exists($uri)) {
    $lock_name = 'background_image_css_deliver:' . $background_image
      ->id() . ':' . $background_image
      ->getImageHash();
    $lock_acquired = $this->lock
      ->acquire($lock_name);
    if (!$lock_acquired) {

      // Tell client to retry again in 3 seconds. Currently no browsers are
      // known to support Retry-After.
      throw new ServiceUnavailableHttpException(3, $this
        ->t('Background Image CSS generation in progress. Try again shortly.'));
    }
  }

  // Try to generate the image, unless another thread just did it while we
  // were acquiring the lock.
  $success = file_exists($uri) || $this
    ->buildCss($background_image, $uri);
  if (!empty($lock_acquired)) {
    $this->lock
      ->release($lock_name);
  }
  if ($success) {
    $headers += [
      'Content-Type' => 'text/css',
      'Content-Length' => filesize($uri),
    ];

    // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
    // sets response as not cacheable if the Cache-Control header is not
    // already modified. We pass in FALSE for non-private schemes for the
    // $public parameter to make sure we don't change the headers.
    return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
  }
  else {
    $this->logger
      ->notice('Unable to generate the background image CSS located at %path.', [
      '%path' => $uri,
    ]);
    return new Response($this
      ->t('Error generating image.'), 500);
  }
}