15 changed files with 385 additions and 18 deletions
-
31app/Helpers/functions.php
-
85app/Http/Controllers/BackupsController.php
-
2app/Providers/AppServiceProvider.php
-
1composer.json
-
124composer.lock
-
1config/app.php
-
65resources/views/backups/forms.blade.php
-
54resources/views/backups/index.blade.php
-
4resources/views/users/chart.blade.php
-
6resources/views/users/edit.blade.php
-
8resources/views/users/partials/action-buttons.blade.php
-
2resources/views/users/partials/childs.blade.php
-
8resources/views/users/show.blade.php
-
4resources/views/users/tree.blade.php
-
8routes/web.php
@ -0,0 +1,31 @@ |
|||
<?php |
|||
|
|||
function formatSizeUnits($bytes) |
|||
{ |
|||
if ($bytes >= 1073741824) |
|||
{ |
|||
$bytes = number_format($bytes / 1073741824, 2) . ' GB'; |
|||
} |
|||
elseif ($bytes >= 1048576) |
|||
{ |
|||
$bytes = number_format($bytes / 1048576, 2) . ' MB'; |
|||
} |
|||
elseif ($bytes >= 1024) |
|||
{ |
|||
$bytes = number_format($bytes / 1024, 2) . ' KB'; |
|||
} |
|||
elseif ($bytes > 1) |
|||
{ |
|||
$bytes = $bytes . ' bytes'; |
|||
} |
|||
elseif ($bytes == 1) |
|||
{ |
|||
$bytes = $bytes . ' byte'; |
|||
} |
|||
else |
|||
{ |
|||
$bytes = '0 bytes'; |
|||
} |
|||
|
|||
return $bytes; |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
<?php |
|||
|
|||
namespace App\Http\Controllers; |
|||
|
|||
use App\Http\Controllers\Controller; |
|||
use App\Http\Requests\BackupUploadRequest; |
|||
use BackupManager\Filesystems\Destination; |
|||
use BackupManager\Manager; |
|||
use Illuminate\Http\Request; |
|||
use League\Flysystem\FileExistsException; |
|||
use League\Flysystem\FileNotFoundException; |
|||
|
|||
class BackupsController extends Controller |
|||
{ |
|||
public function index(Request $request) |
|||
{ |
|||
if (!file_exists(storage_path('app/backup/db'))) { |
|||
$backups = []; |
|||
} else { |
|||
$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 view('backups.index',compact('backups')); |
|||
} |
|||
|
|||
public function store(Request $request) |
|||
{ |
|||
$this->validate($request, [ |
|||
'file_name' => 'nullable|max:30|regex:/^[\w._-]+$/' |
|||
]); |
|||
|
|||
try { |
|||
$manager = app()->make(Manager::class); |
|||
$fileName = $request->get('file_name') ?: date('Y-m-d_Hi'); |
|||
|
|||
$manager->makeBackup()->run('mysql', [ |
|||
new Destination('local', 'backup/db/' . $fileName) |
|||
], 'gzip'); |
|||
|
|||
return redirect()->route('backups.index'); |
|||
} catch (FileExistsException $e) { |
|||
return redirect()->route('backups.index'); |
|||
} |
|||
} |
|||
|
|||
public function destroy($fileName) |
|||
{ |
|||
if (file_exists(storage_path('app/backup/db/') . $fileName)) { |
|||
unlink(storage_path('app/backup/db/') . $fileName); |
|||
} |
|||
return redirect()->route('backups.index'); |
|||
} |
|||
|
|||
public function download($fileName) |
|||
{ |
|||
return response()->download(storage_path('app/backup/db/') . $fileName); |
|||
} |
|||
|
|||
public function restore($fileName) |
|||
{ |
|||
try { |
|||
$manager = app()->make(Manager::class); |
|||
$manager->makeRestore()->run('local', 'backup/db/' . $fileName, 'mysql', 'gzip'); |
|||
} catch (FileNotFoundException $e) {} |
|||
|
|||
return redirect()->route('backups.index'); |
|||
} |
|||
|
|||
public function upload(BackupUploadRequest $request) |
|||
{ |
|||
$file = $request->file('backup_file'); |
|||
|
|||
if (file_exists(storage_path('app/backup/db/') . $file->getClientOriginalName()) == false) { |
|||
$file->storeAs('backup/db', $file->getClientOriginalName()); |
|||
} |
|||
|
|||
return redirect()->route('backups.index'); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
@if (Request::get('action') == 'delete' && Request::has('file_name')) |
|||
<div class="panel panel-danger"> |
|||
<div class="panel-heading"> |
|||
<h3 class="panel-title">{{ trans('backup.delete') }}</h3> |
|||
</div> |
|||
<div class="panel-body"> |
|||
<p>{!! trans('backup.sure_to_delete_file', ['filename' => Request::get('file_name')]) !!}</p> |
|||
</div> |
|||
<div class="panel-footer"> |
|||
<a href="{{ route('backups.index') }}" class="btn btn-default">{{ trans('backup.cancel_delete') }}</a> |
|||
<form action="{{ route('backups.destroy', Request::get('file_name')) }}" method="post" class="pull-right"> |
|||
{{ method_field('delete') }} |
|||
{{ csrf_field() }} |
|||
<input type="hidden" name="file_name" value="{{ Request::get('file_name') }}"> |
|||
<input type="submit" class="btn btn-danger" value="{{ trans('backup.confirm_delete') }}"> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
@endif |
|||
@if (Request::get('action') == 'restore' && Request::has('file_name')) |
|||
<div class="panel panel-warning"> |
|||
<div class="panel-heading"><h3 class="panel-title">{{ trans('backup.restore') }}</h3></div> |
|||
<div class="panel-body"> |
|||
<p>{!! trans('backup.sure_to_restore', ['filename' => Request::get('file_name')]) !!}</p> |
|||
</div> |
|||
<div class="panel-footer"> |
|||
<a href="{{ route('backups.index') }}" class="btn btn-default">{{ trans('backup.cancel_restore') }}</a> |
|||
<form action="{{ route('backups.restore', Request::get('file_name')) }}" |
|||
method="post" |
|||
class="pull-right" |
|||
onsubmit="return confirm('Click OK to Restore.')"> |
|||
{{ csrf_field() }} |
|||
<input type="hidden" name="file_name" value="{{ Request::get('file_name') }}"> |
|||
<input type="submit" class="btn btn-warning" value="{{ trans('backup.confirm_restore') }}"> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
@endif |
|||
<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">{{ trans('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="{{ trans('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">{{ trans('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="{{ trans('backup.upload') }}" class="btn btn-primary"> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,54 @@ |
|||
@extends('layouts.app') |
|||
|
|||
@section('title',trans('backup.index_title')) |
|||
|
|||
@section('content') |
|||
<h1 class="page-header">{{ trans('backup.index_title') }}</h1> |
|||
<div class="row"> |
|||
<div class="col-md-8"> |
|||
<div class="panel panel-default table-responsive"> |
|||
<div class="panel-heading"><h3 class="panel-title">{{ trans('backup.list') }}</h3></div> |
|||
<table class="table table-condensed"> |
|||
<thead> |
|||
<th>#</th>
|
|||
<th>{{ trans('backup.file_name') }}</th> |
|||
<th>{{ trans('backup.file_size') }}</th> |
|||
<th>{{ trans('backup.created_at') }}</th> |
|||
<th class="text-center">{{ trans('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="{{ trans('backup.restore') }}">Restore</i></a> |
|||
<a href="{{ route('backups.download', [$backup->getFilename()]) }}" |
|||
id="download_{{ str_replace('.gz', '', $backup->getFilename()) }}" |
|||
class="btn btn-info btn-xs" |
|||
title="{{ trans('backup.download') }}">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="{{ trans('backup.delete') }}">Delete</a> |
|||
</td> |
|||
</tr> |
|||
@empty |
|||
<tr> |
|||
<td colspan="3">{{ trans('backup.empty') }}</td> |
|||
</tr> |
|||
@endforelse |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4"> |
|||
@include('backups.forms') |
|||
</div> |
|||
</div> |
|||
@endsection |
|||
@ -0,0 +1,8 @@ |
|||
<div class="pull-right btn-group" role="group"> |
|||
@can ('edit', $user) |
|||
{{ link_to_route('users.edit', 'Edit Data', [$user->id], ['class' => 'btn btn-warning']) }} |
|||
@endcan |
|||
{{ link_to_route('users.show', 'Lihat Profil '.$user->name, [$user->id], ['class' => Request::segment(3) == null ? 'btn btn-default active' : 'btn btn-default']) }} |
|||
{{ link_to_route('users.chart', 'Lihat Bagan Keluarga', [$user->id], ['class' => Request::segment(3) == 'chart' ? 'btn btn-default active' : 'btn btn-default']) }} |
|||
{{ link_to_route('users.tree', 'Lihat Pohon Keluarga', [$user->id], ['class' => Request::segment(3) == 'tree' ? 'btn btn-default active' : 'btn btn-default']) }} |
|||
</div> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue