Skip to content

Commit f6a0686

Browse files
committed
WIP more fixups and tests
1 parent 6b520de commit f6a0686

File tree

5 files changed

+634
-75
lines changed

5 files changed

+634
-75
lines changed

admin/settings/courses.php

+32
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,38 @@
439439
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_legacyfiles',
440440
new lang_string('generallegacyfiles', 'backup'),
441441
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
442+
443+
// Filename defaults.
444+
$temp->add(new admin_setting_heading('defaultfilenamesettings', new lang_string('defaultfilenamesettings', 'backup'), ''));
445+
$temp->add(new admin_setting_description('defaultfilenamesettings_help', '', new lang_string('defaultfilenamesettings_help', 'backup'), ''));
446+
447+
$temp->add(new admin_setting_configtextarea('backup/backup_default_filename_template_course',
448+
new lang_string('defaultbackupfilenamecourse', 'backup'),
449+
new lang_string('defaultbackupfilenamecourse_desc', 'backup'),
450+
'{{#str}}backupfilename{{/str}}-{{format}}-{{type}}-{{id}}{{^useidonly}}-{{course.shortname}}{{/useidonly}}-{{date}}{{^users}}-nu{{/users}}{{#anonymised}}{{#users}}-an{{/users}}{{/anonymised}}{{^files}}-nf{{/files}}',
451+
PARAM_TEXT,
452+
'60',
453+
'3'
454+
));
455+
456+
$temp->add(new admin_setting_configtextarea('backup/backup_default_filename_template_section',
457+
new lang_string('defaultbackupfilenamesection', 'backup'),
458+
new lang_string('defaultbackupfilenamesection_desc', 'backup'),
459+
'{{#str}}backupfilename{{/str}}-{{format}}-{{type}}-{{id}}{{^useidonly}}{{#section.name}}-{{section.name}}{{/section.name}}{{^section.name}}-{{section.section}}{{/section.name}}{{/useidonly}}-{{date}}{{^users}}-nu{{/users}}{{#anonymised}}{{#users}}-an{{/users}}{{/anonymised}}{{^files}}-nf{{/files}}',
460+
PARAM_TEXT,
461+
'60',
462+
'3'
463+
));
464+
465+
$temp->add(new admin_setting_configtextarea('backup/backup_default_filename_template_activity',
466+
new lang_string('defaultbackupfilenameactivity', 'backup'),
467+
new lang_string('defaultbackupfilenameactivity_desc', 'backup'),
468+
'{{#str}}backupfilename{{/str}}-{{format}}-{{type}}-{{id}}{{^useidonly}}-{{activity.modname}}{{id}}{{/useidonly}}-{{date}}{{^users}}-nu{{/users}}{{#anonymised}}{{#users}}-an{{/users}}{{/anonymised}}{{^files}}-nf{{/files}}',
469+
PARAM_TEXT,
470+
'60',
471+
'3'
472+
));
473+
442474
$ADMIN->add('backups', $temp);
443475

444476
// Create a page for general import configuration and defaults.

backup/util/dbops/backup_plan_dbops.class.php

+73-74
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2323
*/
2424

25+
use core\exception\coding_exception;
2526
use core\output\mustache_engine;
2627
use core\output\mustache_string_helper;
2728

