1 | <?php |
||
18 | class BackupJob |
||
19 | { |
||
20 | /** @var \Spatie\Backup\Tasks\Backup\FileSelection */ |
||
21 | protected $fileSelection; |
||
22 | |||
23 | /** @var \Illuminate\Support\Collection */ |
||
24 | protected $dbDumpers; |
||
25 | |||
26 | /** @var \Illuminate\Support\Collection */ |
||
27 | protected $backupDestinations; |
||
28 | |||
29 | /** @var string */ |
||
30 | protected $filename; |
||
31 | |||
32 | /** @var \Spatie\TemporaryDirectory\TemporaryDirectory */ |
||
33 | protected $temporaryDirectory; |
||
34 | |||
35 | /** @var bool */ |
||
36 | protected $sendNotifications = true; |
||
37 | |||
38 | public function __construct() |
||
46 | |||
47 | public function dontBackupFilesystem(): self |
||
53 | |||
54 | public function onlyDbName(array $dbNames): self |
||
55 | { |
||
56 | $allowedNames = collect($dbNames); |
||
57 | |||
58 | $filteredDumpers = $this->dbDumpers->filter( |
||
59 | function ($dbDumper, $connectionName) use ($allowedNames) { |
||
60 | return $allowedNames->contains($connectionName); |
||
61 | }); |
||
62 | |||
63 | $this->dbDumpers = $filteredDumpers; |
||
64 | |||
65 | return $this; |
||
66 | } |
||
67 | |||
68 | public function dontBackupDatabases(): self |
||
69 | { |
||
70 | $this->dbDumpers = new Collection(); |
||
71 | |||
72 | return $this; |
||
73 | } |
||
74 | |||
75 | public function disableNotifications(): self |
||
76 | { |
||
77 | $this->sendNotifications = false; |
||
78 | |||
79 | return $this; |
||
80 | } |
||
81 | |||
82 | public function setDefaultFilename(): self |
||
83 | { |
||
84 | $this->filename = Carbon::now()->format('Y-m-d-H-i-s').'.zip'; |
||
85 | |||
86 | return $this; |
||
87 | } |
||
88 | |||
89 | public function setFileSelection(FileSelection $fileSelection): self |
||
90 | { |
||
91 | $this->fileSelection = $fileSelection; |
||
92 | |||
93 | return $this; |
||
94 | } |
||
95 | |||
96 | public function setDbDumpers(Collection $dbDumpers): self |
||
97 | { |
||
98 | $this->dbDumpers = $dbDumpers; |
||
99 | |||
100 | return $this; |
||
101 | } |
||
102 | |||
103 | public function setFilename(string $filename): self |
||
104 | { |
||
105 | $this->filename = $filename; |
||
106 | |||
107 | return $this; |
||
108 | } |
||
109 | |||
110 | public function onlyBackupTo(string $diskName): self |
||
111 | { |
||
112 | $this->backupDestinations = $this->backupDestinations->filter(function (BackupDestination $backupDestination) use ($diskName) { |
||
113 | return $backupDestination->diskName() === $diskName; |
||
114 | }); |
||
115 | |||
116 | if (! count($this->backupDestinations)) { |
||
117 | throw InvalidBackupJob::destinationDoesNotExist($diskName); |
||
118 | } |
||
119 | |||
120 | return $this; |
||
121 | } |
||
122 | |||
123 | public function setBackupDestinations(Collection $backupDestinations): self |
||
124 | { |
||
125 | $this->backupDestinations = $backupDestinations; |
||
126 | |||
127 | return $this; |
||
128 | } |
||
129 | |||
130 | public function run() |
||
131 | { |
||
132 | $this->temporaryDirectory = (new TemporaryDirectory(storage_path('app/backup-temp'))) |
||
133 | ->name('temp') |
||
134 | ->force() |
||
135 | ->create() |
||
136 | ->empty(); |
||
137 | |||
138 | try { |
||
139 | if (! count($this->backupDestinations)) { |
||
140 | throw InvalidBackupJob::noDestinationsSpecified(); |
||
141 | } |
||
142 | |||
143 | $manifest = $this->createBackupManifest(); |
||
144 | |||
145 | if (! $manifest->count()) { |
||
146 | throw InvalidBackupJob::noFilesToBeBackedUp(); |
||
147 | } |
||
148 | |||
149 | $zipFile = $this->createZipContainingEveryFileInManifest($manifest); |
||
150 | |||
151 | $this->copyToBackupDestinations($zipFile); |
||
152 | } catch (Exception $exception) { |
||
153 | consoleOutput()->error("Backup failed because {$exception->getMessage()}.".PHP_EOL.$exception->getTraceAsString()); |
||
|
|||
154 | |||
155 | $this->sendNotification(new BackupHasFailed($exception)); |
||
156 | |||
157 | $this->temporaryDirectory->delete(); |
||
158 | |||
159 | throw $exception; |
||
160 | } |
||
161 | |||
162 | $this->temporaryDirectory->delete(); |
||
163 | } |
||
164 | |||
165 | protected function createBackupManifest(): Manifest |
||
179 | |||
180 | public function filesToBeBackedUp() |
||
186 | |||
187 | protected function directoriesUsedByBackupJob(): array |
||
202 | |||
203 | protected function createZipContainingEveryFileInManifest(Manifest $manifest) |
||
217 | |||
218 | /** |
||
219 | * Dumps the databases to the given directory. |
||
220 | * Returns an array with paths to the dump files. |
||
221 | * |
||
222 | * @return array |
||
223 | */ |
||
224 | protected function dumpDatabases(): array |
||
250 | |||
251 | protected function copyToBackupDestinations(string $path) |
||
252 | { |
||
253 | $this->backupDestinations->each(function (BackupDestination $backupDestination) use ($path) { |
||
254 | try { |
||
255 | consoleOutput()->info("Copying zip to disk named {$backupDestination->diskName()}..."); |
||
256 | |||
257 | $backupDestination->write($path); |
||
258 | |||
259 | consoleOutput()->info("Successfully copied zip to disk named {$backupDestination->diskName()}."); |
||
260 | |||
269 | |||
270 | protected function sendNotification($notification) |
||
276 | } |
||
277 |
If you implement
__call
and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.This is often the case, when
__call
is implemented by a parent class and only the child class knows which methods exist: