From 383b89a1e2fb891b246a0091e54b87f8e68fa13a Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Wed, 28 Nov 2012 18:15:54 +1300 Subject: [PATCH] MDL-36888 theme: allow the use of SVG in CSS background images. --- lib/outputlib.php | 52 +++++++++++++++++++++++++++--------------- theme/styles.php | 38 ++++++++++++++++++++++++++---- theme/styles_debug.php | 9 +++++++- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/lib/outputlib.php b/lib/outputlib.php index da1761b216c..15b772f8b88 100644 --- a/lib/outputlib.php +++ b/lib/outputlib.php @@ -618,20 +618,34 @@ class theme_config { $urls = array(); + $svg = $this->use_svg_icons(); + if ($rev > -1) { + $url = new moodle_url("$CFG->httpswwwroot/theme/styles.php"); if (check_browser_version('MSIE', 5)) { // We need to split the CSS files for IE - $urls[] = new moodle_url($CFG->httpswwwroot.'/theme/styles.php', array('theme'=>$this->name,'rev'=>$rev, 'type'=>'plugins')); - $urls[] = new moodle_url($CFG->httpswwwroot.'/theme/styles.php', array('theme'=>$this->name,'rev'=>$rev, 'type'=>'parents')); - $urls[] = new moodle_url($CFG->httpswwwroot.'/theme/styles.php', array('theme'=>$this->name,'rev'=>$rev, 'type'=>'theme')); + $urls[] = new moodle_url($url, array('theme' => $this->name,'rev' => $rev, 'type' => 'plugins', 'svg' => '0')); + $urls[] = new moodle_url($url, array('theme' => $this->name,'rev' => $rev, 'type' => 'parents', 'svg' => '0')); + $urls[] = new moodle_url($url, array('theme' => $this->name,'rev' => $rev, 'type' => 'theme', 'svg' => '0')); } else { if (!empty($CFG->slasharguments)) { - $url = new moodle_url("$CFG->httpswwwroot/theme/styles.php"); - $url->set_slashargument('/'.$this->name.'/'.$rev.'/all', 'noparam', true); - $urls[] = $url; + $slashargs = '/'.$this->name.'/'.$rev.'/all'; + if (!$svg) { + // We add a simple /_s to the start of the path. + // The underscore is used to ensure that it isn't a valid theme name. + $slashargs = '/_s'.$slashargs; + } + $url->set_slashargument($slashargs, 'noparam', true); } else { - $urls[] = new moodle_url($CFG->httpswwwroot.'/theme/styles.php', array('theme'=>$this->name,'rev'=>$rev, 'type'=>'all')); + $params = array('theme' => $this->name,'rev' => $rev, 'type' => 'all'); + if (!$svg) { + // We add an SVG param so that we know not to serve SVG images. + // We do this because all modern browsers support SVG and this param will one day be removed. + $params['svg'] = '0'; + } + $url->params($params); } + $urls[] = $url; } } else { // find out the current CSS and cache it now for 5 seconds @@ -641,7 +655,11 @@ class theme_config { define('THEME_DESIGNER_CACHE_LIFETIME', 4); // this can be also set in config.php } $candidatedir = "$CFG->cachedir/theme/$this->name"; - $candidatesheet = "$candidatedir/designer.ser"; + if ($svg) { + $candidatesheet = "$candidatedir/designer.ser"; + } else { + $candidatesheet = "$candidatedir/designer_nosvg.ser"; + } $rebuild = true; if (file_exists($candidatesheet) and filemtime($candidatesheet) > time() - THEME_DESIGNER_CACHE_LIFETIME) { if ($css = file_get_contents($candidatesheet)) { @@ -674,8 +692,12 @@ class theme_config { ignore_user_abort($prevabort); } - $baseurl = $CFG->httpswwwroot.'/theme/styles_debug.php'; - + $baseurl = new moodle_url($CFG->httpswwwroot.'/theme/styles_debug.php'); + if (!$svg) { + // We add an SVG param so that we know not to serve SVG images. + // We do this because all modern browsers support SVG and this param will one day be removed. + $baseurl->param('svg', '0'); + } if (check_browser_version('MSIE', 5)) { // lalala, IE does not allow more than 31 linked CSS files from main document $urls[] = new moodle_url($baseurl, array('theme'=>$this->name, 'type'=>'ie', 'subtype'=>'plugins')); @@ -948,12 +970,6 @@ class theme_config { public function post_process($css) { // now resolve all image locations if (preg_match_all('/\[\[pix:([a-z_]+\|)?([^\]]+)\]\]/', $css, $matches, PREG_SET_ORDER)) { - // We are going to disable the use of SVG images when available in CSS background-image properties - // as support for it in browsers is at best quirky. - // When we choose to support SVG in background css we will need to remove this code and implement a solution that is - // either consistent or varies the URL for serving CSS depending upon SVG being used if available, or not. - $originalsvguse = $this->use_svg_icons(); - $this->force_svg_use(false); $replaced = array(); foreach ($matches as $match) { if (isset($replaced[$match[0]])) { @@ -967,7 +983,6 @@ class theme_config { $imageurl = preg_replace('|^http.?://[^/]+|', '', $imageurl); $css = str_replace($match[0], $imageurl, $css); } - $this->force_svg_use($originalsvguse); } // now resolve all theme settings or do any other postprocessing @@ -1145,10 +1160,11 @@ class theme_config { * Forces the usesvg setting to either true or false, avoiding any decision making. * * This function should only ever be used when absolutely required, and before any generation of image URL's has occurred. + * DO NOT ABUSE THIS FUNCTION... not that you'd want to right ;) * * @param bool $setting True to force the use of svg when available, null otherwise. */ - private function force_svg_use($setting) { + public function force_svg_use($setting) { $this->usesvg = (bool)$setting; } diff --git a/theme/styles.php b/theme/styles.php index 0e74a17fad3..1d15639ac1f 100644 --- a/theme/styles.php +++ b/theme/styles.php @@ -38,6 +38,15 @@ if ($slashargument = min_get_slash_argument()) { if (substr_count($slashargument, '/') < 2) { image_not_found(); } + + if (strpos($slashargument, '_s/') === 0) { + // Can't use SVG + $slashargument = substr($slashargument, 3); + $usesvg = false; + } else { + $usesvg = true; + } + // image must be last because it may contain "/" list($themename, $rev, $type) = explode('/', $slashargument, 3); $themename = min_clean_param($themename, 'SAFEDIR'); @@ -48,6 +57,7 @@ if ($slashargument = min_get_slash_argument()) { $themename = min_optional_param('theme', 'standard', 'SAFEDIR'); $rev = min_optional_param('rev', 0, 'INT'); $type = min_optional_param('type', 'all', 'SAFEDIR'); + $usesvg = (bool)min_optional_param('svg', '1', 'INT'); } if (!in_array($type, array('all', 'ie', 'editor', 'plugins', 'parents', 'theme'))) { @@ -68,8 +78,15 @@ if ($type === 'ie') { css_send_ie_css($themename, $rev, $etag, !empty($slashargument)); } -$candidatesheet = "$CFG->cachedir/theme/$themename/css/$type.css"; -$etag = sha1("$themename/$rev/$type"); +$candidatedir = "$CFG->cachedir/theme/$themename/css"; +$etag = "$themename/$rev/$type"; +if (!$usesvg) { + // Add to the sheet name, one day we'll be able to just drop this. + $candidatedir .= '/nosvg'; + $etag .= '/nosvg'; +} +$candidatesheet = "$candidatedir/$type.css"; +$etag = sha1($etag); if (file_exists($candidatesheet)) { if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { @@ -90,14 +107,25 @@ define('NO_UPGRADE_CHECK', true); // Ignore upgrade check require("$CFG->dirroot/lib/setup.php"); $theme = theme_config::load($themename); +$theme->force_svg_use($usesvg); $rev = theme_get_revision(); -$etag = sha1("$themename/$rev/$type"); + +$etag = "$themename/$rev/$type"; +if (!$usesvg) { + // Add to the etag, one day we'll be able to just delete svg nonsense this. + $etag .= '/nosvg'; +} +$etag = sha1($etag); if ($type === 'editor') { $cssfiles = $theme->editor_css_files(); css_store_css($theme, $candidatesheet, $cssfiles); } else { + $basedir = "$CFG->cachedir/theme/$themename/css"; + if (!$usesvg) { + $basedir .= '/nosvg'; + } $css = $theme->css_files(); $allfiles = array(); foreach ($css as $key=>$value) { @@ -111,11 +139,11 @@ if ($type === 'editor') { $cssfiles[] = $val; } } - $cssfile = "$CFG->cachedir/theme/$themename/css/$key.css"; + $cssfile = "$basedir/$key.css"; css_store_css($theme, $cssfile, $cssfiles); $allfiles = array_merge($allfiles, $cssfiles); } - $cssfile = "$CFG->cachedir/theme/$themename/css/all.css"; + $cssfile = "$basedir/all.css"; css_store_css($theme, $cssfile, $allfiles); } diff --git a/theme/styles_debug.php b/theme/styles_debug.php index ea473053ed4..140fefdec63 100644 --- a/theme/styles_debug.php +++ b/theme/styles_debug.php @@ -32,6 +32,7 @@ $themename = min_optional_param('theme', 'standard', 'SAFEDIR'); $type = min_optional_param('type', '', 'SAFEDIR'); $subtype = min_optional_param('subtype', '', 'SAFEDIR'); $sheet = min_optional_param('sheet', '', 'SAFEDIR'); +$usesvg = (bool)min_optional_param('svg', '1', 'INT'); if (!defined('THEME_DESIGNER_CACHE_LIFETIME')) { define('THEME_DESIGNER_CACHE_LIFETIME', 4); // this can be also set in config.php @@ -47,9 +48,15 @@ if (file_exists("$CFG->dirroot/theme/$themename/config.php")) { // no gzip compression when debugging -$candidatesheet = "$CFG->cachedir/theme/$themename/designer.ser"; +if ($usesvg) { + $candidatesheet = "$CFG->cachedir/theme/$themename/designer.ser"; +} else { + // Add to the sheet name, one day we'll be able to just drop this. + $candidatesheet = "$CFG->cachedir/theme/$themename/designer_nosvg.ser"; +} if (!file_exists($candidatesheet)) { + css_send_css_not_found(); }