]> git.mjollnir.org Git - moodle.git/commitdiff
merging MOODLE_19_QUESTIONS with HEAD
authorjamiesensei <jamiesensei>
Thu, 9 Aug 2007 21:50:59 +0000 (21:50 +0000)
committerjamiesensei <jamiesensei>
Thu, 9 Aug 2007 21:50:59 +0000 (21:50 +0000)
19 files changed:
admin/environment.xml
admin/settings/courses.php
backup/backup.php
backup/backup_check.html
backup/backup_form.html
backup/backup_scheduled.php
backup/backuplib.php
backup/lib.php
backup/restore_check.html
backup/restore_form.html
backup/restorelib.php
lang/en_utf8/admin.php
lang/en_utf8/moodle.php
lang/en_utf8/qtype_multichoice.php
lang/en_utf8/qtype_truefalse.php
lang/en_utf8/question.php
lang/en_utf8/quiz.php
lib/moodlelib.php
lib/questionlib.php

index 61486595d2daae45d92abb821cc8452819ea5d14..f8c1b9c0ee81a1fdf411c5ecf8dc71f37bddd738 100644 (file)
           <ON_OK message="qtyperqpwillberemoved" />
         </FEEDBACK>
       </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="question/upgrade.php" function="question_random_check" level="optional">
+        <FEEDBACK>
+          <ON_OK message="questioncwqpfsok" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
     </CUSTOM_CHECKS>
   </MOODLE>
   <MOODLE version="2.0">
index 61614b3c654c7006ef72d003c27531e15e23051e..47e711dc525edd87ad8210b1098e05a6d32c7539 100644 (file)
@@ -26,6 +26,7 @@ $temp->add(new admin_setting_backupselect('backup_sche_users', get_string('users
 $temp->add(new admin_setting_backupcheckbox('backup_sche_logs', get_string('logs'), get_string('backuplogshelp'), 0));
 $temp->add(new admin_setting_backupcheckbox('backup_sche_userfiles', get_string('userfiles'), get_string('backupuserfileshelp'), 0));
 $temp->add(new admin_setting_backupcheckbox('backup_sche_coursefiles', get_string('coursefiles'), get_string('backupcoursefileshelp'), 0));
+$temp->add(new admin_setting_backupcheckbox('backup_sche_sitefiles', get_string('sitefiles'), get_string('backupsitefileshelp'), 0));
 $temp->add(new admin_setting_backupcheckbox('backup_sche_messages', get_string('messages', 'message'), get_string('backupmessageshelp','message'), 0));
 $temp->add(new admin_setting_backupselect('backup_sche_keep', get_string('keep'), get_string('backupkeephelp'), 1, array(0 => get_string('all'),
                                                                                                                          1 => '1',
index d6a8265df3d7a8a886d96928689d724f0e3e55f5..fe90468d367d55bccc0005d6a6980654e0197e19 100644 (file)
@@ -39,7 +39,7 @@
 
     //Check necessary functions exists. Thanks to gregb@crowncollege.edu
     backup_required_functions();
-    
+
     //Check backup_version
     if ($id) {
         $linkto = "backup.php?id=".$id.((!empty($to)) ? '&to='.$to : '');
                       <a href=\"backup.php\">$strcoursebackup</a> -> $course->fullname ($course->shortname)");
     } else {
         print_header("$course->shortname: $strcoursebackup", $course->fullname,
-                     "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> -> 
+                     "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->
                      $strcoursebackup");
     }
 
-    //Print form     
+    //Print form
     print_heading(format_string("$strcoursebackup: $course->fullname ($course->shortname)"));
     print_simple_box_start("center");
 
 
     //Print footer
     print_footer();
-
 ?>
index c77496f66c61a1dbb870d1293f215075e425fe1f..817fbf5b48e4d1e9ea344e5a86683913d6b3faba 100644 (file)
@@ -1,7 +1,8 @@
 <?php //$Id$
+    require_once("$CFG->dirroot/question/backuplib.php");
     //This page prints the backup todo list to see everything
 
-    //Check login   
+    //Check login
     require_login();
 
     if (!empty($course->id)) {
         }
     }
 
-    
+
 
     $backupprefs = new StdClass;
     $count = 0;
     backup_fetch_prefs_from_request($backupprefs,$count,$course);
 
+
+
     //Check site
     if (!$site = get_site()) {
         error("Site not found!");
     if ($count == 0) {
         notice("No backupable modules are installed!");
     }
+
+    if (!execute_sql("DELETE FROM {$CFG->prefix}backup_ids WHERE backup_code = '{$backupprefs->backup_unique_code}'",false)){
+        error('Couldn\'t delete previous backup ids.');
+    }
+
 ?>
 
 <form id="form" method="post" action="backup.php">
         //Add as text field
         echo "<input type=\"text\" name=\"backup_name\" size=\"40\" value=\"".$backupprefs->backup_name."\" />";
         echo "</td></tr>";
-    
+
         //Line
         echo "<tr><td colspan=\"2\"><hr /></td></tr>";
-        
+
         //Now print the To Do list
-        echo "<tr>";    
+        echo "<tr>";
         echo "<td colspan=\"2\" align=\"center\"><b>";
 
     }
@@ -90,7 +98,7 @@
         echo "</b></td></tr>";
     }
 
-    //This is tha align to every ingo table                
+    //This is the alignment of every row in the table
     $table->align = array ("left","right");
 
     if ($allmods = get_records("modules") ) {
                     //Print the full tr
                     echo "<tr>";
                     echo "<td colspan=\"2\">";
-                    //Add hidden fields
-                    $var = "backup_".$modname;
-                    $var = "backup_user_info_".$modname;
                     //Print the mod name
                     echo "<b>".get_string("include")." ".get_string("modulenameplural",$modname)." ";
                     //Now look for user-data status
-                    $backup_user_options[0] = get_string("withoutuserdata"); 
+                    $backup_user_options[0] = get_string("withoutuserdata");
                     $backup_user_options[1] = get_string("withuserdata");
                     $var = "backup_user_info_".$modname;
                     //Print the user info
                                 $obj->id = $instance->id;
                                 $instancestopass[$instance->id]= $obj;
                                 $countinstances++;
-                                
+
                             }
                         }
-                    } 
+                    }
                     $table->data = $modcheckbackup($id,$backupprefs->$var,$backupprefs->backup_unique_code,$instancestopass);
-                    print_table($table); 
+                    print_table($table);
                     echo "</td></tr>";
                 }
             }
         }
-        
+
 
         if (empty($to)) {
             //Line
             $user_options[2] = get_string("includenoneusers");
             echo $user_options[$backupprefs->backup_users].'</b>';
             //Print info
-            $table->data = user_check_backup($id,$backupprefs->backup_unique_code,$backupprefs->backup_users,$backupprefs->backup_messages);  
-            print_table($table); 
+            $table->data = user_check_backup($id,$backupprefs->backup_unique_code,$backupprefs->backup_users,$backupprefs->backup_messages);
+            print_table($table);
             echo "</td></tr>";
-            
+
         }
-        
+
         //Now print the Logs tr conditionally
         if ($backupprefs->backup_logs && empty($to)) {
             echo "<tr>";
             print_table($table);
             echo "</td></tr>";
         }
+       //Now print the site Files tr conditionally
+       if ($backupprefs->backup_site_files) {
+            echo "<tr>";
+            echo "<td colspan=\"2\"><b>";
+            echo get_string("includesitefiles").'</b>';
+            //Print info
+            $table->data = site_files_check_backup($id,$backupprefs->backup_unique_code);
+            print_table($table);
+            echo "</td></tr>";
+        }
     }
 
     // now keep it for next time.
index d670731fff625681d456fed8e784d8e461366ce3..61dfad56000dd3fb49740cc13ff46f3365583cb3 100644 (file)
@@ -1,7 +1,7 @@
 <?php //$Id$
     //This page prints the backup form to select everything
 
-    //Check login   
+    //Check login
     require_login();
 
     if (!empty($course->id)) {
@@ -26,7 +26,7 @@
     }
 
     //Checks for the required files/functions to backup every mod
-    //And check if there is data about it 
+    //And check if there is data about it
     $count = 0;
     if ($allmods = get_records("modules") ) {
         foreach ($allmods as $mod) {
@@ -64,6 +64,7 @@
     $backup_logs = optional_param('backup_logs',0);
     $backup_user_files = optional_param('backup_user_files',1);
     $backup_course_files = optional_param('backup_course_files',1);
+    $backup_site_files = optional_param('backup_site_files',1);
     $backup_gradebook_history =  optional_param('backup_gradebook_history', 1, PARAM_INT);
     $backup_messages = optional_param('backup_messages',1);
 
@@ -145,7 +146,7 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
                 echo "<tr class=\"r".$currentrow."\">";
                 echo "  <td align=\"right\">&nbsp;";
                 echo "</td><td>\n";
-                $backup_options[0] = get_string("no"); 
+                $backup_options[0] = get_string("no");
                 $backup_options[1] = get_string("yes");
                 $var = "backup_".$modname;
                 //choose_from_menu($backup_options, $var, $$var, "");
@@ -155,14 +156,14 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
                 echo "</td><td>";
                 $var = "backup_user_info_".$modname;
                 if (empty($to)) {
-                    $backup_user_options[0] = get_string("withoutuserdata"); 
+                    $backup_user_options[0] = get_string("withoutuserdata");
                     $backup_user_options[1] = get_string("withuserdata");
                     //choose_from_menu($backup_user_options, $var, $$var, "");
                     print_checkbox($var, $$var, $$var, get_string("userdata"),'','selectItemInCheckboxByName(\'form1\',\'backup_user_info_'.$modname.'\',this.checked)');
                 } else {
                     echo '<input type="hidden" name="'.$var.'" value="0" />';
                 }
-                echo "</td></tr>\n"; 
+                echo "</td></tr>\n";
                 // if we have the backup_one_mod function, loop here.
                 $var = 'exists_one_'.$modname;
                 if (!empty($$var)) {
@@ -185,20 +186,20 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
                     }
                     echo '</table></td></tr>';
                 }
-              
+
             }
         }
         //Line
         echo "<tr><td colspan=\"4\"><hr /></td></tr>\n";
-        
+
         if (empty($to)) {
             //Now print the Metacourse tr
             echo "<tr>";
             echo "<td align=\"right\" colspan=\"2\"><b>";
             echo get_string ("metacourse").":";
             echo "</b></td><td colspan=\"2\">";
-            $meta_options[0] = get_string("no"); 
-            $meta_options[1] = get_string("yes"); 
+            $meta_options[0] = get_string("no");
+            $meta_options[1] = get_string("yes");
             choose_from_menu($meta_options, "backup_metacourse", $backup_metacourse, "");
             echo "</td></tr>";
         }
@@ -221,30 +222,30 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         else {
             echo '<input type="hidden" name="backup_users" value="0" />';
         }
-        
+
         if (empty($to)) {
             //Now print the Logs tr
             echo "<tr>";
             echo "<td align=\"right\" colspan=\"2\"><b>";
-            echo get_string("logs").":";                                               
+            echo get_string("logs").":";
             echo "</b></td><td colspan=\"2\">";
             $log_options[0] = get_string("no");
-            $log_options[1] = get_string("yes"); 
-            choose_from_menu($log_options, "backup_logs", $backup_logs, ""); 
+            $log_options[1] = get_string("yes");
+            choose_from_menu($log_options, "backup_logs", $backup_logs, "");
             echo "</td></tr>";
         }
         else {
             echo '<input type="hidden" name="backup_logs" value="0" />';
         }
+
         if (empty($to)) {
             //Now print the User Files tr
             echo "<tr>";
             echo "<td align=\"right\" colspan=\"2\"><b>";
             echo get_string ("userfiles").":";
             echo "</b></td><td colspan=\"2\">";
-            $user_file_options[0] = get_string("no"); 
-            $user_file_options[1] = get_string("yes"); 
+            $user_file_options[0] = get_string("no");
+            $user_file_options[1] = get_string("yes");
             choose_from_menu($user_file_options, "backup_user_files", $backup_user_files, "");
             echo "</td></tr>";
         }
@@ -261,6 +262,19 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         choose_from_menu($course_file_options, "backup_course_files", $backup_course_files, "");
         echo "</td></tr>";
 
+
+        if ($course->id != SITEID){
+            //Now print the site Files tr
+            echo "<tr>";
+            echo "<td align=\"right\" colspan=\"2\"><b>";
+            echo get_string ("sitefilesused").":";
+            echo "</b></td><td colspan=\"2\">";
+            $course_file_options[0] = get_string("no");
+            $course_file_options[1] = get_string("yes");
+            choose_from_menu($course_file_options, "backup_site_files", $backup_site_files, "");
+            echo "</td></tr>";
+        }
+
         // do you want grade histories to be backed up?
         echo "<tr>";
         echo "<td align=\"right\" colspan=\"2\"><b>";
@@ -277,8 +291,8 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
             echo "<td align=\"right\" colspan=\"2\"><b>";
             echo get_string ('messages','message').":";
             echo "</b></td><td colspan=\"2\">";
-            $mess_options[0] = get_string("no"); 
-            $mess_options[1] = get_string("yes"); 
+            $mess_options[0] = get_string("no");
+            $mess_options[1] = get_string("yes");
             choose_from_menu($mess_options, "backup_messages", $backup_messages, "");
             echo "</td></tr>";
         }
@@ -293,8 +307,8 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
     //Calculate the backup unique code to allow simultaneus backups (to define
     //the temp-directory name and records in backup temp tables
     $backup_name = backup_get_zipfile_name($course, $backup_unique_code);
-    
-    
+
+
 ?>
 </table>
 
