CssCollectionOptimizerLazy.php
Same filename in other branches
Namespace
Drupal\Core\AssetFile
-
core/
lib/ Drupal/ Core/ Asset/ CssCollectionOptimizerLazy.php
View source
<?php
namespace Drupal\Core\Asset;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Optimizes CSS assets.
*/
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(AssetCollectionGrouperInterface $grouper, AssetOptimizerInterface $optimizer, ThemeManagerInterface $themeManager, LibraryDependencyResolverInterface $dependencyResolver, RequestStack $requestStack, FileSystemInterface $fileSystem, ConfigFactoryInterface $configFactory, FileUrlGeneratorInterface $fileUrlGenerator, TimeInterface $time, 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;
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
CssCollectionOptimizerLazy | Optimizes CSS assets. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.