12 changed files with 258 additions and 394 deletions
-
92app/Entities/Backups/BackupsRepository.php
-
171app/Http/Controllers/BackupsController.php
-
52app/Http/Requests/Backups/BackupUploadRequest.php
-
31app/Http/Requests/Backups/CreateRequest.php
-
31app/Http/Requests/Backups/DeleteRequest.php
-
40resources/lang/en/backup.php
-
21resources/views/backups/delete.blade.php
-
70resources/views/backups/forms.blade.php
-
95resources/views/backups/index.blade.php
-
22resources/views/backups/restore.blade.php
-
13routes/web.php
-
14routes/web/backup.php
@ -1,92 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Entities\Backups; |
|
||||
|
|
||||
use App\Entities\Options\Option; |
|
||||
use BackupManager\Filesystems\Destination; |
|
||||
use BackupManager\Manager; |
|
||||
use League\Flysystem\FileExistsException; |
|
||||
use League\Flysystem\FileNotFoundException; |
|
||||
use Storage; |
|
||||
|
|
||||
/** |
|
||||
* Backups Repository Class |
|
||||
*/ |
|
||||
class BackupsRepository |
|
||||
{ |
|
||||
protected $storage; |
|
||||
protected $storageType; |
|
||||
|
|
||||
public function __construct() |
|
||||
{ |
|
||||
$this->storageType = 'local'; |
|
||||
$this->storage = Storage::disk($this->storageType); |
|
||||
} |
|
||||
|
|
||||
public function getAllFiles() |
|
||||
{ |
|
||||
$backups = \File::allFiles(storage_path('app/backup/db')); |
|
||||
|
|
||||
// Sort files by modified time DESC
|
|
||||
usort($backups, function($a, $b) { |
|
||||
return -1 * strcmp($a->getMTime(), $b->getMTime()); |
|
||||
}); |
|
||||
|
|
||||
return $backups; |
|
||||
} |
|
||||
|
|
||||
public function create($backupData) |
|
||||
{ |
|
||||
$manager = app()->make(Manager::class); |
|
||||
$fileName = $backupData['file_name'] ?: date('Y-m-d_Hi'); |
|
||||
try { |
|
||||
$manager->makeBackup()->run('mysql', [ |
|
||||
new Destination($this->storageType, 'backup/db/' . $fileName) |
|
||||
], 'gzip'); |
|
||||
|
|
||||
return $fileName; |
|
||||
|
|
||||
} catch (FileExistsException $e) { |
|
||||
flash()->error('Database tidak dapat dibackup dengan Nama File yang sama.'); |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function restore($fileName) |
|
||||
{ |
|
||||
try { |
|
||||
$manager = app()->make(Manager::class); |
|
||||
$manager->makeRestore()->run($this->storageType, 'backup/db/' . $fileName, 'mysql', 'gzip'); |
|
||||
return true; |
|
||||
|
|
||||
} catch (FileNotFoundException $e) { |
|
||||
flash()->error('Tidak dapat mengembalikan Database.'); |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function delete($fileName) |
|
||||
{ |
|
||||
if ($this->storage->has('backup/db/' . $fileName)) { |
|
||||
$this->storage->delete('backup/db/' . $fileName); |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public function proccessBackupFileUpload($req) |
|
||||
{ |
|
||||
$file = $req->file('backup_file'); |
|
||||
|
|
||||
if ($this->storage->has('backup/db/' . $file->getClientOriginalName())) { |
|
||||
flash()->error('Upload file gagal, terdapat Nama File yang sama.'); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
$result = $this->storage->put('backup/db/' . $file->getClientOriginalName(), file_get_contents($file)); |
|
||||
|
|
||||
return $result; |
|
||||
} |
|
||||
} |
|
||||
@ -1,52 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Requests\Backups; |
|
||||
|
|
||||
use App\Http\Requests\Request; |
|
||||
|
|
||||
class BackupUploadRequest extends Request { |
|
||||
|
|
||||
/** |
|
||||
* Determine if the user is authorized to make this request. |
|
||||
* |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public function authorize() |
|
||||
{ |
|
||||
return auth()->user()->can('manage_backups'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the validation rules that apply to the request. |
|
||||
* |
|
||||
* @return array |
|
||||
*/ |
|
||||
public function rules() |
|
||||
{ |
|
||||
return [ |
|
||||
'backup_file' => 'required|sql_zip' |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
public function messages() |
|
||||
{ |
|
||||
return [ |
|
||||
'file.sql_zip' => 'Isian file harus dokumen berjenis .zip, .gz atau .sql', |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
protected function getValidatorInstance() |
|
||||
{ |
|
||||
$validator = parent::getValidatorInstance(); |
|
||||
|
|
||||
$validator->addImplicitExtension('sql_zip', function($attribute, $value, $parameters) { |
|
||||
if ($value) |
|
||||
return in_array($value->getClientOriginalExtension(), ['zip','gz','sql']); |
|
||||
|
|
||||
return false; |
|
||||
}); |
|
||||
|
|
||||
return $validator; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Requests\Backups; |
|
||||
|
|
||||
use App\Http\Requests\Request; |
|
||||
|
|
||||
class CreateRequest extends Request { |
|
||||
|
|
||||
/** |
|
||||
* Determine if the user is authorized to make this request. |
|
||||
* |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public function authorize() |
|
||||
{ |
|
||||
return auth()->user()->can('manage_backups'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the validation rules that apply to the request. |
|
||||
* |
|
||||
* @return array |
|
||||
*/ |
|
||||
public function rules() |
|
||||
{ |
|
||||
return [ |
|
||||
'file_name' => 'nullable|max:20|alpha_dash', |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Requests\Backups; |
|
||||
|
|
||||
use App\Http\Requests\Request; |
|
||||
|
|
||||
class DeleteRequest extends Request { |
|
||||
|
|
||||
/** |
|
||||
* Determine if the user is authorized to make this request. |
|
||||
* |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public function authorize() |
|
||||
{ |
|
||||
return auth()->user()->can('manage_backups'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the validation rules that apply to the request. |
|
||||
* |
|
||||
* @return array |
|
||||
*/ |
|
||||
public function rules() |
|
||||
{ |
|
||||
return [ |
|
||||
'file_name' => 'required' |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -0,0 +1,40 @@ |
|||||
|
<?php |
||||
|
|
||||
|
return [ |
||||
|
// Labels
|
||||
|
'index_title' => 'Database Backup Manager', |
||||
|
'list' => 'Backup File List', |
||||
|
'file_name' => 'File Name', |
||||
|
'file_size' => 'File Size', |
||||
|
'created_at' => 'Created at', |
||||
|
'actions' => 'Actions', |
||||
|
'empty' => 'No backup file available.', |
||||
|
|
||||
|
// Create backup file
|
||||
|
'create' => 'Create Backup File', |
||||
|
'created' => 'Backup file :filename created.', |
||||
|
'not_created' => 'Backup file named :filename already exists.', |
||||
|
|
||||
|
// Delete backup file
|
||||
|
'delete' => 'Delete', |
||||
|
'delete_title' => 'Delete this backup file', |
||||
|
'sure_to_delete_file' => 'Are you sure to delete this file <strong>":filename"</strong>?', |
||||
|
'cancel_delete' => 'Cancel Delete', |
||||
|
'confirm_delete' => 'YES, please delete this file!', |
||||
|
'deleted' => 'Backup file :filename has been deleted!', |
||||
|
|
||||
|
// Download backup file
|
||||
|
'download' => 'Download', |
||||
|
|
||||
|
// Restore backup
|
||||
|
'restore' => 'Restore', |
||||
|
'restore_title' => 'Restore database from file', |
||||
|
'sure_to_restore' => 'Are you sure to restore database with this backup file "<strong>:filename</strong>"? <br><br>Please make sure your <strong>current database has been backed up</strong>.', |
||||
|
'cancel_restore' => 'Cancel Restore', |
||||
|
'confirm_restore' => 'YES, Restore Database!', |
||||
|
'restored' => 'Database restored with backup file :filename', |
||||
|
|
||||
|
// Upload backup fle
|
||||
|
'upload' => 'Upload Backup File', |
||||
|
'uploaded' => 'Backup file :filename uploaded.', |
||||
|
]; |
||||
@ -1,21 +0,0 @@ |
|||||
@extends('layouts.app') |
|
||||
|
|
||||
@section('content') |
|
||||
<br> |
|
||||
<div class="panel panel-warning"> |
|
||||
<div class="panel-heading"> |
|
||||
<h3 class="panel-title"> |
|
||||
Apakah anda yakin akan menghapus file backup <strong>"{{ $fileName }}"</strong> ini? |
|
||||
</h3> |
|
||||
</div> |
|
||||
<div class="panel-footer"> |
|
||||
{!! link_to_route('backups.index', trans('app.cancel'), [], ['class' => 'btn btn-default']) !!} |
|
||||
<div class="pull-right"> |
|
||||
{!! Form::open(['route'=>['backups.destroy', $fileName], 'method' => 'delete']) !!} |
|
||||
{!! Form::hidden('file_name', $fileName) !!} |
|
||||
{!! Form::submit('Hapus File', ['class'=>'btn btn-danger']) !!} |
|
||||
{!! Form::close() !!} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
@endsection |
|
||||
@ -0,0 +1,70 @@ |
|||||
|
@if (request('action') == 'delete' && Request::has('file_name')) |
||||
|
<div class="panel panel-danger"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">@lang('backup.delete')</h3> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
<p>@lang('backup.sure_to_delete_file', ['filename' => request('file_name')])</p> |
||||
|
</div> |
||||
|
<div class="panel-footer"> |
||||
|
<a href="{{ route('backups.index') }}" class="btn btn-default">@lang('backup.cancel_delete')</a> |
||||
|
<form action="{{ route('backups.destroy', request('file_name')) }}" |
||||
|
method="post" |
||||
|
class="pull-right" |
||||
|
onsubmit="return confirm('Click OK to Delete.')"> |
||||
|
{{ method_field('delete') }} |
||||
|
{{ csrf_field() }} |
||||
|
<input type="hidden" name="file_name" value="{{ request('file_name') }}"> |
||||
|
<input type="submit" class="btn btn-danger" value="@lang('backup.confirm_delete')"> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
@endif |
||||
|
@if (request('action') == 'restore' && Request::has('file_name')) |
||||
|
<div class="panel panel-warning"> |
||||
|
<div class="panel-heading"><h3 class="panel-title">@lang('backup.restore')</h3></div> |
||||
|
<div class="panel-body"> |
||||
|
<p>@lang('backup.sure_to_restore', ['filename' => request('file_name')])</p> |
||||
|
</div> |
||||
|
<div class="panel-footer"> |
||||
|
<a href="{{ route('backups.index') }}" class="btn btn-default">@lang('backup.cancel_restore')</a> |
||||
|
<form action="{{ route('backups.restore', request('file_name')) }}" |
||||
|
method="post" |
||||
|
class="pull-right" |
||||
|
onsubmit="return confirm('Click OK to Restore.')"> |
||||
|
{{ csrf_field() }} |
||||
|
<input type="hidden" name="file_name" value="{{ request('file_name') }}"> |
||||
|
<input type="submit" class="btn btn-warning" value="@lang('backup.confirm_restore')"> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
@endif |
||||
|
@if (request('action') == null) |
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-body"> |
||||
|
<form action="{{ route('backups.store') }}" method="post"> |
||||
|
{{ csrf_field() }} |
||||
|
<div class="form-group"> |
||||
|
<label for="file_name" class="control-label">@lang('backup.create')</label> |
||||
|
<input type="text" name="file_name" class="form-control" placeholder="{{ date('Y-m-d_Hi') }}"> |
||||
|
{!! $errors->first('file_name', '<div class="text-danger text-right">:message</div>') !!} |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input type="submit" value="@lang('backup.create')" class="btn btn-success"> |
||||
|
</div> |
||||
|
</form> |
||||
|
<hr> |
||||
|
<form action="{{ route('backups.upload') }}" method="post" enctype="multipart/form-data"> |
||||
|
{{ csrf_field() }} |
||||
|
<div class="form-group"> |
||||
|
<label for="backup_file" class="control-label">@lang('backup.upload')</label> |
||||
|
<input type="file" name="backup_file" class="form-control"> |
||||
|
{!! $errors->first('backup_file', '<div class="text-danger text-right">:message</div>') !!} |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input type="submit" value="@lang('backup.upload')" class="btn btn-primary"> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
@endif |
||||
@ -1,64 +1,57 @@ |
|||||
@extends('layouts.app') |
@extends('layouts.app') |
||||
|
|
||||
@section('title','Daftar Backup Database Sistem') |
|
||||
|
@section('title',trans('backup.index_title')) |
||||
|
|
||||
@section('content') |
@section('content') |
||||
<h1 class="page-header"> |
|
||||
Daftar Backup Database Sistem |
|
||||
</h1> |
|
||||
|
<ul class="breadcrumb hidden-print"> |
||||
|
<li><a href="{{ route('backups.index') }}">@lang('backup.index_title')</a></li> |
||||
|
<li class="active">@lang('backup.list')</li> |
||||
|
</ul> |
||||
|
|
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-md-8"> |
<div class="col-md-8"> |
||||
<div class="panel panel-default"> |
<div class="panel panel-default"> |
||||
<div class="panel-heading"><h3 class="panel-title">Daftar File Backup</h3></div> |
|
||||
<div class="panel-body"> |
|
||||
<table class="table table-condensed"> |
|
||||
<thead> |
|
||||
<th>#</th>
|
|
||||
<th>Nama File</th> |
|
||||
<th>Ukuran</th> |
|
||||
<th>Tanggal Jam</th> |
|
||||
<th>{{ trans('app.action') }}</th> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
@forelse($backups as $key => $backup) |
|
||||
<tr> |
|
||||
<td>{{ $key + 1 }}</td> |
|
||||
<td>{{ $backup->getFilename() }}</td> |
|
||||
<td>{{ formatSizeUnits($backup->getSize()) }}</td> |
|
||||
<td>{{ date('Y-m-d H:i:s', $backup->getMTime()) }}</td> |
|
||||
<td> |
|
||||
{!! link_to_route('backups.download','Download',[$backup->getFilename()],['class'=>'btn btn-default btn-xs','target' => '_blank']) !!} |
|
||||
{!! link_to_route('backups.restore','Restore',[$backup->getFilename()],['class'=>'btn btn-warning btn-xs']) !!} |
|
||||
{!! link_to_route('backups.delete','x',[$backup->getFilename()],['class'=>'btn btn-danger btn-xs']) !!} |
|
||||
</td> |
|
||||
</tr> |
|
||||
@empty |
|
||||
<tr> |
|
||||
<td colspan="3">Belum ada file backup</td> |
|
||||
</tr> |
|
||||
@endforelse |
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
|
<table class="table table-condensed"> |
||||
|
<thead> |
||||
|
<th>@lang('app.table_no')</th> |
||||
|
<th>@lang('backup.file_name')</th> |
||||
|
<th>@lang('backup.file_size')</th> |
||||
|
<th>@lang('backup.created_at')</th> |
||||
|
<th class="text-center">@lang('backup.actions')</th> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
@forelse($backups as $key => $backup) |
||||
|
<tr> |
||||
|
<td>{{ $key + 1 }}</td> |
||||
|
<td>{{ $backup->getFilename() }}</td> |
||||
|
<td>{{ formatSizeUnits($backup->getSize()) }}</td> |
||||
|
<td>{{ date('Y-m-d H:i:s', $backup->getMTime()) }}</td> |
||||
|
<td class="text-center"> |
||||
|
<a href="{{ route('backups.index', ['action' => 'restore', 'file_name' => $backup->getFilename()]) }}" |
||||
|
id="restore_{{ str_replace('.gz', '', $backup->getFilename()) }}" |
||||
|
class="btn btn-warning btn-xs" |
||||
|
title="@lang('backup.download')">@lang('backup.restore')</a> |
||||
|
<a href="{{ route('backups.download', [$backup->getFilename()]) }}" |
||||
|
id="download_{{ str_replace('.gz', '', $backup->getFilename()) }}" |
||||
|
class="btn btn-info btn-xs" |
||||
|
title="@lang('backup.download')">@lang('backup.download')</a> |
||||
|
<a href="{{ route('backups.index', ['action' => 'delete', 'file_name' => $backup->getFilename()]) }}" |
||||
|
id="del_{{ str_replace('.gz', '', $backup->getFilename()) }}" |
||||
|
class="btn btn-danger btn-xs" |
||||
|
title="@lang('backup.delete')">@lang('backup.delete')</a> |
||||
|
</td> |
||||
|
</tr> |
||||
|
@empty |
||||
|
<tr> |
||||
|
<td colspan="3">@lang('backup.empty')</td> |
||||
|
</tr> |
||||
|
@endforelse |
||||
|
</tbody> |
||||
|
</table> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<div class="col-md-4"> |
<div class="col-md-4"> |
||||
<div class="panel panel-default"> |
|
||||
<div class="panel-body"> |
|
||||
{!! Form::open(['route' => 'backups.store','class' => '']) !!} |
|
||||
{!! FormField::text('file_name', ['label' => 'Buat Backup Database', 'placeholder' => date('Y-m-d_Hi')]) !!} |
|
||||
{!! Form::submit('Buat Backup', ['class' => 'btn btn-success']) !!} |
|
||||
{!! Form::close() !!} |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
{!! Form::open(['route' => 'backups.upload','class' => '', 'files' => true]) !!} |
|
||||
{!! FormField::file('backup_file', ['label' => 'Upload File Backup','placeholder'=>'Pilih File']) !!} |
|
||||
{!! Form::submit('Upload', ['class' => 'btn btn-info']) !!} |
|
||||
{!! Form::close() !!} |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
|
@include('backups.forms') |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
@endsection |
@endsection |
||||
@ -1,22 +0,0 @@ |
|||||
@extends('layouts.app') |
|
||||
|
|
||||
@section('content') |
|
||||
<br> |
|
||||
<div class="panel panel-warning"> |
|
||||
<div class="panel-heading"> |
|
||||
<h3 class="panel-title"> |
|
||||
Apakah anda yakin akan mengembalikan seluruh data sesuai file ini <strong>"{{ $fileName }}"</strong>? <br> |
|
||||
Pastikan data saat ini sudah dibackup. |
|
||||
</h3> |
|
||||
</div> |
|
||||
<div class="panel-footer"> |
|
||||
{!! link_to_route('backups.index', trans('app.cancel'), [], ['class' => 'btn btn-default']) !!} |
|
||||
<div class="pull-right"> |
|
||||
{!! Form::open(['route'=>['backups.restore', $fileName]]) !!} |
|
||||
{!! Form::hidden('file_name', $fileName) !!} |
|
||||
{!! Form::submit('Restore Database', ['class'=>'btn btn-danger']) !!} |
|
||||
{!! Form::close() !!} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
@endsection |
|
||||
@ -1,14 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
Route::group(['middleware' => ['web','role:admin']], function() { |
|
||||
/** |
|
||||
* Backups Routes |
|
||||
*/ |
|
||||
Route::get('backups/{fileName}/restore', ['as'=>'backups.restore', 'uses'=>'BackupsController@restore']); |
|
||||
Route::post('backups/{fileName}/restore', ['as'=>'backups.restore', 'uses'=>'BackupsController@postRestore']); |
|
||||
Route::get('backups/{fileName}/dl', ['as'=>'backups.download', 'uses'=>'BackupsController@download']); |
|
||||
Route::post('backups/upload', ['as'=>'backups.upload', 'uses'=>'BackupsController@upload']); |
|
||||
Route::get('backups/{id}/delete', ['as'=>'backups.delete', 'uses'=>'BackupsController@delete']); |
|
||||
Route::resource('backups','BackupsController'); |
|
||||
|
|
||||
}); |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue