X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Fadvagg%2Fsrc%2FAsset%2FAssetResolver.php;fp=web%2Fmodules%2Fcontrib%2Fadvagg%2Fsrc%2FAsset%2FAssetResolver.php;h=a28bee467c9b568527496bf2903ee6230b75aa67;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hp=0000000000000000000000000000000000000000;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad;p=yaffs-website diff --git a/web/modules/contrib/advagg/src/Asset/AssetResolver.php b/web/modules/contrib/advagg/src/Asset/AssetResolver.php new file mode 100644 index 000000000..a28bee467 --- /dev/null +++ b/web/modules/contrib/advagg/src/Asset/AssetResolver.php @@ -0,0 +1,311 @@ +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, + ]; + } + +}