MDL-45027 Availability API: Better handling of invalid data in GUI

If there is invalid data in the availability condition (note: this
should not happen, but can do in unusual situations, such as
specifying a date after 2038 in 32-bit PHP), this should not
leave the course so broken that users cannot edit the activity and
update it.
This commit is contained in:
sam marshall 2014-04-09 14:48:32 +01:00
parent af8a43248e
commit 2a848ab9e2
6 changed files with 60 additions and 29 deletions

View File

@ -172,7 +172,7 @@ abstract class frontend {
$decoded = json_decode($data['availabilityconditionsjson']);
if (!$decoded) {
// This shouldn't be possible.
throw new coding_exception('Invalid JSON from availabilityconditionsjson field');
throw new \coding_exception('Invalid JSON from availabilityconditionsjson field');
}
if (!empty($decoded->errors)) {
$error = '';

View File

@ -193,12 +193,7 @@ abstract class info {
$tree = $this->get_availability_tree();
$result = $tree->check_available(false, $this, $grabthelot, $userid);
} catch (\coding_exception $e) {
// We catch the message because it causes fatal problems in most of
// the GUI if this exception gets thrown (you can't edit the
// activity to fix it). Obviously it should never happen anyway, but
// just in case.
debugging('Error processing availability data for ‘' .
$this->get_thing_name() . '’: ' . s($e->a), DEBUG_DEVELOPER);
$this->warn_about_invalid_availability($e);
$this->modinfo = null;
return false;
}
@ -237,7 +232,12 @@ abstract class info {
if (is_null($this->availability)) {
return true;
} else {
return $this->get_availability_tree()->is_available_for_all();
try {
return $this->get_availability_tree()->is_available_for_all();
} catch (\coding_exception $e) {
$this->warn_about_invalid_availability($e);
return false;
}
}
}
@ -273,13 +273,32 @@ abstract class info {
$this->modinfo = null;
return $result;
} catch (\coding_exception $e) {
// Again we catch the message to avoid problems in GUI.
debugging('Error processing availability data for ‘' .
$this->get_thing_name() . '’: ' . s($e->a), DEBUG_DEVELOPER);
$this->warn_about_invalid_availability($e);
return false;
}
}
/**
* In some places we catch coding_exception because if a bug happens, it
* would be fatal for the course page GUI; instead we just show a developer
* debug message.
*
* @param \coding_exception $e Exception that occurred
*/
protected function warn_about_invalid_availability(\coding_exception $e) {
$name = $this->get_thing_name();
// If it occurs while building modinfo based on somebody calling $cm->name,
// we can't get $cm->name, and this line will cause a warning.
$htmlname = @$this->format_info($name, $this->course);
if ($htmlname === '') {
// So instead use the numbers (cmid) from the tag.
$htmlname = preg_replace('~[^0-9]~', '', $name);
}
$info = 'Error processing availability data for ‘' . $htmlname
. '’: ' . s($e->a);
debugging($info, DEBUG_DEVELOPER);
}
/**
* Called during restore (near end of restore). Updates any necessary ids
* and writes the updated tree to the database. May output warnings if

View File

@ -96,12 +96,16 @@ M.core_availability.form = {
// Get top-level tree as JSON.
var value = this.field.get('value');
if (value === '') {
this.rootList = new M.core_availability.List(null, true);
} else {
var data = Y.JSON.parse(value);
this.rootList = new M.core_availability.List(data, true);
var data = null;
if (value !== '') {
try {
data = Y.JSON.parse(value);
} catch(x) {
// If the JSON data is not valid, treat it as empty.
this.field.set('value', '');
}
}
this.rootList = new M.core_availability.List(data, true);
this.mainDiv.appendChild(this.rootList.node);
// Update JSON value after loading (to reflect any changes that need

File diff suppressed because one or more lines are too long

View File

@ -96,12 +96,16 @@ M.core_availability.form = {
// Get top-level tree as JSON.
var value = this.field.get('value');
if (value === '') {
this.rootList = new M.core_availability.List(null, true);
} else {
var data = Y.JSON.parse(value);
this.rootList = new M.core_availability.List(data, true);
var data = null;
if (value !== '') {
try {
data = Y.JSON.parse(value);
} catch(x) {
// If the JSON data is not valid, treat it as empty.
this.field.set('value', '');
}
}
this.rootList = new M.core_availability.List(data, true);
this.mainDiv.appendChild(this.rootList.node);
// Update JSON value after loading (to reflect any changes that need

View File

@ -94,12 +94,16 @@ M.core_availability.form = {
// Get top-level tree as JSON.
var value = this.field.get('value');
if (value === '') {
this.rootList = new M.core_availability.List(null, true);
} else {
var data = Y.JSON.parse(value);
this.rootList = new M.core_availability.List(data, true);
var data = null;
if (value !== '') {
try {
data = Y.JSON.parse(value);
} catch(x) {
// If the JSON data is not valid, treat it as empty.
this.field.set('value', '');
}
}
this.rootList = new M.core_availability.List(data, true);
this.mainDiv.appendChild(this.rootList.node);
// Update JSON value after loading (to reflect any changes that need