MDL-23797 improved detection of PAGE->context abuse andproblems; fixed incorrect use of this->context instead of this->_context; missing PAGE->context does not throw fatal error any more

This commit is contained in:
Petr Skoda 2010-08-16 19:11:21 +00:00
parent df92ba9a43
commit eb5bdb3510
4 changed files with 65 additions and 26 deletions

View file

@ -5391,7 +5391,7 @@ class admin_setting_manageportfolio extends admin_setting {
function admin_externalpage_setup($section, $extrabutton = '', array $extraurlparams = null, $actualurl = '') {
global $CFG, $PAGE, $USER, $SITE, $OUTPUT;
$PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
$PAGE->set_context(null); // hack - set context to something, by default to system context
$site = get_site();
require_login();

View file

@ -1964,6 +1964,7 @@ EOD;
// can not be used from command line or when outputting custom XML
@header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found');
}
$this->page->set_context(null); // ugly hack - make sure page context is set to something, we do not want bogus warnings here
$this->page->set_url('/'); // no url
//$this->page->set_pagelayout('base'); //TODO: MDL-20676 blocks on error pages are weird, unfortunately it somehow detect the pagelayout from URL :-(
$this->page->set_title(get_string('error'));
@ -2581,6 +2582,9 @@ class core_renderer_ajax extends core_renderer {
*/
public function fatal_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null) {
global $FULLME, $USER;
$this->page->set_context(null); // ugly hack - make sure page context is set to something, we do not want bogus warnings here
$e = new stdClass();
$e->error = $message;
$e->stacktrace = NULL;

View file

@ -328,12 +328,13 @@ class moodle_page {
*/
protected function magic_get_context() {
if (is_null($this->_context)) {
if (CLI_SCRIPT) {
// cli scripts work in system context, do not annoy devs with fatal errors here
$this->_context = get_context_instance(CONTEXT_SYSTEM);
if (CLI_SCRIPT or NO_MOODLE_COOKIES) {
// cli scripts work in system context, do not annoy devs with debug info
// very few scripts do not use cookies, we can safely use system as default context there
} else {
throw new coding_exception('$PAGE->context accessed before it was known.');
debugging('Coding problem: this page does not set $PAGE->context properly.');
}
$this->_context = get_context_instance(CONTEXT_SYSTEM);
}
return $this->_context;
}
@ -641,7 +642,7 @@ class moodle_page {
if ($this->_legacypageobject) {
return $this->_legacypageobject->user_allowed_editing();
}
return has_any_capability($this->all_editing_caps(), $this->context);
return has_any_capability($this->all_editing_caps(), $this->_context);
}
/**
@ -652,7 +653,7 @@ class moodle_page {
$summary = '';
$summary .= 'General type: ' . $this->pagelayout . '. ';
if (!during_initial_install()) {
$summary .= 'Context ' . print_context_name($this->context) . ' (context id ' . $this->context->id . '). ';
$summary .= 'Context ' . print_context_name($this->_context) . ' (context id ' . $this->_context->id . '). ';
}
$summary .= 'Page type ' . $this->pagetype . '. ';
if ($this->subpage) {
@ -723,6 +724,28 @@ class moodle_page {
* @param object $context a context object, normally obtained with get_context_instance.
*/
public function set_context($context) {
if ($context === null) {
// extremely ugly hack which sets context to some value in order to prevent warnings,
// use only for core error handling!!!!
if (!$this->_context) {
$this->_context = get_context_instance(CONTEXT_SYSTEM);
}
return;
}
// ideally we should set context only once
if (isset($this->_context)) {
if ($context->id == $this->_context->id) {
// fine - no change needed
} else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) {
// hmm - not ideal, but it might produce too many warnings due to the design of require_login
} else {
// we do not want devs to do weird switching of context levels on the fly,
// because we might have used the context already such as in text filter in page title
debugging('Coding problem: unsupported modification of PAGE->context from '.$this->_context->contextlevel.' to '.$context->contextlevel);
}
}
$this->_context = $context;
}
@ -732,6 +755,8 @@ class moodle_page {
* @param objcet $cm a full cm object obtained from get_coursemodule_from_id or get_coursemodule_from_instance.
*/
public function set_cm($cm, $course = null, $module = null) {
global $DB;
if (!isset($cm->name) || !isset($cm->modname) || !isset($cm->id)) {
throw new coding_exception('The $cm you set on $PAGE must have been obtained with get_coursemodule_from_id or get_coursemodule_from_instance. That is, the ->name and -> modname fields must be present and correct.');
}
@ -742,8 +767,7 @@ class moodle_page {
}
if (!$this->_course || $this->_course->id != $cm->course) {
if (!$course) {
global $DB;
$course = $DB->get_record('course', array('id' => $cm->course));
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
}
if ($course->id != $cm->course) {
throw new coding_exception('The course you passed to $PAGE->set_cm does not seem to correspond to the $cm.');
@ -1115,6 +1139,11 @@ class moodle_page {
return;
}
if (!during_initial_install()) {
// detect PAGE->context mess
$this->magic_get_context();
}
if (!$this->_course && !during_initial_install()) {
$this->set_course($SITE);
}
@ -1290,7 +1319,7 @@ class moodle_page {
if (!during_initial_install()) {
$this->add_body_class('course-' . $this->_course->id);
$this->add_body_class('context-' . $this->context->id);
$this->add_body_class('context-' . $this->_context->id);
}
if (!empty($this->_cm)) {
@ -1669,10 +1698,10 @@ function page_map_class($type, $classname = NULL) {
* @deprecated since Moodle 2.0
* Parent class from which all Moodle page classes derive
*
* @package moodlecore
* @subpackage pages
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core
* @subpackage lib
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class page_base extends moodle_page {
/**
@ -1707,10 +1736,10 @@ class page_base extends moodle_page {
* Although this does nothing, this class declaration should be left for now
* since there may be legacy class doing class page_... extends page_course
*
* @package moodlecore
* @subpackage pages
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core
* @subpackage lib
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class page_course extends page_base {
}
@ -1719,10 +1748,10 @@ class page_course extends page_base {
* @deprecated since Moodle 2.0
* Class that models the common parts of all activity modules
*
* @package moodlecore
* @subpackage pages
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core
* @subpackage lib
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class page_generic_activity extends page_base {
// Although this function is deprecated, it should be left here because

View file

@ -963,18 +963,24 @@ class bootstrap_renderer {
$recursing = is_early_init($backtrace);
}
$earlymethods = array(
'fatal_error' => 'early_error',
'notification' => 'early_notification',
);
// If lib/outputlib.php has been loaded, call it.
if (!empty($PAGE) && !$recursing) {
if (array_key_exists($method, $earlymethods)) {
//prevent PAGE->context warnings - exceptions might appear before we set any context
$PAGE->set_context(null);
}
$PAGE->initialise_theme_and_output();
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);
}