22
22
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
23
*/
24
24
25
+ use core \exception \coding_exception ;
26
+ use core \output \mustache_engine ;
27
+ use core \output \mustache_string_helper ;
28
+
25
29
/**
26
30
* Non instantiable helper class providing DB support to the @backup_plan class
27
31
*
@@ -199,7 +203,7 @@ public static function get_mnet_localhost_wwwroot() {
199
203
* Default format is (see MDL-22145)
200
204
* backup word - format - type - name - date - info . mbz
201
205
* where name is variable (course shortname, section name/id, activity modulename + cmid)
202
- * 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 ,
203
207
* defaulting to false, allows to replace the course shortname by the course id (used
204
208
* by automated backups, to avoid non-ascii chars in OS filesystem)
205
209
*
@@ -212,63 +216,94 @@ public static function get_mnet_localhost_wwwroot() {
212
216
* @return string The filename to use
213
217
*/
214
218
public static function get_default_backup_filename ($ format , $ type , $ id , $ users , $ anonymised ,
215
- $ useidonly = false , $ files = true ) {
219
+ $ useidonly = false , $ files = true , $ time = null ) {
216
220
global $ DB ;
217
221
218
- // Calculate backup word
219
- $ backupword = str_replace (' ' , '_ ' , core_text::strtolower (get_string ('backupfilename ' )));
220
- $ backupword = trim (clean_filename ($ backupword ), '_ ' );
221
-
222
- // Not $useidonly, lets fetch the name
223
- $ shortname = '' ;
224
- if (!$ useidonly ) {
225
- // Calculate proper name element (based on type)
226
- switch ($ type ) {
227
- case backup::TYPE_1COURSE :
228
- $ shortname = $ DB ->get_field ('course ' , 'shortname ' , array ('id ' => $ id ));
229
- $ context = context_course::instance ($ id );
230
- $ shortname = format_string ($ shortname , true , array ('context ' => $ context ));
231
- break ;
232
- case backup::TYPE_1SECTION :
233
- if (!$ shortname = $ DB ->get_field ('course_sections ' , 'name ' , array ('id ' => $ id ))) {
234
- $ shortname = $ DB ->get_field ('course_sections ' , 'section ' , array ('id ' => $ id ));
235
- }
236
- break ;
237
- case backup::TYPE_1ACTIVITY :
238
- $ cm = get_coursemodule_from_id (null , $ id );
239
- $ shortname = $ cm ->modname . $ id ;
240
- break ;
241
- }
242
- $ shortname = str_replace (' ' , '_ ' , $ shortname );
243
- $ shortname = core_text::strtolower (trim (clean_filename ($ shortname ), '_ ' ));
244
- }
245
-
246
- // The name will always contain the ID, but we append the course short name if requested.
247
- $ name = $ id ;
248
- if (!$ useidonly && $ shortname != '' ) {
249
- $ name .= '- ' . $ shortname ;
222
+ if ($ time === null ) {
223
+ $ time = time ();
250
224
}
251
225
252
- // Calculate date
253
226
$ backupdateformat = str_replace (' ' , '_ ' , get_string ('backupnameformat ' , 'langconfig ' ));
254
- $ date = userdate (time (), $ backupdateformat , 99 , false );
255
- $ date = core_text::strtolower (trim (clean_filename ($ date ), '_ ' ));
256
-
257
- // Calculate info
258
- $ info = '' ;
259
- if (!$ users ) {
260
- $ info = '-nu ' ;
261
- } else if ($ anonymised ) {
262
- $ 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 ' );
263
264
}
264
265
265
- // Indicate if backup doesn't contain files.
266
- if (!$ files ) {
267
- $ 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 ' );
268
281
}
269
282
270
- return $ backupword . '- ' . $ format . '- ' . $ type . '- ' .
271
- $ name . '- ' . $ date . $ info . '.mbz ' ;
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 ];
297
+ $ mustache = new mustache_engine ([
298
+ 'helpers ' => [
299
+ 'str ' => [new mustache_string_helper (), 'str ' ],
300
+ ],
301
+ ]);
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 ' ;
272
307
}
273
308
274
309
/**
@@ -289,7 +324,6 @@ public static function require_gradebook_backup($courseid, $backupid) {
289
324
AND bi.backupid = :backupid) " ;
290
325
$ params = array ('courseid ' =>$ courseid , 'backupid ' =>$ backupid );
291
326
292
-
293
327
$ count = $ DB ->count_records_sql ($ sql , $ params );
294
328
295
329
//if there are 0 activity grade items not already included in the backup
0 commit comments