コード例 #1
0
 /**
  * Removes excess backups from the external system and the local file system.
  *
  * The number of backups keep comes from $config->backup_auto_keep.
  *
  * @param stdClass $course object
  * @return bool
  */
 public static function remove_excess_backups($course)
 {
     $config = get_config('backup');
     $keep = (int) $config->backup_auto_keep;
     $storage = $config->backup_auto_storage;
     $dir = $config->backup_auto_destination;
     if ($keep == 0) {
         // Means keep all backup files.
         return true;
     }
     if (!file_exists($dir) || !is_dir($dir) || !is_writable($dir)) {
         $dir = null;
     }
     // Clean up excess backups in the course backup filearea.
     if ($storage == 0 || $storage == 2) {
         $fs = get_file_storage();
         $context = context_course::instance($course->id);
         $component = 'backup';
         $filearea = 'automated';
         $itemid = 0;
         $files = array();
         // Store all the matching files into timemodified => stored_file array.
         foreach ($fs->get_area_files($context->id, $component, $filearea, $itemid) as $file) {
             $files[$file->get_timemodified()] = $file;
         }
         if (count($files) <= $keep) {
             // There are less matching files than the desired number to keep there is nothing to clean up.
             return 0;
         }
         // Sort by keys descending (newer to older filemodified).
         krsort($files);
         $remove = array_splice($files, $keep);
         foreach ($remove as $file) {
             $file->delete();
         }
         //mtrace('Removed '.count($remove).' old backup file(s) from the automated filearea');
     }
     // Clean up excess backups in the specified external directory.
     if (!empty($dir) && ($storage == 1 || $storage == 2)) {
         // Calculate backup filename regex, ignoring the date/time/info parts that can be
         // variable, depending of languages, formats and automated backup settings.
         $filename = backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' . $course->id . '-';
         $regex = '#' . preg_quote($filename, '#') . '.*\\.mbz$#';
         // Store all the matching files into filename => timemodified array.
         $files = array();
         foreach (scandir($dir) as $file) {
             // Skip files not matching the naming convention.
             if (!preg_match($regex, $file, $matches)) {
                 continue;
             }
             // Read the information contained in the backup itself.
             try {
                 $bcinfo = backup_general_helper::get_backup_information_from_mbz($dir . '/' . $file);
             } catch (backup_helper_exception $e) {
                 mtrace('Error: ' . $file . ' does not appear to be a valid backup (' . $e->errorcode . ')');
                 continue;
             }
             // Make sure this backup concerns the course and site we are looking for.
             if ($bcinfo->format === backup::FORMAT_MOODLE && $bcinfo->type === backup::TYPE_1COURSE && $bcinfo->original_course_id == $course->id && backup_general_helper::backup_is_samesite($bcinfo)) {
                 $files[$file] = $bcinfo->backup_date;
             }
         }
         if (count($files) <= $keep) {
             // There are less matching files than the desired number to keep there is nothing to clean up.
             return 0;
         }
         // Sort by values descending (newer to older filemodified).
         arsort($files);
         $remove = array_splice($files, $keep);
         foreach (array_keys($remove) as $file) {
             unlink($dir . '/' . $file);
         }
         //mtrace('Removed '.count($remove).' old backup file(s) from external directory');
     }
     return true;
 }
コード例 #2
0
ファイル: upgradelib.php プロジェクト: jtibbetts/moodle
/**
 * Rename old backup files to current backup files.
 *
 * When added the setting 'backup_shortname' (MDL-28657) the backup file names did not contain the id of the course.
 * Further we fixed that behaviour by forcing the id to be always present in the file name (MDL-33812).
 * This function will explore the backup directory and attempt to rename the previously created files to include
 * the id in the name. Doing this will put them back in the process of deleting the excess backups for each course.
 *
 * This function manually recreates the file name, instead of using
 * {@link backup_plan_dbops::get_default_backup_filename()}, use it carefully if you're using it outside of the
 * usual upgrade process.
 *
 * @see backup_cron_automated_helper::remove_excess_backups()
 * @link http://tracker.moodle.org/browse/MDL-35116
 * @return void
 * @since Moodle 2.4
 */
