MDL-21938 support for json renderer and error handler

This commit is contained in:
Petr Skoda
2010-03-28 09:05:47 +00:00
parent c6d2a6f4aa
commit 1adaa40466
6 changed files with 113 additions and 8 deletions
+1
View File
@@ -384,6 +384,7 @@ $string['prefixcannotbeempty'] = '<p>Error: database table prefix cannot be empt
$string['prefixtoolong'] = '<p>Error: database table prefix is too long ($a->dbfamily)</p>
<p>The site administrator must fix this problem. Maximum length for table prefixes in $a->dbfamily is $a->maxlength characters.</p>';
$string['processingstops'] = 'Processing stops here. Remaining records ignored.';
$string['redirecterrordetected'] = 'Unsupported redirect detected, script execution terminated';
$string['refoundtoorigi'] = 'Refunded to original amount: $a';
$string['refoundto'] = 'Can be refunded to $a';
$string['remotedownloaderror'] = 'Download of component to your server failed, please verify proxy settings, PHP cURL extension is highly recommended.<br /><br />You must download the <a href=\"$a->url\">$a->url</a> file manually, copy it to \"$a->dest\" in your server and unzip it there.';
+11 -3
View File
@@ -33,6 +33,9 @@ define('RENDERER_TARGET_GENERAL', 'general');
/** Plain text rendering for CLI scripts and cron */
define('RENDERER_TARGET_CLI', 'cli');
/** Plain text rendering for Ajax scripts*/
define('RENDERER_TARGET_AJAX', 'ajax');
/** Plain text rendering intended for sending via email */
define('RENDERER_TARGET_TEXTEMAIL', 'textemail');
@@ -120,13 +123,18 @@ abstract class renderer_factory_base implements renderer_factory {
* @return array two element array, first element is target, second the target suffix string
*/
protected function get_target_suffix($target) {
if (empty($target) and CLI_SCRIPT) {
// automatically guessed default for all CLI scripts
$target = RENDERER_TARGET_CLI;
if (empty($target)) {
// automatically guessed defaults
if (CLI_SCRIPT) {
$target = RENDERER_TARGET_CLI;
} else if (AJAX_SCRIPT) {
$target = RENDERER_TARGET_AJAX;
}
}
switch ($target) {
case RENDERER_TARGET_CLI: $suffix = '_cli'; break;
case RENDERER_TARGET_AJAX: $suffix = '_ajax'; break;
case RENDERER_TARGET_TEXTEMAIL: $suffix = '_textemail'; break;
case RENDERER_TARGET_HTMLEMAIL: $suffix = '_htmlemail'; break;
default: $target = RENDERER_TARGET_GENERAL; $suffix = '';
+51 -2
View File
@@ -1201,7 +1201,7 @@ class core_renderer extends renderer_base {
if (!empty($CFG->doctonewwindow)) {
$attributes['id'] = $this->add_action_handler(new popup_action('click', $url));
}
return html_writer::tag('a', $icon.$text, $attributes);
}
@@ -1283,7 +1283,7 @@ class core_renderer extends renderer_base {
$scalemax = $rating->settings->scale->scaleitems;
$ratingstr = round($rating->aggregate,1);
}
$aggstr = "{$ratingstr} / $scalemax ({$rating->count}) ";
if ($rating->settings->permissions->canviewall) {
@@ -2081,3 +2081,52 @@ class core_renderer_cli extends core_renderer {
}
}
/**
* A renderer that generates output for ajax scripts.
*
* This renderer prevents accidental sends back only json
* encoded error messages, all other output is ignored.
*
* @copyright 2010 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.0
*/
class core_renderer_ajax extends core_renderer {
/**
* Returns a template fragment representing a fatal error.
* @param string $message The message to output
* @param string $moreinfourl URL where more info can be found about the error
* @param string $link Link for the Continue button
* @param array $backtrace The execution backtrace
* @param string $debuginfo Debugging information
* @return string A template fragment for a fatal error
*/
public function fatal_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null) {
$e = new stdClass();
$e->error = $message;
$e->stacktrace = NULL;
$e->debuginfo = NULL;
if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) {
if (!empty($debuginfo)) {
$e->debuginfo = $debuginfo;
}
if (!empty($backtrace)) {
$e->stacktrace = format_backtrace($backtrace, true);
}
}
return json_encode($e);
}
public function notification($message, $classes = 'notifyproblem') {
}
public function redirect_message($encodedurl, $message, $delay, $debugdisableredirect) {
}
public function header() {
}
public function footer() {
}
public function heading($text, $level, $classes = 'main', $id = null) {
}
}
+5
View File
@@ -207,6 +207,11 @@ if (!defined('CLI_SCRIPT')) { // CLI_SCRIPT might be defined in 'fake' CLI scrip
}
}
// Detect ajax scripts - they are similar to CLI because we can not redirect, output html, etc.
if (!defined('AJAX_SCRIPT')) {
define('AJAX_SCRIPT', false);
}
// sometimes default PHP settings are borked on shared hosting servers, I wonder why they have to do that??
@ini_set('precision', 14); // needed for upgrades and gradebook
+39 -3
View File
@@ -224,9 +224,14 @@ function default_exception_handler($ex) {
// default exception handler MUST not throw any exceptions!!
// the problem here is we do not know if page already started or not, we only know that somebody messed up in outputlib or theme
// so we just print at least something instead of "Exception thrown without a stack frame in Unknown on line 0":-(
echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
$outinfo = get_exception_info($out_ex);
echo bootstrap_renderer::early_error_content($outinfo->message, $outinfo->moreinfourl, $outinfo->link, $outinfo->backtrace, $outinfo->debuginfo);
if (CLI_SCRIPT or AJAX_SCRIPT) {
// just ignore the error and send something back using the safest method
echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
} else {
echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
$outinfo = get_exception_info($out_ex);
echo bootstrap_renderer::early_error_content($outinfo->message, $outinfo->moreinfourl, $outinfo->link, $outinfo->backtrace, $outinfo->debuginfo);
}
}
}
@@ -950,6 +955,37 @@ width: 80%; -moz-border-radius: 20px; padding: 15px">
* @return string
*/
public static function early_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null) {
global $CFG;
if (CLI_SCRIPT) {
echo "!!! $message !!!\n";
if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) {
if (!empty($debuginfo)) {
echo "\nDebug info: $debuginfo";
}
if (!empty($backtrace)) {
echo "\nStack trace: " . format_backtrace($backtrace, true);
}
}
return;
} else if (AJAX_SCRIPT) {
$e = new stdClass();
$e->error = $message;
$e->stacktrace = NULL;
$e->debuginfo = NULL;
if (!empty($CFG->debug) and $CFG->debug >= DEBUG_DEVELOPER) {
if (!empty($debuginfo)) {
$e->debuginfo = $debuginfo;
}
if (!empty($backtrace)) {
$e->stacktrace = format_backtrace($backtrace, true);
}
}
echo json_encode($e);
return;
}
// In the name of protocol correctness, monitoring and performance
// profiling, set the appropriate error headers for machine consumption
if (isset($_SERVER['SERVER_PROTOCOL'])) {
+6
View File
@@ -2523,6 +2523,12 @@ function notice ($message, $link='', $course=NULL) {
function redirect($url, $message='', $delay=-1) {
global $OUTPUT, $PAGE, $SESSION, $CFG;
if (CLI_SCRIPT or AJAX_SCRIPT) {
// this is wrong - developers should not use redirect in these scripts,
// but it should not be very likely
throw new moodle_exception('redirecterrordetected', 'error');
}
if ($url instanceof moodle_url) {
$url = $url->out(false);
}