Skip to content
Snippets Groups Projects
Commit 6e3832f4 authored by Angie Byron's avatar Angie Byron
Browse files

#264876 by Rob Loach, jhedstrom, mfer: Allow external CSS files through drupal_add_css().

parent bc2a814c
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
...@@ -2423,13 +2423,16 @@ function drupal_add_link($attributes) { ...@@ -2423,13 +2423,16 @@ function drupal_add_link($attributes) {
* - 'inline': A string of CSS that should be placed in the given scope. Note * - 'inline': A string of CSS that should be placed in the given scope. Note
* that it is better practice to use 'file' stylesheets, rather than 'inline' * that it is better practice to use 'file' stylesheets, rather than 'inline'
* as the CSS would then be aggregated and cached. * as the CSS would then be aggregated and cached.
* - 'external': The absolute path to an external CSS file that is not hosted
* on the local server. These files will not be aggregated if CSS aggregation
* is enabled.
* *
* @param $options * @param $options
* (optional) A string defining the 'type' of CSS that is being added in the * (optional) A string defining the 'type' of CSS that is being added in the
* $data parameter ('file'/'inline'), or an array which can have any or all of * $data parameter ('file'/'inline'), or an array which can have any or all of
* the following keys: * the following keys:
* - 'type': The type of stylesheet being added. Available options are 'file' * - 'type': The type of stylesheet being added. Available options are 'file',
* or 'inline'. Defaults to 'file'. * 'inline' or 'external'. Defaults to 'file'.
* - 'weight': The weight of the stylesheet specifies the order in which the * - 'weight': The weight of the stylesheet specifies the order in which the
* CSS will appear when presented on the page. * CSS will appear when presented on the page.
* *
...@@ -2454,7 +2457,8 @@ function drupal_add_link($attributes) { ...@@ -2454,7 +2457,8 @@ function drupal_add_link($attributes) {
* files into one file that is then compressed by removing all extraneous * files into one file that is then compressed by removing all extraneous
* white space. Note that preprocessed inline stylesheets will not be * white space. Note that preprocessed inline stylesheets will not be
* aggregated into this single file, instead it will just be compressed * aggregated into this single file, instead it will just be compressed
* when being output on the page. * when being output on the page. External stylesheets will not be
* aggregated.
* *
* The reason for merging the CSS files is outlined quite thoroughly here: * The reason for merging the CSS files is outlined quite thoroughly here:
* http://www.die.net/musings/page_load_time/ * http://www.die.net/musings/page_load_time/
...@@ -2501,14 +2505,15 @@ function drupal_add_css($data = NULL, $options = NULL) { ...@@ -2501,14 +2505,15 @@ function drupal_add_css($data = NULL, $options = NULL) {
// Add the data to the CSS array depending on the type. // Add the data to the CSS array depending on the type.
switch ($options['type']) { switch ($options['type']) {
case 'file':
$css[$data] = $options;
break;
case 'inline': case 'inline':
// For inline stylesheets, we don't want to use the $data as the array // For inline stylesheets, we don't want to use the $data as the array
// key as $data could be a very long string of CSS. // key as $data could be a very long string of CSS.
$css[] = $options; $css[] = $options;
break; break;
default:
// Local and external files must keep their name as the associative key
// so the same CSS file is not be added twice.
$css[$data] = $options;
} }
} }
...@@ -2576,6 +2581,7 @@ function drupal_get_css($css = NULL) { ...@@ -2576,6 +2581,7 @@ function drupal_get_css($css = NULL) {
// Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones. // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
$rendered_css = array(); $rendered_css = array();
$inline_css = ''; $inline_css = '';
$external_css = '';
$preprocess_items = array(); $preprocess_items = array();
foreach ($css as $data => $item) { foreach ($css as $data => $item) {
// Loop through each of the stylesheets, including them appropriately based // Loop through each of the stylesheets, including them appropriately based
...@@ -2597,6 +2603,10 @@ function drupal_get_css($css = NULL) { ...@@ -2597,6 +2603,10 @@ function drupal_get_css($css = NULL) {
// Include inline stylesheets. // Include inline stylesheets.
$inline_css .= drupal_load_stylesheet_content($item['data'], $item['preprocess']); $inline_css .= drupal_load_stylesheet_content($item['data'], $item['preprocess']);
break; break;
case 'external':
// Preprocessing for external CSS files is ignored.
$external_css .= '<link type="text/css" rel="stylesheet" media="' . $item['media'] . '" href="' . $item['data'] . '" />' . "\n";
break;
} }
} }
...@@ -2615,7 +2625,7 @@ function drupal_get_css($css = NULL) { ...@@ -2615,7 +2625,7 @@ function drupal_get_css($css = NULL) {
} }
// Output all the CSS files with the inline stylesheets showing up last. // Output all the CSS files with the inline stylesheets showing up last.
return implode("\n", $rendered_css) . $inline_css; return implode("\n", $rendered_css) . $external_css . $inline_css;
} }
/** /**
...@@ -2826,7 +2836,9 @@ function drupal_clear_css_cache() { ...@@ -2826,7 +2836,9 @@ function drupal_clear_css_cache() {
* (optional) If given, the value depends on the $options parameter: * (optional) If given, the value depends on the $options parameter:
* - 'file': Path to the file relative to base_path(). * - 'file': Path to the file relative to base_path().
* - 'inline': The JavaScript code that should be placed in the given scope. * - 'inline': The JavaScript code that should be placed in the given scope.
* - 'external': The absolute path to a JavaScript file hosted externally. * - 'external': The absolute path to an external JavaScript file that is not
* hosted on the local server. These files will not be aggregated if
* JavaScript aggregation is enabled.
* - 'setting': An array with configuration options as associative array. The * - 'setting': An array with configuration options as associative array. The
* array is directly placed in Drupal.settings. All modules should wrap * array is directly placed in Drupal.settings. All modules should wrap
* their actual configuration settings in another variable to prevent * their actual configuration settings in another variable to prevent
...@@ -2940,7 +2952,6 @@ function drupal_add_js($data = NULL, $options = NULL) { ...@@ -2940,7 +2952,6 @@ function drupal_add_js($data = NULL, $options = NULL) {
// Local and external files must keep their name as the associative key // Local and external files must keep their name as the associative key
// so the same JavaScript file is not be added twice. // so the same JavaScript file is not be added twice.
$javascript[$options['data']] = $options; $javascript[$options['data']] = $options;
break;
} }
} }
return $javascript; return $javascript;
......
...@@ -224,6 +224,15 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -224,6 +224,15 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
$this->assertEqual($css[$path]['data'], $path, t('Adding a CSS file caches it properly.')); $this->assertEqual($css[$path]['data'], $path, t('Adding a CSS file caches it properly.'));
} }
/**
* Tests adding an external stylesheet.
*/
function testAddExternal() {
$path = 'http://example.com/style.css';
$css = drupal_add_css($path, 'external');
$this->assertEqual($css[$path]['type'], 'external', t('Adding an external CSS file caches it properly.'));
}
/** /**
* Makes sure that reseting the CSS empties the cache. * Makes sure that reseting the CSS empties the cache.
*/ */
...@@ -238,7 +247,18 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -238,7 +247,18 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
function testRenderFile() { function testRenderFile() {
$css = drupal_get_path('module', 'simpletest') . '/simpletest.css'; $css = drupal_get_path('module', 'simpletest') . '/simpletest.css';
drupal_add_css($css); drupal_add_css($css);
$this->assertTrue(strpos(drupal_get_css(), $css) > 0, t('Rendered CSS includes the added stylesheet.')); $styles = drupal_get_css();
$this->assertTrue(strpos($styles, $css) > 0, t('Rendered CSS includes the added stylesheet.'));
}
/**
* Tests rendering an external stylesheet.
*/
function testRenderExternal() {
$css = 'http://example.com/style.css';
drupal_add_css($css, 'external');
$styles = drupal_get_css();
$this->assertTrue(strpos($styles, 'href="' . $css) > 0, t('Rendering an external CSS file.'));
} }
/** /**
...@@ -248,8 +268,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -248,8 +268,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
$css = 'body { padding: 0px; }'; $css = 'body { padding: 0px; }';
$css_preprocessed = '<style type="text/css">' . drupal_load_stylesheet_content($css, TRUE) . '</style>'; $css_preprocessed = '<style type="text/css">' . drupal_load_stylesheet_content($css, TRUE) . '</style>';
drupal_add_css($css, 'inline'); drupal_add_css($css, 'inline');
$css = drupal_get_css(); $styles = drupal_get_css();
$this->assertEqual($css, "\n" . $css_preprocessed, t('Rendering preprocessed inline CSS adds it to the page.')); $this->assertEqual($styles, "\n" . $css_preprocessed, t('Rendering preprocessed inline CSS adds it to the page.'));
} }
/** /**
...@@ -258,7 +278,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -258,7 +278,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
function testRenderInlineNoPreprocess() { function testRenderInlineNoPreprocess() {
$css = 'body { padding: 0px; }'; $css = 'body { padding: 0px; }';
drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE)); drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
$this->assertTrue(strpos(drupal_get_css(), $css) > 0, t('Rendering non-preprocessed inline CSS adds it to the page.')); $styles = drupal_get_css();
$this->assertTrue(strpos($styles, $css) > 0, t('Rendering non-preprocessed inline CSS adds it to the page.'));
} }
/** /**
...@@ -300,8 +321,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -300,8 +321,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
drupal_get_path('module', 'simpletest') . '/simpletest.css', drupal_get_path('module', 'simpletest') . '/simpletest.css',
); );
$css = drupal_get_css(); $styles = drupal_get_css();
if (preg_match_all('/href="' . preg_quote(base_path(), '/') . '([^?]+)\?/', $css, $matches)) { if (preg_match_all('/href="' . preg_quote(base_path(), '/') . '([^?]+)\?/', $styles, $matches)) {
$result = $matches[1]; $result = $matches[1];
} }
else { else {
...@@ -319,17 +340,17 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -319,17 +340,17 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css'); drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
// The dummy stylesheet should be the only one included. // The dummy stylesheet should be the only one included.
$css = drupal_get_css(); $styles = drupal_get_css();
$this->assert(strpos($css, drupal_get_path('module', 'simpletest') . '/tests/system.css') !== FALSE, t('The overriding CSS file is output.')); $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') !== FALSE, t('The overriding CSS file is output.'));
$this->assert(strpos($css, drupal_get_path('module', 'system') . '/system.css') === FALSE, t('The overriden CSS file is not output.')); $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') === FALSE, t('The overriden CSS file is not output.'));
drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css'); drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
drupal_add_css(drupal_get_path('module', 'system') . '/system.css'); drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
// The standard stylesheet should be the only one included. // The standard stylesheet should be the only one included.
$css = drupal_get_css(); $styles = drupal_get_css();
$this->assert(strpos($css, drupal_get_path('module', 'system') . '/system.css') !== FALSE, t('The overriding CSS file is output.')); $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') !== FALSE, t('The overriding CSS file is output.'));
$this->assert(strpos($css, drupal_get_path('module', 'simpletest') . '/tests/system.css') === FALSE, t('The overriden CSS file is not output.')); $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') === FALSE, t('The overriden CSS file is not output.'));
} }
/** /**
...@@ -342,8 +363,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase { ...@@ -342,8 +363,8 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
drupal_add_css(drupal_get_path('module', 'system') . '/system.css'); drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
// Check to see if system-rtl.css was also added. // Check to see if system-rtl.css was also added.
$css = drupal_get_css(); $styles = drupal_get_css();
$this->assert(strpos($css, drupal_get_path('module', 'system') . '/system-rtl.css') !== FALSE, t('CSS is alterable as right to left overrides are added.')); $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system-rtl.css') !== FALSE, t('CSS is alterable as right to left overrides are added.'));
// Change the language back to left to right. // Change the language back to left to right.
$language->direction = LANGUAGE_LTR; $language->direction = LANGUAGE_LTR;
...@@ -559,6 +580,15 @@ class JavaScriptTestCase extends DrupalWebTestCase { ...@@ -559,6 +580,15 @@ class JavaScriptTestCase extends DrupalWebTestCase {
$this->assertEqual('rocks', $javascript['settings']['data'][1]['drupal'], t('The other JavaScript setting is set correctly.')); $this->assertEqual('rocks', $javascript['settings']['data'][1]['drupal'], t('The other JavaScript setting is set correctly.'));
} }
/**
* Tests adding an external JavaScript File.
*/
function testAddExternal() {
$path = 'http://example.com/script.js';
$javascript = drupal_add_js($path, 'external');
$this->assertTrue(array_key_exists('http://example.com/script.js', $javascript), t('Added an external JavaScript file.'));
}
/** /**
* Test drupal_get_js() for JavaScript settings. * Test drupal_get_js() for JavaScript settings.
*/ */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment