Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 293065

CSS aggregation breaks file URL rewriting because it abuses it

$
0
0

The problems (they're intertwined though):

file_create_url() result for the CSS file itself abused to generate the URLs for files referenced by CSS files
Drupal 7 core's CSS aggregation does call file_create_url() (and thus allowing hook_file_url_alter() to modify that URL) on the aggregate CSS file that's being built (e.g. http://site.com/subdir/sites/default/foobar.css). It then proceeds to strip the filename away, the result (http://site.com/subdir/sites/default/) of which it then uses to prepend to the referenced files. So e.g. if foobar.css references cat.png, it will concatenate http://site.com/subdir/sites/default and cat.png.
This breaks down as soon as each file gets a unique file URL. e.g. when it is rewritten to be served from a CDN with Far Future expiration headers: http://cdn.com/last-modified:2012-03-10/foobar.css works fine, but because of the above logic, the same URL will be forced upon each referenced file, which is of course very wrong.
Fix:
-        // Build the base URL of this CSS file: start with the full URL.
-        $css_base_url = file_create_url($stylesheet['data']);
-        // Move to the parent.
-        $css_base_url = substr($css_base_url, 0, strrpos($css_base_url, '/'));
-        // Simplify to a relative URL if the stylesheet URL starts with the
-        // base URL of the website.
-        if (substr($css_base_url, 0, strlen($GLOBALS['base_root'])) == $GLOBALS['base_root']) {
-          $css_base_url = substr($css_base_url, strlen($GLOBALS['base_root']));
-        }
-
+        // Get the parent directory of this file, relative to the Drupal root.
+        $css_base_url = drupal_substr($stylesheet['data'], 0, strrpos($stylesheet['data'], '/'));

file_create_url() not applied to files referenced by CSS files
Drupal 7 core's CSS aggregation breaks modules that want to alter file URLs via hook_file_url_alter() because it does not route file URLs of files referenced by aggregated CSS files (e.g. background images, fonts).
So: inability to have hook_file_url_alter() process files referenced by a CSS file.
Fix:
-  return 'url(' . $path . ')';
+  return 'url(' . file_create_url($path) . ')';

This breaks the CDN module, and forces many other modules (e.g. to use data URIs) to apply crazy hackery in the theme layer to parse HTML and then modify it.

The CDN module has been shipping with an override for Drupal core's CSS aggregation for over a year, but there are unsolvable compatibility problems with certain modules (e.g. http://drupal.org/project/css_emimage, see #1532178-10: Integrate with CSS Embedded Images module) and themes (e.g. http://drupal.org/project/omega, see #1790348: Far-Future mode: background images and font files referenced in CSS files incorrectly rewritten, but only in an Omega subtheme) because Drupal core forces us to use crazy theme layer hackery to achieve what we need to achieve.

On Drupal 8

This code is still identical in D8, so in theory this patch should be against D8, but asset handling in D8 is still going to have to change completely because of the new Symfony-based render system. So it's rather pointless to apply it to D8. If that's desired though, then I'd be happy to do so.


Viewing all articles
Browse latest Browse all 293065

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>