|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00030 abstract class backup_helper { 00031 00035 static public function check_and_create_backup_dir($backupid) { 00036 global $CFG; 00037 if (!check_dir_exists($CFG->tempdir . '/backup/' . $backupid, true, true)) { 00038 throw new backup_helper_exception('cannot_create_backup_temp_dir'); 00039 } 00040 } 00041 00045 static public function clear_backup_dir($backupid) { 00046 global $CFG; 00047 if (!self::delete_dir_contents($CFG->tempdir . '/backup/' . $backupid)) { 00048 throw new backup_helper_exception('cannot_empty_backup_temp_dir'); 00049 } 00050 return true; 00051 } 00052 00056 static public function delete_backup_dir($backupid) { 00057 global $CFG; 00058 self::clear_backup_dir($backupid); 00059 return rmdir($CFG->tempdir . '/backup/' . $backupid); 00060 } 00061 00067 static public function delete_dir_contents($dir, $excludeddir='') { 00068 global $CFG; 00069 00070 if (!is_dir($dir)) { 00071 // if we've been given a directory that doesn't exist yet, return true. 00072 // this happens when we're trying to clear out a course that has only just 00073 // been created. 00074 return true; 00075 } 00076 $slash = "/"; 00077 00078 // Create arrays to store files and directories 00079 $dir_files = array(); 00080 $dir_subdirs = array(); 00081 00082 // Make sure we can delete it 00083 chmod($dir, $CFG->directorypermissions); 00084 00085 if ((($handle = opendir($dir))) == false) { 00086 // The directory could not be opened 00087 return false; 00088 } 00089 00090 // Loop through all directory entries, and construct two temporary arrays containing files and sub directories 00091 while (false !== ($entry = readdir($handle))) { 00092 if (is_dir($dir. $slash .$entry) && $entry != ".." && $entry != "." && $entry != $excludeddir) { 00093 $dir_subdirs[] = $dir. $slash .$entry; 00094 00095 } else if ($entry != ".." && $entry != "." && $entry != $excludeddir) { 00096 $dir_files[] = $dir. $slash .$entry; 00097 } 00098 } 00099 00100 // Delete all files in the curent directory return false and halt if a file cannot be removed 00101 for ($i=0; $i<count($dir_files); $i++) { 00102 chmod($dir_files[$i], $CFG->directorypermissions); 00103 if (((unlink($dir_files[$i]))) == false) { 00104 return false; 00105 } 00106 } 00107 00108 // Empty sub directories and then remove the directory 00109 for ($i=0; $i<count($dir_subdirs); $i++) { 00110 chmod($dir_subdirs[$i], $CFG->directorypermissions); 00111 if (self::delete_dir_contents($dir_subdirs[$i]) == false) { 00112 return false; 00113 } else { 00114 if (remove_dir($dir_subdirs[$i]) == false) { 00115 return false; 00116 } 00117 } 00118 } 00119 00120 // Close directory 00121 closedir($handle); 00122 00123 // Success, every thing is gone return true 00124 return true; 00125 } 00126 00130 static public function delete_old_backup_dirs($deletefrom) { 00131 global $CFG; 00132 00133 $status = true; 00134 // Get files and directories in the temp backup dir witout descend 00135 $list = get_directory_list($CFG->tempdir . '/backup', '', false, true, true); 00136 foreach ($list as $file) { 00137 $file_path = $CFG->tempdir . '/backup/' . $file; 00138 $moddate = filemtime($file_path); 00139 if ($status && $moddate < $deletefrom) { 00140 //If directory, recurse 00141 if (is_dir($file_path)) { 00142 // $file is really the backupid 00143 $status = self::delete_backup_dir($file); 00144 //If file 00145 } else { 00146 unlink($file_path); 00147 } 00148 } 00149 } 00150 if (!$status) { 00151 throw new backup_helper_exception('problem_deleting_old_backup_temp_dirs'); 00152 } 00153 } 00154 00161 static public function log($message, $level, $a, $depth, $display, $logger) { 00162 // Send to standard loggers 00163 $logmessage = $message; 00164 $options = empty($depth) ? array() : array('depth' => $depth); 00165 if (!empty($a)) { 00166 $logmessage = $logmessage . ' ' . implode(', ', (array)$a); 00167 } 00168 $logger->process($logmessage, $level, $options); 00169 00170 // If $display specified, send translated string to output_controller 00171 if ($display) { 00172 output_controller::get_instance()->output($message, 'backup', $a, $depth); 00173 } 00174 } 00175 00180 static public function store_backup_file($backupid, $filepath) { 00181 00182 // First of all, get some information from the backup_controller to help us decide 00183 list($dinfo, $cinfo, $sinfo) = backup_controller_dbops::get_moodle_backup_information($backupid); 00184 00185 // Extract useful information to decide 00186 $hasusers = (bool)$sinfo['users']->value; // Backup has users 00187 $isannon = (bool)$sinfo['anonymize']->value; // Backup is anonymised 00188 $filename = $sinfo['filename']->value; // Backup filename 00189 $backupmode= $dinfo[0]->mode; // Backup mode backup::MODE_GENERAL/IMPORT/HUB 00190 $backuptype= $dinfo[0]->type; // Backup type backup::TYPE_1ACTIVITY/SECTION/COURSE 00191 $userid = $dinfo[0]->userid; // User->id executing the backup 00192 $id = $dinfo[0]->id; // Id of activity/section/course (depends of type) 00193 $courseid = $dinfo[0]->courseid; // Id of the course 00194 00195 // Quick hack. If for any reason, filename is blank, fix it here. 00196 // TODO: This hack will be out once MDL-22142 - P26 gets fixed 00197 if (empty($filename)) { 00198 $filename = backup_plan_dbops::get_default_backup_filename('moodle2', $backuptype, $id, $hasusers, $isannon); 00199 } 00200 00201 // Backups of type IMPORT aren't stored ever 00202 if ($backupmode == backup::MODE_IMPORT) { 00203 return false; 00204 } 00205 00206 // Calculate file storage options of id being backup 00207 $ctxid = 0; 00208 $filearea = ''; 00209 $component = ''; 00210 $itemid = 0; 00211 switch ($backuptype) { 00212 case backup::TYPE_1ACTIVITY: 00213 $ctxid = get_context_instance(CONTEXT_MODULE, $id)->id; 00214 $component = 'backup'; 00215 $filearea = 'activity'; 00216 $itemid = 0; 00217 break; 00218 case backup::TYPE_1SECTION: 00219 $ctxid = get_context_instance(CONTEXT_COURSE, $courseid)->id; 00220 $component = 'backup'; 00221 $filearea = 'section'; 00222 $itemid = $id; 00223 break; 00224 case backup::TYPE_1COURSE: 00225 $ctxid = get_context_instance(CONTEXT_COURSE, $courseid)->id; 00226 $component = 'backup'; 00227 $filearea = 'course'; 00228 $itemid = 0; 00229 break; 00230 } 00231 00232 if ($backupmode == backup::MODE_AUTOMATED) { 00233 // Automated backups have there own special area! 00234 $filearea = 'automated'; 00235 } 00236 00237 // Backups of type HUB (by definition never have user info) 00238 // are sent to user's "user_tohub" file area. The upload process 00239 // will be responsible for cleaning that filearea once finished 00240 if ($backupmode == backup::MODE_HUB) { 00241 $ctxid = get_context_instance(CONTEXT_USER, $userid)->id; 00242 $component = 'user'; 00243 $filearea = 'tohub'; 00244 $itemid = 0; 00245 } 00246 00247 // Backups without user info or with the anonymise functionality 00248 // enabled are sent to user's "user_backup" 00249 // file area. Maintenance of such area is responsibility of 00250 // the user via corresponding file manager frontend 00251 if ($backupmode == backup::MODE_GENERAL && (!$hasusers || $isannon)) { 00252 $ctxid = get_context_instance(CONTEXT_USER, $userid)->id; 00253 $component = 'user'; 00254 $filearea = 'backup'; 00255 $itemid = 0; 00256 } 00257 00258 // Let's send the file to file storage, everything already defined 00259 $fs = get_file_storage(); 00260 $fr = array( 00261 'contextid' => $ctxid, 00262 'component' => $component, 00263 'filearea' => $filearea, 00264 'itemid' => $itemid, 00265 'filepath' => '/', 00266 'filename' => $filename, 00267 'userid' => $userid, 00268 'timecreated' => time(), 00269 'timemodified'=> time()); 00270 // If file already exists, delete if before 00271 // creating it again. This is BC behaviour - copy() 00272 // overwrites by default 00273 if ($fs->file_exists($fr['contextid'], $fr['component'], $fr['filearea'], $fr['itemid'], $fr['filepath'], $fr['filename'])) { 00274 $pathnamehash = $fs->get_pathname_hash($fr['contextid'], $fr['component'], $fr['filearea'], $fr['itemid'], $fr['filepath'], $fr['filename']); 00275 $sf = $fs->get_file_by_hash($pathnamehash); 00276 $sf->delete(); 00277 } 00278 return $fs->create_file_from_pathname($fr, $filepath); 00279 } 00280 00287 public static function is_sqlparam($value) { 00288 return array('sqlparam' => $value); 00289 } 00290 00295 public static function get_inforef_itemnames() { 00296 return array('user', 'grouping', 'group', 'role', 'file', 'scale', 'outcome', 'grade_item', 'question_category'); 00297 } 00298 } 00299 00300 /* 00301 * Exception class used by all the @helper stuff 00302 */ 00303 class backup_helper_exception extends backup_exception { 00304 00305 public function __construct($errorcode, $a=NULL, $debuginfo=null) { 00306 parent::__construct($errorcode, $a, $debuginfo); 00307 } 00308 }