themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
<?php
|
|
|
|
// This file is part of Moodle - http://moodle.org/
|
|
|
|
//
|
|
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
|
|
|
* Functions for generating the HTML that Moodle should output.
|
|
|
|
*
|
|
|
|
* Please see http://docs.moodle.org/en/Developement:How_Moodle_outputs_HTML
|
|
|
|
* for an overview.
|
|
|
|
*
|
2012-01-05 13:27:54 +13:00
|
|
|
* @copyright 2009 Tim Hunt
|
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
2012-02-14 18:24:09 +13:00
|
|
|
* @package core
|
2012-01-11 10:40:55 +13:00
|
|
|
* @category output
|
2009-12-16 18:00:58 +00:00
|
|
|
*/
|
|
|
|
|
2010-07-25 13:35:05 +00:00
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
|
2009-08-10 06:22:04 +00:00
|
|
|
require_once($CFG->libdir.'/outputcomponents.php');
|
|
|
|
require_once($CFG->libdir.'/outputactions.php');
|
|
|
|
require_once($CFG->libdir.'/outputfactories.php');
|
|
|
|
require_once($CFG->libdir.'/outputrenderers.php');
|
2010-02-07 08:45:21 +00:00
|
|
|
require_once($CFG->libdir.'/outputrequirementslib.php');
|
2009-08-10 06:22:04 +00:00
|
|
|
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Invalidate all server and client side caches.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2012-05-23 11:11:13 +02:00
|
|
|
* This method deletes the physical directory that is used to cache the theme
|
2012-01-05 13:27:54 +13:00
|
|
|
* files used for serving.
|
2012-05-23 11:11:13 +02:00
|
|
|
* Because it deletes the main theme cache directory all themes are reset by
|
2012-01-05 13:27:54 +13:00
|
|
|
* this function.
|
2009-12-16 18:00:58 +00:00
|
|
|
*/
|
|
|
|
function theme_reset_all_caches() {
|
2013-04-10 10:57:18 +02:00
|
|
|
global $CFG, $PAGE;
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2012-05-23 11:11:13 +02:00
|
|
|
$next = time();
|
|
|
|
if (isset($CFG->themerev) and $next <= $CFG->themerev and $CFG->themerev - $next < 60*60) {
|
|
|
|
// This resolves problems when reset is requested repeatedly within 1s,
|
|
|
|
// the < 1h condition prevents accidental switching to future dates
|
|
|
|
// because we might not recover from it.
|
|
|
|
$next = $CFG->themerev+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_config('themerev', $next); // time is unique even when you reset/switch database
|
2013-04-10 10:57:18 +02:00
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
if (!empty($CFG->themedesignermode)) {
|
|
|
|
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'core', 'themedesigner');
|
|
|
|
$cache->purge();
|
|
|
|
}
|
|
|
|
|
2013-04-10 10:57:18 +02:00
|
|
|
if ($PAGE) {
|
|
|
|
$PAGE->reload_theme();
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable or disable theme designer mode.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param bool $state
|
|
|
|
*/
|
|
|
|
function theme_set_designer_mod($state) {
|
|
|
|
set_config('themedesignermode', (int)!empty($state));
|
2014-02-27 14:35:03 +08:00
|
|
|
// Reset caches after switching mode so that any designer mode caches get purged too.
|
|
|
|
theme_reset_all_caches();
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns current theme revision number.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return int
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
function theme_get_revision() {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if (empty($CFG->themedesignermode)) {
|
|
|
|
if (empty($CFG->themerev)) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return $CFG->themerev;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-15 07:29:02 +00:00
|
|
|
/**
|
|
|
|
* Checks if the given device has a theme defined in config.php.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
function theme_is_device_locked($device) {
|
|
|
|
global $CFG;
|
|
|
|
$themeconfigname = core_useragent::get_device_type_cfg_var_name($device);
|
|
|
|
return isset($CFG->config_php_settings[$themeconfigname]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the theme named defined in config.php for the given device.
|
|
|
|
*
|
|
|
|
* @return string or null
|
|
|
|
*/
|
|
|
|
function theme_get_locked_theme_for_device($device) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if (!theme_is_device_locked($device)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$themeconfigname = core_useragent::get_device_type_cfg_var_name($device);
|
|
|
|
return $CFG->config_php_settings[$themeconfigname];
|
|
|
|
}
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
|
|
|
/**
|
2009-07-07 05:05:06 +00:00
|
|
|
* This class represents the configuration variables of a Moodle theme.
|
|
|
|
*
|
|
|
|
* All the variables with access: public below (with a few exceptions that are marked)
|
2012-01-12 12:55:50 +13:00
|
|
|
* are the properties you can set in your themes config.php file.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
|
|
|
* There are also some methods and protected variables that are part of the inner
|
2012-01-12 12:55:50 +13:00
|
|
|
* workings of Moodle's themes system. If you are just editing a themes config.php
|
2009-07-23 02:33:58 +00:00
|
|
|
* file, you can just ignore those, and the following information for developers.
|
2009-07-02 08:49:25 +00:00
|
|
|
*
|
|
|
|
* Normally, to create an instance of this class, you should use the
|
|
|
|
* {@link theme_config::load()} factory method to load a themes config.php file.
|
2009-07-23 02:33:58 +00:00
|
|
|
* However, normally you don't need to bother, because moodle_page (that is, $PAGE)
|
2009-07-07 05:05:06 +00:00
|
|
|
* will create one for you, accessible as $PAGE->theme.
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*
|
|
|
|
* @copyright 2009 Tim Hunt
|
2012-01-05 13:27:54 +13:00
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
|
* @since Moodle 2.0
|
2012-02-14 18:24:09 +13:00
|
|
|
* @package core
|
2012-01-11 10:40:55 +13:00
|
|
|
* @category output
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2009-07-02 08:49:25 +00:00
|
|
|
class theme_config {
|
2012-01-05 13:27:54 +13:00
|
|
|
|
2010-01-12 17:21:52 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string Default theme, used when requested theme not found.
|
2010-01-12 17:21:52 +00:00
|
|
|
*/
|
2014-01-30 11:42:36 +08:00
|
|
|
const DEFAULT_THEME = 'clean';
|
2010-01-12 17:21:52 +00:00
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array You can base your theme on other themes by linking to the other theme as
|
2009-12-16 18:00:58 +00:00
|
|
|
* parents. This lets you use the CSS and layouts from the other themes
|
2012-02-14 18:24:09 +13:00
|
|
|
* (see {@link theme_config::$layouts}).
|
2009-07-07 05:05:06 +00:00
|
|
|
* That makes it easy to create a new theme that is similar to another one
|
2012-01-12 12:55:50 +13:00
|
|
|
* but with a few changes. In this themes CSS you only need to override
|
2009-07-07 05:05:06 +00:00
|
|
|
* those rules you want to change.
|
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $parents;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array The names of all the stylesheets from this theme that you would
|
2009-12-16 18:00:58 +00:00
|
|
|
* like included, in order. Give the names of the files without .css.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $sheets = array();
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array The names of all the stylesheets from parents that should be excluded.
|
2009-12-16 18:00:58 +00:00
|
|
|
* true value may be used to specify all parents or all themes from one parent.
|
|
|
|
* If no value specified value from parent theme used.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $parents_exclude_sheets = null;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array List of plugin sheets to be excluded.
|
2009-12-16 18:00:58 +00:00
|
|
|
* If no value specified value from parent theme used.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $plugins_exclude_sheets = null;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array List of style sheets that are included in the text editor bodies.
|
2009-12-16 18:00:58 +00:00
|
|
|
* Sheets from parent themes are used automatically and can not be excluded.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $editor_sheets = array();
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-12-20 21:50:46 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array The names of all the javascript files this theme that you would
|
2010-01-05 23:22:16 +00:00
|
|
|
* like included from head, in order. Give the names of the files without .js.
|
2009-12-20 21:50:46 +00:00
|
|
|
*/
|
|
|
|
public $javascripts = array();
|
|
|
|
|
2010-01-05 23:22:16 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array The names of all the javascript files this theme that you would
|
2010-01-05 23:22:16 +00:00
|
|
|
* like included from footer, in order. Give the names of the files without .js.
|
|
|
|
*/
|
|
|
|
public $javascripts_footer = array();
|
2010-04-15 14:43:25 +00:00
|
|
|
|
2009-12-20 21:50:46 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array The names of all the javascript files from parents that should
|
|
|
|
* be excluded. true value may be used to specify all parents or all themes
|
|
|
|
* from one parent.
|
2009-12-20 21:50:46 +00:00
|
|
|
* If no value specified value from parent theme used.
|
|
|
|
*/
|
|
|
|
public $parents_exclude_javascripts = null;
|
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array Which file to use for each page layout.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* This is an array of arrays. The keys of the outer array are the different layouts.
|
|
|
|
* Pages in Moodle are using several different layouts like 'normal', 'course', 'home',
|
|
|
|
* 'popup', 'form', .... The most reliable way to get a complete list is to look at
|
|
|
|
* {@link http://cvs.moodle.org/moodle/theme/base/config.php?view=markup the base theme config.php file}.
|
2009-07-09 07:35:03 +00:00
|
|
|
* That file also has a good example of how to set this setting.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* For each layout, the value in the outer array is an array that describes
|
2009-07-09 07:35:03 +00:00
|
|
|
* how you want that type of page to look. For example
|
|
|
|
* <pre>
|
|
|
|
* $THEME->layouts = array(
|
2010-01-11 10:04:39 +00:00
|
|
|
* // Most pages - if we encounter an unknown or a missing page type, this one is used.
|
2009-12-27 12:02:04 +00:00
|
|
|
* 'standard' => array(
|
2009-12-16 18:00:58 +00:00
|
|
|
* 'theme' = 'mytheme',
|
|
|
|
* 'file' => 'normal.php',
|
2009-07-09 07:35:03 +00:00
|
|
|
* 'regions' => array('side-pre', 'side-post'),
|
|
|
|
* 'defaultregion' => 'side-post'
|
|
|
|
* ),
|
|
|
|
* // The site home page.
|
|
|
|
* 'home' => array(
|
2009-12-16 18:00:58 +00:00
|
|
|
* 'theme' = 'mytheme',
|
|
|
|
* 'file' => 'home.php',
|
2009-07-09 07:35:03 +00:00
|
|
|
* 'regions' => array('side-pre', 'side-post'),
|
|
|
|
* 'defaultregion' => 'side-post'
|
|
|
|
* ),
|
|
|
|
* // ...
|
|
|
|
* );
|
|
|
|
* </pre>
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* 'theme' name of the theme where is the layout located
|
|
|
|
* 'file' is the layout file to use for this type of page.
|
|
|
|
* layout files are stored in layout subfolder
|
2009-07-09 07:35:03 +00:00
|
|
|
* 'regions' This lists the regions on the page where blocks may appear. For
|
|
|
|
* each region you list here, your layout file must include a call to
|
|
|
|
* <pre>
|
|
|
|
* echo $OUTPUT->blocks_for_region($regionname);
|
|
|
|
* </pre>
|
|
|
|
* or equivalent so that the blocks are actually visible.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
2009-07-09 07:35:03 +00:00
|
|
|
* 'defaultregion' If the list of regions is non-empty, then you must pick
|
|
|
|
* one of the one of them as 'default'. This has two meanings. First, this is
|
|
|
|
* where new blocks are added. Second, if there are any blocks associated with
|
2009-07-23 02:33:58 +00:00
|
|
|
* the page, but in non-existent regions, they appear here. (Imaging, for example,
|
2009-07-09 07:35:03 +00:00
|
|
|
* that someone added blocks using a different theme that used different region
|
|
|
|
* names, and then switched to this theme.)
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-07-09 07:35:03 +00:00
|
|
|
public $layouts = array();
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string Name of the renderer factory class to use. Must implement the
|
|
|
|
* {@link renderer_factory} interface.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
|
|
|
* This is an advanced feature. Moodle output is generated by 'renderers',
|
|
|
|
* you can customise the HTML that is output by writing custom renderers,
|
|
|
|
* and then you need to specify 'renderer factory' so that Moodle can find
|
|
|
|
* your renderers.
|
|
|
|
*
|
|
|
|
* There are some renderer factories supplied with Moodle. Please follow these
|
|
|
|
* links to see what they do.
|
|
|
|
* <ul>
|
|
|
|
* <li>{@link standard_renderer_factory} - the default.</li>
|
|
|
|
* <li>{@link theme_overridden_renderer_factory} - use this if you want to write
|
2009-12-16 18:00:58 +00:00
|
|
|
* your own custom renderers in a lib.php file in this theme (or the parent theme).</li>
|
2009-07-07 05:05:06 +00:00
|
|
|
* </ul>
|
|
|
|
*/
|
2009-07-02 08:49:25 +00:00
|
|
|
public $rendererfactory = 'standard_renderer_factory';
|
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string Function to do custom CSS post-processing.
|
2009-07-07 05:05:06 +00:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* This is an advanced feature. If you want to do custom post-processing on the
|
|
|
|
* CSS before it is output (for example, to replace certain variable names
|
|
|
|
* with particular values) you can give the name of a function here.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $csspostprocess = null;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string Accessibility: Right arrow-like character is
|
2009-12-16 18:00:58 +00:00
|
|
|
* used in the breadcrumb trail, course navigation menu
|
|
|
|
* (previous/next activity), calendar, and search forum block.
|
|
|
|
* If the theme does not set characters, appropriate defaults
|
|
|
|
* are set automatically. Please DO NOT
|
|
|
|
* use < > » - these are confusing for blind users.
|
|
|
|
*/
|
|
|
|
public $rarrow = null;
|
|
|
|
|
|
|
|
/**
|
2012-09-12 16:13:43 +02:00
|
|
|
* @var string Accessibility: Left arrow-like character is
|
2009-12-16 18:00:58 +00:00
|
|
|
* used in the breadcrumb trail, course navigation menu
|
|
|
|
* (previous/next activity), calendar, and search forum block.
|
|
|
|
* If the theme does not set characters, appropriate defaults
|
|
|
|
* are set automatically. Please DO NOT
|
|
|
|
* use < > » - these are confusing for blind users.
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $larrow = null;
|
|
|
|
|
2014-10-28 09:29:28 +00:00
|
|
|
/**
|
|
|
|
* @var string Accessibility: Up arrow-like character is used in
|
|
|
|
* the book heirarchical navigation.
|
|
|
|
* If the theme does not set characters, appropriate defaults
|
|
|
|
* are set automatically. Please DO NOT
|
|
|
|
* use ^ - this is confusing for blind users.
|
|
|
|
*/
|
|
|
|
public $uarrow = null;
|
|
|
|
|
2010-11-09 11:55:37 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var bool Some themes may want to disable ajax course editing.
|
2010-11-09 11:55:37 +00:00
|
|
|
*/
|
|
|
|
public $enablecourseajax = true;
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2012-07-21 19:23:44 +02:00
|
|
|
/**
|
|
|
|
* @var string Determines served document types
|
|
|
|
* - 'html5' the only officially supported doctype in Moodle
|
|
|
|
* - 'xhtml5' may be used in development for validation (not intended for production servers!)
|
|
|
|
* - 'xhtml' XHTML 1.0 Strict for legacy themes only
|
|
|
|
*/
|
|
|
|
public $doctype = 'html5';
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
//==Following properties are not configurable from theme config.php==
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string The name of this theme. Set automatically when this theme is
|
2009-12-16 18:00:58 +00:00
|
|
|
* loaded. This can not be set in theme config.php
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $name;
|
2009-07-07 05:05:06 +00:00
|
|
|
|
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var string The folder where this themes files are stored. This is set
|
2009-12-16 18:00:58 +00:00
|
|
|
* automatically. This can not be set in theme config.php
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public $dir;
|
2009-07-07 05:05:06 +00:00
|
|
|
|
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var stdClass Theme settings stored in config_plugins table.
|
2009-12-16 18:00:58 +00:00
|
|
|
* This can not be set in theme config.php
|
|
|
|
*/
|
|
|
|
public $setting = null;
|
|
|
|
|
2010-01-14 06:56:12 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var bool If set to true and the theme enables the dock then blocks will be able
|
2010-01-14 06:56:12 +00:00
|
|
|
* to be moved to the special dock
|
|
|
|
*/
|
|
|
|
public $enable_dock = false;
|
|
|
|
|
2010-04-28 03:32:16 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var bool If set to true then this theme will not be shown in the theme selector unless
|
2010-04-28 03:32:16 +00:00
|
|
|
* theme designer mode is turned on.
|
|
|
|
*/
|
|
|
|
public $hidefromselector = false;
|
|
|
|
|
2013-03-14 15:59:03 +01:00
|
|
|
/**
|
|
|
|
* @var array list of YUI CSS modules to be included on each page. This may be used
|
|
|
|
* to remove cssreset and use cssnormalise module instead.
|
|
|
|
*/
|
|
|
|
public $yuicssmodules = array('cssreset', 'cssfonts', 'cssgrids', 'cssbase');
|
|
|
|
|
2013-06-07 10:25:47 +12:00
|
|
|
/**
|
|
|
|
* An associative array of block manipulations that should be made if the user is using an rtl language.
|
|
|
|
* The key is the original block region, and the value is the block region to change to.
|
|
|
|
* This is used when displaying blocks for regions only.
|
|
|
|
* @var array
|
|
|
|
*/
|
2013-09-26 09:12:44 +12:00
|
|
|
public $blockrtlmanipulations = array();
|
2013-06-07 10:25:47 +12:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var renderer_factory Instance of the renderer_factory implementation
|
2009-07-07 05:05:06 +00:00
|
|
|
* we are using. Implementation detail.
|
|
|
|
*/
|
|
|
|
protected $rf = null;
|
|
|
|
|
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array List of parent config objects.
|
2009-12-16 18:00:58 +00:00
|
|
|
**/
|
|
|
|
protected $parent_configs = array();
|
2009-07-07 05:05:06 +00:00
|
|
|
|
2012-06-08 15:58:37 +12:00
|
|
|
/**
|
|
|
|
* @var bool If set to true then the theme is safe to run through the optimiser (if it is enabled)
|
|
|
|
* If set to false then we know either the theme has already been optimised and the CSS optimiser is not needed
|
|
|
|
* or the theme is not compatible with the CSS optimiser. In both cases even if enabled the CSS optimiser will not
|
|
|
|
* be used with this theme if set to false.
|
|
|
|
*/
|
|
|
|
public $supportscssoptimisation = true;
|
|
|
|
|
2012-09-27 10:58:42 +12:00
|
|
|
/**
|
|
|
|
* Used to determine whether we can serve SVG images or not.
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
private $usesvg = null;
|
|
|
|
|
2014-02-19 17:02:11 +08:00
|
|
|
/**
|
|
|
|
* The LESS file to compile. When set, the theme will attempt to compile the file itself.
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
public $lessfile = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The name of the function to call to get the LESS code to inject.
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $extralesscallback = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The name of the function to call to get extra LESS variables.
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $lessvariablescallback = null;
|
|
|
|
|
2014-02-24 10:38:17 +13:00
|
|
|
/**
|
|
|
|
* Sets the render method that should be used for rendering custom block regions by scripts such as my/index.php
|
|
|
|
* Defaults to {@link core_renderer::blocks_for_region()}
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $blockrendermethod = null;
|
|
|
|
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
/**
|
2009-07-02 08:49:25 +00:00
|
|
|
* Load the config.php file for a particular theme, and return an instance
|
|
|
|
* of this class. (That is, this is a factory method.)
|
|
|
|
*
|
|
|
|
* @param string $themename the name of the theme.
|
|
|
|
* @return theme_config an instance of this class.
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2009-07-02 08:49:25 +00:00
|
|
|
public static function load($themename) {
|
|
|
|
global $CFG;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
// load theme settings from db
|
|
|
|
try {
|
|
|
|
$settings = get_config('theme_'.$themename);
|
|
|
|
} catch (dml_exception $e) {
|
2009-12-17 20:11:39 +00:00
|
|
|
// most probably moodle tables not created yet
|
2010-09-21 08:07:44 +00:00
|
|
|
$settings = new stdClass();
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
if ($config = theme_config::find_theme_config($themename, $settings)) {
|
|
|
|
return new theme_config($config);
|
2010-01-12 17:21:52 +00:00
|
|
|
|
|
|
|
} else if ($themename == theme_config::DEFAULT_THEME) {
|
|
|
|
throw new coding_exception('Default theme '.theme_config::DEFAULT_THEME.' not available or broken!');
|
|
|
|
|
2012-11-30 12:11:07 +00:00
|
|
|
} else if ($config = theme_config::find_theme_config($CFG->theme, $settings)) {
|
|
|
|
return new theme_config($config);
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
} else {
|
|
|
|
// bad luck, the requested theme has some problems - admin see details in theme config
|
2010-01-12 17:21:52 +00:00
|
|
|
return new theme_config(theme_config::find_theme_config(theme_config::DEFAULT_THEME, $settings));
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
|
|
|
* Theme diagnostic code. It is very problematic to send debug output
|
|
|
|
* to the actual CSS file, instead this functions is supposed to
|
2010-01-11 10:06:56 +00:00
|
|
|
* diagnose given theme and highlights all potential problems.
|
2009-12-16 18:00:58 +00:00
|
|
|
* This information should be available from the theme selection page
|
|
|
|
* or some other debug page for theme designers.
|
|
|
|
*
|
|
|
|
* @param string $themename
|
|
|
|
* @return array description of problems
|
|
|
|
*/
|
|
|
|
public static function diagnose($themename) {
|
2009-12-17 20:06:35 +00:00
|
|
|
//TODO: MDL-21108
|
2009-12-16 18:00:58 +00:00
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private constructor, can be called only from the factory method.
|
|
|
|
* @param stdClass $config
|
|
|
|
*/
|
|
|
|
private function __construct($config) {
|
|
|
|
global $CFG; //needed for included lib.php files
|
|
|
|
|
|
|
|
$this->settings = $config->settings;
|
|
|
|
$this->name = $config->name;
|
|
|
|
$this->dir = $config->dir;
|
|
|
|
|
|
|
|
if ($this->name != 'base') {
|
|
|
|
$baseconfig = theme_config::find_theme_config('base', $this->settings);
|
|
|
|
} else {
|
|
|
|
$baseconfig = $config;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2014-10-28 09:29:28 +00:00
|
|
|
$configurable = array(
|
|
|
|
'parents', 'sheets', 'parents_exclude_sheets', 'plugins_exclude_sheets',
|
|
|
|
'javascripts', 'javascripts_footer', 'parents_exclude_javascripts',
|
|
|
|
'layouts', 'enable_dock', 'enablecourseajax', 'supportscssoptimisation',
|
|
|
|
'rendererfactory', 'csspostprocess', 'editor_sheets', 'rarrow', 'larrow', 'uarrow',
|
|
|
|
'hidefromselector', 'doctype', 'yuicssmodules', 'blockrtlmanipulations',
|
|
|
|
'lessfile', 'extralesscallback', 'lessvariablescallback', 'blockrendermethod');
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
foreach ($config as $key=>$value) {
|
|
|
|
if (in_array($key, $configurable)) {
|
|
|
|
$this->$key = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify all parents and load configs and renderers
|
|
|
|
foreach ($this->parents as $parent) {
|
|
|
|
if ($parent == 'base') {
|
|
|
|
$parent_config = $baseconfig;
|
|
|
|
} else if (!$parent_config = theme_config::find_theme_config($parent, $this->settings)) {
|
|
|
|
// this is not good - better exclude faulty parents
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$libfile = $parent_config->dir.'/lib.php';
|
|
|
|
if (is_readable($libfile)) {
|
|
|
|
// theme may store various function here
|
|
|
|
include_once($libfile);
|
|
|
|
}
|
|
|
|
$renderersfile = $parent_config->dir.'/renderers.php';
|
|
|
|
if (is_readable($renderersfile)) {
|
|
|
|
// may contain core and plugin renderers and renderer factory
|
|
|
|
include_once($renderersfile);
|
|
|
|
}
|
|
|
|
$this->parent_configs[$parent] = $parent_config;
|
|
|
|
}
|
|
|
|
$libfile = $this->dir.'/lib.php';
|
|
|
|
if (is_readable($libfile)) {
|
|
|
|
// theme may store various function here
|
|
|
|
include_once($libfile);
|
|
|
|
}
|
|
|
|
$rendererfile = $this->dir.'/renderers.php';
|
|
|
|
if (is_readable($rendererfile)) {
|
|
|
|
// may contain core and plugin renderers and renderer factory
|
|
|
|
include_once($rendererfile);
|
2012-03-12 12:38:53 -06:00
|
|
|
} else {
|
|
|
|
// check if renderers.php file is missnamed renderer.php
|
|
|
|
if (is_readable($this->dir.'/renderer.php')) {
|
|
|
|
debugging('Developer hint: '.$this->dir.'/renderer.php should be renamed to ' . $this->dir."/renderers.php.
|
2012-03-19 19:12:02 +13:00
|
|
|
See: http://docs.moodle.org/dev/Output_renderers#Theme_renderers.", DEBUG_DEVELOPER);
|
2012-03-12 12:38:53 -06:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2010-04-15 14:43:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
// cascade all layouts properly
|
|
|
|
foreach ($baseconfig->layouts as $layout=>$value) {
|
|
|
|
if (!isset($this->layouts[$layout])) {
|
|
|
|
foreach ($this->parent_configs as $parent_config) {
|
|
|
|
if (isset($parent_config->layouts[$layout])) {
|
|
|
|
$this->layouts[$layout] = $parent_config->layouts[$layout];
|
|
|
|
continue 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->layouts[$layout] = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//fix arrows if needed
|
|
|
|
$this->check_theme_arrows();
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
|
|
|
|
2013-03-19 11:47:31 +01:00
|
|
|
/**
|
|
|
|
* Let the theme initialise the page object (usually $PAGE).
|
|
|
|
*
|
|
|
|
* This may be used for example to request jQuery in add-ons.
|
|
|
|
*
|
|
|
|
* @param moodle_page $page
|
|
|
|
*/
|
|
|
|
public function init_page(moodle_page $page) {
|
|
|
|
$themeinitfunction = 'theme_'.$this->name.'_page_init';
|
|
|
|
if (function_exists($themeinitfunction)) {
|
|
|
|
$themeinitfunction($page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-14 18:24:09 +13:00
|
|
|
/**
|
2014-10-28 09:29:28 +00:00
|
|
|
* Checks if arrows $THEME->rarrow, $THEME->larrow, $THEME->uarrow have been set (theme/-/config.php).
|
2009-12-16 18:00:58 +00:00
|
|
|
* If not it applies sensible defaults.
|
|
|
|
*
|
|
|
|
* Accessibility: right and left arrow Unicode characters for breadcrumb, calendar,
|
|
|
|
* search forum block, etc. Important: these are 'silent' in a screen-reader
|
|
|
|
* (unlike > »), and must be accompanied by text.
|
2009-06-26 09:06:16 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
private function check_theme_arrows() {
|
|
|
|
if (!isset($this->rarrow) and !isset($this->larrow)) {
|
|
|
|
// Default, looks good in Win XP/IE 6, Win/Firefox 1.5, Win/Netscape 8...
|
|
|
|
// Also OK in Win 9x/2K/IE 5.x
|
|
|
|
$this->rarrow = '►';
|
|
|
|
$this->larrow = '◄';
|
2014-10-28 09:29:28 +00:00
|
|
|
$this->uarrow = '▲';
|
2009-12-16 18:00:58 +00:00
|
|
|
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
|
|
|
$uagent = '';
|
2009-07-02 08:49:25 +00:00
|
|
|
} else {
|
2009-12-16 18:00:58 +00:00
|
|
|
$uagent = $_SERVER['HTTP_USER_AGENT'];
|
|
|
|
}
|
|
|
|
if (false !== strpos($uagent, 'Opera')
|
|
|
|
|| false !== strpos($uagent, 'Mac')) {
|
|
|
|
// Looks good in Win XP/Mac/Opera 8/9, Mac/Firefox 2, Camino, Safari.
|
|
|
|
// Not broken in Mac/IE 5, Mac/Netscape 7 (?).
|
2015-07-07 14:13:18 +01:00
|
|
|
$this->rarrow = '▶︎';
|
|
|
|
$this->larrow = '◀︎';
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2013-06-24 11:28:23 +12:00
|
|
|
elseif ((false !== strpos($uagent, 'Konqueror'))
|
2013-05-28 15:25:08 +08:00
|
|
|
|| (false !== strpos($uagent, 'Android'))) {
|
|
|
|
// The fonts on Android don't include the characters required for this to work as expected.
|
|
|
|
// So we use the same ones Konqueror uses.
|
2009-12-16 18:00:58 +00:00
|
|
|
$this->rarrow = '→';
|
|
|
|
$this->larrow = '←';
|
2014-10-28 09:29:28 +00:00
|
|
|
$this->uarrow = '↑';
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
elseif (isset($_SERVER['HTTP_ACCEPT_CHARSET'])
|
|
|
|
&& false === stripos($_SERVER['HTTP_ACCEPT_CHARSET'], 'utf-8')) {
|
|
|
|
// (Win/IE 5 doesn't set ACCEPT_CHARSET, but handles Unicode.)
|
|
|
|
// To be safe, non-Unicode browsers!
|
|
|
|
$this->rarrow = '>';
|
|
|
|
$this->larrow = '<';
|
2014-10-28 09:29:28 +00:00
|
|
|
$this->uarrow = '^';
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
|
2012-02-14 18:24:09 +13:00
|
|
|
// RTL support - in RTL languages, swap r and l arrows
|
2009-12-16 18:00:58 +00:00
|
|
|
if (right_to_left()) {
|
|
|
|
$t = $this->rarrow;
|
|
|
|
$this->rarrow = $this->larrow;
|
|
|
|
$this->larrow = $t;
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
|
|
|
* Returns output renderer prefixes, these are used when looking
|
2010-05-22 20:16:12 +00:00
|
|
|
* for the overridden renderers in themes.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function renderer_prefixes() {
|
|
|
|
global $CFG; // just in case the included files need it
|
|
|
|
|
2009-12-29 12:23:39 +00:00
|
|
|
$prefixes = array('theme_'.$this->name);
|
2009-12-16 18:00:58 +00:00
|
|
|
|
|
|
|
foreach ($this->parent_configs as $parent) {
|
|
|
|
$prefixes[] = 'theme_'.$parent->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $prefixes;
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
|
|
|
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Returns the stylesheet URL of this editor content
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param bool $encoded false means use & and true use & in URLs
|
2013-06-28 16:49:02 +12:00
|
|
|
* @return moodle_url
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public function editor_css_url($encoded=true) {
|
|
|
|
global $CFG;
|
|
|
|
$rev = theme_get_revision();
|
|
|
|
if ($rev > -1) {
|
2013-06-28 16:49:02 +12:00
|
|
|
$url = new moodle_url("$CFG->httpswwwroot/theme/styles.php");
|
2012-05-05 15:25:20 +02:00
|
|
|
if (!empty($CFG->slasharguments)) {
|
|
|
|
$url->set_slashargument('/'.$this->name.'/'.$rev.'/editor', 'noparam', true);
|
|
|
|
} else {
|
2013-06-28 16:49:02 +12:00
|
|
|
$url->params(array('theme'=>$this->name,'rev'=>$rev, 'type'=>'editor'));
|
2012-05-05 15:25:20 +02:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
} else {
|
|
|
|
$params = array('theme'=>$this->name, 'type'=>'editor');
|
2013-06-28 16:49:02 +12:00
|
|
|
$url = new moodle_url($CFG->httpswwwroot.'/theme/styles_debug.php', $params);
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
2013-06-28 16:49:02 +12:00
|
|
|
return $url;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Returns the content of the CSS to be used in editor content
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2014-02-27 14:35:03 +08:00
|
|
|
* @return array
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2010-10-01 01:43:06 +00:00
|
|
|
public function editor_css_files() {
|
|
|
|
$files = array();
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
// First editor plugins.
|
2013-07-16 22:36:11 +02:00
|
|
|
$plugins = core_component::get_plugin_list('editor');
|
2009-12-16 18:00:58 +00:00
|
|
|
foreach ($plugins as $plugin=>$fulldir) {
|
|
|
|
$sheetfile = "$fulldir/editor_styles.css";
|
|
|
|
if (is_readable($sheetfile)) {
|
2010-10-01 01:43:06 +00:00
|
|
|
$files['plugin_'.$plugin] = $sheetfile;
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-27 14:35:03 +08:00
|
|
|
// Then parent themes - base first, the immediate parent last.
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) {
|
2009-12-16 18:00:58 +00:00
|
|
|
if (empty($parent_config->editor_sheets)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($parent_config->editor_sheets as $sheet) {
|
2010-10-06 07:38:34 +00:00
|
|
|
$sheetfile = "$parent_config->dir/style/$sheet.css";
|
2009-12-16 18:00:58 +00:00
|
|
|
if (is_readable($sheetfile)) {
|
2010-10-01 01:43:06 +00:00
|
|
|
$files['parent_'.$parent_config->name.'_'.$sheet] = $sheetfile;
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-02-27 14:35:03 +08:00
|
|
|
// Finally this theme.
|
2009-12-16 18:00:58 +00:00
|
|
|
if (!empty($this->editor_sheets)) {
|
|
|
|
foreach ($this->editor_sheets as $sheet) {
|
2010-10-01 01:43:06 +00:00
|
|
|
$sheetfile = "$this->dir/style/$sheet.css";
|
2009-12-16 18:00:58 +00:00
|
|
|
if (is_readable($sheetfile)) {
|
2010-10-01 01:43:06 +00:00
|
|
|
$files['theme_'.$sheet] = $sheetfile;
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-01 01:43:06 +00:00
|
|
|
return $files;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-02-27 14:35:03 +08:00
|
|
|
* Get the stylesheet URL of this theme.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
|
|
|
* @param moodle_page $page Not used... deprecated?
|
2014-02-27 14:35:03 +08:00
|
|
|
* @return moodle_url[]
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
*/
|
2010-01-05 00:33:15 +00:00
|
|
|
public function css_urls(moodle_page $page) {
|
2009-12-16 18:00:58 +00:00
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
$rev = theme_get_revision();
|
|
|
|
|
2010-01-05 00:33:15 +00:00
|
|
|
$urls = array();
|
|
|
|
|
2012-11-28 18:15:54 +13:00
|
|
|
$svg = $this->use_svg_icons();
|
2014-04-03 16:47:12 +08:00
|
|
|
$separate = (core_useragent::is_ie() && !core_useragent::check_ie_version('10'));
|
2012-11-28 18:15:54 +13:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
if ($rev > -1) {
|
2012-11-28 18:15:54 +13:00
|
|
|
$url = new moodle_url("$CFG->httpswwwroot/theme/styles.php");
|
2013-06-28 16:49:02 +12:00
|
|
|
if (!empty($CFG->slasharguments)) {
|
|
|
|
$slashargs = '';
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
$slashargs .= '/'.$this->name.'/'.$rev.'/all';
|
|
|
|
if ($separate) {
|
|
|
|
$slashargs .= '/chunk0';
|
|
|
|
}
|
|
|
|
$url->set_slashargument($slashargs, 'noparam', true);
|
2010-05-10 07:47:52 +00:00
|
|
|
} else {
|
2013-06-28 16:49:02 +12:00
|
|
|
$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';
|
2012-05-05 15:25:20 +02:00
|
|
|
}
|
2013-06-28 16:49:02 +12:00
|
|
|
if ($separate) {
|
|
|
|
$params['chunk'] = '0';
|
|
|
|
}
|
|
|
|
$url->params($params);
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2013-06-28 16:49:02 +12:00
|
|
|
$urls[] = $url;
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
} else {
|
2012-11-28 18:15:54 +13:00
|
|
|
$baseurl = new moodle_url($CFG->httpswwwroot.'/theme/styles_debug.php');
|
2010-02-08 16:50:12 +00:00
|
|
|
|
2014-03-17 14:39:57 +08:00
|
|
|
$css = $this->get_css_files(true);
|
2012-11-28 18:15:54 +13:00
|
|
|
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');
|
|
|
|
}
|
2014-04-03 16:47:12 +08:00
|
|
|
if ($separate) {
|
|
|
|
// We might need to chunk long files.
|
|
|
|
$baseurl->param('chunk', '0');
|
|
|
|
}
|
2013-05-31 13:10:00 +08:00
|
|
|
if (core_useragent::is_ie()) {
|
2014-02-27 14:35:03 +08:00
|
|
|
// Lalala, IE does not allow more than 31 linked CSS files from main document.
|
2010-10-01 01:43:06 +00:00
|
|
|
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name, 'type'=>'ie', 'subtype'=>'plugins'));
|
2010-07-07 09:10:10 +00:00
|
|
|
foreach ($css['parents'] as $parent=>$sheets) {
|
2014-02-27 14:35:03 +08:00
|
|
|
// We need to serve parents individually otherwise we may easily exceed the style limit IE imposes (4096).
|
2010-10-01 01:43:06 +00:00
|
|
|
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name,'type'=>'ie', 'subtype'=>'parents', 'sheet'=>$parent));
|
2010-07-07 09:10:10 +00:00
|
|
|
}
|
2014-03-17 14:39:57 +08:00
|
|
|
if (!empty($this->lessfile)) {
|
|
|
|
// No need to define the type as IE here.
|
2014-04-03 16:47:12 +08:00
|
|
|
$urls[] = new moodle_url($baseurl, array('theme' => $this->name, 'type' => 'less'));
|
2014-03-04 16:39:40 +08:00
|
|
|
}
|
2010-10-01 01:43:06 +00:00
|
|
|
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name, 'type'=>'ie', 'subtype'=>'theme'));
|
2010-02-08 16:50:12 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
foreach ($css['plugins'] as $plugin=>$unused) {
|
|
|
|
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name,'type'=>'plugin', 'subtype'=>$plugin));
|
|
|
|
}
|
|
|
|
foreach ($css['parents'] as $parent=>$sheets) {
|
|
|
|
foreach ($sheets as $sheet=>$unused2) {
|
|
|
|
$urls[] = new moodle_url($baseurl, array('theme'=>$this->name,'type'=>'parent', 'subtype'=>$parent, 'sheet'=>$sheet));
|
|
|
|
}
|
|
|
|
}
|
2014-03-17 14:39:57 +08:00
|
|
|
foreach ($css['theme'] as $sheet => $filename) {
|
|
|
|
if ($sheet === $this->lessfile) {
|
|
|
|
// This is the theme LESS file.
|
|
|
|
$urls[] = new moodle_url($baseurl, array('theme' => $this->name, 'type' => 'less'));
|
|
|
|
} else {
|
2014-02-19 17:02:11 +08:00
|
|
|
// Sheet first in order to make long urls easier to read.
|
|
|
|
$urls[] = new moodle_url($baseurl, array('sheet'=>$sheet, 'theme'=>$this->name, 'type'=>'theme'));
|
2010-02-08 16:50:12 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-05 00:33:15 +00:00
|
|
|
|
|
|
|
return $urls;
|
themes: MDL-19077 implement the renderer_factory instrastructure.
This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F
The concept is that all the print_... functions in weblib get replaced by methods
on a moodle_core_renderer class. Then, the theme can choose whether to
use the standard moodle_core_renderer class, or another implemenatation of
its own choosing, to generate different HTML.
Also, becuase Moodle is modular, we may need a moodle_mod_forum_renderer
and so on.
In order for the theme to be able to choose which renderers get created, we
introduce the concept of a renderer factory, as in the factory design pattern.
The theme will choose which factory should be used, and that then creates
the renderer objects based on the module name.
This commit includes 4 types of factory:
* standard_renderer_factory
* custom_corners_renderer_factory
* theme_overridden_renderer_factory
* template_renderer_factory
All this with unit tests and PHP doc comments.
Note, this new code is not actually used yet. Still todo:
1. actually define the moodle_core_renderer class, and deprecate a lot of weblib functions.
2. make theme_setup initialise everything, so it is used.
2009-06-18 10:43:13 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2014-02-27 14:35:03 +08:00
|
|
|
* Get the whole css stylesheet for production mode.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2014-03-03 14:19:12 +08:00
|
|
|
* NOTE: this method is not expected to be used from any addons.
|
|
|
|
*
|
2014-02-27 14:35:03 +08:00
|
|
|
* @return string CSS markup, already optimised and compressed
|
|
|
|
*/
|
|
|
|
public function get_css_content() {
|
|
|
|
global $CFG;
|
|
|
|
require_once($CFG->dirroot.'/lib/csslib.php');
|
|
|
|
|
|
|
|
$csscontent = '';
|
2014-03-17 14:39:57 +08:00
|
|
|
foreach ($this->get_css_files(false) as $type => $value) {
|
|
|
|
foreach ($value as $identifier => $val) {
|
2014-02-27 14:35:03 +08:00
|
|
|
if (is_array($val)) {
|
|
|
|
foreach ($val as $v) {
|
|
|
|
$csscontent .= file_get_contents($v) . "\n";
|
|
|
|
}
|
|
|
|
} else {
|
2014-03-17 14:39:57 +08:00
|
|
|
if ($type === 'theme' && $identifier === $this->lessfile) {
|
|
|
|
// We need the content from LESS because this is the LESS file from the theme.
|
|
|
|
$csscontent .= $this->get_css_content_from_less(false);
|
2014-02-19 17:02:11 +08:00
|
|
|
} else {
|
|
|
|
$csscontent .= file_get_contents($val) . "\n";
|
2014-02-27 14:35:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$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().
|
|
|
|
*
|
2014-03-03 14:19:12 +08:00
|
|
|
* NOTE: this method is not expected to be used from any addons.
|
|
|
|
*
|
2014-02-27 14:35:03 +08:00
|
|
|
* @param string $type
|
|
|
|
* @param string $subtype
|
|
|
|
* @param string $sheet
|
|
|
|
* @return string CSS markup
|
2009-07-02 08:49:25 +00:00
|
|
|
*/
|
2014-02-27 14:35:03 +08:00
|
|
|
public function get_css_content_debug($type, $subtype, $sheet) {
|
|
|
|
global $CFG;
|
|
|
|
require_once($CFG->dirroot.'/lib/csslib.php');
|
|
|
|
|
2014-03-17 14:39:57 +08:00
|
|
|
// The LESS file of the theme is requested.
|
|
|
|
if ($type === 'less') {
|
|
|
|
$csscontent = $this->get_css_content_from_less(true);
|
|
|
|
if ($csscontent !== false) {
|
|
|
|
return $csscontent;
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
$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'];
|
2014-04-03 16:40:42 +08:00
|
|
|
foreach ($cssfiles as $key => $value) {
|
|
|
|
if ($this->lessfile && $key === $this->lessfile) {
|
|
|
|
// Remove the LESS file from the theme CSS files.
|
|
|
|
// The LESS files use the type 'less', not 'ie'.
|
|
|
|
unset($cssfiles[$key]);
|
|
|
|
}
|
|
|
|
}
|
2014-02-27 14:35:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} 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.
|
2014-03-03 14:19:12 +08:00
|
|
|
*
|
|
|
|
* NOTE: this method is not expected to be used from any addons.
|
|
|
|
*
|
2014-02-27 14:35:03 +08:00
|
|
|
* @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;
|
2014-03-17 14:39:57 +08:00
|
|
|
$cachekey = 'cssfiles';
|
2014-02-27 14:35:03 +08:00
|
|
|
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));
|
2014-02-19 17:02:11 +08:00
|
|
|
if ($files = $cache->get($cachekey)) {
|
2014-02-27 14:35:03 +08:00
|
|
|
if ($files['created'] > time() - THEME_DESIGNER_CACHE_LIFETIME) {
|
|
|
|
unset($files['created']);
|
|
|
|
return $files;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-19 02:15:16 +00:00
|
|
|
$cssfiles = array('plugins'=>array(), 'parents'=>array(), 'theme'=>array());
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
// Get all plugin sheets.
|
2010-05-19 02:15:16 +00:00
|
|
|
$excludes = $this->resolve_excludes('plugins_exclude_sheets');
|
2009-12-16 18:00:58 +00:00
|
|
|
if ($excludes !== true) {
|
2013-07-16 22:31:48 +02:00
|
|
|
foreach (core_component::get_plugin_types() as $type=>$unused) {
|
2010-05-19 02:15:16 +00:00
|
|
|
if ($type === 'theme' || (!empty($excludes[$type]) and $excludes[$type] === true)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
continue;
|
|
|
|
}
|
2013-07-16 22:36:11 +02:00
|
|
|
$plugins = core_component::get_plugin_list($type);
|
2009-12-16 18:00:58 +00:00
|
|
|
foreach ($plugins as $plugin=>$fulldir) {
|
|
|
|
if (!empty($excludes[$type]) and is_array($excludes[$type])
|
2014-01-20 13:29:20 +01:00
|
|
|
and in_array($plugin, $excludes[$type])) {
|
2009-12-16 18:00:58 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-02-18 08:47:47 +00:00
|
|
|
|
2014-03-17 14:39:57 +08:00
|
|
|
// Get the CSS from the plugin.
|
2009-12-16 18:00:58 +00:00
|
|
|
$sheetfile = "$fulldir/styles.css";
|
|
|
|
if (is_readable($sheetfile)) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$cssfiles['plugins'][$type.'_'.$plugin] = $sheetfile;
|
2010-02-18 08:47:47 +00:00
|
|
|
}
|
2014-01-20 13:29:20 +01:00
|
|
|
|
|
|
|
// Create a list of candidate sheets from parents (direct parent last) and current theme.
|
|
|
|
$candidates = array();
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) {
|
|
|
|
$candidates[] = $parent_config->name;
|
2010-02-18 08:47:47 +00:00
|
|
|
}
|
2014-01-20 13:29:20 +01:00
|
|
|
$candidates[] = $this->name;
|
|
|
|
|
|
|
|
// Add the sheets found.
|
|
|
|
foreach ($candidates as $candidate) {
|
|
|
|
$sheetthemefile = "$fulldir/styles_{$candidate}.css";
|
|
|
|
if (is_readable($sheetthemefile)) {
|
|
|
|
$cssfiles['plugins'][$type.'_'.$plugin.'_'.$candidate] = $sheetthemefile;
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-20 13:29:20 +01:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
// Find out wanted parent sheets.
|
2010-05-19 02:15:16 +00:00
|
|
|
$excludes = $this->resolve_excludes('parents_exclude_sheets');
|
2009-12-16 18:00:58 +00:00
|
|
|
if ($excludes !== true) {
|
2014-02-27 14:35:03 +08:00
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // Base first, the immediate parent last.
|
2009-12-16 18:00:58 +00:00
|
|
|
$parent = $parent_config->name;
|
2010-05-19 02:15:16 +00:00
|
|
|
if (empty($parent_config->sheets) || (!empty($excludes[$parent]) and $excludes[$parent] === true)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($parent_config->sheets as $sheet) {
|
2014-02-19 17:02:11 +08:00
|
|
|
if (!empty($excludes[$parent]) && is_array($excludes[$parent])
|
|
|
|
&& in_array($sheet, $excludes[$parent])) {
|
2009-12-16 18:00:58 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-02-19 17:02:11 +08:00
|
|
|
|
|
|
|
// We never refer to the parent LESS files.
|
2009-12-16 18:00:58 +00:00
|
|
|
$sheetfile = "$parent_config->dir/style/$sheet.css";
|
|
|
|
if (is_readable($sheetfile)) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$cssfiles['parents'][$parent][$sheet] = $sheetfile;
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2014-02-19 17:02:11 +08:00
|
|
|
// Current theme sheets and less file.
|
|
|
|
// We first add the LESS files because we want the CSS ones to be included after the
|
|
|
|
// LESS code. However, if both the LESS file and the CSS file share the same name,
|
|
|
|
// the CSS file is ignored.
|
2014-03-17 14:39:57 +08:00
|
|
|
if (!empty($this->lessfile)) {
|
2014-02-19 17:02:11 +08:00
|
|
|
$sheetfile = "{$this->dir}/less/{$this->lessfile}.less";
|
|
|
|
if (is_readable($sheetfile)) {
|
|
|
|
$cssfiles['theme'][$this->lessfile] = $sheetfile;
|
|
|
|
}
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
if (is_array($this->sheets)) {
|
|
|
|
foreach ($this->sheets as $sheet) {
|
|
|
|
$sheetfile = "$this->dir/style/$sheet.css";
|
2014-02-19 17:02:11 +08:00
|
|
|
if (is_readable($sheetfile) && !isset($cssfiles['theme'][$sheet])) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$cssfiles['theme'][$sheet] = $sheetfile;
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
|
|
|
|
2014-02-27 14:35:03 +08:00
|
|
|
if ($cache) {
|
|
|
|
$files = $cssfiles;
|
|
|
|
$files['created'] = time();
|
2014-02-19 17:02:11 +08:00
|
|
|
$cache->set($cachekey, $files);
|
2010-05-19 02:15:16 +00:00
|
|
|
}
|
2014-02-27 14:35:03 +08:00
|
|
|
return $cssfiles;
|
|
|
|
}
|
2009-12-20 23:06:57 +00:00
|
|
|
|
2014-02-19 17:02:11 +08:00
|
|
|
/**
|
2014-03-17 14:39:57 +08:00
|
|
|
* Return the CSS content generated from LESS the file.
|
2014-02-19 17:02:11 +08:00
|
|
|
*
|
|
|
|
* @param bool $themedesigner True if theme designer is enabled.
|
|
|
|
* @return bool|string Return false when the compilation failed. Else the compiled string.
|
|
|
|
*/
|
|
|
|
protected function get_css_content_from_less($themedesigner) {
|
|
|
|
|
|
|
|
$lessfile = $this->lessfile;
|
|
|
|
if (!$lessfile || !is_readable($this->dir . '/less/' . $lessfile . '.less')) {
|
|
|
|
throw new coding_exception('The theme did not define a LESS file, or it is not readable.');
|
|
|
|
}
|
|
|
|
|
|
|
|
// We might need more memory to do this, so let's play safe.
|
|
|
|
raise_memory_limit(MEMORY_EXTRA);
|
|
|
|
|
|
|
|
// Files list.
|
2014-03-17 14:39:57 +08:00
|
|
|
$files = $this->get_css_files($themedesigner);
|
2014-02-19 17:02:11 +08:00
|
|
|
|
2014-03-17 14:39:57 +08:00
|
|
|
// Get the LESS file path.
|
|
|
|
$themelessfile = $files['theme'][$lessfile];
|
2014-02-19 17:02:11 +08:00
|
|
|
|
2014-03-21 11:48:52 +08:00
|
|
|
// Setup compiler options.
|
|
|
|
$options = array(
|
2014-02-19 17:02:11 +08:00
|
|
|
// We need to set the import directory to where $lessfile is.
|
2014-03-17 14:39:57 +08:00
|
|
|
'import_dirs' => array(dirname($themelessfile) => '/'),
|
2014-02-19 17:02:11 +08:00
|
|
|
// Always disable default caching.
|
|
|
|
'cache_method' => false,
|
|
|
|
// Disable the relative URLs, we have post_process() to handle that.
|
|
|
|
'relativeUrls' => false,
|
2014-03-21 11:48:52 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
if ($themedesigner) {
|
|
|
|
// Add the sourceMap inline to ensure that it is atomically generated.
|
|
|
|
$options['sourceMap'] = true;
|
|
|
|
$options['sourceRoot'] = 'theme';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the compiler.
|
|
|
|
$compiler = new core_lessc($options);
|
2014-02-19 17:02:11 +08:00
|
|
|
|
|
|
|
try {
|
2014-03-17 14:39:57 +08:00
|
|
|
$compiler->parse_file_content($themelessfile);
|
2014-02-19 17:02:11 +08:00
|
|
|
|
|
|
|
// Get the callbacks.
|
|
|
|
$compiler->parse($this->get_extra_less_code());
|
|
|
|
$compiler->ModifyVars($this->get_less_variables());
|
|
|
|
|
|
|
|
// Compile the CSS.
|
|
|
|
$compiled = $compiler->getCss();
|
|
|
|
|
|
|
|
// Post process the entire thing.
|
|
|
|
$compiled = $this->post_process($compiled);
|
|
|
|
} catch (Less_Exception_Parser $e) {
|
|
|
|
$compiled = false;
|
|
|
|
debugging('Error while compiling LESS ' . $lessfile . ' file: ' . $e->getMessage(), DEBUG_DEVELOPER);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to save memory.
|
|
|
|
$compiler = null;
|
|
|
|
unset($compiler);
|
|
|
|
|
|
|
|
return $compiled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return extra LESS variables to use when compiling.
|
|
|
|
*
|
|
|
|
* @return array Where keys are the variable names (omitting the @), and the values are the value.
|
|
|
|
*/
|
|
|
|
protected function get_less_variables() {
|
|
|
|
$variables = array();
|
|
|
|
|
|
|
|
// Getting all the candidate functions.
|
|
|
|
$candidates = array();
|
|
|
|
foreach ($this->parent_configs as $parent_config) {
|
|
|
|
if (!isset($parent_config->lessvariablescallback)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$candidates[] = $parent_config->lessvariablescallback;
|
|
|
|
}
|
|
|
|
$candidates[] = $this->lessvariablescallback;
|
|
|
|
|
|
|
|
// Calling the functions.
|
|
|
|
foreach ($candidates as $function) {
|
|
|
|
if (function_exists($function)) {
|
|
|
|
$vars = $function($this);
|
|
|
|
if (!is_array($vars)) {
|
|
|
|
debugging('Callback ' . $function . ' did not return an array() as expected', DEBUG_DEVELOPER);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$variables = array_merge($variables, $vars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $variables;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return extra LESS code to add when compiling.
|
|
|
|
*
|
|
|
|
* This is intended to be used by themes to inject some LESS code
|
|
|
|
* before it gets compiled. If you want to inject variables you
|
|
|
|
* should use {@link self::get_less_variables()}.
|
|
|
|
*
|
|
|
|
* @return string The LESS code to inject.
|
|
|
|
*/
|
|
|
|
protected function get_extra_less_code() {
|
|
|
|
$content = '';
|
|
|
|
|
|
|
|
// Getting all the candidate functions.
|
|
|
|
$candidates = array();
|
|
|
|
foreach ($this->parent_configs as $parent_config) {
|
|
|
|
if (!isset($parent_config->extralesscallback)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$candidates[] = $parent_config->extralesscallback;
|
|
|
|
}
|
|
|
|
$candidates[] = $this->extralesscallback;
|
|
|
|
|
|
|
|
// Calling the functions.
|
|
|
|
foreach ($candidates as $function) {
|
|
|
|
if (function_exists($function)) {
|
|
|
|
$content .= "\n/** Extra LESS from $function **/\n" . $function($this) . "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $content;
|
|
|
|
}
|
|
|
|
|
2009-12-20 23:06:57 +00:00
|
|
|
/**
|
2012-01-05 13:27:54 +13:00
|
|
|
* Generate a URL to the file that serves theme JavaScript files.
|
|
|
|
*
|
2012-11-05 14:03:04 +00:00
|
|
|
* If we determine that the theme has no relevant files, then we return
|
|
|
|
* early with a null value.
|
|
|
|
*
|
2010-05-22 20:16:12 +00:00
|
|
|
* @param bool $inhead true means head url, false means footer
|
2012-11-05 14:03:04 +00:00
|
|
|
* @return moodle_url|null
|
2009-12-20 23:06:57 +00:00
|
|
|
*/
|
2010-02-07 13:08:46 +00:00
|
|
|
public function javascript_url($inhead) {
|
2009-12-20 23:06:57 +00:00
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
$rev = theme_get_revision();
|
|
|
|
$params = array('theme'=>$this->name,'rev'=>$rev);
|
2010-02-07 13:08:46 +00:00
|
|
|
$params['type'] = $inhead ? 'head' : 'footer';
|
|
|
|
|
2012-11-05 14:03:04 +00:00
|
|
|
// Return early if there are no files to serve
|
|
|
|
if (count($this->javascript_files($params['type'])) === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-05-05 15:31:27 +02:00
|
|
|
if (!empty($CFG->slasharguments) and $rev > 0) {
|
|
|
|
$url = new moodle_url("$CFG->httpswwwroot/theme/javascript.php");
|
|
|
|
$url->set_slashargument('/'.$this->name.'/'.$rev.'/'.$params['type'], 'noparam', true);
|
|
|
|
return $url;
|
|
|
|
} else {
|
|
|
|
return new moodle_url($CFG->httpswwwroot.'/theme/javascript.php', $params);
|
|
|
|
}
|
2009-12-20 23:06:57 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 13:27:54 +13:00
|
|
|
/**
|
|
|
|
* Get the URL's for the JavaScript files used by this theme.
|
|
|
|
* They won't be served directly, instead they'll be mediated through
|
|
|
|
* theme/javascript.php.
|
|
|
|
*
|
|
|
|
* @param string $type Either javascripts_footer, or javascripts
|
|
|
|
* @return array
|
|
|
|
*/
|
2010-05-19 02:15:16 +00:00
|
|
|
public function javascript_files($type) {
|
|
|
|
if ($type === 'footer') {
|
|
|
|
$type = 'javascripts_footer';
|
|
|
|
} else {
|
2010-05-19 02:22:17 +00:00
|
|
|
$type = 'javascripts';
|
2010-05-19 02:15:16 +00:00
|
|
|
}
|
2010-01-05 23:22:16 +00:00
|
|
|
|
2009-12-23 17:18:46 +00:00
|
|
|
$js = array();
|
|
|
|
// find out wanted parent javascripts
|
2010-05-19 02:15:16 +00:00
|
|
|
$excludes = $this->resolve_excludes('parents_exclude_javascripts');
|
2009-12-23 17:18:46 +00:00
|
|
|
if ($excludes !== true) {
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
|
|
|
$parent = $parent_config->name;
|
2010-01-05 23:22:16 +00:00
|
|
|
if (empty($parent_config->$type)) {
|
2009-12-23 17:18:46 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!empty($excludes[$parent]) and $excludes[$parent] === true) {
|
|
|
|
continue;
|
|
|
|
}
|
2010-01-05 23:22:16 +00:00
|
|
|
foreach ($parent_config->$type as $javascript) {
|
2009-12-23 17:18:46 +00:00
|
|
|
if (!empty($excludes[$parent]) and is_array($excludes[$parent])
|
|
|
|
and in_array($javascript, $excludes[$parent])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$javascriptfile = "$parent_config->dir/javascript/$javascript.js";
|
|
|
|
if (is_readable($javascriptfile)) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$js[] = $javascriptfile;
|
2009-12-23 17:18:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// current theme javascripts
|
2010-01-05 23:22:16 +00:00
|
|
|
if (is_array($this->$type)) {
|
|
|
|
foreach ($this->$type as $javascript) {
|
2009-12-23 17:18:46 +00:00
|
|
|
$javascriptfile = "$this->dir/javascript/$javascript.js";
|
|
|
|
if (is_readable($javascriptfile)) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$js[] = $javascriptfile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $js;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-01-12 12:55:50 +13:00
|
|
|
* Resolves an exclude setting to the themes setting is applicable or the
|
2010-05-19 02:15:16 +00:00
|
|
|
* setting of its closest parent.
|
|
|
|
*
|
|
|
|
* @param string $variable The name of the setting the exclude setting to resolve
|
2012-02-14 18:24:09 +13:00
|
|
|
* @param string $default
|
2010-05-19 02:15:16 +00:00
|
|
|
* @return mixed
|
|
|
|
*/
|
2012-02-14 18:24:09 +13:00
|
|
|
protected function resolve_excludes($variable, $default = null) {
|
2010-05-19 02:15:16 +00:00
|
|
|
$setting = $default;
|
|
|
|
if (is_array($this->{$variable}) or $this->{$variable} === true) {
|
|
|
|
$setting = $this->{$variable};
|
|
|
|
} else {
|
|
|
|
foreach ($this->parent_configs as $parent_config) { // the immediate parent first, base last
|
|
|
|
if (!isset($parent_config->{$variable})) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (is_array($parent_config->{$variable}) or $parent_config->{$variable} === true) {
|
|
|
|
$setting = $parent_config->{$variable};
|
|
|
|
break;
|
2009-12-23 17:18:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-19 02:15:16 +00:00
|
|
|
return $setting;
|
|
|
|
}
|
2009-12-23 17:18:46 +00:00
|
|
|
|
2010-05-19 02:15:16 +00:00
|
|
|
/**
|
|
|
|
* Returns the content of the one huge javascript file merged from all theme javascript files.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2012-02-14 18:24:09 +13:00
|
|
|
* @param bool $type
|
2010-05-19 02:15:16 +00:00
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function javascript_content($type) {
|
|
|
|
$jsfiles = $this->javascript_files($type);
|
|
|
|
$js = '';
|
|
|
|
foreach ($jsfiles as $jsfile) {
|
|
|
|
$js .= file_get_contents($jsfile)."\n";
|
|
|
|
}
|
|
|
|
return $js;
|
2009-12-20 23:06:57 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 13:27:54 +13:00
|
|
|
/**
|
|
|
|
* Post processes CSS.
|
|
|
|
*
|
|
|
|
* This method post processes all of the CSS before it is served for this theme.
|
|
|
|
* This is done so that things such as image URL's can be swapped in and to
|
|
|
|
* run any specific CSS post process method the theme has requested.
|
2012-01-12 12:55:50 +13:00
|
|
|
* This allows themes to use CSS settings.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
|
|
|
* @param string $css The CSS to process.
|
|
|
|
* @return string The processed CSS.
|
|
|
|
*/
|
2010-05-19 02:15:16 +00:00
|
|
|
public function post_process($css) {
|
2009-12-16 18:00:58 +00:00
|
|
|
// now resolve all image locations
|
2013-07-20 13:08:35 +02:00
|
|
|
if (preg_match_all('/\[\[pix:([a-z0-9_]+\|)?([^\]]+)\]\]/', $css, $matches, PREG_SET_ORDER)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
$replaced = array();
|
|
|
|
foreach ($matches as $match) {
|
|
|
|
if (isset($replaced[$match[0]])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$replaced[$match[0]] = true;
|
|
|
|
$imagename = $match[2];
|
|
|
|
$component = rtrim($match[1], '|');
|
2010-01-17 09:50:55 +00:00
|
|
|
$imageurl = $this->pix_url($imagename, $component)->out(false);
|
2010-01-05 21:45:08 +00:00
|
|
|
// we do not need full url because the image.php is always in the same dir
|
2012-05-05 14:45:26 +02:00
|
|
|
$imageurl = preg_replace('|^http.?://[^/]+|', '', $imageurl);
|
2010-01-05 21:45:08 +00:00
|
|
|
$css = str_replace($match[0], $imageurl, $css);
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
2009-06-30 07:57:41 +00:00
|
|
|
|
2013-07-19 11:53:16 +02:00
|
|
|
// Now resolve all font locations.
|
2013-07-20 13:08:35 +02:00
|
|
|
if (preg_match_all('/\[\[font:([a-z0-9_]+\|)?([^\]]+)\]\]/', $css, $matches, PREG_SET_ORDER)) {
|
2013-07-19 11:53:16 +02:00
|
|
|
$replaced = array();
|
|
|
|
foreach ($matches as $match) {
|
|
|
|
if (isset($replaced[$match[0]])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$replaced[$match[0]] = true;
|
|
|
|
$fontname = $match[2];
|
|
|
|
$component = rtrim($match[1], '|');
|
|
|
|
$fonturl = $this->font_url($fontname, $component)->out(false);
|
|
|
|
// We do not need full url because the font.php is always in the same dir.
|
|
|
|
$fonturl = preg_replace('|^http.?://[^/]+|', '', $fonturl);
|
|
|
|
$css = str_replace($match[0], $fonturl, $css);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
// now resolve all theme settings or do any other postprocessing
|
|
|
|
$csspostprocess = $this->csspostprocess;
|
|
|
|
if (function_exists($csspostprocess)) {
|
|
|
|
$css = $csspostprocess($css, $this);
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
return $css;
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-30 07:57:41 +00:00
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Return the URL for an image
|
|
|
|
*
|
|
|
|
* @param string $imagename the name of the icon.
|
2012-02-14 18:24:09 +13:00
|
|
|
* @param string $component specification of one plugin like in get_string()
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return moodle_url
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 20:33:37 +00:00
|
|
|
public function pix_url($imagename, $component) {
|
2009-07-07 05:05:06 +00:00
|
|
|
global $CFG;
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2012-05-05 14:45:26 +02:00
|
|
|
$params = array('theme'=>$this->name);
|
2012-09-27 10:58:42 +12:00
|
|
|
$svg = $this->use_svg_icons();
|
2012-05-05 14:45:26 +02:00
|
|
|
|
|
|
|
if (empty($component) or $component === 'moodle' or $component === 'core') {
|
|
|
|
$params['component'] = 'core';
|
|
|
|
} else {
|
|
|
|
$params['component'] = $component;
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
|
|
|
|
$rev = theme_get_revision();
|
|
|
|
if ($rev != -1) {
|
|
|
|
$params['rev'] = $rev;
|
|
|
|
}
|
2012-05-05 14:45:26 +02:00
|
|
|
|
|
|
|
$params['image'] = $imagename;
|
|
|
|
|
2012-09-27 10:58:42 +12:00
|
|
|
$url = new moodle_url("$CFG->httpswwwroot/theme/image.php");
|
2012-05-05 14:45:26 +02:00
|
|
|
if (!empty($CFG->slasharguments) and $rev > 0) {
|
2012-09-27 10:58:42 +12:00
|
|
|
$path = '/'.$params['theme'].'/'.$params['component'].'/'.$params['rev'].'/'.$params['image'];
|
|
|
|
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.
|
|
|
|
$path = '/_s'.$path;
|
|
|
|
}
|
|
|
|
$url->set_slashargument($path, 'noparam', true);
|
2012-05-05 14:45:26 +02:00
|
|
|
} else {
|
2012-09-27 10:58:42 +12:00
|
|
|
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);
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2012-05-05 14:45:26 +02:00
|
|
|
return $url;
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
|
2013-07-19 11:53:16 +02:00
|
|
|
/**
|
|
|
|
* Return the URL for a font
|
|
|
|
*
|
|
|
|
* @param string $font the name of the font (including extension).
|
|
|
|
* @param string $component specification of one plugin like in get_string()
|
|
|
|
* @return moodle_url
|
|
|
|
*/
|
|
|
|
public function font_url($font, $component) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
$params = array('theme'=>$this->name);
|
|
|
|
|
|
|
|
if (empty($component) or $component === 'moodle' or $component === 'core') {
|
|
|
|
$params['component'] = 'core';
|
|
|
|
} else {
|
|
|
|
$params['component'] = $component;
|
|
|
|
}
|
|
|
|
|
|
|
|
$rev = theme_get_revision();
|
|
|
|
if ($rev != -1) {
|
|
|
|
$params['rev'] = $rev;
|
|
|
|
}
|
|
|
|
|
|
|
|
$params['font'] = $font;
|
|
|
|
|
|
|
|
$url = new moodle_url("$CFG->httpswwwroot/theme/font.php");
|
|
|
|
if (!empty($CFG->slasharguments) and $rev > 0) {
|
|
|
|
$path = '/'.$params['theme'].'/'.$params['component'].'/'.$params['rev'].'/'.$params['font'];
|
|
|
|
$url->set_slashargument($path, 'noparam', true);
|
|
|
|
} else {
|
|
|
|
$url->params($params);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
2013-04-10 10:57:18 +02:00
|
|
|
/**
|
|
|
|
* Returns URL to the stored file via pluginfile.php.
|
|
|
|
*
|
|
|
|
* Note the theme must also implement pluginfile.php handler,
|
|
|
|
* theme revision is used instead of the itemid.
|
|
|
|
*
|
|
|
|
* @param string $setting
|
|
|
|
* @param string $filearea
|
|
|
|
* @return string protocol relative URL or null if not present
|
|
|
|
*/
|
|
|
|
public function setting_file_url($setting, $filearea) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if (empty($this->settings->$setting)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$component = 'theme_'.$this->name;
|
|
|
|
$itemid = theme_get_revision();
|
|
|
|
$filepath = $this->settings->$setting;
|
|
|
|
$syscontext = context_system::instance();
|
|
|
|
|
|
|
|
$url = moodle_url::make_file_url("$CFG->wwwroot/pluginfile.php", "/$syscontext->id/$component/$filearea/$itemid".$filepath);
|
|
|
|
|
|
|
|
// Now this is tricky because the we can not hardcode http or https here, lets use the relative link.
|
|
|
|
// Note: unfortunately moodle_url does not support //urls yet.
|
|
|
|
|
|
|
|
$url = preg_replace('|^https?://|i', '//', $url->out(false));
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Serve the theme setting file.
|
|
|
|
*
|
|
|
|
* @param string $filearea
|
|
|
|
* @param array $args
|
|
|
|
* @param bool $forcedownload
|
|
|
|
* @param array $options
|
|
|
|
* @return bool may terminate if file not found or donotdie not specified
|
|
|
|
*/
|
|
|
|
public function setting_file_serve($filearea, $args, $forcedownload, $options) {
|
|
|
|
global $CFG;
|
|
|
|
require_once("$CFG->libdir/filelib.php");
|
|
|
|
|
|
|
|
$syscontext = context_system::instance();
|
|
|
|
$component = 'theme_'.$this->name;
|
|
|
|
|
|
|
|
$revision = array_shift($args);
|
|
|
|
if ($revision < 0) {
|
|
|
|
$lifetime = 0;
|
|
|
|
} else {
|
|
|
|
$lifetime = 60*60*24*60;
|
2014-11-09 08:06:46 +01:00
|
|
|
// By default, theme files must be cache-able by both browsers and proxies.
|
|
|
|
if (!array_key_exists('cacheability', $options)) {
|
|
|
|
$options['cacheability'] = 'public';
|
|
|
|
}
|
2013-04-10 10:57:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$fs = get_file_storage();
|
|
|
|
$relativepath = implode('/', $args);
|
|
|
|
|
|
|
|
$fullpath = "/{$syscontext->id}/{$component}/{$filearea}/0/{$relativepath}";
|
|
|
|
$fullpath = rtrim($fullpath, '/');
|
|
|
|
if ($file = $fs->get_file_by_hash(sha1($fullpath))) {
|
|
|
|
send_stored_file($file, $lifetime, 0, $forcedownload, $options);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
send_file_not_found();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Resolves the real image location.
|
2012-09-27 10:58:42 +12:00
|
|
|
*
|
|
|
|
* $svg was introduced as an arg in 2.4. It is important because not all supported browsers support the use of SVG
|
|
|
|
* and we need a way in which to turn it off.
|
|
|
|
* By default SVG won't be used unless asked for. This is done for two reasons:
|
|
|
|
* 1. It ensures that we don't serve svg images unless we really want to. The admin has selected to force them, of the users
|
|
|
|
* browser supports SVG.
|
|
|
|
* 2. We only serve SVG images from locations we trust. This must NOT include any areas where the image may have been uploaded
|
|
|
|
* by the user due to security concerns.
|
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $image name of image, may contain relative path
|
|
|
|
* @param string $component
|
2012-09-27 10:58:42 +12:00
|
|
|
* @param bool $svg If set to true SVG images will also be looked for.
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return string full file path
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2012-09-27 10:58:42 +12:00
|
|
|
public function resolve_image_location($image, $component, $svg = false) {
|
2009-12-16 18:00:58 +00:00
|
|
|
global $CFG;
|
|
|
|
|
2012-09-27 10:58:42 +12:00
|
|
|
if (!is_bool($svg)) {
|
|
|
|
// If $svg isn't a bool then we need to decide for ourselves.
|
|
|
|
$svg = $this->use_svg_icons();
|
|
|
|
}
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
if ($component === 'moodle' or $component === 'core' or empty($component)) {
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$this->dir/pix_core/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$parent_config->dir/pix_core/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
}
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$CFG->dataroot/pix/$image", $svg)) {
|
2012-04-05 08:50:16 -04:00
|
|
|
return $imagefile;
|
|
|
|
}
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$CFG->dirroot/pix/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
} else if ($component === 'theme') { //exception
|
|
|
|
if ($image === 'favicon') {
|
|
|
|
return "$this->dir/pix/favicon.ico";
|
|
|
|
}
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$this->dir/pix/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$parent_config->dir/pix/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (strpos($component, '_') === false) {
|
|
|
|
$component = 'mod_'.$component;
|
|
|
|
}
|
|
|
|
list($type, $plugin) = explode('_', $component, 2);
|
|
|
|
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$this->dir/pix_plugins/$type/$plugin/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // base first, the immediate parent last
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$parent_config->dir/pix_plugins/$type/$plugin/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
}
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$CFG->dataroot/pix_plugins/$type/$plugin/$image", $svg)) {
|
2012-04-05 08:50:16 -04:00
|
|
|
return $imagefile;
|
|
|
|
}
|
2013-07-16 22:38:38 +02:00
|
|
|
$dir = core_component::get_plugin_directory($type, $plugin);
|
2012-09-27 10:58:42 +12:00
|
|
|
if ($imagefile = $this->image_exists("$dir/pix/$image", $svg)) {
|
2009-12-16 18:00:58 +00:00
|
|
|
return $imagefile;
|
|
|
|
}
|
|
|
|
return null;
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-19 11:53:16 +02:00
|
|
|
/**
|
|
|
|
* Resolves the real font location.
|
|
|
|
*
|
|
|
|
* @param string $font name of font file
|
|
|
|
* @param string $component
|
|
|
|
* @return string full file path
|
|
|
|
*/
|
|
|
|
public function resolve_font_location($font, $component) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if ($component === 'moodle' or $component === 'core' or empty($component)) {
|
|
|
|
if (file_exists("$this->dir/fonts_core/$font")) {
|
|
|
|
return "$this->dir/fonts_core/$font";
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // Base first, the immediate parent last.
|
|
|
|
if (file_exists("$parent_config->dir/fonts_core/$font")) {
|
|
|
|
return "$parent_config->dir/fonts_core/$font";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (file_exists("$CFG->dataroot/fonts/$font")) {
|
|
|
|
return "$CFG->dataroot/fonts/$font";
|
|
|
|
}
|
|
|
|
if (file_exists("$CFG->dirroot/lib/fonts/$font")) {
|
|
|
|
return "$CFG->dirroot/lib/fonts/$font";
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
} else if ($component === 'theme') { // Exception.
|
|
|
|
if (file_exists("$this->dir/fonts/$font")) {
|
|
|
|
return "$this->dir/fonts/$font";
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // Base first, the immediate parent last.
|
|
|
|
if (file_exists("$parent_config->dir/fonts/$font")) {
|
|
|
|
return "$parent_config->dir/fonts/$font";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (strpos($component, '_') === false) {
|
|
|
|
$component = 'mod_'.$component;
|
|
|
|
}
|
|
|
|
list($type, $plugin) = explode('_', $component, 2);
|
|
|
|
|
|
|
|
if (file_exists("$this->dir/fonts_plugins/$type/$plugin/$font")) {
|
|
|
|
return "$this->dir/fonts_plugins/$type/$plugin/$font";
|
|
|
|
}
|
|
|
|
foreach (array_reverse($this->parent_configs) as $parent_config) { // Base first, the immediate parent last.
|
|
|
|
if (file_exists("$parent_config->dir/fonts_plugins/$type/$plugin/$font")) {
|
|
|
|
return "$parent_config->dir/fonts_plugins/$type/$plugin/$font";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (file_exists("$CFG->dataroot/fonts_plugins/$type/$plugin/$font")) {
|
|
|
|
return "$CFG->dataroot/fonts_plugins/$type/$plugin/$font";
|
|
|
|
}
|
|
|
|
$dir = core_component::get_plugin_directory($type, $plugin);
|
|
|
|
if (file_exists("$dir/fonts/$font")) {
|
|
|
|
return "$dir/fonts/$font";
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-27 10:58:42 +12:00
|
|
|
/**
|
|
|
|
* Return true if we should look for SVG images as well.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function use_svg_icons() {
|
|
|
|
global $CFG;
|
|
|
|
if ($this->usesvg === null) {
|
2013-07-30 17:00:54 +12:00
|
|
|
|
2015-08-24 10:59:30 +08:00
|
|
|
if (!isset($CFG->svgicons)) {
|
2013-07-30 17:00:54 +12:00
|
|
|
$this->usesvg = core_useragent::supports_svg();
|
2012-09-27 10:58:42 +12:00
|
|
|
} else {
|
|
|
|
// Force them on/off depending upon the setting.
|
2015-08-24 10:59:30 +08:00
|
|
|
$this->usesvg = (bool)$CFG->svgicons;
|
2012-09-27 10:58:42 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $this->usesvg;
|
|
|
|
}
|
|
|
|
|
2012-10-03 08:32:40 +13:00
|
|
|
/**
|
|
|
|
* 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.
|
2012-11-28 18:15:54 +13:00
|
|
|
* DO NOT ABUSE THIS FUNCTION... not that you'd want to right ;)
|
2012-10-03 08:32:40 +13:00
|
|
|
*
|
|
|
|
* @param bool $setting True to force the use of svg when available, null otherwise.
|
|
|
|
*/
|
2012-11-28 18:15:54 +13:00
|
|
|
public function force_svg_use($setting) {
|
2012-10-03 08:32:40 +13:00
|
|
|
$this->usesvg = (bool)$setting;
|
|
|
|
}
|
|
|
|
|
2009-07-09 07:35:03 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Checks if file with any image extension exists.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2012-09-27 10:58:42 +12:00
|
|
|
* The order to these images was adjusted prior to the release of 2.4
|
|
|
|
* At that point the were the following image counts in Moodle core:
|
|
|
|
*
|
|
|
|
* - png = 667 in pix dirs (1499 total)
|
|
|
|
* - gif = 385 in pix dirs (606 total)
|
|
|
|
* - jpg = 62 in pix dirs (74 total)
|
|
|
|
* - jpeg = 0 in pix dirs (1 total)
|
|
|
|
*
|
|
|
|
* There is work in progress to move towards SVG presently hence that has been prioritiesed.
|
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $filepath
|
2012-09-27 10:58:42 +12:00
|
|
|
* @param bool $svg If set to true SVG images will also be looked for.
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return string image name with extension
|
2009-07-09 07:35:03 +00:00
|
|
|
*/
|
2012-09-27 10:58:42 +12:00
|
|
|
private static function image_exists($filepath, $svg = false) {
|
|
|
|
if ($svg && file_exists("$filepath.svg")) {
|
|
|
|
return "$filepath.svg";
|
2009-12-16 18:00:58 +00:00
|
|
|
} else if (file_exists("$filepath.png")) {
|
|
|
|
return "$filepath.png";
|
2012-09-27 10:58:42 +12:00
|
|
|
} else if (file_exists("$filepath.gif")) {
|
|
|
|
return "$filepath.gif";
|
2009-12-16 18:00:58 +00:00
|
|
|
} else if (file_exists("$filepath.jpg")) {
|
|
|
|
return "$filepath.jpg";
|
|
|
|
} else if (file_exists("$filepath.jpeg")) {
|
|
|
|
return "$filepath.jpeg";
|
2009-07-09 07:35:03 +00:00
|
|
|
} else {
|
2009-12-16 18:00:58 +00:00
|
|
|
return false;
|
2009-07-09 07:35:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Loads the theme config from config.php file.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $themename
|
2012-01-05 13:27:54 +13:00
|
|
|
* @param stdClass $settings from config_plugins table
|
2013-10-09 16:58:37 +08:00
|
|
|
* @param boolean $parentscheck true to also check the parents. .
|
2012-01-05 13:27:54 +13:00
|
|
|
* @return stdClass The theme configuration
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2013-10-09 16:58:37 +08:00
|
|
|
private static function find_theme_config($themename, $settings, $parentscheck = true) {
|
2009-12-16 18:00:58 +00:00
|
|
|
// We have to use the variable name $THEME (upper case) because that
|
|
|
|
// is what is used in theme config.php files.
|
2009-07-07 05:05:06 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
if (!$dir = theme_config::find_theme_location($themename)) {
|
|
|
|
return null;
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
2009-12-16 22:22:37 +00:00
|
|
|
|
2010-09-21 08:07:44 +00:00
|
|
|
$THEME = new stdClass();
|
2009-12-16 18:00:58 +00:00
|
|
|
$THEME->name = $themename;
|
|
|
|
$THEME->dir = $dir;
|
|
|
|
$THEME->settings = $settings;
|
|
|
|
|
|
|
|
global $CFG; // just in case somebody tries to use $CFG in theme config
|
|
|
|
include("$THEME->dir/config.php");
|
|
|
|
|
|
|
|
// verify the theme configuration is OK
|
|
|
|
if (!is_array($THEME->parents)) {
|
|
|
|
// parents option is mandatory now
|
|
|
|
return null;
|
2013-10-09 16:58:37 +08:00
|
|
|
} else {
|
|
|
|
// We use $parentscheck to only check the direct parents (avoid infinite loop).
|
|
|
|
if ($parentscheck) {
|
|
|
|
// Find all parent theme configs.
|
|
|
|
foreach ($THEME->parents as $parent) {
|
|
|
|
$parentconfig = theme_config::find_theme_config($parent, $settings, false);
|
|
|
|
if (empty($parentconfig)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
return $THEME;
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 07:35:03 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Finds the theme location and verifies the theme has all needed files
|
|
|
|
* and is not obsoleted.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $themename
|
|
|
|
* @return string full dir path or null if not found
|
2009-07-09 07:35:03 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
private static function find_theme_location($themename) {
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if (file_exists("$CFG->dirroot/theme/$themename/config.php")) {
|
|
|
|
$dir = "$CFG->dirroot/theme/$themename";
|
2009-07-09 07:35:03 +00:00
|
|
|
|
2011-04-26 22:56:32 +02:00
|
|
|
} else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$themename/config.php")) {
|
|
|
|
$dir = "$CFG->themedir/$themename";
|
|
|
|
|
2009-09-30 16:24:05 +00:00
|
|
|
} else {
|
2009-12-16 18:00:58 +00:00
|
|
|
return null;
|
2009-07-09 07:35:03 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
|
|
|
|
if (file_exists("$dir/styles.php")) {
|
|
|
|
//legacy theme - needs to be upgraded - upgrade info is displayed on the admin settings page
|
|
|
|
return null;
|
|
|
|
}
|
2009-12-16 22:22:37 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
return $dir;
|
2009-07-09 07:35:03 +00:00
|
|
|
}
|
|
|
|
|
2009-07-16 10:50:19 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Get the renderer for a part of Moodle for this theme.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param moodle_page $page the page we are rendering
|
2012-02-14 18:24:09 +13:00
|
|
|
* @param string $component the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'.
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
|
2009-12-17 22:43:27 +00:00
|
|
|
* @param string $target one of rendering target constants
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return renderer_base the requested renderer.
|
2009-07-16 10:50:19 +00:00
|
|
|
*/
|
2009-12-17 22:43:27 +00:00
|
|
|
public function get_renderer(moodle_page $page, $component, $subtype = null, $target = null) {
|
2009-12-16 18:00:58 +00:00
|
|
|
if (is_null($this->rf)) {
|
2009-12-17 22:43:27 +00:00
|
|
|
$classname = $this->rendererfactory;
|
2009-12-16 18:00:58 +00:00
|
|
|
$this->rf = new $classname($this);
|
2009-07-16 10:50:19 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
|
2009-12-17 22:43:27 +00:00
|
|
|
return $this->rf->get_renderer($page, $component, $subtype, $target);
|
2009-07-16 10:50:19 +00:00
|
|
|
}
|
|
|
|
|
2009-07-07 05:05:06 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Get the information from {@link $layouts} for this type of page.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $pagelayout the the page layout name.
|
|
|
|
* @return array the appropriate part of {@link $layouts}.
|
2009-07-07 05:05:06 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
protected function layout_info_for_page($pagelayout) {
|
|
|
|
if (array_key_exists($pagelayout, $this->layouts)) {
|
|
|
|
return $this->layouts[$pagelayout];
|
|
|
|
} else {
|
2009-12-27 12:02:04 +00:00
|
|
|
debugging('Invalid page layout specified: ' . $pagelayout);
|
|
|
|
return $this->layouts['standard'];
|
2009-07-07 05:05:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Given the settings of this theme, and the page pagelayout, return the
|
|
|
|
* full path of the page layout file to use.
|
|
|
|
*
|
|
|
|
* Used by {@link core_renderer::header()}.
|
|
|
|
*
|
|
|
|
* @param string $pagelayout the the page layout name.
|
|
|
|
* @return string Full path to the lyout file to use
|
2009-07-02 08:49:25 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public function layout_file($pagelayout) {
|
2009-07-02 08:49:25 +00:00
|
|
|
global $CFG;
|
2009-07-07 05:05:06 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
$layoutinfo = $this->layout_info_for_page($pagelayout);
|
|
|
|
$layoutfile = $layoutinfo['file'];
|
2009-07-07 05:05:06 +00:00
|
|
|
|
2010-04-15 06:37:55 +00:00
|
|
|
if (array_key_exists('theme', $layoutinfo)) {
|
|
|
|
$themes = array($layoutinfo['theme']);
|
|
|
|
} else {
|
|
|
|
$themes = array_merge(array($this->name),$this->parents);
|
|
|
|
}
|
2010-04-15 14:43:25 +00:00
|
|
|
|
2010-04-15 06:37:55 +00:00
|
|
|
foreach ($themes as $theme) {
|
|
|
|
if ($dir = $this->find_theme_location($theme)) {
|
|
|
|
$path = "$dir/layout/$layoutfile";
|
|
|
|
|
|
|
|
// Check the template exists, return general base theme template if not.
|
|
|
|
if (is_readable($path)) {
|
|
|
|
return $path;
|
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
|
|
|
|
2009-12-27 12:02:04 +00:00
|
|
|
debugging('Can not find layout file for: ' . $pagelayout);
|
2009-12-16 18:00:58 +00:00
|
|
|
// fallback to standard normal layout
|
|
|
|
return "$CFG->dirroot/theme/base/layout/general.php";
|
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
|
|
|
* Returns auxiliary page layout options specified in layout configuration array.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $pagelayout
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function pagelayout_options($pagelayout) {
|
|
|
|
$info = $this->layout_info_for_page($pagelayout);
|
|
|
|
if (!empty($info['options'])) {
|
|
|
|
return $info['options'];
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
return array();
|
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-12-16 18:00:58 +00:00
|
|
|
/**
|
|
|
|
* Inform a block_manager about the block regions this theme wants on this
|
|
|
|
* page layout.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @param string $pagelayout the general type of the page.
|
|
|
|
* @param block_manager $blockmanager the block_manger to set up.
|
|
|
|
*/
|
|
|
|
public function setup_blocks($pagelayout, $blockmanager) {
|
|
|
|
$layoutinfo = $this->layout_info_for_page($pagelayout);
|
|
|
|
if (!empty($layoutinfo['regions'])) {
|
2014-03-31 11:46:18 +13:00
|
|
|
$blockmanager->add_regions($layoutinfo['regions'], false);
|
2009-12-16 18:00:58 +00:00
|
|
|
$blockmanager->set_default_region($layoutinfo['defaultregion']);
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
|
|
|
|
2012-01-05 13:27:54 +13:00
|
|
|
/**
|
|
|
|
* Gets the visible name for the requested block region.
|
|
|
|
*
|
|
|
|
* @param string $region The region name to get
|
|
|
|
* @param string $theme The theme the region belongs to (may come from the parent theme)
|
|
|
|
* @return string
|
|
|
|
*/
|
2010-01-21 11:07:15 +00:00
|
|
|
protected function get_region_name($region, $theme) {
|
|
|
|
$regionstring = get_string('region-' . $region, 'theme_' . $theme);
|
|
|
|
// A name exists in this theme, so use it
|
|
|
|
if (substr($regionstring, 0, 1) != '[') {
|
|
|
|
return $regionstring;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, try to find one elsewhere
|
|
|
|
// Check parents, if any
|
|
|
|
foreach ($this->parents as $parentthemename) {
|
|
|
|
$regionstring = get_string('region-' . $region, 'theme_' . $parentthemename);
|
|
|
|
if (substr($regionstring, 0, 1) != '[') {
|
|
|
|
return $regionstring;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Last resort, try the base theme for names
|
|
|
|
return get_string('region-' . $region, 'theme_base');
|
|
|
|
}
|
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2009-12-16 18:00:58 +00:00
|
|
|
* Get the list of all block regions known to this theme in all templates.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-12-16 18:00:58 +00:00
|
|
|
* @return array internal region name => human readable name.
|
2009-07-02 08:49:25 +00:00
|
|
|
*/
|
2009-12-16 18:00:58 +00:00
|
|
|
public function get_all_block_regions() {
|
|
|
|
$regions = array();
|
|
|
|
foreach ($this->layouts as $layoutinfo) {
|
|
|
|
foreach ($layoutinfo['regions'] as $region) {
|
2010-04-21 07:05:39 +00:00
|
|
|
$regions[$region] = $this->get_region_name($region, $this->name);
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
2009-12-16 18:00:58 +00:00
|
|
|
return $regions;
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
2011-08-10 12:56:04 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the human readable name of the theme
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function get_theme_name() {
|
|
|
|
return get_string('pluginname', 'theme_'.$this->name);
|
|
|
|
}
|
2014-02-24 10:38:17 +13:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the block render method.
|
|
|
|
*
|
|
|
|
* It is set by the theme via:
|
|
|
|
* $THEME->blockrendermethod = '...';
|
|
|
|
*
|
|
|
|
* It can be one of two values, blocks or blocks_for_region.
|
|
|
|
* It should be set to the method being used by the theme layouts.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function get_block_render_method() {
|
|
|
|
if ($this->blockrendermethod) {
|
|
|
|
// Return the specified block render method.
|
|
|
|
return $this->blockrendermethod;
|
|
|
|
}
|
|
|
|
// Its not explicitly set, check the parent theme configs.
|
|
|
|
foreach ($this->parent_configs as $config) {
|
|
|
|
if (isset($config->blockrendermethod)) {
|
|
|
|
return $config->blockrendermethod;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Default it to blocks.
|
|
|
|
return 'blocks';
|
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* This class keeps track of which HTML tags are currently open.
|
|
|
|
*
|
|
|
|
* This makes it much easier to always generate well formed XHTML output, even
|
|
|
|
* if execution terminates abruptly. Any time you output some opening HTML
|
|
|
|
* without the matching closing HTML, you should push the necessary close tags
|
|
|
|
* onto the stack.
|
2009-07-02 08:49:25 +00:00
|
|
|
*
|
|
|
|
* @copyright 2009 Tim Hunt
|
2012-01-05 13:27:54 +13:00
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
|
* @since Moodle 2.0
|
2012-02-14 18:24:09 +13:00
|
|
|
* @package core
|
2012-01-11 10:40:55 +13:00
|
|
|
* @category output
|
2009-07-02 08:49:25 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
class xhtml_container_stack {
|
2012-01-05 13:27:54 +13:00
|
|
|
|
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array Stores the list of open containers.
|
2012-01-05 13:27:54 +13:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
protected $opencontainers = array();
|
2012-01-05 13:27:54 +13:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var array In developer debug mode, stores a stack trace of all opens and
|
2009-08-10 06:22:04 +00:00
|
|
|
* closes, so we can output helpful error messages when there is a mismatch.
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
protected $log = array();
|
2012-01-05 13:27:54 +13:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2012-01-11 10:40:55 +13:00
|
|
|
* @var boolean Store whether we are developer debug mode. We need this in
|
|
|
|
* several places including in the destructor where we may not have access to $CFG.
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
protected $isdebugging;
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2012-01-05 13:27:54 +13:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
public function __construct() {
|
2013-08-10 22:46:49 +02:00
|
|
|
global $CFG;
|
|
|
|
$this->isdebugging = $CFG->debugdeveloper;
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* Push the close HTML for a recently opened container onto the stack.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-08-10 06:22:04 +00:00
|
|
|
* @param string $type The type of container. This is checked when {@link pop()}
|
|
|
|
* is called and must match, otherwise a developer debug warning is output.
|
|
|
|
* @param string $closehtml The HTML required to close the container.
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
public function push($type, $closehtml) {
|
|
|
|
$container = new stdClass;
|
|
|
|
$container->type = $type;
|
|
|
|
$container->closehtml = $closehtml;
|
|
|
|
if ($this->isdebugging) {
|
|
|
|
$this->log('Open', $type);
|
2009-07-02 09:28:19 +00:00
|
|
|
}
|
2009-08-10 06:22:04 +00:00
|
|
|
array_push($this->opencontainers, $container);
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* Pop the HTML for the next closing container from the stack. The $type
|
|
|
|
* must match the type passed when the container was opened, otherwise a
|
|
|
|
* warning will be output.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-08-10 06:22:04 +00:00
|
|
|
* @param string $type The type of container.
|
|
|
|
* @return string the HTML required to close the container.
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
public function pop($type) {
|
|
|
|
if (empty($this->opencontainers)) {
|
|
|
|
debugging('<p>There are no more open containers. This suggests there is a nesting problem.</p>' .
|
|
|
|
$this->output_log(), DEBUG_DEVELOPER);
|
|
|
|
return;
|
2009-07-02 09:28:19 +00:00
|
|
|
}
|
2009-07-02 08:49:25 +00:00
|
|
|
|
2009-08-10 06:22:04 +00:00
|
|
|
$container = array_pop($this->opencontainers);
|
|
|
|
if ($container->type != $type) {
|
|
|
|
debugging('<p>The type of container to be closed (' . $container->type .
|
|
|
|
') does not match the type of the next open container (' . $type .
|
|
|
|
'). This suggests there is a nesting problem.</p>' .
|
|
|
|
$this->output_log(), DEBUG_DEVELOPER);
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-08-10 06:22:04 +00:00
|
|
|
if ($this->isdebugging) {
|
|
|
|
$this->log('Close', $type);
|
2009-06-29 07:19:05 +00:00
|
|
|
}
|
2009-08-10 06:22:04 +00:00
|
|
|
return $container->closehtml;
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-29 07:19:05 +00:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* Close all but the last open container. This is useful in places like error
|
|
|
|
* handling, where you want to close all the open containers (apart from <body>)
|
|
|
|
* before outputting the error message.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-08-10 06:22:04 +00:00
|
|
|
* @param bool $shouldbenone assert that the stack should be empty now - causes a
|
|
|
|
* developer debug warning if it isn't.
|
|
|
|
* @return string the HTML required to close any open containers inside <body>.
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
public function pop_all_but_last($shouldbenone = false) {
|
|
|
|
if ($shouldbenone && count($this->opencontainers) != 1) {
|
|
|
|
debugging('<p>Some HTML tags were opened in the body of the page but not closed.</p>' .
|
|
|
|
$this->output_log(), DEBUG_DEVELOPER);
|
|
|
|
}
|
|
|
|
$output = '';
|
|
|
|
while (count($this->opencontainers) > 1) {
|
|
|
|
$container = array_pop($this->opencontainers);
|
|
|
|
$output .= $container->closehtml;
|
2009-06-29 07:19:05 +00:00
|
|
|
}
|
2009-08-10 06:22:04 +00:00
|
|
|
return $output;
|
2009-06-29 07:19:05 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-02 08:49:25 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* You can call this function if you want to throw away an instance of this
|
|
|
|
* class without properly emptying the stack (for example, in a unit test).
|
|
|
|
* Calling this method stops the destruct method from outputting a developer
|
|
|
|
* debug warning. After calling this method, the instance can no longer be used.
|
2009-07-02 08:49:25 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
public function discard() {
|
|
|
|
$this->opencontainers = null;
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-08-10 06:22:04 +00:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* Adds an entry to the log.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-08-10 06:22:04 +00:00
|
|
|
* @param string $action The name of the action
|
|
|
|
* @param string $type The type of action
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
protected function log($action, $type) {
|
|
|
|
$this->log[] = '<li>' . $action . ' ' . $type . ' at:' .
|
|
|
|
format_backtrace(debug_backtrace()) . '</li>';
|
2009-07-02 08:49:25 +00:00
|
|
|
}
|
2009-06-26 09:06:16 +00:00
|
|
|
|
2009-07-23 02:33:58 +00:00
|
|
|
/**
|
2009-08-10 06:22:04 +00:00
|
|
|
* Outputs the log's contents as a HTML list.
|
2012-01-05 13:27:54 +13:00
|
|
|
*
|
2009-08-10 06:22:04 +00:00
|
|
|
* @return string HTML list of the log
|
2009-07-23 02:33:58 +00:00
|
|
|
*/
|
2009-08-10 06:22:04 +00:00
|
|
|
protected function output_log() {
|
|
|
|
return '<ul>' . implode("\n", $this->log) . '</ul>';
|
2009-06-26 09:06:16 +00:00
|
|
|
}
|
2012-03-12 12:38:53 -06:00
|
|
|
}
|