Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature : Automatic Exports #36

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,37 @@ Any Problems, questions, suggestions
If you have a problem with this block, suggestions for improvement, drop an email at :
- Pimenko : [email protected]
- Github : https://github.com/DigiDago/moodle-block_admin_presets

Usage
===================
- **Check if plugin is installed :**
go to *Admin > Plugins > Plugins overview > Additional Plugins > Admin presets*. It's installed if it appears.
- **Set-up the block :** Make the block appear in your 'Site Home' page by adding it to the page, go to *Site Home > Turn Editing On*. Then go to *Add Block > Admin presets*
- **Usage :** In the 'Site Home' page, an admin_preset block should now appear. from there you can

- **Import a config file :** Just drag&drop a config_file generated by admin_presets from this moodle or another one. Just in case, before importing anything you should always export your actual configuration to be able to retrieve it later.
- **Export your current config :** Select all the settings you wish to be in your export file, **by default all settings are selected**. Be careful not to select unnecessary settings because the selected settings will always override previous settings at the import. The config.xml file won't be downloaded right away, you will find it in the presets list.
- **See the presets list :** Here are listed all the imported & exported config files, from there you can
- Preview : see the config to check which settings are contained
- Load : load the config onto the site
- Download : download a .xml fil containing the config, allowing you to import it to any moodle project running the admin_presets plugin
- Delete : permanently remove that configuration from de presets list
> Carefull : settings related to the Moodle Theme are exported/imported but the used theme still needs to be set manually.


Automatic Export
===================
A feature was added allowing the plugin to perform an automatic export which will provide a daily back-up if enabled. You can enable this setting the same way you're configuring the plugin following : *Admin > Plugins > Plugins overview > Additional Plugins > Admin presets > Settings*.
These backups are named with a timestamp looking like '20210816160918' and will be found with any other record of admin_presets : in the "presets" list that regroups exports, imports and automatic backups.

### How it works
- Automatic export daily at 23:00, creates an export with full config named with a time stamp **default : Enabled**
- Automatic export cleanup runs daily at 23:30, will delete automatic exports as follows
- Last 7 weeks : keeps all
- Last 14 days : keeps one export out of 2
- Last month : keeps one export out of 4
- Last 3 months : keeps one export out of 8
- Older than 3 months : deletes all
> This feature only targets automatic exports, if you perform a manual export or import they'll stay untouched.
>
> If you import an automatic export in this project or another, it won't be targeted by this cleanup feature
145 changes: 145 additions & 0 deletions classes/task/automatic_export.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* @author [email protected]
* @date 16/08/2021
* @copyright 2021, CBlue SPRL, [email protected]
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package block_admin_presets
*/

namespace block_admin_presets\task;

use admin_presets_export;
use coding_exception;
use core\task\scheduled_task;
use dml_exception;
use stdClass;

defined('MOODLE_INTERNAL') || die();

