Namespace
Drupal\advagg\AssetFichier
-
src/
Asset/ AssetResolver.php
View source
<?php
namespace Drupal\advagg\Asset;
use Drupal\Core\Asset\AssetCollectionOptimizerInterface;
use Drupal\Core\Asset\AssetResolver as CoreAssetResolver;
use Drupal\Core\Asset\AssetResolverInterface;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Asset\LibraryDiscoveryInterface;
use Drupal\Core\Asset\LibraryDependencyResolverInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\State\StateInterface;
/**
* The default asset resolver.
*/
class AssetResolver extends CoreAssetResolver implements AssetResolverInterface {
/**
* The CSS collection optimizer.
*
* @var \Drupal\Core\Asset\AssetCollectionOptimizerInterface
*/
protected $cssCollectionOptimizer;
/**
* The JS collection optimizer.
*
* @var \Drupal\Core\Asset\AssetCollectionOptimizerInterface
*/
protected $jsCollectionOptimizer;
/**
* The AdvAgg file status state information storage service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $advaggFiles;
/**
* Constructs a new AssetResolver instance.
*
* @param \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery
* The library discovery service.
* @param \Drupal\Core\Asset\LibraryDependencyResolverInterface $library_dependency_resolver
* The library dependency resolver.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
* The theme manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend.
* @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $css_collection_optimizer
* The CSS collection optimizer.
* @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $js_collection_optimizer
* The JS collection optimizer.
* @param \Drupal\Core\State\StateInterface $advagg_files
* The AdvAgg file status state information storage service.
*/
public function __construct(LibraryDiscoveryInterface $library_discovery, LibraryDependencyResolverInterface $library_dependency_resolver, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager, LanguageManagerInterface $language_manager, CacheBackendInterface $cache, AssetCollectionOptimizerInterface $css_collection_optimizer, AssetCollectionOptimizerInterface $js_collection_optimizer, StateInterface $advagg_files) {
$this->libraryDiscovery = $library_discovery;
$this->libraryDependencyResolver = $library_dependency_resolver;
$this->moduleHandler = $module_handler;
$this->themeManager = $theme_manager;
$this->languageManager = $language_manager;
$this->cache = $cache;
$this->cssCollectionOptimizer = $css_collection_optimizer;
$this->jsCollectionOptimizer = $js_collection_optimizer;
$this->advaggFiles = $advagg_files;
}
/**
* {@inheritdoc}
*/
public function getCssAssets(AttachedAssetsInterface $assets, $optimize) {
$theme_info = $this->themeManager
->getActiveTheme();
// Add the theme name to the cache key since themes may implement
// hook_css_alter().
$libraries_to_load = $this->getLibrariesToLoad($assets);
$cid = 'css:' . $theme_info->getName() . ':' . Crypt::hashBase64(serialize($libraries_to_load)) . (int) $optimize;
if ($cached = $this->cache
->get($cid)) {
return $cached->data;
}
$css = [];
$default_options = [
'type' => 'file',
'group' => CSS_AGGREGATE_DEFAULT,
'weight' => 0,
'media' => 'all',
'preprocess' => TRUE,
'browsers' => [],
];
foreach ($libraries_to_load as $library) {
list($extension, $name) = explode('/', $library, 2);
$definition = $this->libraryDiscovery
->getLibraryByName($extension, $name);
if (isset($definition['css'])) {
foreach ($definition['css'] as $options) {
$options += $default_options;
$options['browsers'] += [
'IE' => TRUE,
'!IE' => TRUE,
];
// Files with a query string cannot be preprocessed.
if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
$options['preprocess'] = FALSE;
}
// Always add a tiny value to the weight, to conserve the insertion
// order.
$options['weight'] += count($css) / 1000;
// CSS files are being keyed by the full path.
$css[$options['data']] = $options;
}
}
}
// Allow modules and themes to alter the CSS assets.
$this->moduleHandler
->alter('css', $css, $assets);
$this->themeManager
->alter('css', $css, $assets);
// After alter get file information (in case alter changes things).
$this->advaggFiles
->getMultiple(array_column($css, 'data'));
// Sort CSS items, so that they appear in the correct order.
uasort($css, 'static::sort');
// Allow themes to remove CSS files by CSS files full path and file name.
// @todo Remove in Drupal 9.0.x.
if ($stylesheet_remove = $theme_info->getStyleSheetsRemove()) {
foreach ($css as $key => $options) {
if (isset($stylesheet_remove[$key])) {
unset($css[$key]);
}
}
}
if ($optimize) {
$css = $this->cssCollectionOptimizer
->optimize($css);
}
$this->cache
->set($cid, $css, CacheBackendInterface::CACHE_PERMANENT, [
'library_info',
]);
return $css;
}
/**
* {@inheritdoc}
*/
public function getJsAssets(AttachedAssetsInterface $assets, $optimize) {
$theme_info = $this->themeManager
->getActiveTheme();
// Add the theme name to the cache key since themes may implement
// hook_js_alter(). Additionally add the current language to support
// translation of JavaScript files.
$libraries_to_load = $this->getLibrariesToLoad($assets);
$cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager
->getCurrentLanguage()
->getId() . ':' . Crypt::hashBase64(serialize($libraries_to_load)) . (int) (count($assets->getSettings()) > 0) . (int) $optimize;
if ($cached = $this->cache
->get($cid)) {
list($js_assets_header, $js_assets_footer, $settings, $settings_in_header) = $cached->data;
}
else {
$javascript = [];
$default_options = [
'type' => 'file',
'group' => JS_DEFAULT,
'weight' => 0,
'cache' => TRUE,
'preprocess' => TRUE,
'attributes' => [],
'version' => NULL,
'browsers' => [],
];
// Collect all libraries that contain JS assets and are in the header.
$header_js_libraries = [];
foreach ($libraries_to_load as $library) {
list($extension, $name) = explode('/', $library, 2);
$definition = $this->libraryDiscovery
->getLibraryByName($extension, $name);
if (isset($definition['js']) && !empty($definition['header'])) {
$header_js_libraries[] = $library;
}
}
// The current list of header JS libraries are only those libraries that
// are in the header, but their dependencies must also be loaded for them
// to function correctly, so update the list with those.
$header_js_libraries = $this->libraryDependencyResolver
->getLibrariesWithDependencies($header_js_libraries);
foreach ($libraries_to_load as $library) {
list($extension, $name) = explode('/', $library, 2);
$definition = $this->libraryDiscovery
->getLibraryByName($extension, $name);
if (isset($definition['js'])) {
foreach ($definition['js'] as $options) {
$options += $default_options;
// 'scope' is a calculated option, based on which libraries are
// marked to be loaded from the header (see above).
$options['scope'] = in_array($library, $header_js_libraries) ? 'header' : 'footer';
// Preprocess can only be set if caching is enabled and no
// attributes are set.
$options['preprocess'] = $options['cache'] && empty($options['attributes']) ? $options['preprocess'] : FALSE;
// Always add a tiny value to the weight, to conserve the insertion
// order.
$options['weight'] += count($javascript) / 1000;
// Local and external files must keep their name as the associative
// key so the same JavaScript file is not added twice.
$javascript[$options['data']] = $options;
}
}
}
// Allow modules and themes to alter the JavaScript assets.
$this->moduleHandler
->alter('js', $javascript, $assets);
$this->themeManager
->alter('js', $javascript, $assets);
// After alter get file information (in case alter changes things).
$this->advaggFiles
->getMultiple(array_column($javascript, 'data'));
// Sort JavaScript assets, so that they appear in the correct order.
uasort($javascript, 'static::sort');
// Prepare the return value: filter JavaScript assets per scope.
$js_assets_header = [];
$js_assets_footer = [];
foreach ($javascript as $key => $item) {
if ($item['scope'] == 'header') {
$js_assets_header[$key] = $item;
}
elseif ($item['scope'] == 'footer') {
$js_assets_footer[$key] = $item;
}
}
if ($optimize) {
$js_assets_header = $this->jsCollectionOptimizer
->optimize($js_assets_header);
$js_assets_footer = $this->jsCollectionOptimizer
->optimize($js_assets_footer);
}
// If the core/drupalSettings library is being loaded or is already
// loaded, get the JavaScript settings assets, and convert them into a
// single "regular" JavaScript asset.
$libraries_to_load = $this->getLibrariesToLoad($assets);
$settings_required = in_array('core/drupalSettings', $libraries_to_load) || in_array('core/drupalSettings', $this->libraryDependencyResolver
->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()));
$settings_have_changed = count($libraries_to_load) > 0 || count($assets->getSettings()) > 0;
// Initialize settings to FALSE since they are not needed by default. This
// distinguishes between an empty array which must still allow
// hook_js_settings_alter() to be run.
$settings = FALSE;
if ($settings_required && $settings_have_changed) {
$settings = $this->getJsSettingsAssets($assets);
// Allow modules to add cached JavaScript settings.
foreach ($this->moduleHandler
->getImplementations('js_settings_build') as $module) {
$function = $module . '_js_settings_build';
$function($settings, $assets);
}
}
$settings_in_header = in_array('core/drupalSettings', $header_js_libraries);
$this->cache
->set($cid, [
$js_assets_header,
$js_assets_footer,
$settings,
$settings_in_header,
], CacheBackendInterface::CACHE_PERMANENT, [
'library_info',
]);
}
if ($settings !== FALSE) {
// Attached settings override both library definitions and
// hook_js_settings_build().
$settings = NestedArray::mergeDeepArray([
$settings,
$assets->getSettings(),
], TRUE);
// Allow modules and themes to alter the JavaScript settings.
$this->moduleHandler
->alter('js_settings', $settings, $assets);
$this->themeManager
->alter('js_settings', $settings, $assets);
// Update the $assets object accordingly, so that it reflects the final
// settings.
$assets->setSettings($settings);
$settings_as_inline_javascript = [
'type' => 'setting',
'group' => JS_SETTING,
'weight' => 0,
'browsers' => [],
'data' => $settings,
];
$settings_js_asset = [
'drupalSettings' => $settings_as_inline_javascript,
];
// Prepend to the list of JS assets, to render it first. Preferably in
// the footer, but in the header if necessary.
if ($settings_in_header) {
$js_assets_header = $settings_js_asset + $js_assets_header;
}
else {
$js_assets_footer = $settings_js_asset + $js_assets_footer;
}
}
return [
$js_assets_header,
$js_assets_footer,
];
}
}
Classes
Titre | Deprecated | Résumé |
---|---|---|
AssetResolver | The default asset resolver. |