function upgrade_rename_old_backup_files_using_shortname() {
    global $CFG;
    $dir = get_config('backup', 'backup_auto_destination');
    $useshortname = get_config('backup', 'backup_shortname');
    if (empty($dir) || !is_dir($dir) || !is_writable($dir)) {
        return;
    }

    require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php');
    $backupword = str_replace(' ', '_', core_text::strtolower(get_string('backupfilename')));
    $backupword = trim(clean_filename($backupword), '_');
    $filename = $backupword . '-' . backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-';
    $regex = '#^'.preg_quote($filename, '#').'.*\.mbz$#';
    $thirtyapril = strtotime('30 April 2012 00:00');

    // Reading the directory.
    if (!$files = scandir($dir)) {
        return;
    }
    foreach ($files as $file) {
        // Skip directories and files which do not start with the common prefix.
        // This avoids working on files which are not related to this issue.
        if (!is_file($dir . '/' . $file) || !preg_match($regex, $file)) {
            continue;
        }

        // Extract the information from the XML file.
        try {
            $bcinfo = backup_general_helper::get_backup_information_from_mbz($dir . '/' . $file);
        } catch (backup_helper_exception $e) {
            // Some error while retrieving the backup informations, skipping...
            continue;
        }

        // Make sure this a course backup.
        if ($bcinfo->format !== backup::FORMAT_MOODLE || $bcinfo->type !== backup::TYPE_1COURSE) {
            continue;
        }

        // Skip the backups created before the short name option was initially introduced (MDL-28657).
        // This was integrated on the 2nd of May 2012. Let's play safe with timezone and use the 30th of April.
        if ($bcinfo->backup_date < $thirtyapril) {
            continue;
        }

        // Let's check if the file name contains the ID where it is supposed to be, if it is the case then
        // we will skip the file. Of course it could happen that the course ID is identical to the course short name
        // even though really unlikely, but then renaming this file is not necessary. If the ID is not found in the
        // file name then it was probably the short name which was used.
        $idfilename = $filename . $bcinfo->original_course_id . '-';
        $idregex = '#^'.preg_quote($idfilename, '#').'.*\.mbz$#';
        if (preg_match($idregex, $file)) {
            continue;
        }

        // Generating the file name manually. We do not use backup_plan_dbops::get_default_backup_filename() because
        // it will query the database to get some course information, and the course could not exist any more.
        $newname = $filename . $bcinfo->original_course_id . '-';
        if ($useshortname) {
            $shortname = str_replace(' ', '_', $bcinfo->original_course_shortname);
            $shortname = core_text::strtolower(trim(clean_filename($shortname), '_'));
            $newname .= $shortname . '-';
        }

        $backupdateformat = str_replace(' ', '_', get_string('backupnameformat', 'langconfig'));
        $date = userdate($bcinfo->backup_date, $backupdateformat, 99, false);
        $date = core_text::strtolower(trim(clean_filename($date), '_'));
        $newname .= $date;

        if (isset($bcinfo->root_settings['users']) && !$bcinfo->root_settings['users']) {
            $newname .= '-nu';
        } else if (isset($bcinfo->root_settings['anonymize']) && $bcinfo->root_settings['anonymize']) {
            $newname .= '-an';
        }
        $newname .= '.mbz';

        // Final check before attempting the renaming.
        if ($newname == $file || file_exists($dir . '/' . $newname)) {
            continue;
        }
        @rename($dir . '/' . $file, $dir . '/' . $newname);
    }
}
コード例 #3
0
 protected function define_execution()
 {
     // Get basepath
     $basepath = $this->get_basepath();
     // Get the list of files in directory
     $filestemp = get_directory_list($basepath, '', false, true, true);
     $files = array();
     foreach ($filestemp as $file) {
         // Add zip paths and fs paths to all them
         $files[$file] = $basepath . '/' . $file;
     }
     // Add the log file if exists
     $logfilepath = $basepath . '.log';
     if (file_exists($logfilepath)) {
         $files['moodle_backup.log'] = $logfilepath;
     }
     // Calculate the zip fullpath (in OS temp area it's always backup.mbz)
     $zipfile = $basepath . '/backup.mbz';
     // Get the zip packer
     $zippacker = get_file_packer('application/vnd.moodle.backup');
     // Track overall progress for the 2 long-running steps (archive to
     // pathname, get backup information).
     $reporter = $this->task->get_progress();
     $reporter->start_progress('backup_zip_contents', 2);
     // Zip files
     $result = $zippacker->archive_to_pathname($files, $zipfile, true, $this);
     // If any sub-progress happened, end it.
     if ($this->startedprogress) {
         $this->task->get_progress()->end_progress();
         $this->startedprogress = false;
     } else {
         // No progress was reported, manually move it on to the next overall task.
         $reporter->progress(1);
     }
     // Something went wrong.
     if ($result === false) {
         @unlink($zipfile);
         throw new backup_step_exception('error_zip_packing', '', 'An error was encountered while trying to generate backup zip');
     }
     // Read to make sure it is a valid backup. Refer MDL-37877 . Delete it, if found not to be valid.
     try {
         backup_general_helper::get_backup_information_from_mbz($zipfile, $this);
     } catch (backup_helper_exception $e) {
         @unlink($zipfile);
         throw new backup_step_exception('error_zip_packing', '', $e->debuginfo);
     }
     // If any sub-progress happened, end it.
     if ($this->startedprogress) {
         $this->task->get_progress()->end_progress();
         $this->startedprogress = false;
     } else {
         $reporter->progress(2);
     }
     $reporter->end_progress();
 }