class automatic_export extends scheduled_task {

/**
* @return string
* @throws coding_exception
*/
public function get_name() {
return get_string('automaticexport', 'block_admin_presets');
}

/**
* This function is meant to be called by a CRON task, see the ../db/tasks.php file to check how it is programmed.
* This function will get all site's settings through the _get_setting() function, it'll then will loop through them and construct a $_POST array that'll be handled to create an admin_presets valid database record. The record will be named with a timestamp YearMonthDayHourMinuteSecond.
* If the config is successfully recorded, the function will return true, if not it'll throw the appropriate Exception along the way.
*
* For testing purposes you can manually launch this function : sudo -u www-data php7.3 admin/cli/scheduled_task.php --execute="\block_admin_presets\task\automatic_export"
*
* @return bool
* @throws \moodle_exception
* @throws coding_exception
* @throws dml_exception
*/
public function execute() {
global $CFG, $DB;

$config = get_config('block_admin_presets', 'automaticexport');
if (empty($config)) {
return;
}

require_once $CFG->dirroot . "/blocks/admin_presets/lib/admin_presets_export.class.php";

$export = new admin_presets_export();

// Reload site settings.
$sitesettings = $export->load_site_settings();

//Construct $presets for each site setting
foreach ($sitesettings as $sitesetting => $settingvalue) {
foreach ($settingvalue as $key => $value) {
$presets[$key . '@@' . $sitesetting] = '1';
}
}

// admin_preset record.
$preset = new stdClass();
$preset->userid = '1';
$preset->name = date('YmdGis');
$preset->comments = $presets['comments']['text'];
$preset->site = $CFG->wwwroot;
$preset->author = $presets['author'];
$preset->moodleversion = $CFG->version;
$preset->moodlerelease = $CFG->release;
$preset->timecreated = time();
$preset->timemodified = 0;
if (!$preset->id = $DB->insert_record('block_admin_presets', $preset)) {
print_error('errorinserting', 'block_admin_presets');
}

// Store it here for logging and other future id-oriented stuff.
$this->id = $preset->id;

// We must ensure that there are settings selected.
foreach ($presets as $varname => $value) {

unset($setting);

if (strstr($varname, '@@') != false) {

$settingsfound = true;

$name = explode('@@', $varname);
$setting = new StdClass();
$setting->adminpresetid = $preset->id;
$setting->plugin = $name[1];
$setting->name = $name[0];
$setting->value = $sitesettings[$setting->plugin][$setting->name]->get_value();

if (!$setting->id = $DB->insert_record('block_admin_presets_it', $setting)) {
print_error('errorinserting', 'block_admin_presets');
}

// Setting attributes must also be exported.
if ($attributes = $sitesettings[$setting->plugin][$setting->name]->get_attributes_values()) {
foreach ($attributes as $attributename => $value) {

$attr = new StdClass();
$attr->itemid = $setting->id;
$attr->name = $attributename;
$attr->value = $value;

$DB->insert_record('block_admin_presets_it_a', $attr);
}
}
}
}

// If there are no valid or selected settings we should delete the admin preset record.
if (empty($settingsfound)) {
$DB->delete_records('block_admin_presets', ['id' => $preset->id]);
redirect($CFG->wwwroot . '/blocks/admin_presets/index.php?action=export',
get_string('novalidsettingsselected', 'block_admin_presets'), 4);
}


// Trigger the as it is usually triggered after execute finishes.
$export->log();

return true;
}
}
203 changes: 203 additions & 0 deletions classes/task/automatic_export_cleanup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* @author [email protected]
* @date 16/08/2021
* @copyright 2021, CBlue SPRL, [email protected]
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package block_admin_presets
*/

namespace block_admin_presets\task;

use coding_exception;
use core\task\scheduled_task;
use DateTime;

defined('MOODLE_INTERNAL') || die();