index 5bb9c5a36a20ed55d2b74335455abdd304121bf6..29366b78ae47ad9796466bf458fa2f58fdc0b43b 100644 (file)
@@ -6,7 +6,7 @@
 function schedule_backup_cron() {
 
     global $CFG;
-    
+
     $status = true;
 
     $emailpending = false;
@@ -29,7 +29,7 @@ function schedule_backup_cron() {
         return true;
     } else if (isset($backup_config->backup_sche_running) && $backup_config->backup_sche_running) {
         mtrace("RUNNING");
-        //Now check if it's a really running task or something very old looking 
+        //Now check if it's a really running task or something very old looking
         //for info in backup_logs to unlock status as necessary
         $timetosee = 1800;   //Half an hour looking for activity
         $timeafter = time() - $timetosee;
@@ -106,7 +106,7 @@ function schedule_backup_cron() {
                     mtrace("            SKIPPING - hidden+unmodified");
                     set_field("backup_courses","laststatus","3","courseid",$backup_course->courseid);
                     $skipped = true;
-                } 
+                }
                 //Now we backup every non skipped course with nextstarttime < now
                 if (!$skipped  && $backup_course->nextstarttime > 0 && $backup_course->nextstarttime < $now) {
                     //We have to send a email because we have included at least one backup
@@ -192,13 +192,13 @@ function schedule_backup_cron() {
         $prefix = $site->shortname.": ";
         if ($count_error != 0 || $count_unfinished != 0) {
             $prefix .= "[".strtoupper(get_string('error'))."] ";
-        } 
+        }
         $subject = $prefix.get_string("scheduledbackupstatus");
 
         //Send the message
         email_to_user($admin,$admin,$subject,$message);
     }
-    
+
 
     //Everything is finished stop backup_sche_running
     backup_set_config("backup_sche_running","0");
@@ -251,7 +251,7 @@ function schedule_backup_log($starttime,$courseid,$message) {
         $log->time = time();
         $log->laststarttime = $starttime;
         $log->info = addslashes($message);
-    
+
         insert_record ("backup_log",$log);
     }
 
@@ -282,7 +282,7 @@ function schedule_backup_next_execution ($backup_course,$backup_config,$now,$tim
                 ($backup_config->backup_sche_hour*3600) +      //Hours distance
                 ($backup_config->backup_sche_minute*60);       //Minutes distance
         $result = $midnight + $dist;
-    } 
+    }
 
     //If that time is past, call the function recursively to obtain the next valid day
     if ($result > 0 && $result < time()) {
@@ -296,10 +296,10 @@ function schedule_backup_next_execution ($backup_course,$backup_config,$now,$tim
 
 //This function implements all the needed code to prepare a course
 //to be in backup (insert temp info into backup temp tables).
-function schedule_backup_course_configure($course,$starttime = 0) {  
+function schedule_backup_course_configure($course,$starttime = 0) {
 
     global $CFG;
-    
+
     $status = true;
 
     schedule_backup_log($starttime,$course->id,"    checking parameters");
@@ -334,6 +334,9 @@ function schedule_backup_course_configure($course,$starttime = 0) {
         if (!isset($backup_config->backup_sche_coursefiles)) {
             $backup_config->backup_sche_coursefiles = 1;
         }
+        if (!isset($backup_config->backup_sche_sitefiles)) {
+            $backup_config->backup_sche_sitefiles = 1;
+        }
         if (!isset($backup_config->backup_sche_messages)) {
             $backup_config->backup_sche_messages = 0;
         }
@@ -373,8 +376,8 @@ function schedule_backup_course_configure($course,$starttime = 0) {
                        $var = "exists_".$modname;
                        $$var = true;
                        $count++;
-                       
-                       // PENNY NOTES: I have moved from here to the closing brace inside 
+
+                       // PENNY NOTES: I have moved from here to the closing brace inside
                        // by two sets of ifs()
                        // to avoid the backup failing on a non existant backup.
                        // If the file/function/whatever doesn't exist, we don't want to set this
@@ -387,7 +390,7 @@ function schedule_backup_course_configure($course,$starttime = 0) {
                        }
                        //Now stores all the mods preferences into an array into preferences
                        $preferences->mods[$modname]->backup = $$var;
-                       
+
                        //Check include user info
                        $var = "backup_user_info_".$modname;
                        if (!isset($$var)) {
@@ -416,7 +419,7 @@ function schedule_backup_course_configure($course,$starttime = 0) {
             }
         }
     }
-    
+
     //Convert other parameters
     if ($status) {
         $preferences->backup_metacourse = $backup_config->backup_sche_metacourse;
@@ -424,12 +427,13 @@ function schedule_backup_course_configure($course,$starttime = 0) {
         $preferences->backup_logs = $backup_config->backup_sche_logs;
         $preferences->backup_user_files = $backup_config->backup_sche_userfiles;
         $preferences->backup_course_files = $backup_config->backup_sche_coursefiles;
+        $preferences->backup_site_files = $backup_config->backup_sche_sitefiles;
         $preferences->backup_messages = $backup_config->backup_sche_messages;
         $preferences->backup_course = $course->id;
         $preferences->backup_destination = $backup_config->backup_sche_destination;
         $preferences->backup_keep = $backup_config->backup_sche_keep;
     }
-    
+
     //Calculate the backup string
     if ($status) {
         schedule_backup_log($starttime,$course->id,"    calculating backup name");
@@ -474,7 +478,7 @@ function schedule_backup_course_configure($course,$starttime = 0) {
         $keep_name .= moodle_strtolower($backup_shortname)."-";
         //And finally, clean everything
         $keep_name = clean_filename($keep_name);
+
         $preferences->backup_name = $backup_name;
         $preferences->keep_name = $keep_name;
     }
@@ -520,7 +524,7 @@ function schedule_backup_course_configure($course,$starttime = 0) {
         } else {
             $include_message_users = false;
         }
-        user_check_backup($course->id,$backup_unique_code,$preferences->backup_users,$include_message_users);  
+        user_check_backup($course->id,$backup_unique_code,$preferences->backup_users,$include_message_users);
     }
 
     //Now calculate the logs
@@ -538,7 +542,7 @@ function schedule_backup_course_configure($course,$starttime = 0) {
             user_files_check_backup($course->id,$preferences->backup_unique_code);
         }
     }
+
     //Now calculate the coursefiles
     if ($status) {
        if ($preferences->backup_course_files) {
@@ -547,6 +551,14 @@ function schedule_backup_course_configure($course,$starttime = 0) {
         }
     }
 
+    //Now calculate the sitefiles
+    if ($status) {
+       if ($preferences->backup_site_files) {
+            schedule_backup_log($starttime,$course->id,"    calculating site files");
+            site_files_check_backup($course->id,$preferences->backup_unique_code);
+        }
+    }
+
     //If everything is ok, return calculated preferences
     if ($status) {
         $status = $preferences;
@@ -643,10 +655,10 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
             schedule_backup_log($starttime,$preferences->backup_course,"      categories & questions");
             $status = backup_question_categories($backup_file,$preferences);
         }
-        
+
         //Print logs if selected
         if ($status) {
-            if ($preferences->backup_logs) {  
+            if ($preferences->backup_logs) {
                 schedule_backup_log($starttime,$preferences->backup_course,"      logs");
                 $status = backup_log_info($backup_file,$preferences);
             }
@@ -657,7 +669,7 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
             schedule_backup_log($starttime,$preferences->backup_course,"      scales");
             $status = backup_scales_info($backup_file,$preferences);
         }
+
         //Print groups info
         if ($status) {
             schedule_backup_log($starttime,$preferences->backup_course,"      groups");
@@ -682,9 +694,9 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
             $mods_to_backup = false;
             //Check if we have any mod to backup
             foreach ($preferences->mods as $module) {
-                if ($module->backup) { 
+                if ($module->backup) {
                     $mods_to_backup = true;
-                }    
+                }
             }
             //If we have to backup some module
             if ($mods_to_backup) {
@@ -703,7 +715,7 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
             }
         }
 
-        //Prints course end 
+        //Prints course end
         if ($status) {
             $status = backup_course_end($backup_file,$preferences);
         }
@@ -713,7 +725,7 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
             backup_close_xml($backup_file);
         }
     }
-    
+
     //Now, if selected, copy user files
     if ($status) {
         if ($preferences->backup_user_files) {
@@ -730,6 +742,14 @@ function schedule_backup_course_execute($preferences,$starttime = 0) {
         }
     }
 
+    //Now, if selected, copy site files
+    if ($status) {
+        if ($preferences->backup_site_files) {
+            schedule_backup_log($starttime,$preferences->backup_course,"    copying site files");
+            $status = backup_copy_site_files ($preferences);
+        }
+    }
+
     //Now, zip all the backup directory contents
     if ($status) {
         schedule_backup_log($starttime,$preferences->backup_course,"    zipping files");
index 573678359b6cf5c2e003a9afa35da01969c55901..d70c6e51d0993ff53ecf626cb5716dd82cb82692 100644 (file)
         return $info;
     }
 
-    //Calculate the number of course files to backup
-    //under $CFG->dataroot/$course, except $CFG->moddata, and backupdata
-    //and put them (their path) in backup_ids
-    //Return an array of info (name,value)
-    function course_files_check_backup($course,$backup_unique_code) {
+    /**
+     * Calculate the number of course files to backup
+     * under $CFG->dataroot/$course, except $CFG->moddata, and backupdata
+     * and put them (their path) in backup_ids
+     * Return an array of info (name,value)
+     */
+    function course_files_check_backup($course, $backup_unique_code) {
 
         global $CFG;
 
                                 WHERE backup_code = '$backup_unique_code' AND
                                       file_type = 'course'");
         //Gets the user data
+        $info = array();
+        $info[0] = array();
         $info[0][0] = get_string("files");
         if ($ids) {
             $info[0][1] = count($ids);
         return $info;
     }
 
+    /**
+     * Calculate the number of site files to backup
+     * under $CFG->dataroot/SITEID
+     * Their path is already in backup_ids, put there by modules check_backup functions.
+     * Modules only put in paths of files that are used.
+     *
+     * Return an array of info (name,value)
+     */
+    function site_files_check_backup($course, $backup_unique_code) {
+        global $CFG;
+
+        //execute the select, records have been inserted by modules during their ****_check_backup_mods function.
+        $ids = get_records_sql("SELECT DISTINCT b.path
+                                FROM {$CFG->prefix}backup_files b
+                                WHERE backup_code = '$backup_unique_code' AND
+                                      file_type = 'site'");
+        //Gets the user data
+        $info = array();
+        $info[0] = array();
+        $info[0][0] = get_string('files');
+        if ($ids) {
+            $info[0][1] = count($ids);
+        } else {
+            $info[0][1] = 0;
+        }
+
+        return $info;
+    }
+
     //Function to check and create the needed moddata dir to
     //save all the mod backup files. We always name it moddata
     //to be able to restore it, but in restore we check for
 
         global $CFG;
 
-            $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/moddata",true);
+        $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/moddata",true);
 
         return $status;
     }
 
         global $CFG;
 
-            $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/user_files",true);
+        $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/user_files",true);
 
         return $status;
     }
 
         global $CFG;
 
-            $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/group_files",true);
+        $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/group_files",true);
 
         return $status;
     }
 
         global $CFG;
 
-            $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/course_files",true);
+        $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/course_files",true);
+
+        return $status;
+    }
+
+    //Function to check and create the "site_files" dir to
+    //save all the course files we need from "CFG->datadir/SITEID" dir
+    function check_and_create_site_files_dir($backup_unique_code) {
+
+        global $CFG;
+
+        $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/site_files",true);
 
         return $status;
     }
         } else {
             fwrite ($bf,full_tag("COURSEFILES",3,false,"false"));
         }
+        //The course files
+        if ($preferences->backup_site_files == 1) {
+            fwrite ($bf,full_tag("SITEFILES",3,false,"true"));
+        } else {
+            fwrite ($bf,full_tag("SITEFILES",3,false,"false"));
+        }
         //The messages in backup
         if ($preferences->backup_messages == 1 && $preferences->backup_course == SITEID) {
             fwrite ($bf,full_tag("MESSAGES",3,false,"true"));
         if ($backupall) {
             $status = backup_gradebook_category_info($bf,$preferences);
         }
-        
+
         $status = backup_gradebook_item_info($bf,$preferences, $backupall);
         $status = backup_gradebook_outcomes_info($bf, $preferences);
         $status = backup_gradebook_outcomes_courses_info($bf, $preferences);
-        
+
         // backup gradebook histories
         if ($preferences->backup_gradebook_history) {
             $status = backup_gradebook_categories_history_info($bf, $preferences);
         global $CFG;
         $status = true;
 
-        // getting grade categories, but make sure parents come before children
+       // getting grade categories, but make sure parents come before children
         // because when we do restore, we need to recover the parents first
         // we do this by getting the lowest depth first
         $grade_categories = get_records_sql("SELECT * FROM {$CFG->prefix}grade_categories
 
         global $CFG;
         $status = true;
-        // only back up courses already in the grade_outcomes_courses table    
+        // only back up courses already in the grade_outcomes_courses table
         $grade_outcomes = get_records_sql('SELECT go.*
                                        FROM '.$CFG->prefix.'grade_outcomes_courses goc,
                                             '.$CFG->prefix.'grade_outcomes go
                 //Output individual fields
 
                 fwrite ($bf,full_tag("ID",5,false,$grade_outcome->id));
-                fwrite ($bf,full_tag("COURSEID",5,false,$grade_outcome->courseid));             
+                fwrite ($bf,full_tag("COURSEID",5,false,$grade_outcome->courseid));
                 fwrite ($bf,full_tag("SHORTNAME",5,false,$grade_outcome->shortname));
                 fwrite ($bf,full_tag("FULLNAME",5,false,$grade_outcome->fullname));
                 fwrite ($bf,full_tag("SCALEID",5,false,$grade_outcome->scaleid));
         }
         return $status;
     }
-    
+
     // outcomes assigned to this course
     function backup_gradebook_outcomes_courses_info($bf,$preferences) {
 
         global $CFG;
 
         $status = true;
-        // get all global outcomes (used in this course) 
+        // get all global outcomes (used in this course)
         // and course specific outcomes
-        // we don't need to backup all the outcomes in this case        
+        // we don't need to backup all the outcomes in this case
         if ($outcomes_courses = get_records('grade_outcomes_courses', 'courseid', $preferences->backup_course)) {
             //Begin grade_outcomes tag
             fwrite ($bf,start_tag("GRADE_OUTCOMES_COURSES",3,true));
                         fwrite ($bf,end_tag("GRADE_TEXT",6,true));
                     }
                 }
-            } 
+            }
             $status = fwrite ($bf,end_tag("GRADE_GRADES_TEXT",5,true));
         }
         return $status;
     }
 
     function backup_gradebook_categories_history_info($bf, $preferences) {
-        
+
         global $CFG;
         $status = true;
 
                 fwrite ($bf,full_tag("PARENT",7,false,$ch->parent));
                 fwrite ($bf,full_tag("DEPTH",7,false,$ch->depth));
                 fwrite ($bf,full_tag("PATH",7,false,$ch->path));
-                fwrite ($bf,full_tag("FULLNAME",7,false,$ch->fullname));                
+                fwrite ($bf,full_tag("FULLNAME",7,false,$ch->fullname));
                 fwrite ($bf,full_tag("AGGRETGATION",7,false,$ch->aggregation));
                 fwrite ($bf,full_tag("KEEPHIGH",7,false,$ch->keephigh));
-                fwrite ($bf,full_tag("DROPLOW",7,false,$ch->droplow));              
+                fwrite ($bf,full_tag("DROPLOW",7,false,$ch->droplow));
                 fwrite ($bf,end_tag("GRADE_CATEGORIES_HISTORY",6,true));
             }
             $status = fwrite ($bf,end_tag("GRADE_CATEGORIES_HISTORIES",5,true));
         }
-        return $status; 
+        return $status;
     }
 
     function backup_gradebook_grades_history_info($bf, $preferences) {
-        
+
         global $CFG;
         $status = true;
 
                 fwrite ($bf,full_tag("TIMEMODIFIED",7,false,$ch->timemodified));
                 fwrite ($bf,full_tag("LOGGEDUSER",7,false,$ch->loggeduser));
                 fwrite ($bf,full_tag("ITEMID",7,false,$ch->itemid));
-                fwrite ($bf,full_tag("USERID",7,false,$ch->userid));               
+                fwrite ($bf,full_tag("USERID",7,false,$ch->userid));
                 fwrite ($bf,full_tag("RAWGRADE",7,false,$ch->rawgrade));
-                fwrite ($bf,full_tag("RAWGRADEMAX",7,false,$ch->rawgrademax));                
+                fwrite ($bf,full_tag("RAWGRADEMAX",7,false,$ch->rawgrademax));
                 fwrite ($bf,full_tag("RAWGRADEMIN",7,false,$ch->rawgrademin));
                 fwrite ($bf,full_tag("USERMODIFIED",7,false,$ch->usermodified));
-                fwrite ($bf,full_tag("FINALGRADE",7,false,$ch->finalgrade));                            
+                fwrite ($bf,full_tag("FINALGRADE",7,false,$ch->finalgrade));
                 fwrite ($bf,full_tag("HIDDEN",7,false,$ch->hidden));
-                fwrite ($bf,full_tag("LOCKED",7,false,$ch->locked));                
+                fwrite ($bf,full_tag("LOCKED",7,false,$ch->locked));
                 fwrite ($bf,full_tag("LOCKTIME",7,false,$ch->locktime));
                 fwrite ($bf,full_tag("EXPORTED",7,false,$ch->exported));
-                fwrite ($bf,full_tag("OVERRIDDEN",7,false,$ch->overridden));                
-                fwrite ($bf,full_tag("EXCLUDED",7,false,$ch->excluded));                                                
+                fwrite ($bf,full_tag("OVERRIDDEN",7,false,$ch->overridden));
+                fwrite ($bf,full_tag("EXCLUDED",7,false,$ch->excluded));
                 fwrite ($bf,end_tag("GRADE_GRADES_HISTORY",6,true));
             }
             $status = fwrite ($bf,end_tag("GRADE_GRADES_HISTORIES",5,true));
         }
-        return $status; 
+        return $status;
     }
-   
+
     function backup_gradebook_grades_text_history_info($bf, $preferences) {
-        
+
         global $CFG;
         $status = true;
 
                 fwrite ($bf,full_tag("INFORMATIONFORMAT",7,false,$ch->informationformat));
                 fwrite ($bf,full_tag("FEEDBACK",7,false,$ch->feedback));
                 fwrite ($bf,full_tag("FEEDBACKFORMAT",7,false,$ch->feedbackformat));
-                fwrite ($bf,full_tag("USERMODIFIED",7,false,$ch->usermodified));                            
+                fwrite ($bf,full_tag("USERMODIFIED",7,false,$ch->usermodified));
                 fwrite ($bf,end_tag("GRADE_TEXT_HISTORY",6,true));
             }
             $status = fwrite ($bf,end_tag("GRADE_TEXT_HISTORIES",5,true));
         }
