The error handling makes it a bit ugly, but the basic idea is:
- Get the grade data in a simple XML format, by fetching it from a URL that the other system provides.
- Pass that XML to the standard import_xml_grades function provided by the gradebook.
- If that seems to have worked OK, call grade_import_commit to actually save the data to the database.
Here is the full version of the key function, copied and pasted from our code. (This runs on cron, so error handling involves sending an email to a certain email address to notify of the error.)
/**
* Import the remote data into the gradebook
* @param string $cronuser the user to email status information to.
* @return boolean true if successful, false on failure.
*/
public function import_into_gradebook($cronuser) {
global $DB;
// Large files are likely to take their time and memory. Let PHP know
// that we'll take longer, and that the process should be recycled soon
// to free up memory.
set_time_limit(0);
raise_memory_limit(MEMORY_EXTRA);
//read the data from the url into a string
$errormess = '';
$commitmess = '';
if (!$text = file_get_contents($this->urlused)) {
mtrace('sending email to ' . $cronuser->email . ' ...');
email_to_user($cronuser, $cronuser, get_string('importerroremailsubj', 'externalquiz'),
externalquiz_autoimport::format_mail_error_message('importerrorreadfile',
$this->urlused));
mtrace(externalquiz_autoimport::format_message('importerrorreadfile', $this->urlused));
return false;
}
if (!$course = $DB->get_record('course', array('id'=>$this->course))) {
mtrace(externalquiz_autoimport::format_message('nocourseid', $this->course));
}
//check its valid XML
if ($text === false) {
$errormess = externalquiz_autoimport::format_message(
'importerrorreadfile', $this->urlused);
} else {
$olderrorsetting = libxml_use_internal_errors(true);
$a = simplexml_load_string($text);
libxml_use_internal_errors($olderrorsetting);
if ($a === false || $a->getName() != 'results') {
$errormess = externalquiz_autoimport::format_message(
'importerrornotvalidxml', $this->urlused);
} else if ($a->count() == 0) {
// The file was OK, but empty. In this case, we cannot pass it
// to Moodle because Moodle treats this as an error.
$commitmess = 'The file was empty, so nothing to import.';
} else {
//It was a valid XML string so lets import
$error = '';
if (!$course = $DB->get_record('course', array('id'=> $this->course))) {
$errormess = externalquiz_autoimport::format_message(
'nocourseid', $this->course);
} else {
$importcode = import_xml_grades($text, $course, $error);
if ($importcode !== false) {
// comit the code if we are up this far, stick the output
// in a string so we can email it.
ob_start();
if (grade_import_commit($this->course, $importcode, '', true)) {
// Bug 8970 we don't want output in the cron log on success.
} else {
$errormess = externalquiz_autoimport::format_message(
'importcommitedfailed', $this->urlused .
get_string('witherror', 'externalquiz', $error));
}
$commitmess = ob_get_contents();
ob_end_clean();
} else {
$errormess = externalquiz_autoimport::format_message(
'importtoGBfailed', $this->urlused .
get_string('witherror', 'externalquiz', $error));
}
}
}
}
if ($errormess) {
mtrace('sending error email to ' . $cronuser->email . ' ...');
mtrace($errormess);
email_to_user($cronuser, $cronuser, get_string('importerroremailsubj', 'externalquiz'),
externalquiz_autoimport::format_mail_error_message('importgradeerror',
$errormess));
}
return $commitmess && !$errormess;
}