@@ -202,7 +203,7 @@ public static function get_mnet_localhost_wwwroot() {
202203
* Default format is (see MDL-22145)
203204
* backup word - format - type - name - date - info . mbz
204205
* where name is variable (course shortname, section name/id, activity modulename + cmid)
205-
* and info can be (nu = no user info, an = anonymized). The last param $useidasname,
206+
* and info can be (nu = no user info, an = anonymized). The last param $useidonly,
206207
* defaulting to false, allows to replace the course shortname by the course id (used
207208
* by automated backups, to avoid non-ascii chars in OS filesystem)
208209
*
@@ -222,88 +223,87 @@ public static function get_default_backup_filename($format, $type, $id, $users,
222223
$time = time();
223224
}
224225

225-
// Calculate backup word
226-
$backupword = str_replace(' ', '_', core_text::strtolower(get_string('backupfilename')));
227-
$backupword = trim(clean_filename($backupword), '_');
228-
229-
// Not $useidonly, lets fetch the name
230-
$shortname = '';
231-
if (!$useidonly) {
232-
// Calculate proper name element (based on type)
233-
switch ($type) {
234-
case backup::TYPE_1COURSE:
235-
$shortname = $DB->get_field('course', 'shortname', array('id' => $id));
236-
$context = context_course::instance($id);
237-
$shortname = format_string($shortname, true, array('context' => $context));
238-
break;
239-
case backup::TYPE_1SECTION:
240-
if (!$shortname = $DB->get_field('course_sections', 'name', array('id' => $id))) {
241-
$shortname = $DB->get_field('course_sections', 'section', array('id' => $id));
242-
}
243-
break;
244-
case backup::TYPE_1ACTIVITY:
245-
$cm = get_coursemodule_from_id(null, $id);
246-
$shortname = $cm->modname . $id;
247-
break;
248-
}
249-
$shortname = str_replace(' ', '_', $shortname);
250-
$shortname = core_text::strtolower(trim(clean_filename($shortname), '_'));
251-
}
252-
253-
// The name will always contain the ID, but we append the course short name if requested.
254-
$name = $id;
255-
if (!$useidonly && $shortname != '') {
256-
$name .= '-' . $shortname;
257-
}
258-
259-
// Calculate date
260226
$backupdateformat = str_replace(' ', '_', get_string('backupnameformat', 'langconfig'));
261-
$date = userdate($time, $backupdateformat, 99, false);
262-
$date = core_text::strtolower(trim(clean_filename($date), '_'));
263-
264-
// Calculate info
265-
$info = '';
266-
if (!$users) {
267-
$info = '-nu';
268-
} else if ($anonymised) {
269-
$info = '-an';
227+
$formatdate = function(int $date) use ($backupdateformat): string {
228+
$date = userdate($date, $backupdateformat, 99, false);
229+
return core_text::strtolower(trim(clean_filename($date), '_'));
230+
};
231+
232+
$context = [
233+
'format' => $format,
234+
'type' => $type,
235+
'id' => $id,
236+
'users' => $users,
237+
'anonymised' => $anonymised,
238+
'files' => $files,
239+
'useidonly' => $useidonly,
240+
'time' => $time,
241+
'date' => $formatdate($time),
242+
];
243+
244+
// Add extra context based on the type of backup.
245+
// It is important to use array and not stdClass here, otherwise array_walk_recursive will not work.
246+
switch ($type) {
247+
case backup::TYPE_1COURSE:
248+
$context['course'] = (array) $DB->get_record('course', ['id' => $id], 'shortname,fullname,startdate,enddate', MUST_EXIST);
249+
$context['course']['startdate'] = $formatdate($context['course']['startdate']);
250+
$context['course']['enddate'] = $formatdate($context['course']['enddate']);
251+
break;
252+
case backup::TYPE_1SECTION:
253+
$context['section'] = (array) $DB->get_record('course_sections', ['id' => $id], 'name,section', MUST_EXIST);
254+
break;
255+
case backup::TYPE_1ACTIVITY:
256+
$cm = get_coursemodule_from_id(null, $id, 0, false, MUST_EXIST);
257+
$context['activity'] = [
258+
'modname' => $cm->modname,
259+
'name' => $cm->name,
260+
];
261+
break;
262+
default:
263+
throw new coding_exception('Unknown backup type - cannot get template context');
270264
}
271265

272-
// Indicate if backup doesn't contain files.
273-
if (!$files) {
274-
$info .= '-nf';
266+
$instancecontext = null;
267+
switch ($type) {
268+
case backup::TYPE_1COURSE:
269+
$instancecontext = context_course::instance($id);
270+
break;
271+
case backup::TYPE_1SECTION:
272+
// A section is still course context, but needs an extra step to find the course id.
273+
$courseid = $DB->get_field('course_sections', 'course', ['id' => $id], MUST_EXIST);
274+
$instancecontext = context_course::instance($courseid);
275+
break;
276+
case backup::TYPE_1ACTIVITY:
277+
$instancecontext = context_module::instance($id);
278+
break;
279+
default:
280+
throw new coding_exception('Unknown backup type - cannot get instance context');
275281
}
276282

277-
$original = $backupword . '-' . $format . '-' . $type . '-' .
278-
$name . '-' . $date . $info . '.mbz';
279-
280-
// NEW TESTING STUFF.
281-
$template = "
282-
{{#str}}backupfilename{{/str}}-{{format}}-{{type}}-{{course.shortname}}{{section.name}}{{^section.name}}{{section.section}}{{/section.name}}{{module.modname}}{{id}}
283-
";
283+
// Recursively format all the strings and trim any extra whitespace.
284+
array_walk_recursive($context, function(&$item) use ($instancecontext) {
285+
if (is_string($item)) {
286+
// Update by reference.
287+
$item = trim(format_string($item, true, ['context' => $instancecontext]));
288+
}
289+
});
290+
291+
$templates = [
292+
backup::TYPE_1COURSE => get_config('backup', 'backup_default_filename_template_course'),
293+
backup::TYPE_1SECTION => get_config('backup', 'backup_default_filename_template_section'),
294+
backup::TYPE_1ACTIVITY => get_config('backup', 'backup_default_filename_template_activity'),
295+
];
296+
$template = $templates[$type];
284297
$mustache = new mustache_engine([
285-
'escape' => 's',
286298
'helpers' => [
287299
'str' => [new mustache_string_helper(), 'str'],
288300
],
289-
'pragmas' => [\Mustache_Engine::PRAGMA_BLOCKS],
290301
]);
291-
$new = trim($mustache->render($template, [
292-
'format' => $format,
293-
'type' => $type,
294-
'course' => [
295-
// 'shortname' => 'dummy'
296-
],
297-
'section' => [
298-
// 'name' => '123',
299-
'section' => '567'
300-
],
301-
'module' => [
302-
'modname' => 'hvp',
303-
'id' => $id
304-
]
305-
]));
306-
return $original;
302+
$new = $mustache->render($template, $context);
303+
304+
// Clean as filename, remove spaces, and trim to max 251 chars (filename limit, 255 including .mbz extension).
305+
$cleaned = substr(str_replace(' ', '_', clean_filename($new)),0, 251);
306+
return $cleaned . '.mbz';
307307
}
308308

309309
/**
@@ -324,7 +324,6 @@ public static function require_gradebook_backup($courseid, $backupid) {
324324
AND bi.backupid = :backupid)";
325325
$params = array('courseid'=>$courseid, 'backupid'=>$backupid);
326326

327-
328327
$count = $DB->count_records_sql($sql, $params);
329328

330329
//if there are 0 activity grade items not already included in the backup

0 commit comments

Comments
 (0)