}
if (empty($userid)) { // we must accept null, 0, '0', '' etc. in $userid
+ if (empty($USER->id)) {
+ // Session not set up yet.
+ return false;
+ }
$userid = $USER->id;
}
*/
define('PAGE_COURSE_VIEW', 'course-view');
-/// Debug levels ///
-/** no warnings at all */
-define ('DEBUG_NONE', 0);
-/** E_ERROR | E_PARSE */
-define ('DEBUG_MINIMAL', 5);
-/** E_ERROR | E_PARSE | E_WARNING | E_NOTICE */
-define ('DEBUG_NORMAL', 15);
-/** E_ALL without E_STRICT for now, do show recoverable fatal errors */
-define ('DEBUG_ALL', 6143);
-/** DEBUG_ALL with extra Moodle debug messages - (DEBUG_ALL | 32768) */
-define ('DEBUG_DEVELOPER', 38911);
-
/** Get remote addr constant */
define('GETREMOTEADDR_SKIP_HTTP_CLIENT_IP', '1');
/** Get remote addr constant */
*
* Notes for develpers
* ===================
- *
* Performance of this class is important. If you decide to change this class,
* please use the lib/simpletest/getstringperformancetester.php script to make
* sure your changes do not cause a performance problem.
*
- * In some cases (for example _print_early_error) get_string gets called very
- * early on during Moodle's self-initialisation. Think very carefully before
- * relying on the normal Moodle libraries here.
+ * In some cases (for example bootstrap_renderer::early_error) get_string gets
+ * called very early on during Moodle's self-initialisation. Think very carefully
+ * before relying on the normal Moodle libraries here.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package moodlecore
*/
-/**
- * Set up a preliminary $OUTPUT. This will be changed later once the correct theme
- * for this page is known. Must be called after $PAGE is setup.
- */
-function setup_bootstrat_output() {
- global $OUTPUT, $PAGE;
+function initialise_theme_and_output() {
+ global $CFG, $OUTPUT, $PAGE, $THEME;
+ if (!($OUTPUT instanceof bootstrap_renderer)) {
+ return; // Already done.
+ }
+ if (!isset($CFG->theme) || empty($PAGE)) {
+ // Too soon to do anything.
+ return;
+ }
+ theme_setup();
if (CLI_SCRIPT) {
- $OUTPUT = new cli_core_renderer(new xhtml_container_stack(), $PAGE);
+ $rendererfactory = new cli_renderer_factory($THEME, $PAGE);
} else {
- $OUTPUT = new moodle_core_renderer(new xhtml_container_stack(), $PAGE);
+ $classname = $THEME->rendererfactory;
+ $rendererfactory = new $classname($THEME, $PAGE);
}
+ $OUTPUT = $rendererfactory->get_renderer('core');
}
/* Implement the subclass method. */
public function create_renderer($module) {
if ($module == 'core') {
- return new moodle_core_renderer($this->opencontainers, $this->page);
+ return new moodle_core_renderer($this->opencontainers, $this->page, $this);
} else {
$class = $this->standard_renderer_class_for_module($module);
return new $class($this->opencontainers, $this->get_renderer('core'), $this->page);
*/
public function __construct($theme, $page) {
parent::__construct($theme, $page);
- $this->renderers = array('core' => new custom_corners_core_renderer($this->opencontainers, $this->page));
+ $this->renderers = array('core' => new custom_corners_core_renderer($this->opencontainers, $this->page, $this));
+ }
+}
+
+
+/**
+ * This is a slight variation on the standard_renderer_factory used by CLI scripts.
+ *
+ * @copyright 2009 Tim Hunt
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 2.0
+ */
+class cli_renderer_factory extends standard_renderer_factory {
+ /**
+ * Constructor.
+ * @param object $theme the theme we are rendering for.
+ * @param moodle_page $page the page we are doing output for.
+ */
+ public function __construct($theme, $page) {
+ parent::__construct($theme, $page);
+ $this->renderers = array('core' => new cli_core_renderer($this->opencontainers, $this->page, $this));
}
}
$classname = $prefix . $module . '_renderer';
if (class_exists($classname)) {
if ($module == 'core') {
- return new $classname($this->opencontainers, $this->page);
+ return new $classname($this->opencontainers, $this->page, $this);
} else {
return new $classname($this->opencontainers, $this->get_renderer('core'), $this->page);
}
// Create a template_renderer that copies the API of the standard renderer.
$copiedclass = $this->standard_renderer_class_for_module($module);
- return new template_renderer($copiedclass, $searchpaths, $this->opencontainers, $this->page);
+ return new template_renderer($copiedclass, $searchpaths, $this->opencontainers, $this->page, $this);
}
}
protected $copiedclass;
/** @var array of places to search for templates. */
protected $searchpaths;
+ protected $rendererfactory;
/**
* Magic word used when breaking apart container templates to implement
* @param $searchpaths a list of folders to search for templates in.
* @param $opencontainers the xhtml_container_stack to use.
* @param moodle_page $page the page we are doing output for.
+ * @param renderer_factory $rendererfactory the renderer factory that created us.
*/
- public function __construct($copiedclass, $searchpaths, $opencontainers, $page) {
+ public function __construct($copiedclass, $searchpaths, $opencontainers, $page, $rendererfactory) {
parent::__construct($opencontainers, $page);
$this->copiedclass = new ReflectionClass($copiedclass);
$this->searchpaths = $searchpaths;
+ $this->rendererfactory = $rendererfactory;
+ }
+
+ /**
+ * Get a renderer for another part of Moodle.
+ * @param $module the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'.
+ * @return object an object implementing the requested renderer interface.
+ */
+ public function get_other_renderer($module) {
+ $this->rendererfactory->get_renderer($module);
}
/* PHP magic method implementation. */
const END_HTML_TOKEN = '%%ENDHTML%%';
const MAIN_CONTENT_TOKEN = '[MAIN CONTENT GOES HERE]';
protected $contenttype;
+ protected $rendererfactory;
+
+ /**
+ * Constructor
+ * @param $opencontainers the xhtml_container_stack to use.
+ * @param moodle_page $page the page we are doing output for.
+ * @param renderer_factory $rendererfactory the renderer factory that created us.
+ */
+ public function __construct($opencontainers, $page, $rendererfactory) {
+ parent::__construct($opencontainers, $page);
+ $this->rendererfactory = $rendererfactory;
+ }
+
+ /**
+ * Get a renderer for another part of Moodle.
+ * @param $module the name of part of moodle. E.g. 'core', 'quiz', 'qtype_multichoice'.
+ * @return object an object implementing the requested renderer interface.
+ */
+ public function get_other_renderer($module) {
+ $this->rendererfactory->get_renderer($module);
+ }
public function doctype() {
global $CFG;
if ($this->opencontainers->count() == 0) {
// Header not yet printed
@header('HTTP/1.0 404 Not Found');
- print_header(get_string('error'));
+ $this->page->set_title(get_string('error'));
+ $output .= $this->header();
} else {
$output .= $this->opencontainers->pop_all_but_last();
}
$output .= $this->continue_button($link);
}
- print_footer();
+ $output .= $this->footer();
// Padding to encourage IE to display our error page, rather than its own.
$output .= str_repeat(' ', 512);
* @since Moodle 2.0
*/
class custom_corners_core_renderer extends moodle_core_renderer {
+ protected $wraplevel = 1;
+
protected function custom_corners_divs($classes = '', $idbase = '') {
if (strpos($classes, 'clearfix') !== false) {
$clearfix = ' clearfix';
$idbb = $idbase . '-bb';
}
- // Calculate current level
- $level = $this->opencontainers->count();
-
// Create start tags.
- $start = $this->output_start_tag('div', array('id' => $idbb, 'class' => "wrap wraplevel$level $classes")) . "\n";
+ $start = $this->output_start_tag('div', array('id' => $id, 'class' => "wrap wraplevel{$this->wraplevel} $classes")) . "\n";
$start .= $this->output_tag('div', array('id' => $idbt, 'class' => 'bt'), '<div> </div>') . "\n";
$start .= $this->output_start_tag('div', array('id' => $idi1, 'class' => 'i1'));
$start .= $this->output_start_tag('div', array('id' => $idi2, 'class' => 'i2'));
public function box_start($classes = 'generalbox', $id = '') {
list($start, $end) = $this->custom_corners_divs('ccbox box ' . moodle_renderer_base::prepare_classes($classes), $id);
$this->opencontainers->push('box', $end);
+ $this->wraplevel += 1;
return $start;
}
+ public function box_end() {
+ $this->wraplevel -= 1;
+ return parent::box_end();
+ }
+
public function container_start($classes = '', $id = '') {
list($start, $end) = $this->custom_corners_divs(moodle_renderer_base::prepare_classes($classes), $id);
$this->opencontainers->push('container', $end);
+ $this->wraplevel += 1;
return $start;
}
+
+ public function container_end() {
+ $this->wraplevel -= 1;
+ return parent::container_end();
+ }
}
* @return blocks_manager the blocks manager object for this page.
*/
public function get_blocks() {
- global $CFG;
+ global $CFG, $THEME;
if (is_null($this->_blocks)) {
+ initialise_theme_and_output();
if (!empty($CFG->blockmanagerclass)) {
$classname = $CFG->blockmanagerclass;
} else {
$classname = 'block_manager';
}
$this->_blocks = new $classname($this);
+ $this->_blocks->add_regions($THEME->blockregions);
+ $this->_blocks->set_default_region($THEME->defaultblockregion);
}
return $this->_blocks;
}
}
moodle_setlocale();
- theme_setup();
}
/**
$this->_course = new stdClass;
$this->_course->id = 1;
moodle_setlocale();
- theme_setup();
return;
}
* $OUTPUT is an instance of moodle_core_renderer or one of its subclasses. Use
* it to generate HTML for output.
*
- * $OUTPUT is initialised when the theme is setup. That normally happens during
- * the call to require_login, or $PAGE->set_course.
+ * $OUTPUT is initialised the first time it is used. See {@link bootstrap_renderer}
+ * for the magic that does that. After $OUTPUT has been initialised, any attempt
+ * to change something that affects the current theme ($PAGE->course, logged in use,
+ * httpsrequried ... will result in an exception.)
*
* @global object $OUTPUT
* @name $OUTPUT
/// Time to start counting
init_performance_info();
+/// Put $OUTPUT in place, so errors can be displayed.
+ $OUTPUT = new bootstrap_renderer();
+
+/// set handler for uncought exceptions - equivalent to print_error() call
+ set_exception_handler('default_exception_handler');
/// If there are any errors in the standard libraries we want to know!
error_reporting(E_ALL);
//point zend include path to moodles lib/zend so that includes and requires will search there for files before anywhere else
ini_set('include_path', $CFG->libdir.'/zend' . PATH_SEPARATOR . ini_get('include_path'));
-/// set handler for uncought exceptions - equivalent to print_error() call
- set_exception_handler('default_exception_handler');
-
/// make sure PHP is not severly misconfigured
setup_validate_php_configuration();
unset($originaldatabasedebug);
error_reporting($CFG->debug);
-
/// find out if PHP cofigured to display warnings
if (ini_get_bool('display_errors')) {
define('WARN_DISPLAY_ERRORS_ENABLED', true);
@ini_set('log_errors', '1');
}
-/// Create the $PAGE global.
- if (!empty($CFG->moodlepageclass)) {
- $classname = $CFG->moodlepageclass;
- } else {
- $classname = 'moodle_page';
- }
- $PAGE = new $classname();
-
-/// Create an initial $OUTPUT. This will be changes later once we know the theme.
- setup_bootstrat_output();
-
- unset($classname);
-
/// detect unsupported upgrade jump as soon as possible - do not change anything, do not use system functions
if (!empty($CFG->version) and $CFG->version < 2007101509) {
print_error('upgraderequires19', 'error');
$CFG->javascript = $CFG->libdir .'/javascript.php';
$CFG->moddata = 'moddata';
+/// Create the $PAGE global.
+ if (!empty($CFG->moodlepageclass)) {
+ $classname = $CFG->moodlepageclass;
+ } else {
+ $classname = 'moodle_page';
+ }
+ $PAGE = new $classname();
+ unset($classname);
+
/// A hack to get around magic_quotes_gpc being turned on
/// It is strongly recommended to disable "magic_quotes_gpc"!
if (ini_get_bool('magic_quotes_gpc')) {
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+/// Debug levels ///
+/** no warnings at all */
+define ('DEBUG_NONE', 0);
+/** E_ERROR | E_PARSE */
+define ('DEBUG_MINIMAL', 5);
+/** E_ERROR | E_PARSE | E_WARNING | E_NOTICE */
+define ('DEBUG_NORMAL', 15);
+/** E_ALL without E_STRICT for now, do show recoverable fatal errors */
+define ('DEBUG_ALL', 6143);
+/** DEBUG_ALL with extra Moodle debug messages - (DEBUG_ALL | 32768) */
+define ('DEBUG_DEVELOPER', 38911);
+
/**
* Simple class
*
/**
* Base Moodle Exception class
*
+ * Although this class is defined here, you cannot throw a moodle_exception until
+ * after moodlelib.php has been included (which will happen very soon).
+ *
* @package moodlecore
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* Does not return. Terminates execution.
*/
function default_exception_handler($ex, $isupgrade = false, $plugin = null) {
- global $CFG, $DB, $SCRIPT;
+ global $CFG, $DB, $OUTPUT, $SCRIPT;
// detect active db transactions, rollback and log as error
- if ($DB->is_transaction_started()) {
- error_log('Database transaction aborted by exception in '.$CFG->dirroot.$SCRIPT);
+ if ($DB && $DB->is_transaction_started()) {
+ error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
try {
// note: transaction blocks should never change current $_SESSION
$DB->rollback_sql();
$place = array('file'=>$ex->getFile(), 'line'=>$ex->getLine(), 'exception'=>get_class($ex));
array_unshift($backtrace, $place);
- $earlyerror = empty($OUTPUT);
foreach ($backtrace as $stackframe) {
- if (isset($stackframe['function']) && $stackframe['function'] == 'print_header') {
+ if (isset($stackframe['function']) && $stackframe['function'] == 'default_exception_handler') {
$earlyerror = true;
break;
}
$CFG->debug = DEBUG_DEVELOPER;
}
- if ($earlyerror) {
- // Error found before setup.php finished
- _print_early_error($message, $backtrace, $debuginfo);
- } else {
- echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
- }
-
+ echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
exit(1); // General error code
}
}
list($message, $moreinfourl, $link) = prepare_error_message($errorcode, $module, $link, $a);
-
- if (empty($OUTPUT)) {
- // Error found before setup.php finished
- _print_early_error($message);
- } else {
- echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
- }
+ echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
exit(1); // General error code
}
$DB->set_debug(0);
}
+ // Be careful, no guarantee moodlelib.php is loaded.
if (empty($module) || $module == 'moodle' || $module == 'core') {
$module = 'error';
}
- $message = get_string($errorcode, $module, $a);
- if ($module === 'error' and strpos($message, '[[') === 0) {
- // Search in moodle file if error specified - needed for backwards compatibility
- $message = get_string($errorcode, 'moodle', $a);
+ if (function_exists('get_string')) {
+ $message = get_string($errorcode, $module, $a);
+ if ($module === 'error' and strpos($message, '[[') === 0) {
+ // Search in moodle file if error specified - needed for backwards compatibility
+ $message = get_string($errorcode, 'moodle', $a);
+ }
+ } else {
+ $message = $module . '/' . $errorcode;
+ }
+
+ // Be careful, no guarantee weblib.php is loaded.
+ if (function_exists('clean_text')) {
+ $message = clean_text($message);
+ } else {
+ $message = htmlspecialchars($message);
}
- $message = clean_text($message);
if (!empty($CFG->errordocroot)) {
$errordocroot = $CFG->errordocroot;
return array($message, $moreinfourl, $link);
}
-/**
- * Internal function used by print_error. Do not use this directly!!
- *
- * Displays a fatal error before the theme is fully initialised.
- * For example errors that occur during lib/setup.php.
- *
- * @param string $message
- * @param string $link
- * @param array $backtrace
- * @param string $debuginfo
- */
-function _print_early_error($message, $backtrace = null, $debuginfo = null) {
- // In the name of protocol correctness, monitoring and performance
- // profiling, set the appropriate error headers for machine comsumption
- if (isset($_SERVER['SERVER_PROTOCOL'])) {
- // Avoid it with cron.php. Note that we assume it's HTTP/1.x
- @header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable');
- }
-
- // better disable any caching
- @header('Content-Type: text/html; charset=utf-8');
- @header('Cache-Control: no-store, no-cache, must-revalidate');
- @header('Cache-Control: post-check=0, pre-check=0', false);
- @header('Pragma: no-cache');
- @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
- @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
-
- echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" ' . get_html_lang() . '>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>' . get_string('error') . '</title>
-</head><body>
-<div style="margin-top: 6em; margin-left:auto; margin-right:auto; color:#990000; text-align:center; font-size:large; border-width:1px;
- border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse;
- width: 80%; -moz-border-radius: 20px; padding: 15px">
-' . $message . '
-</div>';
- if (debugging('', DEBUG_DEVELOPER)) {
- if (!empty($debuginfo)) {
- echo '<div class="notifytiny">' . $debuginfo . '</div>';
- }
- if (!empty($backtrace)) {
- echo '<div class="notifytiny">Stack trace: ' . format_backtrace($backtrace, false) . '</div>';
- }
- }
-
- echo '</body></html>';
-}
-
/**
* Formats a backtrace ready for output.
*
$PERF->logwrites = 0;
if (function_exists('microtime')) {
$PERF->starttime = microtime();
- }
+ }
if (function_exists('memory_get_usage')) {
$PERF->startmemory = memory_get_usage();
}
}
+/**
+ * This class solves the problem of how to initialise $OUTPUT.
+ *
+ * The problem is caused be two factors
+ * <ol>
+ * <li>On the one hand, we cannot be sure when output will start. In particular,
+ * an error, which needs to be displayed, could br thrown at any time.</li>
+ * <li>On the other hand, we cannot be sure when we will have all the information
+ * necessary to correctly initialise $OUTPUT. $OUTPUT depends on the theme, which
+ * (potentially) depends on the current course, course categories, and logged in user.
+ * It also depends on whether the current page requires HTTPS.</li>
+ * </ol>
+ *
+ * So, it is hard to find a single natural place during Moodle script execution,
+ * which we can guarantee is the right time to initialise $OUTPUT. Instead we
+ * adopt the following strategy
+ * <ol>
+ * <li>We will initialise $OUTPUT the first time it is used.</li>
+ * <li>If, after $OUTPUT has been initialised, the script tries to change something
+ * that $OUPTUT depends on, we throw an exception making it clear that the script
+ * did something wrong.
+ * </ol>
+ *
+ * The only problem with that is, how do we initialise $OUTPUT on first use if,
+ * it is going to be used like $OUTPUT->somthing(...)? Well that is where this
+ * class comes in. Initially, we set up $OUTPUT = new bootstrap_renderer(). Then,
+ * when any method is called on that object, we initialise $OUTPUT, and pass the call on.
+ *
+ * Note that this class is used before lib/outputlib.php has been loaded, so we
+ * must be careful referring to classes/funtions from there, they may not be
+ * defined yet, and we must avoid fatal errors.
+ *
+ * @copyright 2009 Tim Hunt
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 2.0
+ */
+class bootstrap_renderer {
+ /**
+ * Handles re-entrancy. Without this, errors or debugging output that occur
+ * during the initialisation of $OUTPUT, cause infinite recursion.
+ * @var boolean
+ */
+ protected $initialising = false;
+
+ public function __call($method, $arguments) {
+ global $OUTPUT;
+
+ // If lib/outputlib.php has been loaded, call it.
+ if (!$this->initialising && function_exists('initialise_theme_and_output')) {
+ $this->initialising = true;
+ initialise_theme_and_output(debug_backtrace());
+ if (!($OUTPUT instanceof bootstrap_renderer)) {
+ return call_user_func_array(array($OUTPUT, $method), $arguments);
+ }
+ }
-?>
+ $this->initialising = true;
+ // Too soon to initialise $OUTPUT, provide a couple of key methods.
+ $earlymethods = array(
+ 'fatal_error' => 'early_error',
+ 'notification' => 'early_notification',
+ );
+ if (array_key_exists($method, $earlymethods)) {
+ return call_user_func_array(array('bootstrap_renderer', $earlymethods[$method]), $arguments);
+ }
+
+ throw new coding_exception('Attempt to start output before enough information is known to initialise the theme.');
+ }
+
+ /**
+ * This function should only be called by this class, or by
+ * @return unknown_type
+ */
+ public static function early_error($message, $moreinfourl, $link, $backtrace,
+ $debuginfo = null, $showerrordebugwarning = false) {
+ // In the name of protocol correctness, monitoring and performance
+ // profiling, set the appropriate error headers for machine comsumption
+ if (isset($_SERVER['SERVER_PROTOCOL'])) {
+ // Avoid it with cron.php. Note that we assume it's HTTP/1.x
+ @header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable');
+ }
+
+ // better disable any caching
+ @header('Content-Type: text/html; charset=utf-8');
+ @header('Cache-Control: no-store, no-cache, must-revalidate');
+ @header('Cache-Control: post-check=0, pre-check=0', false);
+ @header('Pragma: no-cache');
+ @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
+ @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
+
+ if (function_exists('get_string') && function_exists('get_html_lang')) {
+ $htmllang = get_html_lang();
+ $strerror = get_string('error');
+ } else {
+ $htmllang = '';
+ $strerror = 'Error';
+ }
+
+
+ $output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" ' . $htmllang . '>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>' . $strerror . '</title>
+</head><body>
+<div style="margin-top: 6em; margin-left:auto; margin-right:auto; color:#990000; text-align:center; font-size:large; border-width:1px;
+ border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse;
+ width: 80%; -moz-border-radius: 20px; padding: 15px">
+' . $message . '
+</div>';
+ if (!empty($CFG->debug) && $CFG->debug >= DEBUG_DEVELOPER) {
+ if (!empty($debuginfo)) {
+ $output .= '<div class="notifytiny">' . $debuginfo . '</div>';
+ }
+ if (!empty($backtrace)) {
+ $output .= '<div class="notifytiny">Stack trace: ' . format_backtrace($backtrace, false) . '</div>';
+ }
+ }
+
+ $output .= '</body></html>';
+ return $output;
+ }
+
+ public static function early_notification($message, $classes = 'notifyproblem') {
+ return '<div class="' . $classes . '">' . $message . '</div>';
+ }
+}
public function create_renderer($module) {
$this->createcalls[] = $module;
- return new moodle_core_renderer(new xhtml_container_stack(), null);
+ return new moodle_core_renderer(new xhtml_container_stack(), null, null);
}
public function standard_renderer_class_for_module($module) {
*/
class moodle_test_renderer extends moodle_core_renderer {
public function __construct($containerstack, $page) {
- parent::__construct($containerstack, $page);
+ parent::__construct($containerstack, $page, null);
}
public function greeting($name = 'world') {
$page = new stdClass;
$page->course = new stdClass;
$this->renderer = new template_renderer('moodle_test_renderer',
- array($this->templatefolder), new xhtml_container_stack(), $page);
+ array($this->templatefolder), new xhtml_container_stack(), $page, null);
$this->savedtemplates = array();
}
public function setUp() {
parent::setUp();
$this->containerstack = new xhtml_container_stack();
- $this->renderer = new moodle_core_renderer($this->containerstack, null);
+ $this->renderer = new moodle_core_renderer($this->containerstack, null, null);
}
public function test_select_menu_simple() {
$CFG->stylesheets[] = $CFG->themewww.'/'.$theme.'/rtl.css'.$paramstring;
}
- /// Set up the block regions.
- if (!empty($THEME->blockregions)) {
- $PAGE->blocks->add_regions($THEME->blockregions);
- } else {
- // Support legacy themes by supplying a sensible default.
- $PAGE->blocks->add_regions(array('side-pre', 'side-post'));
+ // Support legacy themes, by setting sensible defaults for some of the new
+ // properties that were introduced in Moodle 2.0.
+ if (empty($THEME->rendererfactory)) {
+ $THEME->rendererfactory = 'standard_renderer_factory';
}
- if (!empty($THEME->defaultblockregion)) {
- $PAGE->blocks->set_default_region($THEME->defaultblockregion);
- } else {
- // Support legacy themes by supplying a sensible default.
- $PAGE->blocks->set_default_region('side-post');
+ if (empty($THEME->blockregions)) {
+ $THEME->blockregions = array('side-pre', 'side-post');
+ }
+ if (empty($THEME->defaultblockregion)) {
+ $THEME->defaultblockregion = 'side-post';
}
}
/// "pix/mod" directory containing all the icons
/// for all the activity modules.
////////////////////////////////////////////////////////////////////////////////
-?>
+
+
+$THEME->rendererfactory = 'custom_corners_renderer_factory';
+/// This is an advanced features that lets you control the HTML that Moodle
+/// generates. You need to specify a class that implements the renderer_factory
+/// interface. As well as the default 'standard_renderer_factory', there is
+/// also the experimental 'template_renderer_factory', or you could implement
+/// your own. For more information, please see
+/// http://docs.moodle.org/en/Developement:How_Moodle_outputs_HTML
+////////////////////////////////////////////////////////////////////////////////