-        return $status; 
+        return $status;
     }
 
     function backup_gradebook_items_history_info($bf, $preferences) {
-        
+
         global $CFG;
         $status = true;
 
                 fwrite ($bf,end_tag("GRADE_ITEM_HISTORY",6,true));
             }
             $status = fwrite ($bf,end_tag("GRADE_ITEM_HISTORIES",5,true));
+
         }
-        return $status; 
+        return $status;
     }
-    
+
     function backup_gradebook_outcomes_history($bf, $preferences) {
-        
         global $CFG;
         $status = true;
 
             }
             $status = fwrite ($bf,end_tag("GRADE_OUTCOME_HISTORIES",5,true));
         }
-        return $status; 
+        return $status;
     }
 
     //Backup scales info (common and course scales)
         }
         return $status;
     }
+    /*
+     * This function copies all the site files under the site directory (except the moddata and backupdata
+     * directories to the "site_files" directory under temp/backup
+     */
+    function backup_copy_site_files ($preferences) {
+
+        global $CFG;
+
+        $status = true;
+
+        if ($preferences->backup_course == SITEID){
+            return $status;
+        }
+
+        //First we check to "site_files" exists and create it as necessary
+        //in temp/backup/$backup_code  dir
+        $status = $status && check_and_create_site_files_dir($preferences->backup_unique_code);
+
+        $rootdir = $CFG->dataroot."/".SITEID;
 
+
+
+        $files = get_records_select('backup_files',
+                        "backup_code = '$preferences->backup_unique_code' AND file_type = 'site'");
+        if ($files) {
+            //Iterate
+            foreach ($files as $fileobj) {
+                //check for dir structure and create recursively
+                $file = $fileobj->path;
+                $status = $status && check_dir_exists(dirname($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/site_files/".$file), true, true);
+                $status = $status && backup_copy_file($rootdir."/".$file,
+                                   $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/site_files/".$file);
+            }
+        }
+        return $status;
+    }
     //This function creates the zip file containing all the backup info
     //moodle.xml, moddata, user_files, course_files.
     //The zipped file is created in the backup directory and named with
         $preferences->backup_user_files = optional_param('backup_user_files',1,PARAM_INT);
         $preferences->backup_course_files = optional_param('backup_course_files',1,PARAM_INT);
         $preferences->backup_gradebook_history = optional_param('backup_gradebook_history', 1, PARAM_INT);
+        $preferences->backup_site_files = optional_param('backup_site_files',1,PARAM_INT);
         $preferences->backup_messages = optional_param('backup_messages',1,PARAM_INT);
         $preferences->backup_course = $course->id;
         $preferences->backup_name = required_param('backup_name',PARAM_FILE);
         $preferences->backup_unique_code =  required_param('backup_unique_code');
 
         // put it (back) in the session
-       $SESSION->backupprefs[$course->id] = $preferences;
+        $SESSION->backupprefs[$course->id] = $preferences;
     }
 
     /* Finds all related roles used in course, mod and blocks context
                 }
             }
 
-            //If we have selected to backup quizzes, backup categories and
-            //questions structure (step 1). See notes on mod/quiz/backuplib.php
-            if ($status and !empty($preferences->mods['quiz']->backup)) {
+            //If we have selected to backup quizzes or other modules that use questions
+            //we've already added ids of categories and questions to backup to backup_ids table
+            if ($status) {
                 if (!defined('BACKUP_SILENTLY')) {
                     echo "<li>".get_string("writingcategoriesandquestions").'</li>';
                 }
-                require_once($CFG->dirroot.'/mod/quiz/backuplib.php');
-                if (!$status = backup_question_categories($backup_file,$preferences)) {
+                require_once($CFG->dirroot.'/question/backuplib.php');
+                if (!$status = backup_question_categories($backup_file, $preferences)) {
                     if (!defined('BACKUP_SILENTLY')) {
                         notify("An error occurred while backing up quiz categories");
                     }
                 }
             }
         }
-
+        //Now, if selected, copy site files
+        if ($status) {
+            if ($preferences->backup_site_files) {
+                if (!defined('BACKUP_SILENTLY')) {
+                    echo "<li>".get_string("copyingsitefiles").'</li>';
+                }
+                if (!$status = backup_copy_site_files ($preferences)) {
+                    if (!defined('BACKUP_SILENTLY')) {
+                        notify("An error occurred while copying site files");
+                    }
+                    else {
+                        $errorstr = "An error occurred while copying site files";
+                        return false;
+                    }
+                }
+            }
+        }
         //Now, zip all the backup directory contents
         if ($status) {
             if (!defined('BACKUP_SILENTLY')) {
index 3b4668b46131c584240e1dfb3be3df2f1a70e451..72b562b656ad50e9f5421233e335d1c047b6f94a 100644 (file)
@@ -31,7 +31,7 @@
     //Four hours seem to be appropiate now that backup is stable
     function backup_delete_old_data() {
 
-        global $CFG; 
+        global $CFG;
 
         //Change this if you want !!
         $hours = 4;
         return $status;
     }
 
-    //Function to check and create the needed dir to 
+    //Function to check and create the needed dir to
     //save all the backup
     function check_and_create_backup_dir($backup_unique_code) {
-   
-        global $CFG; 
+
+        global $CFG;
 
         $status = check_dir_exists($CFG->dataroot."/temp",true);
         if ($status) {
@@ -95,7 +95,7 @@
         if ($status) {
             $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code,true);
         }
-        
+
         return $status;
     }
 
     //Copied from the web !!
     function delete_dir_contents ($dir,$excludeddir="") {
 
-        if (!is_dir($dir)) { 
+        if (!is_dir($dir)) {
             // if we've been given a directory that doesn't exist yet, return true.
             // this happens when we're trying to clear out a course that has only just
             // been created.
 
     //Function to clear (empty) the contents of the backup_dir
     function clear_backup_dir($backup_unique_code) {
-  
-        global $CFG; 
+
+        global $CFG;
 
         $rootdir = $CFG->dataroot."/temp/backup/".$backup_unique_code;
-        
+
         //Delete recursively
         $status = delete_dir_contents($rootdir);
 
         return $status;
     }
 
-    //Returns the module type of a course_module's id in a course 
+    //Returns the module type of a course_module's id in a course
     function get_module_type ($courseid,$moduleid) {
 
         global $CFG;
     function list_directories ($rootdir) {
 
         $results = null;
-  
+
         $dir = opendir($rootdir);
         while ($file=readdir($dir)) {
             if ($file=="." || $file=="..") {
                 $results[$file] = $file;
             }
         }
-        closedir($dir);  
-        return $results;       
+        closedir($dir);
+        return $results;
     }
 
     //This function return the names of all directories and files under a give directory
     function list_directories_and_files ($rootdir) {
 
         $results = "";
+
         $dir = opendir($rootdir);
         while ($file=readdir($dir)) {
             if ($file=="." || $file=="..") {
             }
             $results[$file] = $file;
         }
-        closedir($dir); 
+        closedir($dir);
         return $results;
     }
 
     //mantains file perms.
     //I've copied it from: http://www.php.net/manual/en/function.copy.php
     //Little modifications done
-  
+
     function backup_copy_file ($from_file,$to_file,$log_clam=false) {
 
         global $CFG;
     function upgrade_backup_db($continueto) {
     /// This function upgrades the backup tables, if necessary
     /// It's called from admin/index.php, also backup.php and restore.php
-    
+
         global $CFG, $db;
 
         require_once ("$CFG->dirroot/backup/version.php");  // Get code versions
 
         if (empty($CFG->backup_version)) {                  // Backup has never been installed.
             $strdatabaseupgrades = get_string("databaseupgrades");
-            print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades, "", 
+            print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades, "",
                     upgrade_get_javascript(), false, "&nbsp;", "&nbsp;");
 
             upgrade_log_start();
             } else if (file_exists($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.sql')) {
                 $status = modify_database($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.sql'); //Old method
             }
+
             $db->debug = false;
             if ($status) {
                 if (set_config("backup_version", $backup_version) and set_config("backup_release", $backup_release)) {
         upgrade_log_finish();
     }
 
+
     //This function is used to insert records in the backup_ids table
     //If the info field is greater than max_db_storage, then its info
     //is saved to filesystem
         global $CFG;
 
         $max_db_storage = 128;  //Max bytes to save to db, else save to file
+
         $status = true;
-        
+
         //First delete to avoid PK duplicates
         $status = backup_delid($backup_unique_code, $table, $old_id);
 
         //Now, serialize info
         $info_ser = serialize($info);
 
-        //Now, if the size of $info_ser > $max_db_storage, save it to filesystem and 
+        //Now, if the size of $info_ser > $max_db_storage, save it to filesystem and
         //insert a "infile" in the info field
 
         if (strlen($info_ser) > $max_db_storage) {
             //Calculate filename (in current_backup_dir, $backup_unique_code_$table_$old_id.info)
             $filename = $CFG->dataroot."/temp/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info";
             //Save data to file
-            $status = backup_data2file($filename,$info_ser); 
+            $status = backup_data2file($filename,$info_ser);
             //Set info_to save
             $info_to_save = "infile";
         } else {
         $status2 = true;
 
         $status = get_record ("backup_ids","backup_code",$backup_unique_code,
-                                           "table_name",$table, 
+                                           "table_name",$table,
                                            "old_id", $old_id);
 
         //If info field = "infile", get file contents
         return restore_decode_absolute_links(addslashes($data));
     }
 
-    //This function is used to check that every necessary function to 
+    //This function is used to check that every necessary function to
     //backup/restore exists in the current php installation. Thanks to
     //gregb@crowncollege.edu by the idea.
     function backup_required_functions($justcheck=false) {
 
         if(!function_exists('utf8_encode')) {
             if (empty($justcheck)) {
-                error('You need to add XML support to your PHP installation');  
+                error('You need to add XML support to your PHP installation');
             } else {
                 return false;
             }
         echo str_repeat(" ", $n) . $ti . "\n";
         flush();
     }
-    
+
     //This function creates the filename and write data to it
     //returning status as result
     function backup_data2file ($file,&$data) {
 
         $status = true;
         $status2 = true;
-    
+
         $f = fopen($file,"w");
         $status = fwrite($f,$data);
         $status2 = fclose($f);
         }
 
         define('RESTORE_SILENTLY',true); // don't output all the stuff to us.
-        
+
         $debuginfo = 'import_backup_file_silently: ';
         $cleanupafter = false;
         $errorstr = ''; // passed by reference to restore_precheck to get errors from.
             mtrace($debuginfo.'Required function check failed (see backup_required_functions)');
             return false;
         }
-        
+
         @ini_set("max_execution_time","3000");
         raise_memory_limit("192M");
-            
+
         if (!$backup_unique_code = restore_precheck($destinationcourse,$pathtofile,$errorstr,true)) {
             mtrace($debuginfo.'Failed restore_precheck (error was '.$errorstr.')');
             return false;
         }
-        
+
         $SESSION->restore = new StdClass;
 
         // add on some extra stuff we need...
         $SESSION->restore->messages     = $restore->messages = (isset($preferences['restore_messages']) ? $preferences['restore_messages'] : 0);
         $SESSION->restore->course_id    = $restore->course_id = $destinationcourse;
         $SESSION->restore->restoreto    = 1;
-        $SESSION->restore->course_id    = $destinationcourse; 
+        $SESSION->restore->course_id    = $destinationcourse;
         $SESSION->restore->deleting     = $emptyfirst;
         $SESSION->restore->restore_course_files = $restore->course_files = (isset($preferences['restore_course_files']) ? $preferences['restore_course_files'] : 0);
         $SESSION->restore->backup_version = $SESSION->info->backup_backup_version;
         return true;
     }
 
-    /** 
+    /**
     * Function to backup an entire course silently and create a zipfile.
-    * 
-    * @param int $courseid the id of the course 
+    *
+    * @param int $courseid the id of the course
     * @param array $prefs see {@link backup_generate_preferences_artificially}
     */
     function backup_course_silently($courseid, $prefs, &$errorstring) {
-        global $CFG, $preferences; // global preferences here because something else wants it :( 
+        global $CFG, $preferences; // global preferences here because something else wants it :(
         define('BACKUP_SILENTLY', 1);
         if (!$course = get_record('course', 'id', $courseid)) {
             debugging("Couldn't find course with id $courseid in backup_course_silently");
             return false;
         }
-        $preferences = backup_generate_preferences_artificially($course, $prefs); 
+        $preferences = backup_generate_preferences_artificially($course, $prefs);
         if (backup_execute($preferences, $errorstring)) {
             return $CFG->dataroot . '/' . $course->id . '/backupdata/' . $preferences->backup_name;
         }
     }
 
     /**
-    * Function to generate the $preferences variable that 
+    * Function to generate the $preferences variable that
     * backup uses.  This will back up all modules and instances in a course.
-    * 
+    *
     * @param object $course course object
     * @param array $prefs can contain:
             backup_metacourse
             backup_logs
             backup_user_files
             backup_course_files
+            backup_site_files
             backup_messages
     * and if not provided, they will not be included.
     */
 
             }
         }
-        
+
         //Check other parameters
         $preferences->backup_metacourse = (isset($prefs['backup_metacourse']) ? $prefs['backup_metacourse'] : 0);
         $preferences->backup_users = (isset($prefs['backup_users']) ? $prefs['backup_users'] : 0);
         $preferences->backup_logs = (isset($prefs['backup_logs']) ? $prefs['backup_logs'] : 0);
         $preferences->backup_user_files = (isset($prefs['backup_user_files']) ? $prefs['backup_user_files'] : 0);
         $preferences->backup_course_files = (isset($prefs['backup_course_files']) ? $prefs['backup_course_files'] : 0);
+        $preferences->backup_site_files = (isset($prefs['backup_site_files']) ? $prefs['backup_site_files'] : 0);
         $preferences->backup_messages = (isset($prefs['backup_messages']) ? $prefs['backup_messages'] : 0);
         $preferences->backup_course = $course->id;
         backup_add_static_preferences($preferences);
index 8e8fd102006d640d500ca6af47e6d6a45113485a..c5605551bef55990a9cb90a5aa2455fcac4e2d0c 100644 (file)
 
     if ($form1 = data_submitted()) {
         $currentcourseshortname = $course_header->course_shortname; //"store_ShortName";
-        $course_header->course_shortname =  $form1->shortname;  //"update_ShortName";    
-        $course_header->course_fullname =   $form1->fullname;   //"update_FullName";  
-        $form1->startdate = make_timestamp($form1->startyear, $form1->startmonth, $form1->startday);          
+        $course_header->course_shortname =  $form1->shortname;  //"update_ShortName";
+        $course_header->course_fullname =   $form1->fullname;   //"update_FullName";
+        $form1->startdate = make_timestamp($form1->startyear, $form1->startmonth, $form1->startday);
         $currentcoursestartdate = $course_header->course_startdate;
         $coursestartdatedateoffset = $form1->startdate - $currentcoursestartdate;
         $restore->course_startdateoffset = $coursestartdatedateoffset; //change to restore
-    } 
+    }
 
     ///Enforce SESSION->course_header rewrite (PHP 4.x needed because assigns are by value) MDL-8298
     $SESSION->course_header = $course_header;
@@ -39,7 +39,7 @@
     if (empty($info) or empty($course_header)) {
       error( 'important information missing from SESSION' );
     }
-    
+
 
     //If the restore object doesn't exist, we are going
     //to check every variable individually and create it
@@ -55,7 +55,7 @@
             foreach ($allmods as $mod) {
                 $modname = $mod->name;
                 $var = "restore_".$modname;
-                $$var = optional_param( $var,0); 
+                $$var = optional_param( $var,0);
                 $var = "restore_user_info_".$modname;
                 $$var = optional_param( $var,0);
                 $instances = !empty($info->mods[$mod->name]->instances) ? $info->mods[$mod->name]->instances : NULL;
         $restore_user_files = required_param('restore_user_files');
         //restore_course_files
         $restore_course_files = required_param('restore_course_files');
+        //restore_site_files
+        $restore_site_files = required_param('restore_site_files');
         //restore_messages
         $restore_messages = required_param('restore_messages');
 
         //Check we've selected a course to restore to
         $course_id = optional_param('course_id', 0, PARAM_INT);
+
         //We are here, having all we need !!
         //Create the restore object and put it in the session
         $restore->backup_unique_code = $backup_unique_code;
         $restore->logs=$restore_logs;
         $restore->user_files=$restore_user_files;
         $restore->course_files=$restore_course_files;
+        $restore->site_files=$restore_site_files;
         $restore->messages=$restore_messages;
         $restore->course_id=$course_id;
-        //add new vars to restore object 
+        //add new vars to restore object
         $restore->course_startdateoffset = $coursestartdatedateoffset;
         $restore->course_shortname = $currentcourseshortname;
-   
+
         // create role mappings, not sure all should be here
         if ($data2 = data_submitted()) {
             foreach ($data2 as $tempname=>$tempdata) {
                     $oldroleid = $temprole[1];
                     $newroleid = $tempdata;
                     $restore->rolesmapping[$oldroleid] = $newroleid;
-                }                     
-            }       
+                }
+            }
         }