コード例 #4
0
 /**
  * Removes excess backups in the specified external directory from a specified course.
  *
  * @param stdClass $course Course object
  * @param int $now Starting time of the process
  * @return bool Whether or not backups are being removed
  */
 protected static function remove_excess_backups_from_directory($course, $now)
 {
     $config = get_config('backup');
     $dir = $config->backup_auto_destination;
     $isnotvaliddir = !file_exists($dir) || !is_dir($dir) || !is_writable($dir);
     if ($isnotvaliddir) {
         mtrace('Error: ' . $dir . ' does not appear to be a valid directory');
         return false;
     }
     // Calculate backup filename regex, ignoring the date/time/info parts that can be
     // variable, depending of languages, formats and automated backup settings.
     $filename = backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' . $course->id . '-';
     $regex = '#' . preg_quote($filename, '#') . '.*\\.mbz$#';
     // Store all the matching files into filename => timemodified array.
     $backupfiles = array();
     foreach (scandir($dir) as $backupfile) {
         // Skip files not matching the naming convention.
         if (!preg_match($regex, $backupfile)) {
             continue;
         }
         // Read the information contained in the backup itself.
         try {
             $bcinfo = backup_general_helper::get_backup_information_from_mbz($dir . '/' . $backupfile);
         } catch (backup_helper_exception $e) {
             mtrace('Error: ' . $backupfile . ' does not appear to be a valid backup (' . $e->errorcode . ')');
             continue;
         }
         // Make sure this backup concerns the course and site we are looking for.
         if ($bcinfo->format === backup::FORMAT_MOODLE && $bcinfo->type === backup::TYPE_1COURSE && $bcinfo->original_course_id == $course->id && backup_general_helper::backup_is_samesite($bcinfo)) {
             $backupfiles[$bcinfo->backup_date] = $backupfile;
         }
     }
     $backupstodelete = self::get_backups_to_delete($backupfiles, $now);
     if ($backupstodelete) {
         foreach ($backupstodelete as $backuptodelete) {
             unlink($dir . '/' . $backuptodelete);
         }
         mtrace('Deleted ' . count($backupstodelete) . ' old backup file(s) from external directory');
         return true;
     } else {
         return false;
     }
 }
