Permalink
Browse files

Merge branch 'MOODLE_22_STABLE' into install_22_STABLE

  • Loading branch information...
2 parents 986343b + 555112a commit eca810808c72f9ac62bd919168b4c047eba0c0fa AMOS bot committed Sep 8, 2012
Showing with 837 additions and 302 deletions.
  1. +111 −0 admin/environment.xml
  2. +7 −2 backup/moodle2/backup_custom_fields.php
  3. +17 −0 backup/upgrade.txt
  4. +9 −5 backup/util/dbops/backup_plan_dbops.class.php
  5. +21 −1 backup/util/dbops/restore_dbops.class.php
  6. +44 −23 backup/util/helper/backup_cron_helper.class.php
  7. +11 −0 backup/util/plan/backup_structure_step.class.php
  8. +28 −0 backup/util/plan/base_task.class.php
  9. +8 −2 backup/util/plan/restore_structure_step.class.php
  10. +73 −0 backup/util/structure/backup_nested_element.class.php
  11. +3 −0 backup/util/ui/backup_ui_stage.class.php
  12. +3 −0 backup/util/ui/restore_ui_stage.class.php
  13. +14 −12 blocks/completionstatus/block_completionstatus.php
  14. +127 −112 blocks/completionstatus/details.php
  15. +1 −0 blocks/completionstatus/lang/en/block_completionstatus.php
  16. +9 −0 blog/external_blogs.php
  17. +2 −3 blog/locallib.php
  18. +1 −1 enrol/manual/yui/quickenrolment/quickenrolment.js
  19. +11 −11 enrol/paypal/ipn.php
  20. +15 −0 filter/mediaplugin/filter.php
  21. +3 −0 filter/mediaplugin/simpletest/testfiltermediaplugin.php
  22. +2 −1 grade/edit/tree/category_form.php
  23. +1 −1 lang/en/admin.php
  24. +2 −0 lang/en/backup.php
  25. +1 −0 lang/en/moodle.php
  26. +1 −1 lib/accesslib.php
  27. +10 −0 lib/db/upgrade.php
  28. +11 −9 lib/googleapi.php
  29. +33 −3 lib/moodlelib.php
  30. +7 −5 lib/questionlib.php
  31. +1 −1 mod/data/field/checkbox/mod.html
  32. +5 −4 mod/data/field/latlong/field.class.php
  33. +1 −1 mod/data/field/menu/mod.html
  34. +1 −1 mod/data/field/multimenu/mod.html
  35. +2 −2 mod/data/field/picture/field.class.php
  36. +4 −4 mod/data/field/picture/mod.html
  37. +1 −1 mod/data/field/radiobutton/mod.html
  38. +2 −2 mod/data/field/textarea/mod.html
  39. +11 −17 mod/data/lib.php
  40. +32 −0 mod/data/styles.css
  41. +7 −7 mod/data/templates.php
  42. +17 −1 mod/quiz/lib.php
  43. +1 −0 mod/quiz/styles.css
  44. +5 −2 question/category_class.php
  45. +3 −0 question/type/multichoice/styles.css
  46. +10 −3 report/backups/index.php
  47. +2 −2 report/stats/lib.php
  48. +1 −1 report/stats/settings.php
  49. +38 −10 repository/flickr/lib.php
  50. +48 −26 repository/flickr_public/lib.php
  51. +3 −1 repository/googledocs/lib.php
  52. +6 −0 repository/lib.php
  53. +10 −6 repository/manage_instances.php
  54. +4 −0 theme/afterburner/style/afterburner_styles.css
  55. +1 −2 theme/anomaly/style/general.css
  56. +1 −0 theme/base/style/admin.css
  57. +30 −13 user/profile.php
  58. +2 −1 user/selector/module.js
  59. +2 −2 version.php