-        
+
         // default role mapping for moodle < 1.7
         if ($defaultteacheredit = optional_param('defaultteacheredit', 0, PARAM_INT)) {
-            $restore->rolesmapping['defaultteacheredit'] = $defaultteacheredit; 
+            $restore->rolesmapping['defaultteacheredit'] = $defaultteacheredit;
         }
         if ($defaultteacher = optional_param('defaultteacher', 0, PARAM_INT)) {
-            $restore->rolesmapping['defaultteacher'] = $defaultteacher; 
+            $restore->rolesmapping['defaultteacher'] = $defaultteacher;
         }
         if ($defaultstudent = optional_param('defaultstudent', 0, PARAM_INT)) {
-            $restore->rolesmapping['defaultstudent'] = $defaultstudent; 
+            $restore->rolesmapping['defaultstudent'] = $defaultstudent;
         }
-                
+
     } else {
         //We have the object, so check if we have a new course_id
         //passed as parammeter
             $restore->course_id=$course_id;
         }
     }
-    
+
     // pass in the course category param
     $cat_id = optional_param('restore_restorecatto', 0, PARAM_INT);
     if ($cat_id) {
         $restore->restore_restorecatto = $cat_id;
     }
-    
+
     //We have the object with data, put it in the session
     $SESSION->restore = $restore;
 
     if (!$site = get_site()) {
         error("Site not found!");
     }
+
     //Depending the selected restoreto:
     // If user is a teacher (and not creator):
     //    0-Current course, deleting: Put $restore->course_id and $restore->deleting (true), create the restore object
     //    2-New course: Create the restore object and launch the execute.
 
     //If the user is a teacher and not a creator
-    
-    
+
+
     //if (!has_capability('moodle/course:create', get_context_instance(CONTEXT_SYSTEM, SITEID))) {
-    
+
     if (!user_can_create_courses()) {
         $restore->course_id = $id;
         if ($restore->restoreto == 0) {
 
     //If the user is a creator (or admin)
     //if (has_capability('moodle/course:create', get_context_instance(CONTEXT_SYSTEM, SITEID))) {
-    if (user_can_create_courses()) {    
+    if (user_can_create_courses()) {
         //Set restore->deleting as needed
         if ($restore->restoreto == 0) {
             $restore->deleting = true;
             error("You need to be an edit teacher or admin to restore into selected course!");
         }
         $show_continue_button = true;
-        //Check if we've selected any mod's user info and restore->users 
+        //Check if we've selected any mod's user info and restore->users
         //is set to none. Change it to course and inform.
         if ($restore->users == 2) {
             $changed = false;
             $hidden["id"]                 =  $id;
             print_string('longtimewarning','admin');
 
-            if ($restore->users && !empty($info->mnet_externalusers) 
+            if ($restore->users && !empty($info->mnet_externalusers)
                 && $info->mnet_externalusers === 'true') {
                 if ($info->original_wwwroot === $CFG->wwwroot) {
                     print '<p>'.get_string('mnetrestore_extusers','admin').'</p>';
         } else {
             //Show error
             error ("Something was wrong checking restore preferences");
-        } 
+        }
 
     //If we are here. Something must be wrong. Debug !!!
     } else {
index d7906f0dbd828b2d0d96ca85b7a0755ee7ffdb9e..7993c20c2af0971b0457c2eadd6b04839fc05722 100644 (file)
         }
     } else {
         if (!has_capability('moodle/site:restore', get_context_instance(CONTEXT_SYSTEM, SITEID))) {
-            error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php");   
+            error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php");
         }
     }
 
     //Check site
     if (!$site = get_site()) {
         error("Site not found!");
-    } 
+    }
 
     //Checks for the required files/functions to restore every mod
     $count = 0;
-    if ($allmods = get_records("modules") ) { 
+    if ($allmods = get_records("modules") ) {
         foreach ($allmods as $mod) {
             $modname = $mod->name;
             $modfile = "$CFG->dirroot/mod/$modname/restorelib.php";
     if (!isset($restore_metacourse)) {
         $restore_metacourse = 1;
     }
-   
+
     if (!isset($restore_users)) {
         $restore_users = 1;
     }
-   
+
     if (!isset($restore_logs)) {
         $restore_logs = 1;
     }
         $restore_course_files = 1;
     }
 
+    if (!isset($restore_site_files)) {
+        $restore_site_files = 1;
+    }
+
     if (!isset($restore_messages)) {
         $restore_messages = 1;
         }
     }
 
     if(!isset($form1->startdate)) {
-        $form1->startdate = $course_header->course_startdate; //$course_header->course_startdate;    
+        $form1->startdate = $course_header->course_startdate; //$course_header->course_startdate;
     }
 
     if (empty($form1->shortname)) {
-       $form1->shortname = $course_header->course_shortname; //'_shortname'; //$course_header->course_shortname; 
+       $form1->shortname = $course_header->course_shortname; //'_shortname'; //$course_header->course_shortname;
     }
 
     if (empty($form1->fullname)) {
-      $form1->fullname = $course_header->course_fullname; // '_fullname';   //$course_header->course_fullname; 
+      $form1->fullname = $course_header->course_fullname; // '_fullname';   //$course_header->course_fullname;
     }
 
     if ($count == 0) {
@@ -169,13 +173,13 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
     echo "<td align=\"right\"><b>";
     echo get_string("restoreto").":</b>";
     echo "</td><td colspan=\"3\">";
-        
-    
+
+
     // permission should have been checked already
-    
+
     /**
-     * if user has manageactivities in any course, we show 
-     *      existingcoursedeleting 
+     * if user has manageactivities in any course, we show
+     *      existingcoursedeleting
      *      existingcourseadding
      * else we show
      *      currentcoursedeleting
@@ -183,9 +187,9 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
      * if user has course:create in any category, we show
      *      newcourse
      */
-    
+
     $mycourses = get_capability_courses('moodle/site:restore');
-    
+
     // if the user can manage 2 or more courses,
     // or if the only course the user can manage is not the current course
     // we show options for existing courses
@@ -196,28 +200,28 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
     // else if the user can write to current course
     } else if (has_capability('moodle/site:restore', get_context_instance(CONTEXT_COURSE, $id))){
         $restore_restoreto_options[0] = get_string("currentcoursedeleting");
-        $restore_restoreto_options[1] = get_string("currentcourseadding");   
+        $restore_restoreto_options[1] = get_string("currentcourseadding");
     }
-    
+
     // if user can create any course at all, give the option
     if (user_can_create_courses()) {
-        $restore_restoreto_options[2] = get_string("newcourse"); 
+        $restore_restoreto_options[2] = get_string("newcourse");
     }
-   
+
     choose_from_menu($restore_restoreto_options, "restore_restoreto", $restore_restoreto, "");
     echo "</td></tr>";
     if (user_can_create_courses()) {  //display these fields conditionally
-        
+
         // find the list of cates user can edit
         echo "<tr valign=\"top\" >";
         echo "<td align=\"right\">";
         print_string('category');
         echo " :</td>";
         echo "<td>";
-        choose_from_menu(get_creatable_categories(), "restore_restorecatto", $course_header->category->id, "");        
+        choose_from_menu(get_creatable_categories(), "restore_restorecatto", $course_header->category->id, "");
         echo "</td>";
         echo "</tr>";
-        
+
         echo "<tr valign=\"top\" >";
         echo "<td align=\"right\">";
         print_string("shortname");
@@ -231,12 +235,12 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         echo " :</td>";
         echo "<td><input type=\"text\" name=\"fullname\" maxlength=\"254\" size=\"50\" value=\"$form1->fullname\" alt=\" ".get_string("fullname")."\"  />" ;
         helpbutton("coursefullname", get_string("fullname")) ;
-        if (isset($err["fullname"])) formerr($err["fullname"]); 
+        if (isset($err["fullname"])) formerr($err["fullname"]);
         echo"</td></tr>";
         echo "<tr valign=\"top\"> ";
         echo "<td align=\"right\"> ";
-        print_string("startdate"); 
-        echo ":</td><td>"; 
+        print_string("startdate");
+        echo ":</td><td>";
         print_date_selector("startday", "startmonth", "startyear", $form1->startdate);
         helpbutton("coursestartdate", get_string("startdate"));
         echo "</td></tr>";
@@ -282,7 +286,7 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
                         echo "<td align=\"right\">&nbsp;";
                         echo "</td><td>";
                         $restore_options[1] = get_string("yes");
-                        $restore_options[0] = get_string("no"); 
+                        $restore_options[0] = get_string("no");
                         //choose_from_menu($restore_options, $restore_var, $$restore_var, "");
                         //choose_from_radio($restore_options, $restore_var, $$restore_var);
                         //Print the checkbox
@@ -293,7 +297,7 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
                         echo "</td><td>";
                         if ($info->mods[$modname]->userinfo == "true") {
                             $restore_user_options[1] = get_string("yes");
-                            $restore_user_options[0] = get_string("no"); 
+                            $restore_user_options[0] = get_string("no");
                             //choose_from_menu($restore_user_options, $user_info_var, $$user_info_var, "");
                             //choose_from_radio($restore_user_options, $user_info_var, $$user_info_var);
                             print_checkbox($user_info_var, $$user_info_var, $$user_info_var, get_string("userdata"),'','selectItemInCheckboxByName(\'form1\',\'restore_user_info_'.$modname.'\',this.checked)');
@@ -348,13 +352,13 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         //Now print the Metacourse tr
         echo "<tr>";
         echo "<td align=\"right\" colspan=\"2\"><b>";
-        echo get_string("metacourse").":";                                               
+        echo get_string("metacourse").":";
         echo "</b></td><td colspan=\"2\">";
         //If metacourse are in the backup file, show menu, else fixed to no
         if ($info->backup_metacourse == "true") {
             $metacourse_options[0] = get_string("no");
-            $metacourse_options[1] = get_string("yes"); 
-            choose_from_menu($metacourse_options, "restore_metacourse", $restore_metacourse, ""); 
+            $metacourse_options[1] = get_string("yes");
+            choose_from_menu($metacourse_options, "restore_metacourse", $restore_metacourse, "");
         } else {
             echo get_string("no");
             echo "<input type=\"hidden\" name=\"restore_metacourse\" value=\"0\" />";
@@ -384,13 +388,13 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         //Now print the Logs tr
         echo "<tr>";
         echo "<td align=\"right\" colspan=\"2\"><b>";
-        echo get_string("logs").":";                                               
+        echo get_string("logs").":";
         echo "</b></td><td colspan=\"2\">";
         //If logs are in the backup file, show menu, else fixed to no
         if ($info->backup_logs == "true") {
             $log_options[0] = get_string("no");
-            $log_options[1] = get_string("yes"); 
-            choose_from_menu($log_options, "restore_logs", $restore_logs, ""); 
+            $log_options[1] = get_string("yes");
+            choose_from_menu($log_options, "restore_logs", $restore_logs, "");
         } else {
             echo get_string("no");
             echo "<input type=\"hidden\" name=\"restore_logs\" value=\"0\" />";
@@ -404,8 +408,8 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         echo "</b></td><td colspan=\"2\">";
         //If user files are in the backup file, show menu, else fixed to no
         if ($info->backup_user_files == "true") {
-            $user_file_options[0] = get_string("no"); 
-            $user_file_options[1] = get_string("yes"); 
+            $user_file_options[0] = get_string("no");
+            $user_file_options[1] = get_string("yes");
             choose_from_menu($user_file_options, "restore_user_files", $restore_user_files, "");
         } else {
             echo get_string("no");
@@ -431,10 +435,27 @@ function selectItemInCheckboxByName(formId, checkName, checked ) {
         }
         echo "</td></tr>";
 
+
+        //Now print the Site Files tr
+        echo "<tr>";
+        echo "<td align=\"right\" colspan=\"2\"><b>";
+        echo get_string ("sitefiles").":";
+        echo "</b></td><td colspan=\"2\">";
+        //If site files are in the backup file, show menu, else fixed to no
+        if ($info->backup_site_files == "true") {
+            $site_file_options[0] = get_string("no");
+            $site_file_options[1] = get_string("yes");
+            choose_from_menu($site_file_options, "restore_site_files", $restore_site_files, "");
+        } else {
+            echo get_string("no");
+            echo "<input type=\"hidden\" name=\"restore_site_files\" value=\"0\" />";
+        }
+        echo "</td></tr>";
+
         //Now print the Messages tr
         echo "<tr>";
         echo "<td align=\"right\" colspan=\"2\"><b>";
-        
+
         //This tr is slighty different. Everything becomes hidden if
         //we haven't messages is the backup, to avoid confusions to users.
         //If messages are in the backup file, show menu, else fixed to no and show nothing
@@ -470,48 +491,48 @@ echo ('<tr><td align="right" style="width:50%"><b>'.get_string('sourcerole').'</
 
 if ($info->backup_moodle_version < 2006092801) {
     // 1.6 and below backup
-    
+
     /// Editting teacher
     echo ('<tr><td align="right">');
     print_string('defaultcourseteacher');
     echo ('</td><td algin="left">');
-    
+
     // get the first teacheredit legacy
     $roles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM, SITEID));
 
     $editteacher = array_shift($roles);
     choose_from_menu ($siterolesarray, "defaultteacheredit", $editteacher->id, 'new role', '', '0');
     echo ('</td></tr>');
-    
+
     /// Non-editting teacher
     echo ('<tr><td align="right">');
     print_string('noneditingteacher');
     echo ('</td><td algin="left">');
-    
+
     // get the first teacheredit legacy
     $roles = get_roles_with_capability('moodle/legacy:teacher', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM, SITEID));
     $teacher = array_shift($roles);
-    
+
     choose_from_menu ($siterolesarray, "defaultteacher", $teacher->id, 'new role', '', '0');
     echo ('</td></tr>');
-     
-    
+
+
     /// Student
     echo ('<tr><td align="right">');
     print_string('defaultcoursestudent');
     echo ('</td><td algin="left">');
-    
+
     // get the first teacheredit legacy
     $roles = get_roles_with_capability('moodle/legacy:student', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM, SITEID));
     $studentrole = array_shift($roles);
-    
+
     choose_from_menu ($siterolesarray, "defaultstudent", $studentrole->id, 'new role', '', '0');
     echo ('</td></tr>');
-  
+
 } else {
     // 1.7 and above backup
     $roles = restore_read_xml_roles($xml_file);
-    
+
     if (!empty($roles->roles)) { // possible to have course with no roles
         foreach ($siterolesarray as $siteroleid=>$siteroleshortname) {
             $siteroleschoicearray[$siteroleid] = $siterolesnamearray[$siteroleid]." (". $siterolesarray[$siteroleid].")";
@@ -521,21 +542,21 @@ if ($info->backup_moodle_version < 2006092801) {
             echo ('<tr><td align="right">');
             echo $role->name." (".($role->shortname).")";
             echo ('</td><td align="left">');
-    
+
             // see if any short name match
             $matchrole = 0;
             foreach ($siterolesarray as $siteroleid=>$siteroleshortname) {
                 if ($siteroleshortname == $role->shortname) {
                     $matchrole = $siteroleid;
-                    break;  
-                }  
+                    break;
+                }
             }
-    
+
             choose_from_menu ($siteroleschoicearray, "roles_".$roleid, $matchrole, 'new role', '', '0');
-            echo ('</td></tr>'); 
+            echo ('</td></tr>');
         }
     }
-    
+
 } // end else
 
 echo ('</table>'); // end of role mappings table
index af85a96f903402320202ccb5de7c53e1c237f3cd..6ab234e08915a26062dc72471efc01d4611a4e2b 100644 (file)
                 $tab[$elem][1] = get_string("no");
             }
             $elem++;
+            //site Files info
+            $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>";
+            if ($info->backup_site_files == "true") {
+                $tab[$elem][1] = get_string("yes");
+            } else {
+                $tab[$elem][1] = get_string("no");
+            }
+            $elem++;
             //Messages info (only showed if present)
             if ($info->backup_messages == 'true') {
                 $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
         return $status;
     }
 
-   /**
-    * Returns the best question category (id) found to restore one
-    * question category from a backup file. Works by stamp (since Moodle 1.1)
-    * or by name (for older versions).
-    *
-    * @param object  $cat      the question_categories record to be searched
-    * @param integer $courseid the course where we are restoring
-    * @return integer the id of a existing question_category or 0 (not found)
-    */
-    function restore_get_best_question_category($cat, $courseid) {
-
-        $found = 0;
-
-        //Decide how to work (by stamp or name)
-        if ($cat->stamp) {
-            $searchfield = 'stamp';
-            $searchvalue = $cat->stamp;
-        } else {
-            $searchfield = 'name';
-            $searchvalue = $cat->name;
-        }
 
-        //First shot. Try to get the category from the course being restored
-        if ($fcat = get_record('question_categories','course',$courseid,$searchfield,$searchvalue)) {
-            $found = $fcat->id;
-        //Second shot. Try to obtain any concordant category and check its publish status and editing rights
-        } else if ($fcats = get_records('question_categories', $searchfield, $searchvalue, 'id', 'id, publish, course')) {
-            foreach ($fcats as $fcat) {
-                if ($fcat->publish == 1 && has_capability('moodle/site:restore', get_context_instance(CONTEXT_COURSE, $fcat->course))) {
-                    $found = $fcat->id;
-                    break;
-                }
-            }
-        }
-
-        return $found;
-    }
 
     //This function creates all the block stuff when restoring courses
     //It calls selectively to  restore_create_block_instances() for 1.5
                             //$GLOBALS['traverse_array']="";                     //Debug
                             //Now build the GRADE_PREFERENCES record structure
                             if ($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']) {
-                                $dbrec->courseid   = $restore->course_id;  
+                                $dbrec->courseid   = $restore->course_id;
                             } else {
                                 $dbrec->courseid   = NULL;
                             }
                             $dbrec->usermodified = $modifier->new_id;
 
                             // Structure is equal to db, insert record
-                            // If the shortname doesn't exist                            
-                              
+                            // If the shortname doesn't exist
+
                             if (empty($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#'])) {
-                                $prerec = get_record_sql("SELECT * FROM {$CFG->prefix}grade_outcomes 
+                                $prerec = get_record_sql("SELECT * FROM {$CFG->prefix}grade_outcomes
                                                                    WHERE courseid IS NULL
                                                                    AND shortname = '$dbrec->shortname'");
                             } else {
                                 $prerec = get_record('grade_outcomes','courseid',$restore->course_id,'shortname',$dbrec->shortname);
                             }
-                            
+
                             if (!$prerec) {
                                 $newid = insert_record('grade_outcomes',$dbrec);
                             } else {
-                                $newid = $prerec->id;  
+                                $newid = $prerec->id;
                             }
-                            
+
                             if ($newid) {
                                 backup_putid($restore->backup_unique_code,"grade_outcomes", $rec->old_id, $newid);
                             }
                             //$GLOBALS['traverse_array']="";                     //Debug
 
                             $oldoutcomesid = backup_todb($info['GRADE_OUTCOMES_COURSE']['#']['OUTCOMEID']['0']['#']);
-                            $newoutcome = backup_getid($restore->backup_unique_code,"grade_outcomes",$oldoutcomesid); 
+                            $newoutcome = backup_getid($restore->backup_unique_code,"grade_outcomes",$oldoutcomesid);
                             unset($dbrec);
                             $dbrec->courseid = $restore->course_id;
                             $dbrec->outcomeid = $newoutcome->new_id;
                                 if ($restoreall) {
                                     // TODO any special code needed here to restore course item without duplicating it?
                                     // find the course category with depth 1, and course id = current course id
-                                    // this would have been already restored                                    
-                                    
+                                    // this would have been already restored
+
                                     $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
                                     $dbrec->iteminstance = $cat->id;
-                                    
+
                                 } else {
                                     continue;
                                 }
                             }
 
                             /// needs to be restored first
-                            $dbrec->outcomeid = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']));                            
-                            
+                            $dbrec->outcomeid = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']));
+
                             $dbrec->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#']);
                             $dbrec->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#']);
                             $dbrec->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#']);
                             }
 
 
+
                             /// processing grade_grades_text
                             if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES_TEXT']['0']['#']) && ($texts = $info['GRADE_ITEM']['#']['GRADE_GRADES_TEXT']['0']['#']['GRADE_TEXT'])) {
                                 //Iterate over items
                                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
                                     //$GLOBALS['traverse_array']="";                                                              //Debug
                                     $grade = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($ite_info['#']['GRADEID']['0']['#']));
-                                    
+
                                     $text->gradeid = $grade->new_id;
                                     $text->information = backup_todb($ite_info['#']['INFORMATION']['0']['#']);
                                     $text->informationformat = backup_todb($ite_info['#']['INFORMATIONFORMAT']['0']['#']);
                             $info = $data->info;
                             //traverse_xmlize($info);                            //Debug
                             //print_object ($GLOBALS['traverse_array']);         //Debug
-                            //$GLOBALS['traverse_array']="";                     //Debug          
-                            
+                            //$GLOBALS['traverse_array']="";                     //Debug
+
                             $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
                             if (empty($oldobj->new_id)) {
                                 // if the old object is not being restored, can't restoring its history
                                 $counter++;
-                                continue;                             
+                                continue;
                             }
-                            $dbrec->oldid = $oldobj->new_id;                                                   
-                            $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']); 
+                            $dbrec->oldid = $oldobj->new_id;
+                            $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
                             $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
                             $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
-                            
+
                             // loggeduser might not be restored, e.g. admin
                             if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                 $dbrec->loggeduser = $oldobj->new_id;
-                            }                           
-                            
+                            }
+
                             // this item might not have a parent at all, do not skip it if no parent is specified
                             if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
-                                $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));  
+                                $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
                                 if (empty($oldobj->new_id)) {
                                     // if the parent category not restored
                                     $counter++;
-                                    continue;                             
-                                } 
-                            }                        
+                                    continue;
+                                }
+                            }
                             $dbrec->parent = $oldobj->new_id;
