You are here

ThemeCompilerController.php in Theme Compiler 2.0.x

Same filename and directory in other branches
  1. 8 src/Controller/ThemeCompilerController.php

File

src/Controller/ThemeCompilerController.php
View source
<?php

namespace Drupal\theme_compiler\Controller;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\compiler\CompilerContextInterface;
use Drupal\theme_compiler\Compiler;
use Drupal\theme_compiler\ThemeCompilerControllerInterface;

/**
 * Defines the controller used to compile assets provided by themes.
 *
 * Copyright (C) 2021  Library Solutions, LLC (et al.).
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * @internal
 */
class ThemeCompilerController extends ControllerBase implements ThemeCompilerControllerInterface {
  const DEFAULT_MIME_TYPE = 'application/octet-stream';

  /**
   * The compiler service.
   *
   * @var \Drupal\theme_compiler\Compiler
   */
  protected $compiler;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * The theme manager service.
   *
   * @var \Drupal\Core\Theme\ThemeManagerInterface
   */
  protected $themeManager;

  /**
   * Constructs a ThemeCompilerController object.
   *
   * @param \Drupal\theme_compiler\Compiler $compiler
   *   The compiler service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler service.
   * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
   *   The theme manager service.
   */
  public function __construct(Compiler $compiler, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager) {
    $this->compiler = $compiler;
    $this->moduleHandler = $module_handler;
    $this->themeManager = $theme_manager;
  }

  /**
   * Serve a theme compiler asset as a cacheable response.
   *
   * @param \Drupal\compiler\CompilerContextInterface $theme_compiler_context
   *   A compiler context used to define a compilation.
   *
   * @see hook_theme_compiler_asset_alter()
   *   For more information about how to alter the asset response.
   *
   * @return \Drupal\Core\Cache\CacheableResponse
   *   A cacheable response for the requested resource.
   */
  public function serve(CompilerContextInterface $theme_compiler_context) : CacheableResponse {

    // The default response should be HTTP 404 (Not Found).
    $response = new CacheableResponse('', CacheableResponse::HTTP_NOT_FOUND);
    try {
      $metadata = $theme_compiler_context
        ->getOption('theme_compiler');
      if (!is_array($metadata) || !array_key_exists('theme', $metadata) || !array_key_exists('path', $metadata)) {
        throw new \InvalidArgumentException('The compiler context is missing the required theme compiler metadata');
      }

      // Prepare the asset path for retrieval from the file system.
      $target = $this->compiler
        ->normalizeAndResolveTargetPath("{$metadata['theme']}/{$metadata['path']}");

      // Ensure that the asset could be read from the file system.
      if (($asset = @file_get_contents($target)) !== FALSE) {

        // Assume that the file content retrieval went according to plan.
        $status = CacheableResponse::HTTP_OK;
        if (strlen($asset) === 0) {

          // If the file is empty, status '204 No Content' is more appropriate.
          $status = CacheableResponse::HTTP_NO_CONTENT;
        }

        // Replace the original response with a new one containing the contents.
        $response = new CacheableResponse($asset, $status, [
          'Content-Type' => self::DEFAULT_MIME_TYPE,
        ]);
      }
    } catch (\Exception $previous) {
      watchdog_exception('theme_compiler', $previous);
    }

    // Define the default cacheability for this response.
    $hash = hash('sha384', $target);
    $cacheability = new CacheableMetadata();
    $cacheability
      ->addCacheTags([
      'theme_compiler_asset',
      "theme_compiler_asset:{$hash}",
    ]);

    // Set the initial cacheability for this response.
    $response
      ->addCacheableDependency($cacheability);

    // Allow modules & themes to alter the compiler response.
    $this->moduleHandler
      ->alter([
      'theme_compiler_response',
      "theme_compiler_response_{$theme_compiler_context->getCompiler()}",
    ], $response);
    $this->themeManager
      ->alter([
      'theme_compiler_response',
      "theme_compiler_response_{$theme_compiler_context->getCompiler()}",
    ], $response);
    return $response;
  }

}

Classes

Namesort descending Description
ThemeCompilerController Defines the controller used to compile assets provided by themes.