class CssCollectionOptimizerLazy

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php \Drupal\Core\Asset\CssCollectionOptimizerLazy

Optimizes CSS assets.

Hierarchy

Expanded class hierarchy of CssCollectionOptimizerLazy

1 file declares its use of CssCollectionOptimizerLazy
CssCollectionOptimizerLazyUnitTest.php in core/tests/Drupal/Tests/Core/Asset/CssCollectionOptimizerLazyUnitTest.php
1 string reference to 'CssCollectionOptimizerLazy'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses CssCollectionOptimizerLazy
asset.css.collection_optimizer in core/core.services.yml
Drupal\Core\Asset\CssCollectionOptimizerLazy

File

core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php, line 17

Namespace

Drupal\Core\Asset
View source
class CssCollectionOptimizerLazy implements AssetCollectionGroupOptimizerInterface {
  use AssetGroupSetHashTrait;
  
  /**
   * Constructs a CssCollectionOptimizerLazy.
   *
   * @param \Drupal\Core\Asset\AssetCollectionGrouperInterface $grouper
   *   The grouper for CSS assets.
   * @param \Drupal\Core\Asset\AssetOptimizerInterface $optimizer
   *   The asset optimizer.
   * @param \Drupal\Core\Theme\ThemeManagerInterface $themeManager
   *   The theme manager.
   * @param \Drupal\Core\Asset\LibraryDependencyResolverInterface $dependencyResolver
   *   The library dependency resolver.
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   The request stack.
   * @param \Drupal\Core\File\FileSystemInterface $fileSystem
   *   The file system service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The config factory.
   * @param \Drupal\Core\File\FileUrlGeneratorInterface $fileUrlGenerator
   *   The file URL generator.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
   *   The language manager.
   */
  public function __construct(protected readonly AssetCollectionGrouperInterface $grouper, protected readonly AssetOptimizerInterface $optimizer, protected readonly ThemeManagerInterface $themeManager, protected readonly LibraryDependencyResolverInterface $dependencyResolver, protected readonly RequestStack $requestStack, protected readonly FileSystemInterface $fileSystem, protected readonly ConfigFactoryInterface $configFactory, protected readonly FileUrlGeneratorInterface $fileUrlGenerator, protected readonly TimeInterface $time, protected readonly LanguageManagerInterface $languageManager) {
  }
  
  /**
   * {@inheritdoc}
   */
  public function optimize(array $css_assets, array $libraries) {
    // File names are generated based on library/asset definitions. This
    // includes a hash of the assets and the group index. Additionally, the full
    // set of libraries, already loaded libraries and theme are sent as query
    // parameters to allow a PHP controller to generate a valid file with
    // sufficient information. Files are not generated by this method since
    // they're assumed to be successfully returned from the URL created whether
    // on disk or not.
    // Group the assets.
    $css_groups = $this->grouper
      ->group($css_assets);
    $css_assets = [];
    foreach ($css_groups as $order => $css_group) {
      // We have to return a single asset, not a group of assets. It is now up
      // to one of the pieces of code in the switch statement below to set the
      // 'data' property to the appropriate value.
      $css_assets[$order] = $css_group;
      if ($css_group['type'] === 'file') {
        // No preprocessing, single CSS asset: just use the existing URI.
        if (!$css_group['preprocess']) {
          $uri = $css_group['items'][0]['data'];
          $css_assets[$order]['data'] = $uri;
        }
        else {
          // To reproduce the full context of assets outside of the request,
          // we must know the entire set of libraries used to generate all CSS
          // groups, whether or not files in a group are from a particular
          // library or not.
          $css_assets[$order]['preprocessed'] = TRUE;
        }
      }
      if ($css_group['type'] === 'external') {
        // We don't do any aggregation and hence also no caching for external
        // CSS assets.
        $uri = $css_group['items'][0]['data'];
        $css_assets[$order]['data'] = $uri;
      }
    }
    // All asset group URLs will have exactly the same query arguments, except
    // for the delta, so prepare them in advance.
    $query_args = [
      'language' => $this->languageManager
        ->getCurrentLanguage()
        ->getId(),
      'theme' => $this->themeManager
        ->getActiveTheme()
        ->getName(),
      'include' => UrlHelper::compressQueryParameter(implode(',', $this->dependencyResolver
        ->getMinimalRepresentativeSubset($libraries))),
    ];
    $ajax_page_state = $this->requestStack
      ->getCurrentRequest()
      ->get('ajax_page_state');
    $already_loaded = isset($ajax_page_state) ? explode(',', $ajax_page_state['libraries']) : [];
    if ($already_loaded) {
      $query_args['exclude'] = UrlHelper::compressQueryParameter(implode(',', $this->dependencyResolver
        ->getMinimalRepresentativeSubset($already_loaded)));
    }
    // Generate a URL for each group of assets, but do not process them inline,
    // this is done using optimizeGroup() when the asset path is requested.
    foreach ($css_assets as $order => $css_asset) {
      if (!empty($css_asset['preprocessed'])) {
        $query = [
          'delta' => "{$order}",
        ] + $query_args;
        $filename = 'css_' . $this->generateHash($css_asset) . '.css';
        $uri = 'assets://css/' . $filename;
        $css_assets[$order]['data'] = $this->fileUrlGenerator
          ->generateString($uri) . '?' . UrlHelper::buildQuery($query);
      }
      unset($css_assets[$order]['items']);
    }
    return $css_assets;
  }
  