View
@@ -655,4 +655,115 @@
</PHP_SETTING>
</PHP_SETTINGS>
</MOODLE>
+ <MOODLE version="2.4" requires="2.2">
+ <UNICODE level="required">
+ <FEEDBACK>
+ <ON_ERROR message="unicoderequired" />
+ </FEEDBACK>
+ </UNICODE>
+ <DATABASE level="required">
+ <VENDOR name="mysql" version="5.1.33" />
+ <VENDOR name="postgres" version="8.3" />
+ <VENDOR name="mssql" version="9.0" />
+ <VENDOR name="odbc_mssql" version="9.0" />
+ <VENDOR name="mssql_n" version="9.0" />
+ <VENDOR name="oracle" version="10.2" />
+ <VENDOR name="sqlite" version="2.0" />
+ </DATABASE>
+ <PHP version="5.3.2" level="required">
+ </PHP>
+ <PHP_EXTENSIONS>
+ <PHP_EXTENSION name="iconv" level="required">
+ <FEEDBACK>
+ <ON_CHECK message="iconvrequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="mbstring" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="mbstringrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="curl" level="required">
+ <FEEDBACK>
+ <ON_CHECK message="curlrequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="openssl" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="opensslrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="tokenizer" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="tokenizerrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="xmlrpc" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="xmlrpcrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="soap" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="soaprecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="ctype" level="required">
+ <FEEDBACK>
+ <ON_ERROR message="ctyperequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="zip" level="required">
+ <FEEDBACK>
+ <ON_ERROR message="ziprequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="gd" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="gdrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="simplexml" level="required">
+ <FEEDBACK>
+ <ON_CHECK message="simplexmlrequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="spl" level="required">
+ <FEEDBACK>
+ <ON_CHECK message="splrequired" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="pcre" level="required">
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="dom" level="required">
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="xml" level="required">
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="intl" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="intlrecommended" />
+ </FEEDBACK>
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="json" level="required">
+ </PHP_EXTENSION>
+ <PHP_EXTENSION name="hash" level="required"/>
+ </PHP_EXTENSIONS>
+ <PHP_SETTINGS>
+ <PHP_SETTING name="memory_limit" value="40M" level="required">
+ <FEEDBACK>
+ <ON_ERROR message="settingmemorylimit" />
+ </FEEDBACK>
+ </PHP_SETTING>
+ <PHP_SETTING name="safe_mode" value="0" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="settingsafemode" />
+ </FEEDBACK>
+ </PHP_SETTING>
+ <PHP_SETTING name="file_uploads" value="1" level="optional">
+ <FEEDBACK>
+ <ON_CHECK message="settingfileuploads" />
+ </FEEDBACK>
+ </PHP_SETTING>
+ </PHP_SETTINGS>
+ </MOODLE>
</COMPATIBILITY_MATRIX>
@@ -91,14 +91,19 @@ public function process($processor) {
if (is_null($this->backupid)) {
$this->backupid = $processor->get_var(backup::VAR_BACKUPID);
}
- parent::process($processor);
+ return parent::process($processor);
}
public function fill_values($values) {
// Fill values
parent::fill_values($values);
// Do our own tasks (copy file from moodle to backup)
- backup_file_manager::copy_file_moodle2backup($this->backupid, $values);
+ try {
+ backup_file_manager::copy_file_moodle2backup($this->backupid, $values);
+ } catch (file_exception $e) {
+ $this->add_result(array('missing_files_in_pool' => true));
+ $this->add_log('missing file in pool: ' . $e->debuginfo, backup::LOG_WARNING);
+ }
}
}
View
@@ -0,0 +1,17 @@
+This files describes API changes in /backup/*,
+information provided here is intended especially for developers.
+
+=== 2.4 ===
+
+* Since 2.3.1+ the backup file name schema has changed. The ID of the course will always be part of
+ the filename regardless of the setting 'backup_shortname'. See MDL-33812.
+
+=== 2.3 ===
+
+* Since 2.3.1+ the backup file name schema has changed. The ID of the course will always be part of
+ the filename regardless of the setting 'backup_shortname'. See MDL-33812.
+
+=== 2.2 ===
+
+* Since 2.2.4+ the backup file name schema has changed. The ID of the course will always be part of
+ the filename regardless of the setting 'backup_shortname'. See MDL-33812.
@@ -197,19 +197,19 @@ public static function get_mnet_localhost_wwwroot() {
* @param int $courseid/$sectionid/$cmid
* @param bool $users Should be true is users were included in the backup
* @param bool $anonymised Should be true is user information was anonymized.
- * @param bool $useidasname true to use id, false to use strings (default)
+ * @param bool $useidonly only use the ID in the file name
* @return string The filename to use
*/
- public static function get_default_backup_filename($format, $type, $id, $users, $anonymised, $useidasname = false) {
+ public static function get_default_backup_filename($format, $type, $id, $users, $anonymised, $useidonly = false) {
global $DB;
// Calculate backup word
$backupword = str_replace(' ', '_', moodle_strtolower(get_string('backupfilename')));
$backupword = trim(clean_filename($backupword), '_');
+ // Not $useidonly, lets fetch the name
$shortname = '';
- // Not $useidasname, lets calculate it, else $id will be used
- if (!$useidasname) {
+ if (!$useidonly) {
// Calculate proper name element (based on type)
switch ($type) {
case backup::TYPE_1COURSE:
@@ -231,7 +231,11 @@ public static function get_default_backup_filename($format, $type, $id, $users,
$shortname = moodle_strtolower(trim(clean_filename($shortname), '_'));
}
- $name = empty($shortname) ? $id : $shortname;
+ // The name will always contain the ID, but we append the course short name if requested.
+ $name = $id;
+ if (!$useidonly && $shortname != '') {
+ $name .= '-' . $shortname;
+ }
// Calculate date
$backupdateformat = str_replace(' ', '_', get_string('backupnameformat', 'langconfig'));
@@ -622,10 +622,24 @@ public static function restore_get_questions($restoreid, $qcatid) {
* Given one component/filearea/context and
* optionally one source itemname to match itemids
* put the corresponding files in the pool
+ *
+ * @param string $basepath the full path to the root of unzipped backup file
+ * @param string $restoreid the restore job's identification
+ * @param string $component
+ * @param string $filearea
+ * @param int $oldcontextid
+ * @param int $dfltuserid default $file->user if the old one can't be mapped
+ * @param string|null $itemname
+ * @param int|null $olditemid
+ * @param int|null $forcenewcontextid explicit value for the new contextid (skip mapping)
+ * @param bool $skipparentitemidctxmatch
+ * @return array of result object
*/
public static function send_files_to_pool($basepath, $restoreid, $component, $filearea, $oldcontextid, $dfltuserid, $itemname = null, $olditemid = null, $forcenewcontextid = null, $skipparentitemidctxmatch = false) {
global $DB;
+ $results = array();
+
if ($forcenewcontextid) {
// Some components can have "forced" new contexts (example: questions can end belonging to non-standard context mappings,
// with questions originally at system/coursecat context in source being restored to course context in target). So we need
@@ -701,7 +715,12 @@ public static function send_files_to_pool($basepath, $restoreid, $component, $fi
// Find file in backup pool
$backuppath = $basepath . backup_file_manager::get_backup_content_file_location($file->contenthash);
if (!file_exists($backuppath)) {
- throw new restore_dbops_exception('file_not_found_in_pool', $file);
+ $result = new stdClass();
+ $result->code = 'file_missing_in_backup';
+ $result->message = sprintf('missing file %s%s in backup', $file->filepath, $file->filename);
+ $result->level = backup::LOG_WARNING;
+ $results[] = $result;
+ continue;
}
if (!$fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) {
$file_record = array(
@@ -721,6 +740,7 @@ public static function send_files_to_pool($basepath, $restoreid, $component, $fi
}
}
$rs->close();
+ return $results;
}
/**
@@ -46,6 +46,8 @@
const BACKUP_STATUS_UNFINISHED = 2;
/** Course automated backup was skipped */
const BACKUP_STATUS_SKIPPED = 3;
+ /** Course automated backup had warnings */
+ const BACKUP_STATUS_WARNING = 4;
/** Run if required by the schedule set in config. Default. **/
const RUN_ON_SCHEDULE = 0;
@@ -139,7 +141,7 @@ public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDUL
$params = array('courseid' => $course->id, 'time' => $now-31*24*60*60, 'action' => '%view%');
$logexists = $DB->record_exists_select('log', $sqlwhere, $params);
if (!$logexists) {
- $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_SKIPPED;
+ $backupcourse->laststatus = self::BACKUP_STATUS_SKIPPED;
$backupcourse->nextstarttime = $nextstarttime;
$DB->update_record('backup_courses', $backupcourse);
mtrace('Skipping unchanged course '.$course->fullname);
@@ -160,7 +162,7 @@ public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDUL
$starttime = time();
$backupcourse->laststarttime = time();
- $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_UNFINISHED;
+ $backupcourse->laststatus = self::BACKUP_STATUS_UNFINISHED;
$DB->update_record('backup_courses', $backupcourse);
$backupcourse->laststatus = backup_cron_automated_helper::launch_automated_backup($course, $backupcourse->laststarttime, $admin->id);
@@ -169,7 +171,7 @@ public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDUL
$DB->update_record('backup_courses', $backupcourse);
- if ($backupcourse->laststatus) {
+ if ($backupcourse->laststatus === self::BACKUP_STATUS_OK) {
// Clean up any excess course backups now that we have
// taken a successful backup.
$removedcount = backup_cron_automated_helper::remove_excess_backups($course);
@@ -188,17 +190,18 @@ public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDUL
$message = "";
$count = backup_cron_automated_helper::get_backup_status_array();
- $haserrors = ($count[backup_cron_automated_helper::BACKUP_STATUS_ERROR] != 0 || $count[backup_cron_automated_helper::BACKUP_STATUS_UNFINISHED] != 0);
+ $haserrors = ($count[self::BACKUP_STATUS_ERROR] != 0 || $count[self::BACKUP_STATUS_UNFINISHED] != 0);
//Build the message text
//Summary
$message .= get_string('summary')."\n";
$message .= "==================================================\n";
$message .= " ".get_string('courses').": ".array_sum($count)."\n";
- $message .= " ".get_string('ok').": ".$count[backup_cron_automated_helper::BACKUP_STATUS_OK]."\n";
- $message .= " ".get_string('skipped').": ".$count[backup_cron_automated_helper::BACKUP_STATUS_SKIPPED]."\n";
- $message .= " ".get_string('error').": ".$count[backup_cron_automated_helper::BACKUP_STATUS_ERROR]."\n";
- $message .= " ".get_string('unfinished').": ".$count[backup_cron_automated_helper::BACKUP_STATUS_UNFINISHED]."\n\n";
+ $message .= " ".get_string('ok').": ".$count[self::BACKUP_STATUS_OK]."\n";
+ $message .= " ".get_string('skipped').": ".$count[self::BACKUP_STATUS_SKIPPED]."\n";
+ $message .= " ".get_string('error').": ".$count[self::BACKUP_STATUS_ERROR]."\n";
+ $message .= " ".get_string('unfinished').": ".$count[self::BACKUP_STATUS_UNFINISHED]."\n";
+ $message .= " ".get_string('warning').": ".$count[self::BACKUP_STATUS_WARNING]."\n\n";
//Reference
if ($haserrors) {
@@ -261,6 +264,7 @@ public static function get_backup_status_array() {
self::BACKUP_STATUS_OK => 0,
self::BACKUP_STATUS_UNFINISHED => 0,
self::BACKUP_STATUS_SKIPPED => 0,
+ self::BACKUP_STATUS_WARNING => 0
);
$statuses = $DB->get_records_sql('SELECT DISTINCT bc.laststatus, COUNT(bc.courseid) AS statuscount FROM {backup_courses} bc GROUP BY bc.laststatus');
@@ -334,7 +338,7 @@ public static function calculate_next_automated_backup($timezone, $now) {
*/
public static function launch_automated_backup($course, $starttime, $userid) {
- $outcome = true;
+ $outcome = self::BACKUP_STATUS_OK;
$config = get_config('backup');
$bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_AUTOMATED, $userid);
@@ -369,6 +373,7 @@ public static function launch_automated_backup($course, $starttime, $userid) {
$bc->execute_plan();
$results = $bc->get_results();
+ $outcome = self::outcome_from_results($results);
$file = $results['backup_destination']; // may be empty if file already moved to target location
$dir = $config->backup_auto_destination;
$storage = (int)$config->backup_auto_storage;
@@ -377,8 +382,10 @@ public static function launch_automated_backup($course, $starttime, $userid) {
}
if ($file && !empty($dir) && $storage !== 0) {
$filename = backup_plan_dbops::get_default_backup_filename($format, $type, $course->id, $users, $anonymised, !$config->backup_shortname);
- $outcome = $file->copy_content_to($dir.'/'.$filename);
- if ($outcome && $storage === 1) {
+ if (!$file->copy_content_to($dir.'/'.$filename)) {
+ $outcome = self::BACKUP_STATUS_ERROR;
+ }
+ if ($outcome != self::BACKUP_STATUS_ERROR && $storage === 1) {
$file->delete();
}
}
@@ -387,7 +394,7 @@ public static function launch_automated_backup($course, $starttime, $userid) {
$bc->log('backup_auto_failed_on_course', backup::LOG_ERROR, $course->shortname); // Log error header.
$bc->log('Exception: ' . $e->errorcode, backup::LOG_ERROR, $e->a, 1); // Log original exception problem.
$bc->log('Debug: ' . $e->debuginfo, backup::LOG_DEBUG, null, 1); // Log original debug information.
- $outcome = false;
+ $outcome = self::BACKUP_STATUS_ERROR;
}
$bc->destroy();
@@ -397,6 +404,30 @@ public static function launch_automated_backup($course, $starttime, $userid) {
}
/**
+ * Returns the backup outcome by analysing its results.
+ *
+ * @param array $results returned by a backup
+ * @return int {@link self::BACKUP_STATUS_OK} and other constants
+ */
+ public static function outcome_from_results($results) {
+ $outcome = self::BACKUP_STATUS_OK;
+ foreach ($results as $code => $value) {
+ // Each possible error and warning code has to be specified in this switch
+ // which basically analyses the results to return the correct backup status.
+ switch ($code) {
+ case 'missing_files_in_pool':
+ $outcome = self::BACKUP_STATUS_WARNING;
+ break;
+ }
+ // If we found the highest error level, we exit the loop.
+ if ($outcome == self::BACKUP_STATUS_ERROR) {
+ break;
+ }
+ }
+ return $outcome;
+ }
+
+ /**
* Removes deleted courses fromn the backup_courses table so that we don't
* waste time backing them up.
*
@@ -530,17 +561,7 @@ public static function remove_excess_backups($course) {
if (!empty($dir) && ($storage == 1 || $storage == 2)) {
// Calculate backup filename regex, ignoring the date/time/info parts that can be
// variable, depending of languages, formats and automated backup settings
-
- // MDL-33531: use different filenames depending on backup_shortname option
- if ( !empty($config->backup_shortname) ) {
- $context = get_context_instance(CONTEXT_COURSE, $course->id);
- $courseref = format_string($course->shortname, true, array('context' => $context));
- $courseref = str_replace(' ', '_', $courseref);
- $courseref = moodle_strtolower(trim(clean_filename($courseref), '_'));
- } else {
- $courseref = $course->id;
- }
- $filename = $backupword . '-' . backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' .$courseref . '-';
+ $filename = $backupword . '-' . backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' .$course->id . '-';
$regex = '#^'.preg_quote($filename, '#').'.*\.mbz$#';
// Store all the matching files into fullpath => timemodified array
Oops, something went wrong.

0 comments on commit eca8108

Please sign in to comment.