mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
Merge branch 'w10_MDL-44358_m27_stylesrefact' of https://github.com/skodak/moodle
This commit is contained in:
commit
d129de3761
@ -15,10 +15,12 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains CSS related class, and function for the CSS optimiser
|
||||
* This file contains CSS related class, and function for the CSS optimiser.
|
||||
*
|
||||
* Please see the {@link css_optimiser} class for greater detail.
|
||||
*
|
||||
* NOTE: these functions are not expected to be used from any addons.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cssoptimiser
|
||||
* @copyright 2012 Sam Hemelryk
|
||||
@ -27,6 +29,12 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if (!defined('THEME_DESIGNER_CACHE_LIFETIME')) {
|
||||
// This can be also set in config.php file,
|
||||
// it needs to be higher than the time it takes to generate all CSS content.
|
||||
define('THEME_DESIGNER_CACHE_LIFETIME', 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores CSS in a file at the given path.
|
||||
*
|
||||
@ -34,50 +42,15 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*
|
||||
* @param theme_config $theme The theme that the CSS belongs to.
|
||||
* @param string $csspath The path to store the CSS at.
|
||||
* @param array $cssfiles The CSS files to store.
|
||||
* @param string $csscontent the complete CSS in one string
|
||||
* @param bool $chunk If set to true these files will be chunked to ensure
|
||||
* that no one file contains more than 4095 selectors.
|
||||
* @param string $chunkurl If the CSS is be chunked then we need to know the URL
|
||||
* to use for the chunked files.
|
||||
*/
|
||||
function css_store_css(theme_config $theme, $csspath, array $cssfiles, $chunk = false, $chunkurl = null) {
|
||||
function css_store_css(theme_config $theme, $csspath, $csscontent, $chunk = false, $chunkurl = null) {
|
||||
global $CFG;
|
||||
|
||||
$css = '';
|
||||
foreach ($cssfiles as $file) {
|
||||
$css .= file_get_contents($file)."\n";
|
||||
}
|
||||
|
||||
// Check if both the CSS optimiser is enabled and the theme supports it.
|
||||
if (!empty($CFG->enablecssoptimiser) && $theme->supportscssoptimisation) {
|
||||
// This is an experimental feature introduced in Moodle 2.3
|
||||
// The CSS optimiser organises the CSS in order to reduce the overall number
|
||||
// of rules and styles being sent to the client. It does this by collating
|
||||
// the CSS before it is cached removing excess styles and rules and stripping
|
||||
// out any extraneous content such as comments and empty rules.
|
||||
$optimiser = new css_optimiser;
|
||||
$css = $theme->post_process($css);
|
||||
$css = $optimiser->process($css);
|
||||
|
||||
// If cssoptimisestats is set then stats from the optimisation are collected
|
||||
// and output at the beginning of the CSS.
|
||||
if (!empty($CFG->cssoptimiserstats)) {
|
||||
$css = $optimiser->output_stats_css().$css;
|
||||
}
|
||||
} else {
|
||||
// This is the default behaviour.
|
||||
// The cssoptimise setting was introduced in Moodle 2.3 and will hopefully
|
||||
// in the future be changed from an experimental setting to the default.
|
||||
// The css_minify_css will method will use the Minify library remove
|
||||
// comments, additional whitespace and other minor measures to reduce the
|
||||
// the overall CSS being sent.
|
||||
// However it has the distinct disadvantage of having to minify the CSS
|
||||
// before running the post process functions. Potentially things may break
|
||||
// here if theme designers try to push things with CSS post processing.
|
||||
$css = $theme->post_process($css);
|
||||
$css = core_minify::css($css);
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
if (!file_exists(dirname($csspath))) {
|
||||
@mkdir(dirname($csspath), $CFG->directorypermissions, true);
|
||||
@ -88,11 +61,11 @@ function css_store_css(theme_config $theme, $csspath, array $cssfiles, $chunk =
|
||||
ignore_user_abort(true);
|
||||
|
||||
// First up write out the single file for all those using decent browsers.
|
||||
css_write_file($csspath, $css);
|
||||
css_write_file($csspath, $csscontent);
|
||||
|
||||
if ($chunk) {
|
||||
// If we need to chunk the CSS for browsers that are sub-par.
|
||||
$css = css_chunk_by_selector_count($css, $chunkurl);
|
||||
$css = css_chunk_by_selector_count($csscontent, $chunkurl);
|
||||
$files = count($css);
|
||||
$count = 1;
|
||||
foreach ($css as $content) {
|
||||
@ -240,6 +213,32 @@ function css_send_cached_css($csspath, $etag) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a cached CSS content
|
||||
*
|
||||
* @param string $csscontent The actual CSS markup.
|
||||
* @param string $etag The revision to make sure we utilise any caches.
|
||||
*/
|
||||
function css_send_cached_css_content($csscontent, $etag) {
|
||||
// 60 days only - the revision may get incremented quite often.
|
||||
$lifetime = 60*60*24*60;
|
||||
|
||||
header('Etag: "'.$etag.'"');
|
||||
header('Content-Disposition: inline; filename="styles.php"');
|
||||
header('Last-Modified: '. gmdate('D, d M Y H:i:s', time()) .' GMT');
|
||||
header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT');
|
||||
header('Pragma: ');
|
||||
header('Cache-Control: public, max-age='.$lifetime);
|
||||
header('Accept-Ranges: none');
|
||||
header('Content-Type: text/css; charset=utf-8');
|
||||
if (!min_enable_zlib_compression()) {
|
||||
header('Content-Length: '.strlen($csscontent));
|
||||
}
|
||||
|
||||
echo($csscontent);
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends CSS directly without caching it.
|
||||
*
|
||||
|
@ -55,6 +55,11 @@ function theme_reset_all_caches() {
|
||||
|
||||
set_config('themerev', $next); // time is unique even when you reset/switch database
|
||||
|
||||
if (!empty($CFG->themedesignermode)) {
|
||||
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'core', 'themedesigner');
|
||||
$cache->purge();
|
||||
}
|
||||
|
||||
if ($PAGE) {
|
||||
$PAGE->reload_theme();
|
||||
}
|
||||
@ -66,8 +71,9 @@ function theme_reset_all_caches() {
|
||||
* @param bool $state
|
||||
*/
|
||||
function theme_set_designer_mod($state) {
|
||||
theme_reset_all_caches();
|
||||
set_config('themedesignermode', (int)!empty($state));
|
||||
// Reset caches after switching mode so that any designer mode caches get purged too.
|
||||
theme_reset_all_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -594,14 +600,12 @@ class theme_config {
|
||||
/**
|
||||
* Returns the content of the CSS to be used in editor content
|
||||
*
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
public function editor_css_files() {
|
||||
global $CFG;
|
||||
|
||||
$files = array();
|
||||
|
||||
// first editor plugins
|
||||
// First editor plugins.
|
||||
$plugins = core_component::get_plugin_list('editor');
|
||||
foreach ($plugins as $plugin=>$fulldir) {
|
||||
$sheetfile = "$fulldir/editor_styles.css";
|
||||
@ -609,8 +613,8 @@ class theme_config {
|
||||
$files['plugin_'.$plugin] = $sheetfile;
|
||||
}
|
||||
}
|
||||
// then parent themes
|
||||
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
||||
// Then parent themes - base first, the immediate parent last.
|
||||
foreach (array_reverse($this->parent_configs) as $parent_config) {
|
||||
if (empty($parent_config->editor_sheets)) {
|
||||
continue;
|
||||
}
|
||||
@ -621,7 +625,7 @@ class theme_config {
|
||||
}
|
||||
}
|
||||
}
|
||||
// finally this theme
|
||||
// Finally this theme.
|
||||
if (!empty($this->editor_sheets)) {
|
||||
foreach ($this->editor_sheets as $sheet) {
|
||||
$sheetfile = "$this->dir/style/$sheet.css";
|
||||
@ -635,10 +639,10 @@ class theme_config {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stylesheet URL of this theme
|
||||
* Get the stylesheet URL of this theme.
|
||||
*
|
||||
* @param moodle_page $page Not used... deprecated?
|
||||
* @return array of moodle_url
|
||||
* @return moodle_url[]
|
||||
*/
|
||||
public function css_urls(moodle_page $page) {
|
||||
global $CFG;
|
||||
@ -679,50 +683,7 @@ class theme_config {
|
||||
$urls[] = $url;
|
||||
|
||||
} else {
|
||||
// find out the current CSS and cache it now for 5 seconds
|
||||
// the point is to construct the CSS only once and pass it through the
|
||||
// dataroot to the script that actually serves the sheets
|
||||
if (!defined('THEME_DESIGNER_CACHE_LIFETIME')) {
|
||||
define('THEME_DESIGNER_CACHE_LIFETIME', 4); // this can be also set in config.php
|
||||
}
|
||||
$candidatedir = "$CFG->cachedir/theme/$this->name";
|
||||
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)) {
|
||||
$css = unserialize($css);
|
||||
if (is_array($css)) {
|
||||
$rebuild = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($rebuild) {
|
||||
// Prepare the CSS optimiser if it is to be used,
|
||||
// please note that it may be very slow and is therefore strongly discouraged in theme designer mode.
|
||||
$optimiser = null;
|
||||
if (!empty($CFG->enablecssoptimiser) && $this->supportscssoptimisation) {
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
$optimiser = new css_optimiser;
|
||||
}
|
||||
$css = $this->css_content($optimiser);
|
||||
|
||||
// We do not want any errors here because this may fail easily because of the concurrent access.
|
||||
$prevabort = ignore_user_abort(true);
|
||||
check_dir_exists($candidatedir);
|
||||
$tempfile = tempnam($candidatedir, 'tmpdesigner');
|
||||
file_put_contents($tempfile, serialize($css));
|
||||
$reporting = error_reporting(0);
|
||||
chmod($tempfile, $CFG->filepermissions);
|
||||
unlink($candidatesheet); // Do not rely on rename() deleting original, they may decide to change it at any time as usually.
|
||||
rename($tempfile, $candidatesheet);
|
||||
error_reporting($reporting);
|
||||
ignore_user_abort($prevabort);
|
||||
}
|
||||
|
||||
$css = $this->get_css_files(true);
|
||||
$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.
|
||||
@ -730,10 +691,10 @@ class theme_config {
|
||||
$baseurl->param('svg', '0');
|
||||
}
|
||||
if (core_useragent::is_ie()) {
|
||||
// lalala, IE does not allow more than 31 linked CSS files from main document
|
||||
// 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'));
|
||||
foreach ($css['parents'] as $parent=>$sheets) {
|
||||
// We need to serve parents individually otherwise we may easily exceed the style limit IE imposes (4096)
|
||||
// We need to serve parents individually otherwise we may easily exceed the style limit IE imposes (4096).
|
||||
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name,'type'=>'ie', 'subtype'=>'parents', 'sheet'=>$parent));
|
||||
}
|
||||
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name, 'type'=>'ie', 'subtype'=>'theme'));
|
||||
@ -748,7 +709,8 @@ class theme_config {
|
||||
}
|
||||
}
|
||||
foreach ($css['theme'] as $sheet=>$unused) {
|
||||
$urls[] = new moodle_url($baseurl, array('sheet'=>$sheet, 'theme'=>$this->name, 'type'=>'theme')); // sheet first in order to make long urls easier to read
|
||||
// Sheet first in order to make long urls easier to read.
|
||||
$urls[] = new moodle_url($baseurl, array('sheet'=>$sheet, 'theme'=>$this->name, 'type'=>'theme'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -757,14 +719,169 @@ class theme_config {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of organised CSS files required for this output
|
||||
* Get the whole css stylesheet for production mode.
|
||||
*
|
||||
* @return array
|
||||
* NOTE: this method is not expected to be used from any addons.
|
||||
*
|
||||
* @return string CSS markup, already optimised and compressed
|
||||
*/
|
||||
public function css_files() {
|
||||
public function get_css_content() {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
|
||||
$csscontent = '';
|
||||
foreach ($this->get_css_files(false) as $value) {
|
||||
foreach ($value as $val) {
|
||||
if (is_array($val)) {
|
||||
foreach ($val as $v) {
|
||||
$csscontent .= file_get_contents($v) . "\n";
|
||||
}
|
||||
} else {
|
||||
$csscontent .= file_get_contents($val) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$csscontent = $this->post_process($csscontent);
|
||||
|
||||
if (!empty($CFG->enablecssoptimiser) && $this->supportscssoptimisation) {
|
||||
// This is an experimental feature introduced in Moodle 2.3
|
||||
// The CSS optimiser organises the CSS in order to reduce the overall number
|
||||
// of rules and styles being sent to the client. It does this by collating
|
||||
// the CSS before it is cached removing excess styles and rules and stripping
|
||||
// out any extraneous content such as comments and empty rules.
|
||||
$optimiser = new css_optimiser();
|
||||
$csscontent = $optimiser->process($csscontent);
|
||||
|
||||
} else {
|
||||
$csscontent = core_minify::css($csscontent);
|
||||
}
|
||||
|
||||
return $csscontent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the theme designer css markup,
|
||||
* the parameters are coming from css_urls().
|
||||
*
|
||||
* NOTE: this method is not expected to be used from any addons.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $subtype
|
||||
* @param string $sheet
|
||||
* @return string CSS markup
|
||||
*/
|
||||
public function get_css_content_debug($type, $subtype, $sheet) {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
|
||||
$optimiser = null;
|
||||
if (!empty($CFG->enablecssoptimiser) && $this->supportscssoptimisation) {
|
||||
// This is an experimental feature introduced in Moodle 2.3
|
||||
// The CSS optimiser organises the CSS in order to reduce the overall number
|
||||
// of rules and styles being sent to the client. It does this by collating
|
||||
// the CSS before it is cached removing excess styles and rules and stripping
|
||||
// out any extraneous content such as comments and empty rules.
|
||||
$optimiser = new css_optimiser();
|
||||
}
|
||||
|
||||
$cssfiles = array();
|
||||
$css = $this->get_css_files(true);
|
||||
|
||||
if ($type === 'ie') {
|
||||
// IE is a sloppy browser with weird limits, sorry.
|
||||
if ($subtype === 'plugins') {
|
||||
$cssfiles = $css['plugins'];
|
||||
|
||||
} else if ($subtype === 'parents') {
|
||||
if (empty($sheet)) {
|
||||
// Do not bother with the empty parent here.
|
||||
} else {
|
||||
// Build up the CSS for that parent so we can serve it as one file.
|
||||
foreach ($css[$subtype][$sheet] as $parent => $css) {
|
||||
$cssfiles[] = $css;
|
||||
}
|
||||
}
|
||||
} else if ($subtype === 'theme') {
|
||||
$cssfiles = $css['theme'];
|
||||
}
|
||||
|
||||
} else if ($type === 'plugin') {
|
||||
if (isset($css['plugins'][$subtype])) {
|
||||
$cssfiles[] = $css['plugins'][$subtype];
|
||||
}
|
||||
|
||||
} else if ($type === 'parent') {
|
||||
if (isset($css['parents'][$subtype][$sheet])) {
|
||||
$cssfiles[] = $css['parents'][$subtype][$sheet];
|
||||
}
|
||||
|
||||
} else if ($type === 'theme') {
|
||||
if (isset($css['theme'][$sheet])) {
|
||||
$cssfiles[] = $css['theme'][$sheet];
|
||||
}
|
||||
}
|
||||
|
||||
$csscontent = '';
|
||||
foreach ($cssfiles as $file) {
|
||||
$contents = file_get_contents($file);
|
||||
$contents = $this->post_process($contents);
|
||||
$comment = "/** Path: $type $subtype $sheet.' **/\n";
|
||||
$stats = '';
|
||||
if ($optimiser) {
|
||||
$contents = $optimiser->process($contents);
|
||||
if (!empty($CFG->cssoptimiserstats)) {
|
||||
$stats = $optimiser->output_stats_css();
|
||||
}
|
||||
}
|
||||
$csscontent .= $comment.$stats.$contents."\n\n";
|
||||
}
|
||||
|
||||
return $csscontent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the whole css stylesheet for editor iframe.
|
||||
*
|
||||
* NOTE: this method is not expected to be used from any addons.
|
||||
*
|
||||
* @return string CSS markup
|
||||
*/
|
||||
public function get_css_content_editor() {
|
||||
// Do not bother to optimise anything here, just very basic stuff.
|
||||
$cssfiles = $this->editor_css_files();
|
||||
$css = '';
|
||||
foreach ($cssfiles as $file) {
|
||||
$css .= file_get_contents($file)."\n";
|
||||
}
|
||||
return $this->post_process($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of organised CSS files required for this output.
|
||||
*
|
||||
* @param bool $themedesigner
|
||||
* @return array nested array of file paths
|
||||
*/
|
||||
protected function get_css_files($themedesigner) {
|
||||
global $CFG;
|
||||
|
||||
$cache = null;
|
||||
if ($themedesigner) {
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
// We need some kind of caching here because otherwise the page navigation becomes
|
||||
// way too slow in theme designer mode. Feel free to create full cache definition later...
|
||||
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'core', 'themedesigner', array('theme' => $this->name));
|
||||
if ($files = $cache->get('cssfiles')) {
|
||||
if ($files['created'] > time() - THEME_DESIGNER_CACHE_LIFETIME) {
|
||||
unset($files['created']);
|
||||
return $files;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cssfiles = array('plugins'=>array(), 'parents'=>array(), 'theme'=>array());
|
||||
|
||||
// get all plugin sheets
|
||||
// Get all plugin sheets.
|
||||
$excludes = $this->resolve_excludes('plugins_exclude_sheets');
|
||||
if ($excludes !== true) {
|
||||
foreach (core_component::get_plugin_types() as $type=>$unused) {
|
||||
@ -802,10 +919,10 @@ class theme_config {
|
||||
}
|
||||
}
|
||||
|
||||
// find out wanted parent sheets
|
||||
// Find out wanted parent sheets.
|
||||
$excludes = $this->resolve_excludes('parents_exclude_sheets');
|
||||
if ($excludes !== true) {
|
||||
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
||||
foreach (array_reverse($this->parent_configs) as $parent_config) { // Base first, the immediate parent last.
|
||||
$parent = $parent_config->name;
|
||||
if (empty($parent_config->sheets) || (!empty($excludes[$parent]) and $excludes[$parent] === true)) {
|
||||
continue;
|
||||
@ -823,7 +940,7 @@ class theme_config {
|
||||
}
|
||||
}
|
||||
|
||||
// current theme sheets
|
||||
// Current theme sheets.
|
||||
if (is_array($this->sheets)) {
|
||||
foreach ($this->sheets as $sheet) {
|
||||
$sheetfile = "$this->dir/style/$sheet.css";
|
||||
@ -833,57 +950,15 @@ class theme_config {
|
||||
}
|
||||
}
|
||||
|
||||
if ($cache) {
|
||||
$files = $cssfiles;
|
||||
$files['created'] = time();
|
||||
$cache->set('cssfiles', $files);
|
||||
}
|
||||
|
||||
return $cssfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content of the one huge CSS merged from all style sheets.
|
||||
*
|
||||
* @param css_optimiser|null $optimiser A CSS optimiser to use during on the content. Null = don't optimise
|
||||
* @return string
|
||||
*/
|
||||
public function css_content(css_optimiser $optimiser = null) {
|
||||
$files = array_merge($this->css_files(), array('editor'=>$this->editor_css_files()));
|
||||
$css = $this->css_files_get_contents($files, array(), $optimiser);
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of file paths or a single file path loads the contents of
|
||||
* the CSS file, processes it then returns it in the same structure it was given.
|
||||
*
|
||||
* Can be used recursively on the results of {@link css_files}
|
||||
*
|
||||
* @param array|string $file An array of file paths or a single file path
|
||||
* @param array $keys An array of previous array keys [recursive addition]
|
||||
* @param css_optimiser|null $optimiser A CSS optimiser to use during on the content. Null = don't optimise
|
||||
* @return The converted array or the contents of the single file ($file type)
|
||||
*/
|
||||
protected function css_files_get_contents($file, array $keys, css_optimiser $optimiser = null) {
|
||||
global $CFG;
|
||||
if (is_array($file)) {
|
||||
// We use a separate array to keep everything in the exact same order.
|
||||
$return = array();
|
||||
foreach ($file as $key=>$f) {
|
||||
$return[clean_param($key, PARAM_SAFEDIR)] = $this->css_files_get_contents($f, array_merge($keys, array($key)), $optimiser);
|
||||
}
|
||||
return $return;
|
||||
} else {
|
||||
$contents = file_get_contents($file);
|
||||
$contents = $this->post_process($contents);
|
||||
$comment = '/** Path: '.implode(' ', $keys).' **/'."\n";
|
||||
$stats = '';
|
||||
if (!is_null($optimiser)) {
|
||||
$contents = $optimiser->process($contents);
|
||||
if (!empty($CFG->cssoptimiserstats)) {
|
||||
$stats = $optimiser->output_stats_css();
|
||||
}
|
||||
}
|
||||
return $comment.$stats.$contents;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a URL to the file that serves theme JavaScript files.
|
||||
*
|
||||
@ -1359,7 +1434,6 @@ class theme_config {
|
||||
/**
|
||||
* Return true if we should look for SVG images as well.
|
||||
*
|
||||
* @staticvar bool $svg
|
||||
* @return bool
|
||||
*/
|
||||
public function use_svg_icons() {
|
||||
|
@ -22,20 +22,14 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
// disable moodle specific debug messages and any errors in output,
|
||||
// Disable moodle specific debug messages and any errors in output,
|
||||
// comment out when debugging or better look into error log!
|
||||
define('NO_DEBUG_DISPLAY', true);
|
||||
|
||||
// we need just the values from config.php and minlib.php
|
||||
define('ABORT_AFTER_CONFIG', true);
|
||||
require('../config.php'); // this stops immediately at the beginning of lib/setup.php
|
||||
require('../config.php');
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
|
||||
if (!defined('THEME_DESIGNER_CACHE_LIFETIME')) {
|
||||
define('THEME_DESIGNER_CACHE_LIFETIME', 4); // this can be also set in config.php
|
||||
}
|
||||
|
||||
if ($slashargument = min_get_slash_argument()) {
|
||||
$slashargument = ltrim($slashargument, '/');
|
||||
if (substr_count($slashargument, '/') < 2) {
|
||||
@ -43,7 +37,7 @@ if ($slashargument = min_get_slash_argument()) {
|
||||
}
|
||||
|
||||
if (strpos($slashargument, '_s/') === 0) {
|
||||
// Can't use SVG
|
||||
// Can't use SVG.
|
||||
$slashargument = substr($slashargument, 3);
|
||||
$usesvg = false;
|
||||
} else {
|
||||
@ -79,9 +73,9 @@ if ($type === 'editor') {
|
||||
}
|
||||
|
||||
if (file_exists("$CFG->dirroot/theme/$themename/config.php")) {
|
||||
// exists
|
||||
// The theme exists in standard location - ok.
|
||||
} else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$themename/config.php")) {
|
||||
// exists
|
||||
// Alternative theme location contains this theme - ok.
|
||||
} else {
|
||||
header('HTTP/1.0 404 not found');
|
||||
die('Theme was not found, sorry.');
|
||||
@ -105,19 +99,18 @@ $etag = sha1($etag);
|
||||
|
||||
if (file_exists($candidatesheet)) {
|
||||
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
// we do not actually need to verify the etag value because our files
|
||||
// never change in cache because we increment the rev parameter
|
||||
// We do not actually need to verify the etag value because our files
|
||||
// never change in cache because we increment the rev counter.
|
||||
css_send_unmodified(filemtime($candidatesheet), $etag);
|
||||
}
|
||||
css_send_cached_css($candidatesheet, $etag);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// ok, now we need to start normal moodle script, we need to load all libs and $DB
|
||||
// Ok, now we need to start normal moodle script, we need to load all libs and $DB.
|
||||
define('ABORT_AFTER_CONFIG_CANCEL', true);
|
||||
|
||||
define('NO_MOODLE_COOKIES', true); // Session not used here
|
||||
define('NO_UPGRADE_CHECK', true); // Ignore upgrade check
|
||||
define('NO_MOODLE_COOKIES', true); // Session not used here.
|
||||
define('NO_UPGRADE_CHECK', true); // Ignore upgrade check.
|
||||
|
||||
require("$CFG->dirroot/lib/setup.php");
|
||||
|
||||
@ -131,7 +124,7 @@ if ($themerev <= 0 or $themerev != $rev) {
|
||||
$rev = $themerev;
|
||||
$cache = false;
|
||||
|
||||
$candidatedir = "$CFG->cachedir/theme/$rev/$themename/css";
|
||||
$candidatedir = "$CFG->localcachedir/theme/$rev/$themename/css";
|
||||
$etag = "$rev/$themename/$type";
|
||||
$candidatename = $type;
|
||||
if (!$usesvg) {
|
||||
@ -151,12 +144,13 @@ if ($themerev <= 0 or $themerev != $rev) {
|
||||
make_localcache_directory('theme', false);
|
||||
|
||||
if ($type === 'editor') {
|
||||
$cssfiles = $theme->editor_css_files();
|
||||
css_store_css($theme, "$candidatedir/editor.css", $cssfiles, false);
|
||||
$csscontent = $theme->get_css_content_editor();
|
||||
css_store_css($theme, "$candidatedir/editor.css", $csscontent, false);
|
||||
|
||||
} else {
|
||||
// Older IEs require smaller chunks.
|
||||
$css = $theme->css_files();
|
||||
$csscontent = $theme->get_css_content();
|
||||
|
||||
$relroot = preg_replace('|^http.?://[^/]+|', '', $CFG->wwwroot);
|
||||
if (!empty($slashargument)) {
|
||||
if ($usesvg) {
|
||||
@ -171,36 +165,19 @@ if ($type === 'editor') {
|
||||
$chunkurl = "{$relroot}/theme/styles.php?theme={$themename}&rev={$rev}&type=all&svg=0";
|
||||
}
|
||||
}
|
||||
$cssfiles = array();
|
||||
foreach ($css as $key => $value) {
|
||||
foreach ($value as $val) {
|
||||
if (is_array($val)) {
|
||||
foreach ($val as $k=>$v) {
|
||||
$cssfiles[] = $v;
|
||||
}
|
||||
} else {
|
||||
$cssfiles[] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
css_store_css($theme, "$candidatedir/all.css", $cssfiles, true, $chunkurl);
|
||||
css_store_css($theme, "$candidatedir/all.css", $csscontent, true, $chunkurl);
|
||||
}
|
||||
|
||||
// verify nothing failed in cache file creation
|
||||
clearstatcache();
|
||||
if (!file_exists($candidatesheet)) {
|
||||
// We need to send at least something, IE does not get it chunked properly but who cares.
|
||||
$css = '';
|
||||
foreach ($cssfiles as $file) {
|
||||
$css .= file_get_contents($file)."\n";
|
||||
}
|
||||
css_send_uncached_css($css, false);
|
||||
if (!$cache) {
|
||||
// Do not pollute browser caches if invalid revision requested,
|
||||
// let's ignore legacy IE breakage here too.
|
||||
css_send_uncached_css($csscontent);
|
||||
|
||||
} else if (!$cache) {
|
||||
// Do not pollute browser caches if invalid revision requested.
|
||||
css_send_uncached_css(file_get_contents($candidatesheet), false);
|
||||
} else if ($chunk and file_exists($candidatesheet)) {
|
||||
// Greetings stupid legacy IEs!
|
||||
css_send_cached_css($candidatesheet, $etag);
|
||||
|
||||
} else {
|
||||
// This is the expected result!
|
||||
css_send_cached_css($candidatesheet, $etag);
|
||||
// Real browsers - this is the expected result!
|
||||
css_send_cached_css_content($csscontent, $etag);
|
||||
}
|
||||
|
@ -25,100 +25,47 @@
|
||||
// Disable moodle specific debug messages and any errors in output,
|
||||
// comment out when debugging or better look into error log!
|
||||
define('NO_DEBUG_DISPLAY', true);
|
||||
define('NO_UPGRADE_CHECK', true);
|
||||
define('NO_MOODLE_COOKIES', true);
|
||||
|
||||
define('ABORT_AFTER_CONFIG', true);
|
||||
require('../config.php'); // this stops immediately at the beginning of lib/setup.php
|
||||
require('../config.php');
|
||||
require_once($CFG->dirroot.'/lib/csslib.php');
|
||||
|
||||
$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
|
||||
}
|
||||
$themename = optional_param('theme', 'standard', PARAM_SAFEDIR);
|
||||
$type = optional_param('type', '', PARAM_SAFEDIR);
|
||||
$subtype = optional_param('subtype', '', PARAM_SAFEDIR);
|
||||
$sheet = optional_param('sheet', '', PARAM_SAFEDIR);
|
||||
$usesvg = optional_param('svg', 1, PARAM_BOOL);
|
||||
|
||||
if (file_exists("$CFG->dirroot/theme/$themename/config.php")) {
|
||||
// exists
|
||||
// The theme exists in standard location - ok.
|
||||
} else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$themename/config.php")) {
|
||||
// exists
|
||||
// Alternative theme location contains this theme - ok.
|
||||
} else {
|
||||
css_send_css_not_found();
|
||||
}
|
||||
|
||||
// no gzip compression when debugging
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
$css = false;
|
||||
if (is_readable($candidatesheet) and filemtime($candidatesheet) > time() - THEME_DESIGNER_CACHE_LIFETIME) {
|
||||
$css = @unserialize(file_get_contents($candidatesheet));
|
||||
}
|
||||
|
||||
if (!is_array($css)) {
|
||||
// Ok, we need to start normal moodle script, we need to load all libs and $DB.
|
||||
define('ABORT_AFTER_CONFIG_CANCEL', true);
|
||||
|
||||
define('NO_MOODLE_COOKIES', true); // Session not used here.
|
||||
define('NO_UPGRADE_CHECK', true); // Ignore upgrade check.
|
||||
|
||||
require("$CFG->dirroot/lib/setup.php");
|
||||
$theme = theme_config::load($themename);
|
||||
$css = $theme->css_content();
|
||||
}
|
||||
$theme = theme_config::load($themename);
|
||||
$theme->force_svg_use($usesvg);
|
||||
|
||||
if ($type === 'editor') {
|
||||
if (isset($css['editor'])) {
|
||||
css_send_uncached_css($css['editor']);
|
||||
}
|
||||
} else if ($type === 'ie') {
|
||||
// IE is a sloppy browser with weird limits, sorry
|
||||
if ($subtype === 'plugins') {
|
||||
css_send_uncached_css($css['plugins']);
|
||||
$csscontent = $theme->get_css_content_editor();
|
||||
css_send_uncached_css($csscontent);
|
||||
}
|
||||
|
||||
} else if ($subtype === 'parents') {
|
||||
$sendcss = array();
|
||||
if (empty($sheet)) {
|
||||
// If not specific parent has been specified as $sheet then build a
|
||||
// collection of @import statements into this one sheet.
|
||||
// We shouldn't ever actually get here, but none the less we'll deal
|
||||
// with it incase we ever do.
|
||||
// @import statements arn't processed until after concurrent CSS requests
|
||||
// making them slightly evil.
|
||||
foreach (array_keys($css['parents']) as $sheet) {
|
||||
$sendcss[] = "@import url(styles_debug.php?theme=$themename&type=$type&subtype=$subtype&sheet=$sheet);";
|
||||
}
|
||||
} else {
|
||||
// Build up the CSS for that parent so we can serve it as one file.
|
||||
foreach ($css[$subtype][$sheet] as $parent=>$css) {
|
||||
$sendcss[] = $css;
|
||||
}
|
||||
}
|
||||
css_send_uncached_css($sendcss);
|
||||
} else if ($subtype === 'theme') {
|
||||
css_send_uncached_css($css['theme']);
|
||||
}
|
||||
|
||||
} else if ($type === 'plugin') {
|
||||
if (isset($css['plugins'][$subtype])) {
|
||||
css_send_uncached_css($css['plugins'][$subtype]);
|
||||
}
|
||||
|
||||
} else if ($type === 'parent') {
|
||||
if (isset($css['parents'][$subtype][$sheet])) {
|
||||
css_send_uncached_css($css['parents'][$subtype][$sheet]);
|
||||
}
|
||||
|
||||
} else if ($type === 'theme') {
|
||||
if (isset($css['theme'][$sheet])) {
|
||||
css_send_uncached_css($css['theme'][$sheet]);
|
||||
// We need some kind of caching here because otherwise the page navigation becomes
|
||||
// way too slow in theme designer mode. Feel free to create full cache definition later...
|
||||
$key = "$type $subtype $sheet $usesvg";
|
||||
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'core', 'themedesigner', array('theme' => $themename));
|
||||
if ($content = $cache->get($key)) {
|
||||
if ($content['created'] > time() - THEME_DESIGNER_CACHE_LIFETIME) {
|
||||
$csscontent = $content['data'];
|
||||
css_send_uncached_css($csscontent);
|
||||
}
|
||||
}
|
||||
css_send_css_not_found();
|
||||
|
||||
$csscontent = $theme->get_css_content_debug($type, $subtype, $sheet);
|
||||
|
||||
$cache->set($key, array('data' => $csscontent, 'created' => time()));
|
||||
|
||||
css_send_uncached_css($csscontent);
|
||||
|
@ -3,6 +3,8 @@ information provided here is intended especially for theme designer.
|
||||
|
||||
=== 2.7 ===
|
||||
|
||||
* CSS related functions in theme class and csslib.php were refactored, addons that are
|
||||
using this private API need to be updated
|
||||
* Please update your css to use 'tr:nth-of-type(odd/even)' instead of '.ro/.r1' to apply tr specific css for various tables.
|
||||
These classes are deprecated now and will be removed in Moodle 2.9. This has done to better support styling tables that will be altered by JavaScript.
|
||||
Here is an example to update your css:
|
||||
|
Loading…
x
Reference in New Issue
Block a user