remove old readme
[atutor.git] / mods / _core / backups / classes / TableBackup.class.php
1 <?php\r
2 /************************************************************************/\r
3 /* ATutor                                                                                                                               */\r
4 /************************************************************************/\r
5 /* Copyright (c) 2002-2010                                              */\r
6 /* Inclusive Design Institute                                           */\r
7 /* http://atutor.ca                                                                                                             */\r
8 /*                                                                                                                                              */\r
9 /* This program is free software. You can redistribute it and/or        */\r
10 /* modify it under the terms of the GNU General Public License          */\r
11 /* as published by the Free Software Foundation.                        */\r
12 /************************************************************************/\r
13 // $Id$\r
14 \r
15 exit(__FILE__ . ' no longer used');\r
16 /**\r
17 * TableFactory\r
18 * Class for creating AbstractTable Objects\r
19 * @access       public\r
20 * @author       Joel Kronenberg\r
21 * @package      Backup\r
22 */\r
23 class TableFactory {\r
24         /**\r
25         * The database handler.\r
26         *\r
27         * @access  private\r
28         * @var resource\r
29         */\r
30         var $db;\r
31 \r
32         /**\r
33         * The ATutor version this backup was created with.\r
34         *\r
35         * @access private\r
36         * @var string\r
37         */\r
38         var $version;\r
39 \r
40         /**\r
41         * The course ID we're restoring into.\r
42         *\r
43         * @access private\r
44         * @var int\r
45         */\r
46         var $course_id;\r
47 \r
48         /**\r
49         * The directory unzip backup is found.\r
50         *\r
51         * @access private\r
52         * @var string\r
53         */\r
54         var $import_dir;\r
55 \r
56         /**\r
57         * Constructor.\r
58         * \r
59         * @param string $version The backup version.\r
60         * @param resource $db The database handler.\r
61         * @param int $course_id The ID of this course.\r
62         * @param string $import_dir The directory where the backup was unzipped to.\r
63         * \r
64         */\r
65         function TableFactory ($version, $db, $course_id, $import_dir) {\r
66                 $this->version    = $version;\r
67                 $this->db         = $db;\r
68                 $this->course_id  = $course_id;\r
69                 $this->import_dir = $import_dir;\r
70         }\r
71 \r
72         /**\r
73         * Create and return the specified AbstractTable Object.\r
74         * \r
75         * @access public\r
76         * @param string $table_name The name of the table to create an Object for.\r
77         * @return AbstractTable Object|NULL if $table_name does not match available Objects.\r
78         * @See AbstractTable\r
79         *\r
80         */\r
81         function createTable($table_name) {\r
82                 // static hash to keep track of new ID mappings:\r
83                 static $id_map;\r
84 \r
85                 switch ($table_name) {\r
86                         case 'stats':\r
87                                 return new CourseStatsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
88                                 break;\r
89 \r
90                         /*\r
91                         case 'polls':\r
92                                 return new PollsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
93                                 break;\r
94                         */\r
95 \r
96                         case 'tests':\r
97                                 return new TestsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
98                                 break;\r
99 \r
100                         case 'tests_questions_categories':\r
101                                 return new TestsQuestionsCategoriesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
102                                 break;\r
103 \r
104                         case 'tests_questions_assoc':\r
105                                 return new TestsQuestionsAssocTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
106                                 break;\r
107 \r
108                         case 'tests_questions':\r
109                                 return new TestsQuestionsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
110                                 break;\r
111 \r
112                         case 'news':\r
113                                 return new NewsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
114                                 break;\r
115 \r
116                         case 'groups':\r
117                                 return new GroupsTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
118                                 break;\r
119 \r
120                         case 'forums':\r
121                                 return new ForumsTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
122                                 break;\r
123 \r
124                         case 'forums_courses':\r
125                                 return new ForumsCoursesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
126                                 break;\r
127 \r
128                         case 'glossary':\r
129                                 return new GlossaryTable($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
130                                 break;\r
131 \r
132                         case 'resource_links':\r
133                                 return new ResourceLinksTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
134                                 break;\r
135 \r
136                         case 'resource_categories':\r
137                                 return new ResourceCategoriesTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
138                                 break;\r
139 \r
140                         case 'content':\r
141                                 return new ContentTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
142                                 break;\r
143 \r
144                         case 'related_content':\r
145                                 return new RelatedContentTable($this->version, $this->db, $this->course_id, $this->import_dir, $id_map);\r
146                                 break;\r
147 \r
148                         default:\r
149                                 if (class_exists($table_name . 'Table')) {\r
150                                         $table_name = $table_name . 'Table';\r
151                                         return new $table_name($this->version, $this->db, $this->course_id, $this->import_dir, $garbage);\r
152                                 }\r
153                                 return NULL;\r
154                 }\r
155         }\r
156 }\r
157 \r
158 /**\r
159 * AbstractTable\r
160 * Class for restoring backup tables\r
161 * @access       public\r
162 * @author       Joel Kronenberg\r
163 * @package      Backup\r
164 */\r
165 class AbstractTable {\r
166         /**\r
167         * The ATutor version this backup was created with.\r
168         *\r
169         * @access protected\r
170         * @var string\r
171         */\r
172         var $version;\r
173 \r
174         /**\r
175         * The database handler.\r
176         *\r
177         * @access  private\r
178         * @var resource\r
179         */\r
180         var $db;\r
181 \r
182         /**\r
183         * The CSV table file handler.\r
184         *\r
185         * @access  private\r
186         * @var resource\r
187         */\r
188         var $fp;\r
189 \r
190         /**\r
191         * The course ID we're restoring into.\r
192         *\r
193         * @access private\r
194         * @var int\r
195         */\r
196         var $course_id;\r
197 \r
198         /**\r
199         * The directory unzip backup is found.\r
200         *\r
201         * @access private\r
202         * @var string\r
203         */\r
204         var $import_dir;\r
205 \r
206         /**\r
207         * A hash table associated old ID's (key) with their new ID's (value).\r
208         *\r
209         * @access private\r
210         * @var array\r
211         */\r
212         var $old_ids_to_new_ids;\r
213 \r
214         /**\r
215         * Constructor.\r
216         * \r
217         * @param string $version The backup version.\r
218         * @param resource $db The database handler.\r
219         * @param int $course_id The ID of this course.\r
220         * @param string $import_dir The directory where the backup was unzipped to.\r
221         * @param array $old_ids_to_new_ids Reference.\r
222         * \r
223         */\r
224         function AbstractTable($version, $db, $course_id, $import_dir, &$old_ids_to_new_ids) {\r
225                 global $db;\r
226                 $this->db = $db;\r
227                 $this->course_id = $course_id;\r
228                 $this->version = $version;\r
229                 $this->import_dir = $import_dir;\r
230 \r
231                 $this->old_ids_to_new_ids = $old_ids_to_new_ids;\r
232 \r
233                 if (!isset($this->old_ids_to_new_ids[$this->tableName])) {\r
234                         $this->old_ids_to_new_ids[$this->tableName] = array();\r
235                 }\r
236         }\r
237 \r
238         // -- public methods below:\r
239 \r
240         /**\r
241         * Restores the table defined in the CSV file, one row at a time.\r
242         * \r
243         * @access public\r
244         * @return void\r
245         *\r
246         * @See getRows()\r
247         * @See insertRow()\r
248         */\r
249         function restore() {\r
250                 global $db;\r
251 \r
252                 // skipLock is used specificially with the `forums_courses` table\r
253                 if (!isset($this->skipLock)) {\r
254                         $this->lockTable();\r
255                 }\r
256 \r
257                 $this->getRows();\r
258 \r
259                 if ($this->rows) {\r
260                         foreach ($this->rows as $row) {\r
261                                 \r
262                                 $sql = $this->generateSQL($row); \r
263                                 mysql_query($sql, $db);\r
264                                 //debug($sql);\r
265                                 //debug(mysql_error($this->db));\r
266                         }\r
267                 }\r
268                 if (!isset($this->skipLock)) {\r
269                         $this->unlockTable();\r
270                 }\r
271         }\r
272 \r
273         // -- protected methods below:\r
274 \r
275         /**\r
276         * Converts escaped white space characters to their correct representation.\r
277         * \r
278         * @access protected\r
279         * @param string $input The string to convert.\r
280         * @return string The converted string.\r
281         * @See Backup::quoteCSV()\r
282         */\r
283         function translateWhitespace($input) {\r
284                 $input = str_replace('\n', "\n", $input);\r
285                 $input = str_replace('\r', "\r", $input);\r
286                 $input = str_replace('\x00', "\0", $input);\r
287 \r
288                 $input = addslashes($input);\r
289                 return $input;\r
290         }\r
291 \r
292         // protected\r
293         // find the index offset\r
294         function findOffset($id) {\r
295                 return $this->rows[$id]['index_offset'];\r
296         }\r
297 \r
298         // -- private methods below:\r
299         function getNextID() {\r
300                 global $db;\r
301 \r
302                 $sql      = 'SELECT MAX(' . $this->primaryIDField . ') AS next_id FROM ' . TABLE_PREFIX . $this->tableName;\r
303                 $result   = mysql_query($sql, $db);\r
304                 $next_index = mysql_fetch_assoc($result);\r
305                 return ($next_index['next_id'] + 1);\r
306         }\r
307 \r
308         /**\r
309          * Gets the member_id of the instructor who owns a course in the context of a backup restore\r
310          *\r
311          * @param int $id The backup course to query on\r
312          * @access protected\r
313          * @return int The member_id who owns the corresponding backup course\r
314          */\r
315         function resolveBkpOwner($id) {\r
316                 global $db;\r
317 \r
318                 $sql = 'SELECT member_id FROM ' . TABLE_PREFIX . 'courses WHERE course_id = '. $id;\r
319 \r
320                 $result = mysql_query($sql, $db);\r
321                 \r
322                 if (!$result) {\r
323                         echo 'Fatal SQL error occured in TableBackup:resolveBkpOwner: ' . mysql_error() . \r
324                                                                 ' ' . mysql_error($db) . \r
325                                                                 ' Check that the course your are restoring to exists.';\r
326                         return;\r
327                 }\r
328                 \r
329                 $row = mysql_fetch_assoc($result);\r
330                 \r
331                 if (!$row) {\r
332                         echo 'Fatal SQL error occured in TableBackup:resolveBkpOwner: ' . mysql_error() . \r
333                                                                 ' ' . mysql_error($db) . \r
334                                                                 ' Check that the course your are restoring to exists.';\r
335                         return;\r
336                 }\r
337                 \r
338                 return $row['member_id'];\r
339         }\r
340         \r
341         /**\r
342         * Reads the CSV table file into array $this->rows.\r
343         * \r
344         * @access private\r
345         * @return void\r
346         *\r
347         * @See openTable()\r
348         * @See closeTable()\r
349         * @See getOldID()\r
350         */\r
351         function getRows() {\r
352                 $this->openFile();\r
353                 $i = 0;\r
354 \r
355                 $next_id = $this->getNextID();\r
356 \r
357                 while ($row = @fgetcsv($this->fp, 70000)) {\r
358                         if (count($row)) {\r
359                                 $row[0] = trim($row[0]);\r
360                                 if ($row[0] == '') {\r
361                                         continue;\r
362                                 }\r
363                         }\r
364                         $row = $this->translateText($row);\r
365                         $row = $this->convert($row);\r
366 \r
367                         $row['index_offset'] = $i;\r
368                         $row['new_id'] = $next_id++;\r
369                         if ($this->getOldID($row) === FALSE) {\r
370                                 $this->rows[] = $row;\r
371                         } else {\r
372                                 $this->rows[$this->getOldID($row)] = $row;\r
373                                 $this->old_ids_to_new_ids[$this->tableName][$this->getOldID($row)] = $row['new_id'];\r
374                         }\r
375 \r
376                         $i++;\r
377                 }\r
378                 $this->closeFile();\r
379         }\r
380 \r
381         /**\r
382         * Converts $row to be ready for inserting into the db.\r
383         * \r
384         * @param array $row The row to convert.\r
385         * @access private\r
386         * @return array The converted row.\r
387         *\r
388         * @see translateWhitespace()\r
389         */\r
390         function translateText($row) {\r
391                 return $row;\r
392                 global $backup_tables;\r
393                 $count = 0;\r
394 \r
395                 foreach ($backup_tables[$this->tableName]['fields'] as $field) {\r
396                         if ($field[1] == TEXT) {\r
397                                 $row[$count] = $this->translateWhitespace($row[$count]);\r
398                         }\r
399                         $count++;\r
400                 }\r
401                 return $row;\r
402         }\r
403 \r
404         /**\r
405         * Locks the database table for writing or/and also lock the courses table for resolving restore issues\r
406         * in the admin context \r
407         * \r
408         * @access private\r
409         * @return void\r
410         *\r
411         * @See unlockTable()\r
412         */\r
413         function lockTable() {\r
414                 global $db;\r
415                 $lock_sql;\r
416                         \r
417                 if ($_SESSION['member_id'])\r
418                         $lock_sql = 'LOCK TABLES ' . TABLE_PREFIX . $this->tableName. ' WRITE';\r
419                 else // admin context\r
420                         $lock_sql = 'LOCK TABLES ' . TABLE_PREFIX . $this->tableName. ', ' . TABLE_PREFIX . 'courses WRITE';\r
421                         \r
422                 $result   = mysql_query($lock_sql, $db);\r
423         }\r
424 \r
425         /**\r
426         * UnLocks the database table.\r
427         * \r
428         * @access private\r
429         * @return void\r
430         *\r
431         * @See lockTable()\r
432         */\r
433         function unlockTable() {\r
434                 global $db;\r
435                 $lock_sql = 'UNLOCK TABLES';\r
436                 $result   = mysql_query($lock_sql, $db);\r
437         }\r
438 \r
439         /**\r
440         * Opens the CSV table file for reading.\r
441         * \r
442         * @access private\r
443         * @return void\r
444         *\r
445         * @See closeFile()\r
446         */\r
447         function openFile() {\r
448                 $this->fp = @fopen($this->import_dir . $this->tableName . '.csv', 'rb');\r
449         }\r
450 \r
451         /**\r
452         * Closes the CSV table file.\r
453         * \r
454         * @access private\r
455         * @return void\r
456         *\r
457         * @See openFile()\r
458         */\r
459         function closeFile() {\r
460                 @fclose($this->fp);\r
461         }\r
462 \r
463         /**\r
464         * Gets the entry/row's new ID based on it's old entry ID.\r
465         * \r
466         * @param int $id The old entry ID.\r
467         * @access protected\r
468         * @return int The new entry ID\r
469         *\r
470         */\r
471         function getNewID($id) {\r
472                 return $this->rows[$id]['new_id'];\r
473         }\r
474         \r
475         // -- abstract methods below:\r
476         /**\r
477         * Gets the entry/row ID as it appears in the CSV file, or FALSE if n/a.\r
478         * \r
479         * @param array $row The old entry row from the CSV file.\r
480         * @access private\r
481         * @return boolean|int The old ID or FALSE if not applicable.\r
482         *\r
483         */\r
484         function getOldID($row)    { /* abstract */ }\r
485 \r
486         /**\r
487         * Convert the entry/row to the current ATutor version.\r
488         * \r
489         * @param array $row The old entry row from the CSV file.\r
490         * @access private\r
491         * @return array The converted row.\r
492         *\r
493         */\r
494         function convert($row)     { /* abstract */ }\r
495 \r
496         /**\r
497         * Generate the SQL for this table.\r
498         * \r
499         * Precondition: $row has passed through convert() and \r
500         * translateText().\r
501         *\r
502         * @param array $row The old entry row from the CSV file.\r
503         * @access private\r
504         * @return string The SQL query.\r
505         *\r
506         * @see insertRow()\r
507         */\r
508         function generateSQL($row) { /* abstract */ }\r
509 \r
510 }\r
511 //---------------------------------------------------------------------\r
512 \r
513 /**\r
514 * ForumsTable\r
515 * Extends AbstractTable and provides table specific methods and members.\r
516 * @access       public\r
517 * @author       Joel Kronenberg\r
518 * @author       Heidi Hazelton\r
519 * @package      Backup\r
520 */\r
521 class ForumsTable extends AbstractTable {\r
522         /**\r
523         * The ATutor database table name (w/o prefix).\r
524         * Also the CSV file name (w/o extension).\r
525         *\r
526         * @access private\r
527         * @var const string\r
528         */\r
529         var $tableName      = 'forums';\r
530 \r
531         /**\r
532         * The ATutor database table primary ID field.\r
533         *\r
534         * @access private\r
535         * @var const string\r
536         */\r
537         var $primaryIDField = 'forum_id';\r
538 \r
539         // -- private methods below:\r
540         function getOldID($row) {\r
541                 return $row[0];\r
542         }\r
543 \r
544         function convert($row) {\r
545                 if (version_compare($this->version, '1.4.3', '<')) {\r
546                         // previous versions didn't have a forum_id field\r
547                         static $count;\r
548                         $count++;\r
549                         for($i=5; $i>0; $i--) {\r
550                                 $row[$i] = $row[$i-1];\r
551                         }\r
552                         $row[0] = $count;\r
553                 }\r
554                 return $row;\r
555         }\r
556 \r
557         function generateSQL($row) {\r
558                 $sql = 'INSERT INTO '.TABLE_PREFIX.'forums VALUES ';\r
559                 $sql .= '('.$row['new_id']. ',';\r
560                 $sql .= "'".$row[1]."',"; // title\r
561                 $sql .= "'".$row[2]."',"; // description\r
562                 $sql .= "$row[3],";       // num_topics\r
563                 $sql .= "$row[4],";       // num_posts\r
564                 $sql .= "'".$row[5]."')"; // last_post\r
565                 \r
566                 return $sql;\r
567         }\r
568 }\r
569 //---------------------------------------------------------------------\r
570 /**\r
571 * ForumsCoursesTable\r
572 * Extends AbstractTable and provides table specific methods and members.\r
573 * @access       public\r
574 * @author       Heidi Hazelton\r
575 * @package      Backup\r
576 */\r
577 class ForumsCoursesTable extends AbstractTable {\r
578 \r
579         /**\r
580         * The ATutor database table name (w/o prefix).\r
581         * Also the CSV file name (w/o extension).\r
582         *\r
583         * @access private\r
584         * @var const string\r
585         */\r
586         var $tableName      = 'forums';\r
587 \r
588         /**\r
589         * The ATutor database table primary ID field.\r
590         *\r
591         * @access private\r
592         * @var const string\r
593         */\r
594         var $primaryIDField = 'forum_id';\r
595 \r
596         /**\r
597         * Whether or not lock this table.\r
598         * This is a special case, b/c we read from the `forums` table\r
599         * but insert into the `forums_courses` table. Hence, we lock a different\r
600         * table than we actually insert into (ie. why we don't need/want a lock).\r
601         *\r
602         * @access private\r
603         * @var const boolean\r
604         */\r
605         var $skipLock = TRUE;\r
606 \r
607         // -- private methods below:\r
608         function getOldID($row) {\r
609                 return FALSE;\r
610         }\r
611 \r
612         function convert($row) {\r
613                 return $row;\r
614         }\r
615 \r
616         function generateSQL($row) {\r
617                 $this->count++;\r
618                 if (version_compare($this->version, '1.4.3', '<')) {\r
619                         $id = $this->count;\r
620                 } else {\r
621                         $id = $row[0];\r
622                 }\r
623                 $sql = 'INSERT INTO '.TABLE_PREFIX.'forums_courses VALUES ';\r
624                 $sql .= '('.$this->old_ids_to_new_ids['forums'][$id] . ',';     // forum_id\r
625                 $sql .= $this->course_id .")";          // course_id\r
626 \r
627                 return $sql;\r
628         }\r
629 }\r
630 //---------------------------------------------------------------------\r
631 class GlossaryTable extends AbstractTable {\r
632         var $tableName      = 'glossary';\r
633         var $primaryIDField = 'word_id';\r
634 \r
635         function getOldID($row) {\r
636                 return $row[0];\r
637         }\r
638 \r
639         // private\r
640         function convert($row) {\r
641                 return $row;\r
642         }\r
643 \r
644         // private\r
645         function generateSQL($row) {\r
646                 // insert row\r
647                 $sql = 'INSERT INTO '.TABLE_PREFIX.'glossary VALUES ';\r
648                 $sql .= '('.$row['new_id'].','; // word_id  \r
649                 $sql .= $this->course_id . ',';    // course_id \r
650                 $sql .= "'".$row[1]."',";                  // word\r
651                 $sql .= "'".$row[2]."',";                  // definition\r
652                 if ($row[3] == 0) {\r
653                         $sql .= 0;\r
654                 } else {\r
655                         $sql .= $this->getNewID($row[3]); // related word\r
656                 }\r
657                 $sql .=  ')';\r
658 \r
659                 return $sql;\r
660         }\r
661 }\r
662 //---------------------------------------------------------------------\r
663 class ResourceCategoriesTable extends AbstractTable {\r
664         var $tableName = 'resource_categories';\r
665 \r
666         var $primaryIDField = 'CatID';\r
667 \r
668         function getOldID($row) {\r
669                 return $row[0];\r
670         }\r
671 \r
672         // private\r
673         function convert($row) {\r
674                 return $row;\r
675         }\r
676 \r
677         // private\r
678         function generateSQL($row) {\r
679                 $sql = 'INSERT INTO '.TABLE_PREFIX.'resource_categories VALUES ';\r
680                 $sql .= '('.$row['new_id'].',';\r
681                 $sql .= $this->course_id .',';\r
682                 // CatName\r
683                 $sql .= "'".$row[1]."',";\r
684 \r
685                 // CatParent\r
686                 if ($row[2] == 0) {\r
687                         $sql .= 'NULL';\r
688                 } else {\r
689                         $sql .= $this->getNewID($row[2]); // category parent\r
690                 }\r
691                 $sql .= ')';\r
692 \r
693                 return $sql;\r
694         }\r
695 }\r
696 \r
697 //---------------------------------------------------------------------\r
698 class ResourceLinksTable extends AbstractTable {\r
699         var $tableName = 'resource_links';\r
700 \r
701         var $primaryIDField = 'LinkID';\r
702 \r
703         function getOldID($row) {\r
704                 return FALSE;\r
705         }\r
706 \r
707         // private\r
708         function convert($row) {\r
709                 // handle the white space issue as well\r
710                 return $row;\r
711         }\r
712 \r
713         // private\r
714         function generateSQL($row) {\r
715                 // insert row\r
716                 $sql = 'INSERT INTO '.TABLE_PREFIX.'resource_links VALUES ';\r
717                 $sql .= '('.$row['new_id'].', ';\r
718                 $sql .= $this->old_ids_to_new_ids['resource_categories'][$row[0]] . ',';\r
719 \r
720                 $sql .= "'".$row[1]."',"; // URL\r
721                 $sql .= "'".$row[2]."',"; // LinkName\r
722                 $sql .= "'".$row[3]."',"; // Description\r
723                 $sql .= $row[4].',';      // Approved\r
724                 $sql .= "'".$row[5]."',"; // SubmitName\r
725                 $sql .= "'".$row[6]."',"; // SubmitEmail\r
726                 $sql .= "'".$row[7]."',"; // SubmitDate\r
727                 $sql .= $row[8]. ')';\r
728 \r
729                 return $sql;\r
730         }\r
731 }\r
732 //---------------------------------------------------------------------\r
733 class NewsTable extends AbstractTable {\r
734         var $tableName = 'news';\r
735         var $primaryIDField = 'news_id';\r
736 \r
737         function getOldID($row) {\r
738                 return FALSE;\r
739         }\r
740 \r
741         // private\r
742         function convert($row) {\r
743                 return $row;\r
744         }\r
745 \r
746         // private\r
747         function generateSQL($row) {\r
748                 // insert row\r
749                 $sql = 'INSERT INTO '.TABLE_PREFIX.'news VALUES ';\r
750                 $sql .= '('.$row['new_id'].',';\r
751                 $sql .= $this->course_id.',';\r
752                 \r
753                 /**\r
754                  * Admin user does not possess a member_id, assign ownership to instructor of restored course\r
755                  */\r
756                 if (isset($_SESSION['member_id'])) {\r
757                         $sql .= $_SESSION['member_id'] . ',';\r
758                 } else { // admin context\r
759                         $sql .= $this->resolveBkpOwner($this->course_id) . ',';\r
760                 }\r
761                 \r
762                 $sql .= "'".$row[0]."',";           // date\r
763                 $sql .= "'".$row[1]."',";           // formatting\r
764                 $sql .= "'".$row[2]."',";           // title\r
765                 $sql .= "'".$row[3]."')";           // body\r
766 \r
767                 return $sql;\r
768         }\r
769         \r
770 }\r
771 //---------------------------------------------------------------------\r
772 // -- tests (`tests`, `tests_questions`, `tests_categories`, `tests_questions_assoc`, `content_test_assco`)\r
773 class TestsTable extends AbstractTable {\r
774         var $tableName = 'tests';\r
775         var $primaryIDField = 'test_id';\r
776 \r
777         function getOldID($row) {\r
778                 return $row[0];\r
779         }\r
780 \r
781         // private\r
782         function convert($row) {\r
783                 // handle the white space issue as well\r
784                 if (version_compare($this->version, '1.4', '<')) {\r
785                         $row[8] = 0;\r
786                         $row[9] = 0;\r
787                         $row[10] = 0;\r
788                         $row[11] = 0;\r
789                 } \r
790                 \r
791                 if (version_compare($this->version, '1.4.2', '<')) {\r
792                         $row[12] = 0;\r
793                         $row[13] = 0;\r
794                 }\r
795                 if (version_compare($this->version, '1.4.3', '<')) {\r
796                         $row[9]  = 0;\r
797                         $row[14] = 0;\r
798                 }\r
799                 return $row;\r
800         }\r
801 \r
802         // private\r
803         function generateSQL($row) {\r
804                 $sql = '';\r
805                 $sql = 'INSERT INTO '.TABLE_PREFIX.'tests VALUES ';\r
806                 $sql .= '('.$row['new_id'].',';\r
807                 $sql .= $this->course_id.',';\r
808 \r
809                 $sql .= "'".$row[1]."',";       // title\r
810                 $sql .= "'".$row[2]."',";       // format\r
811                 $sql .= "'".$row[3]."',";       // start_date\r
812                 $sql .= "'".$row[4]."',";       // end_date\r
813                 $sql .= "'".$row[5]."',";       // randomize_order\r
814                 $sql .= "'".$row[6]."',";       // num_questions\r
815                 $sql .= "'".$row[7]."',";       // instructions\r
816                 $sql .= '0,';                           // content_id\r
817                 $sql .= $row[9] . ',';          // release_result\r
818                 $sql .= $row[10] . ',';         // random\r
819                 $sql .= $row[11] . ',';         // difficulty\r
820                 $sql .= $row[12] . ',';         // num_takes\r
821                 $sql .= $row[13] . ',';         // anonymous\r
822                 $sql .= "'".$row[14]."'";   // out_of\r
823                 $sql .= ')';\r
824 \r
825                 return $sql;\r
826         }\r
827 }\r
828 //---------------------------------------------------------------------\r
829 class TestsQuestionsTable extends AbstractTable {\r
830         var $tableName = 'tests_questions';\r
831         var $primaryIDField = 'question_id';\r
832 \r
833         function getOldID($row) {\r
834                 return $row[0];\r
835         }\r
836 \r
837         // private\r
838         function convert($row) {\r
839                 if (version_compare($this->version, '1.4.3', '<')) {\r
840                         // basically, rework the fields then recreate the `tests_questions_assoc.csv` file.\r
841                         // create the tests_questions_assoc file using $row[0] as the `test_id` and $row['new_id'] as the new question ID\r
842                         static $count;\r
843                         $test_id  = $row[0];\r
844                         $order    = $row[1];\r
845                         $weight   = $row[3];\r
846                         $required = $row[4];\r
847 \r
848                         $count++;\r
849                         $row[0] = $count;  // question id\r
850                         $row[1] = 0;       // category id\r
851                         $row[2] = $row[2]; // type\r
852 \r
853                         for($i = 3; $i < 27; $i++) {\r
854                                 $row[$i] = $row[$i+2];\r
855                         }\r
856 \r
857                         $assoc_data = "$test_id,$count,$weight,$order,$required\n";\r
858                         $fp = fopen($this->import_dir . 'tests_questions_assoc.csv', 'ab');\r
859                         fwrite($fp, $assoc_data);\r
860                         fclose($fp);\r
861                 }\r
862 \r
863                 return $row;\r
864         }\r
865 \r
866         // private\r
867         function generateSQL($row) {\r
868                 // insert row\r
869 \r
870                 if (!isset($this->old_ids_to_new_ids['tests_questions_categories'][$row[1]])) {\r
871                         $this->old_ids_to_new_ids['tests_questions_categories'][$row[1]] = 0;\r
872                 }\r
873 \r
874                 $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions VALUES ';\r
875                 $sql .= '('.$row['new_id'].',' . $this->old_ids_to_new_ids['tests_questions_categories'][$row[1]] . ',';\r
876                 $sql .= $this->course_id;\r
877 \r
878                 for ($i=2; $i <= 26; $i++) {\r
879                         $sql .= ",'".$row[$i]."'";\r
880                 }\r
881 \r
882                 $sql .= ')';\r
883 \r
884                 return $sql;\r
885         }\r
886 }\r
887 //---------------------------------------------------------------------\r
888 class TestsQuestionsAssocTable extends AbstractTable {\r
889         var $tableName = 'tests_questions_assoc';\r
890         var $primaryIDField = 'question_id';\r
891 \r
892         function getOldID($row) {\r
893                 return FALSE;\r
894         }\r
895 \r
896         // private\r
897         function convert($row) {\r
898                 return $row;\r
899         }\r
900 \r
901         // private\r
902         function generateSQL($row) {\r
903                 // insert row\r
904                 $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions_assoc VALUES ';\r
905                 $sql .= '(' . $this->old_ids_to_new_ids['tests'][$row[0]].',' . $this->old_ids_to_new_ids['tests_questions'][$row[1]];\r
906                 $sql .= ",'$row[2]','$row[3]','$row[4]')";\r
907 \r
908                 return $sql;\r
909         }\r
910 }\r
911 //---------------------------------------------------------------------\r
912 class TestsQuestionsCategoriesTable extends AbstractTable {\r
913         var $tableName = 'tests_questions_categories';\r
914         var $primaryIDField = 'category_id';\r
915 \r
916         function getOldID($row) {\r
917                 return $row[0];\r
918         }\r
919 \r
920         // private\r
921         function convert($row) {\r
922                 return $row;\r
923         }\r
924 \r
925         // private\r
926         function generateSQL($row) {\r
927                 // insert row\r
928                 $sql = 'INSERT INTO '.TABLE_PREFIX.'tests_questions_categories VALUES ';\r
929                 $sql .= '('.$row['new_id'].',';\r
930                 $sql .= $this->course_id;\r
931                 $sql .= ',"'.$row[1].'"';\r
932                 $sql .= ')';\r
933 \r
934                 return $sql;\r
935         }\r
936 }\r
937 //---------------------------------------------------------------------\r
938 /*\r
939 class PollsTable extends AbstractTable {\r
940         var $tableName = 'polls';\r
941         var $primaryIDField = 'poll_id';\r
942 \r
943         function getOldID($row) {\r
944                 return FALSE;\r
945         }\r
946 \r
947         // private\r
948         function convert($row) {\r
949                 return $row;\r
950         }\r
951 \r
952         // private\r
953         function generateSQL($row) {\r
954                 // insert row\r
955                 $sql = 'INSERT INTO '.TABLE_PREFIX.'polls VALUES ';\r
956                 $sql .= '('.$row['new_id'].',';\r
957                 $sql .= $this->course_id.',';\r
958                 $sql .= "'$row[0]',"; // question\r
959                 $sql .= "'$row[1]',"; // created date\r
960                 $sql .= "0,";         // total\r
961 \r
962                 for ($i=2; $i<=8; $i++) {\r
963                         $sql .= "'".$row[$i]."',0,";\r
964                 }\r
965 \r
966                 $sql  = substr($sql, 0, -1);\r
967                 $sql .= ')';\r
968 \r
969                 return $sql;\r
970         }\r
971 }\r
972 */\r
973 //---------------------------------------------------------------------\r
974 class ContentTable extends AbstractTable {\r
975         var $tableName = 'content';\r
976 \r
977         var $primaryIDField = 'content_id';\r
978 \r
979         var $ordering;\r
980 \r
981         /**\r
982         * Constructor.\r
983         * \r
984         * @param string $version The backup version.\r
985         * @param resource $db The database handler.\r
986         * @param int $course_id The ID of this course.\r
987         * @param string $import_dir The directory where the backup was unzipped to.\r
988         * @param array $old_id_to_new_id Reference to either the parent ID's or to store current ID's.\r
989         * \r
990         */\r
991         function ContentTable($version, $db, $course_id, $import_dir, &$old_id_to_new_id) {\r
992                 // special case for `content` -- we need the max ordering\r
993 \r
994                 $sql        = 'SELECT MAX(ordering) AS ordering FROM '.TABLE_PREFIX.'content WHERE content_parent_id=0 AND course_id='.$course_id;\r
995                 $result     = mysql_query($sql, $db);\r
996                 $ordering   = mysql_fetch_assoc($result);\r
997                 $this->ordering = $ordering['ordering'] +1;\r
998 \r
999                 parent::AbstractTable($version, $db, $course_id, $import_dir, $old_id_to_new_id);\r
1000         }\r
1001 \r
1002         function getOldID($row) {\r
1003                 return $row[0];\r
1004         }\r
1005 \r
1006         // private\r
1007         function convert($row) {\r
1008                 return $row;\r
1009         }\r
1010 \r
1011         // private\r
1012         function generateSQL($row) {\r
1013                 $sql = 'INSERT INTO '.TABLE_PREFIX.'content VALUES ';\r
1014                 $sql .= '('.$row['new_id'].','; // content_id\r
1015                 $sql .= $this->course_id .',';  // course_id\r
1016                 if ($row[1] == 0) { // content_parent_id\r
1017                         $sql .= 0;\r
1018                 } else {\r
1019                         $sql .= $this->getNewID($row[1]);\r
1020                 }\r
1021                 $sql .= ',';\r
1022 \r
1023                 if ($row[1] == 0) {\r
1024                         // find the new ordering:\r
1025                         $sql .= $this->ordering . ',';\r
1026                         $this->ordering ++;\r
1027                 } else {\r
1028                         $sql .= $row[2].',';\r
1029                 }\r
1030 \r
1031                 $sql .= "'".$row[3]."',";    // last_modified\r
1032                 $sql .= $row[4] . ',';       // revision\r
1033                 $sql .= $row[5] . ',';       // formatting\r
1034                 $sql .= "'".$row[6]."',";    // release_date\r
1035                 $sql .= "'".$row[7]."',";    // keywords\r
1036                 $sql .= "'".$row[8]."',";    // content_path\r
1037                 $sql .= "'".$row[9]."',";    // title\r
1038                 $sql .= "'".$row[10]."',0)"; // text\r
1039 \r
1040                 return $sql;\r
1041         }\r
1042 }\r
1043 \r
1044 //---------------------------------------------------------------------\r
1045 class ContentTestsAssocTable extends AbstractTable {\r
1046         var $tableName = 'content_tests_assoc';\r
1047         var $primaryIDField = 'test_id';\r
1048 \r
1049         function getOldID($row) {\r
1050                 return FALSE;\r
1051         }\r
1052 \r
1053         // private\r
1054         function convert($row) {\r
1055                 return $row;\r
1056         }\r
1057 \r
1058         // private\r
1059         function generateSQL($row) {\r
1060                 // insert row\r
1061                 $sql = 'INSERT INTO '.TABLE_PREFIX.'content_tests_assoc VALUES ';\r
1062                 $sql .= '(' . $this->old_ids_to_new_ids['content'][$row[0]].',' . $this->old_ids_to_new_ids['tests'][$row[1]].')';\r
1063 \r
1064                 return $sql;\r
1065         }\r
1066 }\r
1067 //---------------------------------------------------------------------\r
1068 class RelatedContentTable extends AbstractTable {\r
1069         var $tableName = 'related_content';\r
1070 \r
1071         var $primaryIDField = 'content_id';\r
1072 \r
1073         function getOldID($row) {\r
1074                 return FALSE;\r
1075         }\r
1076 \r
1077         // private\r
1078         function convert($row) {\r
1079                 return $row;\r
1080         }\r
1081 \r
1082         // private\r
1083         function generateSQL($row) {\r
1084                 $sql = 'INSERT INTO '.TABLE_PREFIX.'related_content VALUES ';\r
1085                 $sql .= '('.$this->old_ids_to_new_ids['content'][$row['0']].','. $this->old_ids_to_new_ids['content'][$row[1]].')';\r
1086 \r
1087                 return $sql;\r
1088         }\r
1089 }\r
1090 \r
1091 //---------------------------------------------------------------------\r
1092 class CourseStatsTable extends AbstractTable {\r
1093         var $tableName = 'course_stats';\r
1094         var $primaryIDField = 'login_date'; // never actually used\r
1095 \r
1096         function getOldID($row) {\r
1097                 return FALSE;\r
1098         }\r
1099 \r
1100         function getParentID($row) {\r
1101                 return FALSE;\r
1102         }\r
1103 \r
1104         // private\r
1105         function convert($row) {\r
1106                 return $row;\r
1107         }\r
1108 \r
1109         // private\r
1110         function generateSQL($row) {\r
1111                 // insert row\r
1112                 $sql = 'INSERT INTO '.TABLE_PREFIX.'course_stats VALUES ';\r
1113                 $sql .= '('.$this->course_id.",";\r
1114                 $sql .= "'".$row[0]."',"; // login_date\r
1115                 $sql .= "'".$row[1]."',"; // guests\r
1116                 $sql .= "'".$row[2]."'";  // members\r
1117                 $sql .= ')';\r
1118 \r
1119                 return $sql;\r
1120         }\r
1121 }\r
1122 \r
1123 //---------------------------------------------------------------------\r
1124 class GroupsTable extends AbstractTable {\r
1125         var $tableName = 'groups';\r
1126         var $primaryIDField = 'group_id';\r
1127 \r
1128         function getOldID($row) {\r
1129                 return FALSE;\r
1130         }\r
1131 \r
1132         function getParentID($row) {\r
1133                 return FALSE;\r
1134         }\r
1135 \r
1136         // private\r
1137         function convert($row) {\r
1138                 return $row;\r
1139         }\r
1140 \r
1141         // private\r
1142         function generateSQL($row) {\r
1143                 // insert row\r
1144                 $sql = 'INSERT INTO '.TABLE_PREFIX.'groups VALUES ';\r
1145                 $sql .= '('.$row['new_id'] . ',' . $this->course_id.",";\r
1146                 $sql .= "'".$row[0]."'"; // title\r
1147                 $sql .= ')';\r
1148 \r
1149                 return $sql;\r
1150         }\r
1151 }\r
1152 \r
1153 ?>