mirror of
https://github.com/moodle/moodle.git
synced 2025-04-14 13:02:07 +02:00
MDL-19077 - change how $OUTPUT is initialised.
Please read the comment at the top of bootstrap_renderer in setuplib.php
This commit is contained in:
parent
a4103e65fa
commit
c84a2dbea2
@ -480,6 +480,10 @@ function has_capability($capability, $context, $userid=NULL, $doanything=true) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -249,18 +249,6 @@ define('PARAM_PERMISSION', 0x80000);
|
||||
*/
|
||||
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 */
|
||||
@ -5588,14 +5576,13 @@ function print_string($identifier, $module='', $a=NULL) {
|
||||
*
|
||||
* 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
|
||||
|
@ -28,17 +28,23 @@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
if (CLI_SCRIPT) {
|
||||
$OUTPUT = new cli_core_renderer(new xhtml_container_stack(), $PAGE);
|
||||
} else {
|
||||
$OUTPUT = new moodle_core_renderer(new xhtml_container_stack(), $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) {
|
||||
$rendererfactory = new cli_renderer_factory($THEME, $PAGE);
|
||||
} else {
|
||||
$classname = $THEME->rendererfactory;
|
||||
$rendererfactory = new $classname($THEME, $PAGE);
|
||||
}
|
||||
$OUTPUT = $rendererfactory->get_renderer('core');
|
||||
}
|
||||
|
||||
|
||||
@ -181,7 +187,7 @@ class standard_renderer_factory extends renderer_factory_base {
|
||||
/* 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);
|
||||
@ -208,7 +214,27 @@ class custom_corners_renderer_factory extends standard_renderer_factory {
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +288,7 @@ class theme_overridden_renderer_factory extends standard_renderer_factory {
|
||||
$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);
|
||||
}
|
||||
@ -342,7 +368,7 @@ class template_renderer_factory extends renderer_factory_base {
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,6 +458,7 @@ class template_renderer extends moodle_renderer_base {
|
||||
protected $copiedclass;
|
||||
/** @var array of places to search for templates. */
|
||||
protected $searchpaths;
|
||||
protected $rendererfactory;
|
||||
|
||||
/**
|
||||
* Magic word used when breaking apart container templates to implement
|
||||
@ -445,11 +472,22 @@ class template_renderer extends moodle_renderer_base {
|
||||
* @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. */
|
||||
@ -704,6 +742,27 @@ class moodle_core_renderer extends moodle_renderer_base {
|
||||
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;
|
||||
@ -1114,7 +1173,8 @@ class moodle_core_renderer extends moodle_renderer_base {
|
||||
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();
|
||||
}
|
||||
@ -1142,7 +1202,7 @@ class moodle_core_renderer extends moodle_renderer_base {
|
||||
$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);
|
||||
@ -1471,6 +1531,8 @@ class cli_core_renderer extends moodle_core_renderer {
|
||||
* @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';
|
||||
@ -1495,11 +1557,8 @@ class custom_corners_core_renderer extends moodle_core_renderer {
|
||||
$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'));
|
||||
@ -1518,12 +1577,24 @@ class custom_corners_core_renderer extends moodle_core_renderer {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -335,14 +335,17 @@ class moodle_page {
|
||||
* @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;
|
||||
}
|
||||
@ -481,7 +484,6 @@ class moodle_page {
|
||||
}
|
||||
|
||||
moodle_setlocale();
|
||||
theme_setup();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -743,7 +745,6 @@ class moodle_page {
|
||||
$this->_course = new stdClass;
|
||||
$this->_course->id = 1;
|
||||
moodle_setlocale();
|
||||
theme_setup();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -97,8 +97,10 @@ global $COURSE;
|
||||
* $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
|
||||
@ -205,6 +207,11 @@ global $SCRIPT;
|
||||
/// 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);
|
||||
@ -249,9 +256,6 @@ global $SCRIPT;
|
||||
//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();
|
||||
|
||||
@ -346,7 +350,6 @@ global $SCRIPT;
|
||||
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);
|
||||
@ -369,19 +372,6 @@ global $SCRIPT;
|
||||
@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');
|
||||
@ -475,6 +465,15 @@ global $SCRIPT;
|
||||
$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')) {
|
||||
|
240
lib/setuplib.php
240
lib/setuplib.php
@ -26,6 +26,18 @@
|
||||
* @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
|
||||
*
|
||||
@ -38,6 +50,9 @@ class object {};
|
||||
/**
|
||||
* 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
|
||||
@ -124,11 +139,11 @@ class invalid_state_exception extends moodle_exception {
|
||||
* 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();
|
||||
@ -140,9 +155,8 @@ function default_exception_handler($ex, $isupgrade = false, $plugin = null) {
|
||||
$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;
|
||||
}
|
||||
@ -172,13 +186,7 @@ function default_exception_handler($ex, $isupgrade = false, $plugin = null) {
|
||||
$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
|
||||
}
|
||||
|
||||
@ -202,13 +210,7 @@ function print_error($errorcode, $module = 'error', $link = '', $a = null) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -229,15 +231,26 @@ function prepare_error_message($errorcode, $module, $link, $a) {
|
||||
$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;
|
||||
@ -265,56 +278,6 @@ function prepare_error_message($errorcode, $module, $link, $a) {
|
||||
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.
|
||||
*
|
||||
@ -526,7 +489,7 @@ function init_performance_info() {
|
||||
$PERF->logwrites = 0;
|
||||
if (function_exists('microtime')) {
|
||||
$PERF->starttime = microtime();
|
||||
}
|
||||
}
|
||||
if (function_exists('memory_get_usage')) {
|
||||
$PERF->startmemory = memory_get_usage();
|
||||
}
|
||||
@ -739,5 +702,130 @@ function init_eaccelerator() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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>';
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class testable_renderer_factory extends renderer_factory_base {
|
||||
|
||||
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) {
|
||||
@ -64,7 +64,7 @@ class testable_renderer_factory extends renderer_factory_base {
|
||||
*/
|
||||
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') {
|
||||
@ -722,7 +722,7 @@ class template_renderer_test extends UnitTestCase {
|
||||
$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();
|
||||
}
|
||||
|
||||
@ -787,7 +787,7 @@ class moodle_core_renderer_test extends UnitTestCase {
|
||||
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() {
|
||||
|
@ -3198,18 +3198,16 @@ function theme_setup($theme = '', $params=NULL) {
|
||||
$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';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,4 +184,13 @@ $THEME->custompix = false;
|
||||
/// "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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user