mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-06 21:35:49 +01:00
rudimentary backup [fixes #45]
This commit is contained in:
@@ -200,7 +200,6 @@ class AdminPlugin extends Plugin
|
|||||||
$format = $this->uri->extension();
|
$format = $this->uri->extension();
|
||||||
$ext = '.' . ($format ? $format : 'html') . TWIG_EXT;
|
$ext = '.' . ($format ? $format : 'html') . TWIG_EXT;
|
||||||
|
|
||||||
$twig->template = $this->template . $ext;
|
|
||||||
$twig->twig_vars['location'] = $this->template;
|
$twig->twig_vars['location'] = $this->template;
|
||||||
$twig->twig_vars['base_url_relative_frontend'] = $twig->twig_vars['base_url_relative'];
|
$twig->twig_vars['base_url_relative_frontend'] = $twig->twig_vars['base_url_relative'];
|
||||||
$twig->twig_vars['base_url_relative'] .=
|
$twig->twig_vars['base_url_relative'] .=
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use Grav\Common\Page\Page;
|
|||||||
use Grav\Common\Data;
|
use Grav\Common\Data;
|
||||||
use Grav\Common\GPM\GPM;
|
use Grav\Common\GPM\GPM;
|
||||||
use RocketTheme\Toolbox\File\File;
|
use RocketTheme\Toolbox\File\File;
|
||||||
|
use RocketTheme\Toolbox\File\JsonFile;
|
||||||
use RocketTheme\Toolbox\File\LogFile;
|
use RocketTheme\Toolbox\File\LogFile;
|
||||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||||
use RocketTheme\Toolbox\Session\Message;
|
use RocketTheme\Toolbox\Session\Message;
|
||||||
@@ -415,6 +416,32 @@ class Admin
|
|||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function lastBackup()
|
||||||
|
{
|
||||||
|
$file = JsonFile::instance($this->grav['locator']->findResource("log://backup.log"));
|
||||||
|
$content = $file->content();
|
||||||
|
if (empty($content)) {
|
||||||
|
return [
|
||||||
|
'days' => '∞',
|
||||||
|
'chart_fill' => 100,
|
||||||
|
'chart_empty' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$backup = new \DateTime();
|
||||||
|
$backup->setTimestamp($content['time']);
|
||||||
|
$diff = $backup->diff(new \DateTime());
|
||||||
|
|
||||||
|
$days = $diff->days;
|
||||||
|
$chart_fill = $days > 30 ? 100 : round($days / 30 * 100);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'days' => $days,
|
||||||
|
'chart_fill' => $chart_fill,
|
||||||
|
'chart_empty' => 100 - $chart_fill
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the page creating it if it does not exist.
|
* Returns the page creating it if it does not exist.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ use Grav\Common\Data;
|
|||||||
use Grav\Common\Page;
|
use Grav\Common\Page;
|
||||||
use Grav\Common\Page\Collection;
|
use Grav\Common\Page\Collection;
|
||||||
use Grav\Common\User\User;
|
use Grav\Common\User\User;
|
||||||
|
use Grav\Common\Utils;
|
||||||
|
use Grav\Common\Backup\ZipBackup;
|
||||||
|
use RocketTheme\Toolbox\File\JsonFile;
|
||||||
|
|
||||||
class AdminController
|
class AdminController
|
||||||
{
|
{
|
||||||
@@ -266,6 +269,38 @@ class AdminController
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function taskBackup()
|
||||||
|
{
|
||||||
|
$download = $this->grav['uri']->param('download');
|
||||||
|
|
||||||
|
if ($download) {
|
||||||
|
Utils::download(base64_decode(urldecode($download)), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$log = JsonFile::instance($this->grav['locator']->findResource("log://backup.log", true, true));
|
||||||
|
|
||||||
|
$backup = ZipBackup::backup();
|
||||||
|
$download = urlencode(base64_encode($backup));
|
||||||
|
$url = rtrim($this->grav['uri']->rootUrl(true), '/') . '/' . trim($this->admin->base, '/') . '/task:backup/download:' . $download;
|
||||||
|
|
||||||
|
$log->content([
|
||||||
|
'time' => time(),
|
||||||
|
'location' => $backup
|
||||||
|
]);
|
||||||
|
$log->save();
|
||||||
|
|
||||||
|
$this->admin->json_response = [
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Your backup is ready for download. <a href="'.$url.'" class="button">Download backup</a>',
|
||||||
|
'toastr' => [
|
||||||
|
'timeOut' => 0,
|
||||||
|
'closeButton' => true
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected function taskFilterPages()
|
protected function taskFilterPages()
|
||||||
{
|
{
|
||||||
$data = $this->post;
|
$data = $this->post;
|
||||||
|
|||||||
8
pages/admin/backup.md
Normal file
8
pages/admin/backup.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Backup
|
||||||
|
template: ajax
|
||||||
|
|
||||||
|
access:
|
||||||
|
admin.maintenance: true
|
||||||
|
admin.super: true
|
||||||
|
---
|
||||||
@@ -92,6 +92,63 @@ $(function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update plugins/themes
|
||||||
|
$('[data-ajax]').on('click', function(e) {
|
||||||
|
|
||||||
|
var button = $(this),
|
||||||
|
icon = button.find('> .fa'),
|
||||||
|
url = button.data('ajax');
|
||||||
|
|
||||||
|
var iconClasses = [],
|
||||||
|
helperClasses = [ 'fa-lg', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x',
|
||||||
|
'fa-fw', 'fa-ul', 'fa-li', 'fa-border',
|
||||||
|
'fa-rotate-90', 'fa-rotate-180', 'fa-rotate-270',
|
||||||
|
'fa-flip-horizontal', 'fa-flip-vertical' ];
|
||||||
|
|
||||||
|
// Disable button
|
||||||
|
button.attr('disabled','disabled');
|
||||||
|
|
||||||
|
// Swap fontawesome icon to loader
|
||||||
|
$.each(icon.attr('class').split(/\s+/), function (i, classname) {
|
||||||
|
if (classname.indexOf('fa-') === 0 && $.inArray(classname, helperClasses) === -1) {
|
||||||
|
iconClasses.push(classname);
|
||||||
|
icon.removeClass(classname);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
icon.addClass('fa-refresh fa-spin');
|
||||||
|
|
||||||
|
GravAjax({
|
||||||
|
dataType: "json",
|
||||||
|
url: url,
|
||||||
|
success: function(result, status) {
|
||||||
|
|
||||||
|
var toastrBackup = {};
|
||||||
|
if (result.toastr) {
|
||||||
|
for (var setting in result.toastr) { if (result.toastr.hasOwnProperty(setting)) {
|
||||||
|
toastrBackup[setting] = toastr.options[setting];
|
||||||
|
toastr.options[setting] = result.toastr[setting];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status == 'success') {
|
||||||
|
toastr.success(result.message || 'Task completed.');
|
||||||
|
} else {
|
||||||
|
toastr.error(result.message || 'Something went terribly wrong.');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var setting in toastrBackup) { if (toastrBackup.hasOwnProperty(setting)) {
|
||||||
|
toastr.options[setting] = toastrBackup[setting];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).complete(function() {
|
||||||
|
// Restore button
|
||||||
|
button.removeAttr('disabled');
|
||||||
|
icon.removeClass('fa-refresh fa-spin').addClass(iconClasses.join(' '));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var GPMRefresh = function () {
|
var GPMRefresh = function () {
|
||||||
GravAjax({
|
GravAjax({
|
||||||
dataType: "JSON",
|
dataType: "JSON",
|
||||||
|
|||||||
5
themes/grav/templates/ajax.json.twig
Normal file
5
themes/grav/templates/ajax.json.twig
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{% if admin.json_response %}
|
||||||
|
{{ admin.json_response|json_encode }}
|
||||||
|
{% else %}
|
||||||
|
{}
|
||||||
|
{% endif %}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
{% set gpm = admin.gpm() %}
|
{% set gpm = admin.gpm() %}
|
||||||
{% set updatable = gpm.getUpdatablePlugins() %}
|
{% set updatable = gpm.getUpdatablePlugins() %}
|
||||||
|
{% set backup = admin.lastBackup() %}
|
||||||
|
|
||||||
<div id="admin-dashboard">
|
<div id="admin-dashboard">
|
||||||
<div id="updates" class="dashboard-item dashboard-left">
|
<div id="updates" class="dashboard-item dashboard-left">
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
<div class="ct-chart"></div>
|
<div class="ct-chart"></div>
|
||||||
<script>
|
<script>
|
||||||
var data = {
|
var data = {
|
||||||
series: [33,67]
|
series: [{{ backup.chart_fill }}, {{ backup.chart_empty }}]
|
||||||
};
|
};
|
||||||
var options = {
|
var options = {
|
||||||
donut: true,
|
donut: true,
|
||||||
@@ -41,14 +42,14 @@
|
|||||||
};
|
};
|
||||||
Chartist.Pie('.backups-chart .ct-chart', data, options);
|
Chartist.Pie('.backups-chart .ct-chart', data, options);
|
||||||
</script>
|
</script>
|
||||||
<span class="numeric">13<em>days</em></span>
|
<span class="numeric">{{ backup.days }}<em>days</em></span>
|
||||||
</div>
|
</div>
|
||||||
<p>Last Backup</p>
|
<p>Last Backup</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flush-bottom button-bar">
|
<div class="flush-bottom button-bar">
|
||||||
<button data-maintenance-update="{{ base_url_relative }}/update.json/task:update" class="button"><i class="fa fa-cloud-download"></i> Update</button>
|
<button data-maintenance-update="{{ base_url_relative }}/update.json/task:update" class="button"><i class="fa fa-cloud-download"></i> Update</button>
|
||||||
<button href="#" class="button"><i class="fa fa-database"></i> Backup</button>
|
<button data-ajax="{{ base_url_relative }}/backup.json/task:backup" class="button"><i class="fa fa-database"></i> Backup</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user