-                            $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);                            
+                            $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
                             // path needs to be rebuilt
                             if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
                             // to preserve the path and make it work, we need to replace the categories one by one
                             $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
                             $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
                             $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
-                            $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);                                     
+                            $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
                             $dbrec->courseid = $restore->course_id;
                             insert_record('grade_categories_history', $dbrec);
                             unset($dbrec);
                             if (empty($oldobj->new_id)) {
                                 // if the old object is not being restored, can't restoring its history
                                 $counter++;
-                                continue;                             
+                                continue;
                             }
                             $dbrec->oldid = $oldobj->new_id;
                             $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
                             $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
                             $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
                             $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
-                            
+
                             insert_record('grade_grades_history', $dbrec);
                             unset($dbrec);
 
                             //traverse_xmlize($info);                            //Debug
                             //print_object ($GLOBALS['traverse_array']);         //Debug
                             //$GLOBALS['traverse_array']="";                     //Debug
-                            
+
                             $oldobj = backup_getid($restore->backup_unique_code,"grade_grades_text", backup_todb($info['GRADE_TEXT_HISTORY']['#']['OLDID']['0']['#']));
                             if (empty($oldobj->new_id)) {
                                 // if the old object is not being restored, can't restoring its history
                                 $counter++;
-                                continue;                             
+                                continue;
                             }
                             $dbrec->oldid = $oldobj->new_id;
                             $dbrec->action = backup_todb($info['GRADE_TEXT_HISTORY']['#']['ACTION']['0']['#']);
                             $dbrec->timemodified = backup_todb($info['GRADE_TEXT_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                             if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_TEXT_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                 $dbrec->loggeduser = $oldobj->new_id;
-                            }                          
-                            $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_TEXT_HISTORY']['#']['GRADEID']['0']['#']));                           
-                            $dbrec->gradeid = $oldobj->new_id;                            
+                            }
+                            $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_TEXT_HISTORY']['#']['GRADEID']['0']['#']));
+                            $dbrec->gradeid = $oldobj->new_id;
                             if (empty($dbrec->gradeid)) {
                                 $counter++;
-                                continue; // grade not being restore, possibly because grade item is not restored 
+                                continue; // grade not being restore, possibly because grade item is not restored
                             }
-                            $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_TEXT_HISTORY']['#']['USERID']['0']['#']));                           
+                            $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_TEXT_HISTORY']['#']['USERID']['0']['#']));
                             $dbrec->userid = $oldobj->new_id;
                             $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
                             $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
                             $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
-                            $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);                           
-                            if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_TEXT_HISTORY']['#']['USERMODIFIED']['0']['#']))) {         
+                            $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
+                            if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_TEXT_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
                                 $dbrec->usermodified = $oldobj->new_id;
                             }
 
                             //$GLOBALS['traverse_array']="";                     //Debug
 
 
-                            $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));                            
+                            $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
                             if (empty($oldobj->new_id)) {
                                 // if the old object is not being restored, can't restoring its history
                                 $counter++;
-                                continue;                             
+                                continue;
                             }
                             $dbrec->oldid = $oldobj->new_id;
                             $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
                             $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                             if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                 $dbrec->loggeduser = $oldobj->new_id;
-                            }                            
+                            }
                             $oldobj = backup_getid($restore->backup_unique_code,'grade_categories',backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
-                            $oldobj->categoryid = $category->new_id;                        
+                            $oldobj->categoryid = $category->new_id;
                             if (empty($oldobj->categoryid)) {
                                 $counter++;
-                                continue; // category not restored 
+                                continue; // category not restored
                             }
-                            
+
                             $dbrec->itemname= backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
                             $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
                             $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
-                            
+
                             // code from grade_items restore
                             $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
                             // do not restore if this grade_item is a mod, and
                                 if ($restoreall) {
                                     // TODO any special code needed here to restore course item without duplicating it?
                                     // find the course category with depth 1, and course id = current course id
-                                    // this would have been already restored                                    
-                                    
+                                    // this would have been already restored
+
                                     $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
                                     $dbrec->iteminstance = $cat->id;
-                                    
+
                                 } else {
                                     $counter++;
                                     continue;
                             }
 
                             $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
-                            $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);                        
+                            $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
                             $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
                             $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
                             $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
                             }
                             $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
                             $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
-                            $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);                          
+                            $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
                             $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
                             $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
                             $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
                             $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
                             $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
-                            $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);                             
-                            
+                            $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
+
                             insert_record('grade_items_history', $dbrec);
                             unset($dbrec);
 
                             if (empty($oldobj->new_id)) {
                                 // if the old object is not being restored, can't restoring its history
                                 $counter++;
-                                continue;                             
+                                continue;
                             }
-                            $dbrec->oldid = $oldobj->new_id;                         
+                            $dbrec->oldid = $oldobj->new_id;
                             $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
                             $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
                             $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                                 $dbrec->loggeduser = $oldobj->new_id;
                             }
                             $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
-                            $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);                           
+                            $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
                             $oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
                             $dbrec->scaleid = $oldobj->new_id;
                             $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