class automatic_export_cleanup extends scheduled_task {

/**
* @return string
* @throws coding_exception
*/
public function get_name() {
return get_string('automaticexportcleanup', 'block_admin_presets');
}

/**
* This function is meant to be called by a CRON task, see the ../db/tasks.php file to check how it is programmed.
* This function will get all records of the admin_presets plugin than will sort them into 4 arrays depending on the time creation of the record.
* Each array will then be processed according to what cleanup we want to do :
* records that are younger than 1 week will stay untouched
* records that are older than a week but younger than 2 weeks will be deleted 1 day out of 2
* records that are older than two weeks but younger than 1 month will be deleted 3 day out of 4
* records that are older than 1 month but younger than 3 months will be deleted 3 day out of 4
* records that are older than 3 months will all be deleted
*
* This function will return true if deletion was successfull. Otherwise it'll trhow the apropriate Exception along the way.
*
* For testing purposes you can manually launch this function : sudo -u www-data php7.3 admin/cli/scheduled_task.php --execute="\block_admin_presets\task\automatic_export_cleanup"
* *
* @return bool|void
* @throws \dml_exception
*/
public function execute() {
global $CFG, $DB;

$config = get_config('block_admin_presets', 'automaticexportcleanup');
if (empty($config)) {
return;
}

//get all admin_presets records from DB
$presets = $DB->get_records('block_admin_presets');

//set-up arrays for dispatching presets records
$twoweeks = [];
$onemonth = [];
$threemonths = [];
$older = [];

foreach ($presets as $preset) {

// checks name to see if automatic backup
if (preg_match('/^[0-9]{14}$/', $preset->name)) {
// check if record is imported or local and sort records according to their age
if ($preset->timeimported == 0) { //if backup is local, check on creation datetime
if ($preset->timecreated > strtotime('-1 weeks')) {
continue;
} elseif ($preset->timecreated > strtotime('-2 weeks')) {
$twoweeks[] = $preset;
continue;
} elseif ($preset->timecreated > strtotime('-1 months')) {
$onemonth[] = $preset;
continue;
} elseif ($preset->timecreated > strtotime('-3 months')) {
$threemonths[] = $preset;
continue;
} elseif ($preset->timecreated < strtotime('-3 months')) {
$older[] = $preset;
continue;
}
}
}
}

//loop through each now sorted array to delete unwanted records
$this->delete_all_except_nth(2, $twoweeks);
$this->delete_all_except_nth(4, $onemonth);
$this->delete_all_except_nth(8, $threemonths);
$this->delete_all($older);

return true;
}

/**
* This function is used to delete records from the admin_presets plugin
* It is called by the delete_all_but_nth() and delete_all() functions.
* @param $record
* @throws \dml_exception
* @throws \moodle_exception
*/
private function delete($record) {
global $DB;

if (!$DB->delete_records('block_admin_presets', array('id' => $record->id))) {
print_error('errordeleting', 'block_admin_presets');
}

// Getting items ids before deleting to delete item attributes.
$items = $DB->get_records('block_admin_presets_it', array('adminpresetid' => $record->id), 'id');
foreach ($items as $item) {
$DB->delete_records('block_admin_presets_it_a', array('itemid' => $item->id));
}

if (!$DB->delete_records('block_admin_presets_it', array('adminpresetid' => $record->id))) {
print_error('errordeleting', 'block_admin_presets');
}

// Deleting the preset applications.
if ($previouslyapplied = $DB->get_records('block_admin_presets_app',
array('adminpresetid' => $record->id), 'id')) {

foreach ($previouslyapplied as $application) {

// Deleting items.
if (!$DB->delete_records('block_admin_presets_app_it',
array('adminpresetapplyid' => $application->id))) {

print_error('errordeleting', 'block_admin_presets');
}

// Deleting attributes.
if (!$DB->delete_records('block_admin_presets_app_it_a',
array('adminpresetapplyid' => $application->id))) {

print_error('errordeleting', 'block_admin_presets');
}
}

if (!$DB->delete_records('block_admin_presets_app',
array('adminpresetid' => $record->id))) {

print_error('errordeleting', 'block_admin_presets');
}
}
}

/**
* This function will delete every record except 1 out of nth.
* so if nth = 8, it'll delete 7/8 record
*
* The object parameter should be a collection of record of admin_prestes. You can get such a collenction using :
* $object = $DB->get_records('block_admin_presets');
*
* @param int $nth
* @param $object
* @throws \dml_exception
* @throws \moodle_exception
*/
private function delete_all_except_nth(int $nth, $object) {
$reference_date = new DateTime("1970-01-01");

foreach ($object as $record) {
$recorddate = new DateTime();
$recorddate->setTimestamp($record->timecreated);
if((date_diff($reference_date, $recorddate, true)->days)%$nth != 0) {
$this->delete($record);
}
}
}

/**
* This function loops through a collection of admin_presets records to delete each of them.
* You can get such a collenction using :
* $object = $DB->get_records('block_admin_presets');
*
* @param $object
* @throws \dml_exception
* @throws \moodle_exception
*/
private function delete_all($object) {
foreach ($object as $record) {
$this->delete($record);
}
}

}
Loading