  /**
   * {@inheritdoc}
   */
  public function getAll() {
    @trigger_error(__METHOD__ . ' is deprecated in drupal:10.2.0 and is removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3301744', E_USER_DEPRECATED);
    return [];
  }
  
  /**
   * {@inheritdoc}
   */
  public function deleteAll() {
    $this->fileSystem
      ->deleteRecursive('assets://css');
  }
  
  /**
   * {@inheritdoc}
   */
  public function optimizeGroup(array $group) : string {
    // Optimize each asset within the group.
    $data = '';
    $current_license = FALSE;
    foreach ($group['items'] as $css_asset) {
      // Ensure license information is available as a comment after
      // optimization.
      if ($css_asset['license'] !== $current_license) {
        $data .= "/* @license " . $css_asset['license']['name'] . " " . $css_asset['license']['url'] . " */\n";
      }
      $current_license = $css_asset['license'];
      $data .= $this->optimizer
        ->optimize($css_asset);
    }
    // Per the W3C specification at
    // http://www.w3.org/TR/REC-CSS2/cascade.html#at-import, @import rules must
    // precede any other style, so we move those to the top. The regular
    // expression is expressed in NOWDOC since it is detecting backslashes as
    // well as single and double quotes. It is difficult to read when
    // represented as a quoted string.
    $regexp = <<<'REGEXP'
/@import\s*(?:'(?:\\'|.)*'|"(?:\\"|.)*"|url\(\s*(?:\\[\)\'\"]|[^'")])*\s*\)|url\(\s*'(?:\'|.)*'\s*\)|url\(\s*"(?:\"|.)*"\s*\)).*;/iU
REGEXP;
    preg_match_all($regexp, $data, $matches);
    $data = preg_replace($regexp, '', $data);
    return implode('', $matches[0]) . (!empty($matches[0]) ? "\n" : '') . $data;
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
AssetGroupSetHashTrait::generateHash protected function Generates a hash for an array of asset groups.
CssCollectionOptimizerLazy::deleteAll public function Deletes all optimized asset collections assets. Overrides AssetCollectionOptimizerInterface::deleteAll
CssCollectionOptimizerLazy::getAll public function Returns all optimized asset collections assets. Overrides AssetCollectionOptimizerInterface::getAll
CssCollectionOptimizerLazy::optimize public function Optimizes a collection of assets. Overrides AssetCollectionOptimizerInterface::optimize
CssCollectionOptimizerLazy::optimizeGroup public function Optimizes a specific group of assets. Overrides AssetCollectionGroupOptimizerInterface::optimizeGroup
CssCollectionOptimizerLazy::__construct public function Constructs a CssCollectionOptimizerLazy.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.