diff --git a/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php b/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php index 3666605..9039726 100644 --- a/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php +++ b/core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php @@ -25,4 +25,5 @@ protected function generateHash(array $groups) { } return hash('sha256', serialize($normalized)); } + } diff --git a/core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php b/core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php index 19ac573..46c3dac 100644 --- a/core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php +++ b/core/lib/Drupal/Core/Asset/CssCollectionOptimizerLazy.php @@ -139,5 +139,4 @@ public function optimize(array $css_assets) { return $css_assets; } - } diff --git a/core/lib/Drupal/Core/Asset/CssCollectionOptimizerTrait.php b/core/lib/Drupal/Core/Asset/CssCollectionOptimizerTrait.php index e884003..f4057dc 100644 --- a/core/lib/Drupal/Core/Asset/CssCollectionOptimizerTrait.php +++ b/core/lib/Drupal/Core/Asset/CssCollectionOptimizerTrait.php @@ -66,8 +66,8 @@ public function deleteAll() { * @return string[] * URIs for all optimized asset collection assets. */ - public function getAll() { - return $this->state->get('drupal_css_cache_files', []); - } + public function getAll() { + return $this->state->get('drupal_css_cache_files', []); + } } diff --git a/core/lib/Drupal/Core/Asset/JsCollectionOptimizerLazy.php b/core/lib/Drupal/Core/Asset/JsCollectionOptimizerLazy.php index 1082970..58cc573 100644 --- a/core/lib/Drupal/Core/Asset/JsCollectionOptimizerLazy.php +++ b/core/lib/Drupal/Core/Asset/JsCollectionOptimizerLazy.php @@ -117,6 +117,7 @@ public function optimize(array $js_assets) { $uri = $js_group['items'][0]['data']; $js_assets[$order]['data'] = $uri; break; + case 'setting': $js_assets[$order]['data'] = $js_group['data']; break; @@ -124,7 +125,7 @@ public function optimize(array $js_assets) { } if ($libraries) { // Generate a URL for the group, but do not process it inline, this is - // done by \Drupal\system\controller\JsAssetController + // done by \Drupal\system\controller\JsAssetController. $ajax_page_state = $this->requestStack->getCurrentRequest()->query->get('ajax_page_state'); $already_loaded = isset($ajax_page_state) ? explode(',', $ajax_page_state['libraries']) : []; @@ -133,13 +134,13 @@ public function optimize(array $js_assets) { 'theme' => $this->themeManager->getActiveTheme()->getName(), 'already_loaded' => $this->dependencyResolver->getMinimalRepresentativeSubset($already_loaded), ]; - $header_query = UrlHelper::buildQuery($query_args + ['scope' => 'header']); - $footer_query = UrlHelper::buildQuery($query_args + ['scope' => 'footer']); + $header_query = UrlHelper::buildQuery($query_args + ['scope' => 'header']); + $footer_query = UrlHelper::buildQuery($query_args + ['scope' => 'footer']); foreach ($js_assets as $order => $js_asset) { if (!empty($js_asset['preprocessed'])) { $query = $js_asset['scope'] == 'header' ? $header_query : $footer_query; - $filename = 'js' . '_' . $order . '_' . $key . '.js'; - $uri = 'public://js' . '/' . $filename; + $filename = 'js_' . $order . '_' . $key . '.js'; + $uri = 'public://js/' . $filename; $js_assets[$order]['data'] = file_create_url($uri) . '?' . $query; } } diff --git a/core/lib/Drupal/Core/Asset/JsCollectionOptimizerTrait.php b/core/lib/Drupal/Core/Asset/JsCollectionOptimizerTrait.php index 9bea1a8..4cbe72a 100644 --- a/core/lib/Drupal/Core/Asset/JsCollectionOptimizerTrait.php +++ b/core/lib/Drupal/Core/Asset/JsCollectionOptimizerTrait.php @@ -2,8 +2,6 @@ namespace Drupal\Core\Asset; -use Drupal\Core\State\StateInterface; - /** * Optimizes JavaScript assets. */ @@ -74,5 +72,4 @@ public function getAll() { return $this->state->get('system.js_cache_files', []); } - } diff --git a/core/modules/system/src/Controller/AssetControllerBase.php b/core/modules/system/src/Controller/AssetControllerBase.php index d56c59e..a763dcf 100644 --- a/core/modules/system/src/Controller/AssetControllerBase.php +++ b/core/modules/system/src/Controller/AssetControllerBase.php @@ -2,7 +2,6 @@ namespace Drupal\system\Controller; -use Drupal\Component\Utility\Crypt; use Drupal\Core\Asset\AssetCollectionGrouperInterface; use Drupal\Core\Asset\AssetCollectionOptimizerInterface; use Drupal\Core\Asset\AssetDumperUriInterface; @@ -43,14 +42,14 @@ /** * The theme initialization. * - * @var Drupal\Core\Theme\ThemeInitializationInterface; + * @var Drupal\Core\Theme\ThemeInitializationInterface */ protected $themeInitialization; /** * The theme manager. * - * @var Drupal\Core\Theme\ThemeManagerInterface; + * @var Drupal\Core\Theme\ThemeManagerInterface */ protected $themeManager; @@ -105,27 +104,29 @@ /** * The cache control header to use. + * + * @var string */ protected $cacheControl = 'private, no-store'; /** * Constructs a CssAssetController object. * - * @param \Drupal\Core\Asset\LibraryDependencyResolverInterface + * @param \Drupal\Core\Asset\LibraryDependencyResolverInterface $library_dependency_resolver * The library dependency resolver. - * @param \Drupal\Core\Asset\AssetResolverInterface + * @param \Drupal\Core\Asset\AssetResolverInterface $asset_resolver * The asset resolver. - * @param \Drupal\Core\Theme\ThemeInitializationInterface + * @param \Drupal\Core\Theme\ThemeInitializationInterface $theme_initialization * The theme initializer. - * @param \Drupal\Core\Theme\ThemeManagerInterface + * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * The theme manager. - * @param \Drupal\Core\Asset\AssetCollectionGrouperInterface + * @param \Drupal\Core\Asset\AssetCollectionGrouperInterface $grouper * The asset grouper. - * @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface + * @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $optimizer * The asset collection optimizer. - * @param \Drupal\Core\Asset\AssetDumperUriInterface + * @param \Drupal\Core\Asset\AssetDumperUriInterface $dumper * The asset dumper. - * @param \Drupal\Core\State\StateInterface + * @param \Drupal\Core\State\StateInterface $state * The state service. */ public function __construct(LibraryDependencyResolverInterface $library_dependency_resolver, AssetResolverInterface $asset_resolver, ThemeInitializationInterface $theme_initialization, ThemeManagerInterface $theme_manager, AssetCollectionGrouperInterface $grouper, AssetCollectionOptimizerInterface $optimizer, AssetDumperUriInterface $dumper, StateInterface $state) { @@ -145,7 +146,7 @@ public function __construct(LibraryDependencyResolverInterface $library_dependen * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. - * @param $file_name + * @param string $file_name * The file to deliver. * * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response @@ -207,7 +208,7 @@ public function deliver(Request $request, $file_name) { // the same case as #1 but a much shorter window. // 3. Someone is attempting to craft an invalid URL in order to conduct a // denial of service attack on the site. - + // // Dump the optimized group into an aggregate file, but only if the // received hash and generated hash match. This prevents invalid filenames // from filling the disk, while still serving aggregates that may be @@ -235,11 +236,11 @@ public function deliver(Request $request, $file_name) { * Get a group. * * @param array $groups - * An array of asset groups - * @param int $group_delta + * An array of asset groups. + * @param int $group_delta * The group delta. * - * @return [] + * @return array * The correct asset group matching $group_delta. */ protected function getGroup($groups, $group_delta) { @@ -258,4 +259,5 @@ protected function getGroup($groups, $group_delta) { * The current request. */ abstract protected function getGroups(AttachedAssetsInterface $attached_assets, Request $request); + } diff --git a/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php index ea26b9b..fee8b00 100644 --- a/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php +++ b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php @@ -65,6 +65,14 @@ public function testAssetAggregation() { } } + /** + * Tests the URL points to a valid page, and has expected headers. + * + * @param string $url + * The url under test. + * @param bool $from_php + * (optional) is the source of the url php code. Default to TRUE. + */ protected function assertAggregate($url, $from_php = TRUE) { $url = $this->getAbsoluteUrl($url); $session = $this->getSession(); @@ -79,6 +87,12 @@ protected function assertAggregate($url, $from_php = TRUE) { } } + /** + * Test the returned response code under various failure conditions. + * + * @param string $url + * The url under tests. + */ protected function assertInvalidAggregates($url) { $session = $this->getSession(); $session->visit($this->replaceGroupDelta($url)); @@ -103,12 +117,30 @@ protected function assertInvalidAggregates($url) { } + /** + * Invalidate the group delta section of a URL. + * + * @param string $url + * The URL to be modified. + * + * @return string + * The modified absolute URL. + */ protected function replaceGroupDelta($url) { $parts = explode('_', $url); $parts[1] = 100; return $this->getAbsoluteUrl(implode('_', $parts)); } + /** + * Invalidate the hash section of the URL, for example to ensure a cache miss. + * + * @param string $url + * The URL to be modified. + * + * @return string + * The modified absolute URL. + */ protected function replaceGroupHash($url) { $parts = explode('_', $url); $hash = strtok($parts[2], '.'); @@ -116,6 +148,15 @@ protected function replaceGroupHash($url) { return $this->getAbsoluteUrl(implode('_', $parts)); } + /** + * Invalidate the library definition associated with a URL. + * + * @param string $url + * The associated URL. + * + * @return string + * The modified absolute URL. + */ protected function setInvalidLibrary($url) { // First replace the hash so we don't get served the actual file on disk. $url = $this->replaceGroupHash($url); @@ -126,14 +167,22 @@ protected function setInvalidLibrary($url) { return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']); } + /** + * Delete the theme section from a given URL. + * + * @param string $url + * The URL to modify. + * + * @return string + * The modified absolute URL. + */ protected function omitTheme($url) { // First replace the hash so we don't get served the actual file on disk. $url = $this->replaceGroupHash($url); $parts = UrlHelper::parse($url); unset($parts['query']['theme']); $query = UrlHelper::buildQuery($parts['query']); - return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']); + return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']); } - }