themes: MDL-19077 change how the theme is initialised and CSS is served.

This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F

$THEME is now initialised at the same time as $OUTPUT. Old functions like
theme_setup are deprecated in favour of methods on $PAGE. There is a new
theme_config class in outputlib.php that deals with loading the theme config.php file.

CSS used to be served by themes styles.php files calling a function in weblib.php.
Now it works by each theme's styles.php file doing
$themename = basename(dirname(__FILE__));
require_once(dirname(__FILE__) . '/../../theme/styles.php');
which is less code to be copied into each theme. (Old-style styles.php files still
work thanks to some code in deprecatedlib.php.)

Admin UI for choosing a theme cleaned up.

A couple of theme-specific hard-coded hacks like $THEME->cssconstants and
$THEME->CSSEdit have been replaced by a more generic $THEME->customcssoutputfunction
hook. See examples at the end of outputlib.php

Also:
* Fix setting the theme in the URL, which seems to have been broken since 1.9.
* Fix up errors on a few pages caused by the new initialisation order.
* MDL-19097 moodle_page::set_course should not set $COURSE unless it is $PAGE.
* httpsrequired() from moodlelib.php moved to $PAGE->https_required().
* Move has_started() method to the renderer base class.
* Further fixes to display of early errors.
* Remove print_header/footer_old from weblib. I did not mean to commit them before.
This commit is contained in:
tjhunt 2009-07-01 05:54:26 +00:00
parent 0456fc1ac4
commit b70094743a
37 changed files with 1646 additions and 1531 deletions

View file

