Test Setup Failed
Pull Request — master (#55)
by
unknown
10:11
created

App::funBackup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 12
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace PavelMironchik\LaravelBackupPanel\Http\Livewire;
4
5
use Livewire\Component;
6
use Livewire\Attributes\On;
7
use Illuminate\Http\Response;
8
use Spatie\Backup\Helpers\Format;
9
use Illuminate\Support\Facades\Cache;
10
use Illuminate\Support\Facades\Storage;
11
use Illuminate\Support\Facades\Validator;
12
use Spatie\Backup\BackupDestination\Backup;
13
use Illuminate\Validation\ValidationException;
14
use PavelMironchik\LaravelBackupPanel\Rules\PathToZip;
15
use Spatie\Backup\BackupDestination\BackupDestination;
16
use Symfony\Component\HttpFoundation\StreamedResponse;
17
use PavelMironchik\LaravelBackupPanel\Rules\BackupDisk;
18
use Spatie\Backup\Tasks\Monitor\BackupDestinationStatus;
19
use PavelMironchik\LaravelBackupPanel\Jobs\CreateBackupJob;
20
use Spatie\Backup\BackupDestination\BackupDestinationFactory;
21
use Spatie\Backup\Tasks\Monitor\BackupDestinationStatusFactory;
22
23
class App extends Component
24
{
25
    public $backupStatuses = [];
26
27
    public $activeDisk = null;
28
29
    public $disks = [];
30
31
    public $files = [];
32
33
    public $deletingFile = null;
34
35
    public function updateBackupStatuses()
36
    {
37
        $this->backupStatuses = Cache::remember('backup-statuses', now()->addSeconds(4), function () {
38
            $monitoredBackupConfig = \Spatie\Backup\Config\MonitoredBackupsConfig::fromArray(config('backup.monitor_backups'));
39
            return BackupDestinationStatusFactory::createForMonitorConfig($monitoredBackupConfig)->map(function (BackupDestinationStatus $backupDestinationStatus){
40
                $destination = $backupDestinationStatus->backupDestination();
41
                return [
42
                    'name' => $destination->backupName(),
43
                    'disk' => $destination->diskName(),
44
                    'reachable' => $destination->isReachable(),
45
                    'healthy' => $backupDestinationStatus->isHealthy(),
46
                    'amount' => $destination->backups()->count(),
47
                    'newest' => $destination->newestBackup()
48
                        ? $backupDestinationStatus->backupDestination()->newestBackup()->date()->diffForHumans()
49
                        : 'No backups present',
50
                    'usedStorage' => Format::humanReadableSize($backupDestinationStatus->backupDestination()->usedStorage()),
51
                ];
52
            })->all();
53
        });
54
            
55
        if (! $this->activeDisk and count($this->backupStatuses)) {
56
            $this->activeDisk = $this->backupStatuses[0]['disk'];
57
        }
58
59
        $this->disks = collect($this->backupStatuses)
60
            ->map(function ($backupStatus) {
61
                return $backupStatus['disk'];
62
            })
63
            ->values()
64
            ->all();
65
        $this->dispatch('backupStatusesUpdated');
66
    }
67
68
    #[On('backupStatusesUpdated')]
69
    public function getFiles(string $disk = '')
70
    {
71
        if ($disk) {
72
            $this->activeDisk = $disk;
73
        }
74
75
        $this->validateActiveDisk();  
76
77
        $backupDestination = BackupDestination::create($this->activeDisk, config('backup.backup.name'));
78
79
        $this->files = Cache::remember("backups-{$this->activeDisk}", now()->addSeconds(4), function () use ($backupDestination) {
80
            return $backupDestination
81
                ->backups()
82
                ->map(function (Backup $backup) {
83
                    $size = method_exists($backup, 'sizeInBytes') ? $backup->sizeInBytes() : $backup->size();
0 ignored issues
show
Bug introduced by
The method size() does not exist on Spatie\Backup\BackupDestination\Backup. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
                    $size = method_exists($backup, 'sizeInBytes') ? $backup->sizeInBytes() : $backup->/** @scrutinizer ignore-call */ size();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
84
                    return [
85
                        'path' => $backup->path(),
86
                        'date' => $backup->date()->format('Y-m-d H:i:s'),
87
                        'size' => Format::humanReadableSize($size),
88
                    ];
89
                })
90
                ->toArray();
91
        });
92
    }
93
94
    public function showDeleteModal($fileIndex)
95
    {
96
        $this->deletingFile = $this->files[$fileIndex];
97
98
        $this->dispatch('showDeleteModal');
99
    }
100
101
    public function deleteFile()
102
    {
103
        $deletingFile = $this->deletingFile;
104
        $this->deletingFile = null;
105
106
        $this->dispatch('hideDeleteModal');
107
108
        $this->validateActiveDisk();
109
        $this->validateFilePath($deletingFile ? $deletingFile['path'] : '');
110
111
        $backupDestination = BackupDestination::create($this->activeDisk, config('backup.backup.name'));
112
113
        $backupDestination
114
            ->backups()
115
            ->first(function (Backup $backup) use ($deletingFile) {
116
                return $backup->path() === $deletingFile['path'];
117
            })
118
            ->delete();
119
120
        $this->files = collect($this->files)
0 ignored issues
show
Bug introduced by
$this->files of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

120
        $this->files = collect(/** @scrutinizer ignore-type */ $this->files)
Loading history...
121
            ->reject(function ($file) use ($deletingFile) {
122
                return $file['path'] === $deletingFile['path']
123
                    && $file['date'] === $deletingFile['date']
124
                    && $file['size'] === $deletingFile['size'];
125
            })
126
            ->values()
127
            ->all();
128
    }
129
130
    public function downloadFile(string $filePath)
131
    {
132
        $this->validateActiveDisk();
133
        $this->validateFilePath($filePath);
134
135
        $backupDestination = BackupDestination::create($this->activeDisk, config('backup.backup.name'));
136
137
        $backup = $backupDestination->backups()->first(function (Backup $backup) use ($filePath) {
138
            return $backup->path() === $filePath;
139
        });
140
141
        if (! $backup) {
142
            return response('Backup not found', Response::HTTP_UNPROCESSABLE_ENTITY);
143
        }
144
145
        return $this->respondWithBackupStream($backup);
146
    }
147
148
    public function respondWithBackupStream(Backup $backup): StreamedResponse
149
    {
150
        $fileName = pathinfo($backup->path(), PATHINFO_BASENAME);
151
        $size = method_exists($backup, 'sizeInBytes') ? $backup->sizeInBytes() : $backup->size();
152
153
        $downloadHeaders = [
154
            'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
155
            'Content-Type' => 'application/zip',
156
            'Content-Length' => $size,
157
            'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
158
            'Pragma' => 'public',
159
        ];
160
161
        return response()->stream(function () use ($backup) {
162
            $stream = $backup->stream();
163
164
            fpassthru($stream);
165
166
            if (is_resource($stream)) {
167
                fclose($stream);
168
            }
169
        }, 200, $downloadHeaders);
170
    }
171
172
    public function createBackup(string $option = '')
173
    {
174
        dispatch(new CreateBackupJob($option))
175
            ->onQueue(config('laravel_backup_panel.queue'));
176
    }
177
178
    public function render()
179
    {
180
        return view('laravel_backup_panel::livewire.app');
181
    }
182
183
    public function funBackup($option = ''){
184
        $this->js("        
185
            Toastify({
186
                text: 'Creating a new backup in the background... ($option)',
187
                duration: 5000,
188
                gravity: 'bottom',
189
                position: 'right',
190
                backgroundColor: '#1fb16e',
191
                className: 'toastify-custom',
192
            }).showToast()
193
        ");
194
        $this->createBackup($option);
195
    }
196
197
    protected function validateActiveDisk()
198
    {
199
        try {
200
            Validator::make(
201
                ['activeDisk' => $this->activeDisk],
202
                [
203
                    'activeDisk' => ['required', new BackupDisk()],
204
                ],
205
                [
206
                    'activeDisk.required' => 'Select a disk',
207
                ]
208
            )->validate();
209
        } catch (ValidationException $e) {
210
            $message = $e->validator->errors()->get('activeDisk')[0];
211
            $this->dispatch('showErrorToast', $message);
212
213
            throw $e;
214
        }
215
    }
216
217
    protected function validateFilePath(string $filePath)
218
    {
219
        try {
220
            Validator::make(
221
                ['file' => $filePath],
222
                [
223
                    'file' => ['required', new PathToZip()],
224
                ],
225
                [
226
                    'file.required' => 'Select a file',
227
                ]
228
            )->validate();
229
        } catch (ValidationException $e) {
230
            $message = $e->validator->errors()->get('file')[0];
231
            $this->dispatch('showErrorToast', $message);
232
233
            throw $e;
234
        }
235
    }
236
}
237