Commit | Line | Data |
---|---|---|
571fa828 | 1 | <?php |
2 | ||
3 | // This file is part of Moodle - http://moodle.org/ | |
4 | // | |
5 | // Moodle is free software: you can redistribute it and/or modify | |
6 | // it under the terms of the GNU General Public License as published by | |
7 | // the Free Software Foundation, either version 3 of the License, or | |
8 | // (at your option) any later version. | |
9 | // | |
10 | // Moodle is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | // GNU General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU General Public License | |
16 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
f8065dd2 | 18 | /** |
19 | * This constant is used for html attributes which need to have an empty | |
20 | * value and still be output by the renderers (e.g. alt=""); | |
21 | * | |
22 | * @constant @EMPTY@ | |
23 | */ | |
24 | define('HTML_ATTR_EMPTY', '@EMPTY@'); | |
571fa828 | 25 | |
d9c8f425 | 26 | require_once($CFG->libdir.'/outputcomponents.php'); |
27 | require_once($CFG->libdir.'/outputactions.php'); | |
28 | require_once($CFG->libdir.'/outputfactories.php'); | |
d9c8f425 | 29 | require_once($CFG->libdir.'/outputrenderers.php'); |
30 | ||
571fa828 | 31 | /** |
32 | * Functions for generating the HTML that Moodle should output. | |
33 | * | |
34 | * Please see http://docs.moodle.org/en/Developement:How_Moodle_outputs_HTML | |
35 | * for an overview. | |
36 | * | |
37 | * @package moodlecore | |
38 | * @copyright 2009 Tim Hunt | |
b7009474 | 39 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
571fa828 | 40 | */ |
41 | ||
571fa828 | 42 | /** |
fdeb7fa1 | 43 | * This class represents the configuration variables of a Moodle theme. |
44 | * | |
45 | * All the variables with access: public below (with a few exceptions that are marked) | |
46 | * are the properties you can set in your theme's config.php file. | |
47 | * | |
48 | * There are also some methods and protected variables that are part of the inner | |
49 | * workings of Moodle's themes system. If you are just editing a theme's config.php | |
fa1afe32 | 50 | * file, you can just ignore those, and the following information for developers. |
ebebf55c | 51 | * |
52 | * Normally, to create an instance of this class, you should use the | |
53 | * {@link theme_config::load()} factory method to load a themes config.php file. | |
fa1afe32 | 54 | * However, normally you don't need to bother, because moodle_page (that is, $PAGE) |
fdeb7fa1 | 55 | * will create one for you, accessible as $PAGE->theme. |
571fa828 | 56 | * |
57 | * @copyright 2009 Tim Hunt | |
58 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
59 | * @since Moodle 2.0 | |
60 | */ | |
ebebf55c | 61 | class theme_config { |
62 | /** | |
fdeb7fa1 | 63 | * @var string the name of this theme. Set automatically when this theme is |
64 | * loaded. Please do not try to set this in your theme's config.php file. | |
ebebf55c | 65 | */ |
fdeb7fa1 | 66 | public $name; |
571fa828 | 67 | |
fdeb7fa1 | 68 | /** |
69 | * @var string the folder where this themes files are stored. This is set | |
70 | * automatically when the theme is loaded to $CFG->themedir . '/' . $this->name. | |
71 | * Please do not try to set this in your theme's config.php file. | |
72 | */ | |
73 | public $dir; | |
8954245a | 74 | |
fdeb7fa1 | 75 | /** |
76 | * @var array The names of all the stylesheets from this theme that you would | |
77 | * like included, in order. Give the names of the files without .css. | |
78 | */ | |
79 | public $sheets = array('styles_layout', 'styles_fonts', 'styles_color'); | |
b7009474 | 80 | |
fdeb7fa1 | 81 | /** |
82 | * You can base your theme on another theme by linking to the other theme as | |
83 | * a parent. This lets you use the CSS from the other theme | |
d4a03c00 | 84 | * (see {@link $parentsheets}), or layout templates (see {@link $layouts}). |
fdeb7fa1 | 85 | * That makes it easy to create a new theme that is similar to another one |
86 | * but with a few changes. In this theme's CSS you only need to override | |
87 | * those rules you want to change. | |
88 | */ | |
89 | public $parent = null; | |
8954245a | 90 | |
fdeb7fa1 | 91 | /** |
92 | * @var boolean|array Whether and which stylesheets from the parent theme | |
93 | * to use in this theme. (Ignored if parent is null) | |
94 | * | |
fa1afe32 | 95 | * Possible values are: |
fdeb7fa1 | 96 | * false - no parent theme CSS. |
97 | * true - include all the normal parent theme CSS. Currently this means | |
98 | * array('styles_layout', 'styles_fonts', 'styles_color'). | |
99 | * array - include just the listed stylesheets. Give the files names | |
100 | * without the .css, as in the above example. | |
101 | */ | |
102 | public $parentsheets = false; | |
571fa828 | 103 | |
fdeb7fa1 | 104 | /** |
105 | * @var boolean|array Whether and which stylesheets from the standard theme | |
106 | * to use in this theme. | |
107 | * | |
108 | * The advantages of using the standard stylesheets in your theme is that | |
109 | * they give you a good basic layout, and when the Moodle core code is | |
110 | * updated with new features, the standard theme CSS will be updated to match | |
111 | * the changes in the code. Therefore, your theme is less likely to break | |
112 | * when you upgrade Moodle. | |
113 | * | |
fa1afe32 | 114 | * Possible values are: |
fdeb7fa1 | 115 | * false - no standard theme CSS. |
116 | * true - include all the main standard theme CSS. Currently this means | |
117 | * array('styles_layout', 'styles_fonts', 'styles_color'). | |
118 | * array - include just the listed stylesheets. Give the files names | |
119 | * without the .css, as in the above example. | |
120 | */ | |
121 | public $standardsheets = true; | |
571fa828 | 122 | |
fdeb7fa1 | 123 | /** |
124 | * @var array use the CSS fragments from these types of plugins. | |
125 | * | |
126 | * All the plugins of the given types will be searched for a file called | |
127 | * styles.php and, if found, these will be included with the CSS for this theme. | |
128 | * | |
129 | * This allows modules to provide some basic CSS so they work out of the box. | |
130 | * You are strongly advised to leave this enabled, otherwise you will have to | |
131 | * provide styling in your theme for every installed block, activity, course | |
132 | * format, ... in your Moodle site. | |
133 | * | |
134 | * This setting is an array of plugin types, as in the {@link get_plugin_types()} | |
135 | * function. The default value has been chosen to be the same as Moodle 1.9. | |
136 | * This is not necessarily the best choice. | |
137 | * | |
138 | * The plugin CSS is included first, before any theme CSS. To be precise, | |
fa1afe32 | 139 | * if $standardsheets is true, the plugin CSS is included with the |
fdeb7fa1 | 140 | * standard theme's CSS, otherwise if $parentsheets is true, the plugin CSS |
141 | * will be included with the parent theme's CSS, otherwise the plugin CSS | |
142 | * will be include with this theme's CSS. | |
143 | */ | |
144 | public $pluginsheets = array('mod', 'block', 'format', 'gradereport'); | |
571fa828 | 145 | |
fdeb7fa1 | 146 | /** |
147 | * @var boolean When this is true then Moodle will try to include a file | |
148 | * meta.php from this theme into the <head></head> part of the page. | |
149 | */ | |
ebebf55c | 150 | public $metainclude = false; |
571fa828 | 151 | |
fdeb7fa1 | 152 | /** |
153 | * @var boolean When this is true, and when this theme has a parent, then | |
154 | * Moodle will try to include a file meta.php from the parent theme into the | |
155 | * <head></head> part of the page. | |
156 | */ | |
ebebf55c | 157 | public $parentmetainclude = false; |
571fa828 | 158 | |
fdeb7fa1 | 159 | /** |
160 | * @var boolean When this is true then Moodle will try to include the file | |
161 | * meta.php from the standard theme into the <head></head> part of the page. | |
162 | */ | |
163 | public $standardmetainclude = true; | |
571fa828 | 164 | |
fdeb7fa1 | 165 | /** |
166 | * If true, then this theme must have a "pix" subdirectory that contains | |
167 | * copies of all files from the moodle/pix directory, plus a "pix/mod" | |
168 | * directory containing all the icons for all the activity modules. | |
169 | * | |
170 | * @var boolean | |
171 | */ | |
172 | public $custompix = false; | |
571fa828 | 173 | |
fdeb7fa1 | 174 | /** |
175 | * Which template to use for each general type of page. | |
176 | * | |
d4a03c00 | 177 | * This is an array of arrays. The keys of the outer array are the different |
178 | * types of page. Pages in Moodle are categorised into one of a short list of | |
179 | * types like 'normal', 'home', 'popup', 'form', .... The most reliable way | |
180 | * to get a complete list is to look at | |
181 | * {@link http://cvs.moodle.org/moodle/theme/standard/config.php?view=markup the standard theme config.php file}. | |
182 | * That file also has a good example of how to set this setting. | |
fdeb7fa1 | 183 | * |
fa1afe32 | 184 | * If Moodle encounters a general type of page that is not listed in your theme, |
d4a03c00 | 185 | * then it will use the first layout. Therefore, should probably put 'normal' |
186 | * first in this array. | |
fdeb7fa1 | 187 | * |
d4a03c00 | 188 | * For each page type, the value in the outer array is an array that describes |
189 | * how you want that type of page to look. For example | |
190 | * <pre> | |
191 | * $THEME->layouts = array( | |
192 | * // Most pages. Put this first, so if we encounter an unknown page type, this is used. | |
193 | * 'normal' => array( | |
194 | * 'layout' => 'parent:layout.php', | |
195 | * 'regions' => array('side-pre', 'side-post'), | |
196 | * 'defaultregion' => 'side-post' | |
197 | * ), | |
198 | * // The site home page. | |
199 | * 'home' => array( | |
200 | * 'layout' => 'layout-home.php', | |
201 | * 'regions' => array('side-pre', 'side-post'), | |
202 | * 'defaultregion' => 'side-post' | |
203 | * ), | |
204 | * // ... | |
205 | * ); | |
206 | * </pre> | |
fdeb7fa1 | 207 | * |
d4a03c00 | 208 | * 'layout' is the layout template to use for this type of page. You can |
209 | * specify this in one of three ways: | |
fdeb7fa1 | 210 | * <ol> |
d4a03c00 | 211 | * <li><b>filename</b> for example 'layout-home.php' as above. Use that file from this theme.</li> |
212 | * <li><b>parent:filename</b> for example 'parent:layout.php' as above. Use the | |
fdeb7fa1 | 213 | * specified file from the parent theme. (Obviously, you can only do this |
214 | * if this theme has a parent!)</li> | |
215 | * <li><b>standard:filename</b> for example 'standard:layout-popup.php'. Use | |
216 | * the specified file from the standard theme.</li> | |
217 | * </ol> | |
fa1afe32 | 218 | * To promote consistency, you are encouraged to call your layout files |
d4a03c00 | 219 | * layout.php or layout-something.php. |
fdeb7fa1 | 220 | * |
d4a03c00 | 221 | * 'regions' This lists the regions on the page where blocks may appear. For |
222 | * each region you list here, your layout file must include a call to | |
223 | * <pre> | |
224 | * echo $OUTPUT->blocks_for_region($regionname); | |
225 | * </pre> | |
226 | * or equivalent so that the blocks are actually visible. | |
fdeb7fa1 | 227 | * |
d4a03c00 | 228 | * 'defaultregion' If the list of regions is non-empty, then you must pick |
229 | * one of the one of them as 'default'. This has two meanings. First, this is | |
230 | * where new blocks are added. Second, if there are any blocks associated with | |
fa1afe32 | 231 | * the page, but in non-existent regions, they appear here. (Imaging, for example, |
d4a03c00 | 232 | * that someone added blocks using a different theme that used different region |
233 | * names, and then switched to this theme.) | |
fdeb7fa1 | 234 | * |
235 | * @var array | |
236 | */ | |
d4a03c00 | 237 | public $layouts = array(); |
571fa828 | 238 | |
74623e0a | 239 | /* |
40427883 | 240 | * Time in seconds to cache the CSS style sheets for the chosen theme |
74623e0a | 241 | * |
40427883 | 242 | * @var integer |
243 | */ | |
244 | public $csslifetime = 1800; | |
245 | ||
fdeb7fa1 | 246 | /** |
247 | * With this you can control the colours of the big MP3 player | |
248 | * that is used for MP3 resources. | |
249 | * | |
250 | * @var string | |
251 | */ | |
ebebf55c | 252 | public $resource_mp3player_colors = 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&font=Arial&fontColour=3333FF&buffer=10&waitForPlay=no&autoPlay=yes'; |
571fa828 | 253 | |
fdeb7fa1 | 254 | /** |
255 | * With this you can control the colours of the small MP3 player | |
256 | * that is used elsewhere | |
257 | *. | |
258 | * @var string | |
259 | */ | |
ebebf55c | 260 | public $filter_mediaplugin_colors = 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&waitForPlay=yes'; |
261 | ||
fdeb7fa1 | 262 | /** |
263 | *$THEME->rarrow = '►' //OR '→'; | |
264 | *$THEME->larrow = '◄' //OR '←'; | |
265 | *$CFG->block_search_button = link_arrow_right(get_string('search'), $url='', $accesshide=true); | |
266 | * | |
267 | * Accessibility: Right and left arrow-like characters are | |
268 | * used in the breadcrumb trail, course navigation menu | |
269 | * (previous/next activity), calendar, and search forum block. | |
270 | * | |
271 | * If the theme does not set characters, appropriate defaults | |
272 | * are set by (lib/weblib.php:check_theme_arrows). The suggestions | |
273 | * above are 'silent' in a screen-reader like JAWS. Please DO NOT | |
274 | * use < > » - these are confusing for blind users. | |
275 | */ | |
ebebf55c | 276 | |
fdeb7fa1 | 277 | /** |
278 | * Name of the renderer factory class to use. | |
279 | * | |
280 | * This is an advanced feature. Moodle output is generated by 'renderers', | |
281 | * you can customise the HTML that is output by writing custom renderers, | |
282 | * and then you need to specify 'renderer factory' so that Moodle can find | |
283 | * your renderers. | |
284 | * | |
285 | * There are some renderer factories supplied with Moodle. Please follow these | |
286 | * links to see what they do. | |
287 | * <ul> | |
288 | * <li>{@link standard_renderer_factory} - the default.</li> | |
289 | * <li>{@link theme_overridden_renderer_factory} - use this if you want to write | |
290 | * your own custom renderers in a renderers.php file in this theme (or the parent theme).</li> | |
291 | * <li>{@link template_renderer_factory} - highly experimental! Do not use (yet).</li> | |
292 | * </ul> | |
293 | * | |
294 | * @var string name of a class implementing the {@link renderer_factory} interface. | |
295 | */ | |
ebebf55c | 296 | public $rendererfactory = 'standard_renderer_factory'; |
ebebf55c | 297 | |
fdeb7fa1 | 298 | /** |
299 | * Name of the icon finder class to use. | |
300 | * | |
301 | * This is an advanced feature. controls how Moodle converts from the icon | |
302 | * names used in the code to URLs to embed in the HTML. You should not ever | |
303 | * need to change this. | |
304 | * | |
305 | * @var string name of a class implementing the {@link icon_finder} interface. | |
306 | */ | |
ebebf55c | 307 | public $iconfinder = 'pix_icon_finder'; |
571fa828 | 308 | |
309 | /** | |
fdeb7fa1 | 310 | * Function to do custom CSS processing. |
311 | * | |
312 | * This is an advanced feature. If you want to do custom processing on the | |
313 | * CSS before it is output (for example, to replace certain variable names | |
314 | * with particular values) you can give the name of a function here. | |
ebebf55c | 315 | * |
fa1afe32 | 316 | * There are two functions available that you may wish to use (defined in lib/outputlib.php): |
fdeb7fa1 | 317 | * <ul> |
318 | * <li>{@link output_css_replacing_constants}</li> | |
319 | * <li>{@link output_css_for_css_edit}</li> | |
320 | * </ul> | |
321 | * | |
322 | * If you wish to write your own function, look at those two as examples, | |
323 | * and it should be clear what you have to do. | |
ebebf55c | 324 | * |
325 | * @var string the name of a function. | |
571fa828 | 326 | */ |
ebebf55c | 327 | public $customcssoutputfunction = null; |
571fa828 | 328 | |
fdeb7fa1 | 329 | /** |
330 | * You can use this to control the cutoff point for strings | |
331 | * in the navmenus (list of activities in popup menu etc) | |
332 | * Default is 50 characters wide. | |
333 | */ | |
334 | public $navmenuwidth = 50; | |
335 | ||
336 | /** | |
337 | * By setting this to true, then you will have access to a | |
338 | * new variable in your header.html and footer.html called | |
339 | * $navmenulist ... this contains a simple XHTML menu of | |
340 | * all activities in the current course, mostly useful for | |
341 | * creating popup navigation menus and so on. | |
342 | */ | |
343 | public $makenavmenulist = false; | |
344 | ||
345 | /** | |
346 | * @var renderer_factory Instance of the renderer_factory implementation | |
347 | * we are using. Implementation detail. | |
348 | */ | |
349 | protected $rf = null; | |
350 | ||
351 | /** | |
352 | * @var renderer_factory Instance of the icon_finder implementation we are | |
353 | * using. Implementation detail. | |
354 | */ | |
355 | protected $if = null; | |
356 | ||
571fa828 | 357 | /** |
ebebf55c | 358 | * Load the config.php file for a particular theme, and return an instance |
359 | * of this class. (That is, this is a factory method.) | |
360 | * | |
361 | * @param string $themename the name of the theme. | |
362 | * @return theme_config an instance of this class. | |
571fa828 | 363 | */ |
ebebf55c | 364 | public static function load($themename) { |
365 | global $CFG; | |
571fa828 | 366 | |
fa1afe32 | 367 | // We have to use the variable name $THEME (upper case) because that |
ebebf55c | 368 | // is what is used in theme config.php files. |
369 | ||
370 | // Set some other standard properties of the theme. | |
371 | $THEME = new theme_config; | |
372 | $THEME->name = $themename; | |
373 | $THEME->dir = $CFG->themedir . '/' . $themename; | |
374 | ||
375 | // Load up the theme config | |
376 | $configfile = $THEME->dir . '/config.php'; | |
377 | if (!is_readable($configfile)) { | |
378 | throw new coding_exception('Cannot use theme ' . $themename . | |
379 | '. The file ' . $configfile . ' does not exist or is not readable.'); | |
571fa828 | 380 | } |
ebebf55c | 381 | include($configfile); |
382 | ||
383 | $THEME->update_legacy_information(); | |
384 | ||
385 | return $THEME; | |
571fa828 | 386 | } |
387 | ||
34a2777c | 388 | /** |
ebebf55c | 389 | * Get the renderer for a part of Moodle for this theme. |
390 | * @param string $module the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'. | |
391 | * @param moodle_page $page the page we are rendering | |
897b5c82 | 392 | * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news' |
fa1afe32 | 393 | * @return moodle_renderer_base the requested renderer. |
34a2777c | 394 | */ |
897b5c82 | 395 | public function get_renderer($module, $page, $subtype=null) { |
ebebf55c | 396 | if (is_null($this->rf)) { |
397 | if (CLI_SCRIPT) { | |
398 | $classname = 'cli_renderer_factory'; | |
399 | } else { | |
400 | $classname = $this->rendererfactory; | |
401 | } | |
402 | $this->rf = new $classname($this); | |
403 | } | |
404 | ||
897b5c82 | 405 | return $this->rf->get_renderer($module, $page, $subtype); |
34a2777c | 406 | } |
407 | ||
571fa828 | 408 | /** |
ebebf55c | 409 | * Get the renderer for a part of Moodle for this theme. |
410 | * @return moodle_renderer_base the requested renderer. | |
571fa828 | 411 | */ |
ebebf55c | 412 | protected function get_icon_finder() { |
413 | if (is_null($this->if)) { | |
414 | $classname = $this->iconfinder; | |
415 | $this->if = new $classname($this); | |
571fa828 | 416 | } |
ebebf55c | 417 | return $this->if; |
571fa828 | 418 | } |
419 | ||
420 | /** | |
fa1afe32 | 421 | * Return the URL for an icon identified as in pre-Moodle 2.0 code. |
ebebf55c | 422 | * |
423 | * Suppose you have old code like $url = "$CFG->pixpath/i/course.gif"; | |
424 | * then old_icon_url('i/course'); will return the equivalent URL that is correct now. | |
425 | * | |
fa1afe32 | 426 | * @param string $iconname the name of the icon. |
ebebf55c | 427 | * @return string the URL for that icon. |
571fa828 | 428 | */ |
ebebf55c | 429 | public function old_icon_url($iconname) { |
4096752d | 430 | return $this->get_icon_finder()->old_icon_url($iconname); |
571fa828 | 431 | } |
432 | ||
433 | /** | |
fa1afe32 | 434 | * Return the URL for an icon identified as in pre-Moodle 2.0 code. |
ebebf55c | 435 | * |
436 | * Suppose you have old code like $url = "$CFG->modpixpath/$mod/icon.gif"; | |
437 | * then mod_icon_url('icon', $mod); will return the equivalent URL that is correct now. | |
438 | * | |
fa1afe32 | 439 | * @param string $iconname the name of the icon. |
440 | * @param string $module the module the icon belongs to. | |
ebebf55c | 441 | * @return string the URL for that icon. |
571fa828 | 442 | */ |
ebebf55c | 443 | public function mod_icon_url($iconname, $module) { |
4096752d | 444 | return $this->get_icon_finder()->mod_icon_url($iconname, $module); |
571fa828 | 445 | } |
34a2777c | 446 | |
ebebf55c | 447 | /** |
448 | * Get the list of stylesheet URLs that need to go in the header for this theme. | |
449 | * @return array of URLs. | |
450 | */ | |
451 | public function get_stylesheet_urls() { | |
34a2777c | 452 | global $CFG; |
453 | ||
fdeb7fa1 | 454 | // We need to tell the CSS that is being included (for example the standard |
455 | // theme CSS) which theme it is being included for. Prepare the necessary param. | |
456 | $param = '?for=' . $this->name; | |
34a2777c | 457 | |
ebebf55c | 458 | // Stylesheets, in order (standard, parent, this - some of which may be the same). |
459 | $stylesheets = array(); | |
460 | if ($this->name != 'standard' && $this->standardsheets) { | |
fdeb7fa1 | 461 | $stylesheets[] = $CFG->httpsthemewww . '/standard/styles.php' . $param; |
ebebf55c | 462 | } |
463 | if (!empty($this->parent)) { | |
fdeb7fa1 | 464 | $stylesheets[] = $CFG->httpsthemewww . '/' . $this->parent . '/styles.php' . $param; |
34a2777c | 465 | } |
fdeb7fa1 | 466 | $stylesheets[] = $CFG->httpsthemewww . '/' . $this->name . '/styles.php' . $param; |
34a2777c | 467 | |
fdeb7fa1 | 468 | // Additional styles for right-to-left languages, if applicable. |
ebebf55c | 469 | if (right_to_left()) { |
470 | $stylesheets[] = $CFG->httpsthemewww . '/standard/rtl.css'; | |
34a2777c | 471 | |
ebebf55c | 472 | if (!empty($this->parent) && file_exists($CFG->themedir . '/' . $this->parent . '/rtl.css')) { |
473 | $stylesheets[] = $CFG->httpsthemewww . '/' . $this->parent . '/rtl.css'; | |
474 | } | |
34a2777c | 475 | |
ebebf55c | 476 | if (file_exists($this->dir . '/rtl.css')) { |
477 | $stylesheets[] = $CFG->httpsthemewww . '/' . $this->name . '/rtl.css'; | |
478 | } | |
34a2777c | 479 | } |
17a6649b | 480 | |
fdeb7fa1 | 481 | // If the theme wants pluginsheets, get them included in the first (most |
482 | // general) stylesheet we are including. That is, process them with the | |
483 | // standard CSS if we are using that, else with the parent CSS, else with | |
484 | // our own CSS. | |
485 | if (!empty($this->pluginsheets)) { | |
486 | $stylesheets[0] .= '&pluginsheets=1'; | |
487 | } | |
488 | ||
ebebf55c | 489 | return $stylesheets; |
490 | } | |
17a6649b | 491 | |
ebebf55c | 492 | /** |
fdeb7fa1 | 493 | * Get the meta tags from one theme to got in the <head> of the HTML. |
fa1afe32 | 494 | * @param string $themename the name of the theme to get meta tags from. |
495 | * @param string $page that page whose <head> is being output. | |
fdeb7fa1 | 496 | * @return string HTML code. |
497 | */ | |
498 | protected function get_theme_meta_tags($themename, $page) { | |
499 | global $CFG; | |
500 | // At least one theme's meta.php expects to have $PAGE visible. | |
501 | $PAGE = $page; | |
502 | $filename = $CFG->themedir . '/' . $themename . '/meta.php'; | |
503 | if (file_exists($filename)) { | |
504 | ob_start(); | |
505 | include_once($filename); | |
f77fcb5a | 506 | $metatags = ob_get_contents(); |
fdeb7fa1 | 507 | ob_end_clean(); |
508 | } | |
509 | return $metatags; | |
510 | } | |
511 | ||
512 | /** | |
513 | * Get all the meta tags (from this theme, standard, parent) that this theme | |
514 | * wants in the <head> of the HTML. | |
515 | * | |
fa1afe32 | 516 | * @param string $page that page whose <head> is being output. |
fdeb7fa1 | 517 | * @return string HTML code. |
518 | */ | |
519 | public function get_meta_tags($page) { | |
520 | $metatags = ''; | |
521 | if ($this->standardmetainclude) { | |
522 | $metatags .= $this->get_theme_meta_tags('standard', $page); | |
523 | } | |
524 | if ($this->parent && $this->parentmetainclude) { | |
525 | $metatags .= $this->get_theme_meta_tags($this->parent, $page); | |
526 | } | |
527 | if ($this->metainclude) { | |
528 | $metatags .= $this->get_theme_meta_tags($this->name, $page); | |
529 | } | |
530 | return $metatags; | |
531 | } | |
532 | ||
d4a03c00 | 533 | /** |
534 | * Get the information from {@link $layouts} for this type of page. | |
535 | * @param string $generaltype the general type of the page. | |
536 | * @return array the appropriate part of {@link $layouts}. | |
537 | */ | |
538 | protected function layout_info_for_page($generaltype) { | |
539 | if (array_key_exists($generaltype, $this->layouts)) { | |
540 | return $this->layouts[$generaltype]; | |
541 | } else { | |
542 | return reset($this->layouts); | |
543 | } | |
544 | } | |
545 | ||
fdeb7fa1 | 546 | /** |
547 | * Given the settings of this theme, and the page generaltype, return the | |
548 | * full path of the page layout template to use. | |
549 | * | |
550 | * Used by {@link moodle_core_renderer::header()}. If an appropriate new-style | |
551 | * template cannot be found, returns false to signal that the old-style | |
552 | * header.html and footer.html files should be used. | |
553 | * | |
d4a03c00 | 554 | * @param string $generaltype the general type of the page. |
fdeb7fa1 | 555 | * @return string Full path to the template to use, or false if a new-style |
556 | * template cannot be found. | |
557 | */ | |
d4a03c00 | 558 | public function template_for_page($generaltype) { |
fdeb7fa1 | 559 | global $CFG; |
560 | ||
561 | // Legacy fallback. | |
d4a03c00 | 562 | if (empty($this->layouts)) { |
fdeb7fa1 | 563 | return false; |
564 | } | |
565 | ||
d4a03c00 | 566 | $layoutinfo = $this->layout_info_for_page($generaltype); |
567 | $templatefile = $layoutinfo['layout']; | |
fdeb7fa1 | 568 | |
569 | // Parse the name that was found. | |
d4a03c00 | 570 | if (strpos($templatefile, 'standard:') === 0) { |
fdeb7fa1 | 571 | $templatepath = $CFG->themedir . '/standard/' . substr($templatefile, 9); |
d4a03c00 | 572 | } else if (strpos($templatefile, 'parent:') === 0) { |
fdeb7fa1 | 573 | if (empty($this->parent)) { |
574 | throw new coding_exception('This theme (' . $this->name . | |
575 | ') does not have a parent. You cannot specify a layout template like ' . | |
576 | $templatefile); | |
577 | } | |
578 | $templatepath = $CFG->themedir . '/' . $this->parent . '/' . substr($templatefile, 7); | |
579 | } else { | |
580 | $templatepath = $this->dir . '/' . $templatefile; | |
581 | } | |
582 | ||
fa1afe32 | 583 | // Check the template exists. |
fdeb7fa1 | 584 | if (!is_readable($templatepath)) { |
585 | throw new coding_exception('The template ' . $templatefile . ' (' . $templatepath . | |
586 | ') for page type ' . $generaltype . ' cannot be found in this theme (' . | |
587 | $this->name . ')'); | |
588 | } | |
589 | ||
590 | return $templatepath; | |
591 | } | |
592 | ||
d4a03c00 | 593 | /** |
594 | * Inform a block_manager about the block regions this theme wants on this | |
595 | * type of page. | |
596 | * @param string $generaltype the general type of the page. | |
597 | * @param block_manager $blockmanager the block_manger to set up. | |
fa1afe32 | 598 | * @return void |
d4a03c00 | 599 | */ |
600 | public function setup_blocks($generaltype, $blockmanager) { | |
601 | // Legacy fallback. | |
602 | if (empty($this->layouts)) { | |
603 | if (!in_array($generaltype, array('form', 'popup', 'maintenance'))) { | |
604 | $blockmanager->add_regions(array(BLOCK_POS_LEFT, BLOCK_POS_RIGHT)); | |
605 | $blockmanager->set_default_region(BLOCK_POS_RIGHT); | |
606 | } | |
607 | return; | |
608 | } | |
609 | ||
610 | $layoutinfo = $this->layout_info_for_page($generaltype); | |
611 | if (!empty($layoutinfo['regions'])) { | |
612 | $blockmanager->add_regions($layoutinfo['regions']); | |
613 | $blockmanager->set_default_region($layoutinfo['defaultregion']); | |
7d875874 | 614 | } else { |
615 | $blockmanager->set_default_region(''); | |
d4a03c00 | 616 | } |
617 | } | |
618 | ||
1d13c75c | 619 | /** |
620 | * Get the list of all block regions known to this theme in all templates. | |
621 | * @return array internal region name => human readable name. | |
622 | */ | |
623 | public function get_all_block_regions() { | |
624 | // Legacy fallback. | |
625 | if (empty($this->layouts)) { | |
626 | return array( | |
627 | 'side-pre' => get_string('region-side-pre', 'theme_standard'), | |
628 | 'side-post' => get_string('region-side-post', 'theme_standard'), | |
629 | ); | |
630 | } | |
631 | ||
632 | $regions = array(); | |
633 | foreach ($this->layouts as $layoutinfo) { | |
634 | $ownertheme = $this->name; | |
635 | if (strpos($layoutinfo['layout'], 'standard:') === 0) { | |
636 | $ownertheme = 'standard'; | |
637 | } else if (strpos($layoutinfo['layout'], 'parent:') === 0) { | |
638 | $ownertheme = $this->parent; | |
639 | } | |
640 | ||
641 | foreach ($layoutinfo['regions'] as $region) { | |
642 | $regions[$region] = get_string('region-' . $region, 'theme_' . $ownertheme); | |
643 | } | |
644 | } | |
645 | return $regions; | |
646 | } | |
647 | ||
fdeb7fa1 | 648 | /** |
649 | * Helper method used by {@link update_legacy_information()}. Update one entry | |
650 | * in the $this->pluginsheets array, based on the legacy $property propery. | |
fa1afe32 | 651 | * @param string $plugintype e.g. 'mod'. |
652 | * @param string $property e.g. 'modsheets'. | |
653 | * @return void | |
fdeb7fa1 | 654 | */ |
655 | protected function update_legacy_plugin_sheets($plugintype, $property) { | |
d4a03c00 | 656 | // In Moodle 1.9, modsheets etc. were ignored if standardsheets was false. |
657 | if (!empty($this->standardsheets) && property_exists($this, $property)) { | |
fdeb7fa1 | 658 | debugging('$THEME->' . $property . ' is deprecated. Please use the new $THEME->pluginsheets instead.', DEBUG_DEVELOPER); |
659 | if (!empty($this->$property) && !in_array($plugintype, $this->pluginsheets)) { | |
660 | $this->pluginsheets[] = $plugintype; | |
661 | } else if (empty($this->$property) && in_array($plugintype, $this->pluginsheets)) { | |
662 | unset($this->pluginsheets[array_search($plugintype, $this->pluginsheets)]); | |
663 | } | |
664 | } | |
665 | } | |
666 | ||
667 | /** | |
668 | * This method looks a the settings that have been loaded, to see whether | |
ebebf55c | 669 | * any legacy things are being used, and outputs warning and tries to update |
670 | * things to use equivalent newer settings. | |
fa1afe32 | 671 | * @return void |
ebebf55c | 672 | */ |
673 | protected function update_legacy_information() { | |
674 | global $CFG; | |
fdeb7fa1 | 675 | |
676 | $this->update_legacy_plugin_sheets('mod', 'modsheets'); | |
677 | $this->update_legacy_plugin_sheets('block', 'blocksheets'); | |
678 | $this->update_legacy_plugin_sheets('format', 'formatsheets'); | |
679 | $this->update_legacy_plugin_sheets('gradereport', 'gradereportsheets'); | |
680 | ||
fdeb7fa1 | 681 | if (!empty($this->langsheets)) { |
682 | debugging('$THEME->langsheets is no longer supported. No languages were ' . | |
683 | 'using it for anything, and it did not seem to serve any purpose.', DEBUG_DEVELOPER); | |
684 | } | |
685 | ||
ebebf55c | 686 | if (!empty($this->customcorners)) { |
687 | // $THEME->customcorners is deprecated but we provide support for it via the | |
688 | // custom_corners_renderer_factory class in lib/deprecatedlib.php | |
689 | debugging('$THEME->customcorners is deprecated. Please use the new $THEME->rendererfactory ' . | |
690 | 'to control HTML generation. Please use $this->rendererfactory = \'custom_corners_renderer_factory\'; ' . | |
691 | 'in your config.php file instead.', DEBUG_DEVELOPER); | |
692 | $this->rendererfactory = 'custom_corners_renderer_factory'; | |
34a2777c | 693 | } |
694 | ||
ebebf55c | 695 | if (!empty($this->cssconstants)) { |
696 | debugging('$THEME->cssconstants is deprecated. Please use ' . | |
697 | '$THEME->customcssoutputfunction = \'output_css_replacing_constants\'; ' . | |
698 | 'in your config.php file instead.', DEBUG_DEVELOPER); | |
699 | $this->customcssoutputfunction = 'output_css_replacing_constants'; | |
34a2777c | 700 | } |
ebebf55c | 701 | |
702 | if (!empty($this->CSSEdit)) { | |
703 | debugging('$THEME->CSSEdit is deprecated. Please use ' . | |
704 | '$THEME->customcssoutputfunction = \'output_css_for_css_edit\'; ' . | |
705 | 'in your config.php file instead.', DEBUG_DEVELOPER); | |
706 | $this->customcssoutputfunction = 'output_css_for_css_edit'; | |
34a2777c | 707 | } |
708 | ||
ae96b517 | 709 | if (!empty($CFG->smartpix)) { |
ebebf55c | 710 | $this->iconfinder = 'smartpix_icon_finder'; |
711 | } else if ($this->custompix) { | |
712 | $this->iconfinder = 'theme_icon_finder'; | |
713 | } | |
34a2777c | 714 | } |
715 | ||
ebebf55c | 716 | /** |
717 | * Set the variable $CFG->pixpath and $CFG->modpixpath to be the right | |
d436d197 | 718 | * ones for this theme. These should no longer be used, but legacy code |
719 | * might still rely on them. | |
fa1afe32 | 720 | * @return void |
ebebf55c | 721 | */ |
d436d197 | 722 | public function setup_legacy_pix_paths() { |
ebebf55c | 723 | global $CFG; |
724 | if (!empty($CFG->smartpix)) { | |
725 | if ($CFG->slasharguments) { | |
726 | // Use this method if possible for better caching | |
727 | $extra = ''; | |
728 | } else { | |
729 | $extra = '?file='; | |
730 | } | |
731 | $CFG->pixpath = $CFG->httpswwwroot . '/pix/smartpix.php' . $extra . '/' . $this->name; | |
732 | $CFG->modpixpath = $CFG->httpswwwroot . '/pix/smartpix.php' . $extra . '/' . $this->name . '/mod'; | |
34a2777c | 733 | |
ebebf55c | 734 | } else if (empty($THEME->custompix)) { |
735 | $CFG->pixpath = $CFG->httpswwwroot . '/pix'; | |
736 | $CFG->modpixpath = $CFG->httpswwwroot . '/mod'; | |
737 | ||
738 | } else { | |
739 | $CFG->pixpath = $CFG->httpsthemewww . '/' . $this->name . '/pix'; | |
740 | $CFG->modpixpath = $CFG->httpsthemewww . '/' . $this->name . '/pix/mod'; | |
34a2777c | 741 | } |
34a2777c | 742 | } |
ebebf55c | 743 | } |
34a2777c | 744 | |
ebebf55c | 745 | /** |
d9c8f425 | 746 | * This class keeps track of which HTML tags are currently open. |
747 | * | |
748 | * This makes it much easier to always generate well formed XHTML output, even | |
749 | * if execution terminates abruptly. Any time you output some opening HTML | |
750 | * without the matching closing HTML, you should push the necessary close tags | |
751 | * onto the stack. | |
ebebf55c | 752 | * |
753 | * @copyright 2009 Tim Hunt | |
754 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
755 | * @since Moodle 2.0 | |
756 | */ | |
d9c8f425 | 757 | class xhtml_container_stack { |
758 | /** @var array stores the list of open containers. */ | |
759 | protected $opencontainers = array(); | |
fa1afe32 | 760 | /** |
d9c8f425 | 761 | * @var array in developer debug mode, stores a stack trace of all opens and |
762 | * closes, so we can output helpful error messages when there is a mismatch. | |
fa1afe32 | 763 | */ |
d9c8f425 | 764 | protected $log = array(); |
fa1afe32 | 765 | /** |
d9c8f425 | 766 | * Store whether we are developer debug mode. We need this in several places |
767 | * including in the destructor where we may no thave access to $CFG. | |
768 | * @var boolean | |
fa1afe32 | 769 | */ |
d9c8f425 | 770 | protected $isdebugging; |
34a2777c | 771 | |
d9c8f425 | 772 | public function __construct() { |
773 | $this->isdebugging = debugging('', DEBUG_DEVELOPER); | |
ebebf55c | 774 | } |
34a2777c | 775 | |
fa1afe32 | 776 | /** |
d9c8f425 | 777 | * Push the close HTML for a recently opened container onto the stack. |
778 | * @param string $type The type of container. This is checked when {@link pop()} | |
779 | * is called and must match, otherwise a developer debug warning is output. | |
780 | * @param string $closehtml The HTML required to close the container. | |
781 | * @return void | |
fa1afe32 | 782 | */ |
d9c8f425 | 783 | public function push($type, $closehtml) { |
784 | $container = new stdClass; | |
785 | $container->type = $type; | |
786 | $container->closehtml = $closehtml; | |
787 | if ($this->isdebugging) { | |
788 | $this->log('Open', $type); | |
3aaa27f4 | 789 | } |
d9c8f425 | 790 | array_push($this->opencontainers, $container); |
ebebf55c | 791 | } |
34a2777c | 792 | |
fa1afe32 | 793 | /** |
d9c8f425 | 794 | * Pop the HTML for the next closing container from the stack. The $type |
795 | * must match the type passed when the container was opened, otherwise a | |
796 | * warning will be output. | |
797 | * @param string $type The type of container. | |
798 | * @return string the HTML required to close the container. | |
fa1afe32 | 799 | */ |
d9c8f425 | 800 | public function pop($type) { |
801 | if (empty($this->opencontainers)) { | |
802 | debugging('<p>There are no more open containers. This suggests there is a nesting problem.</p>' . | |
803 | $this->output_log(), DEBUG_DEVELOPER); | |
804 | return; | |
3aaa27f4 | 805 | } |
ebebf55c | 806 | |
d9c8f425 | 807 | $container = array_pop($this->opencontainers); |
808 | if ($container->type != $type) { | |
809 | debugging('<p>The type of container to be closed (' . $container->type . | |
810 | ') does not match the type of the next open container (' . $type . | |
811 | '). This suggests there is a nesting problem.</p>' . | |
812 | $this->output_log(), DEBUG_DEVELOPER); | |
ebebf55c | 813 | } |
d9c8f425 | 814 | if ($this->isdebugging) { |
815 | $this->log('Close', $type); | |
e8775320 | 816 | } |
d9c8f425 | 817 | return $container->closehtml; |
ebebf55c | 818 | } |
e8775320 | 819 | |
fa1afe32 | 820 | /** |
d9c8f425 | 821 | * Close all but the last open container. This is useful in places like error |
822 | * handling, where you want to close all the open containers (apart from <body>) | |
823 | * before outputting the error message. | |
824 | * @param bool $shouldbenone assert that the stack should be empty now - causes a | |
825 | * developer debug warning if it isn't. | |
826 | * @return string the HTML required to close any open containers inside <body>. | |
fa1afe32 | 827 | */ |
d9c8f425 | 828 | public function pop_all_but_last($shouldbenone = false) { |
829 | if ($shouldbenone && count($this->opencontainers) != 1) { | |
830 | debugging('<p>Some HTML tags were opened in the body of the page but not closed.</p>' . | |
831 | $this->output_log(), DEBUG_DEVELOPER); | |
832 | } | |
833 | $output = ''; | |
834 | while (count($this->opencontainers) > 1) { | |
835 | $container = array_pop($this->opencontainers); | |
836 | $output .= $container->closehtml; | |
e8775320 | 837 | } |
d9c8f425 | 838 | return $output; |
e8775320 | 839 | } |
34a2777c | 840 | |
ebebf55c | 841 | /** |
d9c8f425 | 842 | * You can call this function if you want to throw away an instance of this |
843 | * class without properly emptying the stack (for example, in a unit test). | |
844 | * Calling this method stops the destruct method from outputting a developer | |
845 | * debug warning. After calling this method, the instance can no longer be used. | |
846 | * @return void | |
ebebf55c | 847 | */ |
d9c8f425 | 848 | public function discard() { |
849 | $this->opencontainers = null; | |
ebebf55c | 850 | } |
d9c8f425 | 851 | |
ebebf55c | 852 | /** |
d9c8f425 | 853 | * Emergency fallback. If we get to the end of processing and not all |
854 | * containers have been closed, output the rest with a developer debug warning. | |
855 | * @return void | |
ebebf55c | 856 | */ |
d9c8f425 | 857 | public function __destruct() { |
858 | if (empty($this->opencontainers)) { | |
859 | return; | |
897b5c82 | 860 | } |
d9c8f425 | 861 | |
d5a8d9aa PS |
862 | // TODO: MDL-20625 this looks dangerous and problematic because we never know |
863 | // the order of calling of constructors ==> the transaction warning will not be included | |
864 | ||
d9c8f425 | 865 | // It seems you cannot rely on $CFG, and hence the debugging function here, |
866 | // becuase $CFG may be destroyed before this object is. | |
867 | if ($this->isdebugging) { | |
868 | echo '<div class="notifytiny"><p>Some containers were left open. This suggests there is a nesting problem.</p>' . | |
869 | $this->output_log() . '</div>'; | |
34a2777c | 870 | } |
d9c8f425 | 871 | echo $this->pop_all_but_last(); |
872 | $container = array_pop($this->opencontainers); | |
873 | echo $container->closehtml; | |
34a2777c | 874 | } |
34a2777c | 875 | |
fa1afe32 | 876 | /** |
d9c8f425 | 877 | * Adds an entry to the log. |
878 | * @param string $action The name of the action | |
879 | * @param string $type The type of action | |
880 | * @return void | |
fa1afe32 | 881 | */ |
d9c8f425 | 882 | protected function log($action, $type) { |
883 | $this->log[] = '<li>' . $action . ' ' . $type . ' at:' . | |
884 | format_backtrace(debug_backtrace()) . '</li>'; | |
ebebf55c | 885 | } |
34a2777c | 886 | |
fa1afe32 | 887 | /** |
d9c8f425 | 888 | * Outputs the log's contents as a HTML list. |
889 | * @return string HTML list of the log | |
fa1afe32 | 890 | */ |
d9c8f425 | 891 | protected function output_log() { |
892 | return '<ul>' . implode("\n", $this->log) . '</ul>'; | |
34a2777c | 893 | } |
894 | } | |
895 | ||
7a5c78e0 | 896 | /** |
897 | * An icon finder is responsible for working out the correct URL for an icon. | |
898 | * | |
899 | * A icon finder must also have a constructor that takes a theme object. | |
900 | * (See {@link standard_icon_finder::__construct} for an example.) | |
901 | * | |
902 | * Note that we are planning to change the Moodle icon naming convention before | |
903 | * the Moodle 2.0 release. Therefore, this API will probably change. | |
904 | * | |
905 | * @copyright 2009 Tim Hunt | |
906 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
907 | * @since Moodle 2.0 | |
908 | */ | |
909 | interface icon_finder { | |
910 | /** | |
911 | * Return the URL for an icon identified as in pre-Moodle 2.0 code. | |
912 | * | |
913 | * Suppose you have old code like $url = "$CFG->pixpath/i/course.gif"; | |
914 | * then old_icon_url('i/course'); will return the equivalent URL that is correct now. | |
915 | * | |
916 | * @param string $iconname the name of the icon. | |
917 | * @return string the URL for that icon. | |
918 | */ | |
919 | public function old_icon_url($iconname); | |
920 | ||
921 | /** | |
922 | * Return the URL for an icon identified as in pre-Moodle 2.0 code. | |
923 | * | |
924 | * Suppose you have old code like $url = "$CFG->modpixpath/$mod/icon.gif"; | |
925 | * then mod_icon_url('icon', $mod); will return the equivalent URL that is correct now. | |
926 | * | |
927 | * @param string $iconname the name of the icon. | |
928 | * @param string $module the module the icon belongs to. | |
929 | * @return string the URL for that icon. | |
930 | */ | |
931 | public function mod_icon_url($iconname, $module); | |
932 | } | |
933 | ||
934 | /** | |
935 | * This icon finder implements the old scheme that was used when themes that had | |
936 | * $THEME->custompix = false. | |
937 | * | |
938 | * @copyright 2009 Tim Hunt | |
939 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
940 | * @since Moodle 2.0 | |
941 | */ | |
942 | class pix_icon_finder implements icon_finder { | |
943 | /** | |
944 | * Constructor | |
945 | * @param theme_config $theme the theme we are finding icons for (which is irrelevant). | |
946 | */ | |
947 | public function __construct($theme) { | |
948 | } | |
949 | ||
950 | /** | |
951 | * Implement interface method. | |
952 | * @param string $iconname the name of the icon. | |
953 | * @return string the URL for that icon. | |
954 | */ | |
955 | public function old_icon_url($iconname) { | |
956 | global $CFG; | |
957 | if (file_exists($CFG->dirroot . '/pix/' . $iconname . '.png')) { | |
958 | return $CFG->httpswwwroot . '/pix/' . $iconname . '.png'; | |
959 | } else { | |
960 | return $CFG->httpswwwroot . '/pix/' . $iconname . '.gif'; | |
961 | } | |
962 | } | |
963 | ||
964 | /** | |
965 | * Implement interface method. | |
966 | * @param string $iconname the name of the icon. | |
967 | * @param string $module the module the icon belongs to. | |
968 | * @return string the URL for that icon. | |
969 | */ | |
970 | public function mod_icon_url($iconname, $module) { | |
971 | global $CFG; | |
972 | if (file_exists($CFG->dirroot . '/mod/' . $module . '/' . $iconname . '.png')) { | |
973 | return $CFG->httpswwwroot . '/mod/' . $module . '/' . $iconname . '.png'; | |
974 | } else { | |
975 | return $CFG->httpswwwroot . '/mod/' . $module . '/' . $iconname . '.gif'; | |
976 | } | |
977 | } | |
978 | } | |
979 | ||
980 | ||
981 | /** | |
982 | * This icon finder implements the old scheme that was used for themes that had | |
983 | * $THEME->custompix = true. | |
984 | * | |
985 | * @copyright 2009 Tim Hunt | |
986 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
987 | * @since Moodle 2.0 | |
988 | */ | |
989 | class theme_icon_finder implements icon_finder { | |
990 | protected $themename; | |
991 | /** | |
992 | * Constructor | |
993 | * @param theme_config $theme the theme we are finding icons for. | |
994 | */ | |
995 | public function __construct($theme) { | |
996 | $this->themename = $theme->name; | |
997 | } | |
998 | ||
999 | /** | |
1000 | * Implement interface method. | |
1001 | * @param string $iconname the name of the icon. | |
1002 | * @return string the URL for that icon. | |
1003 | */ | |
1004 | public function old_icon_url($iconname) { | |
1005 | global $CFG; | |
1006 | if (file_exists($CFG->themedir . '/' . $this->themename . '/pix/' . $iconname . '.png')) { | |
1007 | return $CFG->httpsthemewww . '/' . $this->themename . '/pix/' . $iconname . '.png'; | |
1008 | } else { | |
1009 | return $CFG->httpsthemewww . '/' . $this->themename . '/pix/' . $iconname . '.gif'; | |
1010 | } | |
1011 | } | |
1012 | ||
1013 | /** | |
1014 | * Implement interface method. | |
1015 | * @param string $iconname the name of the icon. | |
1016 | * @param string $module the module the icon belongs to. | |
1017 | * @return string the URL for that icon. | |
1018 | */ | |
1019 | public function mod_icon_url($iconname, $module) { | |
1020 | global $CFG; | |
1021 | if (file_exists($CFG->themedir . '/' . $this->themename . '/pix/mod/' . $module . '/' . $iconname . '.png')) { | |
1022 | return $CFG->httpsthemewww . '/' . $this->themename . '/pix/mod/' . $module . '/' . $iconname . '.png'; | |
1023 | } else { | |
1024 | return $CFG->httpsthemewww . '/' . $this->themename . '/pix/mod/' . $module . '/' . $iconname . '.gif'; | |
1025 | } | |
1026 | } | |
1027 | } | |
1028 | ||
1029 | ||
1030 | /** | |
1031 | * This icon finder implements the algorithm in pix/smartpix.php. | |
1032 | * | |
1033 | * @copyright 2009 Tim Hunt | |
1034 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
1035 | * @since Moodle 2.0 | |
1036 | */ | |
1037 | class smartpix_icon_finder extends pix_icon_finder { | |
1038 | protected $places = array(); | |
1039 | ||
1040 | /** | |
1041 | * Constructor | |
1042 | * @param theme_config $theme the theme we are finding icons for. | |
1043 | */ | |
1044 | public function __construct($theme) { | |
1045 | global $CFG; | |
1046 | $this->places[$CFG->themedir . '/' . $theme->name . '/pix/'] = | |
1047 | $CFG->httpsthemewww . '/' . $theme->name . '/pix/'; | |
1048 | if (!empty($theme->parent)) { | |
1049 | $this->places[$CFG->themedir . '/' . $theme->parent . '/pix/'] = | |
1050 | $CFG->httpsthemewww . '/' . $theme->parent . '/pix/'; | |
1051 | } | |
1052 | } | |
1053 | ||
1054 | /** | |
1055 | * Implement interface method. | |
1056 | * @param string $iconname the name of the icon. | |
1057 | * @return string the URL for that icon. | |
1058 | */ | |
1059 | public function old_icon_url($iconname) { | |
1060 | foreach ($this->places as $dirroot => $urlroot) { | |
1061 | if (file_exists($dirroot . $iconname . '.png')) { | |
1062 | return $dirroot . $iconname . '.png'; | |
1063 | } else if (file_exists($dirroot . $iconname . '.gif')) { | |
1064 | return $dirroot . $iconname . '.gif'; | |
1065 | } | |
1066 | } | |
1067 | return parent::old_icon_url($iconname); | |
1068 | } | |
1069 | ||
1070 | /** | |
1071 | * Implement interface method. | |
1072 | * @param string $iconname the name of the icon. | |
1073 | * @param string $module the module the icon belongs to. | |
1074 | * @return string the URL for that icon. | |
1075 | */ | |
1076 | public function mod_icon_url($iconname, $module) { | |
1077 | foreach ($this->places as $dirroot => $urlroot) { | |
1078 | if (file_exists($dirroot . 'mod/' . $iconname . '.png')) { | |
1079 | return $dirroot . 'mod/' . $iconname . '.png'; | |
1080 | } else if (file_exists($dirroot . 'mod/' . $iconname . '.gif')) { | |
1081 | return $dirroot . 'mod/' . $iconname . '.gif'; | |
1082 | } | |
1083 | } | |
1084 | return parent::old_icon_url($iconname, $module); | |
1085 | } | |
1086 | } | |
1087 | ||
b7009474 | 1088 | |
1089 | /** | |
1090 | * Output CSS while replacing constants/variables. See MDL-6798 for details | |
1091 | * | |
1092 | * Information from Urs Hunkler: | |
1093 | * | |
1094 | * This is an adaptation of Shaun Inman's "CSS Server-side Constants" for Moodle. | |
1095 | * http://www.shauninman.com/post/heap/2005/08/09/css_constants | |
1096 | * | |
1097 | * To use, specify $THEME->customcssoutputfunction = 'output_css_replacing_constants'; | |
1098 | * in your theme's config.php file. | |
1099 | * | |
1100 | * The constant definitions are written into a separate CSS file named like | |
1101 | * constants.css and loaded first in config.php. You can use constants for any | |
1102 | * CSS properties. The constant definition looks like: | |
1103 | * <code> | |
1104 | * \@server constants { | |
1105 | * fontColor: #3a2830; | |
1106 | * aLink: #116699; | |
1107 | * aVisited: #AA2200; | |
1108 | * aHover: #779911; | |
1109 | * pageBackground: #FFFFFF; | |
1110 | * backgroundColor: #EEEEEE; | |
1111 | * backgroundSideblockHeader: #a8a4e9; | |
1112 | * fontcolorSideblockHeader: #222222; | |
1113 | * color1: #98818b; | |
1114 | * color2: #bd807b; | |
1115 | * color3: #f9d1d7; | |
1116 | * color4: #e8d4d8; | |
1117 | * } | |
1118 | * </code> | |
1119 | * | |
1120 | * The lines in the CSS files using CSS constants look like: | |
1121 | * <code> | |
1122 | * body { | |
1123 | * font-size: 100%; | |
1124 | * background-color: pageBackground; | |
1125 | * color: fontColor; | |
1126 | * font-family: 'Bitstream Vera Serif', georgia, times, serif; | |
1127 | * margin: 0; | |
1128 | * padding: 0; | |
1129 | * } | |
1130 | * div#page { | |
1131 | * margin: 0 10px; | |
1132 | * padding-top: 5px; | |
1133 | * border-top-width: 10px; | |
1134 | * border-top-style: solid; | |
1135 | * border-top-color: color3; | |
1136 | * } | |
1137 | * div.clearer { | |
1138 | * clear: both; | |
1139 | * } | |
1140 | * a:link { | |
1141 | * color: aLink; | |
fdeb7fa1 | 1142 | * } |
b7009474 | 1143 | * </code> |
1144 | * | |
fa1afe32 | 1145 | * @param array $files an array of the CSS fields that need to be output. |
fdeb7fa1 | 1146 | * @param array $toreplace for convenience. If you are going to output the names |
1147 | * of the css files, for debugging purposes, then you should output | |
fa1afe32 | 1148 | * str_replace($toreplace, '', $file); because it looks prettier. |
1149 | * @return void | |
b7009474 | 1150 | */ |
fdeb7fa1 | 1151 | function output_css_replacing_constants($files, $toreplace) { |
b7009474 | 1152 | // Get all the CSS. |
b7009474 | 1153 | ob_start(); |
1154 | foreach ($files as $file) { | |
1155 | $shortname = str_replace($toreplace, '', $file); | |
1156 | echo '/******* ' . $shortname . " start *******/\n\n"; | |
1157 | @include_once($file); | |
1158 | echo '/******* ' . $shortname . " end *******/\n\n"; | |
1159 | } | |
1160 | $css = ob_get_contents(); | |
1161 | ob_end_clean(); | |
1162 | ||
1163 | if (preg_match_all("/@server\s+(?:variables|constants)\s*\{\s*([^\}]+)\s*\}\s*/i", $css, $matches)) { | |
1164 | $variables = array(); | |
1165 | foreach ($matches[0] as $key => $server) { | |
1166 | $css = str_replace($server, '', $css); | |
1167 | preg_match_all("/([^:\}\s]+)\s*:\s*([^;\}]+);/", $matches[1][$key], $vars); | |
1168 | foreach ($vars[1] as $var => $value) { | |
1169 | $variables[$value] = $vars[2][$var]; | |
1170 | } | |
1171 | } | |
1172 | $css = str_replace(array_keys($variables), array_values($variables), $css); | |
1173 | } | |
1174 | echo $css; | |
1175 | } | |
1176 | ||
1177 | /** | |
1178 | * This CSS output function will link to CSS files rather than including them | |
1179 | * inline. | |
1180 | * | |
1181 | * The single CSS files can then be edited and saved with interactive | |
1182 | * CSS editors like CSSEdit. Any files that have a .php extension are still included | |
1183 | * inline. | |
1184 | * | |
fa1afe32 | 1185 | * @param array $files an array of the CSS fields that need to be output. |
fdeb7fa1 | 1186 | * @param array $toreplace for convenience. If you are going to output the names |
1187 | * of the css files, for debugging purposes, then you should output | |
fa1afe32 | 1188 | * str_replace($toreplace, '', $file); because it looks prettier. |
1189 | * @return void | |
b7009474 | 1190 | */ |
fdeb7fa1 | 1191 | function output_css_for_css_edit($files, $toreplace) { |
b7009474 | 1192 | foreach ($files as $file) { |
1193 | $shortname = str_replace($toreplace, '', $file); | |
1194 | echo '/* @group ' . $shortname . " */\n\n"; | |
1195 | if (strpos($file, '.css') !== false) { | |
1196 | echo '@import url("' . $file . '");'."\n\n"; | |
1197 | } else { | |
1198 | @include_once($file); | |
1199 | } | |
1200 | echo "/* @end */\n\n"; | |
1201 | } | |
f77fcb5a | 1202 | } |