@ -2357,256 +2357,6 @@ function send_headers($contenttype, $cacheable = true) {
@header('Accept-Ranges: none');
}
/**
* Print a standard header
*
* @param string $title Appears at the top of the window
* @param string $heading Appears at the top of the page
* @param string $navigation Array of $navlinks arrays (keys: name, link, type) for use as breadcrumbs links
* @param string $focus Indicates form element to get cursor focus on load eg inputform.password
* @param string $meta Meta tags to be added to the header
* @param boolean $cache Should this page be cacheable?
* @param string $button HTML code for a button (usually for module editing)
* @param string $menu HTML code for a popup menu
* @param boolean $usexml use XML for this page
* @param string $bodytags This text will be included verbatim in the <body> tag (useful for onload() etc)
* @param bool $return If true, return the visible elements of the header instead of echoing them.
* @return string|void If return=true then string else void
*/
function print_header_old($title='', $heading='', $navigation='', $focus='',
$meta='', $cache=true, $button='&nbsp;', $menu='',
$usexml=false, $bodytags='', $return=false) {
global $USER, $CFG, $THEME, $SESSION, $ME, $SITE, $COURSE, $PAGE;
if (gettype($navigation) == 'string' && strlen($navigation) != 0 && $navigation != 'home') {
debugging("print_header() was sent a string as 3rd ($navigation) parameter. "
. "This is deprecated in favour of an array built by build_navigation(). Please upgrade your code.", DEBUG_DEVELOPER);
}
$PAGE->set_state(moodle_page::STATE_PRINTING_HEADER);
$heading = format_string($heading); // Fix for MDL-8582
if (CLI_SCRIPT) {
$output = $heading."\n";
if ($return) {
return $output;
} else {
echo $output;
return;
}
}
/// Add the required stylesheets
$stylesheetshtml = '';
foreach ($CFG->stylesheets as $stylesheet) {
$stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
}
$meta = $stylesheetshtml.$meta;
/// Add the meta page from the themes if any were requested
$metapage = '';
if (!isset($THEME->standardmetainclude) || $THEME->standardmetainclude) {
ob_start();
include_once($CFG->dirroot.'/theme/standard/meta.php');
$metapage .= ob_get_contents();
ob_end_clean();
}
if ($THEME->parent && (!isset($THEME->parentmetainclude) || $THEME->parentmetainclude)) {
if (file_exists($CFG->dirroot.'/theme/'.$THEME->parent.'/meta.php')) {
ob_start();
include_once($CFG->dirroot.'/theme/'.$THEME->parent.'/meta.php');
$metapage .= ob_get_contents();
ob_end_clean();
}
}
if (!isset($THEME->metainclude) || $THEME->metainclude) {
if (file_exists($CFG->dirroot.'/theme/'.current_theme().'/meta.php')) {
ob_start();
include_once($CFG->dirroot.'/theme/'.current_theme().'/meta.php');
$metapage .= ob_get_contents();
ob_end_clean();
}
}
$meta = $meta."\n".$metapage;
$meta .= $PAGE->requires->get_head_code();
/// Set up some navigation variables
if (is_newnav($navigation)){
$home = false;
} else {
if ($navigation == 'home') {
$home = true;
$navigation = '';
} else {
$home = false;
}
}
/// This is another ugly hack to make navigation elements available to print_footer later
$THEME->title = $title;
$THEME->heading = $heading;
$THEME->navigation = $navigation;
$THEME->button = $button;
$THEME->menu = $menu;
$navmenulist = isset($THEME->navmenulist) ? $THEME->navmenulist : '';
if ($button == '') {
$button = '&nbsp;';
}
if (!empty($CFG->maintenance_enabled)) {
$button = '<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=maintenancemode">'.get_string('maintenancemode', 'admin').'</a> '.$button;
if(!empty($title)) {
$title .= ' - ';
}
$title .= get_string('maintenancemode', 'admin');
}
if (!$menu and $navigation) {
if (empty($CFG->loginhttps)) {
$wwwroot = $CFG->wwwroot;
} else {
$wwwroot = str_replace('http:','https:',$CFG->wwwroot);
}
$menu = user_login_string($COURSE);
}
if (isset($SESSION->justloggedin)) {
unset($SESSION->justloggedin);
if (!empty($CFG->displayloginfailures)) {
if (!empty($USER->username) and $USER->username != 'guest') {
if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) {
$menu .= '&nbsp;<font size="1">';
if (empty($count->accounts)) {
$menu .= get_string('failedloginattempts', '', $count);
} else {
$menu .= get_string('failedloginattemptsall', '', $count);
}
if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) {
$menu .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php'.
'?chooselog=1&amp;id=1&amp;modid=site_errors">'.get_string('logs').'</a>)';
}
$menu .= '</font>';
}
}
}
}
$meta = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' .
"\n" . $meta . "\n";
if (!$usexml) {
@header('Content-Type: text/html; charset=utf-8');
}
@header('Content-Script-Type: text/javascript');
@header('Content-Style-Type: text/css');
//Accessibility: added the 'lang' attribute to $direction, used in theme <html> tag.
$direction = get_html_lang($dir=true);
if ($cache) { // Allow caching on "back" (but not on normal clicks)
@header('Cache-Control: private, pre-check=0, post-check=0, max-age=0');
@header('Pragma: no-cache');
@header('Expires: ');
} else { // Do everything we can to always prevent clients and proxies caching
@header('Cache-Control: no-store, no-cache, must-revalidate');
@header('Cache-Control: post-check=0, pre-check=0', false);
@header('Pragma: no-cache');
@header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
@header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
$meta .= "\n<meta http-equiv=\"pragma\" content=\"no-cache\" />";
$meta .= "\n<meta http-equiv=\"expires\" content=\"0\" />";
}
@header('Accept-Ranges: none');
$currentlanguage = current_language();
if (empty($usexml)) {
$direction = ' xmlns="http://www.w3.org/1999/xhtml"'. $direction; // See debug_header
} else {
$mathplayer = preg_match("/MathPlayer/i", $_SERVER['HTTP_USER_AGENT']);
if(!$mathplayer) {
header('Content-Type: application/xhtml+xml');
}
echo '<?xml version="1.0" ?>'."\n";
if (!empty($CFG->xml_stylesheets)) {
$stylesheets = explode(';', $CFG->xml_stylesheets);
foreach ($stylesheets as $stylesheet) {
echo '<?xml-stylesheet type="text/xsl" href="'. $CFG->wwwroot .'/'. $stylesheet .'" ?>' . "\n";
}
}
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1';
if (!empty($CFG->xml_doctype_extra)) {
echo ' plus '. $CFG->xml_doctype_extra;
}
echo '//' . strtoupper($currentlanguage) . '" "'. $CFG->xml_dtd .'">'."\n";
$direction = " xmlns=\"http://www.w3.org/1999/xhtml\"
xmlns:math=\"http://www.w3.org/1998/Math/MathML\"
xmlns:xlink=\"http://www.w3.org/1999/xlink\"
$direction";
if($mathplayer) {
$meta .= '<object id="mathplayer" classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">' . "\n";
$meta .= '<!--comment required to prevent this becoming an empty tag-->'."\n";
$meta .= '</object>'."\n";
$meta .= '<?import namespace="math" implementation="#mathplayer" ?>' . "\n";
}
}
// Clean up the title
$title = format_string($title); // fix for MDL-8582
$title = str_replace('"', '&quot;', $title);
// Create class and id for this page
$pageid = $PAGE->pagetype;
$pageclass = $PAGE->bodyclasses;
$bodytags .= ' class="'.$pageclass.'" id="'.$pageid.'"';
ob_start();
include($CFG->header);
$output = ob_get_contents();
ob_end_clean();
// container debugging info
$THEME->open_header_containers = open_containers();
// Skip to main content, see skip_main_destination().
if ($pageid=='course-view' or $pageid=='site-index' or $pageid=='course-index') {
$skiplink = '<a class="skip" href="#maincontent">'.get_string('tocontent', 'access').'</a>';
if (! preg_match('/(.*<div[^>]+id="page"[^>]*>)(.*)/s', $output, $matches)) {
preg_match('/(.*<body.*?>)(.*)/s', $output, $matches);
}
$output = $matches[1]."\n". $skiplink .$matches[2];
}
$output = force_strict_header($output);
if (!empty($CFG->messaging)) {
$output .= message_popup_window();
}
// Add in any extra JavaScript libraries that occurred during the header
$output .= $PAGE->requires->get_top_of_body_code();
$PAGE->set_state(moodle_page::STATE_IN_BODY);
if ($return) {
return $output;
} else {
echo $output;
}
}
/**
* This version of print_header is simpler because the course name does not have to be
* provided explicitly in the strings. It can be used on the site page as in courses
@ -2656,569 +2406,6 @@ function print_header_simple($title='', $heading='', $navigation='', $focus='',
}
}
/**
* Can provide a course object to make the footer contain a link to
* to the course home page, otherwise the link will go to the site home
*
* @global object
* @global object
* @global object
* @global object Apparently not used in this function
* @global string
* @global object
* @param mixed $course course object, used for course link button or
* 'none' means no user link, only docs link
* 'empty' means nothing printed in footer
* 'home' special frontpage footer
* @param object $usercourse course used in user link
* @param boolean $return output as string
* @return mixed string or void
*/
function print_footer_old($course=NULL, $usercourse=NULL, $return=false) {
global $USER, $CFG, $THEME, $COURSE, $SITE, $PAGE;
if (defined('ADMIN_EXT_HEADER_PRINTED') and !defined('ADMIN_EXT_FOOTER_PRINTED')) {
admin_externalpage_print_footer();
return;
}
$PAGE->set_state(moodle_page::STATE_PRINTING_FOOTER);
/// Course links or special footer
if ($course) {
if ($course === 'empty') {
// special hack - sometimes we do not want even the docs link in footer
$output = '';
if (!empty($THEME->open_header_containers)) {
for ($i=0; $i<$THEME->open_header_containers; $i++) {
$output .= print_container_end_all(); // containers opened from header
}
} else {
//1.8 theme compatibility
$output .= "\n</div>"; // content div
}
$output .= "\n</div>\n" . $PAGE->requires->get_end_code() . "</body>\n</html>"; // close page div started in header
if ($return) {
return $output;
} else {
echo $output;
return;
}
} else if ($course === 'none') { // Don't print any links etc
$homelink = '';
$loggedinas = '';
$home = false;
} else if ($course === 'home') { // special case for site home page - please do not remove
$course = $SITE;
$homelink = '<div class="sitelink">'.
'<a title="Moodle '. $CFG->release .'" href="http://moodle.org/">'.
'<img style="width:100px;height:30px" src="'.$CFG->wwwroot.'/pix/moodlelogo.gif" alt="moodlelogo" /></a></div>';
$home = true;
} else if ($course === 'upgrade') {
$home = false;
$loggedinas = '';
$homelink = '<div class="sitelink">'.
'<a title="Moodle '. $CFG->target_release .'" href="http://docs.moodle.org/en/Administrator_documentation" onclick="this.target=\'_blank\'">'.
'<img style="width:100px;height:30px" src="'.$CFG->wwwroot.'/pix/moodlelogo.gif" alt="moodlelogo" /></a></div>';
} else {
$homelink = '<div class="homelink"><a '.$CFG->frametarget.' href="'.$CFG->wwwroot.
'/course/view.php?id='.$course->id.'">'.format_string($course->shortname).'</a></div>';
$home = false;
}
} else {
$course = $SITE; // Set course as site course by default
$homelink = '<div class="homelink"><a '.$CFG->frametarget.' href="'.$CFG->wwwroot.'/">'.get_string('home').'</a></div>';
$home = false;
}
/// Set up some other navigation links (passed from print_header by ugly hack)
$menu = isset($THEME->menu) ? str_replace('navmenu', 'navmenufooter', $THEME->menu) : '';
$title = isset($THEME->title) ? $THEME->title : '';
$button = isset($THEME->button) ? $THEME->button : '';
$heading = isset($THEME->heading) ? $THEME->heading : '';
$navigation = isset($THEME->navigation) ? $THEME->navigation : '';
$navmenulist = isset($THEME->navmenulist) ? $THEME->navmenulist : '';
/// Set the user link if necessary
if (!$usercourse and is_object($course)) {
$usercourse = $course;
}
if (!isset($loggedinas)) {
$loggedinas = user_login_string($usercourse, $USER);
}
if ($loggedinas == $menu) {
$menu = '';
}
/// there should be exactly the same number of open containers as after the header
if ($THEME->open_header_containers != open_containers()) {
debugging('Unexpected number of open containers: '.open_containers().', expecting '.$THEME->open_header_containers, DEBUG_DEVELOPER);
}
/// Provide some performance info if required
$performanceinfo = '';
if (defined('MDL_PERF') || (!empty($CFG->perfdebug) and $CFG->perfdebug > 7)) {
$perf = get_performance_info();
if (defined('MDL_PERFTOLOG') && !function_exists('register_shutdown_function')) {
error_log("PERF: " . $perf['txt']);
}
if (defined('MDL_PERFTOFOOT') || debugging() || $CFG->perfdebug > 7) {
$performanceinfo = $perf['html'];
}
}
/// Include the actual footer file
ob_start();
include($CFG->footer);
$output = ob_get_contents();
ob_end_clean();
// Put the end of page <script> tags just inside </body> to maintain validity.
$output = str_replace('</body>', $PAGE->requires->get_end_code() . '</body>', $output);
$PAGE->set_state(moodle_page::STATE_DONE);
if ($return) {
return $output;
} else {
echo $output;
}
}
/**
* Returns the name of the current theme
*
* @global object
* @global object
* @global object
* @global object
* @global string
* @return string
*/
function current_theme() {
global $CFG, $USER, $SESSION, $COURSE, $SCRIPT;
if (empty($CFG->themeorder)) {
$themeorder = array('page', 'course', 'category', 'session', 'user', 'site');
} else {
$themeorder = $CFG->themeorder;
}
if (isloggedin() and isset($CFG->mnet_localhost_id) and $USER->mnethostid != $CFG->mnet_localhost_id) {
require_once($CFG->dirroot.'/mnet/peer.php');
$mnet_peer = new mnet_peer();
$mnet_peer->set_id($USER->mnethostid);
}
$theme = '';
foreach ($themeorder as $themetype) {
if (!empty($theme)) continue;
switch ($themetype) {
case 'page': // Page theme is for special page-only themes set by code
if (!empty($CFG->pagetheme)) {
$theme = $CFG->pagetheme;
}
break;
case 'course':
if (!empty($CFG->allowcoursethemes) and !empty($COURSE->theme)) {
$theme = $COURSE->theme;
}
break;
case 'category':
if (!empty($CFG->allowcategorythemes)) {
/// Nasty hack to check if we're in a category page
if ($SCRIPT == '/course/category.php') {
global $id;
if (!empty($id)) {
$theme = current_category_theme($id);
}
/// Otherwise check if we're in a course that has a category theme set
} else if (!empty($COURSE->category)) {
$theme = current_category_theme($COURSE->category);
}
}
break;
case 'session':
if (!empty($SESSION->theme)) {
$theme = $SESSION->theme;
}
break;
case 'user':
if (!empty($CFG->allowuserthemes) and !empty($USER->theme)) {
if (isloggedin() and $USER->mnethostid != $CFG->mnet_localhost_id && $mnet_peer->force_theme == 1 && $mnet_peer->theme != '') {
$theme = $mnet_peer->theme;
} else {
$theme = $USER->theme;
}
}
break;
case 'site':
if (isloggedin() and isset($CFG->mnet_localhost_id) and $USER->mnethostid != $CFG->mnet_localhost_id && $mnet_peer->force_theme == 1 && $mnet_peer->theme != '') {
$theme = $mnet_peer->theme;
} else {
$theme = $CFG->theme;
}
break;
default:
/// do nothing
}
}
/// A final check in case 'site' was not included in $CFG->themeorder
if (empty($theme)) {
$theme = $CFG->theme;
}
return $theme;
}
/**
* Retrieves the category theme if one exists, otherwise checks the parent categories.
* Recursive function.
*
* @global object
* @global object
* @param integer $categoryid id of the category to check
* @return string theme name
*/
function current_category_theme($categoryid=0) {
global $COURSE, $DB;
/// Use the COURSE global if the categoryid not set
if (empty($categoryid)) {
if (!empty($COURSE->category)) {
$categoryid = $COURSE->category;
} else {
return false;
}
}
/// Retrieve the current category
if ($category = $DB->get_record('course_categories', array('id'=>$categoryid))) {
/// Return the category theme if it exists
if (!empty($category->theme)) {
return $category->theme;
/// Otherwise try the parent category if one exists
} else if (!empty($category->parent)) {
return current_category_theme($category->parent);
}
/// Return false if we can't find the category record
} else {
return false;
}
}
/**
* This function is called by stylesheets to set up the header
* approriately as well as the current path
*
* @global object
* @global object
* @uses PARAM_SAFEDIR
* @param int $lastmodified Always gets set to now
* @param int $lifetime The max-age header setting (seconds) defaults to 300
* @param string $themename The name of the theme to use (optional) defaults to current theme
* @param string $forceconfig Force a particular theme config (optional)
* @param string $lang Load styles for the specified language (optional)
*/
function style_sheet_setup($lastmodified=0, $lifetime=300, $themename='', $forceconfig='', $lang='') {
global $CFG, $THEME;
// Fix for IE6 caching - we don't want the filemtime('styles.php'), instead use now.
$lastmodified = time();
header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastmodified) . ' GMT');
header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $lifetime) . ' GMT');
header('Cache-Control: max-age='. $lifetime);
header('Pragma: ');
header('Content-type: text/css'); // Correct MIME type
$DEFAULT_SHEET_LIST = array('styles_layout', 'styles_fonts', 'styles_color');
if (empty($themename)) {
$themename = current_theme(); // So we have something. Normally not needed.
} else {
$themename = clean_param($themename, PARAM_SAFEDIR);
}
theme_setup($themename);
if (!empty($forceconfig)) { // Page wants to use the config from this theme instead
unset($THEME);
include($CFG->themedir.'/'.$forceconfig.'/'.'config.php');
}
/// If this is the standard theme calling us, then find out what sheets we need
if ($themename == 'standard') {
if (!isset($THEME->standardsheets) or $THEME->standardsheets === true) { // Use all the sheets we have
$THEME->sheets = $DEFAULT_SHEET_LIST;
} else if (empty($THEME->standardsheets)) { // We can stop right now!
echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
exit;
} else { // Use the provided subset only
$THEME->sheets = $THEME->standardsheets;
}
/// If we are a parent theme, then check for parent definitions
} else if (!empty($THEME->parent) && $themename == $THEME->parent) {
if (!isset($THEME->parentsheets) or $THEME->parentsheets === true) { // Use all the sheets we have
$THEME->sheets = $DEFAULT_SHEET_LIST;
} else if (empty($THEME->parentsheets)) { // We can stop right now!
echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
exit;
} else { // Use the provided subset only
$THEME->sheets = $THEME->parentsheets;
}
}
/// Work out the last modified date for this theme
foreach ($THEME->sheets as $sheet) {
if (file_exists($CFG->themedir.'/'.$themename.'/'.$sheet.'.css')) {
$sheetmodified = filemtime($CFG->themedir.'/'.$themename.'/'.$sheet.'.css');
if ($sheetmodified > $lastmodified) {
$lastmodified = $sheetmodified;
}
}
}
/// Get a list of all the files we want to include
$files = array();
foreach ($THEME->sheets as $sheet) {
$files[] = array($CFG->themedir, $themename.'/'.$sheet.'.css');
}
if ($themename == 'standard') { // Add any standard styles included in any modules
if (!empty($THEME->modsheets)) { // Search for styles.php within activity modules
$mods = get_plugin_list('mod');
foreach ($mods as $mod => $moddir) {
if (file_exists($moddir.'/styles.php')) {
$files[] = array($moddir, 'styles.php');
}
}
}
if (!empty($THEME->blocksheets)) { // Search for styles.php within block modules
$mods = get_plugin_list('blocks');
foreach ($mods as $mod => $moddir) {
if (file_exists($moddir.'/styles.php')) {
$files[] = array($moddir, 'styles.php');
}
}
}
if (!isset($THEME->courseformatsheets) || $THEME->courseformatsheets) { // Search for styles.php in course formats
$mods = get_plugin_list('format');
foreach ($mods as $mod => $moddir) {
if (file_exists($moddir.'/styles.php')) {
$files[] = array($moddir, 'styles.php');
}
}
}
if (!isset($THEME->gradereportsheets) || $THEME->gradereportsheets) { // Search for styles.php in grade reports
$reports = get_plugin_list('gradereport');
foreach ($reports as $report => $reportdir) {
if (file_exists($reportdir.'/styles.php')) {
$files[] = array($reportdir, 'styles.php');
}
}
}
if (!empty($THEME->langsheets)) { // Search for styles.php within the current language
if (file_exists($CFG->dirroot.'/lang/'.$lang.'/styles.php')) {
$files[] = array($CFG->dirroot, 'lang/'.$lang.'/styles.php');
}
}
}
if ($files) {
/// Produce a list of all the files first
echo '/**************************************'."\n";
echo ' * THEME NAME: '.$themename."\n *\n";
echo ' * Files included in this sheet:'."\n *\n";
foreach ($files as $file) {
echo ' * '.$file[1]."\n";
}
echo ' **************************************/'."\n\n";
/// check if csscobstants is set
if (!empty($THEME->cssconstants)) {
require_once("$CFG->libdir/cssconstants.php");
/// Actually collect all the files in order.
$css = '';
foreach ($files as $file) {
$css .= '/***** '.$file[1].' start *****/'."\n\n";
$css .= file_get_contents($file[0].'/'.$file[1]);
$ccs .= '/***** '.$file[1].' end *****/'."\n\n";
}
/// replace css_constants with their values
echo replace_cssconstants($css);
} else {
/// Actually output all the files in order.
if (empty($CFG->CSSEdit) && empty($THEME->CSSEdit)) {
foreach ($files as $file) {
echo '/***** '.$file[1].' start *****/'."\n\n";
@include_once($file[0].'/'.$file[1]);
echo '/***** '.$file[1].' end *****/'."\n\n";
}
} else {
foreach ($files as $file) {
echo '/* @group '.$file[1].' */'."\n\n";
if (strstr($file[1], '.css') !== FALSE) {
echo '@import url("'.$CFG->themewww.'/'.$file[1].'");'."\n\n";
} else {
@include_once($file[0].'/'.$file[1]);
}
echo '/* @end */'."\n\n";
}
}
}
}
return $CFG->themewww.'/'.$themename; // Only to help old themes (1.4 and earlier)
}
/**
* Sets up the global variables related to theme
*
* @global object
* @global object
* @global object Apparently not used here
* @global object Apparently not used here
* @global object
* @global object
* @param string $theme The theme to use defaults to current theme
* @param array $params An array of parameters to use
*/
function theme_setup($theme = '', $params=NULL) {
/// Sets up global variables related to themes
global $CFG, $THEME, $SESSION, $USER, $HTTPSPAGEREQUIRED, $PAGE;
/// Do not mess with THEME if header already printed - this would break all the extra stuff in global $THEME from print_header()!!
if ($PAGE->headerprinted) {
return;
}
if (empty($theme)) {
$theme = current_theme();
}
/// If the theme doesn't exist for some reason then revert to standardwhite
if (!file_exists($CFG->themedir .'/'. $theme .'/config.php')) {
$CFG->theme = $theme = 'standardwhite';
}
/// Load up the theme config
$THEME = NULL; // Just to be sure
include($CFG->themedir .'/'. $theme .'/config.php'); // Main config for current theme
$THEME->name = $theme;
$THEME->dir = $CFG->themedir .'/'. $theme;
/// Put together the parameters
if (!$params) {
$params = array();
}
if ($theme != $CFG->theme) {
$params[] = 'forceconfig='.$theme;
}
/// Force language too if required
if (!empty($THEME->langsheets)) {
$params[] = 'lang='.current_language();
}
/// Convert params to string
if ($params) {
$paramstring = '?'.implode('&', $params);
} else {
$paramstring = '';
}
/// Set up image paths
if(isset($CFG->smartpix) && $CFG->smartpix==1) {
if($CFG->slasharguments) { // Use this method if possible for better caching
$extra='';
} else {
$extra='?file=';
}
$CFG->pixpath = $CFG->wwwroot. '/pix/smartpix.php'.$extra.'/'.$theme;
$CFG->modpixpath = $CFG->wwwroot .'/pix/smartpix.php'.$extra.'/'.$theme.'/mod';
} else if (empty($THEME->custompix)) { // Could be set in the above file
$CFG->pixpath = $CFG->wwwroot .'/pix';
$CFG->modpixpath = $CFG->wwwroot .'/mod';
} else {
$CFG->pixpath = $CFG->themewww .'/'. $theme .'/pix';
$CFG->modpixpath = $CFG->themewww .'/'. $theme .'/pix/mod';
}
/// Define stylesheet loading order
$CFG->stylesheets = array();
if ($theme != 'standard') { /// The standard sheet is always loaded first
$CFG->stylesheets[] = $CFG->themewww.'/standard/styles.php'.$paramstring;
}
if (!empty($THEME->parent)) { /// Parent stylesheets are loaded next
$CFG->stylesheets[] = $CFG->themewww.'/'.$THEME->parent.'/styles.php'.$paramstring;
}
$CFG->stylesheets[] = $CFG->themewww.'/'.$theme.'/styles.php'.$paramstring;
/// We have to change some URLs in styles if we are in a $HTTPSPAGEREQUIRED page
if (!empty($HTTPSPAGEREQUIRED)) {
$CFG->themewww = str_replace('http:', 'https:', $CFG->themewww);
$CFG->pixpath = str_replace('http:', 'https:', $CFG->pixpath);
$CFG->modpixpath = str_replace('http:', 'https:', $CFG->modpixpath);
foreach ($CFG->stylesheets as $key => $stylesheet) {
$CFG->stylesheets[$key] = str_replace('http:', 'https:', $stylesheet);
}
}
// RTL support - only for RTL languages, add RTL CSS
if (get_string('thisdirection') == 'rtl') {
$CFG->stylesheets[] = $CFG->themewww.'/standard/rtl.css'.$paramstring;
$CFG->stylesheets[] = $CFG->themewww.'/'.$theme.'/rtl.css'.$paramstring;
}
// Support legacy themes, by setting sensible defaults for some of the new
// properties that were introduced in Moodle 2.0.
if (empty($THEME->rendererfactory)) {
if (!empty($THEME->customcorners)) {
// $THEME->customcorners is deprecated but we provide support for it via the
// custom_corners_renderer_factory class in lib/deprecatedlib.php
debugging('$THEME->customcorners is deprecated. Please use the new $THEME->rendererfactory to control HTML generation.', DEBUG_DEVELOPER);
$THEME->rendererfactory = 'custom_corners_renderer_factory';
} else {
$THEME->rendererfactory = 'standard_renderer_factory';
}
}
if (empty($THEME->blockregions)) {
$THEME->blockregions = array('side-pre', 'side-post');
}
if (empty($THEME->defaultblockregion)) {
$THEME->defaultblockregion = 'side-post';
}
}
/**
* Returns text to be displayed to the user which reflects their login status
*
@ -5729,7 +4916,7 @@ function redirect($url, $message='', $delay=-1) {
$encodedurl = preg_replace('/^.*href="([^"]*)".*$/', "\\1", clean_text('<a href="'.$encodedurl.'" />'));
$message .= '<a href="'. $encodedurl .'">'. get_string('continue') .'</a>';
$CFG->docroot = false; // to prevent the link to moodle docs from being displayed on redirect page.
echo $OUTPUT->redirect($encodedurl, $message, $delay);
die();
@ -6349,18 +5536,15 @@ function print_arrow($direction='up', $strsort=null, $return=false) {
}
/**
* Returns boolean true if the current language is right-to-left (Hebrew, Arabic etc)
*
* @staticvar bool $result
* @return bool
* @return boolean true if the current language is right-to-left (Hebrew, Arabic etc)
*/
function right_to_left() {
static $result;
if (isset($result)) {
return $result;
if (!isset($result)) {
$result = get_string('thisdirection') == 'rtl';
}
return $result = (get_string('thisdirection') == 'rtl');
return $result;
}