-                            
+
                             insert_record('grade_outcomes_history', $dbrec);
                             unset($dbrec);
 
         //categories/questions
         if ($info) {
             if ($info !== true) {
-                //Iterate over each category
-                foreach ($info as $category) {
-                    //Skip empty categories (some backups can contain them)
-                    if (!empty($category->id)) {
-                        $status = restore_question_categories($category,$restore);
-                    }
-                }
-
-                //Now we have to recode the parent field of each restored category
-                $categories = get_records_sql("SELECT old_id, new_id
-                                               FROM {$CFG->prefix}backup_ids
-                                               WHERE backup_code = $restore->backup_unique_code AND
-                                                     table_name = 'question_categories'");
-                if ($categories) {
-                    foreach ($categories as $category) {
-                        $restoredcategory = get_record('question_categories','id',$category->new_id);
-                        $restoredcategory = addslashes_object($restoredcategory);
-                        if ($restoredcategory->parent != 0) {
-                            $idcat = backup_getid($restore->backup_unique_code,'question_categories',$restoredcategory->parent);
-                            if ($idcat->new_id) {
-                                $restoredcategory->parent = $idcat->new_id;
-                            } else {
-                                $restoredcategory->parent = 0;
-                            }
-                            update_record('question_categories', $restoredcategory);
-                        }
-                    }
-                }
+                $status = $status &&  restore_question_categories($info, $restore);
             }
         } else {
             $status = false;
                         } else {
                             $course_to_search = $restore->course_id;
                         }
-                        
+
                         // scale is not course unique, use get_record_sql to suppress warning
-                        
+
                         $sca_db = get_record_sql("SELECT * FROM {$CFG->prefix}scale
                                                            WHERE scale = '$sca->scale'
-                                                           AND courseid = $course_to_search", true);                  
-                        
+                                                           AND courseid = $course_to_search", true);
+
                         //If it doesn't exist, create
                         if (!$sca_db) {
                             $create_scale = true;
         }
     }
 
+    //This function restores the site files from the temp (site_files) directory to the
+    //dataroot/SITEID directory
+    function restore_site_files($restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        $counter = 0;
+
+        //First, we check to "course_id" exists and create is as necessary
+        //in CFG->dataroot
+        $dest_dir = $CFG->dataroot."/".SITEID;
+        $status = check_dir_exists($dest_dir,true);
+
+        //Now, we iterate over "site_files" files to check if that file/dir must be
+        //copied to the "dest_dir" dir.
+        $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/site_files";
+        //Check if directory exists
+        if (is_dir($rootdir)) {
+            $list = list_directories_and_files ($rootdir);
+            if ($list) {
+                //Iterate
+                $counter = 0;
+                foreach ($list as $dir) {
+                    //Copy the dir to its new location
+                    //Only if destination file/dir doesn exists
+                    if (!file_exists($dest_dir."/".$dir)) {
+                        $status = backup_copy_file($rootdir."/".$dir,
+                                      $dest_dir."/".$dir,true);
+                        $counter ++;
+                    }
+                    //Do some output
+                    if ($counter % 2 == 0) {
+                        if (!defined('RESTORE_SILENTLY')) {
+                            echo ".";
+                            if ($counter % 40 == 0) {
+                                echo "<br />";
+                            }
+                        }
+                        backup_flush(300);
+                    }
+                }
+            }
+        }
+        //If status is ok and whe have dirs created, returns counter to inform
+        if ($status and $counter) {
+            return $counter;
+        } else {
+            return $status;
+        }
+    }
+
 
     //This function creates all the structures for every module in backup file
     //Depending what has been selected.
             //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
             if (isset($this->tree[5]) and isset($this->tree[3])) {
                 if (($this->tree[5] == "GRADE_ITEM" || $this->tree[5] == "GRADE_CATEGORY" || $this->tree[5] == "GRADE_OUTCOME" || $this->tree[5] == "GRADE_OUTCOMES_COURSE" || $this->tree[5] == "GRADE_CATEGORIES_HISTORY" || $this->tree[5] == "GRADE_GRADES_HISTORY" || $this->tree[5] == "GRADE_TEXT_HISTORY" || $this->tree[5] == "GRADE_ITEM_HISTORY" || $this->tree[5] == "GRADE_OUTCOME_HISTORY") && ($this->tree[3] == "GRADEBOOK")) {
-                    
+
                     if (!isset($this->temp)) {
                         $this->temp = "";
                     }
                             case "COURSEFILES":
                                 $this->info->backup_course_files = $this->getContents();
                                 break;
+                            case "SITEFILES":
+                                $this->info->backup_site_files = $this->getContents();
+                                break;
                             case "MESSAGES":
                                 $this->info->backup_messages = $this->getContents();
                                 break;
                     //Reset temp
                     unset($this->temp);
                 }
-                
+
                 //If we've finished a grade_outcomes_course, xmlize it an save to db
                 if (($this->level == 5) and ($tagName == "GRADE_OUTCOMES_COURSE")) {
                     //Prepend XML standard header to info gathered
                     $this->info = $this->counter;
                     //Reset temp
                     unset($this->temp);
-                }   
-                
+                }
+
                 if (($this->level == 5) and ($tagName == "GRADE_CATEGORIES_HISTORY")) {
                     //Prepend XML standard header to info gathered
                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
 
                     unset($this->temp);
                 }
-                
+
                 if (($this->level == 5) and ($tagName == "GRADE_GRADES_HISTORY")) {
                     //Prepend XML standard header to info gathered
                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
                     //Reset temp
 
                     unset($this->temp);
-                }                
-                
+                }
+
                 if (($this->level == 5) and ($tagName == "GRADE_TEXT_HISTORY")) {
                     //Prepend XML standard header to info gathered
                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
                     //Reset temp
 
                     unset($this->temp);
-                }              
-                              
+                }
+
                 if (($this->level == 5) and ($tagName == "GRADE_ITEM_HISTORY")) {
                     //Prepend XML standard header to info gathered
                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
                     //Reset temp
 
                     unset($this->temp);
-                }             
-                
+                }
+
                 if (($this->level == 5) and ($tagName == "GRADE_OUTCOME_HISTORY")) {
                     //Prepend XML standard header to info gathered
                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
         $restore->backup_unique_code=$backup_unique_code;
         $restore->users = 2; // yuk
         $restore->course_files = $SESSION->restore->restore_course_files;
+        $restore->site_files = $SESSION->restore->restore_site_files;
         if ($allmods = get_records("modules")) {
             foreach ($allmods as $mod) {
                 $modname = $mod->name;
 
 
         //Now create categories and questions as needed
-        if ($status and ($restore->mods['quiz']->restore)) {
+        if ($status) {
             include_once("$CFG->dirroot/question/restorelib.php");
             if (!defined('RESTORE_SILENTLY')) {
                 echo "<li>".get_string("creatingcategoriesandquestions");
             }
         }
 
+
+        //Now create site files as needed
+        if ($status and ($restore->site_files)) {
+            if (!defined('RESTORE_SILENTLY')) {
+                echo "<li>".get_string('copyingsitefiles');
+            }
+            if (!$status = restore_site_files($restore)) {
+                if (empty($status)) {
+                    notify("Could not restore site files!");
+                } else {
+                    $errorstr = "Could not restore site files!";
+                    return false;
+                }
+            }
+            //If all is ok (and we have a counter)
+            if ($status and ($status !== true)) {
+                //Inform about user dirs created from backup
+                if (!defined('RESTORE_SILENTLY')) {
+                    echo "<ul>";
+                    echo "<li>".get_string("filesfolders").": ".$status.'</li>';
+                    echo "</ul>";
+                }
+            }
+            if (!defined('RESTORE_SILENTLY')) {
+                echo "</li>";
+            }
+        }
+
         //Now create messages as needed
         if ($status and ($restore->messages)) {
             if (!defined('RESTORE_SILENTLY')) {
             }
 
             $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
-            $override->contextid = $newcontext->id; // new context id                
+            $override->contextid = $newcontext->id; // new context id
             // use assign capability instead so we can add context to context_rel
             assign_capability($override->capability, $override->permission, $override->roleid, $override->contextid);
         }
index 822fa1da484aa4d2f6d4035c7e01d0b22a1425cc..4686d83f5bea67abe1e6f2b09c92951acd5622f5 100644 (file)
@@ -502,7 +502,12 @@ $string['profilevisible'] = 'Who is this field visible to?';
 $string['protectusernames'] = 'Protect usernames';
 $string['proxyhost'] = 'Proxy host';
 $string['proxyport'] = 'Proxy port';
+$string['qtyperqpwillberemoved'] = 'During the upgrade, the RQP question type will be removed. You were not using this question type, so you should not experience any problems.';
+$string['qtyperqpwillberemovedanyway'] = 'During the upgrade, the RQP question type will be removed. You have some RQP questions in your database, and these will stop working unless you reinstall the code from http://moodle.org/mod/data/view.php?d=13&amp;rid=797 before continuing with the upgrade.';
 $string['quarantinedir'] = 'Quarantine directory';
+$string['question'] = 'Question';
+$string['questioncwqpfscheck'] = 'One or more \'random\' questions in a quiz are set up to select questions from a mixture of shared and unshared question categories. There is a more detailled report <a href=\"$a->reporturl\">here</a> and see Moodle Docs page <a href=\"$a->docsurl\">here</a>.';
+$string['questioncwqpfsok'] = 'Good. There are no \'random\' questions in your quizzes that are set up to select questions from a mixture of shared and unshared question categories.';
 $string['rcache'] = 'Record cache';
 $string['rcachettl'] = 'Record cache TTL';
 $string['releasenoteslink'] = 'For information about this version of Moodle, please see the online <a target=\"_new\" href=\"$a\">Release Notes</a>';
@@ -521,8 +526,6 @@ $string['riskspamshort'] = 'Spam risk';
 $string['riskxss'] = 'Users could add files and texts that allow cross-site scripting (XSS)';
 $string['riskxssshort'] = 'XSS risk';
 $string['runclamavonupload'] = 'Use clam AV on uploaded files';
-$string['qtyperqpwillberemoved'] = 'During the upgrade, the RQP question type will be removed. You were not using this question type, so you should not experience any problems.';
-$string['qtyperqpwillberemovedanyway'] = 'During the upgrade, the RQP question type will be removed. You have some RQP questions in your database, and these will stop working unless you reinstall the code from http://moodle.org/mod/data/view.php?d=13&amp;rid=797 before continuing with the upgrade.';
 $string['savechanges'] = 'Save Changes';
 $string['search'] = 'Search';
 $string['searchresults'] = 'Search Results';
index 9cedba1fe564a9a7f13e59b8f06eb4751f644b87..28acde923db5f00f7133217362807fa54ca29e39 100644 (file)
@@ -159,6 +159,7 @@ $string['backupnonisowarning'] = 'Warning: this backup is from a non-Unicode ver
 $string['backuporiginalname'] = 'Backup Name';
 $string['backupsavetohelp'] = 'Full path to the directory where you want to save the backup files<br />(leave blank to save in its course default dir)';
 $string['backupschedulehelp'] = 'Choose which days of the week to perform automated backups.';
+$string['backupsitefileshelp'] = 'If enabled then site files used in courses will be included in automated backups';
 $string['backuptakealook'] = 'Please take a look at your backup logs in:
   $a';
 $string['backupuserfileshelp'] = 'Choose whether user files (eg profile images) should be included in automated backups';
@@ -239,6 +240,7 @@ $string['cookiesnotenabled'] = 'Unfortunately, cookies are currently not enabled
 $string['copy'] = 'copy';
 $string['copyasnoun'] = 'copy';
 $string['copyingcoursefiles'] = 'Copying course files';
+$string['copyingsitefiles'] = 'Copying site files used in course';
 $string['copyinguserfiles'] = 'Copying user files';
 $string['copyingzipfile'] = 'Copying zip file';
 $string['copyrightnotice'] = 'Copyright notice';
@@ -508,7 +510,7 @@ $string['emailpasswordchangeinfodisabled'] = 'Hi $a->firstname,
 Someone (probably you) has requested a new password for your
 account on \'$a->sitename\'.
 
-Unfortunately your account on this site is disabled and can not be reset, 
+Unfortunately your account on this site is disabled and can not be reset,
 please contact the site administrator,
 $a->admin';
 $string['emailpasswordchangeinfofail'] = 'Hi $a->firstname,
@@ -516,7 +518,7 @@ $string['emailpasswordchangeinfofail'] = 'Hi $a->firstname,
 Someone (probably you) has requested a new password for your
 account on \'$a->sitename\'.
 
-Unfortunately passwords can not be reset on this site, 
+Unfortunately passwords can not be reset on this site,
 please contact the site administrator,
 $a->admin';
 $string['emailpasswordchangeinfosubject'] = '$a: Change password information';
@@ -775,6 +777,7 @@ $string['includemodules'] = 'Include Modules';
 $string['includemoduleuserdata'] = 'Include module user data';
 $string['includeneededusers'] = 'Include Needed Users';
 $string['includenoneusers'] = 'Include No Users';
+$string['includesitefiles'] = 'Include Site Files Used in This Course';
 $string['includeuserfiles'] = 'Include User Files';
 $string['info'] = 'Information';
 $string['institution'] = 'Institution';
@@ -1299,6 +1302,7 @@ $string['site'] = 'Site';
 $string['sitedefault'] = 'Site Default';
 $string['siteerrors'] = 'Site errors';
 $string['sitefiles'] = 'Site files';
+$string['sitefilesused'] = 'Site files used in this course';
 $string['sitelogs'] = 'Site logs';
 $string['sitenews'] = 'Site news';
 $string['sitepartlist'] = 'You do not have the required permissions to view the participants list';
index 8cecea59f5e2568b214bf87a2440a5b0bc2b8bdc..809065474b31acf0a7ff8aa8abd3863a0d2426c8 100644 (file)
@@ -1,6 +1,7 @@
 <?PHP // $Id$
       // qtype_multichoice.php - created with Moodle 1.7 beta + (2006101003)
 
+$string['addingmultichoice'] = 'Adding a Multiple Choice question';
 $string['answerhowmany'] = 'One or multiple answers?';
 $string['addmorechoiceblanks'] = 'Blanks for {no} More Choices';
 $string['answerhowmany'] = 'One or multiple answers?';
index 0bee22aa669c9ba9c51ebd63550b8f6079603f0b..aaf49dbba505eb62d15789e4d6f090c46563cea4 100644 (file)
@@ -1,6 +1,7 @@
 <?php // $Id$ 
       // qtype_truefalse.php - created with Moodle 1.8dev
 
+$string['addingtruefalse'] = 'Adding a True/False question';
 $string['correctanswer'] = 'Correct answer';
 $string['editingtruefalse'] = 'Editing a True/False question';
 $string['false'] = 'False';
index 5fbeba3808b4d3fe93df98fd437fd682ddfe3853..a4b07a7760bcba8be1a61b2f75aaf60976a2d09f 100644 (file)
@@ -1,14 +1,78 @@
 <?php // $Id$
 // question.php - created with Moodle 1.8 dev
 
+$string['adminreport'] = 'Report on possible problems in your question database.';
+$string['broken'] = 'This is a \"broken link\", it points to a nonexistent file.';
+$string['byandon'] = 'by <em>$a->user</em> on <em>$a->time</em>';
 $string['categorydoesnotexist'] = 'This category does not exist';
+$string['categorycurrent'] = 'Current Category';
+$string['categorycurrentuse'] = 'Use This Category';
+$string['categorymoveto'] = 'Save in Category';
+$string['changepublishstatuscat'] = '<a href=\"$a->caturl\">Category \"$a->name\"</a> in course \"$a->coursename\" will have it\'s sharing status changed from <strong>$a->changefrom to $a->changeto</strong>.';
+$string['cwrqpfs'] = 'Random questions selecting questions from sub categories.';
+$string['cwrqpfsinfo'] = '<p>During the upgrade to Moodle 1.9 we will seperate question categories into
+different contexts. Some question categories and questions on your site will have to have their sharing
+status changed. This is necessary in the rare case that one or more \'random\' questions in a quiz are set up to select from a mixture of
+shared and unshared categories (as is the case on this site). This happens when a \'random\' question is set to select
+from subcategories and one or more subcategories have a different sharing status to the parent category in which
+the random question is created.</p>
+<p>The following question categories, from which \'random\' questions in parent categories select questions from, will have their sharing status changed to the same sharing status as the category with the \'random\' question in on upgrading to Moodle 1.9. The following categories will have their sharing status changed. Questions which are affected will continue to work in all existing quizzes until you remove them from these quizzes.';
+$string['cwrqpfsnoprob'] = 'No question categories in your site are affected by the \'Random questions selecting questions from sub categories\' issue.';
+$string['copy']= 'Copy from $a and change links.';
+$string['created'] = 'Created';
+$string['createdmodifiedheader'] = 'Created / Modified';
+$string['defaultfor'] = 'Default for $a';
+$string['defaultinfofor'] = 'The default category for questions shared in context \'$a\'.';
+$string['donothing']= 'Don\'t copy or move files or change links.';
+$string['editingcategory'] = 'Editing a category';
 $string['editingquestion'] = 'Editing a question';
+$string['erroraccessingcontext'] = 'Cannot access context';
+$string['errorfilecannotbecopied'] = 'Error cannot copy file $a.';
+$string['errorfilecannotbemoved'] = 'Error cannot move file $a.';
+$string['errorfileschanged'] = 'Error files linked to from questions have changed since form was displayed.';
+$string['exportcategory'] = 'Export category';
+$string['filesareasite']= 'the site files area';
+$string['filesareacourse']= 'the course files area';
+$string['filestomove']= 'Move / copy files to $a?';
+$string['fractionsnomax'] = 'One of the answers should have a score of 100%% so it is possible to get full marks for this question.';
+$string['getcategoryfromfile'] = 'Get category from file';
+$string['getcontextfromfile'] = 'Get context from file';
+$string['ignorebroken'] = 'Ignore broken links';
+$string['linkedfiledoesntexist'] = 'Linked file $a doesn\'t exist';
+$string['makechildof'] = "Make Child of '\$a'";
+$string['maketoplevelitem'] = 'Move to top level';
 $string['missingimportantcode'] = 'This question type is missing important code: $a.';
+$string['modified'] = 'Modified';
+$string['move']= 'Move from $a and change links.';
+$string['movecategory']= 'Move Category';
+$string['movelinksonly']= 'Just change where links point to, do not move or copy files.';
+$string['moveqtoanothercontext']= 'Move question to another context.';
+$string['moveq']= 'Move question(s)';
+$string['movingcategory']= 'Moving Category';
+$string['movingcategoryandfiles']= 'Are you sure you want to move category {$a->name} and all child categories to context for \"{$a->contextto}\"?<br /> We have detected {$a->urlcount} files linked from questions in {$a->fromareaname}, would you like to copy or move these to {$a->toareaname}?';
+$string['movingcategorynofiles']= 'Are you sure you want to move category \"{$a->name}\" and all child categories to context for \"{$a->contextto}\"?';
+$string['movingquestions'] = 'Moving Questions and Any Files';
+$string['movingquestionsandfiles']= 'Are you sure you want to move question(s) {$a->questions} to context for <strong>\"{$a->tocontext}\"</strong>?<br /> We have detected <strong>{$a->urlcount} files</strong> linked from these question(s) in {$a->fromareaname}, would you like to copy or move these to {$a->toareaname}?';
+$string['movingquestionsnofiles']=  'Are you sure you want to move question(s) {$a->questions} to context for <strong>\"{$a->tocontext}\"</strong>?<br /> There are <strong>no files</strong> linked from these question(s) in {$a->fromareaname}.';
+$string['needtochoosecat'] = 'You need to choose a category to move this question to or press \'cancel\'.';
+$string['nopermissionadd'] = 'You don\'t have permission to add questions here.';
+$string['noprobs'] = 'No problems found in your question database.';
 $string['notenoughdatatoeditaquestion'] = 'Neither a question id, nor a category id and question type, was specified.';
+$string['notenoughdatatomovequestions'] = 'You need to provide the question ids of questions you want to move.';
+$string['permissionedit'] = 'Edit this question';
+$string['permissionmove'] = 'Move this question';
+$string['permissionsaveasnew'] = 'Save this as a new question';
+$string['permissionto'] = 'You have permission to :';
+$string['published'] = 'published';
+$string['questionaffected'] = '<a href=\"$a->qurl\">Question \"$a->name\" ($a->qtype)</a> is in this question category but is also being used in <a href=\"$a->qurl\">quiz \"$a->quizname\"</a> in another course \"$a->coursename\".';
 $string['questionbank'] = 'Question bank';
+$string['questioncatsfor'] = 'Question Categories for \'$a\'';
 $string['questiondoesnotexist'] = 'This question does not exist';
+$string['questionuse'] = 'Use question in this activity';
+$string['shareincontext'] = 'Share in context for $a';
+$string['tofilecategory'] = 'Write category to file';
+$string['tofilecontext'] = 'Write context to file';
+$string['unknown'] = 'Unknown';
 $string['unknownquestiontype'] = 'Unknown question type: $a.';
-$string['fractionsnomax'] = 'One of the answers should have a score of 100%% so it is possible to get full marks for this question.';
-$string['makechildof'] = "Make Child of '\$a'";
-$string['maketoplevelitem'] = 'Move to top level';
+$string['unpublished'] = 'unpublished';
 ?>
index 82d879647accfd73cae3de51b0e0b1bf5736919d..ef2786b58b0c533d45f555d61a27c49c221f5100 100644 (file)
@@ -10,6 +10,18 @@ $string['action'] = 'Action';
 $string['adaptive'] = 'Adaptive mode';
 $string['addcategory'] = 'Add category';
 $string['addingquestions'] = 'This side of the page is where you manage your database of questions.  Questions are stored in categories to help you keep them organised, and can be used by any quiz in your course or even other courses if you choose to \'publish\' them. <br /><br />After you select or create a question category you will be able to create or edit questions.  You can select any of these questions to add to your quiz over on the other side of this page.';
+$string['addingcalculated'] = 'Adding a Calculated question';
+$string['addingdescription'] = 'Adding a Description';
+$string['addingessay'] = 'Adding Essay';
+$string['addingmatch'] = 'Adding a Matching Question';
+$string['addingmultianswer'] = 'Adding Embedded Answers (Cloze)';
+$string['addingmultichoice'] = 'Adding a Multiple Choice question';
+$string['addingnumerical'] = 'Adding a Numerical question';
+$string['addingquestion'] = 'Adding a question';
+$string['addingrandom'] = 'Adding a Random Question';
+$string['addingrandomsamatch'] = 'Adding a Random Short-Answer Matching question';
+$string['addingshortanswer'] = 'Adding a Short-Answer question';
+$string['addingtruefalse'] = 'Adding a True/False question';
 $string['addquestions'] = 'Add questions';
 $string['addquestionstoquiz'] = 'Add questions to current quiz';
 $string['addrandom'] = 'Add $a random questions';
@@ -404,7 +416,7 @@ $string['quiz:deleteattempts'] = 'Delete quiz attempts';
 $string['quiz:emailconfirmsubmission'] = 'Get email confirmation when submitting';
 $string['quiz:emailnotifysubmission'] = 'Get email notification of submissions';
 $string['quiz:grade'] = 'Grade quizzes manually';
-$string['quiz:ignoretimelimits'] = 'Ignores time limit on quizzes';
+$string['quiz:ignoretimelimits'] = 'Ignores time limit on quizs';
 $string['quiz:manage'] = 'Manage quizzes';
 $string['quiz:preview'] = 'Preview quizzes';
 $string['quiz:view'] = 'View quiz information';
index 5d115fff4d48812dfce417411a804c9e76acf469..d1ec05260ef704772bca3e0362225e9f5441b246 100644 (file)
@@ -3017,6 +3017,7 @@ function delete_course($courseid, $showfeedback = true) {
  */
 function remove_course_contents($courseid, $showfeedback=true) {
 
+    include_once($CFG->libdir.'/questionlib.php');
     global $CFG;
 
     $result = true;
@@ -3042,6 +3043,8 @@ function remove_course_contents($courseid, $showfeedback=true) {
                     if ($instances = get_records($modname, 'course', $course->id)) {
                         foreach ($instances as $instance) {
                             if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) {
+                                /// Delete activity context questions and question categories
+                                question_delete_activity($cm,  $showfeedback);
                                 delete_context(CONTEXT_MODULE, $cm->id);
                             }
                             if ($moddelete($instance->id)) {
@@ -3187,7 +3190,6 @@ function remove_course_contents($courseid, $showfeedback=true) {
     }
 
 /// Delete questions and question categories
-    include_once($CFG->libdir.'/questionlib.php');
     question_delete_course($course, $showfeedback);
 
 /// Delete all roles and overiddes in the course context (but keep the course context)
index f118679e15716d89dc463186b769dcf8df226e0f..a3162906e2d948f1c78d8a9f354e12323f1f33cd 100644 (file)
@@ -87,6 +87,16 @@ define('QUESTION_PREVIEW_POPUP_OPTIONS', 'scrollbars=yes,resizable=yes,width=700
  */
 define('QUESTION_ADAPTIVE', 1);
 
+/**
+ * options used in forms that move files.
+ *
+ */
+define('QUESTION_FILENOTHINGSELECTED', 0);
+define('QUESTION_FILEDONOTHING', 1);
+define('QUESTION_FILECOPY', 2);
+define('QUESTION_FILEMOVE', 3);
+define('QUESTION_FILEMOVELINKSONLY', 4);
+
 /**#@-*/
 
 /// QTYPES INITIATION //////////////////
@@ -373,7 +383,7 @@ function delete_attempt($attemptid) {
     $states = get_records('question_states', 'attempt', $attemptid);
     if ($states) {
         $stateslist = implode(',', array_keys($states));
-    
+
         // delete question-type specific data
         foreach ($QTYPES as $qtype) {
             $qtype->delete_states($stateslist);
@@ -402,7 +412,9 @@ function delete_question($questionid) {
     }
 
     // delete questiontype-specific data
-    if ($question = get_record('question', 'id', $questionid)) {
+    $question = get_record('question', 'id', $questionid);
+    question_require_capability_on($question, 'edit');
+    if ($question) {
         if (isset($QTYPES[$question->qtype])) {
             $QTYPES[$question->qtype]->delete_question($questionid);
         }
@@ -441,106 +453,88 @@ function delete_question($questionid) {
 }
 
 /**
- * All non-used question categories and their questions are deleted and
- * categories still used by other courses are moved to the site course.
+ * All question categories and their questions are deleted for this course.
  *
- * @param object $course an object representing the course
+ * @param object $mod an object representing the activity
  * @param boolean $feedback to specify if the process must output a summary of its work
  * @return boolean
  */
 function question_delete_course($course, $feedback=true) {
-
-    global $CFG, $QTYPES;
-
-    //To detect if we have created the "container category"
-    $concatid = 0;
-
-    //The "container" category we'll create if we need if
-    $contcat = new object;
-
-    //To temporary store changes performed with parents
-    $parentchanged = array();
-
     //To store feedback to be showed at the end of the process
     $feedbackdata   = array();
 
     //Cache some strings
-    $strcatcontainer=get_string('containercategorycreated', 'quiz');
-    $strcatmoved   = get_string('usedcategorymoved', 'quiz');
     $strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
+    $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
+    $categoriescourse = get_records('question_categories', 'contextid', $coursecontext->id, 'parent', 'id, parent, name');
 
-    if ($categories = get_records('question_categories', 'course', $course->id, 'parent', 'id, parent, name, course')) {
+    if ($categoriescourse) {
 
         //Sort categories following their tree (parent-child) relationships
-        $categories = sort_categories_by_tree($categories);
-
-        foreach ($categories as $cat) {
-
-            //Get the full record
-            $category = get_record('question_categories', 'id', $cat->id);
-
-            //Check if the category is being used anywhere
-            if(question_category_isused($category->id, true)) {
-                //It's being used. Cannot delete it, so:
-                //Create a container category in SITEID course if it doesn't exist
-                if (!$concatid) {
-                    $concat = new stdClass;
-                    $concat->course = SITEID;
-                    if (!isset($course->shortname)) {
-                        $course->shortname = 'id=' . $course->id;
-                    }
-                    $concat->name = get_string('savedfromdeletedcourse', 'quiz', format_string($course->shortname));
-                    $concat->info = $concat->name;
-                    $concat->publish = 1;
-                    $concat->stamp = make_unique_id_code();
-                    $concatid = insert_record('question_categories', $concat);
-
-                    //Fill feedback
-                    $feedbackdata[] = array($concat->name, $strcatcontainer);
-                }
-                //Move the category to the container category in SITEID course
-                $category->course = SITEID;
-                //Assign to container if the category hasn't parent or if the parent is wrong (not belongs to the course)
-                if (!$category->parent || !isset($categories[$category->parent])) {
-                    $category->parent = $concatid;
+        //this will make the feedback more readable
+        $categoriescourse = sort_categories_by_tree($categoriescourse);
+
+        foreach ($categoriescourse as $category) {
+
+            //Delete it completely (questions and category itself)
+            //deleting questions
+            if ($questions = get_records("question", "category", $category->id)) {
+                foreach ($questions as $question) {
+                    delete_question($question->id);
                 }
-                //If it's being used, its publish field should be 1
-                $category->publish = 1;
-                //Let's update it
-                update_record('question_categories', $category);
+                delete_records("question", "category", $category->id);
+            }
+            //delete the category
+            delete_records('question_categories', 'id', $category->id);
 
-                //Save this parent change for future use
-                $parentchanged[$category->id] = $category->parent;
+            //Fill feedback
+            $feedbackdata[] = array($category->name, $strcatdeleted);
+        }
+        //Inform about changes performed if feedback is enabled
+        if ($feedback) {
+            $table = new stdClass;
+            $table->head = array(get_string('category','quiz'), get_string('action'));
+            $table->data = $feedbackdata;
+            print_table($table);
+        }
+    }
+    return true;
+}
 
-                //Fill feedback
-                $feedbackdata[] = array($category->name, $strcatmoved);
+/**
+ * All question categories and their questions are deleted for this activity.
+ *
+ * @param object $cm the course module object representing the activity
+ * @param boolean $feedback to specify if the process must output a summary of its work
+ * @return boolean
+ */
+function question_delete_activity($cm, $feedback=true) {
+    //To store feedback to be showed at the end of the process
+    $feedbackdata   = array();
 
-            } else {
-                //Category isn't being used so:
-                //Delete it completely (questions and category itself)
-                //deleting questions
-                if ($questions = get_records("question", "category", $category->id)) {
-                    foreach ($questions as $question) {
-                        delete_question($question->id);
-                    }
-                    delete_records("question", "category", $category->id);
-                }
-                //delete the category
-                delete_records('question_categories', 'id', $category->id);
-
-                //Save this parent change for future use
-                if (!empty($category->parent)) {
-                    $parentchanged[$category->id] = $category->parent;
-                } else {
-                    $parentchanged[$category->id] = $concatid;
-                }
+    //Cache some strings
+    $strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
+    $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+    if ($categoriesmods = get_records('question_categories', 'contextid', $modcontext->id, 'parent', 'id, parent, name')){
+        //Sort categories following their tree (parent-child) relationships
+        //this will make the feedback more readable
+        $categoriesmods = sort_categories_by_tree($categoriesmods);
 
-                //Update all its child categories to re-parent them to grandparent.
-                set_field ('question_categories', 'parent', $parentchanged[$category->id], 'parent', $category->id);
+        foreach ($categoriesmods as $category) {
 
-                //Fill feedback
-                $feedbackdata[] = array($category->name, $strcatdeleted);
+            //Delete it completely (questions and category itself)
+            //deleting questions
+            if ($questions = get_records("question", "category", $category->id)) {
+                foreach ($questions as $question) {
+                    delete_question($question->id);
+                }
+                delete_records("question", "category", $category->id);
             }
+            //delete the category
+            delete_records('question_categories', 'id', $category->id);
+
+            //Fill feedback
+            $feedbackdata[] = array($category->name, $strcatdeleted);
         }
         //Inform about changes performed if feedback is enabled
         if ($feedback) {
@@ -552,23 +546,22 @@ function question_delete_course($course, $feedback=true) {
     }
     return true;
 }
-
-function questionbank_navigation_tabs(&$row, $context, $querystring) {
-    global $CFG;
-    if (has_capability('moodle/question:manage', $context)) {
-        $row[] = new tabobject('questions', "$CFG->wwwroot/question/edit.php?$querystring", get_string('questions', 'quiz'), get_string('editquestions', "quiz"));
-    }
-    
-    if (has_capability('moodle/question:managecategory', $context)) {
-        $row[] = new tabobject('categories', "$CFG->wwwroot/question/category.php?$querystring", get_string('categories', 'quiz'), get_string('editqcats', 'quiz'));
-    }
-    
-    if (has_capability('moodle/question:import', $context)) {
-        $row[] = new tabobject('import', "$CFG->wwwroot/question/import.php?$querystring", get_string('import', 'quiz'), get_string('importquestions', 'quiz'));
-    }
-    
-    if (has_capability('moodle/question:export', $context)) {
-        $row[] = new tabobject('export', "$CFG->wwwroot/question/export.php?$querystring", get_string('export', 'quiz'), get_string('exportquestions', 'quiz'));
+/**
+ * @param array $row tab objects
+ * @param question_edit_contexts $contexts object representing contexts available from this context
+ * @param string $querystring to append to urls
+ * */
+function questionbank_navigation_tabs(&$row, $contexts, $querystring) {
+    global $CFG, $QUESTION_EDITTABCAPS;
+    $tabs = array(
+            'questions' =>array("$CFG->wwwroot/question/edit.php?$querystring", get_string('questions', 'quiz'), get_string('editquestions', 'quiz')),
+            'categories' =>array("$CFG->wwwroot/question/category.php?$querystring", get_string('categories', 'quiz'), get_string('editqcats', 'quiz')),
+            'import' =>array("$CFG->wwwroot/question/import.php?$querystring", get_string('import', 'quiz'), get_string('importquestions', 'quiz')),
+            'export' =>array("$CFG->wwwroot/question/export.php?$querystring", get_string('export', 'quiz'), get_string('exportquestions', 'quiz')));
+    foreach ($tabs as $tabname => $tabparams){
+        if ($contexts->have_one_edit_tab_cap($tabname)) {
+            $row[] = new tabobject($tabname, $tabparams[0], $tabparams[1], $tabparams[2]);
+        }
     }
 }
 
@@ -712,7 +705,7 @@ function get_question_states(&$questions, $cmoptions, $attempt, $lastattemptid =
             $states[$i]->sumpenalty = 0;
             $states[$i]->manualcomment = '';
 
-            // if building on last attempt we want to preserve responses  
+            // if building on last attempt we want to preserve responses
             if (!$lastattemptid) {
               $states[$i]->responses = array('' => '');
             }
@@ -731,7 +724,7 @@ function get_question_states(&$questions, $cmoptions, $attempt, $lastattemptid =
                 question_process_responses($questions[$i], $states[$i], $action, $cmoptions, $attempt);
 
                 // Fix for Bug #5506: When each attempt is built on the last one,
-                // preserve the options from any previous attempt. 
+                // preserve the options from any previous attempt.
                 if ( isset($laststate->options) ) {
                     $states[$i]->options = $laststate->options;
                 }
@@ -1161,7 +1154,7 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
     if (!question_isgradingevent($action->event)) {
         // Grade the response but don't update the overall grade
         $QTYPES[$question->qtype]->grade_responses($question, $state, $cmoptions);
-        
+
         // Temporary hack because question types are not given enough control over what is going
         // on. Used by Opaque questions.
         // TODO fix this code properly.
@@ -1173,7 +1166,7 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
                 // update the attempt grade
                 $attempt->sumgrades -= (float)$state->last_graded->grade;
                 $attempt->sumgrades += (float)$state->grade;
-    
+
                 // and update the last_graded field.
                 unset($state->last_graded);
                 $state->last_graded = clone($state);
@@ -1183,7 +1176,7 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
             // Don't allow the processing to change the event type
             $state->event = $action->event;
         }
-        
+
     } else { // grading event
 
         // Unless the attempt is closing, we want to work out if the current responses
@@ -1248,7 +1241,7 @@ function question_isgradingevent($event) {
 function question_apply_penalty_and_timelimit(&$question, &$state, $attempt, $cmoptions) {
     // TODO. Quiz dependancy. The fact that the attempt that is passed in here
     // is from quiz_attempts, and we use things like $cmoptions->timelimit.
-    
+
     // deal with penalty
     if ($cmoptions->penaltyscheme) {
         $state->grade = $state->raw_grade - $state->sumpenalty;
@@ -1589,7 +1582,7 @@ function sort_categories_by_tree(&$categories, $id = 0, $level = 1) {
  * @param int $depth the indent depth. Used in recursive calls.
  * @return array a new array of categories, in the right order for the tree.
  */
-function flatten_category_tree(&$categories, $id, $depth = 0) {
+function flatten_category_tree(&$categories, $id, $depth = 0, $nochildrenof = -1) {
 
     // Indent the name of this category.
     $newcategories = array();
@@ -1598,7 +1591,9 @@ function flatten_category_tree(&$categories, $id, $depth = 0) {
 
     // Recursively indent the children.
     foreach ($categories[$id]->childids as $childid) {
-        $newcategories = $newcategories + flatten_category_tree($categories, $childid, $depth + 1);
+        if ($childid != $nochildrenof){
+            $newcategories = $newcategories + flatten_category_tree($categories, $childid, $depth + 1, $nochildrenof);
+        }
     }
 
     // Remove the childids array that were temporarily added.
@@ -1613,7 +1608,7 @@ function flatten_category_tree(&$categories, $id, $depth = 0) {
  * @param array $categories An array of category objects, for example from the.
  * @return array The formatted list of categories.
  */
-function add_indented_names($categories) {
+function add_indented_names($categories, $nochildrenof = -1) {
 
     // Add an array to each category to hold the child category ids. This array will be removed
     // again by flatten_category_tree(). It should not be used outside these two functions.
@@ -1636,7 +1631,7 @@ function add_indented_names($categories) {
     // Flatten the tree to and add the indents.
     $newcategories = array();
     foreach ($toplevelcategoryids as $id) {
-        $newcategories = $newcategories + flatten_category_tree($categories, $id);
+        $newcategories = $newcategories + flatten_category_tree($categories, $id, 0, $nochildrenof);
     }
 
     return $newcategories;
@@ -1653,70 +1648,102 @@ function add_indented_names($categories) {
  * @param integer $only_editable if true, exclude categories this user is not allowed to edit.
  * @param integer $selected optionally, the id of a category to be selected by default in the dropdown.
  */
-function question_category_select_menu($courseid, $published = false, $only_editable = false, $selected = "") {
-    $categoriesarray = question_category_options($courseid, $published, $only_editable);
+function question_category_select_menu($contexts, $top = false, $currentcat = 0, $selected = "", $nochildrenof = -1) {
+    $categoriesarray = question_category_options($contexts, $top, $currentcat, false, $nochildrenof);
     if ($selected) {
         $nothing = '';
     } else {
         $nothing = 'choose';
     }
-    choose_from_menu($categoriesarray, 'category', $selected, $nothing);
+    choose_from_menu_nested($categoriesarray, 'category', $selected, $nothing);
 }
 
 /**
- * Output an array of question categories.
+ * Get all the category objects, including a count of the number of questions in that category,
+ * for all the categories in the lists $contexts.
  *
- * Categories from this course and (optionally) published categories from other courses
- * are included. Optionally, only categories the current user may edit can be included.
- *
- * @param integer $courseid the id of the course to get the categories for.
- * @param integer $published if true, include publised categories from other courses.
- * @param integer $only_editable if true, exclude categories this user is not allowed to edit.
- * @return array The list of categories.
+ * @param mixed $contexts either a single contextid, or a comma-separated list of context ids.
+ * @param string $sortorder used as the ORDER BY clause in the select statement.
+ * @return array of category objects.
  */
-function question_category_options($courseid, $published = false, $only_editable = false) {
+function get_categories_for_contexts($contexts, $sortorder = 'parent, sortorder, name ASC') {
     global $CFG;
+    return get_records_sql("
+            SELECT *, (SELECT count(1) FROM {$CFG->prefix}question q
+                    WHERE c.id = q.category AND q.hidden='0' AND q.parent='0') as questioncount
+            FROM {$CFG->prefix}question_categories as c
+            WHERE c.contextid IN ($contexts)
+            ORDER BY $sortorder");
+}
 
-    // get sql fragment for published
-    $publishsql="";
-    if ($published) {
-        $publishsql = " OR publish = 1";
+/**
+ * Output an array of question categories.
+ */
+function question_category_options($contexts, $top = false, $currentcat = 0, $popupform = false, $nochildrenof = -1) {
+    global $CFG;
+    $pcontexts = array();
+    foreach($contexts as $context){
+        $pcontexts[] = $context->id;
     }
+    $contextslist = join($pcontexts, ', ');
+
+    $categories = get_categories_for_contexts($contextslist);
 
-    $categories = get_records_sql("
-            SELECT cat.*, c.shortname AS coursename
-            FROM {$CFG->prefix}question_categories cat, {$CFG->prefix}course c
-            WHERE c.id = cat.course AND (cat.course = $courseid $publishsql)
-            ORDER BY (CASE WHEN cat.course = $courseid THEN 0 ELSE 1 END), cat.parent, cat.sortorder, cat.name ASC");
-    $categories = add_indented_names($categories);
+    $categories = question_add_context_in_key($categories);
+
+    if ($top){
+        $categories = question_add_tops($categories, $pcontexts);
+    }
+    $categories = add_indented_names($categories, $nochildrenof);
 
+    //sort cats out into different contexts
     $categoriesarray = array();
-    foreach ($categories as $category) {
-        $cid = $category->id;
-        $cname = question_category_coursename($category, $courseid);
-        if ((!$only_editable) || has_capability('moodle/question:managecategory', get_context_instance(CONTEXT_COURSE, $category->course))) {
-            $categoriesarray[$cid] = $cname;
+    foreach ($pcontexts as $pcontext){
+        $contextstring = print_context_name(get_context_instance_by_id($pcontext), true, true);
+        foreach ($categories as $category) {
+            if ($category->contextid == $pcontext){
+                $cid = $category->id;
+                if ($currentcat!= $cid || $currentcat==0) {
+                    $countstring = (!empty($category->questioncount))?"($category->questioncount)":'';
+                    $categoriesarray[$contextstring][$cid] = $category->indentedname.$countstring;
+                }
+            }
         }
     }
-    return $categoriesarray;
+    if ($popupform){
+        $popupcats = array();
+        foreach ($categoriesarray as $contextstring => $optgroup){
+            $popupcats[] = '--'.$contextstring;
+            $popupcats = array_merge($popupcats, $optgroup);
+            $popupcats[] = '--';
+        }
+        return $popupcats;
+    } else {
+        return $categoriesarray;
+    }
 }
 
-/**
- * If the category is not from this course, and it is a published category,
- * then return the course category name with the course shortname appended in
- * brackets. Otherwise, just return the category name.
- */
-function question_category_coursename($category, $courseid = 0) {
-    $cname = (isset($category->indentedname)) ? $category->indentedname : $category->name;
-    if ($category->course != $courseid && $category->publish) {
-        if (!empty($category->coursename)) {
-            $coursename = $category->coursename;
-        } else {
-            $coursename = get_field('course', 'shortname', 'id', $category->course);
-        }
-        $cname .= " ($coursename)";
+function question_add_context_in_key($categories){
+    $newcatarray = array();
+    foreach ($categories as $id => $category) {
+        $category->parent = "$category->parent,$category->contextid";
+        $category->id = "$category->id,$category->contextid";
+        $newcatarray["$id,$category->contextid"] = $category;
     }
-    return $cname;
+    return $newcatarray;
+}
+function question_add_tops($categories, $pcontexts){
+    $topcats = array();
+    foreach ($pcontexts as $context){
+        $newcat = new object();
+        $newcat->id = "0,$context";
+        $newcat->name = get_string('top');
+        $newcat->parent = -1;
+        $newcat->contextid = $context;
+        $topcats["0,$context"] = $newcat;
+    }
+    //put topcats in at beginning of array - they'll be sorted into different contexts later.
+    return array_merge($topcats, $categories);
 }
 
 /**
@@ -1733,67 +1760,8 @@ function question_categorylist($categoryid) {
     return $categorylist;
 }
 
-/**
- * find and/or create the category described by a delimited list
- * e.g. tom/dick/harry
- * @param string catpath delimited category path
- * @param string delimiter path delimiting character
- * @param int courseid course to search for categories
- * @return mixed category object or null if fails
- */
-function create_category_path( $catpath, $delimiter='/', $courseid=0 ) {
-    $catpath = clean_param( $catpath,PARAM_PATH );
-    $catnames = explode( $delimiter, $catpath );
-    $parent = 0;
-    $category = null;
-    foreach ($catnames as $catname) {
-        if ($category = get_record( 'question_categories', 'name', $catname, 'course', $courseid, 'parent', $parent )) {
-            $parent = $category->id;
-        }
-        else {
-            // create the new category
-            $category = new object;
-            $category->course = $courseid;
-            $category->name = $catname;
-            $category->info = '';
-            $category->publish = false;
-            $category->parent = $parent;
-            $category->sortorder = 999;
-            $category->stamp = make_unique_id_code();
-            if (!($id = insert_record( 'question_categories', $category ))) {
-                error( "cannot create new category - $catname" );
-            }
-            $category->id = $id;
-            $parent = $id;
-        }
-    }
-    return $category;
-}
 
-/**
- * get the category as a path (e.g., tom/dick/harry)
- * @param int id the id of the most nested catgory
- * @param string delimiter the delimiter you want
- * @return string the path
- */
-function get_category_path( $id, $delimiter='/' ) {
-    $path = '';    
-    do {
-        if (!$category = get_record( 'question_categories','id',$id )) {
-            print_error( "Error reading category record - $id" );    
-        }
-        $name = $category->name;
-        $id = $category->parent;
-        if (!empty($path)) {
-            $path = "{$name}{$delimiter}{$path}";
-        }
-        else {
-            $path = $name;
-        }    
-    } while ($id != 0);        
-         
-    return $path;
-}
+
 
 //===========================
 // Import/Export Functions
@@ -1887,5 +1855,213 @@ function default_export_filename($course,$category) {
 
     return $export_name;
 }
+class context_to_string_translator{
+    /**
+     * @var array used to translate between contextids and strings for this context.
+     */
+    var $contexttostringarray = array();
+
+    function context_to_string_translator($contexts){
+        $this->generate_context_to_string_array($contexts);
+    }
+
+    function context_to_string($contextid){
+        return $this->contexttostringarray[$contextid];
+    }
+
+    function string_to_context($contextname){
+        $contextid = array_search($contextname, $this->contexttostringarray);
+        return $contextid;
+    }
+
+    function generate_context_to_string_array($contexts){
+        if (!$this->contexttostringarray){
+            $catno = 1;
+            foreach ($contexts as $context){
+                switch  ($context->contextlevel){
+                    case CONTEXT_MODULE :
+                        $contextstring = 'module';
+                        break;
+                    case CONTEXT_COURSE :
+                        $contextstring = 'course';
+                        break;
+                    case CONTEXT_COURSECAT :
+                        $contextstring = "cat$catno";
+                        $catno++;
+                        break;
+                    case CONTEXT_SYSTEM :
+                        $contextstring = 'system';
+                        break;
+                }
+                $this->contexttostringarray[$context->id] = $contextstring;
+            }
+        }
+    }
+
+}
 
+
+/**
+ * Check capability on category
+ * @param mixed $question object or id
+ * @param string $cap 'add', 'edit', 'view', 'use', 'move'
+ * @param integer $cachecat useful to cache all question records in a category
+ * @return boolean this user has the capability $cap for this question $question?
+ */
+function question_has_capability_on($question, $cap, $cachecat = -1){
+    global $USER;
+    // these are capabilities on existing questions capabilties are
+    //set per category. Each of these has a mine and all version. Append 'mine' and 'all'
+    $question_questioncaps = array('edit', 'view', 'use', 'move');
+
+    static $questions = array();
+    static $categories = array();
+    static $cachedcat = array();
+    if ($cachecat != -1 && (array_search($cachecat, $cachedcat)!==FALSE)){
+        $questions += get_records('question', 'category', $cachecat);
+        $cachedcat[] = $cachecat;
+    }
+    if (!is_object($question)){
+        if (!isset($questions[$question])){
+            if (!$questions[$question] = get_record('question', 'id', $question)){
+                print_error('invalidcategory', 'quiz');
+            }
+        }
+        $question = $questions[$question];
+    }
+    if (!isset($categories[$question->category])){
+        if (!$categories[$question->category] = get_record('question_categories', 'id', $question->category)){
+            print_error('invalidcategory', 'quiz');
+        }
+    }
+    $category = $categories[$question->category];
+
+    if (array_search($cap, $question_questioncaps)!== FALSE){
+        if (!has_capability('moodle/question:'.$cap.'all', get_context_instance_by_id($category->contextid))){
+            if ($question->createdby == $USER->id){
+                return has_capability('moodle/question:'.$cap.'mine', get_context_instance_by_id($category->contextid));
+            } else {
+                return false;
+            }
+        } else {
+            return true;
+        }
+    } else {
+        return has_capability('moodle/question:'.$cap, get_context_instance_by_id($category->contextid));
+    }
+
+}
+
+/**
+ * Require capability on question.
+ */
+function question_require_capability_on($question, $cap){
+    if (!question_has_capability_on($question, $cap)){
+        print_error('nopermissions', '', '', $cap);
+    }
+    return true;
+}
+
+function question_file_links_base_url($courseid){
+    global $CFG;
+    $baseurl = preg_quote("$CFG->wwwroot/file.php", '!');
+    $baseurl .= '('.preg_quote('?file=', '!').')?';//may or may not
+                                     //be using slasharguments, accept either
+    $baseurl .= "/$courseid/";//course directory
+    return $baseurl;
+}
+
+/*
+ * Find all course / site files linked to in a piece of html.
+ * @param string html the html to search
+ * @param int course search for files for courseid course or set to siteid for
+ *              finding site files.
+ * @return array files with keys being files.
+ */
+function question_find_file_links_from_html($html, $courseid){
+    global $CFG;
+    $baseurl = question_file_links_base_url($courseid);
+    $searchfor = '!'.
+                   '(<\s*(a|img)\s[^>]*(href|src)\s*=\s*")'.$baseurl.'([^"]*)"'.
+                   '|'.
+                   '(<\s*(a|img)\s[^>]*(href|src)\s*=\s*\')'.$baseurl.'([^\']*)\''.
+                  '!i';
+    $matches = array();
+    $no = preg_match_all($searchfor, $html, $matches);
+    if ($no){
+        $rawurls = array_filter(array_merge($matches[5], $matches[10]));//array_filter removes empty elements
+        //remove any links that point somewhere they shouldn't
+        foreach (array_keys($rawurls) as $rawurlkey){
+            if (!$cleanedurl = question_url_check($rawurls[$rawurlkey])){
+                unset($rawurls[$rawurlkey]);
+            } else {
+                $rawurls[$rawurlkey] = $cleanedurl;
+            }
+
+        }
+        $urls = array_flip($rawurls);// array_flip removes duplicate files
+                                            // and when we merge arrays will continue to automatically remove duplicates
+    } else {
+        $urls = array();
+    }
+    return $urls;
+}
+/*
+ * Check that url doesn't point anywhere it shouldn't
+ *
+ * @param $url string relative url within course files directory
+ * @return mixed boolean false if not OK or cleaned URL as string if OK
+ */
+function question_url_check($url){
+    global $CFG;
+    if ((substr(strtolower($url), 0, strlen($CFG->moddata)) == strtolower($CFG->moddata)) ||
+            (substr(strtolower($url), 0, 10) == 'backupdata')){
+        return false;
+    } else {
+        return clean_param($url, PARAM_PATH);
+    }
+}
+
+/*
+ * Find all course / site files linked to in a piece of html.
+ * @param string html the html to search
+ * @param int course search for files for courseid course or set to siteid for
+ *              finding site files.
+ * @return array files with keys being files.
+ */
+function question_replace_file_links_in_html($html, $fromcourseid, $tocourseid, $url, $destination, &$changed){
+    global $CFG;
+    if ($CFG->slasharguments) {        // Use this method if possible for better caching
+        $tourl = "$CFG->wwwroot/file.php/$tocourseid/$destination";
+
+    } else {
+        $tourl = "$CFG->wwwroot/file.php?file=/$tocourseid/$destination";
+    }
+    $fromurl = question_file_links_base_url($fromcourseid).preg_quote($url, '!');
+    $searchfor = array('!(<\s*(a|img)\s[^>]*(href|src)\s*=\s*")'.$fromurl.'(")!i',
+                   '!(<\s*(a|img)\s[^>]*(href|src)\s*=\s*\')'.$fromurl.'(\')!i');
+    $newhtml = preg_replace($searchfor, '\\1'.$tourl.'\\5', $html);
+    if ($newhtml != $html){
+        $changed = true;
+    }
+    return $newhtml;
+}
+
+function get_filesdir_from_context($context){
+    switch ($context->contextlevel){
+        case CONTEXT_COURSE :
+            $courseid = $context->instanceid;
+            break;
+        case CONTEXT_MODULE :
+            $courseid = get_field('course_modules', 'course', 'id', $context->instanceid);
+            break;
+        case CONTEXT_COURSECAT :
+        case CONTEXT_SYSTEM :
+            $courseid = SITEID;
+            break;
+        default :
+            error('Unsupported contextlevel in category record!');
+    }
+    return $courseid;
+}
 ?>