MDL-16106 report - fix old double-column trick causing problems in backup logs. Thank...
[moodle.git] / mod / hotpot / backuplib.php
blob157a650e87e1a334800ca4c9f497b1f3afc41364
1 <?PHP //$Id$
2 //This php script contains all the stuff to backup/restore
3 //quiz mods
4 //-----------------------------------------------------------
5 // This is the "graphical" structure of the hotpot mod:
6 //-----------------------------------------------------------
7 //
8 // hotpot
9 // (CL, pk->id,
10 // fk->course, files)
11 // |
12 // +--------------+---------------+
13 // | |
14 // hotpot_attempts hotpot_questions
15 // (UL, pk->id, (UL, pk->id,
16 // fk->hotpot) fk->hotpot, text)
17 // | | |
18 // +-------------------+----------+ |
19 // | | |
20 // hotpot_details hotpot_responses |
21 // (UL, pk->id, (UL, pk->id, |
22 // fk->attempt) fk->attempt, question, |
23 // correct, wrong, ignored) |
24 // | |
25 // +-------+-------+
26 // |
27 // hotpot_strings
28 // (UL, pk->id)
30 // Meaning: pk->primary key field of the table
31 // fk->foreign key to link with parent
32 // nt->nested field (recursive data)
33 // CL->course level info
34 // UL->user level info
35 // files->table may have files
37 //-----------------------------------------------------------
38 function hotpot_backup_mods($bf, $preferences) {
39 global $CFG;
41 $status = true;
43 //Iterate over hotpot table
44 $hotpots = get_records ("hotpot","course",$preferences->backup_course,"id");
45 if ($hotpots) {
46 foreach ($hotpots as $hotpot) {
47 if (function_exists('backup_mod_selected')) {
48 // Moodle >= 1.6
49 $backup_mod_selected = backup_mod_selected($preferences, 'hotpot', $hotpot->id);
50 } else {
51 // Moodle <= 1.5
52 $backup_mod_selected = true;
54 if ($backup_mod_selected) {
55 $status = hotpot_backup_one_mod($bf, $preferences, $hotpot->id);
59 return $status;
62 function hotpot_backup_one_mod($bf, $preferences, $instance=0) {
63 // $bf : resource id for b(ackup) f(ile)
64 // $preferences : object containing switches and settings for this backup
65 $level = 3;
66 $status = true;
67 $table = 'hotpot';
68 $select = "course=$preferences->backup_course AND id='$instance'";
69 $records_tag = '';
70 $records_tags = array();
71 $record_tag = 'MOD';
72 $record_tags = array('MODTYPE'=>'hotpot');
73 $excluded_tags = array();
74 $more_backup = '';
75 if (function_exists('backup_userdata_selected')) {
76 // Moodle >= 1.6
77 $backup_userdata_selected = backup_userdata_selected($preferences, 'hotpot', $instance);
78 } else {
79 // Moodle <= 1.5
80 $backup_userdata_selected = $preferences->mods['hotpot']->userinfo;
82 if ($backup_userdata_selected) {
83 $more_backup .= '$GLOBALS["hotpot_backup_string_ids"] = array();';
84 $more_backup .= '$status = hotpot_backup_attempts($bf, $record, $level, $status);';
85 $more_backup .= '$status = hotpot_backup_questions($bf, $record, $level, $status);';
86 $more_backup .= '$status = hotpot_backup_strings($bf, $record, $level, $status);';
87 $more_backup .= 'unset($GLOBALS["hotpot_backup_string_ids"]);'; // tidy up
89 return hotpot_backup_records(
90 $bf, $status, $level,
91 $table, $select,
92 $records_tag, $records_tags,
93 $record_tag, $record_tags,
94 $excluded_tags, $more_backup
97 function hotpot_backup_attempts($bf, &$parent, $level, $status) {
98 // $parent is a reference to a hotpot record
99 $table = 'hotpot_attempts';
100 $select = "hotpot=$parent->id";
101 $records_tag = 'ATTEMPT_DATA';
102 $records_tags = array();
103 $record_tag = 'ATTEMPT';
104 $record_tags = array();
105 $more_backup = '';
106 $more_backup .= 'hotpot_backup_details($bf, $record, $level, $status);';
107 $more_backup .= 'hotpot_backup_responses($bf, $record, $level, $status);';
108 $excluded_tags = array('hotpot');
109 return hotpot_backup_records(
110 $bf, $status, $level,
111 $table, $select,
112 $records_tag, $records_tags,
113 $record_tag, $record_tags,
114 $excluded_tags, $more_backup
117 function hotpot_backup_details($bf, &$parent, $level, $status) {
118 // $parent is a reference to an attempt record
119 $table = 'hotpot_details';
120 $select = "attempt=$parent->id";
121 $records_tag = '';
122 $records_tags = array();
123 $record_tag = '';
124 $record_tags = array();
125 $more_backup = '';
126 $excluded_tags = array('id','attempt');
127 return hotpot_backup_records(
128 $bf, $status, $level,
129 $table, $select,
130 $records_tag, $records_tags,
131 $record_tag, $record_tags,
132 $excluded_tags, $more_backup
135 function hotpot_backup_responses($bf, &$parent, $level, $status) {
136 // $parent is a reference to an attempt record
137 $table = 'hotpot_responses';
138 $select = "attempt=$parent->id";
139 $records_tag = 'RESPONSE_DATA';
140 $records_tags = array();
141 $record_tag = 'RESPONSE';
142 $record_tags = array();
143 $more_backup = 'hotpot_backup_string_ids($record, array("correct","wrong","ignored"));';
144 $excluded_tags = array('id','attempt');
145 return hotpot_backup_records(
146 $bf, $status, $level,
147 $table, $select,
148 $records_tag, $records_tags,
149 $record_tag, $record_tags,
150 $excluded_tags, $more_backup
153 function hotpot_backup_questions($bf, &$parent, $level, $status) {
154 // $parent is a reference to an hotpot record
155 $table = 'hotpot_questions';
156 $select = "hotpot=$parent->id";
157 $records_tag = 'QUESTION_DATA';
158 $records_tags = array();
159 $record_tag = 'QUESTION';
160 $record_tags = array();
161 $more_backup = 'hotpot_backup_string_ids($record, array("text"));';
162 $excluded_tags = array('hotpot');
163 return hotpot_backup_records(
164 $bf, $status, $level,
165 $table, $select,
166 $records_tag, $records_tags,
167 $record_tag, $record_tags,
168 $excluded_tags, $more_backup
171 function hotpot_backup_string_ids(&$record, $fields) {
172 // as the questions and responses tables are backed up
173 // this function is called to store the ids of strings.
174 // The string ids are used later by "hotpot_backup_strings"
175 // $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
176 // store the ids of strings used in this $record's $fields
177 foreach ($fields as $field) {
178 if (empty($record->$field)) {
179 // do nothing
180 } else {
181 $value = $record->$field;
182 $ids = explode(',', "$value");
183 foreach ($ids as $id) {
184 if (empty($id)) {
185 // do nothing
186 } else {
187 $GLOBALS['hotpot_backup_string_ids'][$id] = true;
193 function hotpot_backup_strings($bf, $record, $level, $status) {
194 // This functions backups the strings used
195 // in the question and responses for a single hotpot activity
196 // The ids of the strings were stored by "hotpot_backup_string_ids"
197 // $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
198 // retrieve $ids of strings to be backed up
199 $ids = array_keys($GLOBALS['hotpot_backup_string_ids']);
200 if (empty($ids)) {
201 // no strings to backup
202 } else {
203 sort($ids);
204 $ids = implode(',', $ids);
205 $table = 'hotpot_strings';
206 $select = "id IN ($ids)";
207 $records_tag = 'STRING_DATA';
208 $records_tags = array();
209 $record_tag = 'STRING';
210 $record_tags = array();
211 $more_backup = '';
212 $excluded_tags = array('');
213 $status = hotpot_backup_records(
214 $bf, $status, $level,
215 $table, $select,
216 $records_tag, $records_tags,
217 $record_tag, $record_tags,
218 $excluded_tags, $more_backup
221 return $status;
223 function hotpot_backup_records(&$bf, $status, $level, $table, $select, $records_tag, $records_tags, $record_tag, $record_tags, $excluded_tags, $more_backup) {
224 // general purpose backup function
225 // $bf : resource id of backup file
226 // $status : current status of backup (true or false)
227 // $level : current depth level in the backup XML tree
228 // $table : table from which records will be selected and backed up
229 // $select : SQL selection string
230 // $records_tag : optional XML tag which starts a group of records (and descends a level)
231 // $records_tags : optional XML tags to be inserted at the start of a group of records
232 // $record_tag : optional XML tag which starts a record (and descends a level)
233 // $record_tags : optional XML tags to be inserted at the start of a record
234 // $excluded_tags : fields which will NOT be backed up from the records
235 // $more_backup : optional PHP code to be eval(uated) for each record
236 // If any of the "fwrite" statements fail,
237 // no further "fwrite"s will be attempted
238 // and the function returns "false".
239 // Otherwise, the function returns "true".
240 if ($status && ($records = get_records_select($table, $select, 'id'))) {
241 // start a group of records
242 if ($records_tag) {
243 $status = $status && fwrite($bf, start_tag($records_tag, $level, true));
244 $level++;
245 foreach ($records_tags as $tag) {
246 $status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
249 foreach ($records as $record) {
250 // start a single record
251 if ($record_tag) {
252 $status = $status && fwrite($bf, start_tag($record_tag, $level, true));
253 $level++;
254 foreach ($record_tags as $tag=>$value) {
255 $status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
258 // backup fields in this record
259 $tags = get_object_vars($record);
260 foreach ($tags as $tag=>$value) {
261 if (!is_numeric($tag) && !in_array($tag, $excluded_tags)) {
262 $status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
265 // backup related records, if required
266 if ($more_backup) {
267 eval($more_backup);
269 // end a single record
270 if ($record_tag) {
271 $level--;
272 $status = $status && fwrite($bf, end_tag($record_tag, $level, true));
275 // end a group of records
276 if ($records_tag) {
277 $level--;
278 $status = $status && fwrite($bf, end_tag($records_tag, $level, true));
281 return $status;
283 ////Return an array of info (name, value)
284 function hotpot_check_backup_mods($course, $user_data=false, $backup_unique_code, $instances=null) {
285 global $CFG;
286 $info = array();
287 if (isset($instances) && is_array($instances) && count($instances)) {
288 foreach ($instances as $id => $instance) {
289 $info += hotpot_check_backup_mods_instances($instance,$backup_unique_code);
291 } else {
292 // the course data
293 $info[0][0] = get_string('modulenameplural','hotpot');
294 $info[0][1] = count_records('hotpot', 'course', $course);
296 // the user_data, if requested
297 if ($user_data) {
298 $table = "{$CFG->prefix}hotpot h, {$CFG->prefix}hotpot_attempts a";
299 $select = "h.course = $course AND h.id = a.hotpot";
301 $info[1][0] = get_string('attempts', 'quiz');
302 $info[1][1] = count_records_sql("SELECT COUNT(*) FROM $table WHERE $select");
305 return $info;
308 ////Return an array of info (name, value)
309 function hotpot_check_backup_mods_instances($instance,$backup_unique_code) {
310 global $CFG;
311 $info = array();
313 // the course data
314 $info[$instance->id.'0'][0] = '<b>'.$instance->name.'</b>';
315 $info[$instance->id.'0'][1] = '';
317 // the user_data, if requested
318 if (!empty($instance->userdata)) {
319 $table = "{$CFG->prefix}hotpot_attempts a";
320 $select = "a.hotpot = $instance->id";
322 $info[$instance->id.'1'][0] = get_string('attempts', 'quiz');
323 $info[$instance->id.'1'][1] = count_records_sql("SELECT COUNT(*) FROM $table WHERE $select");
325 return $info;
328 // Return content encoded to support interactivities linking.
329 // Called by "backup_encode_absolute_links()" in backup/backuplib.php
330 // Content will be decoded by "hotpot_decode_content_links()"
331 function hotpot_encode_content_links ($content, $preferences) {
332 global $CFG;
333 $base = preg_quote("$CFG->wwwroot/mod/hotpot/", '/');
334 $search = "/($base)([a-z]+).php\?([a-z]+)\=([0-9]+)/";
335 return preg_replace($search, '$@HOTPOT*$2*$3*$4@$', $content);