MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / mod / scorm / backuplib.php
blobea058d748c096fe600a0c720e5fd34c7361b283b
1 <?php //$Id$
2 //This php script contains all the stuff to backup/restore
3 //scorm mods
5 //This is the "graphical" structure of the scorm mod:
6 //
7 // scorm
8 // (CL,pk->id)-------------------------------------
9 // | |
10 // | |
11 // | |
12 // scorm_scoes scorm_scoes_data |
13 // (UL,pk->id, fk->scorm)-------(UL,pk->id, fk->scoid) |
14 // | |
15 // | |
16 // | |
17 // scorm_scoes_track |
18 // (UL,k->id, fk->scormid, fk->scoid, k->element)-------------------
20 // Meaning: pk->primary key field of the table
21 // fk->foreign key to link with parent
22 // nt->nested field (recursive data)
23 // CL->course level info
24 // UL->user level info
25 // files->table may have files)
27 //-----------------------------------------------------------
29 function scorm_backup_mods($bf,$preferences) {
31 global $CFG;
33 $status = true;
35 //Iterate over scorm table
36 $scorms = get_records ('scorm','course',$preferences->backup_course,'id');
37 if ($scorms) {
38 foreach ($scorms as $scorm) {
39 if (backup_mod_selected($preferences,'scorm',$scorm->id)) {
40 $status = scorm_backup_one_mod($bf,$preferences,$scorm);
44 return $status;
47 function scorm_backup_one_mod($bf,$preferences,$scorm) {
48 $status = true;
50 if (is_numeric($scorm)) {
51 $scorm = get_record('scorm','id',$scorm);
54 //Start mod
55 fwrite ($bf,start_tag('MOD',3,true));
56 //Print scorm data
57 fwrite ($bf,full_tag('ID',4,false,$scorm->id));
58 fwrite ($bf,full_tag('MODTYPE',4,false,'scorm'));
59 fwrite ($bf,full_tag('NAME',4,false,$scorm->name));
60 fwrite ($bf,full_tag('REFERENCE',4,false,$scorm->reference));
61 fwrite ($bf,full_tag('VERSION',4,false,$scorm->version));
62 fwrite ($bf,full_tag('MAXGRADE',4,false,$scorm->maxgrade));
63 fwrite ($bf,full_tag('GRADEMETHOD',4,false,$scorm->grademethod));
64 fwrite ($bf,full_tag('LAUNCH',4,false,$scorm->launch));
65 fwrite ($bf,full_tag('SKIPVIEW',4,false,$scorm->skipview));
66 fwrite ($bf,full_tag('SUMMARY',4,false,$scorm->summary));
67 fwrite ($bf,full_tag('HIDEBROWSE',4,false,$scorm->hidebrowse));
68 fwrite ($bf,full_tag('HIDETOC',4,false,$scorm->hidetoc));
69 fwrite ($bf,full_tag('HIDENAV',4,false,$scorm->hidenav));
70 fwrite ($bf,full_tag('AUTO',4,false,$scorm->auto));
71 fwrite ($bf,full_tag('POPUP',4,false,$scorm->popup));
72 fwrite ($bf,full_tag('OPTIONS',4,false,$scorm->options));
73 fwrite ($bf,full_tag('WIDTH',4,false,$scorm->width));
74 fwrite ($bf,full_tag('HEIGHT',4,false,$scorm->height));
75 fwrite ($bf,full_tag('MD5HASH',4,false,$scorm->md5hash));
76 fwrite ($bf,full_tag("MAXATTEMPT",4,false,$scorm->maxattempt));
77 fwrite ($bf,full_tag("UPDATEFREQ",4,false,$scorm->updatefreq));
78 fwrite ($bf,full_tag('TIMEMODIFIED',4,false,$scorm->timemodified));
79 $status = backup_scorm_scoes($bf,$preferences,$scorm->id);
81 //if we've selected to backup users info, then execute backup_scorm_scoes_track
82 if ($status) {
83 if (backup_userdata_selected($preferences,'scorm',$scorm->id)) {
84 $status = backup_scorm_scoes_track($bf,$preferences,$scorm->id);
86 $status = backup_scorm_files_instance($bf,$preferences,$scorm->id);
89 //End mod
90 $status =fwrite ($bf,end_tag('MOD',3,true));
91 return $status;
94 //Backup scorm_scoes contents (executed from scorm_backup_mods)
95 function backup_scorm_scoes ($bf,$preferences,$scorm) {
97 global $CFG;
99 $status = true;
101 $scorm_scoes = get_records('scorm_scoes','scorm',$scorm,'id');
102 //If there is scoes
103 if ($scorm_scoes) {
104 //Write start tag
105 $status =fwrite ($bf,start_tag('SCOES',4,true));
106 //Iterate over each sco
107 foreach ($scorm_scoes as $sco) {
108 //Start sco
109 $status =fwrite ($bf,start_tag('SCO',5,true));
110 //Print submission contents
111 fwrite ($bf,full_tag('ID',6,false,$sco->id));
112 fwrite ($bf,full_tag('MANIFEST',6,false,$sco->manifest));
113 fwrite ($bf,full_tag('ORGANIZATION',6,false,$sco->organization));
114 fwrite ($bf,full_tag('PARENT',6,false,$sco->parent));
115 fwrite ($bf,full_tag('IDENTIFIER',6,false,$sco->identifier));
116 fwrite ($bf,full_tag('LAUNCH',6,false,$sco->launch));
117 fwrite ($bf,full_tag('SCORMTYPE',6,false,$sco->scormtype));
118 fwrite ($bf,full_tag('TITLE',6,false,$sco->title));
119 $status = backup_scorm_scoes_data($bf,$preferences,$sco->id);
120 $status = backup_scorm_seq_ruleconds($bf,$preferences,$sco->id);
121 $status = backup_scorm_seq_rolluprule($bf,$preferences,$sco->id);
122 $status = backup_scorm_seq_objective($bf,$preferences,$sco->id);
123 //End sco
124 $status =fwrite ($bf,end_tag('SCO',5,true));
126 //Write end tag
127 $status =fwrite ($bf,end_tag('SCOES',4,true));
129 return $status;
132 //Backup scorm_scoes_data contents (executed from scorm_backup_scorm_scoes)
133 function backup_scorm_scoes_data ($bf,$preferences,$sco) {
135 global $CFG;
137 $status = true;
139 $scorm_sco_datas = get_records('scorm_scoes_data','scoid',$sco,'id');
140 //If there is data
141 if ($scorm_sco_datas) {
142 //Write start tag
143 $status =fwrite ($bf,start_tag('SCO_DATAS',4,true));
144 //Iterate over each sco
145 foreach ($scorm_sco_datas as $sco_data) {
146 //Start sco track
147 $status =fwrite ($bf,start_tag('SCO_DATA',5,true));
148 //Print track contents
149 fwrite ($bf,full_tag('ID',6,false,$sco_data->id));
150 fwrite ($bf,full_tag('SCOID',6,false,$sco_data->scoid));
151 fwrite ($bf,full_tag('NAME',6,false,$sco_data->name));
152 fwrite ($bf,full_tag('VALUE',6,false,$sco_data->value));
153 //End sco track
154 $status =fwrite ($bf,end_tag('SCO_DATA',5,true));
156 //Write end tag
157 $status =fwrite ($bf,end_tag('SCO_DATAS',4,true));
159 return $status;
162 //Backup scorm_scoes_track contents (executed from scorm_backup_mods)
163 function backup_scorm_scoes_track ($bf,$preferences,$scorm) {
165 global $CFG;
167 $status = true;
169 $scorm_scoes_track = get_records('scorm_scoes_track','scormid',$scorm,'id');
170 //If there is track
171 if ($scorm_scoes_track) {
172 //Write start tag
173 $status =fwrite ($bf,start_tag('SCO_TRACKS',4,true));
174 //Iterate over each sco
175 foreach ($scorm_scoes_track as $sco_track) {
176 //Start sco track
177 $status =fwrite ($bf,start_tag('SCO_TRACK',5,true));
178 //Print track contents
179 fwrite ($bf,full_tag('ID',6,false,$sco_track->id));
180 fwrite ($bf,full_tag('USERID',6,false,$sco_track->userid));
181 fwrite ($bf,full_tag('SCOID',6,false,$sco_track->scoid));
182 fwrite ($bf,full_tag('ELEMENT',6,false,$sco_track->element));
183 fwrite ($bf,full_tag('VALUE',6,false,$sco_track->value));
184 fwrite ($bf,full_tag('ATTEMPT',6,false,$sco_track->attempt));
185 fwrite ($bf,full_tag('TIMEMODIFIED',6,false,$sco_track->timemodified));
186 //End sco track
187 $status =fwrite ($bf,end_tag('SCO_TRACK',5,true));
189 //Write end tag
190 $status =fwrite ($bf,end_tag('SCO_TRACKS',4,true));
192 return $status;
196 function backup_scorm_seq_ruleconds ($bf,$preferences,$sco) {
198 global $CFG;
200 $status = true;
202 $scorm_seq_ruleconditions = get_records('scorm_seq_ruleconds','scoid',$sco,'id');
203 //If there is rulecondition
204 if ($scorm_seq_ruleconditions) {
205 //Write start tag
206 $status =fwrite ($bf,start_tag('SEQ_RULECONDS',4,true));
207 //Iterate over each sco
208 foreach ($scorm_seq_ruleconditions as $seq_rulecondition) {
209 //Start sco
210 $status =fwrite ($bf,start_tag('SEQ_RULECOND',5,true));
211 //Print track contents
212 fwrite ($bf,full_tag('ID',6,false,$seq_rulecondition->id));
213 fwrite ($bf,full_tag('SCOID',6,false,$seq_rulecondition->scoid));
214 fwrite ($bf,full_tag('CONDITIONCOMBINATION',6,false,$seq_rulecondition->conditioncombination));
215 fwrite ($bf,full_tag('RULETYPE',6,false,$seq_rulecondition->ruletype));
216 fwrite ($bf,full_tag('ACTION',6,false,$seq_rulecondition->action));
218 $status = backup_scorm_seq_rulecond($bf,$preferences,$seq_rulecondition->id);
219 //End sco track
220 $status =fwrite ($bf,end_tag('SEQ_RULECOND',5,true));
222 //Write end tag
223 $status =fwrite ($bf,end_tag('SEQ_RULECOND',4,true));
225 return $status;
229 function backup_scorm_seq_rulecond ($bf,$preferences,$ruleconditions) {
231 global $CFG;
233 $status = true;
235 $scorm_seq_ruleconditions = get_records('scorm_seq_rulecond','ruleconditionsid',$ruleconditions,'id');
236 //If there is rulecondition
237 if ($scorm_seq_ruleconditions) {
238 //Write start tag
239 $status =fwrite ($bf,start_tag('SEQ_RULECOND_DATAS',4,true));
240 //Iterate over each sco
241 foreach ($scorm_seq_ruleconditions as $seq_rulecondition) {
242 //Start sco
243 $status =fwrite ($bf,start_tag('SEQ_RULECOND_DATA',5,true));
244 //Print track contents
245 fwrite ($bf,full_tag('ID',6,false,$seq_rulecondition->id));
246 fwrite ($bf,full_tag('SCOID',6,false,$seq_rulecondition->scoid));
247 fwrite ($bf,full_tag('RULECONDITIONSID',6,false,$seq_rulecondition->ruleconditionsid));
248 fwrite ($bf,full_tag('REFRENCEDOBJECTIVE',6,false,$seq_rulecondition->refrencedobjective));
249 fwrite ($bf,full_tag('MEASURETHRESHOLD',6,false,$seq_rulecondition->measurethreshold));
250 fwrite ($bf,full_tag('OPERATOR',6,false,$seq_rulecondition->operator));
251 fwrite ($bf,full_tag('COND',6,false,$seq_rulecondition->cond));
252 //End sco track
253 $status =fwrite ($bf,end_tag('SEQ_RULECOND_DATA',5,true));
255 //Write end tag
256 $status =fwrite ($bf,end_tag('SEQ_RULECOND_DATAS',4,true));
258 return $status;
261 function backup_scorm_seq_rolluprule ($bf,$preferences,$sco) {
263 global $CFG;
265 $status = true;
267 $scorm_seq_rolluprules = get_records('scorm_seq_rolluprule','scoid',$sco,'id');
268 //If there is rulecondition
269 if ($scorm_seq_rolluprules) {
270 //Write start tag
271 $status =fwrite ($bf,start_tag('SEQ_ROLLUPRULES',4,true));
272 //Iterate over each sco
273 foreach ($scorm_seq_rolluprules as $seq_rolluprule) {
274 //Start sco
275 $status =fwrite ($bf,start_tag('SEQ_ROLLUPRULE',5,true));
276 //Print track contents
277 fwrite ($bf,full_tag('ID',6,false,$seq_rolluprule->id));
278 fwrite ($bf,full_tag('SCOID',6,false,$seq_rolluprule->scoid));
279 fwrite ($bf,full_tag('CHILDACTIVITYSET',6,false,$seq_rolluprule->childactivityset));
280 fwrite ($bf,full_tag('MINIMUMCOUNT',6,false,$seq_rolluprule->minimumcount));
281 fwrite ($bf,full_tag('MINIMUMPERCENT',6,false,$seq_rolluprule->minimumpercent));
282 fwrite ($bf,full_tag('CONDITIONCOMBINATION',6,false,$seq_rolluprule->conditioncomnination));
283 fwrite ($bf,full_tag('ACTION',6,false,$seq_rolluprule->action));
284 $status = backup_scorm_seq_rolluprulecond($bf,$preferences,$seq_rolluprule->id);
285 //End sco track
286 $status =fwrite ($bf,end_tag('SEQ_ROLLUPRULE',5,true));
288 //Write end tag
289 $status =fwrite ($bf,end_tag('SEQ_ROLLUPRULES',4,true));
291 return $status;
295 function backup_scorm_seq_rolluprulecond ($bf,$preferences,$rolluprule) {
297 global $CFG;
299 $status = true;
301 $scorm_seq_rollupruleconditions = get_records('scorm_seq_rolluprulecond','rollupruleid',$rolluprule,'id');
302 //If there is rulecondition
303 if ($scorm_seq_rollupruleconditions) {
304 //Write start tag
305 $status =fwrite ($bf,start_tag('SEQ_ROLLUPRULECONDS',4,true));
306 //Iterate over each sco
307 foreach ($scorm_seq_rollupruleconditions as $seq_rolluprulecondition) {
308 //Start sco
309 $status =fwrite ($bf,start_tag('SEQ_ROLLUPRULECOND',5,true));
310 //Print track contents
311 fwrite ($bf,full_tag('ID',6,false,$seq_rolluprulecondition->id));
312 fwrite ($bf,full_tag('SCOID',6,false,$seq_rolluprulecondition->scoid));
313 fwrite ($bf,full_tag('ROLLUPRULEID',6,false,$seq_rolluprulecondition->rollupruleid));
314 fwrite ($bf,full_tag('COND',6,false,$seq_rolluprulecondition->condition));
315 fwrite ($bf,full_tag('OPERATOR',6,false,$seq_rolluprulecondition->operator));
317 //End sco track
318 $status =fwrite ($bf,end_tag('SEQ_ROLLUPRULECOND',5,true));
320 //Write end tag
321 $status =fwrite ($bf,end_tag('SEQ_ROLLUPRULECONDS',4,true));
323 return $status;
327 function backup_scorm_seq_objective ($bf,$preferences,$sco) {
329 global $CFG;
331 $status = true;
333 $scorm_seq_objectives = get_records('scorm_seq_objective','scoid',$sco,'id');
334 //If there is rulecondition
335 if ($scorm_seq_objectives) {
336 //Write start tag
337 $status =fwrite ($bf,start_tag('SEQ_OBJECTIVES',4,true));
338 //Iterate over each sco
339 foreach ($scorm_seq_objectives as $seq_objective) {
340 //Start sco
341 $status =fwrite ($bf,start_tag('SEQ_OBJECTIVE',5,true));
342 //Print track contents
343 fwrite ($bf,full_tag('ID',6,false,$seq_objective->id));
344 fwrite ($bf,full_tag('SCOID',6,false,$seq_objective->scoid));
345 fwrite ($bf,full_tag('PRIMARYOBJ',6,false,$seq_objective->primaryobj));
346 fwrite ($bf,full_tag('OBJECTIVEID',6,false,$seq_objective->objectiveid));
347 fwrite ($bf,full_tag('MINNORMALIZEDMEASURE',6,false,$seq_objective->minnormalizedmeasure));
348 fwrite ($bf,full_tag('SATISFIEDBYMEASURE',6,false,$seq_objective->objectivemeasureweight));
350 $status = backup_scorm_seq_mapinfo($bf,$preferences,$seq_objective->id);
351 //End sco track
352 $status =fwrite ($bf,end_tag('SEQ_OBJECTIVE',5,true));
354 //Write end tag
355 $status =fwrite ($bf,end_tag('SEQ_OBJECTIVES',4,true));
357 return $status;
360 function backup_scorm_seq_mapinfo ($bf,$preferences,$objectives) {
362 global $CFG;
364 $status = true;
366 $scorm_seq_objectives = get_records('scorm_seq_mapinfo','objectiveid',$objectives,'id');
367 //If there is rulecondition
368 if ($scorm_seq_objectives) {
369 //Write start tag
370 $status =fwrite ($bf,start_tag('SEQ_MAPINFO',4,true));
371 //Iterate over each sco
372 foreach ($scorm_seq_objectives as $seq_objective) {
373 //Start sco
374 $status =fwrite ($bf,start_tag('SEQ_MAPINF',5,true));
375 //Print track contents
376 fwrite ($bf,full_tag('ID',6,false,$seq_objective->id));
377 fwrite ($bf,full_tag('SCOID',6,false,$seq_objective->scoid));
378 fwrite ($bf,full_tag('OBJECTIVEID',6,false,$seq_objective->objectiveid));
379 fwrite ($bf,full_tag('TARGETOBJECTIVEID',6,false,$seq_objective->targetobjectiveid));
380 fwrite ($bf,full_tag('READSATISFIEDSTATUS',6,false,$seq_objective->readsatisfiedstatus));
381 fwrite ($bf,full_tag('READNORMALIZEDMEASURE',6,false,$seq_objective->readnormalizedmeasure));
382 fwrite ($bf,full_tag('WRITESATISFIEDSTATUS',6,false,$seq_objective->writesatisfiedstatus));
383 fwrite ($bf,full_tag('WRITENORMALIZEDMEASURE',6,false,$seq_objective->writenormalizedmeasure));
384 //End sco track
385 $status =fwrite ($bf,end_tag('SEQ_MAPINF',5,true));
387 //Write end tag
388 $status =fwrite ($bf,end_tag('SEQ_MAPINFO',4,true));
390 return $status;
393 ////Return an array of info (name,value)
394 function scorm_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) {
395 if (!empty($instances) && is_array($instances) && count($instances)) {
396 $info = array();
397 foreach ($instances as $id => $instance) {
398 $info += scorm_check_backup_mods_instances($instance,$backup_unique_code);
400 return $info;
402 //First the course data
403 $info[0][0] = get_string('modulenameplural','scorm');
404 if ($ids = scorm_ids ($course)) {
405 $info[0][1] = count($ids);
406 } else {
407 $info[0][1] = 0;
410 //Now, if requested, the user_data
411 if ($user_data) {
412 $info[1][0] = get_string('scoes','scorm');
413 if ($ids = scorm_scoes_track_ids_by_course ($course)) {
414 $info[1][1] = count($ids);
415 } else {
416 $info[1][1] = 0;
419 return $info;
422 function scorm_check_backup_mods_instances($instance,$backup_unique_code) {
423 $info[$instance->id.'0'][0] = $instance->name;
424 $info[$instance->id.'0'][1] = '';
425 if (!empty($instance->userdata)) {
426 $info[$instance->id.'1'][0] = get_string('scoes','scorm');
427 if ($ids = scorm_scoes_track_ids_by_instance ($instance->id)) {
428 $info[$instance->id.'1'][1] = count($ids);
429 } else {
430 $info[$instance->id.'1'][1] = 0;
434 return $info;
438 function backup_scorm_files_instance($bf,$preferences,$instanceid) {
439 global $CFG;
441 $status = true;
443 //First we check to moddata exists and create it as necessary
444 //in temp/backup/$backup_code dir
445 $status = check_and_create_moddata_dir($preferences->backup_unique_code);
446 $status = check_dir_exists($CFG->dataroot.'/temp/backup/'.$preferences->backup_unique_code.'/moddata/scorm/',true);
447 if ($status) {
448 //Only if it exists !! Thanks to Daniel Miksik.
449 if (is_dir($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm/'.$instanceid)) {
450 $status = backup_copy_file($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm/'.$instanceid,
451 $CFG->dataroot.'/temp/backup/'.$preferences->backup_unique_code.'/moddata/scorm/'.$instanceid);
455 return $status;
459 //Backup scorm package files
460 function backup_scorm_files($bf,$preferences) {
462 global $CFG;
464 $status = true;
466 //First we check to moddata exists and create it as necessary
467 //in temp/backup/$backup_code dir
468 $status = check_and_create_moddata_dir($preferences->backup_unique_code);
469 //Now copy the scorm dir
470 if ($status) {
471 if (is_dir($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm')) {
472 $handle = opendir($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm');
473 while (false!==($item = readdir($handle))) {
474 if ($item != '.' && $item != '..' && is_dir($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm/'.$item)
475 && array_key_exists($item,$preferences->mods['scorm']->instances)
476 && !empty($preferences->mods['scorm']->instances[$item]->backup)) {
477 $status = backup_copy_file($CFG->dataroot.'/'.$preferences->backup_course.'/'.$CFG->moddata.'/scorm/'.$item,
478 $CFG->dataroot.'/temp/backup/'.$preferences->backup_unique_code.'/moddata/scorm/',$item);
484 return $status;
488 //Return a content encoded to support interactivities linking. Every module
489 //should have its own. They are called automatically from the backup procedure.
490 function scorm_encode_content_links ($content,$preferences) {
492 global $CFG;
494 $base = preg_quote($CFG->wwwroot,"/");
496 //Link to the list of scorms
497 $buscar="/(".$base."\/mod\/scorm\/index.php\?id\=)([0-9]+)/";
498 $result= preg_replace($buscar,'$@SCORMINDEX*$2@$',$content);
500 //Link to scorm view by moduleid
501 $buscar="/(".$base."\/mod\/scorm\/view.php\?id\=)([0-9]+)/";
502 $result= preg_replace($buscar,'$@SCORMVIEWBYID*$2@$',$result);
504 return $result;
507 // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE
509 //Returns an array of scorms id
510 function scorm_ids ($course) {
512 global $CFG;
514 return get_records_sql ("SELECT a.id, a.course
515 FROM {$CFG->prefix}scorm a
516 WHERE a.course = '$course'");
519 //Returns an array of scorm_scoes id
520 function scorm_scoes_track_ids_by_course ($course) {
522 global $CFG;
524 return get_records_sql ("SELECT s.id , s.scormid
525 FROM {$CFG->prefix}scorm_scoes_track s,
526 {$CFG->prefix}scorm a
527 WHERE a.course = '$course' AND
528 s.scormid = a.id");
531 //Returns an array of scorm_scoes id
532 function scorm_scoes_track_ids_by_instance ($instanceid) {
534 global $CFG;
536 return get_records_sql ("SELECT s.id , s.scormid
537 FROM {$CFG->prefix}scorm_scoes_track s
538 WHERE s.scormid = $instanceid");