Fixed hard coded string
[moodle-linuxchix.git] / question / backuplib.php
blob51a49dbd85ac4f4fab047db832bd61b40710763d
1 <?php //$Id$
2 /**
3 * Question bank backup code.
5 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
6 * @package questionbank
7 *//** */
9 //This is the "graphical" structure of the question database:
10 //To see, put your terminal to 160cc
12 // The following holds student-independent information about the questions
14 // question_categories
15 // (CL,pk->id)
16 // |
17 // |
18 // |.......................................
19 // | .
20 // | .
21 // | -------question_datasets------ .
22 // | | (CL,pk->id,fk->question, | .
23 // | | fk->dataset_definition) | .
24 // | | | .
25 // | | | .
26 // | | | .
27 // | | question_dataset_definitions
28 // | | (CL,pk->id,fk->category)
29 // question |
30 // (CL,pk->id,fk->category,files) |
31 // | question_dataset_items
32 // | (CL,pk->id,fk->definition)
33 // | question_rqp_type
34 // | (SL,pk->id)
35 // | |
36 // -------------------------------------------------------------------------------------------------------------- |
37 // | | | | | | | question_rqp
38 // | | | | | | |--(CL,pk->id,fk->question)
39 // | | | | question_calculated | |
40 // question_truefalse | question_multichoice | (CL,pl->id,fk->question) | |
41 // (CL,pk->id,fk->question) | (CL,pk->id,fk->question) | . | | question_randomsamatch
42 // . | . | . | |--(CL,pk->id,fk->question)
43 // . question_shortanswer . question_numerical . question_multianswer. |
44 // . (CL,pk->id,fk->question) . (CL,pk->id,fk->question) . (CL,pk->id,fk->question) |
45 // . . . . . . | question_match
46 // . . . . . . |--(CL,pk->id,fk->question)
47 // . . . . . . | .
48 // . . . . . . | .
49 // . . . . . . | .
50 // . . . . . . | question_match_sub
51 // ........................................................................................ |--(CL,pk->id,fk->question)
52 // . |
53 // . |
54 // . | question_numerical_units
55 // question_answers |--(CL,pk->id,fk->question)
56 // (CL,pk->id,fk->question)----------------------------------------------------------
59 // The following holds the information about student interaction with the questions
61 // question_sessions
62 // (UL,pk->id,fk->attempt,question)
63 // .
64 // .
65 // question_states
66 // (UL,pk->id,fk->attempt,question)
67 // |
68 // question_rqp_states
69 // (UL,pk->id,fk->stateid)
71 // Meaning: pk->primary key field of the table
72 // fk->foreign key to link with parent
73 // nt->nested field (recursive data)
74 // SL->site level info
75 // CL->course level info
76 // UL->user level info
77 // files->table may have files
79 //-----------------------------------------------------------
81 require_once("$CFG->libdir/questionlib.php");
83 function backup_question_categories($bf,$preferences) {
85 global $CFG;
87 $status = true;
89 //First, we get the used categories from backup_ids
90 $categories = question_category_ids_by_backup ($preferences->backup_unique_code);
92 //If we've categories
93 if ($categories) {
94 //Write start tag
95 $status = fwrite($bf,start_tag("QUESTION_CATEGORIES",2,true));
96 //Iterate over each category
97 foreach ($categories as $cat) {
98 //Start category
99 $status = fwrite ($bf,start_tag("QUESTION_CATEGORY",3,true));
100 //Get category data from question_categories
101 $category = get_record ("question_categories","id",$cat->old_id);
102 //Print category contents
103 fwrite($bf,full_tag("ID",4,false,$category->id));
104 fwrite($bf,full_tag("NAME",4,false,$category->name));
105 fwrite($bf,full_tag("INFO",4,false,$category->info));
106 fwrite($bf,full_tag("PUBLISH",4,false,$category->publish));
107 fwrite($bf,full_tag("STAMP",4,false,$category->stamp));
108 fwrite($bf,full_tag("PARENT",4,false,$category->parent));
109 fwrite($bf,full_tag("SORTORDER",4,false,$category->sortorder));
110 //Now, backup their questions
111 $status = backup_question($bf,$preferences,$category->id);
112 //End category
113 $status = fwrite ($bf,end_tag("QUESTION_CATEGORY",3,true));
115 //Write end tag
116 $status = fwrite ($bf,end_tag("QUESTION_CATEGORIES",2,true));
119 return $status;
122 //This function backups all the questions in selected category and their
123 //asociated data
124 function backup_question($bf,$preferences,$category, $level = 4) {
126 global $CFG, $QTYPES;
128 $status = true;
130 // We'll fetch the questions sorted by parent so that questions with no parents
131 // (these are the ones which could be parents themselves) are backed up first. This
132 // is important for the recoding of the parent field during the restore process
133 $questions = get_records("question","category",$category,"parent ASC, id");
134 //If there are questions
135 if ($questions) {
136 //Write start tag
137 $status = fwrite ($bf,start_tag("QUESTIONS",$level,true));
138 $counter = 0;
139 //Iterate over each question
140 foreach ($questions as $question) {
141 //Start question
142 $status = fwrite ($bf,start_tag("QUESTION",$level + 1,true));
143 //Print question contents
144 fwrite ($bf,full_tag("ID",$level + 2,false,$question->id));
145 fwrite ($bf,full_tag("PARENT",$level + 2,false,$question->parent));
146 fwrite ($bf,full_tag("NAME",$level + 2,false,$question->name));
147 fwrite ($bf,full_tag("QUESTIONTEXT",$level + 2,false,$question->questiontext));
148 fwrite ($bf,full_tag("QUESTIONTEXTFORMAT",$level + 2,false,$question->questiontextformat));
149 fwrite ($bf,full_tag("IMAGE",$level + 2,false,$question->image));
150 fwrite ($bf,full_tag("GENERALFEEDBACK",$level + 2,false,$question->generalfeedback));
151 fwrite ($bf,full_tag("DEFAULTGRADE",$level + 2,false,$question->defaultgrade));
152 fwrite ($bf,full_tag("PENALTY",$level + 2,false,$question->penalty));
153 fwrite ($bf,full_tag("QTYPE",$level + 2,false,$question->qtype));
154 fwrite ($bf,full_tag("LENGTH",$level + 2,false,$question->length));
155 fwrite ($bf,full_tag("STAMP",$level + 2,false,$question->stamp));
156 fwrite ($bf,full_tag("VERSION",$level + 2,false,$question->version));
157 fwrite ($bf,full_tag("HIDDEN",$level + 2,false,$question->hidden));
158 // Backup question type specific data
159 $status = $QTYPES[$question->qtype]->backup($bf,$preferences,$question->id, $level + 2);
160 //End question
161 $status = fwrite ($bf,end_tag("QUESTION",$level + 1,true));
162 //Do some output
163 $counter++;
164 if ($counter % 10 == 0) {
165 echo ".";
166 if ($counter % 200 == 0) {
167 echo "<br />";
169 backup_flush(300);
172 //Write end tag
173 $status = fwrite ($bf,end_tag("QUESTIONS",$level,true));
175 return $status;
178 //This function backups the answers data in some question types
179 //(truefalse, shortanswer,multichoice,numerical,calculated)
180 function question_backup_answers($bf,$preferences,$question, $level = 6) {
182 global $CFG;
184 $status = true;
186 $answers = get_records("question_answers","question",$question,"id");
187 //If there are answers
188 if ($answers) {
189 $status = fwrite ($bf,start_tag("ANSWERS",$level,true));
190 //Iterate over each answer
191 foreach ($answers as $answer) {
192 $status = fwrite ($bf,start_tag("ANSWER",$level + 1,true));
193 //Print answer contents
194 fwrite ($bf,full_tag("ID",$level + 2,false,$answer->id));
195 fwrite ($bf,full_tag("ANSWER_TEXT",$level + 2,false,$answer->answer));
196 fwrite ($bf,full_tag("FRACTION",$level + 2,false,$answer->fraction));
197 fwrite ($bf,full_tag("FEEDBACK",$level + 2,false,$answer->feedback));
198 $status = fwrite ($bf,end_tag("ANSWER",$level + 1,true));
200 $status = fwrite ($bf,end_tag("ANSWERS",$level,true));
202 return $status;
205 //This function backups question_numerical_units from different question types
206 function question_backup_numerical_units($bf,$preferences,$question,$level=7) {
208 global $CFG;
210 $status = true;
212 $numerical_units = get_records("question_numerical_units","question",$question,"id");
213 //If there are numericals_units
214 if ($numerical_units) {
215 $status = fwrite ($bf,start_tag("NUMERICAL_UNITS",$level,true));
216 //Iterate over each numerical_unit
217 foreach ($numerical_units as $numerical_unit) {
218 $status = fwrite ($bf,start_tag("NUMERICAL_UNIT",$level+1,true));
219 //Print numerical_unit contents
220 fwrite ($bf,full_tag("MULTIPLIER",$level+2,false,$numerical_unit->multiplier));
221 fwrite ($bf,full_tag("UNIT",$level+2,false,$numerical_unit->unit));
222 //Now backup numerical_units
223 $status = fwrite ($bf,end_tag("NUMERICAL_UNIT",$level+1,true));
225 $status = fwrite ($bf,end_tag("NUMERICAL_UNITS",$level,true));
228 return $status;
232 //This function backups dataset_definitions (via question_datasets) from different question types
233 function question_backup_datasets($bf,$preferences,$question,$level=7) {
235 global $CFG;
237 $status = true;
239 //First, we get the used datasets for this question
240 $question_datasets = get_records("question_datasets","question",$question,"id");
241 //If there are question_datasets
242 if ($question_datasets) {
243 $status = $status &&fwrite ($bf,start_tag("DATASET_DEFINITIONS",$level,true));
244 //Iterate over each question_dataset
245 foreach ($question_datasets as $question_dataset) {
246 $def = NULL;
247 //Get dataset_definition
248 if ($def = get_record("question_dataset_definitions","id",$question_dataset->datasetdefinition)) {;
249 $status = $status &&fwrite ($bf,start_tag("DATASET_DEFINITION",$level+1,true));
250 //Print question_dataset contents
251 fwrite ($bf,full_tag("CATEGORY",$level+2,false,$def->category));
252 fwrite ($bf,full_tag("NAME",$level+2,false,$def->name));
253 fwrite ($bf,full_tag("TYPE",$level+2,false,$def->type));
254 fwrite ($bf,full_tag("OPTIONS",$level+2,false,$def->options));
255 fwrite ($bf,full_tag("ITEMCOUNT",$level+2,false,$def->itemcount));
256 //Now backup dataset_entries
257 $status = question_backup_dataset_items($bf,$preferences,$def->id,$level+2);
258 //End dataset definition
259 $status = $status &&fwrite ($bf,end_tag("DATASET_DEFINITION",$level+1,true));
262 $status = $status &&fwrite ($bf,end_tag("DATASET_DEFINITIONS",$level,true));
265 return $status;
269 //This function backups datases_items from dataset_definitions
270 function question_backup_dataset_items($bf,$preferences,$datasetdefinition,$level=9) {
272 global $CFG;
274 $status = true;
276 //First, we get the datasets_items for this dataset_definition
277 $dataset_items = get_records("question_dataset_items","definition",$datasetdefinition,"id");
278 //If there are dataset_items
279 if ($dataset_items) {
280 $status = $status &&fwrite ($bf,start_tag("DATASET_ITEMS",$level,true));
281 //Iterate over each dataset_item
282 foreach ($dataset_items as $dataset_item) {
283 $status = $status &&fwrite ($bf,start_tag("DATASET_ITEM",$level+1,true));
284 //Print question_dataset contents
285 fwrite ($bf,full_tag("NUMBER",$level+2,false,$dataset_item->itemnumber));
286 fwrite ($bf,full_tag("VALUE",$level+2,false,$dataset_item->value));
287 //End dataset definition
288 $status = $status &&fwrite ($bf,end_tag("DATASET_ITEM",$level+1,true));
290 $status = $status &&fwrite ($bf,end_tag("DATASET_ITEMS",$level,true));
293 return $status;
298 //Backup question_states contents (executed from backup_quiz_attempts)
299 function backup_question_states ($bf,$preferences,$attempt, $level = 6) {
301 global $CFG;
303 $status = true;
305 $question_states = get_records("question_states","attempt",$attempt,"id");
306 //If there are states
307 if ($question_states) {
308 //Write start tag
309 $status = fwrite ($bf,start_tag("STATES",$level,true));
310 //Iterate over each state
311 foreach ($question_states as $state) {
312 //Start state
313 $status = fwrite ($bf,start_tag("STATE",$level + 1,true));
314 //Print state contents
315 fwrite ($bf,full_tag("ID",$level + 2,false,$state->id));
316 fwrite ($bf,full_tag("QUESTION",$level + 2,false,$state->question));
317 fwrite ($bf,full_tag("ORIGINALQUESTION",$level + 2,false,$state->originalquestion));
318 fwrite ($bf,full_tag("SEQ_NUMBER",$level + 2,false,$state->seq_number));
319 fwrite ($bf,full_tag("ANSWER",$level + 2,false,$state->answer));
320 fwrite ($bf,full_tag("TIMESTAMP",$level + 2,false,$state->timestamp));
321 fwrite ($bf,full_tag("EVENT",$level + 2,false,$state->event));
322 fwrite ($bf,full_tag("GRADE",$level + 2,false,$state->grade));
323 fwrite ($bf,full_tag("RAW_GRADE",$level + 2,false,$state->raw_grade));
324 fwrite ($bf,full_tag("PENALTY",$level + 2,false,$state->penalty));
325 // now back up question type specific state information
326 $status = backup_question_rqp_state ($bf,$preferences,$state->id, $level + 2);
327 //End state
328 $status = fwrite ($bf,end_tag("STATE",$level + 1,true));
330 //Write end tag
331 $status = fwrite ($bf,end_tag("STATES",$level,true));
335 //Backup question_sessions contents (executed from backup_quiz_attempts)
336 function backup_question_sessions ($bf,$preferences,$attempt, $level = 6) {
337 global $CFG;
339 $status = true;
341 $question_sessions = get_records("question_sessions","attemptid",$attempt,"id");
342 //If there are sessions
343 if ($question_sessions) {
344 //Write start tag (the funny name 'newest states' has historical reasons)
345 $status = fwrite ($bf,start_tag("NEWEST_STATES",$level,true));
346 //Iterate over each newest_state
347 foreach ($question_sessions as $newest_state) {
348 //Start newest_state
349 $status = fwrite ($bf,start_tag("NEWEST_STATE",$level + 1,true));
350 //Print newest_state contents
351 fwrite ($bf,full_tag("ID",$level + 2,false,$newest_state->id));
352 fwrite ($bf,full_tag("QUESTIONID",$level + 2,false,$newest_state->questionid));
353 fwrite ($bf,full_tag("NEWEST",$level + 2,false,$newest_state->newest));
354 fwrite ($bf,full_tag("NEWGRADED",$level + 2,false,$newest_state->newgraded));
355 fwrite ($bf,full_tag("SUMPENALTY",$level + 2,false,$newest_state->sumpenalty));
356 fwrite ($bf,full_tag("MANUALCOMMENT",$level + 2,false,$newest_state->manualcomment));
357 //End newest_state
358 $status = fwrite ($bf,end_tag("NEWEST_STATE",$level + 1,true));
360 //Write end tag
361 $status = fwrite ($bf,end_tag("NEWEST_STATES",$level,true));
363 return $status;
366 //Backup question_rqp_state contents (executed from backup_question_states)
367 function backup_question_rqp_state ($bf,$preferences,$state, $level = 8) {
369 global $CFG;
371 $status = true;
373 $rqp_state = get_record("question_rqp_states","stateid",$state);
374 //If there is a state
375 if ($rqp_state) {
376 //Write start tag
377 $status = fwrite ($bf,start_tag("RQP_STATE",$level,true));
378 //Print state contents
379 fwrite ($bf,full_tag("RESPONSES",$level + 1,false,$rqp_state->responses));
380 fwrite ($bf,full_tag("PERSISTENT_DATA",$level + 1,false,$rqp_state->persistent_data));
381 fwrite ($bf,full_tag("TEMPLATE_VARS",$level + 1,false,$rqp_state->template_vars));
382 //Write end tag
383 $status = fwrite ($bf,end_tag("RQP_STATE",$level,true));
385 return $status;
388 //Returns an array of categories id
389 function question_category_ids_by_backup ($backup_unique_code) {
391 global $CFG;
393 return get_records_sql ("SELECT a.old_id, a.backup_code
394 FROM {$CFG->prefix}backup_ids a
395 WHERE a.backup_code = '$backup_unique_code' AND
396 a.table_name = 'question_categories'");
399 function question_ids_by_backup ($backup_unique_code) {
401 global $CFG;
403 return get_records_sql ("SELECT q.id, q.category
404 FROM {$CFG->prefix}backup_ids a,
405 {$CFG->prefix}question q
406 WHERE a.backup_code = '$backup_unique_code' AND
407 q.category = a.old_id AND
408 a.table_name = 'question_categories'");
411 //Delete category ids from backup_ids table
412 function delete_category_ids ($backup_unique_code) {
413 global $CFG;
414 $status = true;
415 $status = execute_sql("DELETE FROM {$CFG->prefix}backup_ids
416 WHERE backup_code = '$backup_unique_code'",false);
417 return $status;