diff --git a/.htaccess b/.htaccess index f4024c6..47d0f5b 100644 --- a/.htaccess +++ b/.htaccess @@ -2,6 +2,9 @@ # Apache/PHP/Drupal settings: # +php_value auto_prepend_file /Users/catch/xhprof/header.php +php_value auto_append_file /Users/catch/xhprof/footer.php + # Protect files and directories from prying eyes. diff --git a/core/includes/file.inc b/core/includes/file.inc index 992c1a8..3e5eb8c 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -195,7 +195,6 @@ function file_stream_wrapper_uri_normalize($uri) { * @see file_url_transform_relative() */ function file_create_url($uri) { - debug($uri); // Allow the URI to be altered, e.g. to serve a file from a CDN or static // file server. \Drupal::moduleHandler()->alter('file_url', $uri); diff --git a/core/lib/Drupal/Core/Asset/AssetDumper.php b/core/lib/Drupal/Core/Asset/AssetDumper.php index 0504fa4..ed563c0 100644 --- a/core/lib/Drupal/Core/Asset/AssetDumper.php +++ b/core/lib/Drupal/Core/Asset/AssetDumper.php @@ -21,13 +21,16 @@ class AssetDumper implements AssetDumperInterface { * the aggregated contents of the files in $data. This forces proxies and * browsers to download new CSS when the CSS changes. */ - public function dump($data, $file_extension) { - // Prefix filename to prevent blocking by firewalls which reject files - // starting with "ad*". - $filename = $file_extension. '_' . Crypt::hashBase64($data) . '.' . $file_extension; - // Create the css/ or js/ path within the files folder. + public function dump($data, $file_extension, $uri = NULL) { $path = 'public://' . $file_extension; - $uri = $path . '/' . $filename; + if (!isset($uri)) { + // Prefix filename to prevent blocking by firewalls which reject files + // starting with "ad*". + $filename = $file_extension . '_' . $group . '_' . Crypt::hashBase64($data) . '.' . $file_extension; + // Create the css/ or js/ path within the files folder. + $path = 'public://' . $file_extension; + $uri = $path . '/' . $filename; + } // Create the CSS or JS file. file_prepare_directory($path, FILE_CREATE_DIRECTORY); if (!file_exists($uri) && !file_unmanaged_save_data($data, $uri, FILE_EXISTS_REPLACE)) { diff --git a/core/lib/Drupal/Core/Asset/AssetDumperInterface.php b/core/lib/Drupal/Core/Asset/AssetDumperInterface.php index 5f70aa6..8b997eb 100644 --- a/core/lib/Drupal/Core/Asset/AssetDumperInterface.php +++ b/core/lib/Drupal/Core/Asset/AssetDumperInterface.php @@ -19,9 +19,12 @@ * @param string $file_extension * The file extension of this asset. * + * @param string $uri + * (optional) The file URI to write to. + * * @return string * An URI to access the dumped asset. */ - public function dump($data, $file_extension); + public function dump($data, $file_extension, $uri); } diff --git a/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php b/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php index df9a104..1c20033 100644 --- a/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php +++ b/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php @@ -68,6 +68,7 @@ public function __construct(AssetCollectionGrouperInterface $grouper, AssetOptim public function optimize(array $css_assets) { // Group the assets. $css_groups = $this->grouper->group($css_assets); + $key = $this->generateHash($css_groups); $css_assets = array(); $libraries = []; @@ -118,16 +119,16 @@ public function optimize(array $css_assets) { // Generate a URL for the group, but do not process it inline, this is // done by \Drupal\system\controller\CssAssetController $minimal_set = \Drupal::service('library.dependency_resolver')->getMinimalRepresentativeSubset($libraries); + foreach ($css_assets as $order => $css_asset) { if (!empty($css_asset['preprocessed'])) { - $key = $this->generateHash($css_asset); $filename = 'css' . '_' . $order . '_' . $key . '.' . 'css'; // Create the css/ or js/ path within the files folder. $path = 'public://' . 'css'; $uri = $path . '/' . $filename; $theme_name = $this->themeManager->getActiveTheme()->getName(); $query = UrlHelper::buildQuery(['libraries' => $minimal_set, 'theme' => $theme_name]); - $css_assets[$order]['data'] = file_create_url($uri) . '?=' . $query; + $css_assets[$order]['data'] = file_create_url($uri) . '?' . $query; } } @@ -144,7 +145,13 @@ public function optimize(array $css_assets) { * A hash to uniquely identify the given group of CSS assets. */ protected function generateHash(array $css_group) { - return hash('sha256', serialize($css_group)); + $normalized = $css_group; + foreach ($normalized as $order => $group) { + foreach ($group['items'] as $key => $asset) { + unset($normalized[$order]['items'][$key]['weight']); + } + } + return hash('sha256', serialize($normalized)); } /** diff --git a/core/modules/system/src/Controller/CssAssetController.php b/core/modules/system/src/Controller/CssAssetController.php index 5530af1..e0f158a 100644 --- a/core/modules/system/src/Controller/CssAssetController.php +++ b/core/modules/system/src/Controller/CssAssetController.php @@ -69,6 +69,13 @@ class CssAssetController extends FileDownloadController { protected $optimizer; /** + * An asset dumper. + * + * @var \Drupal\Core\Asset\AssetDumperInterface + */ + protected $dumper; + + /** * Constructs a CssAssetController object. * * @param \Drupal\Core\Asset\LibraryDependencyResolverInterface @@ -83,14 +90,17 @@ class CssAssetController extends FileDownloadController { * The grouper for CSS assets. * @param \Drupal\Core\Asset\AssetOptimizerInterface * The optimizer for a single CSS asset. + * @param \Drupal\Core\Asset\AssetDumperInterface + * The asset dumper. */ - public function __construct($library_dependency_resolver, $asset_resolver, $theme_initialization, $theme_manager, $grouper, $optimizer) { + public function __construct($library_dependency_resolver, $asset_resolver, $theme_initialization, $theme_manager, $grouper, $optimizer, $dumper) { $this->libraryDependencyResolver = $library_dependency_resolver; $this->assetResolver = $asset_resolver; $this->themeInitialization = $theme_initialization; $this->themeManager = $theme_manager; $this->grouper = $grouper; $this->optimizer = $optimizer; + $this->dumper = $dumper; } /** @@ -103,7 +113,8 @@ public static function create(ContainerInterface $container) { $container->get('theme.initialization'), $container->get('theme.manager'), $container->get('asset.css.collection_grouper'), - $container->get('asset.css.optimizer') + $container->get('asset.css.optimizer'), + $container->get('asset.css.dumper') ); } @@ -144,7 +155,7 @@ public function deliver(Request $request, $file_name) { $css_assets = array(); $libraries = []; - $base_name = basename($file_name); + $base_name = basename($file_name, '.css'); $file_parts = explode('_', $base_name); // The group delta is the second segment of the filename, if it's not there @@ -162,7 +173,10 @@ public function deliver(Request $request, $file_name) { } $hash = $file_parts[2]; - + // If the group being requested does not exist, assume an invalid filename. + if (!isset($css_groups[$group_delta])) { + throw new BadRequestHttpException('Invalid filename'); + } $css_group = $css_groups[$group_delta]; // Only groups that are preprocessed will be requested, so don't try to @@ -170,7 +184,7 @@ public function deliver(Request $request, $file_name) { if (!$css_group['preprocess']) { throw new BadRequestHttpException('Invalid filename'); } - $key = $this->generateHash($css_group); + $key = $this->generateHash($css_groups); // The hash from the library definitions in code may not match the hash from @@ -197,7 +211,7 @@ public function deliver(Request $request, $file_name) { // use the filename matching this code base, not the one that generated // the original filename for the request. if (!file_exists($uri)) { - $uri = 'public://css/' . '_' . $group_delta . '_' . $hash . '.css'; + $uri = 'public://css/' . 'css_' . $group_delta . '_' . $hash . '.css'; } // Either way, we didn't get a match. $match = FALSE; @@ -223,7 +237,7 @@ public function deliver(Request $request, $file_name) { $data = implode('', $matches[0]) . $data; // Dump the optimized CSS for this group into an aggregate file. if ($match) { - $uri = $this->dumper->dump($data, 'css'); + $uri = $this->dumper->dump($data, 'css', $uri); } $headers = [ 'Content-Type' => 'text/css', @@ -248,7 +262,13 @@ public function deliver(Request $request, $file_name) { * A hash to uniquely identify the given group of CSS assets. */ protected function generateHash(array $css_group) { - return hash('sha256', serialize($css_group)); + $normalized = $css_group; + foreach ($normalized as $order => $group) { + foreach ($group['items'] as $key => $asset) { + unset($normalized[$order]['items'][$key]['weight']); + } + } + return hash('sha256', serialize($normalized)); } }