コード例 #5
0
 /**
  * Return an array of owners and a list of each course they are teachers of.
  *
  * @param object $obj course obj
  * @param string $folder name of folder (optional)
  * @return bool of courses that match the search
  */
 protected function archivecourse($obj, $folder = false)
 {
     global $CFG;
     require_once $CFG->dirroot . '/backup/util/includes/backup_includes.php';
     require_once $CFG->dirroot . '/backup/controller/backup_controller.class.php';
     if (empty($CFG->siteadmins)) {
         // Should not happen on an ordinary site.
         return false;
     } else {
         $admin = get_admin();
     }
     $coursetobackup = $obj["course"]->id;
     // Set this to one existing choice cmid in your dev site.
     $userdoingthebackup = $admin->id;
     // Set this to the id of your admin account.
     try {
         // Prepare path.
         $matchers = array('/\\s/', '/\\//');
         $safeshort = preg_replace($matchers, '-', $obj["course"]->shortname);
         if (empty($obj["course"]->idnumber)) {
             $suffix = '-ID-' . $obj["course"]->id;
         } else {
             $suffix = '-ID-' . $obj["course"]->id . '-IDNUM-' . $obj["course"]->idnumber;
         }
         $archivefile = date("Y-m-d") . "{$suffix}-{$safeshort}.zip";
         $archivepath = str_replace(str_split('\\/:*?"<>|'), '', get_config('tool_coursearchiver', 'coursearchiverpath'));
         // Check for custom folder.
         if (!empty($folder)) {
             $folder = str_replace(str_split('\\/:*?"<>|'), '', $folder);
         }
         // If no custom folder is given, use the current year.
         if (empty($folder)) {
             $folder = date('Y');
         }
         // Final full path of file.
         $path = $CFG->dataroot . '/' . $archivepath . '/' . $folder;
         // If the path doesn't exist, make it so!
         if (!is_dir($path)) {
             umask(00);
             // Create the directory for CourseArchival.
             if (!mkdir($path, $CFG->directorypermissions, true)) {
                 throw new Exception('Archive path could not be created');
             }
             @chmod($path, $dirpermissions);
         }
         // Perform Backup.
         $bc = new backup_controller(backup::TYPE_1COURSE, $coursetobackup, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_AUTOMATED, $userdoingthebackup);
         $bc->execute_plan();
         // Execute backup.
         $results = $bc->get_results();
         // Get the file information needed.
         $config = get_config('backup');
         $dir = $config->backup_auto_destination;
         // The backup file will have already been moved, so I have to find it.
         if (!empty($dir)) {
             // Calculate backup filename regex, ignoring the date/time/info parts that can be
             // variable, depending of languages, formats and automated backup settings.
             $filename = backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' . $obj["course"]->id . '-';
             $regex = '#' . preg_quote($filename, '#') . '.*\\.mbz#';
             // Store all the matching files into filename => timemodified array.
             $files = array();
             foreach (scandir($dir) as $file) {
                 // Skip files not matching the naming convention.
                 if (!preg_match($regex, $file, $matches)) {
                     continue;
                 }
                 // Read the information contained in the backup itself.
                 try {
                     $bcinfo = backup_general_helper::get_backup_information_from_mbz($dir . '/' . $file);
                 } catch (backup_helper_exception $e) {
                     throw new Exception('Error: ' . $file . ' does not appear to be a valid backup (' . $e->errorcode . ')');
                     continue;
                 }
                 // Make sure this backup concerns the course and site we are looking for.
                 if ($bcinfo->format === backup::FORMAT_MOODLE && $bcinfo->type === backup::TYPE_1COURSE && $bcinfo->original_course_id == $obj["course"]->id && backup_general_helper::backup_is_samesite($bcinfo)) {
                     $files[$file] = $bcinfo->backup_date;
                 }
             }
             // Sort by values descending (newer to older filemodified).
             arsort($files);
             foreach ($files as $filename => $backupdate) {
                 // Make sure the backup is from today.
                 if (date('m/d/Y', $backupdate) == date('m/d/Y')) {
                     rename($dir . '/' . $filename, $path . '/' . $archivefile);
                 }
                 break;
                 // Just the last backup...thanks!
             }
         } else {
             $file = $results['backup_destination'];
             if (!empty($file)) {
                 $file->copy_content_to($path . '/' . $archivefile);
             } else {
                 throw new Exception('Backup failed');
             }
         }
         $bc->destroy();
         unset($bc);
         if (file_exists($path . '/' . $archivefile)) {
             // Make sure file got moved.
             // Remove Course.
             delete_course($obj["course"]->id, false);
         } else {
             throw new Exception('Course archive file does not exist');
         }
     } catch (Exception $e) {
         return false;
     }
     return true;
 }
コード例 #6
0
ファイル: backup_stepslib.php プロジェクト: verbazend/AWFA
 protected function define_execution()
 {
     // Get basepath
     $basepath = $this->get_basepath();
     // Get the list of files in directory
     $filestemp = get_directory_list($basepath, '', false, true, true);
     $files = array();
     foreach ($filestemp as $file) {
         // Add zip paths and fs paths to all them
         $files[$file] = $basepath . '/' . $file;
     }
     // Add the log file if exists
     $logfilepath = $basepath . '.log';
     if (file_exists($logfilepath)) {
         $files['moodle_backup.log'] = $logfilepath;
     }
     // Calculate the zip fullpath (in OS temp area it's always backup.mbz)
     $zipfile = $basepath . '/backup.mbz';
     // Get the zip packer
     $zippacker = get_file_packer('application/zip');
     // Zip files
     $result = $zippacker->archive_to_pathname($files, $zipfile, true, $this);
     // Something went wrong.
     if ($result === false) {
         @unlink($zipfile);
         throw new backup_step_exception('error_zip_packing', '', 'An error was encountered while trying to generate backup zip');
     }
     // Read to make sure it is a valid backup. Refer MDL-37877 . Delete it, if found not to be valid.
     try {
         backup_general_helper::get_backup_information_from_mbz($zipfile);
     } catch (backup_helper_exception $e) {
         @unlink($zipfile);
         throw new backup_step_exception('error_zip_packing', '', $e->debuginfo);
     }
 }