From c88103ca13f850214f3be0ae22e7a6a3361802ca Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:46:14 +0200 Subject: [PATCH 01/33] init Rector --- composer.json | 8 +++++--- phpstan.neon.dist | 3 +-- rector.php | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 rector.php diff --git a/composer.json b/composer.json index 173939cf..9094525a 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,8 @@ "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1" + "phpstan/phpstan-phpunit": "^1.1", + "rector/rector": "^1.1" }, "autoload": { "psr-4": { @@ -61,9 +62,10 @@ } }, "scripts": { - "test": "vendor/bin/pest", + "test": "vendor/bin/pest --compact", "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes", - "analyse": "vendor/bin/phpstan analyse" + "analyse": "vendor/bin/phpstan analyse", + "rector": "./vendor/bin/rector --dry-run" }, "suggest": { "laravel/slack-notification-channel": "Required for sending notifications via Slack" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2670010c..9bfe1ece 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,14 +2,13 @@ includes: - phpstan-baseline.neon parameters: - level: 5 + level: max paths: - src - config tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true - checkMissingIterableValueType: false ignoreErrors: - '#Unsafe usage of new static#' diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..eb66deb4 --- /dev/null +++ b/rector.php @@ -0,0 +1,26 @@ +withPaths([ + __DIR__ . '/config', + __DIR__ . '/resources', + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withPhpSets(php81: true) + ->withRules([ + AddVoidReturnTypeWhereNoReturnRector::class, + ]) + ->withSkip([ + ReturnNeverTypeRector::class, + OptionalParametersAfterRequiredRector::class, + ClosureToArrowFunctionRector::class, + ]); From 25e2e3ba7daf3b8cfddf4267e6e7445b03207d62 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:48:09 +0200 Subject: [PATCH 02/33] apply rector for 8.1 --- composer.json | 3 ++- phpstan-baseline.neon | 9 +++++++++ phpstan.neon.dist | 2 +- src/BackupDestination/BackupDestination.php | 15 ++------------- src/BackupServiceProvider.php | 4 ++-- src/Commands/CleanupCommand.php | 6 +----- .../Channels/Discord/DiscordMessage.php | 2 +- src/Tasks/Backup/BackupJob.php | 2 +- src/Tasks/Backup/DbDumperFactory.php | 4 ++-- src/Tasks/Backup/FileSelection.php | 2 +- src/Tasks/Backup/Manifest.php | 8 ++------ src/Tasks/Backup/Zip.php | 10 +++------- src/Tasks/Cleanup/CleanupJob.php | 12 ++---------- src/Tasks/Cleanup/Strategies/DefaultStrategy.php | 2 +- tests/BackupDestination/BackupTest.php | 6 +++--- tests/Commands/BackupCommandTest.php | 2 +- tests/Commands/CleanupCommandTest.php | 2 +- tests/Commands/MonitorCommandTest.php | 2 +- tests/FormatTest.php | 6 +++--- tests/TestCase.php | 2 +- 20 files changed, 40 insertions(+), 61 deletions(-) diff --git a/composer.json b/composer.json index 9094525a..ffaea00b 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,8 @@ "test": "vendor/bin/pest --compact", "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes", "analyse": "vendor/bin/phpstan analyse", - "rector": "./vendor/bin/rector --dry-run" + "rector": "./vendor/bin/rector --dry-run", + "baseline": "./vendor/bin/phpstan analyse --generate-baseline --memory-limit=2G" }, "suggest": { "laravel/slack-notification-channel": "Required for sending notifications via Slack" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 364905f7..41478adf 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,2 +1,11 @@ parameters: ignoreErrors: + - + message: "#^Deprecated in PHP 8\\.0\\: Required parameter \\$diskName follows optional parameter \\$disk\\.$#" + count: 1 + path: src/BackupDestination/BackupDestination.php + + - + message: "#^Deprecated in PHP 8\\.1\\: Required parameter \\$backupName follows optional parameter \\$disk\\.$#" + count: 1 + path: src/BackupDestination/BackupDestination.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9bfe1ece..81a4e5b0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,7 +2,7 @@ includes: - phpstan-baseline.neon parameters: - level: max + level: 5 paths: - src - config diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index 9c689f6a..ea271602 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -10,23 +10,12 @@ class BackupDestination { - protected ?Filesystem $disk; - - protected string $diskName; - - protected string $backupName; - public ?Exception $connectionError = null; protected ?BackupCollection $backupCollectionCache = null; - public function __construct(Filesystem $disk = null, string $backupName, string $diskName) + public function __construct(protected ?Filesystem $disk = null, protected string $backupName, protected string $diskName) { - $this->disk = $disk; - - $this->diskName = $diskName; - - $this->backupName = $backupName; } public function disk(): Filesystem @@ -49,7 +38,7 @@ public function filesystemType(): string $filesystemType = last(explode('\\', $adapterClass)); - return strtolower($filesystemType); + return strtolower((string) $filesystemType); } public static function create(string $diskName, string $backupName): self diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index 64e4c663..8e460d53 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -34,7 +34,7 @@ public function configurePackage(Package $package): void ]); } - public function packageBooted() + public function packageBooted(): void { $this->app['events']->subscribe(EventHandler::class); @@ -43,7 +43,7 @@ public function packageBooted() } } - public function packageRegistered() + public function packageRegistered(): void { $this->app->singleton(ConsoleOutput::class); diff --git a/src/Commands/CleanupCommand.php b/src/Commands/CleanupCommand.php index d770f07e..28551e3f 100644 --- a/src/Commands/CleanupCommand.php +++ b/src/Commands/CleanupCommand.php @@ -20,13 +20,9 @@ class CleanupCommand extends BaseCommand implements Isolatable /** @var string */ protected $description = 'Remove all backups older than specified number of days in config.'; - protected CleanupStrategy $strategy; - - public function __construct(CleanupStrategy $strategy) + public function __construct(protected CleanupStrategy $strategy) { parent::__construct(); - - $this->strategy = $strategy; } public function handle(): int diff --git a/src/Notifications/Channels/Discord/DiscordMessage.php b/src/Notifications/Channels/Discord/DiscordMessage.php index 8854aef2..b6bb5341 100644 --- a/src/Notifications/Channels/Discord/DiscordMessage.php +++ b/src/Notifications/Channels/Discord/DiscordMessage.php @@ -120,7 +120,7 @@ public function toArray(): array 'type' => 'rich', 'description' => $this->description, 'fields' => $this->fields, - 'color' => hexdec($this->color), + 'color' => hexdec((string) $this->color), 'footer' => [ 'text' => $this->footer ?? '', ], diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index 952cb57e..c425cac5 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -249,7 +249,7 @@ protected function dumpDatabases(): array ->map(function (DbDumper $dbDumper, $key) { consoleOutput()->info("Dumping database {$dbDumper->getDbName()}..."); - $dbType = mb_strtolower(basename(str_replace('\\', '/', get_class($dbDumper)))); + $dbType = mb_strtolower(basename(str_replace('\\', '/', $dbDumper::class))); if (config('backup.backup.database_dump_filename_base') === 'connection') { diff --git a/src/Tasks/Backup/DbDumperFactory.php b/src/Tasks/Backup/DbDumperFactory.php index d62ff378..c416abd1 100644 --- a/src/Tasks/Backup/DbDumperFactory.php +++ b/src/Tasks/Backup/DbDumperFactory.php @@ -69,14 +69,14 @@ public static function createFromConnection(string $dbConnectionName): DbDumper return $dbDumper; } - public static function extend(string $driver, callable $callback) + public static function extend(string $driver, callable $callback): void { static::$custom[$driver] = $callback; } protected static function forDriver($dbDriver): DbDumper { - $driver = strtolower($dbDriver); + $driver = strtolower((string) $dbDriver); if (isset(static::$custom[$driver])) { return (static::$custom[$driver])(); diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index 93a03958..84071495 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -140,6 +140,6 @@ protected function getMatchingPaths(string $path): array protected function canUseGlobBrace(string $path): bool { - return strpos($path, '*') !== false && defined('GLOB_BRACE'); + return str_contains($path, '*') && defined('GLOB_BRACE'); } } diff --git a/src/Tasks/Backup/Manifest.php b/src/Tasks/Backup/Manifest.php index 69894cfe..fe6c233b 100644 --- a/src/Tasks/Backup/Manifest.php +++ b/src/Tasks/Backup/Manifest.php @@ -8,18 +8,14 @@ class Manifest implements Countable { - protected string $manifestPath; - public static function create(string $manifestPath): self { return new static($manifestPath); } - public function __construct(string $manifestPath) + public function __construct(protected string $manifestPath) { - $this->manifestPath = $manifestPath; - - touch($manifestPath); + touch($this->manifestPath); } public function path(): string diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index 3dbcbf1f..bf5c1a48 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -12,12 +12,10 @@ class Zip protected int $fileCount = 0; - protected string $pathToZip; - public static function createForManifest(Manifest $manifest, string $pathToZip): self { $relativePath = config('backup.backup.source.files.relative_path') ? - rtrim(config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : false; + rtrim((string) config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : false; $zip = new static($pathToZip); @@ -49,12 +47,10 @@ protected static function determineNameOfFileInZip(string $pathToFile, string $p return $pathToFile; } - public function __construct(string $pathToZip) + public function __construct(protected string $pathToZip) { $this->zipFile = new ZipArchive(); - $this->pathToZip = $pathToZip; - $this->open(); } @@ -106,7 +102,7 @@ public function add(string | iterable $files, string $nameInZip = null): self } if (is_file($file)) { - $this->zipFile->addFile($file, ltrim($nameInZip, DIRECTORY_SEPARATOR)); + $this->zipFile->addFile($file, ltrim((string) $nameInZip, DIRECTORY_SEPARATOR)); if (is_int($compressionMethod)) { $this->zipFile->setCompressionName( diff --git a/src/Tasks/Cleanup/CleanupJob.php b/src/Tasks/Cleanup/CleanupJob.php index d327cda5..c782e426 100644 --- a/src/Tasks/Cleanup/CleanupJob.php +++ b/src/Tasks/Cleanup/CleanupJob.php @@ -11,21 +11,13 @@ class CleanupJob { - protected Collection $backupDestinations; - - protected CleanupStrategy $strategy; - protected bool $sendNotifications = true; public function __construct( - Collection $backupDestinations, - CleanupStrategy $strategy, + protected Collection $backupDestinations, + protected CleanupStrategy $strategy, bool $disableNotifications = false, ) { - $this->backupDestinations = $backupDestinations; - - $this->strategy = $strategy; - $this->sendNotifications = ! $disableNotifications; } diff --git a/src/Tasks/Cleanup/Strategies/DefaultStrategy.php b/src/Tasks/Cleanup/Strategies/DefaultStrategy.php index 81152de4..f73dca91 100644 --- a/src/Tasks/Cleanup/Strategies/DefaultStrategy.php +++ b/src/Tasks/Cleanup/Strategies/DefaultStrategy.php @@ -13,7 +13,7 @@ class DefaultStrategy extends CleanupStrategy { protected ?Backup $newestBackup = null; - public function deleteOldBackups(BackupCollection $backups) + public function deleteOldBackups(BackupCollection $backups): void { // Don't ever delete the newest backup. $this->newestBackup = $backups->shift(); diff --git a/tests/BackupDestination/BackupTest.php b/tests/BackupDestination/BackupTest.php index 4dd6bf4d..9767eabd 100644 --- a/tests/BackupDestination/BackupTest.php +++ b/tests/BackupDestination/BackupTest.php @@ -62,7 +62,7 @@ }); it('can determine its size', function () { - $backup = getBackupForFile('test.zip', 0, 'this backup has content'); + $backup = getBackupForFile('test.zip', 0); $fileSize = floatval(Storage::disk('local')->size('mysite.com/test.zip')); @@ -72,7 +72,7 @@ }); it('can determine its size even after it has been deleted', function () { - $backup = getBackupForFile('test.zip', 0, 'this backup has content'); + $backup = getBackupForFile('test.zip', 0); $backup->delete(); @@ -113,7 +113,7 @@ }); it('need a float type size', function () { - $backup = getBackupForFile('test.zip', 0, 'this backup has content'); + $backup = getBackupForFile('test.zip', 0); expect($backup->sizeInBytes())->toBeFloat(); }); diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php index 446af30b..aa157cd1 100644 --- a/tests/Commands/BackupCommandTest.php +++ b/tests/Commands/BackupCommandTest.php @@ -123,7 +123,7 @@ } $zip->close(); - expect($zipFile)->toStartWith(ltrim($this->getStubDirectory(), DIRECTORY_SEPARATOR)); + expect($zipFile)->toStartWith(ltrim((string) $this->getStubDirectory(), DIRECTORY_SEPARATOR)); }); it('excludes the temporary directory from the backup', function () { diff --git a/tests/Commands/CleanupCommandTest.php b/tests/Commands/CleanupCommandTest.php index 1e717e4c..4ff893e1 100644 --- a/tests/Commands/CleanupCommandTest.php +++ b/tests/Commands/CleanupCommandTest.php @@ -35,7 +35,7 @@ return [ $this->createFileOnDisk('local', "mysite/test_{$date->format('Ymd')}_first.zip", $date), - $this->createFileOnDisk('local', "mysite/test_{$date->format('Ymd')}_second.zip", $date->addHour(2)), + $this->createFileOnDisk('local', "mysite/test_{$date->format('Ymd')}_second.zip", $date->addHours(2)), ]; })->partition(function (string $backupPath) { return in_array($backupPath, [ diff --git a/tests/Commands/MonitorCommandTest.php b/tests/Commands/MonitorCommandTest.php index a43b7c32..ccc28270 100644 --- a/tests/Commands/MonitorCommandTest.php +++ b/tests/Commands/MonitorCommandTest.php @@ -7,7 +7,7 @@ class MonitorCommandTest extends TestCase { /** @test */ - public function it_warns_the_user_about_the_old_style_config_keys() + public function it_warns_the_user_about_the_old_style_config_keys(): void { $this->artisan('backup:monitor') ->assertSuccessful(); diff --git a/tests/FormatTest.php b/tests/FormatTest.php index dd4bb4e0..a61d0eea 100644 --- a/tests/FormatTest.php +++ b/tests/FormatTest.php @@ -18,7 +18,7 @@ Carbon::setTestNow(Carbon::create(2016, 1, 1)->startOfDay()); expect(Format::ageInDays(Carbon::now()->subSeconds(5)))->toEqual('0.00 (5 seconds ago)'); - expect(Format::ageInDays(Carbon::now()->subHour(1)))->toEqual('0.04 (1 hour ago)'); - expect(Format::ageInDays(Carbon::now()->subHour(1)->subDay(1)))->toEqual('1.04 (1 day ago)'); - expect(Format::ageInDays(Carbon::now()->subHour(1)->subMonths(1)))->toEqual('30.04 (4 weeks ago)'); + expect(Format::ageInDays(Carbon::now()->subHour()))->toEqual('0.04 (1 hour ago)'); + expect(Format::ageInDays(Carbon::now()->subHour()->subDay()))->toEqual('1.04 (1 day ago)'); + expect(Format::ageInDays(Carbon::now()->subHour()->subMonths(1)))->toEqual('30.04 (4 weeks ago)'); }); diff --git a/tests/TestCase.php b/tests/TestCase.php index 27f4ce42..67ba0c7f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -206,7 +206,7 @@ public function getTempDirectory(?string $file = null): string return __DIR__.'/temp'.($file ? '/'.$file : ''); } - public function initializeTempDirectory() + public function initializeTempDirectory(): void { $this->initializeDirectory($this->getTempDirectory()); } From 46b98e38cb175f5258bb008bccb4331f99c6d5cb Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 7 Jun 2024 07:53:49 +0000 Subject: [PATCH 03/33] Fix styling --- rector.php | 8 ++++---- src/BackupDestination/BackupDestination.php | 2 +- src/Commands/ListCommand.php | 4 ++-- src/Commands/MonitorCommand.php | 2 +- src/Exceptions/CannotCreateDbDumper.php | 2 +- src/Helpers/ConsoleOutput.php | 1 + src/Helpers/File.php | 2 +- .../Channels/Discord/DiscordMessage.php | 4 +++- src/Notifications/EventHandler.php | 2 +- src/Notifications/Notifiable.php | 2 +- .../HealthyBackupWasFoundNotification.php | 2 +- src/Tasks/Backup/BackupJob.php | 19 ++++++++----------- src/Tasks/Backup/FileSelection.php | 12 ++++++------ src/Tasks/Backup/Manifest.php | 4 ++-- src/Tasks/Backup/Zip.php | 8 ++++---- src/Tasks/Monitor/BackupDestinationStatus.php | 2 +- .../BackupDestinationStatusFactory.php | 4 ++-- src/Traits/Retryable.php | 6 +++--- tests/Commands/BackupCommandTest.php | 2 -- tests/Commands/ListCommandTest.php | 2 +- tests/Commands/MonitorCommandTest.php | 2 +- tests/DbDumperFactoryTest.php | 1 - tests/FileSelectionTest.php | 7 +++---- tests/FormatTest.php | 1 - tests/Listeners/EncryptBackupArchiveTest.php | 2 +- tests/ManifestTest.php | 1 - tests/Pest.php | 4 ++-- tests/TestCase.php | 8 +++----- 28 files changed, 54 insertions(+), 62 deletions(-) diff --git a/rector.php b/rector.php index eb66deb4..378933ec 100644 --- a/rector.php +++ b/rector.php @@ -10,10 +10,10 @@ return RectorConfig::configure() ->withPaths([ - __DIR__ . '/config', - __DIR__ . '/resources', - __DIR__ . '/src', - __DIR__ . '/tests', + __DIR__.'/config', + __DIR__.'/resources', + __DIR__.'/src', + __DIR__.'/tests', ]) ->withPhpSets(php81: true) ->withRules([ diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index ea271602..73d6f684 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -14,7 +14,7 @@ class BackupDestination protected ?BackupCollection $backupCollectionCache = null; - public function __construct(protected ?Filesystem $disk = null, protected string $backupName, protected string $diskName) + public function __construct(protected ?Filesystem $disk, protected string $backupName, protected string $diskName) { } diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index ac9cada7..cf63ca23 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -20,7 +20,7 @@ class ListCommand extends BaseCommand public function handle(): int { if (config()->has('backup.monitorBackups')) { - $this->warn("Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups."); + $this->warn('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); } $statuses = BackupDestinationStatusFactory::createForMonitorConfig(config('backup.monitor_backups')); @@ -98,7 +98,7 @@ protected function displayFailures(Collection $backupDestinationStatuses) return $this; } - protected function getFormattedBackupDate(Backup $backup = null) + protected function getFormattedBackupDate(?Backup $backup = null) { return is_null($backup) ? 'No backups present' diff --git a/src/Commands/MonitorCommand.php b/src/Commands/MonitorCommand.php index f68040bf..652cda42 100644 --- a/src/Commands/MonitorCommand.php +++ b/src/Commands/MonitorCommand.php @@ -18,7 +18,7 @@ class MonitorCommand extends BaseCommand implements Isolatable public function handle(): int { if (config()->has('backup.monitorBackups')) { - $this->warn("Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups."); + $this->warn('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); } $hasError = false; diff --git a/src/Exceptions/CannotCreateDbDumper.php b/src/Exceptions/CannotCreateDbDumper.php index dca0e6bf..9680b20b 100644 --- a/src/Exceptions/CannotCreateDbDumper.php +++ b/src/Exceptions/CannotCreateDbDumper.php @@ -8,7 +8,7 @@ class CannotCreateDbDumper extends Exception { public static function unsupportedDriver(string $driver): self { - $supportedDrivers = collect(config("database.connections"))->keys(); + $supportedDrivers = collect(config('database.connections'))->keys(); $formattedSupportedDrivers = $supportedDrivers ->map(fn (string $supportedDriver) => "`$supportedDriver`") diff --git a/src/Helpers/ConsoleOutput.php b/src/Helpers/ConsoleOutput.php index dbe2728f..72107288 100644 --- a/src/Helpers/ConsoleOutput.php +++ b/src/Helpers/ConsoleOutput.php @@ -6,6 +6,7 @@ /** * @phpstan-ignore-next-line + * * @mixin \Illuminate\Console\Concerns\InteractsWithIO */ class ConsoleOutput diff --git a/src/Helpers/File.php b/src/Helpers/File.php index c1f6b2d8..bcf7a2fe 100644 --- a/src/Helpers/File.php +++ b/src/Helpers/File.php @@ -32,7 +32,7 @@ protected function hasAllowedMimeType(?Filesystem $disk, string $path): bool return in_array($this->mimeType($disk, $path), self::$allowedMimeTypes); } - protected function mimeType(?Filesystem $disk, string $path): bool | string + protected function mimeType(?Filesystem $disk, string $path): bool|string { try { if ($disk && method_exists($disk, 'mimeType')) { diff --git a/src/Notifications/Channels/Discord/DiscordMessage.php b/src/Notifications/Channels/Discord/DiscordMessage.php index b6bb5341..b7bf6555 100644 --- a/src/Notifications/Channels/Discord/DiscordMessage.php +++ b/src/Notifications/Channels/Discord/DiscordMessage.php @@ -7,7 +7,9 @@ class DiscordMessage { public const COLOR_SUCCESS = '0b6623'; + public const COLOR_WARNING = 'fD6a02'; + public const COLOR_ERROR = 'e32929'; protected string $username = 'Laravel Backup'; @@ -28,7 +30,7 @@ class DiscordMessage protected string $url = ''; - public function from(string $username, string $avatarUrl = null): self + public function from(string $username, ?string $avatarUrl = null): self { $this->username = $username; diff --git a/src/Notifications/EventHandler.php b/src/Notifications/EventHandler.php index 5feb46e0..25c20f3a 100644 --- a/src/Notifications/EventHandler.php +++ b/src/Notifications/EventHandler.php @@ -40,7 +40,7 @@ protected function determineNotifiable() protected function determineNotification($event): Notification { - $lookingForNotificationClass = class_basename($event) . "Notification"; + $lookingForNotificationClass = class_basename($event).'Notification'; $notificationClass = collect($this->config->get('backup.notifications.notifications')) ->keys() diff --git a/src/Notifications/Notifiable.php b/src/Notifications/Notifiable.php index f20549a2..13e30475 100644 --- a/src/Notifications/Notifiable.php +++ b/src/Notifications/Notifiable.php @@ -8,7 +8,7 @@ class Notifiable { use NotifiableTrait; - public function routeNotificationForMail(): string | array + public function routeNotificationForMail(): string|array { return config('backup.notifications.mail.to'); } diff --git a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php index 6ed4a9e8..eb10b85f 100644 --- a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php @@ -49,7 +49,7 @@ public function toDiscord(): DiscordMessage ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) ->title( trans('backup::notifications.healthy_backup_found_subject_title', [ - 'application_name' => $this->applicationName(), + 'application_name' => $this->applicationName(), ]) )->fields($this->backupDestinationProperties()->toArray()); } diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index c425cac5..662acfda 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -170,7 +170,7 @@ public function run(): void $this->copyToBackupDestinations($zipFile); } catch (Exception $exception) { - consoleOutput()->error("Backup failed because: {$exception->getMessage()}." . PHP_EOL . $exception->getTraceAsString()); + consoleOutput()->error("Backup failed because: {$exception->getMessage()}.".PHP_EOL.$exception->getTraceAsString()); $this->temporaryDirectory->delete(); @@ -211,7 +211,7 @@ protected function directoriesUsedByBackupJob(): array return $this->backupDestinations ->filter(fn (BackupDestination $backupDestination) => $backupDestination->filesystemType() === 'localfilesystemadapter') ->map( - fn (BackupDestination $backupDestination) => $backupDestination->disk()->path('') . $backupDestination->backupName() + fn (BackupDestination $backupDestination) => $backupDestination->disk()->path('').$backupDestination->backupName() ) ->each(fn (string $backupDestinationDirectory) => $this->fileSelection->excludeFilesFrom($backupDestinationDirectory)) ->push($this->temporaryDirectory->path()) @@ -222,7 +222,7 @@ protected function createZipContainingEveryFileInManifest(Manifest $manifest): s { consoleOutput()->info("Zipping {$manifest->count()} files and directories..."); - $pathToZip = $this->temporaryDirectory->path(config('backup.backup.destination.filename_prefix') . $this->filename); + $pathToZip = $this->temporaryDirectory->path(config('backup.backup.destination.filename_prefix').$this->filename); $zip = Zip::createForManifest($manifest, $pathToZip); @@ -240,8 +240,6 @@ protected function createZipContainingEveryFileInManifest(Manifest $manifest): s /** * Dumps the databases to the given directory. * Returns an array with paths to the dump files. - * - * @return array */ protected function dumpDatabases(): array { @@ -251,33 +249,32 @@ protected function dumpDatabases(): array $dbType = mb_strtolower(basename(str_replace('\\', '/', $dbDumper::class))); - if (config('backup.backup.database_dump_filename_base') === 'connection') { $dbName = $key; } elseif ($dbDumper instanceof Sqlite) { - $dbName = $key . '-database'; + $dbName = $key.'-database'; } else { $dbName = $dbDumper->getDbName(); } $timeStamp = ''; if ($timeStampFormat = config('backup.backup.database_dump_file_timestamp_format')) { - $timeStamp = '-' . Carbon::now()->format($timeStampFormat); + $timeStamp = '-'.Carbon::now()->format($timeStampFormat); } $fileName = "{$dbType}-{$dbName}{$timeStamp}.{$this->getExtension($dbDumper)}"; if (config('backup.backup.gzip_database_dump')) { $dbDumper->useCompressor(new GzipCompressor()); - $fileName .= '.' . $dbDumper->getCompressorExtension(); + $fileName .= '.'.$dbDumper->getCompressorExtension(); } if ($compressor = config('backup.backup.database_dump_compressor')) { $dbDumper->useCompressor(new $compressor()); - $fileName .= '.' . $dbDumper->getCompressorExtension(); + $fileName .= '.'.$dbDumper->getCompressorExtension(); } - $temporaryFilePath = $this->temporaryDirectory->path('db-dumps' . DIRECTORY_SEPARATOR . $fileName); + $temporaryFilePath = $this->temporaryDirectory->path('db-dumps'.DIRECTORY_SEPARATOR.$fileName); event(new DumpingDatabase($dbDumper)); diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index 84071495..ff51274e 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -17,19 +17,19 @@ class FileSelection protected bool $shouldIgnoreUnreadableDirs = false; - public static function create(array | string $includeFilesAndDirectories = []): self + public static function create(array|string $includeFilesAndDirectories = []): self { return new static($includeFilesAndDirectories); } - public function __construct(array | string $includeFilesAndDirectories = []) + public function __construct(array|string $includeFilesAndDirectories = []) { $this->includeFilesAndDirectories = collect($includeFilesAndDirectories); $this->excludeFilesAndDirectories = collect(); } - public function excludeFilesFrom(array | string $excludeFilesAndDirectories): self + public function excludeFilesFrom(array|string $excludeFilesAndDirectories): self { $this->excludeFilesAndDirectories = $this->excludeFilesAndDirectories->merge($this->sanitize($excludeFilesAndDirectories)); @@ -50,7 +50,7 @@ public function shouldIgnoreUnreadableDirs(bool $ignoreUnreadableDirs): self return $this; } - public function selectedFiles(): Generator | array + public function selectedFiles(): Generator|array { if ($this->includeFilesAndDirectories->isEmpty()) { return []; @@ -105,7 +105,7 @@ protected function shouldExclude(string $path): bool { $path = realpath($path); if (is_dir($path)) { - $path .= DIRECTORY_SEPARATOR ; + $path .= DIRECTORY_SEPARATOR; } foreach ($this->excludeFilesAndDirectories as $excludedPath) { if (Str::startsWith($path, $excludedPath.(is_dir($excludedPath) ? DIRECTORY_SEPARATOR : ''))) { @@ -120,7 +120,7 @@ protected function shouldExclude(string $path): bool return false; } - protected function sanitize(string | array $paths): Collection + protected function sanitize(string|array $paths): Collection { return collect($paths) ->reject(fn ($path) => $path === '') diff --git a/src/Tasks/Backup/Manifest.php b/src/Tasks/Backup/Manifest.php index fe6c233b..330b23b9 100644 --- a/src/Tasks/Backup/Manifest.php +++ b/src/Tasks/Backup/Manifest.php @@ -23,7 +23,7 @@ public function path(): string return $this->manifestPath; } - public function addFiles(array | string | Generator $filePaths): self + public function addFiles(array|string|Generator $filePaths): self { if (is_string($filePaths)) { $filePaths = [$filePaths]; @@ -38,7 +38,7 @@ public function addFiles(array | string | Generator $filePaths): self return $this; } - public function files(): Generator | array + public function files(): Generator|array { $file = new SplFileObject($this->path()); diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index bf5c1a48..d6d664a0 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -15,7 +15,7 @@ class Zip public static function createForManifest(Manifest $manifest, string $pathToZip): self { $relativePath = config('backup.backup.source.files.relative_path') ? - rtrim((string) config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : false; + rtrim((string) config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR : false; $zip = new static($pathToZip); @@ -32,9 +32,9 @@ public static function createForManifest(Manifest $manifest, string $pathToZip): protected static function determineNameOfFileInZip(string $pathToFile, string $pathToZip, string $relativePath) { - $fileDirectory = pathinfo($pathToFile, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR; + $fileDirectory = pathinfo($pathToFile, PATHINFO_DIRNAME).DIRECTORY_SEPARATOR; - $zipDirectory = pathinfo($pathToZip, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR; + $zipDirectory = pathinfo($pathToZip, PATHINFO_DIRNAME).DIRECTORY_SEPARATOR; if (Str::startsWith($fileDirectory, $zipDirectory)) { return substr($pathToFile, strlen($zipDirectory)); @@ -83,7 +83,7 @@ public function close(): void $this->zipFile->close(); } - public function add(string | iterable $files, string $nameInZip = null): self + public function add(string|iterable $files, ?string $nameInZip = null): self { if (is_array($files)) { $nameInZip = null; diff --git a/src/Tasks/Monitor/BackupDestinationStatus.php b/src/Tasks/Monitor/BackupDestinationStatus.php index e63e8900..5908ef7d 100644 --- a/src/Tasks/Monitor/BackupDestinationStatus.php +++ b/src/Tasks/Monitor/BackupDestinationStatus.php @@ -22,7 +22,7 @@ public function backupDestination(): BackupDestination return $this->backupDestination; } - public function check(HealthCheck $check): bool | HealthCheckFailure + public function check(HealthCheck $check): bool|HealthCheckFailure { try { $check->checkHealth($this->backupDestination()); diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index 061b3132..81036302 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -12,7 +12,7 @@ public static function createForMonitorConfig(array $monitorConfiguration): Coll { return collect($monitorConfiguration) ->flatMap(fn (array $monitorProperties) => self::createForSingleMonitor($monitorProperties)) - ->sortBy(fn (BackupDestinationStatus $backupDestinationStatus) => $backupDestinationStatus->backupDestination()->backupName() . '-' . + ->sortBy(fn (BackupDestinationStatus $backupDestinationStatus) => $backupDestinationStatus->backupDestination()->backupName().'-'. $backupDestinationStatus->backupDestination()->diskName()); } @@ -39,7 +39,7 @@ protected static function buildHealthChecks($monitorConfig): array })->toArray(); } - protected static function buildHealthCheck(string $class, string | array $options): HealthCheck + protected static function buildHealthCheck(string $class, string|array $options): HealthCheck { if (! is_array($options)) { return new $class($options); diff --git a/src/Traits/Retryable.php b/src/Traits/Retryable.php index b0ef0fb6..69a973c2 100644 --- a/src/Traits/Retryable.php +++ b/src/Traits/Retryable.php @@ -32,16 +32,16 @@ protected function sleepFor(int $seconds = 0) protected function setTries(string $type) { if ($this->option('tries')) { - $this->tries = (int)$this->option('tries'); + $this->tries = (int) $this->option('tries'); return; } - $this->tries = (int)config('backup.' . $type . '.tries', 1); + $this->tries = (int) config('backup.'.$type.'.tries', 1); } protected function getRetryDelay(string $type) { - return (int)config('backup.' . $type . '.retry_delay', 0); + return (int) config('backup.'.$type.'.retry_delay', 0); } } diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php index aa157cd1..c35e1498 100644 --- a/tests/Commands/BackupCommandTest.php +++ b/tests/Commands/BackupCommandTest.php @@ -386,7 +386,6 @@ expect($zip->statIndex(0)['comp_method'])->toBe(ZipArchive::CM_DEFLATE); $zip->close(); - // check no compression with ZipArchive::CM_STORE method config()->set('backup.backup.destination.compression_method', ZipArchive::CM_STORE); config()->set('backup.backup.destination.compression_level', 0); @@ -399,7 +398,6 @@ expect($zip->statIndex(0)['comp_method'])->toBe(ZipArchive::CM_STORE); $zip->close(); - // check ZipArchive::CM_DEFLATE method with custom compression level config()->set('backup.backup.destination.compression_method', ZipArchive::CM_DEFLATE); config()->set('backup.backup.destination.compression_level', 2); diff --git a/tests/Commands/ListCommandTest.php b/tests/Commands/ListCommandTest.php index 35657b57..e3c12903 100644 --- a/tests/Commands/ListCommandTest.php +++ b/tests/Commands/ListCommandTest.php @@ -15,5 +15,5 @@ config(['backup.monitorBackups' => config('backup.monitor_backups')]); $this->artisan('backup:list') - ->expectsOutput("Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups."); + ->expectsOutput('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); }); diff --git a/tests/Commands/MonitorCommandTest.php b/tests/Commands/MonitorCommandTest.php index ccc28270..79277a05 100644 --- a/tests/Commands/MonitorCommandTest.php +++ b/tests/Commands/MonitorCommandTest.php @@ -15,6 +15,6 @@ public function it_warns_the_user_about_the_old_style_config_keys(): void config(['backup.monitorBackups' => config('backup.monitor_backups')]); $this->artisan('backup:monitor') - ->expectsOutput("Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups."); + ->expectsOutput('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); } } diff --git a/tests/DbDumperFactoryTest.php b/tests/DbDumperFactoryTest.php index d93c82ee..d45c4158 100644 --- a/tests/DbDumperFactoryTest.php +++ b/tests/DbDumperFactoryTest.php @@ -174,7 +174,6 @@ expect(DbDumperFactory::createFromConnection('mysql'))->toBeInstanceOf(MongoDb::class); }); - function getDumpCommand(): string { $dumpFile = ''; diff --git a/tests/FileSelectionTest.php b/tests/FileSelectionTest.php index 4c5b9eeb..db75ff40 100644 --- a/tests/FileSelectionTest.php +++ b/tests/FileSelectionTest.php @@ -37,7 +37,7 @@ it('can exclude files from a given subdirectory', function () { $fileSelection = (new FileSelection($this->sourceDirectory)) - ->excludeFilesFrom("{$this->sourceDirectory}/directory1"); + ->excludeFilesFrom("{$this->sourceDirectory}/directory1"); $testFiles = getTestFiles([ '.dot', @@ -62,8 +62,8 @@ it('can exclude files with wildcards from a given subdirectory', function () { $fileSelection = (new FileSelection($this->sourceDirectory)) ->excludeFilesFrom(getTestFiles([ - "*/file1.txt", - "*/directory1", + '*/file1.txt', + '*/directory1', ])); $testFiles = getTestFiles([ @@ -160,7 +160,6 @@ expect($fileSelection)->toBeInstanceOf(FileSelection::class); }); - function assertSameArrayContent($expected, $actual, $message = '') { test()->assertCount(count($expected), array_intersect($expected, $actual), $message); diff --git a/tests/FormatTest.php b/tests/FormatTest.php index a61d0eea..0f61ed97 100644 --- a/tests/FormatTest.php +++ b/tests/FormatTest.php @@ -1,7 +1,6 @@ set('backup.backup.encryption', $algorithm); diff --git a/tests/ManifestTest.php b/tests/ManifestTest.php index 52f372b7..85ab2f86 100644 --- a/tests/ManifestTest.php +++ b/tests/ManifestTest.php @@ -67,7 +67,6 @@ } }); - function getManifestTestFiles(): array { return collect(range(1, 3)) diff --git a/tests/Pest.php b/tests/Pest.php index 0819fb64..43d20332 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,9 +1,9 @@ in(__DIR__); expect()->extend('hasItemContaining', function (string $searchString) { diff --git a/tests/TestCase.php b/tests/TestCase.php index 67ba0c7f..dca6ea6b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -19,9 +19,7 @@ abstract class TestCase extends Orchestra { /** - * @param \Illuminate\Foundation\Application $app - * - * @return array + * @param \Illuminate\Foundation\Application $app */ protected function getPackageProviders($app): array { @@ -31,7 +29,7 @@ protected function getPackageProviders($app): array } /** - * @param \Illuminate\Foundation\Application $app + * @param \Illuminate\Foundation\Application $app */ protected function getEnvironmentSetUp($app) { @@ -236,7 +234,7 @@ public function fakeBackup(): self return $this; } - public function makeHealthCheckFail(Exception $customException = null): self + public function makeHealthCheckFail(?Exception $customException = null): self { FakeFailingHealthCheck::$reason = $customException; From 0c66d929fc9cda8c5edbce9367a17fd33e92d863 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:13:18 +0200 Subject: [PATCH 04/33] add code styling config --- rector.php | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/rector.php b/rector.php index 378933ec..eff24e15 100644 --- a/rector.php +++ b/rector.php @@ -3,24 +3,32 @@ declare(strict_types=1); use Rector\CodeQuality\Rector\ClassMethod\OptionalParametersAfterRequiredRector; +use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector; +use Rector\CodeQuality\Rector\If_\ExplicitBoolCompareRector; +use Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector; +use Rector\CodingStyle\Rector\Closure\StaticClosureRector; +use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector; +use Rector\CodingStyle\Rector\If_\NullableCompareToNullRector; +use Rector\CodingStyle\Rector\Plus\UseIncrementAssignRector; +use Rector\CodingStyle\Rector\PostInc\PostIncDecToPreIncDecRector; use Rector\Config\RectorConfig; use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; -use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; return RectorConfig::configure() - ->withPaths([ - __DIR__.'/config', - __DIR__.'/resources', - __DIR__.'/src', - __DIR__.'/tests', - ]) + ->withPaths(['config', 'resources', 'src', 'tests']) ->withPhpSets(php81: true) - ->withRules([ - AddVoidReturnTypeWhereNoReturnRector::class, - ]) + ->withPreparedSets(deadCode: true,codingStyle: true) ->withSkip([ ReturnNeverTypeRector::class, OptionalParametersAfterRequiredRector::class, ClosureToArrowFunctionRector::class, + FlipTypeControlToUseExclusiveTypeRector::class, + ExplicitBoolCompareRector::class, + EncapsedStringsToSprintfRector::class, + StaticClosureRector::class, + StaticArrowFunctionRector::class, + UseIncrementAssignRector::class, + PostIncDecToPreIncDecRector::class, + NullableCompareToNullRector::class, ]); From 225f4dff81e4faecbf6ce96a92d6615d3d99292c Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:13:41 +0200 Subject: [PATCH 05/33] apply code styling from rector --- phpstan-baseline.neon | 11 ----------- rector.php | 4 ++-- resources/lang/fr/notifications.php | 14 +++++++------- resources/lang/it/notifications.php | 10 +++++----- src/Commands/BackupCommand.php | 1 + src/Commands/BaseCommand.php | 2 +- src/Exceptions/CannotCreateDbDumper.php | 2 +- src/Helpers/Format.php | 1 + src/Listeners/EncryptBackupArchive.php | 2 +- .../Notifications/BackupHasFailedNotification.php | 2 +- .../BackupWasSuccessfulNotification.php | 2 +- .../Notifications/CleanupHasFailedNotification.php | 2 +- .../CleanupWasSuccessfulNotification.php | 2 +- .../HealthyBackupWasFoundNotification.php | 2 +- .../UnhealthyBackupWasFoundNotification.php | 2 +- src/Tasks/Backup/FileSelection.php | 3 ++- src/Tasks/Backup/Zip.php | 1 + tests/Commands/BackupCommandTest.php | 11 +++++++++++ tests/Notifications/EventHandlerTest.php | 2 +- tests/TestCase.php | 4 ++-- 20 files changed, 42 insertions(+), 38 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 41478adf..e69de29b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Deprecated in PHP 8\\.0\\: Required parameter \\$diskName follows optional parameter \\$disk\\.$#" - count: 1 - path: src/BackupDestination/BackupDestination.php - - - - message: "#^Deprecated in PHP 8\\.1\\: Required parameter \\$backupName follows optional parameter \\$disk\\.$#" - count: 1 - path: src/BackupDestination/BackupDestination.php diff --git a/rector.php b/rector.php index eff24e15..0e029b14 100644 --- a/rector.php +++ b/rector.php @@ -16,9 +16,9 @@ use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; return RectorConfig::configure() - ->withPaths(['config', 'resources', 'src', 'tests']) + ->withPaths(['config', 'resources', 'src']) ->withPhpSets(php81: true) - ->withPreparedSets(deadCode: true,codingStyle: true) + ->withPreparedSets(deadCode: true, codingStyle: true, typeDeclarations: true) ->withSkip([ ReturnNeverTypeRector::class, OptionalParametersAfterRequiredRector::class, diff --git a/resources/lang/fr/notifications.php b/resources/lang/fr/notifications.php index 2ae49765..ad60a5c9 100644 --- a/resources/lang/fr/notifications.php +++ b/resources/lang/fr/notifications.php @@ -1,10 +1,10 @@ 'Message de l\'exception : :message', - 'exception_trace' => 'Trace de l\'exception : :trace', - 'exception_message_title' => 'Message de l\'exception', - 'exception_trace_title' => 'Trace de l\'exception', + 'exception_message' => "Message de l'exception : :message", + 'exception_trace' => "Trace de l'exception : :trace", + 'exception_message_title' => "Message de l'exception", + 'exception_trace_title' => "Trace de l'exception", 'backup_failed_subject' => 'Échec de la sauvegarde de :application_name', 'backup_failed_body' => 'Important : Une erreur est survenue lors de la sauvegarde de :application_name', @@ -27,14 +27,14 @@ 'unhealthy_backup_found_subject' => 'Important : Les sauvegardes pour :application_name sont corrompues', 'unhealthy_backup_found_subject_title' => 'Important : Les sauvegardes pour :application_name sont corrompues. :problem', 'unhealthy_backup_found_body' => 'Les sauvegardes pour :application_name sur le disque :disk_name sont corrompues.', - 'unhealthy_backup_found_not_reachable' => 'La destination de la sauvegarde n\'est pas accessible. :error', - 'unhealthy_backup_found_empty' => 'Il n\'y a aucune sauvegarde pour cette application.', + 'unhealthy_backup_found_not_reachable' => "La destination de la sauvegarde n'est pas accessible. :error", + 'unhealthy_backup_found_empty' => "Il n'y a aucune sauvegarde pour cette application.", 'unhealthy_backup_found_old' => 'La dernière sauvegarde du :date est considérée trop vieille.', 'unhealthy_backup_found_unknown' => 'Désolé, une raison exacte ne peut être déterminée.', 'unhealthy_backup_found_full' => 'Les sauvegardes utilisent trop d\'espace disque. L\'utilisation actuelle est de :disk_usage alors que la limite autorisée est de :disk_limit.', 'no_backups_info' => 'Aucune sauvegarde n\'a encore été effectuée', - 'application_name' => 'Nom de l\'application', + 'application_name' => "Nom de l'application", 'backup_name' => 'Nom de la sauvegarde', 'disk' => 'Disque', 'newest_backup_size' => 'Taille de la sauvegarde la plus récente', diff --git a/resources/lang/it/notifications.php b/resources/lang/it/notifications.php index 94fe1415..e96618d0 100644 --- a/resources/lang/it/notifications.php +++ b/resources/lang/it/notifications.php @@ -1,10 +1,10 @@ 'Messaggio dell\'eccezione: :message', - 'exception_trace' => 'Traccia dell\'eccezione: :trace', - 'exception_message_title' => 'Messaggio dell\'eccezione', - 'exception_trace_title' => 'Traccia dell\'eccezione', + 'exception_message' => "Messaggio dell'eccezione: :message", + 'exception_trace' => "Traccia dell'eccezione: :trace", + 'exception_message_title' => "Messaggio dell'eccezione", + 'exception_trace_title' => "Traccia dell'eccezione", 'backup_failed_subject' => 'Fallito il backup di :application_name', 'backup_failed_body' => 'Importante: Si è verificato un errore durante il backup di :application_name', @@ -34,7 +34,7 @@ 'unhealthy_backup_found_full' => 'I backup utilizzano troppa memoria. L\'utilizzo corrente è :disk_usage che è superiore al limite consentito di :disk_limit.', 'no_backups_info' => 'Non sono stati ancora effettuati backup', - 'application_name' => 'Nome dell\'applicazione', + 'application_name' => "Nome dell'applicazione", 'backup_name' => 'Nome di backup', 'disk' => 'Disco', 'newest_backup_size' => 'Dimensione backup più recente', diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index 6dba3b7c..b69d5cfd 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -36,6 +36,7 @@ public function handle(): int if ($this->option('only-db')) { $backupJob->dontBackupFilesystem(); } + if ($this->option('db-name')) { $backupJob->onlyDbName($this->option('db-name')); } diff --git a/src/Commands/BaseCommand.php b/src/Commands/BaseCommand.php index c12ad4f5..0762f723 100644 --- a/src/Commands/BaseCommand.php +++ b/src/Commands/BaseCommand.php @@ -30,7 +30,7 @@ public function run(InputInterface $input, OutputInterface $output): int protected function runningInConsole(): bool { - return in_array(php_sapi_name(), ['cli', 'phpdbg']); + return in_array(PHP_SAPI, ['cli', 'phpdbg']); } public function getSubscribedSignals(): array diff --git a/src/Exceptions/CannotCreateDbDumper.php b/src/Exceptions/CannotCreateDbDumper.php index 9680b20b..3c756a23 100644 --- a/src/Exceptions/CannotCreateDbDumper.php +++ b/src/Exceptions/CannotCreateDbDumper.php @@ -11,7 +11,7 @@ public static function unsupportedDriver(string $driver): self $supportedDrivers = collect(config('database.connections'))->keys(); $formattedSupportedDrivers = $supportedDrivers - ->map(fn (string $supportedDriver) => "`$supportedDriver`") + ->map(fn (string $supportedDriver) => "`{$supportedDriver}`") ->join(glue: ', ', finalGlue: ' or '); return new static("Cannot create a dumper for db driver `{$driver}`. Use {$formattedSupportedDrivers}."); diff --git a/src/Helpers/Format.php b/src/Helpers/Format.php index 07903a95..49a6ed19 100644 --- a/src/Helpers/Format.php +++ b/src/Helpers/Format.php @@ -13,6 +13,7 @@ public static function humanReadableSize(float $sizeInBytes): string if ($sizeInBytes === 0.0) { return '0 '.$units[1]; } + for ($i = 0; $sizeInBytes > 1024; $i++) { $sizeInBytes /= 1024; } diff --git a/src/Listeners/EncryptBackupArchive.php b/src/Listeners/EncryptBackupArchive.php index 35d62b1d..ceca313b 100644 --- a/src/Listeners/EncryptBackupArchive.php +++ b/src/Listeners/EncryptBackupArchive.php @@ -57,7 +57,7 @@ protected static function getAlgorithm(): ?int $encryption = config('backup.backup.encryption'); if ($encryption === 'default') { - $encryption = defined("\ZipArchive::EM_AES_256") + $encryption = defined(\ZipArchive::class . '::EM_AES_256') ? ZipArchive::EM_AES_256 : null; } diff --git a/src/Notifications/Notifications/BackupHasFailedNotification.php b/src/Notifications/Notifications/BackupHasFailedNotification.php index 64d99bd8..bf4cea52 100644 --- a/src/Notifications/Notifications/BackupHasFailedNotification.php +++ b/src/Notifications/Notifications/BackupHasFailedNotification.php @@ -26,7 +26,7 @@ public function toMail(): MailMessage ->line(trans('backup::notifications.exception_message', ['message' => $this->event->exception->getMessage()])) ->line(trans('backup::notifications.exception_trace', ['trace' => $this->event->exception->getTraceAsString()])); - $this->backupDestinationProperties()->each(fn ($value, $name) => $mailMessage->line("{$name}: $value")); + $this->backupDestinationProperties()->each(fn ($value, $name) => $mailMessage->line("{$name}: {$value}")); return $mailMessage; } diff --git a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php index 013bafc9..2b21b335 100644 --- a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php @@ -24,7 +24,7 @@ public function toMail(): MailMessage ->line(trans('backup::notifications.backup_successful_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])); $this->backupDestinationProperties()->each(function ($value, $name) use ($mailMessage) { - $mailMessage->line("{$name}: $value"); + $mailMessage->line("{$name}: {$value}"); }); return $mailMessage; diff --git a/src/Notifications/Notifications/CleanupHasFailedNotification.php b/src/Notifications/Notifications/CleanupHasFailedNotification.php index 42cf2383..0a76876b 100644 --- a/src/Notifications/Notifications/CleanupHasFailedNotification.php +++ b/src/Notifications/Notifications/CleanupHasFailedNotification.php @@ -27,7 +27,7 @@ public function toMail(): MailMessage ->line(trans('backup::notifications.exception_trace', ['trace' => $this->event->exception->getTraceAsString()])); $this->backupDestinationProperties()->each(function ($value, $name) use ($mailMessage) { - $mailMessage->line("{$name}: $value"); + $mailMessage->line("{$name}: {$value}"); }); return $mailMessage; diff --git a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php index b554be0d..8ab7da53 100644 --- a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php @@ -24,7 +24,7 @@ public function toMail(): MailMessage ->line(trans('backup::notifications.cleanup_successful_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])); $this->backupDestinationProperties()->each(function ($value, $name) use ($mailMessage) { - $mailMessage->line("{$name}: $value"); + $mailMessage->line("{$name}: {$value}"); }); return $mailMessage; diff --git a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php index eb10b85f..44ed0d1b 100644 --- a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php @@ -24,7 +24,7 @@ public function toMail(): MailMessage ->line(trans('backup::notifications.healthy_backup_found_body', ['application_name' => $this->applicationName()])); $this->backupDestinationProperties()->each(function ($value, $name) use ($mailMessage) { - $mailMessage->line("{$name}: $value"); + $mailMessage->line("{$name}: {$value}"); }); return $mailMessage; diff --git a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php index 4e7570f8..8c7fab75 100644 --- a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php @@ -27,7 +27,7 @@ public function toMail(): MailMessage ->line($this->problemDescription()); $this->backupDestinationProperties()->each(function ($value, $name) use ($mailMessage) { - $mailMessage->line("{$name}: $value"); + $mailMessage->line("{$name}: {$value}"); }); if ($this->failure()->wasUnexpected()) { diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index ff51274e..a11f6b08 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -72,7 +72,7 @@ public function selectedFiles(): Generator|array yield $includedFile; } - if (! count($this->includedDirectories())) { + if ($this->includedDirectories() === []) { return []; } @@ -107,6 +107,7 @@ protected function shouldExclude(string $path): bool if (is_dir($path)) { $path .= DIRECTORY_SEPARATOR; } + foreach ($this->excludeFilesAndDirectories as $excludedPath) { if (Str::startsWith($path, $excludedPath.(is_dir($excludedPath) ? DIRECTORY_SEPARATOR : ''))) { if ($path != $excludedPath && is_file($excludedPath)) { diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index d6d664a0..1234649a 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -112,6 +112,7 @@ public function add(string|iterable $files, ?string $nameInZip = null): self ); } } + $this->fileCount++; } diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php index c35e1498..3b883325 100644 --- a/tests/Commands/BackupCommandTest.php +++ b/tests/Commands/BackupCommandTest.php @@ -102,6 +102,7 @@ foreach (range(0, $zip->numFiles - 1) as $i) { $zipFiles[] = $zip->statIndex($i)['name']; } + $zip->close(); sort($testFiles); sort($zipFiles); @@ -121,6 +122,7 @@ if ($zip->numFiles) { $zipFile = $zip->statIndex(0)['name']; } + $zip->close(); expect($zipFile)->toStartWith(ltrim((string) $this->getStubDirectory(), DIRECTORY_SEPARATOR)); @@ -132,6 +134,7 @@ if (! file_exists($tempDirectoryPath)) { mkdir($tempDirectoryPath, 0777, true); } + touch($tempDirectoryPath.DIRECTORY_SEPARATOR.'testing-file-temp.txt'); $this->artisan('backup:run --only-files')->assertExitCode(0); @@ -367,8 +370,10 @@ $zip = new ZipArchive(); $zip->open(Storage::disk('local')->path($this->expectedZipPath)); + expect($zip->numFiles)->toBe(1); expect($zip->statIndex(0)['encryption_method'])->toBe(ZipArchive::EM_AES_256); + $zip->close(); Event::assertNotDispatched(BackupZipWasCreated::class); @@ -382,8 +387,10 @@ $zip = new ZipArchive(); $zip->open(Storage::disk('local')->path($this->expectedZipPath)); + expect($zip->numFiles)->toBe(1); expect($zip->statIndex(0)['comp_method'])->toBe(ZipArchive::CM_DEFLATE); + $zip->close(); // check no compression with ZipArchive::CM_STORE method @@ -394,8 +401,10 @@ $zip = new ZipArchive(); $zip->open(Storage::disk('local')->path($this->expectedZipPath)); + expect($zip->numFiles)->toBe(1); expect($zip->statIndex(0)['comp_method'])->toBe(ZipArchive::CM_STORE); + $zip->close(); // check ZipArchive::CM_DEFLATE method with custom compression level @@ -406,8 +415,10 @@ $zip = new ZipArchive(); $zip->open(Storage::disk('local')->path($this->expectedZipPath)); + expect($zip->numFiles)->toBe(1); expect($zip->statIndex(0)['comp_method'])->toBe(ZipArchive::CM_DEFLATE); + $zip->close(); }); diff --git a/tests/Notifications/EventHandlerTest.php b/tests/Notifications/EventHandlerTest.php index b001bc39..5da94435 100644 --- a/tests/Notifications/EventHandlerTest.php +++ b/tests/Notifications/EventHandlerTest.php @@ -4,7 +4,7 @@ use Spatie\Backup\BackupDestination\BackupDestinationFactory; use Spatie\Backup\Events\BackupHasFailed; use Spatie\Backup\Notifications\Notifiable; -use Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification as BackupHasFailedNotification; +use Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification; beforeEach(function () { Notification::fake(); diff --git a/tests/TestCase.php b/tests/TestCase.php index dca6ea6b..28b699ef 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -72,7 +72,7 @@ protected function seeInConsoleOutput(string $expectedText): void $this->assertStringContainsString( $expectedText, $consoleOutput, - "Did not see `{$expectedText}` in console output: `$consoleOutput`" + "Did not see `{$expectedText}` in console output: `{$consoleOutput}`" ); } @@ -83,7 +83,7 @@ protected function doNotSeeInConsoleOutput(string $unexpectedText): void $this->assertNotContains( $unexpectedText, $consoleOutput, - "Did not expect to see `{$unexpectedText}` in console output: `$consoleOutput`" + "Did not expect to see `{$unexpectedText}` in console output: `{$consoleOutput}`" ); } From e835ce842a7a8003296af9f14d7191cd7396ce1a Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 7 Jun 2024 08:17:10 +0000 Subject: [PATCH 06/33] Fix styling --- src/Listeners/EncryptBackupArchive.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Listeners/EncryptBackupArchive.php b/src/Listeners/EncryptBackupArchive.php index ceca313b..230aa700 100644 --- a/src/Listeners/EncryptBackupArchive.php +++ b/src/Listeners/EncryptBackupArchive.php @@ -57,7 +57,7 @@ protected static function getAlgorithm(): ?int $encryption = config('backup.backup.encryption'); if ($encryption === 'default') { - $encryption = defined(\ZipArchive::class . '::EM_AES_256') + $encryption = defined(\ZipArchive::class.'::EM_AES_256') ? ZipArchive::EM_AES_256 : null; } From 1b1fa88c43f539344afbf938e4938027a9918679 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:20:55 +0200 Subject: [PATCH 07/33] add return types --- rector.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rector.php b/rector.php index 0e029b14..a81f8384 100644 --- a/rector.php +++ b/rector.php @@ -13,6 +13,7 @@ use Rector\CodingStyle\Rector\PostInc\PostIncDecToPreIncDecRector; use Rector\Config\RectorConfig; use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; +use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; return RectorConfig::configure() @@ -31,4 +32,5 @@ UseIncrementAssignRector::class, PostIncDecToPreIncDecRector::class, NullableCompareToNullRector::class, + AddArrowFunctionReturnTypeRector::class, ]); From a93a5b8d4fcfd65d961600faf3e67dca93851f5b Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:59:48 +0200 Subject: [PATCH 08/33] add more types --- composer.json | 4 +- phpstan-baseline.neon | 56 +++++++++++++++++++ phpstan.neon.dist | 2 +- src/BackupDestination/Backup.php | 1 + src/BackupDestination/BackupCollection.php | 2 + src/BackupDestination/BackupDestination.php | 1 + .../BackupDestinationFactory.php | 4 ++ src/BackupServiceProvider.php | 2 +- src/Commands/BackupCommand.php | 2 +- src/Commands/BaseCommand.php | 2 + src/Commands/ListCommand.php | 11 +++- src/Exceptions/CannotCreateDbDumper.php | 8 ++- src/Exceptions/NotificationCouldNotBeSent.php | 2 +- src/Helpers/ConsoleOutput.php | 3 +- src/Helpers/File.php | 1 + src/Notifications/BaseNotification.php | 2 + .../Channels/Discord/DiscordChannel.php | 3 +- .../Channels/Discord/DiscordMessage.php | 4 +- src/Notifications/EventHandler.php | 10 +++- src/Notifications/Notifiable.php | 1 + src/Tasks/Backup/BackupJob.php | 17 ++++-- src/Tasks/Backup/BackupJobFactory.php | 7 +++ src/Tasks/Backup/DbDumperFactory.php | 8 ++- src/Tasks/Backup/FileSelection.php | 24 ++++++-- src/Tasks/Backup/Manifest.php | 3 + src/Tasks/Backup/Zip.php | 2 +- src/Tasks/Cleanup/CleanupJob.php | 3 +- src/Tasks/Cleanup/CleanupStrategy.php | 2 +- .../Cleanup/Strategies/DefaultStrategy.php | 14 +++-- src/Tasks/Monitor/BackupDestinationStatus.php | 2 + .../BackupDestinationStatusFactory.php | 27 ++++++++- src/Tasks/Monitor/HealthCheck.php | 2 +- src/Traits/Retryable.php | 10 ++-- tests/TestSupport/FakeFailingHealthCheck.php | 2 +- 34 files changed, 195 insertions(+), 49 deletions(-) diff --git a/composer.json b/composer.json index ffaea00b..d41ff2e0 100644 --- a/composer.json +++ b/composer.json @@ -32,10 +32,10 @@ "spatie/laravel-signal-aware-command": "^1.2|^2.0", "spatie/temporary-directory": "^2.0", "symfony/console": "^6.0|^7.0", - "symfony/finder": "^6.0|^7.0" + "symfony/finder": "^6.0|^7.0", + "ext-pcntl": "*" }, "require-dev": { - "ext-pcntl": "*", "composer-runtime-api": "^2.0", "larastan/larastan": "^2.7.0", "laravel/slack-notification-channel": "^2.5|^3.0", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e69de29b..c56c638a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -0,0 +1,56 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:filter\\(\\) expects \\(callable\\(Spatie\\\\Backup\\\\BackupDestination\\\\Backup, int\\)\\: bool\\)\\|null, Closure\\(string\\)\\: bool given\\.$#" + count: 1 + path: src/BackupDestination/BackupCollection.php + + - + message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:map\\(\\) expects callable\\(Spatie\\\\Backup\\\\BackupDestination\\\\Backup, int\\)\\: Spatie\\\\Backup\\\\BackupDestination\\\\Backup, Closure\\(string\\)\\: Spatie\\\\Backup\\\\BackupDestination\\\\Backup given\\.$#" + count: 1 + path: src/BackupDestination/BackupCollection.php + + - + message: "#^Unable to resolve the template type TKey in call to function collect$#" + count: 1 + path: src/BackupDestination/BackupDestinationFactory.php + + - + message: "#^Unable to resolve the template type TValue in call to function collect$#" + count: 1 + path: src/BackupDestination/BackupDestinationFactory.php + + - + message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:map\\(\\) expects callable\\(int, int\\)\\: string, Closure\\(string\\)\\: non\\-falsy\\-string given\\.$#" + count: 1 + path: src/Exceptions/CannotCreateDbDumper.php + + - + message: "#^Method Spatie\\\\Backup\\\\Notifications\\\\Channels\\\\Discord\\\\DiscordMessage\\:\\:toArray\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Notifications/Channels/Discord/DiscordMessage.php + + - + message: "#^Method Spatie\\\\Backup\\\\Tasks\\\\Backup\\\\FileSelection\\:\\:sanitize\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Tasks/Backup/FileSelection.php + + - + message: "#^Method Spatie\\\\Backup\\\\Tasks\\\\Backup\\\\Manifest\\:\\:files\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Tasks/Backup/Manifest.php + + - + message: "#^Method Spatie\\\\Backup\\\\Tasks\\\\Backup\\\\Manifest\\:\\:files\\(\\) return type has no value type specified in iterable type array\\|Generator\\.$#" + count: 1 + path: src/Tasks/Backup/Manifest.php + + - + message: "#^Method Spatie\\\\Backup\\\\Tasks\\\\Backup\\\\Zip\\:\\:add\\(\\) has parameter \\$files with no value type specified in iterable type iterable\\.$#" + count: 1 + path: src/Tasks/Backup/Zip.php + + - + message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:each\\(\\) expects callable\\(Spatie\\\\Backup\\\\BackupDestination\\\\Backup, int\\)\\: mixed, Closure\\(Spatie\\\\Backup\\\\BackupDestination\\\\BackupCollection\\)\\: void given\\.$#" + count: 1 + path: src/Tasks/Cleanup/Strategies/DefaultStrategy.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 81a4e5b0..685a823f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,7 +2,7 @@ includes: - phpstan-baseline.neon parameters: - level: 5 + level: 6 paths: - src - config diff --git a/src/BackupDestination/Backup.php b/src/BackupDestination/Backup.php index b4b4c0f7..6a0d6d31 100644 --- a/src/BackupDestination/Backup.php +++ b/src/BackupDestination/Backup.php @@ -66,6 +66,7 @@ public function sizeInBytes(): float return $this->size; } + /** @return resource */ public function stream() { return throw_unless( diff --git a/src/BackupDestination/BackupCollection.php b/src/BackupDestination/BackupCollection.php index 514c1bfa..dc998fdf 100644 --- a/src/BackupDestination/BackupCollection.php +++ b/src/BackupDestination/BackupCollection.php @@ -6,10 +6,12 @@ use Illuminate\Support\Collection; use Spatie\Backup\Helpers\File; +/** @extends Collection */ class BackupCollection extends Collection { protected ?float $sizeCache = null; + /** @param array $files */ public static function createFromFiles(?FileSystem $disk, array $files): self { return (new static($files)) diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index 73d6f684..3ef69882 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -114,6 +114,7 @@ public function connectionError(): Exception return $this->connectionError; } + /** @return array */ public function getDiskOptions(): array { return config("filesystems.disks.{$this->diskName()}.backup_options") ?? []; diff --git a/src/BackupDestination/BackupDestinationFactory.php b/src/BackupDestination/BackupDestinationFactory.php index 3212470a..99c085b4 100644 --- a/src/BackupDestination/BackupDestinationFactory.php +++ b/src/BackupDestination/BackupDestinationFactory.php @@ -6,6 +6,10 @@ class BackupDestinationFactory { + /** + * @param array $config + * @return Collection + */ public static function createFromArray(array $config): Collection { return collect($config['destination']['disks']) diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index 8e460d53..ecd087bb 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -52,7 +52,7 @@ public function packageRegistered(): void $this->registerDiscordChannel(); } - protected function registerDiscordChannel() + protected function registerDiscordChannel(): void { Notification::resolved(function (ChannelManager $service) { $service->extend('discord', function ($app) { diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index b69d5cfd..07dfdaa7 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -95,7 +95,7 @@ public function handle(): int } } - protected function guardAgainstInvalidOptions() + protected function guardAgainstInvalidOptions(): void { if (! $this->option('only-db')) { return; diff --git a/src/Commands/BaseCommand.php b/src/Commands/BaseCommand.php index 0762f723..b05aaf56 100644 --- a/src/Commands/BaseCommand.php +++ b/src/Commands/BaseCommand.php @@ -10,6 +10,7 @@ abstract class BaseCommand extends SignalAwareCommand { + /** @var array */ protected array $handlesSignals = []; public function __construct() @@ -33,6 +34,7 @@ protected function runningInConsole(): bool return in_array(PHP_SAPI, ['cli', 'phpdbg']); } + /** @return array */ public function getSubscribedSignals(): array { return $this->handlesSignals; diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index cf63ca23..94d961e3 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -30,7 +30,10 @@ public function handle(): int return static::SUCCESS; } - protected function displayOverview(Collection $backupDestinationStatuses) + /** + * @param Collection $backupDestinationStatuses + */ + protected function displayOverview(Collection $backupDestinationStatuses): static { $headers = ['Name', 'Disk', 'Reachable', 'Healthy', '# of backups', 'Newest backup', 'Used storage']; @@ -46,6 +49,7 @@ protected function displayOverview(Collection $backupDestinationStatuses) return $this; } + /** @return array{0: string, 1: string, 2: string, disk: string, amount: integer, newest: string, usedStorage: string} */ public function convertToRow(BackupDestinationStatus $backupDestinationStatus): array { $destination = $backupDestinationStatus->backupDestination(); @@ -73,7 +77,8 @@ public function convertToRow(BackupDestinationStatus $backupDestinationStatus): return $row; } - protected function displayFailures(Collection $backupDestinationStatuses) + /** @param Collection $backupDestinationStatuses */ + protected function displayFailures(Collection $backupDestinationStatuses): static { $failed = $backupDestinationStatuses ->filter(function (BackupDestinationStatus $backupDestinationStatus) { @@ -98,7 +103,7 @@ protected function displayFailures(Collection $backupDestinationStatuses) return $this; } - protected function getFormattedBackupDate(?Backup $backup = null) + protected function getFormattedBackupDate(?Backup $backup = null): string { return is_null($backup) ? 'No backups present' diff --git a/src/Exceptions/CannotCreateDbDumper.php b/src/Exceptions/CannotCreateDbDumper.php index 3c756a23..5fabe436 100644 --- a/src/Exceptions/CannotCreateDbDumper.php +++ b/src/Exceptions/CannotCreateDbDumper.php @@ -6,11 +6,13 @@ class CannotCreateDbDumper extends Exception { - public static function unsupportedDriver(string $driver): self + public static function unsupportedDriver(string $driver): static { - $supportedDrivers = collect(config('database.connections'))->keys(); + /** @var array $supportedDrivers */ + $supportedDrivers = config('database.connections'); - $formattedSupportedDrivers = $supportedDrivers + $formattedSupportedDrivers = collect($supportedDrivers) + ->keys() ->map(fn (string $supportedDriver) => "`{$supportedDriver}`") ->join(glue: ', ', finalGlue: ' or '); diff --git a/src/Exceptions/NotificationCouldNotBeSent.php b/src/Exceptions/NotificationCouldNotBeSent.php index b01d0c17..c09dfad1 100644 --- a/src/Exceptions/NotificationCouldNotBeSent.php +++ b/src/Exceptions/NotificationCouldNotBeSent.php @@ -6,7 +6,7 @@ class NotificationCouldNotBeSent extends Exception { - public static function noNotificationClassForEvent($event): self + public static function noNotificationClassForEvent(object $event): static { $eventClass = $event::class; diff --git a/src/Helpers/ConsoleOutput.php b/src/Helpers/ConsoleOutput.php index 72107288..8294d3ab 100644 --- a/src/Helpers/ConsoleOutput.php +++ b/src/Helpers/ConsoleOutput.php @@ -18,7 +18,8 @@ public function setCommand(Command $command): void $this->command = $command; } - public function __call(string $method, array $arguments) + /** @param array $arguments */ + public function __call(string $method, array $arguments): void { $consoleOutput = app(static::class); diff --git a/src/Helpers/File.php b/src/Helpers/File.php index bcf7a2fe..0c33b3d1 100644 --- a/src/Helpers/File.php +++ b/src/Helpers/File.php @@ -7,6 +7,7 @@ class File { + /** @var array */ protected static array $allowedMimeTypes = [ 'application/zip', 'application/x-zip', diff --git a/src/Notifications/BaseNotification.php b/src/Notifications/BaseNotification.php index 9a509e9f..d91d75e4 100644 --- a/src/Notifications/BaseNotification.php +++ b/src/Notifications/BaseNotification.php @@ -9,6 +9,7 @@ abstract class BaseNotification extends Notification { + /** @return array */ public function via(): array { $notificationChannels = config('backup.notifications.notifications.'.static::class); @@ -34,6 +35,7 @@ public function diskName(): string return $this->backupDestination()->diskName(); } + /** @return Collection */ protected function backupDestinationProperties(): Collection { $backupDestination = $this->backupDestination(); diff --git a/src/Notifications/Channels/Discord/DiscordChannel.php b/src/Notifications/Channels/Discord/DiscordChannel.php index 6571e12d..93c32230 100644 --- a/src/Notifications/Channels/Discord/DiscordChannel.php +++ b/src/Notifications/Channels/Discord/DiscordChannel.php @@ -4,10 +4,11 @@ use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Http; +use Spatie\Backup\Notifications\Notifiable; class DiscordChannel { - public function send($notifiable, Notification $notification): void + public function send(Notifiable $notifiable, Notification $notification): void { $discordMessage = $notification->toDiscord(); // @phpstan-ignore-line diff --git a/src/Notifications/Channels/Discord/DiscordMessage.php b/src/Notifications/Channels/Discord/DiscordMessage.php index b7bf6555..1d865eeb 100644 --- a/src/Notifications/Channels/Discord/DiscordMessage.php +++ b/src/Notifications/Channels/Discord/DiscordMessage.php @@ -20,6 +20,7 @@ class DiscordMessage protected string $description = ''; + /** @var array */ protected array $fields = []; protected ?string $timestamp = null; @@ -48,7 +49,7 @@ public function url(string $url): self return $this; } - public function title($title): self + public function title(string $title): self { $this->title = $title; @@ -97,6 +98,7 @@ public function error(): self return $this; } + /** @param array $fields */ public function fields(array $fields, bool $inline = true): self { foreach ($fields as $label => $value) { diff --git a/src/Notifications/EventHandler.php b/src/Notifications/EventHandler.php index 25c20f3a..6f1fdeec 100644 --- a/src/Notifications/EventHandler.php +++ b/src/Notifications/EventHandler.php @@ -31,18 +31,21 @@ public function subscribe(Dispatcher $events): void }); } - protected function determineNotifiable() + protected function determineNotifiable(): Notifiable { $notifiableClass = $this->config->get('backup.notifications.notifiable'); return app($notifiableClass); } - protected function determineNotification($event): Notification + protected function determineNotification(object $event): Notification { $lookingForNotificationClass = class_basename($event).'Notification'; - $notificationClass = collect($this->config->get('backup.notifications.notifications')) + /** @var array> $notificationClasses */ + $notificationClasses = $this->config->get('backup.notifications.notifications'); + + $notificationClass = collect($notificationClasses) ->keys() ->first(fn (string $notificationClass) => class_basename($notificationClass) === $lookingForNotificationClass); @@ -53,6 +56,7 @@ protected function determineNotification($event): Notification return new $notificationClass($event); } + /** @return array */ protected function allBackupEventClasses(): array { return [ diff --git a/src/Notifications/Notifiable.php b/src/Notifications/Notifiable.php index 13e30475..419ce283 100644 --- a/src/Notifications/Notifiable.php +++ b/src/Notifications/Notifiable.php @@ -8,6 +8,7 @@ class Notifiable { use NotifiableTrait; + /** @return string|array{int, string} */ public function routeNotificationForMail(): string|array { return config('backup.notifications.mail.to'); diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index 662acfda..16bf96d2 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -27,8 +27,10 @@ class BackupJob protected FileSelection $fileSelection; + /** @var Collection */ protected Collection $dbDumpers; + /** @var Collection */ protected Collection $backupDestinations; protected string $filename; @@ -56,6 +58,7 @@ public function dontBackupFilesystem(): self return $this; } + /** @param array $allowedDbNames */ public function onlyDbName(array $allowedDbNames): self { $this->dbDumpers = $this->dbDumpers->filter( @@ -100,6 +103,10 @@ public function setFileSelection(FileSelection $fileSelection): self return $this; } + /** + * @param Collection $dbDumpers + * @return $this + */ public function setDbDumpers(Collection $dbDumpers): self { $this->dbDumpers = $dbDumpers; @@ -127,6 +134,7 @@ public function onlyBackupTo(string $diskName): self return $this; } + /** @param Collection $backupDestinations */ public function setBackupDestinations(Collection $backupDestinations): self { $this->backupDestinations = $backupDestinations; @@ -134,9 +142,7 @@ public function setBackupDestinations(Collection $backupDestinations): self return $this; } - /** - * @throws Exception - */ + /** @throws Exception */ public function run(): void { $temporaryDirectoryPath = config('backup.backup.temporary_directory') ?? storage_path('app/backup-temp'); @@ -206,6 +212,7 @@ public function filesToBeBackedUp(): Generator return $this->fileSelection->selectedFiles(); } + /** @return array */ protected function directoriesUsedByBackupJob(): array { return $this->backupDestinations @@ -240,6 +247,8 @@ protected function createZipContainingEveryFileInManifest(Manifest $manifest): s /** * Dumps the databases to the given directory. * Returns an array with paths to the dump files. + * + * @return array */ protected function dumpDatabases(): array { @@ -312,7 +321,7 @@ protected function copyToBackupDestinations(string $path): void }); } - protected function sendNotification($notification): void + protected function sendNotification(object|string $notification): void { if ($this->sendNotifications) { rescue( diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index f9cfddfe..3ce874a8 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -5,9 +5,11 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestinationFactory; +use Spatie\DbDumper\DbDumper; class BackupJobFactory { + /** @param array> $config */ public static function createFromArray(array $config): BackupJob { return (new BackupJob()) @@ -16,6 +18,7 @@ public static function createFromArray(array $config): BackupJob ->setBackupDestinations(BackupDestinationFactory::createFromArray($config['backup'])); } + /** @param array $sourceFiles */ protected static function createFileSelection(array $sourceFiles): FileSelection { return FileSelection::create($sourceFiles['include']) @@ -24,6 +27,10 @@ protected static function createFileSelection(array $sourceFiles): FileSelection ->shouldIgnoreUnreadableDirs(Arr::get($sourceFiles, 'ignore_unreadable_directories', false)); } + /** + * @param array $dbConnectionNames + * @return Collection + */ protected static function createDbDumpers(array $dbConnectionNames): Collection { return collect($dbConnectionNames)->mapWithKeys( diff --git a/src/Tasks/Backup/DbDumperFactory.php b/src/Tasks/Backup/DbDumperFactory.php index c416abd1..f879a790 100644 --- a/src/Tasks/Backup/DbDumperFactory.php +++ b/src/Tasks/Backup/DbDumperFactory.php @@ -15,6 +15,7 @@ class DbDumperFactory { + /** @var array */ protected static array $custom = []; public static function createFromConnection(string $dbConnectionName): DbDumper @@ -74,9 +75,9 @@ public static function extend(string $driver, callable $callback): void static::$custom[$driver] = $callback; } - protected static function forDriver($dbDriver): DbDumper + protected static function forDriver(string $dbDriver): DbDumper { - $driver = strtolower((string) $dbDriver); + $driver = strtolower($dbDriver); if (isset(static::$custom[$driver])) { return (static::$custom[$driver])(); @@ -91,6 +92,7 @@ protected static function forDriver($dbDriver): DbDumper }; } + /** @param array> $dumpConfiguration */ protected static function processExtraDumpParameters(array $dumpConfiguration, DbDumper $dbDumper): DbDumper { collect($dumpConfiguration)->each(function ($configValue, $configName) use ($dbDumper) { @@ -107,7 +109,7 @@ protected static function processExtraDumpParameters(array $dumpConfiguration, D return $dbDumper; } - protected static function callMethodOnDumper(DbDumper $dbDumper, string $methodName, $methodValue): DbDumper + protected static function callMethodOnDumper(DbDumper $dbDumper, string $methodName, mixed $methodValue): DbDumper { if (! $methodValue) { $dbDumper->$methodName(); diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index a11f6b08..45364662 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -9,19 +9,23 @@ class FileSelection { + /** @var Collection */ protected Collection $includeFilesAndDirectories; + /** @var Collection */ protected Collection $excludeFilesAndDirectories; protected bool $shouldFollowLinks = false; protected bool $shouldIgnoreUnreadableDirs = false; - public static function create(array|string $includeFilesAndDirectories = []): self + /** @param array|string $includeFilesAndDirectories */ + public static function create(array|string $includeFilesAndDirectories = []): static { return new static($includeFilesAndDirectories); } + /** @param array|string $includeFilesAndDirectories */ public function __construct(array|string $includeFilesAndDirectories = []) { $this->includeFilesAndDirectories = collect($includeFilesAndDirectories); @@ -29,6 +33,7 @@ public function __construct(array|string $includeFilesAndDirectories = []) $this->excludeFilesAndDirectories = collect(); } + /** @param array|string $excludeFilesAndDirectories */ public function excludeFilesFrom(array|string $excludeFilesAndDirectories): self { $this->excludeFilesAndDirectories = $this->excludeFilesAndDirectories->merge($this->sanitize($excludeFilesAndDirectories)); @@ -50,6 +55,7 @@ public function shouldIgnoreUnreadableDirs(bool $ignoreUnreadableDirs): self return $this; } + /** @return Generator|array */ public function selectedFiles(): Generator|array { if ($this->includeFilesAndDirectories->isEmpty()) { @@ -87,18 +93,20 @@ public function selectedFiles(): Generator|array } } + /** @return array */ protected function includedFiles(): array { return $this ->includeFilesAndDirectories - ->filter(fn ($path) => is_file($path))->toArray(); + ->filter(fn (string $path) => is_file($path))->toArray(); } + /** @return array */ protected function includedDirectories(): array { return $this ->includeFilesAndDirectories - ->reject(fn ($path) => is_file($path))->toArray(); + ->reject(fn (string $path) => is_file($path))->toArray(); } protected function shouldExclude(string $path): bool @@ -121,15 +129,19 @@ protected function shouldExclude(string $path): bool return false; } + /** + * @param string|array $paths + */ protected function sanitize(string|array $paths): Collection { return collect($paths) - ->reject(fn ($path) => $path === '') - ->flatMap(fn ($path) => $this->getMatchingPaths($path)) - ->map(fn ($path) => realpath($path)) + ->reject(fn (string $path) => $path === '') + ->flatMap(fn (string $path) => $this->getMatchingPaths($path)) + ->map(fn (string $path) => realpath($path)) ->reject(fn ($path) => $path === false); } + /** @return array */ protected function getMatchingPaths(string $path): array { if ($this->canUseGlobBrace($path)) { diff --git a/src/Tasks/Backup/Manifest.php b/src/Tasks/Backup/Manifest.php index 330b23b9..ab0efa2d 100644 --- a/src/Tasks/Backup/Manifest.php +++ b/src/Tasks/Backup/Manifest.php @@ -23,6 +23,9 @@ public function path(): string return $this->manifestPath; } + /** + * @param Generator|string|array $filePaths + */ public function addFiles(array|string|Generator $filePaths): self { if (is_string($filePaths)) { diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index 1234649a..83b0010f 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -30,7 +30,7 @@ public static function createForManifest(Manifest $manifest, string $pathToZip): return $zip; } - protected static function determineNameOfFileInZip(string $pathToFile, string $pathToZip, string $relativePath) + protected static function determineNameOfFileInZip(string $pathToFile, string $pathToZip, string $relativePath): string { $fileDirectory = pathinfo($pathToFile, PATHINFO_DIRNAME).DIRECTORY_SEPARATOR; diff --git a/src/Tasks/Cleanup/CleanupJob.php b/src/Tasks/Cleanup/CleanupJob.php index c782e426..a8734eda 100644 --- a/src/Tasks/Cleanup/CleanupJob.php +++ b/src/Tasks/Cleanup/CleanupJob.php @@ -13,6 +13,7 @@ class CleanupJob { protected bool $sendNotifications = true; + /** @param Collection $backupDestinations */ public function __construct( protected Collection $backupDestinations, protected CleanupStrategy $strategy, @@ -49,7 +50,7 @@ public function run(): void }); } - protected function sendNotification($notification): void + protected function sendNotification(string|object $notification): void { if ($this->sendNotifications) { rescue( diff --git a/src/Tasks/Cleanup/CleanupStrategy.php b/src/Tasks/Cleanup/CleanupStrategy.php index 49bf3438..59d698f9 100644 --- a/src/Tasks/Cleanup/CleanupStrategy.php +++ b/src/Tasks/Cleanup/CleanupStrategy.php @@ -15,7 +15,7 @@ public function __construct( ) { } - abstract public function deleteOldBackups(BackupCollection $backups); + abstract public function deleteOldBackups(BackupCollection $backups): void; public function setBackupDestination(BackupDestination $backupDestination): self { diff --git a/src/Tasks/Cleanup/Strategies/DefaultStrategy.php b/src/Tasks/Cleanup/Strategies/DefaultStrategy.php index f73dca91..d4ba5c17 100644 --- a/src/Tasks/Cleanup/Strategies/DefaultStrategy.php +++ b/src/Tasks/Cleanup/Strategies/DefaultStrategy.php @@ -20,7 +20,7 @@ public function deleteOldBackups(BackupCollection $backups): void $dateRanges = $this->calculateDateRanges(); - /** @var Collection<(string|BackupCollection)> */ + /** @var Collection $backupsPerPeriod */ $backupsPerPeriod = $dateRanges->map(function (Period $period) use ($backups) { return $backups ->filter(fn (Backup $backup) => $backup->date()->between($period->startDate(), $period->endDate())); @@ -38,6 +38,7 @@ public function deleteOldBackups(BackupCollection $backups): void $this->removeOldBackupsUntilUsingLessThanMaximumStorage($backups); } + /** @return Collection */ protected function calculateDateRanges(): Collection { $config = $this->config->get('backup.cleanup.default_strategy'); @@ -70,15 +71,16 @@ protected function calculateDateRanges(): Collection return collect(compact('daily', 'weekly', 'monthly', 'yearly')); } - protected function groupByDateFormat(Collection $backups, string $dateFormat): Collection + protected function groupByDateFormat(BackupCollection $backups, string $dateFormat): BackupCollection { return $backups->groupBy(fn (Backup $backup) => $backup->date()->format($dateFormat)); } - protected function removeBackupsForAllPeriodsExceptOne(Collection $backupsPerPeriod) + /** @param Collection $backupsPerPeriod */ + protected function removeBackupsForAllPeriodsExceptOne(Collection $backupsPerPeriod): void { $backupsPerPeriod->each(function (Collection $groupedBackupsByDateProperty, string $periodName) { - $groupedBackupsByDateProperty->each(function (Collection $group) { + $groupedBackupsByDateProperty->each(function (BackupCollection $group) { $group->shift(); $group->each(fn (Backup $backup) => $backup->delete()); @@ -86,14 +88,14 @@ protected function removeBackupsForAllPeriodsExceptOne(Collection $backupsPerPer }); } - protected function removeBackupsOlderThan(Carbon $endDate, BackupCollection $backups) + protected function removeBackupsOlderThan(Carbon $endDate, BackupCollection $backups): void { $backups ->filter(fn (Backup $backup) => $backup->exists() && $backup->date()->lt($endDate)) ->each(fn (Backup $backup) => $backup->delete()); } - protected function removeOldBackupsUntilUsingLessThanMaximumStorage(BackupCollection $backups) + protected function removeOldBackupsUntilUsingLessThanMaximumStorage(BackupCollection $backups): void { if (! $this->shouldRemoveOldestBackup($backups)) { return; diff --git a/src/Tasks/Monitor/BackupDestinationStatus.php b/src/Tasks/Monitor/BackupDestinationStatus.php index 5908ef7d..35387e6f 100644 --- a/src/Tasks/Monitor/BackupDestinationStatus.php +++ b/src/Tasks/Monitor/BackupDestinationStatus.php @@ -11,6 +11,7 @@ class BackupDestinationStatus { protected ?HealthCheckFailure $healthCheckFailure = null; + /** @param array $healthChecks */ public function __construct( protected BackupDestination $backupDestination, protected array $healthChecks = [] @@ -33,6 +34,7 @@ public function check(HealthCheck $check): bool|HealthCheckFailure return true; } + /** @return Collection */ public function getHealthChecks(): Collection { return collect($this->healthChecks)->prepend(new IsReachable()); diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index 81036302..eb2ad233 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -8,6 +8,11 @@ class BackupDestinationStatusFactory { + + /** + * @param array{name: string, disks: array, health_checks: array>} $monitorConfiguration + * @return Collection + */ public static function createForMonitorConfig(array $monitorConfiguration): Collection { return collect($monitorConfiguration) @@ -16,6 +21,10 @@ public static function createForMonitorConfig(array $monitorConfiguration): Coll $backupDestinationStatus->backupDestination()->diskName()); } + /** + * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @return Collection + */ public static function createForSingleMonitor(array $monitorConfig): Collection { return collect($monitorConfig['disks']) @@ -26,9 +35,22 @@ public static function createForSingleMonitor(array $monitorConfig): Collection }); } - protected static function buildHealthChecks($monitorConfig): array + /** + * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @return array + */ + protected static function buildHealthChecks(array $monitorConfig): array { - return collect(Arr::get($monitorConfig, 'health_checks')) + ray(collect($monitorConfig['health_checks']) + ->map(function ($options, $class) { + if (is_int($class)) { + $class = $options; + $options = []; + } + + return static::buildHealthCheck($class, $options); + })->toArray()); + return collect($monitorConfig['health_checks']) ->map(function ($options, $class) { if (is_int($class)) { $class = $options; @@ -39,6 +61,7 @@ protected static function buildHealthChecks($monitorConfig): array })->toArray(); } + /** @param string|array $options */ protected static function buildHealthCheck(string $class, string|array $options): HealthCheck { if (! is_array($options)) { diff --git a/src/Tasks/Monitor/HealthCheck.php b/src/Tasks/Monitor/HealthCheck.php index 6d04f141..499c12e5 100644 --- a/src/Tasks/Monitor/HealthCheck.php +++ b/src/Tasks/Monitor/HealthCheck.php @@ -8,7 +8,7 @@ abstract class HealthCheck { - abstract public function checkHealth(BackupDestination $backupDestination); + abstract public function checkHealth(BackupDestination $backupDestination): void; public function name(): string { diff --git a/src/Traits/Retryable.php b/src/Traits/Retryable.php index 69a973c2..bae1cf1a 100644 --- a/src/Traits/Retryable.php +++ b/src/Traits/Retryable.php @@ -10,7 +10,7 @@ trait Retryable protected int $currentTry = 1; - protected function shouldRetry() + protected function shouldRetry(): bool { if ($this->tries <= 1) { return false; @@ -19,17 +19,17 @@ protected function shouldRetry() return $this->currentTry < $this->tries; } - protected function hasRetryDelay(string $type) + protected function hasRetryDelay(string $type): bool { return ! empty($this->getRetryDelay($type)); } - protected function sleepFor(int $seconds = 0) + protected function sleepFor(int $seconds = 0): void { Sleep::for($seconds)->seconds(); } - protected function setTries(string $type) + protected function setTries(string $type): void { if ($this->option('tries')) { $this->tries = (int) $this->option('tries'); @@ -40,7 +40,7 @@ protected function setTries(string $type) $this->tries = (int) config('backup.'.$type.'.tries', 1); } - protected function getRetryDelay(string $type) + protected function getRetryDelay(string $type): int { return (int) config('backup.'.$type.'.retry_delay', 0); } diff --git a/tests/TestSupport/FakeFailingHealthCheck.php b/tests/TestSupport/FakeFailingHealthCheck.php index 7f96a5f6..d0be35a4 100644 --- a/tests/TestSupport/FakeFailingHealthCheck.php +++ b/tests/TestSupport/FakeFailingHealthCheck.php @@ -10,7 +10,7 @@ class FakeFailingHealthCheck extends HealthCheck { public static $reason; - public function checkHealth(BackupDestination $backupDestination) + public function checkHealth(BackupDestination $backupDestination): void { throw (static::$reason ?: new Exception('dummy exception message')); } From 3016d9987825763c96cc1af7602253e7d2dba83f Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 7 Jun 2024 11:43:33 +0000 Subject: [PATCH 09/33] Fix styling --- src/BackupDestination/BackupDestinationFactory.php | 2 +- src/Commands/ListCommand.php | 4 ++-- src/Tasks/Backup/BackupJob.php | 2 +- src/Tasks/Backup/BackupJobFactory.php | 2 +- src/Tasks/Backup/FileSelection.php | 2 +- src/Tasks/Backup/Manifest.php | 2 +- src/Tasks/Monitor/BackupDestinationStatusFactory.php | 9 ++++----- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/BackupDestination/BackupDestinationFactory.php b/src/BackupDestination/BackupDestinationFactory.php index 99c085b4..8ba0e95b 100644 --- a/src/BackupDestination/BackupDestinationFactory.php +++ b/src/BackupDestination/BackupDestinationFactory.php @@ -7,7 +7,7 @@ class BackupDestinationFactory { /** - * @param array $config + * @param array $config * @return Collection */ public static function createFromArray(array $config): Collection diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index 94d961e3..2c76faa1 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -31,7 +31,7 @@ public function handle(): int } /** - * @param Collection $backupDestinationStatuses + * @param Collection $backupDestinationStatuses */ protected function displayOverview(Collection $backupDestinationStatuses): static { @@ -49,7 +49,7 @@ protected function displayOverview(Collection $backupDestinationStatuses): stati return $this; } - /** @return array{0: string, 1: string, 2: string, disk: string, amount: integer, newest: string, usedStorage: string} */ + /** @return array{0: string, 1: string, 2: string, disk: string, amount: int, newest: string, usedStorage: string} */ public function convertToRow(BackupDestinationStatus $backupDestinationStatus): array { $destination = $backupDestinationStatus->backupDestination(); diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index 16bf96d2..5453426c 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -104,7 +104,7 @@ public function setFileSelection(FileSelection $fileSelection): self } /** - * @param Collection $dbDumpers + * @param Collection $dbDumpers * @return $this */ public function setDbDumpers(Collection $dbDumpers): self diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index 3ce874a8..64bfb7fc 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -28,7 +28,7 @@ protected static function createFileSelection(array $sourceFiles): FileSelection } /** - * @param array $dbConnectionNames + * @param array $dbConnectionNames * @return Collection */ protected static function createDbDumpers(array $dbConnectionNames): Collection diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index 45364662..9daae78b 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -130,7 +130,7 @@ protected function shouldExclude(string $path): bool } /** - * @param string|array $paths + * @param string|array $paths */ protected function sanitize(string|array $paths): Collection { diff --git a/src/Tasks/Backup/Manifest.php b/src/Tasks/Backup/Manifest.php index ab0efa2d..538dc4a8 100644 --- a/src/Tasks/Backup/Manifest.php +++ b/src/Tasks/Backup/Manifest.php @@ -24,7 +24,7 @@ public function path(): string } /** - * @param Generator|string|array $filePaths + * @param Generator|string|array $filePaths */ public function addFiles(array|string|Generator $filePaths): self { diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index eb2ad233..233fdec8 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -2,15 +2,13 @@ namespace Spatie\Backup\Tasks\Monitor; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; class BackupDestinationStatusFactory { - /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfiguration + * @param array{name: string, disks: array, health_checks: array>} $monitorConfiguration * @return Collection */ public static function createForMonitorConfig(array $monitorConfiguration): Collection @@ -22,7 +20,7 @@ public static function createForMonitorConfig(array $monitorConfiguration): Coll } /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @param array{name: string, disks: array, health_checks: array>} $monitorConfig * @return Collection */ public static function createForSingleMonitor(array $monitorConfig): Collection @@ -36,7 +34,7 @@ public static function createForSingleMonitor(array $monitorConfig): Collection } /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @param array{name: string, disks: array, health_checks: array>} $monitorConfig * @return array */ protected static function buildHealthChecks(array $monitorConfig): array @@ -50,6 +48,7 @@ protected static function buildHealthChecks(array $monitorConfig): array return static::buildHealthCheck($class, $options); })->toArray()); + return collect($monitorConfig['health_checks']) ->map(function ($options, $class) { if (is_int($class)) { From 712f2f82320896bb18f7c3f5ab0466afaa47c25f Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:06:31 +0200 Subject: [PATCH 10/33] mock the config file into classes --- src/Config/BackupConfig.php | 27 +++++++++++++++++++++++++++ src/Config/DestinationConfig.php | 20 ++++++++++++++++++++ src/Config/NotificationsConfig.php | 21 +++++++++++++++++++++ src/Config/SourceConfig.php | 17 +++++++++++++++++ src/Config/SourceFilesConfig.php | 24 ++++++++++++++++++++++++ src/Support/Data.php | 30 ++++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+) create mode 100644 src/Config/BackupConfig.php create mode 100644 src/Config/DestinationConfig.php create mode 100644 src/Config/NotificationsConfig.php create mode 100644 src/Config/SourceConfig.php create mode 100644 src/Config/SourceFilesConfig.php create mode 100644 src/Support/Data.php diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php new file mode 100644 index 00000000..ab4a3cff --- /dev/null +++ b/src/Config/BackupConfig.php @@ -0,0 +1,27 @@ + $compressionLevel + * @param array $disks + */ + public function __construct( + public int $compressionMethod, + public int $compressionLevel, + public string $filenamePrefix, + public array $disks, + ) { + } +} diff --git a/src/Config/NotificationsConfig.php b/src/Config/NotificationsConfig.php new file mode 100644 index 00000000..a137b60f --- /dev/null +++ b/src/Config/NotificationsConfig.php @@ -0,0 +1,21 @@ +, array> $notifications + * @param class-string $notifiable + */ + public function __construct( + public array $notifications, + public string $notifiable, + ) { + // @todo mail, slack, discord + } +} diff --git a/src/Config/SourceConfig.php b/src/Config/SourceConfig.php new file mode 100644 index 00000000..a1060dea --- /dev/null +++ b/src/Config/SourceConfig.php @@ -0,0 +1,17 @@ + $databases + */ + public function __construct( + public SourceFilesConfig $files, + public array $databases, + ) { + } +} diff --git a/src/Config/SourceFilesConfig.php b/src/Config/SourceFilesConfig.php new file mode 100644 index 00000000..bc0c8642 --- /dev/null +++ b/src/Config/SourceFilesConfig.php @@ -0,0 +1,24 @@ + $include + * @param array $exclude + * @param bool $followLinks + * @param bool $ignoreUnreadableDirectories + * @param string|null $relativePath + */ + public function __construct( + public array $include, + public array $exclude, + public bool $followLinks, + public bool $ignoreUnreadableDirectories, + public ?string $relativePath, + ) { + } +} diff --git a/src/Support/Data.php b/src/Support/Data.php new file mode 100644 index 00000000..c8f474a1 --- /dev/null +++ b/src/Support/Data.php @@ -0,0 +1,30 @@ + */ +class Data implements Arrayable +{ + public function toArray(): array + { + $array = []; + $reflectionClass = new ReflectionClass($this); + + foreach ($reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { + $name = $property->getName(); + $value = $this->$name; + + if ($value instanceof Arrayable) { + $array[$name] = $value->toArray(); + } else { + $array[$name] = $value; + } + } + + return $array; + } +} From 7cfa2856b79d0f30c062b9ec41bcdef2719d9dea Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:15:20 +0200 Subject: [PATCH 11/33] add the Config value object to the service provider --- src/BackupServiceProvider.php | 5 +++++ src/Config/BackupConfig.php | 21 ++++++++++++++++++++- src/Config/DestinationConfig.php | 13 ++++++++++++- src/Config/SourceConfig.php | 11 ++++++++++- src/Config/SourceFilesConfig.php | 17 +++++++++++++---- 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index ecd087bb..e7c98031 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -9,6 +9,7 @@ use Spatie\Backup\Commands\CleanupCommand; use Spatie\Backup\Commands\ListCommand; use Spatie\Backup\Commands\MonitorCommand; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\BackupZipWasCreated; use Spatie\Backup\Helpers\ConsoleOutput; use Spatie\Backup\Listeners\EncryptBackupArchive; @@ -50,6 +51,10 @@ public function packageRegistered(): void $this->app->bind(CleanupStrategy::class, config('backup.cleanup.strategy')); $this->registerDiscordChannel(); + + $this->app->singleton(BackupConfig::class, function () { + return BackupConfig::fromArray(config('backup.backup')); + }); } protected function registerDiscordChannel(): void diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index ab4a3cff..7fdcf3b0 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -9,7 +9,7 @@ class BackupConfig extends Data /** * @param positive-int $tries */ - public function __construct( + protected function __construct( public string $name, public SourceConfig $source, public ?string $databaseDumpCompressor, @@ -24,4 +24,23 @@ public function __construct( public int $retryDelay, ) { } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + name: $data['name'], + source: SourceConfig::fromArray($data['source']), + databaseDumpCompressor: $data['database_dump_compressor'], + databaseDumpFileTimestampFormat: $data['database_dump_file_timestamp_format'], + databaseDumpFilenameBase: $data['database_dump_file_directory'], + databaseDumpFileExtension: $data['database_dump_file_extension'], + destination: DestinationConfig::fromArray($data['destination']), + temporaryDirectory: $data['temporary_directory'], + password: $data['password'], + encryption: $data['encryption'], + tries: $data['tries'], + retryDelay: $data['retry_delay'], + ); + } } diff --git a/src/Config/DestinationConfig.php b/src/Config/DestinationConfig.php index 10321723..648fc3fb 100644 --- a/src/Config/DestinationConfig.php +++ b/src/Config/DestinationConfig.php @@ -10,11 +10,22 @@ class DestinationConfig extends Data * @param int<0,9> $compressionLevel * @param array $disks */ - public function __construct( + protected function __construct( public int $compressionMethod, public int $compressionLevel, public string $filenamePrefix, public array $disks, ) { } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + compressionMethod: $data['compression_method'], + compressionLevel: $data['compression_level'], + filenamePrefix: $data['filename_prefix'], + disks: $data['disks'], + ); + } } diff --git a/src/Config/SourceConfig.php b/src/Config/SourceConfig.php index a1060dea..1cc7ead4 100644 --- a/src/Config/SourceConfig.php +++ b/src/Config/SourceConfig.php @@ -9,9 +9,18 @@ class SourceConfig extends Data /** * @param array $databases */ - public function __construct( + protected function __construct( public SourceFilesConfig $files, public array $databases, ) { } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + files: SourceFilesConfig::fromArray($data['files']), + databases: $data['databases'], + ); + } } diff --git a/src/Config/SourceFilesConfig.php b/src/Config/SourceFilesConfig.php index bc0c8642..97ba8b8d 100644 --- a/src/Config/SourceFilesConfig.php +++ b/src/Config/SourceFilesConfig.php @@ -9,11 +9,8 @@ class SourceFilesConfig extends Data /** * @param array $include * @param array $exclude - * @param bool $followLinks - * @param bool $ignoreUnreadableDirectories - * @param string|null $relativePath */ - public function __construct( + protected function __construct( public array $include, public array $exclude, public bool $followLinks, @@ -21,4 +18,16 @@ public function __construct( public ?string $relativePath, ) { } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + include: $data['include'], + exclude: $data['exclude'], + followLinks: $data['follow_links'], + ignoreUnreadableDirectories: $data['ignore_unreadable_directories'], + relativePath: $data['relative_path'], + ); + } } From 75202bcfc9cc75c9a36dcf10017df8a7394fdcb5 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:38:41 +0200 Subject: [PATCH 12/33] pass the appropriate config class down the line --- .../BackupDestinationFactory.php | 8 +++---- src/Commands/BackupCommand.php | 8 ++++++- src/Commands/CleanupCommand.php | 9 ++++--- src/Config/BackupConfig.php | 2 +- src/Config/SourceFilesConfig.php | 4 ++-- src/Tasks/Backup/BackupJob.php | 6 +++-- src/Tasks/Backup/BackupJobFactory.php | 24 +++++++++---------- tests/BackupDestination/BackupTest.php | 9 +++++-- tests/Notifications/EventHandlerTest.php | 7 ++++-- 9 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/BackupDestination/BackupDestinationFactory.php b/src/BackupDestination/BackupDestinationFactory.php index 99c085b4..6beab64e 100644 --- a/src/BackupDestination/BackupDestinationFactory.php +++ b/src/BackupDestination/BackupDestinationFactory.php @@ -3,16 +3,16 @@ namespace Spatie\Backup\BackupDestination; use Illuminate\Support\Collection; +use Spatie\Backup\Config\BackupConfig; class BackupDestinationFactory { /** - * @param array $config * @return Collection */ - public static function createFromArray(array $config): Collection + public static function createFromArray(BackupConfig $config): Collection { - return collect($config['destination']['disks']) - ->map(fn ($filesystemName) => BackupDestination::create($filesystemName, $config['name'])); + return collect($config->destination->disks) + ->map(fn (string $filesystemName) => BackupDestination::create($filesystemName, $config->name)); } } diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index 07dfdaa7..ebaca067 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -4,6 +4,7 @@ use Exception; use Illuminate\Contracts\Console\Isolatable; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\BackupHasFailed; use Spatie\Backup\Exceptions\BackupFailed; use Spatie\Backup\Exceptions\InvalidCommand; @@ -18,6 +19,11 @@ class BackupCommand extends BaseCommand implements Isolatable protected $description = 'Run the backup.'; + public function __construct(protected BackupConfig $config) + { + parent::__construct(); + } + public function handle(): int { consoleOutput()->comment($this->currentTry > 1 ? sprintf('Attempt n°%d...', $this->currentTry) : 'Starting backup...'); @@ -31,7 +37,7 @@ public function handle(): int try { $this->guardAgainstInvalidOptions(); - $backupJob = BackupJobFactory::createFromArray(config('backup')); + $backupJob = BackupJobFactory::createFromConfig($this->config); if ($this->option('only-db')) { $backupJob->dontBackupFilesystem(); diff --git a/src/Commands/CleanupCommand.php b/src/Commands/CleanupCommand.php index 28551e3f..83393d4a 100644 --- a/src/Commands/CleanupCommand.php +++ b/src/Commands/CleanupCommand.php @@ -5,6 +5,7 @@ use Exception; use Illuminate\Contracts\Console\Isolatable; use Spatie\Backup\BackupDestination\BackupDestinationFactory; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\CleanupHasFailed; use Spatie\Backup\Tasks\Cleanup\CleanupJob; use Spatie\Backup\Tasks\Cleanup\CleanupStrategy; @@ -20,8 +21,10 @@ class CleanupCommand extends BaseCommand implements Isolatable /** @var string */ protected $description = 'Remove all backups older than specified number of days in config.'; - public function __construct(protected CleanupStrategy $strategy) - { + public function __construct( + protected CleanupStrategy $strategy, + protected BackupConfig $config, + ) { parent::__construct(); } @@ -36,7 +39,7 @@ public function handle(): int try { $config = config('backup'); - $backupDestinations = BackupDestinationFactory::createFromArray($config['backup']); + $backupDestinations = BackupDestinationFactory::createFromArray($this->config); $cleanupJob = new CleanupJob($backupDestinations, $this->strategy, $disableNotifications); diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index 7fdcf3b0..c3a59ed8 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -33,7 +33,7 @@ public static function fromArray(array $data): self source: SourceConfig::fromArray($data['source']), databaseDumpCompressor: $data['database_dump_compressor'], databaseDumpFileTimestampFormat: $data['database_dump_file_timestamp_format'], - databaseDumpFilenameBase: $data['database_dump_file_directory'], + databaseDumpFilenameBase: $data['database_dump_filename_base'], databaseDumpFileExtension: $data['database_dump_file_extension'], destination: DestinationConfig::fromArray($data['destination']), temporaryDirectory: $data['temporary_directory'], diff --git a/src/Config/SourceFilesConfig.php b/src/Config/SourceFilesConfig.php index 97ba8b8d..af36b32c 100644 --- a/src/Config/SourceFilesConfig.php +++ b/src/Config/SourceFilesConfig.php @@ -25,8 +25,8 @@ public static function fromArray(array $data): self return new self( include: $data['include'], exclude: $data['exclude'], - followLinks: $data['follow_links'], - ignoreUnreadableDirectories: $data['ignore_unreadable_directories'], + followLinks: $data['follow_links'] ?? false, + ignoreUnreadableDirectories: $data['ignore_unreadable_directories'] ?? false, relativePath: $data['relative_path'], ); } diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index 16bf96d2..ae03920c 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -8,6 +8,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\BackupManifestWasCreated; use Spatie\Backup\Events\BackupWasSuccessful; use Spatie\Backup\Events\BackupZipWasCreated; @@ -41,7 +42,7 @@ class BackupJob protected bool $signals = true; - public function __construct() + public function __construct(protected BackupConfig $config) { $this ->dontBackupFilesystem() @@ -278,7 +279,8 @@ protected function dumpDatabases(): array $fileName .= '.'.$dbDumper->getCompressorExtension(); } - if ($compressor = config('backup.backup.database_dump_compressor')) { + ray($this->config->databaseDumpCompressor); + if ($compressor = $this->config->databaseDumpCompressor) { $dbDumper->useCompressor(new $compressor()); $fileName .= '.'.$dbDumper->getCompressorExtension(); } diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index 3ce874a8..a77919ae 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -5,26 +5,26 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestinationFactory; +use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\SourceFilesConfig; use Spatie\DbDumper\DbDumper; class BackupJobFactory { - /** @param array> $config */ - public static function createFromArray(array $config): BackupJob + public static function createFromConfig(BackupConfig $config): BackupJob { - return (new BackupJob()) - ->setFileSelection(static::createFileSelection($config['backup']['source']['files'])) - ->setDbDumpers(static::createDbDumpers($config['backup']['source']['databases'])) - ->setBackupDestinations(BackupDestinationFactory::createFromArray($config['backup'])); + return (new BackupJob($config)) + ->setFileSelection(static::createFileSelection($config->source->files)) + ->setDbDumpers(static::createDbDumpers($config->source->databases)) + ->setBackupDestinations(BackupDestinationFactory::createFromArray($config)); } - /** @param array $sourceFiles */ - protected static function createFileSelection(array $sourceFiles): FileSelection + protected static function createFileSelection(SourceFilesConfig $sourceFiles): FileSelection { - return FileSelection::create($sourceFiles['include']) - ->excludeFilesFrom($sourceFiles['exclude']) - ->shouldFollowLinks(isset($sourceFiles['follow_links']) && $sourceFiles['follow_links']) - ->shouldIgnoreUnreadableDirs(Arr::get($sourceFiles, 'ignore_unreadable_directories', false)); + return FileSelection::create($sourceFiles->include) + ->excludeFilesFrom($sourceFiles->exclude) + ->shouldFollowLinks($sourceFiles->followLinks) + ->shouldIgnoreUnreadableDirs($sourceFiles->ignoreUnreadableDirectories); } /** diff --git a/tests/BackupDestination/BackupTest.php b/tests/BackupDestination/BackupTest.php index 9767eabd..a5c1b5a5 100644 --- a/tests/BackupDestination/BackupTest.php +++ b/tests/BackupDestination/BackupTest.php @@ -6,6 +6,7 @@ use Mockery as m; use Spatie\Backup\BackupDestination\Backup; use Spatie\Backup\BackupDestination\BackupDestinationFactory; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Exceptions\InvalidBackupFile; it('can determine the disk of the backup', function () { @@ -92,7 +93,9 @@ 's3-test-backup', ]); - $backupDestination = BackupDestinationFactory::createFromArray(config('backup.backup'))->first(); + $config = BackupConfig::fromArray(config('backup.backup')); + + $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); expect($backupDestination->getDiskOptions())->toEqual(['StorageClass' => 'COLD']); }); @@ -107,7 +110,9 @@ 'local', ]); - $backupDestination = BackupDestinationFactory::createFromArray(config('backup.backup'))->first(); + $config = BackupConfig::fromArray(config('backup.backup')); + + $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); expect($backupDestination->getDiskOptions())->toBe([]); }); diff --git a/tests/Notifications/EventHandlerTest.php b/tests/Notifications/EventHandlerTest.php index 5da94435..f3fa87b2 100644 --- a/tests/Notifications/EventHandlerTest.php +++ b/tests/Notifications/EventHandlerTest.php @@ -2,6 +2,7 @@ use Illuminate\Support\Facades\Notification; use Spatie\Backup\BackupDestination\BackupDestinationFactory; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\BackupHasFailed; use Spatie\Backup\Notifications\Notifiable; use Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification; @@ -49,11 +50,13 @@ Notification::assertSentTimes(BackupHasFailedNotification::class, 1); }); -function fireBackupHasFailedEvent() +function fireBackupHasFailedEvent(): void { $exception = new Exception('Dummy exception'); - $backupDestination = BackupDestinationFactory::createFromArray(config('backup.backup'))->first(); + $config = BackupConfig::fromArray(config('backup.backup')); + + $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); event(new BackupHasFailed($exception, $backupDestination)); } From 7a9e9a88f2d253356425f86f95ff3c0550c19ead Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 15:13:08 +0200 Subject: [PATCH 13/33] define all config --- src/Commands/MonitorCommand.php | 6 ++++ src/Config/BackupConfig.php | 4 +++ src/Config/CleanupConfig.php | 31 ++++++++++++++++++++ src/Config/MonitoredBackupConfig.php | 29 +++++++++++++++++++ src/Config/MonitoredBackupsConfig.php | 24 +++++++++++++++ src/Config/NotificationDiscordConfig.php | 23 +++++++++++++++ src/Config/NotificationMailConfig.php | 37 ++++++++++++++++++++++++ src/Config/NotificationSlackConfig.php | 27 +++++++++++++++++ src/Config/NotificationsConfig.php | 22 +++++++++++--- src/Config/StrategyConfig.php | 29 +++++++++++++++++++ src/Exceptions/InvalidConfig.php | 13 +++++++++ 11 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 src/Config/CleanupConfig.php create mode 100644 src/Config/MonitoredBackupConfig.php create mode 100644 src/Config/MonitoredBackupsConfig.php create mode 100644 src/Config/NotificationDiscordConfig.php create mode 100644 src/Config/NotificationMailConfig.php create mode 100644 src/Config/NotificationSlackConfig.php create mode 100644 src/Config/StrategyConfig.php create mode 100644 src/Exceptions/InvalidConfig.php diff --git a/src/Commands/MonitorCommand.php b/src/Commands/MonitorCommand.php index 652cda42..c9a1a9f6 100644 --- a/src/Commands/MonitorCommand.php +++ b/src/Commands/MonitorCommand.php @@ -3,6 +3,7 @@ namespace Spatie\Backup\Commands; use Illuminate\Contracts\Console\Isolatable; +use Spatie\Backup\Config\BackupConfig; use Spatie\Backup\Events\HealthyBackupWasFound; use Spatie\Backup\Events\UnhealthyBackupWasFound; use Spatie\Backup\Tasks\Monitor\BackupDestinationStatusFactory; @@ -15,6 +16,11 @@ class MonitorCommand extends BaseCommand implements Isolatable /** @var string */ protected $description = 'Monitor the health of all backups.'; + public function __construct(protected BackupConfig $config) + { + parent::__construct(); + } + public function handle(): int { if (config()->has('backup.monitorBackups')) { diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index c3a59ed8..542a0773 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -22,6 +22,8 @@ protected function __construct( public string $encryption, public int $tries, public int $retryDelay, + public ?NotificationsConfig $notifications, + public ?MonitoredBackupsConfig $monitoredBackups, ) { } @@ -41,6 +43,8 @@ public static function fromArray(array $data): self encryption: $data['encryption'], tries: $data['tries'], retryDelay: $data['retry_delay'], + notifications: isset($data['notifications']) ? NotificationsConfig::fromArray($data['notifications']) : null, + monitoredBackups: isset($data['monitored_backups']) ? MonitoredBackupsConfig::fromArray($data['monitored_backups']) : null, ); } } diff --git a/src/Config/CleanupConfig.php b/src/Config/CleanupConfig.php new file mode 100644 index 00000000..59366a92 --- /dev/null +++ b/src/Config/CleanupConfig.php @@ -0,0 +1,31 @@ + $strategy + * @param positive-int $tries + */ + protected function __construct( + public string $strategy, + public StrategyConfig $defaultStrategy, + public int $tries, + public int $retryDelay, + ) { + } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + strategy: $data['strategy'], + defaultStrategy: StrategyConfig::fromArray($data['defaultStrategy']), + tries: $data['tries'], + retryDelay: $data['retryDelay'], + ); + } +} diff --git a/src/Config/MonitoredBackupConfig.php b/src/Config/MonitoredBackupConfig.php new file mode 100644 index 00000000..1147447c --- /dev/null +++ b/src/Config/MonitoredBackupConfig.php @@ -0,0 +1,29 @@ + $disks + * @param array $healthChecks + */ + protected function __construct( + public string $name, + public array $disks, + public array $healthChecks, + ) { + } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + name: $data['name'], + disks: $data['disks'], + healthChecks: $data['health_checks'], + ); + } +} diff --git a/src/Config/MonitoredBackupsConfig.php b/src/Config/MonitoredBackupsConfig.php new file mode 100644 index 00000000..7e0b2f6c --- /dev/null +++ b/src/Config/MonitoredBackupsConfig.php @@ -0,0 +1,24 @@ + $monitorBackups + */ + protected function __construct ( + public array $monitorBackups, + ) { + } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + monitorBackups: collect($data) + ->map(fn (array $monitoredBackup) => MonitoredBackupConfig::fromArray($monitoredBackup)) + ->toArray(), + ); + } +} diff --git a/src/Config/NotificationDiscordConfig.php b/src/Config/NotificationDiscordConfig.php new file mode 100644 index 00000000..73c71d3b --- /dev/null +++ b/src/Config/NotificationDiscordConfig.php @@ -0,0 +1,23 @@ + $data */ + public static function fromArray(array $data): self + { + return new self( + webhookUrl: $data['webhook_url'], + channel: $data['channel'], + avatar_url: $data['avatar_url'], + ); + } +} diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php new file mode 100644 index 00000000..4b288787 --- /dev/null +++ b/src/Config/NotificationMailConfig.php @@ -0,0 +1,37 @@ + $data + * @throws InvalidConfig + */ + public static function fromArray(array $data): self + { + if (filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { + throw InvalidConfig::invalidEmail($data['to']); + } + + if (filter_var($data['from']['address'], FILTER_VALIDATE_EMAIL)) { + throw InvalidConfig::invalidEmail($data['from']['address']); + } + + return new self( + to: $data['to'], + from: $data['from'], + ); + } +} diff --git a/src/Config/NotificationSlackConfig.php b/src/Config/NotificationSlackConfig.php new file mode 100644 index 00000000..ae02f391 --- /dev/null +++ b/src/Config/NotificationSlackConfig.php @@ -0,0 +1,27 @@ + $data */ + public static function fromArray(array $data): self + { + return new self( + webhookUrl: $data['webhook_url'], + channel: $data['channel'], + username: $data['username'], + icon: $data['icon'], + ); + } +} diff --git a/src/Config/NotificationsConfig.php b/src/Config/NotificationsConfig.php index a137b60f..9b722ec4 100644 --- a/src/Config/NotificationsConfig.php +++ b/src/Config/NotificationsConfig.php @@ -12,10 +12,24 @@ class NotificationsConfig extends Data * @param array, array> $notifications * @param class-string $notifiable */ - public function __construct( - public array $notifications, - public string $notifiable, + protected function __construct( + public array $notifications, + public string $notifiable, + public NotificationMailConfig $mail, + public NotificationSlackConfig $slack, + public NotificationDiscordConfig $discord, ) { - // @todo mail, slack, discord + } + + /** @param array $data */ + public static function fromArray(array $data): self + { + return new self( + notifications: $data['notifications'], + notifiable: $data['notifiable'], + mail: $data['mail'], + slack: $data['slack'], + discord: $data['discord'], + ); } } diff --git a/src/Config/StrategyConfig.php b/src/Config/StrategyConfig.php new file mode 100644 index 00000000..543bf205 --- /dev/null +++ b/src/Config/StrategyConfig.php @@ -0,0 +1,29 @@ + $data */ + public static function fromArray(array $data): self + { + return new self( + keepAllBackupsForDays: $data['keep_all_backups_for_days'], + keepDailyBackupsForDays: $data['keep_daily_backups_for_days'], + keepWeeklyBackupsForWeeks: $data['keep_weekly_backups_for_days'], + keepMonthlyBackupsForMonths: $data['keep_monthly_backups_for_days'], + keepYearlyBackupsForYears: $data['keep_yearly_backups_for_days'], + deleteOldestBackupsWhenUsingMoreMegabytesThan: $data['delete_oldest_backups_when_using_more_megabytes_than'], + ); + } +} diff --git a/src/Exceptions/InvalidConfig.php b/src/Exceptions/InvalidConfig.php new file mode 100644 index 00000000..930e8bd1 --- /dev/null +++ b/src/Exceptions/InvalidConfig.php @@ -0,0 +1,13 @@ + Date: Fri, 7 Jun 2024 16:09:31 +0200 Subject: [PATCH 14/33] use Config class in more places --- phpstan-baseline.neon | 15 ++++------- .../BackupDestinationFactory.php | 8 +++--- src/BackupServiceProvider.php | 6 ++--- src/Commands/BackupCommand.php | 4 +-- src/Commands/CleanupCommand.php | 6 ++--- src/Commands/ListCommand.php | 12 +++++---- src/Commands/MonitorCommand.php | 10 +++----- src/Config/BackupConfig.php | 4 ++- src/Config/CleanupConfig.php | 7 +++--- src/Config/Config.php | 25 +++++++++++++++++++ src/Config/MonitoredBackupConfig.php | 5 ++-- src/Config/MonitoredBackupsConfig.php | 4 ++- src/Config/NotificationDiscordConfig.php | 4 ++- src/Config/NotificationMailConfig.php | 3 ++- src/Config/StrategyConfig.php | 10 +++++--- src/Tasks/Backup/BackupJob.php | 7 +++--- src/Tasks/Backup/BackupJobFactory.php | 8 +++--- .../BackupDestinationStatusFactory.php | 21 +++++----------- tests/BackupDestination/BackupTest.php | 6 ++--- tests/Commands/ListCommandTest.php | 10 -------- tests/Commands/MonitorCommandTest.php | 19 +++----------- tests/Notifications/EventHandlerTest.php | 4 +-- tests/TestCase.php | 4 +-- 23 files changed, 98 insertions(+), 104 deletions(-) create mode 100644 src/Config/Config.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c56c638a..80e7aa86 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -10,16 +10,6 @@ parameters: count: 1 path: src/BackupDestination/BackupCollection.php - - - message: "#^Unable to resolve the template type TKey in call to function collect$#" - count: 1 - path: src/BackupDestination/BackupDestinationFactory.php - - - - message: "#^Unable to resolve the template type TValue in call to function collect$#" - count: 1 - path: src/BackupDestination/BackupDestinationFactory.php - - message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:map\\(\\) expects callable\\(int, int\\)\\: string, Closure\\(string\\)\\: non\\-falsy\\-string given\\.$#" count: 1 @@ -54,3 +44,8 @@ parameters: message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\\\:\\:each\\(\\) expects callable\\(Spatie\\\\Backup\\\\BackupDestination\\\\Backup, int\\)\\: mixed, Closure\\(Spatie\\\\Backup\\\\BackupDestination\\\\BackupCollection\\)\\: void given\\.$#" count: 1 path: src/Tasks/Cleanup/Strategies/DefaultStrategy.php + + - + message: "#^Parameter \\#1 \\$callback of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),Spatie\\\\Backup\\\\Config\\\\MonitoredBackupConfig\\>\\:\\:flatMap\\(\\) expects callable\\(Spatie\\\\Backup\\\\Config\\\\MonitoredBackupConfig, int\\|string\\)\\: \\(array\\\\|Illuminate\\\\Support\\\\Collection\\\\), Closure\\(array\\)\\: Illuminate\\\\Support\\\\Collection\\ given\\.$#" + count: 1 + path: src/Tasks/Monitor/BackupDestinationStatusFactory.php diff --git a/src/BackupDestination/BackupDestinationFactory.php b/src/BackupDestination/BackupDestinationFactory.php index 6beab64e..af48085b 100644 --- a/src/BackupDestination/BackupDestinationFactory.php +++ b/src/BackupDestination/BackupDestinationFactory.php @@ -3,16 +3,16 @@ namespace Spatie\Backup\BackupDestination; use Illuminate\Support\Collection; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; class BackupDestinationFactory { /** * @return Collection */ - public static function createFromArray(BackupConfig $config): Collection + public static function createFromArray(Config $config): Collection { - return collect($config->destination->disks) - ->map(fn (string $filesystemName) => BackupDestination::create($filesystemName, $config->name)); + return collect($config->backup->destination->disks) + ->map(fn (string $filesystemName) => BackupDestination::create($filesystemName, $config->backup->name)); } } diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index e7c98031..bc815d16 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -9,7 +9,7 @@ use Spatie\Backup\Commands\CleanupCommand; use Spatie\Backup\Commands\ListCommand; use Spatie\Backup\Commands\MonitorCommand; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\BackupZipWasCreated; use Spatie\Backup\Helpers\ConsoleOutput; use Spatie\Backup\Listeners\EncryptBackupArchive; @@ -52,8 +52,8 @@ public function packageRegistered(): void $this->registerDiscordChannel(); - $this->app->singleton(BackupConfig::class, function () { - return BackupConfig::fromArray(config('backup.backup')); + $this->app->singleton(Config::class, function () { + return Config::fromArray(config('backup')); }); } diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index ebaca067..3ddeb225 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -4,7 +4,7 @@ use Exception; use Illuminate\Contracts\Console\Isolatable; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\BackupHasFailed; use Spatie\Backup\Exceptions\BackupFailed; use Spatie\Backup\Exceptions\InvalidCommand; @@ -19,7 +19,7 @@ class BackupCommand extends BaseCommand implements Isolatable protected $description = 'Run the backup.'; - public function __construct(protected BackupConfig $config) + public function __construct(protected Config $config) { parent::__construct(); } diff --git a/src/Commands/CleanupCommand.php b/src/Commands/CleanupCommand.php index 83393d4a..2730f814 100644 --- a/src/Commands/CleanupCommand.php +++ b/src/Commands/CleanupCommand.php @@ -5,7 +5,7 @@ use Exception; use Illuminate\Contracts\Console\Isolatable; use Spatie\Backup\BackupDestination\BackupDestinationFactory; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\CleanupHasFailed; use Spatie\Backup\Tasks\Cleanup\CleanupJob; use Spatie\Backup\Tasks\Cleanup\CleanupStrategy; @@ -23,7 +23,7 @@ class CleanupCommand extends BaseCommand implements Isolatable public function __construct( protected CleanupStrategy $strategy, - protected BackupConfig $config, + protected Config $config, ) { parent::__construct(); } @@ -37,8 +37,6 @@ public function handle(): int $this->setTries('cleanup'); try { - $config = config('backup'); - $backupDestinations = BackupDestinationFactory::createFromArray($this->config); $cleanupJob = new CleanupJob($backupDestinations, $this->strategy, $disableNotifications); diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index 94d961e3..ddb089ad 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -4,6 +4,7 @@ use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\Backup; +use Spatie\Backup\Config\Config; use Spatie\Backup\Helpers\Format; use Spatie\Backup\Helpers\RightAlignedTableStyle; use Spatie\Backup\Tasks\Monitor\BackupDestinationStatus; @@ -17,13 +18,14 @@ class ListCommand extends BaseCommand /** @var string */ protected $description = 'Display a list of all backups.'; - public function handle(): int + public function __construct(protected Config $config) { - if (config()->has('backup.monitorBackups')) { - $this->warn('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); - } + parent::__construct(); + } - $statuses = BackupDestinationStatusFactory::createForMonitorConfig(config('backup.monitor_backups')); + public function handle(): int + { + $statuses = BackupDestinationStatusFactory::createForMonitorConfig($this->config->monitoredBackups); $this->displayOverview($statuses)->displayFailures($statuses); diff --git a/src/Commands/MonitorCommand.php b/src/Commands/MonitorCommand.php index c9a1a9f6..d0adb34a 100644 --- a/src/Commands/MonitorCommand.php +++ b/src/Commands/MonitorCommand.php @@ -3,7 +3,7 @@ namespace Spatie\Backup\Commands; use Illuminate\Contracts\Console\Isolatable; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\HealthyBackupWasFound; use Spatie\Backup\Events\UnhealthyBackupWasFound; use Spatie\Backup\Tasks\Monitor\BackupDestinationStatusFactory; @@ -16,20 +16,16 @@ class MonitorCommand extends BaseCommand implements Isolatable /** @var string */ protected $description = 'Monitor the health of all backups.'; - public function __construct(protected BackupConfig $config) + public function __construct(protected Config $config) { parent::__construct(); } public function handle(): int { - if (config()->has('backup.monitorBackups')) { - $this->warn('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); - } - $hasError = false; - $statuses = BackupDestinationStatusFactory::createForMonitorConfig(config('backup.monitor_backups')); + $statuses = BackupDestinationStatusFactory::createForMonitorConfig($this->config->monitoredBackups); foreach ($statuses as $backupDestinationStatus) { $backupName = $backupDestinationStatus->backupDestination()->backupName(); diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index 542a0773..200ce243 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -30,6 +30,8 @@ protected function __construct( /** @param array $data */ public static function fromArray(array $data): self { + $monitoredBackups = $data['monitored_backups'] ?? $data['monitorBackups'] ?? null; + return new self( name: $data['name'], source: SourceConfig::fromArray($data['source']), @@ -44,7 +46,7 @@ public static function fromArray(array $data): self tries: $data['tries'], retryDelay: $data['retry_delay'], notifications: isset($data['notifications']) ? NotificationsConfig::fromArray($data['notifications']) : null, - monitoredBackups: isset($data['monitored_backups']) ? MonitoredBackupsConfig::fromArray($data['monitored_backups']) : null, + monitoredBackups: $monitoredBackups ? MonitoredBackupsConfig::fromArray($monitoredBackups) : null, ); } } diff --git a/src/Config/CleanupConfig.php b/src/Config/CleanupConfig.php index 59366a92..c296ed1e 100644 --- a/src/Config/CleanupConfig.php +++ b/src/Config/CleanupConfig.php @@ -2,9 +2,10 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Support\Data; use Spatie\Backup\Tasks\Cleanup\CleanupStrategy; -class CleanupConfig +class CleanupConfig extends Data { /** * @param class-string $strategy @@ -23,9 +24,9 @@ public static function fromArray(array $data): self { return new self( strategy: $data['strategy'], - defaultStrategy: StrategyConfig::fromArray($data['defaultStrategy']), + defaultStrategy: StrategyConfig::fromArray($data['default_strategy']), tries: $data['tries'], - retryDelay: $data['retryDelay'], + retryDelay: $data['retry_delay'], ); } } diff --git a/src/Config/Config.php b/src/Config/Config.php new file mode 100644 index 00000000..4c16f39b --- /dev/null +++ b/src/Config/Config.php @@ -0,0 +1,25 @@ + $data */ + public static function fromArray(array $data): self + { + return new self( + backup: BackupConfig::fromArray($data['backup']), + monitoredBackups: MonitoredBackupsConfig::fromArray($data['monitor_backups']), + cleanup: CleanupConfig::fromArray($data['cleanup']), + ); + } +} diff --git a/src/Config/MonitoredBackupConfig.php b/src/Config/MonitoredBackupConfig.php index 1147447c..75fa3cf9 100644 --- a/src/Config/MonitoredBackupConfig.php +++ b/src/Config/MonitoredBackupConfig.php @@ -2,13 +2,14 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Support\Data; use Spatie\Backup\Tasks\Monitor\HealthCheck; -class MonitoredBackupConfig +class MonitoredBackupConfig extends Data { /** * @param array $disks - * @param array $healthChecks + * @param array, integer> $healthChecks */ protected function __construct( public string $name, diff --git a/src/Config/MonitoredBackupsConfig.php b/src/Config/MonitoredBackupsConfig.php index 7e0b2f6c..2a24f0af 100644 --- a/src/Config/MonitoredBackupsConfig.php +++ b/src/Config/MonitoredBackupsConfig.php @@ -2,7 +2,9 @@ namespace Spatie\Backup\Config; -class MonitoredBackupsConfig +use Spatie\Backup\Support\Data; + +class MonitoredBackupsConfig extends Data { /** * @param array $monitorBackups diff --git a/src/Config/NotificationDiscordConfig.php b/src/Config/NotificationDiscordConfig.php index 73c71d3b..dc359a0b 100644 --- a/src/Config/NotificationDiscordConfig.php +++ b/src/Config/NotificationDiscordConfig.php @@ -2,7 +2,9 @@ namespace Spatie\Backup\Config; -class NotificationDiscordConfig +use Spatie\Backup\Support\Data; + +class NotificationDiscordConfig extends Data { protected function __construct( public string $webhookUrl, diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index 4b288787..237963c5 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -3,8 +3,9 @@ namespace Spatie\Backup\Config; use Spatie\Backup\Exceptions\InvalidConfig; +use Spatie\Backup\Support\Data; -class NotificationMailConfig +class NotificationMailConfig extends Data { /** * @param array{address: string, name: string} $from diff --git a/src/Config/StrategyConfig.php b/src/Config/StrategyConfig.php index 543bf205..2c25e6d0 100644 --- a/src/Config/StrategyConfig.php +++ b/src/Config/StrategyConfig.php @@ -2,7 +2,9 @@ namespace Spatie\Backup\Config; -class StrategyConfig +use Spatie\Backup\Support\Data; + +class StrategyConfig extends Data { protected function __construct( public int $keepAllBackupsForDays, @@ -20,9 +22,9 @@ public static function fromArray(array $data): self return new self( keepAllBackupsForDays: $data['keep_all_backups_for_days'], keepDailyBackupsForDays: $data['keep_daily_backups_for_days'], - keepWeeklyBackupsForWeeks: $data['keep_weekly_backups_for_days'], - keepMonthlyBackupsForMonths: $data['keep_monthly_backups_for_days'], - keepYearlyBackupsForYears: $data['keep_yearly_backups_for_days'], + keepWeeklyBackupsForWeeks: $data['keep_weekly_backups_for_weeks'], + keepMonthlyBackupsForMonths: $data['keep_monthly_backups_for_months'], + keepYearlyBackupsForYears: $data['keep_yearly_backups_for_years'], deleteOldestBackupsWhenUsingMoreMegabytesThan: $data['delete_oldest_backups_when_using_more_megabytes_than'], ); } diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index ae03920c..d38141d1 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -8,7 +8,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\BackupManifestWasCreated; use Spatie\Backup\Events\BackupWasSuccessful; use Spatie\Backup\Events\BackupZipWasCreated; @@ -42,7 +42,7 @@ class BackupJob protected bool $signals = true; - public function __construct(protected BackupConfig $config) + public function __construct(protected Config $config) { $this ->dontBackupFilesystem() @@ -279,8 +279,7 @@ protected function dumpDatabases(): array $fileName .= '.'.$dbDumper->getCompressorExtension(); } - ray($this->config->databaseDumpCompressor); - if ($compressor = $this->config->databaseDumpCompressor) { + if ($compressor = $this->config->backup->databaseDumpCompressor) { $dbDumper->useCompressor(new $compressor()); $fileName .= '.'.$dbDumper->getCompressorExtension(); } diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index a77919ae..19b387f6 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -5,17 +5,17 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestinationFactory; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Config\SourceFilesConfig; use Spatie\DbDumper\DbDumper; class BackupJobFactory { - public static function createFromConfig(BackupConfig $config): BackupJob + public static function createFromConfig(Config $config): BackupJob { return (new BackupJob($config)) - ->setFileSelection(static::createFileSelection($config->source->files)) - ->setDbDumpers(static::createDbDumpers($config->source->databases)) + ->setFileSelection(static::createFileSelection($config->backup->source->files)) + ->setDbDumpers(static::createDbDumpers($config->backup->source->databases)) ->setBackupDestinations(BackupDestinationFactory::createFromArray($config)); } diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index eb2ad233..f58cf962 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -5,24 +5,24 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; +use Spatie\Backup\Config\MonitoredBackupsConfig; class BackupDestinationStatusFactory { /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfiguration * @return Collection */ - public static function createForMonitorConfig(array $monitorConfiguration): Collection + public static function createForMonitorConfig(MonitoredBackupsConfig $monitorConfiguration): Collection { - return collect($monitorConfiguration) + return collect($monitorConfiguration->monitorBackups) ->flatMap(fn (array $monitorProperties) => self::createForSingleMonitor($monitorProperties)) ->sortBy(fn (BackupDestinationStatus $backupDestinationStatus) => $backupDestinationStatus->backupDestination()->backupName().'-'. $backupDestinationStatus->backupDestination()->diskName()); } /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig * @return Collection */ public static function createForSingleMonitor(array $monitorConfig): Collection @@ -36,21 +36,12 @@ public static function createForSingleMonitor(array $monitorConfig): Collection } /** - * @param array{name: string, disks: array, health_checks: array>} $monitorConfig + * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig * @return array */ protected static function buildHealthChecks(array $monitorConfig): array { - ray(collect($monitorConfig['health_checks']) - ->map(function ($options, $class) { - if (is_int($class)) { - $class = $options; - $options = []; - } - - return static::buildHealthCheck($class, $options); - })->toArray()); - return collect($monitorConfig['health_checks']) + return collect($monitorConfig['healthChecks']) ->map(function ($options, $class) { if (is_int($class)) { $class = $options; diff --git a/tests/BackupDestination/BackupTest.php b/tests/BackupDestination/BackupTest.php index a5c1b5a5..2b48c1c5 100644 --- a/tests/BackupDestination/BackupTest.php +++ b/tests/BackupDestination/BackupTest.php @@ -6,7 +6,7 @@ use Mockery as m; use Spatie\Backup\BackupDestination\Backup; use Spatie\Backup\BackupDestination\BackupDestinationFactory; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Exceptions\InvalidBackupFile; it('can determine the disk of the backup', function () { @@ -93,7 +93,7 @@ 's3-test-backup', ]); - $config = BackupConfig::fromArray(config('backup.backup')); + $config = Config::fromArray(config('backup')); $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); @@ -110,7 +110,7 @@ 'local', ]); - $config = BackupConfig::fromArray(config('backup.backup')); + $config = Config::fromArray(config('backup')); $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); diff --git a/tests/Commands/ListCommandTest.php b/tests/Commands/ListCommandTest.php index e3c12903..a5b67f6e 100644 --- a/tests/Commands/ListCommandTest.php +++ b/tests/Commands/ListCommandTest.php @@ -7,13 +7,3 @@ $this->artisan('backup:list')->assertExitCode(0); }); - -it('warns_the_user_about_the_old_style_config_keys', function () { - $this->artisan('backup:list') - ->assertSuccessful(); - - config(['backup.monitorBackups' => config('backup.monitor_backups')]); - - $this->artisan('backup:list') - ->expectsOutput('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); -}); diff --git a/tests/Commands/MonitorCommandTest.php b/tests/Commands/MonitorCommandTest.php index 79277a05..f768f0dc 100644 --- a/tests/Commands/MonitorCommandTest.php +++ b/tests/Commands/MonitorCommandTest.php @@ -2,19 +2,6 @@ namespace Spatie\Backup\Tests\Commands; -use Spatie\Backup\Tests\TestCase; - -class MonitorCommandTest extends TestCase -{ - /** @test */ - public function it_warns_the_user_about_the_old_style_config_keys(): void - { - $this->artisan('backup:monitor') - ->assertSuccessful(); - - config(['backup.monitorBackups' => config('backup.monitor_backups')]); - - $this->artisan('backup:monitor') - ->expectsOutput('Warning! Your config file still uses the old monitorBackups key. Update it to monitor_backups.'); - } -} +it('can run the monitor command', function () { + $this->artisan('backup:monitor')->assertExitCode(0); +}); diff --git a/tests/Notifications/EventHandlerTest.php b/tests/Notifications/EventHandlerTest.php index f3fa87b2..bcfb1aee 100644 --- a/tests/Notifications/EventHandlerTest.php +++ b/tests/Notifications/EventHandlerTest.php @@ -2,7 +2,7 @@ use Illuminate\Support\Facades\Notification; use Spatie\Backup\BackupDestination\BackupDestinationFactory; -use Spatie\Backup\Config\BackupConfig; +use Spatie\Backup\Config\Config; use Spatie\Backup\Events\BackupHasFailed; use Spatie\Backup\Notifications\Notifiable; use Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification; @@ -54,7 +54,7 @@ function fireBackupHasFailedEvent(): void { $exception = new Exception('Dummy exception'); - $config = BackupConfig::fromArray(config('backup.backup')); + $config = Config::fromArray(config('backup')); $backupDestination = BackupDestinationFactory::createFromArray($config)->first(); diff --git a/tests/TestCase.php b/tests/TestCase.php index 28b699ef..d7e5f45b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -55,7 +55,7 @@ protected function getEnvironmentSetUp($app) Storage::fake('secondLocal'); } - protected function setUpDatabase(Application $app) + protected function setUpDatabase(Application $app): void { touch($this->getTempDirectory().'/database.sqlite'); @@ -114,7 +114,7 @@ protected function fileExistsInZip(string $diskName, string $zipPath, string $fi return false; } - protected function assertExactPathExistsInZip(string $diskName, string $zipPath, string $fullPath) + protected function assertExactPathExistsInZip(string $diskName, string $zipPath, string $fullPath): void { $this->assertTrue( $this->exactPathExistsInZip($diskName, $zipPath, $fullPath), From b8b5e50a0d1ab3bb319050c86da1fc587dfe58cc Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 7 Jun 2024 14:12:10 +0000 Subject: [PATCH 15/33] Fix styling --- src/Commands/CleanupCommand.php | 2 +- src/Commands/ListCommand.php | 4 ++-- src/Config/BackupConfig.php | 2 +- src/Config/CleanupConfig.php | 4 ++-- src/Config/Config.php | 4 ++-- src/Config/DestinationConfig.php | 4 ++-- src/Config/MonitoredBackupConfig.php | 4 ++-- src/Config/MonitoredBackupsConfig.php | 4 ++-- src/Config/NotificationMailConfig.php | 5 +++-- src/Config/NotificationsConfig.php | 10 +++++----- src/Config/SourceConfig.php | 2 +- src/Config/SourceFilesConfig.php | 4 ++-- src/Tasks/Backup/BackupJob.php | 2 +- src/Tasks/Backup/BackupJobFactory.php | 3 +-- src/Tasks/Backup/FileSelection.php | 2 +- src/Tasks/Backup/Manifest.php | 2 +- src/Tasks/Monitor/BackupDestinationStatusFactory.php | 6 ++---- 17 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/Commands/CleanupCommand.php b/src/Commands/CleanupCommand.php index 2730f814..be4b5332 100644 --- a/src/Commands/CleanupCommand.php +++ b/src/Commands/CleanupCommand.php @@ -23,7 +23,7 @@ class CleanupCommand extends BaseCommand implements Isolatable public function __construct( protected CleanupStrategy $strategy, - protected Config $config, + protected Config $config, ) { parent::__construct(); } diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index ddb089ad..ac024e50 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -33,7 +33,7 @@ public function handle(): int } /** - * @param Collection $backupDestinationStatuses + * @param Collection $backupDestinationStatuses */ protected function displayOverview(Collection $backupDestinationStatuses): static { @@ -51,7 +51,7 @@ protected function displayOverview(Collection $backupDestinationStatuses): stati return $this; } - /** @return array{0: string, 1: string, 2: string, disk: string, amount: integer, newest: string, usedStorage: string} */ + /** @return array{0: string, 1: string, 2: string, disk: string, amount: int, newest: string, usedStorage: string} */ public function convertToRow(BackupDestinationStatus $backupDestinationStatus): array { $destination = $backupDestinationStatus->backupDestination(); diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index 200ce243..3edf832c 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -7,7 +7,7 @@ class BackupConfig extends Data { /** - * @param positive-int $tries + * @param positive-int $tries */ protected function __construct( public string $name, diff --git a/src/Config/CleanupConfig.php b/src/Config/CleanupConfig.php index c296ed1e..6c1c0b87 100644 --- a/src/Config/CleanupConfig.php +++ b/src/Config/CleanupConfig.php @@ -8,8 +8,8 @@ class CleanupConfig extends Data { /** - * @param class-string $strategy - * @param positive-int $tries + * @param class-string $strategy + * @param positive-int $tries */ protected function __construct( public string $strategy, diff --git a/src/Config/Config.php b/src/Config/Config.php index 4c16f39b..8e5e7842 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -7,9 +7,9 @@ class Config extends Data { protected function __construct( - public BackupConfig $backup, + public BackupConfig $backup, public MonitoredBackupsConfig $monitoredBackups, - public CleanupConfig $cleanup, + public CleanupConfig $cleanup, ) { } diff --git a/src/Config/DestinationConfig.php b/src/Config/DestinationConfig.php index 648fc3fb..75484bbc 100644 --- a/src/Config/DestinationConfig.php +++ b/src/Config/DestinationConfig.php @@ -7,8 +7,8 @@ class DestinationConfig extends Data { /** - * @param int<0,9> $compressionLevel - * @param array $disks + * @param int<0,9> $compressionLevel + * @param array $disks */ protected function __construct( public int $compressionMethod, diff --git a/src/Config/MonitoredBackupConfig.php b/src/Config/MonitoredBackupConfig.php index 75fa3cf9..c3668a74 100644 --- a/src/Config/MonitoredBackupConfig.php +++ b/src/Config/MonitoredBackupConfig.php @@ -8,8 +8,8 @@ class MonitoredBackupConfig extends Data { /** - * @param array $disks - * @param array, integer> $healthChecks + * @param array $disks + * @param array, int> $healthChecks */ protected function __construct( public string $name, diff --git a/src/Config/MonitoredBackupsConfig.php b/src/Config/MonitoredBackupsConfig.php index 2a24f0af..7d2ae1fd 100644 --- a/src/Config/MonitoredBackupsConfig.php +++ b/src/Config/MonitoredBackupsConfig.php @@ -7,9 +7,9 @@ class MonitoredBackupsConfig extends Data { /** - * @param array $monitorBackups + * @param array $monitorBackups */ - protected function __construct ( + protected function __construct( public array $monitorBackups, ) { } diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index 237963c5..36fb9f7e 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -8,7 +8,7 @@ class NotificationMailConfig extends Data { /** - * @param array{address: string, name: string} $from + * @param array{address: string, name: string} $from */ protected function __construct( public string $to, @@ -17,7 +17,8 @@ protected function __construct( } /** - * @param array $data + * @param array $data + * * @throws InvalidConfig */ public static function fromArray(array $data): self diff --git a/src/Config/NotificationsConfig.php b/src/Config/NotificationsConfig.php index 9b722ec4..accfad95 100644 --- a/src/Config/NotificationsConfig.php +++ b/src/Config/NotificationsConfig.php @@ -9,14 +9,14 @@ class NotificationsConfig extends Data { /** - * @param array, array> $notifications - * @param class-string $notifiable + * @param array, array> $notifications + * @param class-string $notifiable */ protected function __construct( - public array $notifications, - public string $notifiable, + public array $notifications, + public string $notifiable, public NotificationMailConfig $mail, - public NotificationSlackConfig $slack, + public NotificationSlackConfig $slack, public NotificationDiscordConfig $discord, ) { } diff --git a/src/Config/SourceConfig.php b/src/Config/SourceConfig.php index 1cc7ead4..2bc9ba6d 100644 --- a/src/Config/SourceConfig.php +++ b/src/Config/SourceConfig.php @@ -7,7 +7,7 @@ class SourceConfig extends Data { /** - * @param array $databases + * @param array $databases */ protected function __construct( public SourceFilesConfig $files, diff --git a/src/Config/SourceFilesConfig.php b/src/Config/SourceFilesConfig.php index af36b32c..1fa2b5cc 100644 --- a/src/Config/SourceFilesConfig.php +++ b/src/Config/SourceFilesConfig.php @@ -7,8 +7,8 @@ class SourceFilesConfig extends Data { /** - * @param array $include - * @param array $exclude + * @param array $include + * @param array $exclude */ protected function __construct( public array $include, diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index d38141d1..933cc8f7 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -105,7 +105,7 @@ public function setFileSelection(FileSelection $fileSelection): self } /** - * @param Collection $dbDumpers + * @param Collection $dbDumpers * @return $this */ public function setDbDumpers(Collection $dbDumpers): self diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index 19b387f6..67e98355 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -2,7 +2,6 @@ namespace Spatie\Backup\Tasks\Backup; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestinationFactory; use Spatie\Backup\Config\Config; @@ -28,7 +27,7 @@ protected static function createFileSelection(SourceFilesConfig $sourceFiles): F } /** - * @param array $dbConnectionNames + * @param array $dbConnectionNames * @return Collection */ protected static function createDbDumpers(array $dbConnectionNames): Collection diff --git a/src/Tasks/Backup/FileSelection.php b/src/Tasks/Backup/FileSelection.php index 45364662..9daae78b 100644 --- a/src/Tasks/Backup/FileSelection.php +++ b/src/Tasks/Backup/FileSelection.php @@ -130,7 +130,7 @@ protected function shouldExclude(string $path): bool } /** - * @param string|array $paths + * @param string|array $paths */ protected function sanitize(string|array $paths): Collection { diff --git a/src/Tasks/Backup/Manifest.php b/src/Tasks/Backup/Manifest.php index ab0efa2d..538dc4a8 100644 --- a/src/Tasks/Backup/Manifest.php +++ b/src/Tasks/Backup/Manifest.php @@ -24,7 +24,7 @@ public function path(): string } /** - * @param Generator|string|array $filePaths + * @param Generator|string|array $filePaths */ public function addFiles(array|string|Generator $filePaths): self { diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index f58cf962..46e47cc0 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -2,14 +2,12 @@ namespace Spatie\Backup\Tasks\Monitor; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; use Spatie\Backup\Config\MonitoredBackupsConfig; class BackupDestinationStatusFactory { - /** * @return Collection */ @@ -22,7 +20,7 @@ public static function createForMonitorConfig(MonitoredBackupsConfig $monitorCon } /** - * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig + * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig * @return Collection */ public static function createForSingleMonitor(array $monitorConfig): Collection @@ -36,7 +34,7 @@ public static function createForSingleMonitor(array $monitorConfig): Collection } /** - * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig + * @param array{name: string, disks: array, healthChecks: array>} $monitorConfig * @return array */ protected static function buildHealthChecks(array $monitorConfig): array From 0e0c095bda7a23bde22c3f876291d249bfd2e834 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:37:48 +0200 Subject: [PATCH 16/33] refactor to Config class --- composer.json | 2 +- src/BackupDestination/BackupDestination.php | 1 + src/Tasks/Backup/Zip.php | 29 +++++++++++++-------- src/Traits/Retryable.php | 12 +++++++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index d41ff2e0..11d9c522 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ } ], "require": { - "php": "^8.1", + "php": "^8.2", "ext-zip": "^1.14.0", "illuminate/console": "^10.10.0|^11.0", "illuminate/contracts": "^10.10.0|^11.0", diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index 3ef69882..dd5c89eb 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -6,6 +6,7 @@ use Exception; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; +use Spatie\Backup\Config\Config; use Spatie\Backup\Exceptions\InvalidBackupDestination; class BackupDestination diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index 83b0010f..3fd66167 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -3,6 +3,7 @@ namespace Spatie\Backup\Tasks\Backup; use Illuminate\Support\Str; +use Spatie\Backup\Config\Config; use Spatie\Backup\Helpers\Format; use ZipArchive; @@ -12,10 +13,23 @@ class Zip protected int $fileCount = 0; + protected Config $config; + + public function __construct(protected string $pathToZip) + { + $this->zipFile = new ZipArchive(); + $this->config = app(Config::class); + + $this->open(); + } + public static function createForManifest(Manifest $manifest, string $pathToZip): self { - $relativePath = config('backup.backup.source.files.relative_path') ? - rtrim((string) config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR : false; + $config = app(Config::class); + + $relativePath = $config->backup->source->files->relativePath + ? rtrim($config->backup->source->files->relativePath, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR + : false; $zip = new static($pathToZip); @@ -47,13 +61,6 @@ protected static function determineNameOfFileInZip(string $pathToFile, string $p return $pathToFile; } - public function __construct(protected string $pathToZip) - { - $this->zipFile = new ZipArchive(); - - $this->open(); - } - public function path(): string { return $this->pathToZip; @@ -93,8 +100,8 @@ public function add(string|iterable $files, ?string $nameInZip = null): self $files = [$files]; } - $compressionMethod = config('backup.backup.destination.compression_method', null); - $compressionLevel = config('backup.backup.destination.compression_level', 9); + $compressionMethod = $this->config->backup->destination->compressionMethod; + $compressionLevel = $this->config->backup->destination->compressionLevel; foreach ($files as $file) { if (is_dir($file)) { diff --git a/src/Traits/Retryable.php b/src/Traits/Retryable.php index bae1cf1a..f255a983 100644 --- a/src/Traits/Retryable.php +++ b/src/Traits/Retryable.php @@ -37,11 +37,19 @@ protected function setTries(string $type): void return; } - $this->tries = (int) config('backup.'.$type.'.tries', 1); + $this->tries = match ($type) { + 'backup' => $this->config->backup->tries, + 'cleanup' => $this->config->cleanup->tries, + default => 1, + }; } protected function getRetryDelay(string $type): int { - return (int) config('backup.'.$type.'.retry_delay', 0); + return match ($type) { + 'backup' => $this->config->backup->retryDelay, + 'cleanup' => $this->config->cleanup->retryDelay, + default => 0, + }; } } From e67fdc5bfee96f14114389d404772f520fccec37 Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 7 Jun 2024 14:38:14 +0000 Subject: [PATCH 17/33] Fix styling --- src/BackupDestination/BackupDestination.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index dd5c89eb..3ef69882 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -6,7 +6,6 @@ use Exception; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; -use Spatie\Backup\Config\Config; use Spatie\Backup\Exceptions\InvalidBackupDestination; class BackupDestination From 556e526833e39fd42545f3ccafa2266c961b19f9 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 23:39:46 +0200 Subject: [PATCH 18/33] use more config files --- src/BackupDestination/BackupDestination.php | 1 + src/BackupServiceProvider.php | 2 +- src/Config/Config.php | 8 ++++++++ tests/Commands/BackupCommandTest.php | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index 3ef69882..dd5c89eb 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -6,6 +6,7 @@ use Exception; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; +use Spatie\Backup\Config\Config; use Spatie\Backup\Exceptions\InvalidBackupDestination; class BackupDestination diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index bc815d16..bf1559e3 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -52,7 +52,7 @@ public function packageRegistered(): void $this->registerDiscordChannel(); - $this->app->singleton(Config::class, function () { + $this->app->scoped(Config::class, function () { return Config::fromArray(config('backup')); }); } diff --git a/src/Config/Config.php b/src/Config/Config.php index 8e5e7842..b56e3754 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -13,6 +13,14 @@ protected function __construct( ) { } + /** @internal used for testing */ + public static function rebind(): void + { + app()->scoped(Config::class, function () { + return self::fromArray(config('backup')); + }); + } + /** @param array $data */ public static function fromArray(array $data): self { diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php index 3b883325..0c59d72b 100644 --- a/tests/Commands/BackupCommandTest.php +++ b/tests/Commands/BackupCommandTest.php @@ -397,6 +397,8 @@ config()->set('backup.backup.destination.compression_method', ZipArchive::CM_STORE); config()->set('backup.backup.destination.compression_level', 0); + \Spatie\Backup\Config\Config::rebind(); + $this->artisan('backup:run --only-db')->assertExitCode(0); $zip = new ZipArchive(); @@ -411,6 +413,8 @@ config()->set('backup.backup.destination.compression_method', ZipArchive::CM_DEFLATE); config()->set('backup.backup.destination.compression_level', 2); + \Spatie\Backup\Config\Config::rebind(); + $this->artisan('backup:run --only-db')->assertExitCode(0); $zip = new ZipArchive(); From d7b719c96b9ad5feceed89da00f116e9431b5739 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:23:20 +0200 Subject: [PATCH 19/33] refactor some more config --- src/Config/BackupConfig.php | 6 ++---- src/Config/Config.php | 2 ++ src/Config/NotificationDiscordConfig.php | 4 ++-- src/Config/NotificationMailConfig.php | 7 ++++--- src/Config/NotificationsConfig.php | 6 +++--- src/Notifications/BaseNotification.php | 8 +++++++- .../UnhealthyBackupWasFoundNotification.php | 11 +++++++---- src/Tasks/Backup/BackupJob.php | 12 +++++++----- 8 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index 3edf832c..dbd53032 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -17,12 +17,11 @@ protected function __construct( public string $databaseDumpFilenameBase, public string $databaseDumpFileExtension, public DestinationConfig $destination, - public string $temporaryDirectory, + public ?string $temporaryDirectory, public ?string $password, public string $encryption, public int $tries, public int $retryDelay, - public ?NotificationsConfig $notifications, public ?MonitoredBackupsConfig $monitoredBackups, ) { } @@ -40,12 +39,11 @@ public static function fromArray(array $data): self databaseDumpFilenameBase: $data['database_dump_filename_base'], databaseDumpFileExtension: $data['database_dump_file_extension'], destination: DestinationConfig::fromArray($data['destination']), - temporaryDirectory: $data['temporary_directory'], + temporaryDirectory: $data['temporary_directory'] ?? null, password: $data['password'], encryption: $data['encryption'], tries: $data['tries'], retryDelay: $data['retry_delay'], - notifications: isset($data['notifications']) ? NotificationsConfig::fromArray($data['notifications']) : null, monitoredBackups: $monitoredBackups ? MonitoredBackupsConfig::fromArray($monitoredBackups) : null, ); } diff --git a/src/Config/Config.php b/src/Config/Config.php index b56e3754..b3667476 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -8,6 +8,7 @@ class Config extends Data { protected function __construct( public BackupConfig $backup, + public NotificationsConfig $notifications, public MonitoredBackupsConfig $monitoredBackups, public CleanupConfig $cleanup, ) { @@ -26,6 +27,7 @@ public static function fromArray(array $data): self { return new self( backup: BackupConfig::fromArray($data['backup']), + notifications: NotificationsConfig::fromArray($data['notifications']), monitoredBackups: MonitoredBackupsConfig::fromArray($data['monitor_backups']), cleanup: CleanupConfig::fromArray($data['cleanup']), ); diff --git a/src/Config/NotificationDiscordConfig.php b/src/Config/NotificationDiscordConfig.php index dc359a0b..46ce63f9 100644 --- a/src/Config/NotificationDiscordConfig.php +++ b/src/Config/NotificationDiscordConfig.php @@ -8,7 +8,7 @@ class NotificationDiscordConfig extends Data { protected function __construct( public string $webhookUrl, - public string $channel, + public string $username, public string $avatar_url, ) { } @@ -18,7 +18,7 @@ public static function fromArray(array $data): self { return new self( webhookUrl: $data['webhook_url'], - channel: $data['channel'], + username: $data['username'], avatar_url: $data['avatar_url'], ); } diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index 36fb9f7e..5918e2bf 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -8,7 +8,7 @@ class NotificationMailConfig extends Data { /** - * @param array{address: string, name: string} $from + * @param array{address: string|null, name: string|null} $from */ protected function __construct( public string $to, @@ -23,11 +23,12 @@ protected function __construct( */ public static function fromArray(array $data): self { - if (filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { + if (! filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { throw InvalidConfig::invalidEmail($data['to']); } - if (filter_var($data['from']['address'], FILTER_VALIDATE_EMAIL)) { + if ($data['from']['address'] + && ! filter_var($data['from']['address'], FILTER_VALIDATE_EMAIL)) { throw InvalidConfig::invalidEmail($data['from']['address']); } diff --git a/src/Config/NotificationsConfig.php b/src/Config/NotificationsConfig.php index accfad95..b8594a62 100644 --- a/src/Config/NotificationsConfig.php +++ b/src/Config/NotificationsConfig.php @@ -27,9 +27,9 @@ public static function fromArray(array $data): self return new self( notifications: $data['notifications'], notifiable: $data['notifiable'], - mail: $data['mail'], - slack: $data['slack'], - discord: $data['discord'], + mail: NotificationMailConfig::fromArray($data['mail']), + slack: NotificationSlackConfig::fromArray($data['slack']), + discord: NotificationDiscordConfig::fromArray($data['discord']), ); } } diff --git a/src/Notifications/BaseNotification.php b/src/Notifications/BaseNotification.php index d91d75e4..77e0dfbc 100644 --- a/src/Notifications/BaseNotification.php +++ b/src/Notifications/BaseNotification.php @@ -5,6 +5,7 @@ use Illuminate\Notifications\Notification; use Illuminate\Support\Collection; use Spatie\Backup\BackupDestination\BackupDestination; +use Spatie\Backup\Config\Config; use Spatie\Backup\Helpers\Format; abstract class BaseNotification extends Notification @@ -12,11 +13,16 @@ abstract class BaseNotification extends Notification /** @return array */ public function via(): array { - $notificationChannels = config('backup.notifications.notifications.'.static::class); + $notificationChannels = $this->config()->notifications->notifications[static::class]; return array_filter($notificationChannels); } + public function config(): Config + { + return app(Config::class); + } + public function applicationName(): string { $name = config('app.name') ?? config('app.url') ?? 'Laravel'; diff --git a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php index 8c7fab75..22808180 100644 --- a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php @@ -19,9 +19,12 @@ public function __construct( public function toMail(): MailMessage { + $address = $this->config()->notifications->mail->from['address'] ?? config('mail.from.address'); + $name = $this->config()->notifications->mail->from['name'] ?? config('mail.from.name'); + $mailMessage = (new MailMessage()) ->error() - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($address, $name) ->subject(trans('backup::notifications.unhealthy_backup_found_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.unhealthy_backup_found_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])) ->line($this->problemDescription()); @@ -44,8 +47,8 @@ public function toSlack(): SlackMessage { $slackMessage = (new SlackMessage()) ->error() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.unhealthy_backup_found_subject_title', ['application_name' => $this->applicationName(), 'problem' => $this->problemDescription()])) ->attachment(function (SlackAttachment $attachment) { $attachment->fields($this->backupDestinationProperties()->toArray()); @@ -77,7 +80,7 @@ public function toDiscord(): DiscordMessage { $discordMessage = (new DiscordMessage()) ->error() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title( trans('backup::notifications.unhealthy_backup_found_subject_title', [ 'application_name' => $this->applicationName(), diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index 933cc8f7..ad702f87 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -146,7 +146,7 @@ public function setBackupDestinations(Collection $backupDestinations): self /** @throws Exception */ public function run(): void { - $temporaryDirectoryPath = config('backup.backup.temporary_directory') ?? storage_path('app/backup-temp'); + $temporaryDirectoryPath = $this->config->backup->temporaryDirectory ?? storage_path('app/backup-temp'); $this->temporaryDirectory = (new TemporaryDirectory($temporaryDirectoryPath)) ->name('temp') @@ -230,7 +230,7 @@ protected function createZipContainingEveryFileInManifest(Manifest $manifest): s { consoleOutput()->info("Zipping {$manifest->count()} files and directories..."); - $pathToZip = $this->temporaryDirectory->path(config('backup.backup.destination.filename_prefix').$this->filename); + $pathToZip = $this->temporaryDirectory->path($this->config->backup->destination->filenamePrefix.$this->filename); $zip = Zip::createForManifest($manifest, $pathToZip); @@ -259,7 +259,7 @@ protected function dumpDatabases(): array $dbType = mb_strtolower(basename(str_replace('\\', '/', $dbDumper::class))); - if (config('backup.backup.database_dump_filename_base') === 'connection') { + if ($this->config->backup->databaseDumpFilenameBase === 'connection') { $dbName = $key; } elseif ($dbDumper instanceof Sqlite) { $dbName = $key.'-database'; @@ -268,12 +268,14 @@ protected function dumpDatabases(): array } $timeStamp = ''; - if ($timeStampFormat = config('backup.backup.database_dump_file_timestamp_format')) { + + if ($timeStampFormat = $this->config->backup->databaseDumpFileTimestampFormat) { $timeStamp = '-'.Carbon::now()->format($timeStampFormat); } $fileName = "{$dbType}-{$dbName}{$timeStamp}.{$this->getExtension($dbDumper)}"; + // @todo is this still relevant or undocumented? if (config('backup.backup.gzip_database_dump')) { $dbDumper->useCompressor(new GzipCompressor()); $fileName .= '.'.$dbDumper->getCompressorExtension(); @@ -334,7 +336,7 @@ protected function sendNotification(object|string $notification): void protected function getExtension(DbDumper $dbDumper): string { - if ($extension = config('backup.backup.database_dump_file_extension')) { + if ($extension = $this->config->backup->databaseDumpFileExtension) { return $extension; } From e8ad304ee4243ccfbe08dd52253a366110ed1670 Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Mon, 10 Jun 2024 07:24:00 +0000 Subject: [PATCH 20/33] Fix styling --- src/BackupDestination/BackupDestination.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index dd5c89eb..3ef69882 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -6,7 +6,6 @@ use Exception; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Contracts\Filesystem\Filesystem; -use Spatie\Backup\Config\Config; use Spatie\Backup\Exceptions\InvalidBackupDestination; class BackupDestination From 69fc4ded3ca645457a061fca919800e25d6c7622 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:55:27 +0200 Subject: [PATCH 21/33] refactor the Notifications --- src/Config/NotificationMailConfig.php | 15 ++++---- src/Config/NotificationMailSenderConfig.php | 34 +++++++++++++++++++ src/Exceptions/InvalidConfig.php | 5 +++ .../BackupHasFailedNotification.php | 8 ++--- .../BackupWasSuccessfulNotification.php | 8 ++--- .../CleanupHasFailedNotification.php | 8 ++--- .../CleanupWasSuccessfulNotification.php | 8 ++--- .../HealthyBackupWasFoundNotification.php | 8 ++--- .../UnhealthyBackupWasFoundNotification.php | 5 +-- 9 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 src/Config/NotificationMailSenderConfig.php diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index 5918e2bf..f0072e1b 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -7,12 +7,9 @@ class NotificationMailConfig extends Data { - /** - * @param array{address: string|null, name: string|null} $from - */ protected function __construct( public string $to, - public array $from, + public NotificationMailSenderConfig $from, ) { } @@ -24,17 +21,19 @@ protected function __construct( public static function fromArray(array $data): self { if (! filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { + throw InvalidConfig::invalidEmail($data['to']); } - if ($data['from']['address'] - && ! filter_var($data['from']['address'], FILTER_VALIDATE_EMAIL)) { - throw InvalidConfig::invalidEmail($data['from']['address']); + $address = $data['from']['address'] ?? config('mail.from.address'); + + if ($address && ! filter_var($address, FILTER_VALIDATE_EMAIL)) { + throw InvalidConfig::invalidEmail($address); } return new self( to: $data['to'], - from: $data['from'], + from: NotificationMailSenderConfig::fromArray($data['from'] ?? []), ); } } diff --git a/src/Config/NotificationMailSenderConfig.php b/src/Config/NotificationMailSenderConfig.php new file mode 100644 index 00000000..3013d9b7 --- /dev/null +++ b/src/Config/NotificationMailSenderConfig.php @@ -0,0 +1,34 @@ + $data */ + public static function fromArray(array $data): self + { + $address = $data['from']['address'] ?? config('mail.from.address'); + + if ($address === null) { + throw InvalidConfig::missingSender(); + } + + if ($address && ! filter_var($address, FILTER_VALIDATE_EMAIL)) { + throw InvalidConfig::invalidEmail($address); + } + + return new self( + address: $address, + name: $data['from']['name'] ?? config('mail.from.name'), + ); + } +} diff --git a/src/Exceptions/InvalidConfig.php b/src/Exceptions/InvalidConfig.php index 930e8bd1..70e71ad5 100644 --- a/src/Exceptions/InvalidConfig.php +++ b/src/Exceptions/InvalidConfig.php @@ -10,4 +10,9 @@ public static function invalidEmail(string $email): static { return new static("{$email} is not a valid email address."); } + + public static function missingSender(): static + { + return new static("No sender email address specified."); + } } diff --git a/src/Notifications/Notifications/BackupHasFailedNotification.php b/src/Notifications/Notifications/BackupHasFailedNotification.php index bf4cea52..5e59c50d 100644 --- a/src/Notifications/Notifications/BackupHasFailedNotification.php +++ b/src/Notifications/Notifications/BackupHasFailedNotification.php @@ -20,7 +20,7 @@ public function toMail(): MailMessage { $mailMessage = (new MailMessage()) ->error() - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.backup_failed_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.backup_failed_body', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.exception_message', ['message' => $this->event->exception->getMessage()])) @@ -35,8 +35,8 @@ public function toSlack(): SlackMessage { return (new SlackMessage()) ->error() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.backup_failed_subject', ['application_name' => $this->applicationName()])) ->attachment(function (SlackAttachment $attachment) { $attachment @@ -57,7 +57,7 @@ public function toDiscord(): DiscordMessage { return (new DiscordMessage()) ->error() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title(trans('backup::notifications.backup_failed_subject', ['application_name' => $this->applicationName()])) ->fields([ trans('backup::notifications.exception_message_title') => $this->event->exception->getMessage(), diff --git a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php index 2b21b335..3ff78c58 100644 --- a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php @@ -19,7 +19,7 @@ public function __construct( public function toMail(): MailMessage { $mailMessage = (new MailMessage()) - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.backup_successful_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.backup_successful_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])); @@ -34,8 +34,8 @@ public function toSlack(): SlackMessage { return (new SlackMessage()) ->success() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.backup_successful_subject_title')) ->attachment(function (SlackAttachment $attachment) { $attachment->fields($this->backupDestinationProperties()->toArray()); @@ -46,7 +46,7 @@ public function toDiscord(): DiscordMessage { return (new DiscordMessage()) ->success() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title(trans('backup::notifications.backup_successful_subject_title')) ->fields($this->backupDestinationProperties()->toArray()); } diff --git a/src/Notifications/Notifications/CleanupHasFailedNotification.php b/src/Notifications/Notifications/CleanupHasFailedNotification.php index 0a76876b..699c0915 100644 --- a/src/Notifications/Notifications/CleanupHasFailedNotification.php +++ b/src/Notifications/Notifications/CleanupHasFailedNotification.php @@ -20,7 +20,7 @@ public function toMail(): MailMessage { $mailMessage = (new MailMessage()) ->error() - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.cleanup_failed_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.cleanup_failed_body', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.exception_message', ['message' => $this->event->exception->getMessage()])) @@ -37,8 +37,8 @@ public function toSlack(): SlackMessage { return (new SlackMessage()) ->error() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.cleanup_failed_subject', ['application_name' => $this->applicationName()])) ->attachment(function (SlackAttachment $attachment) { $attachment @@ -59,7 +59,7 @@ public function toDiscord(): DiscordMessage { return (new DiscordMessage()) ->error() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title( trans('backup::notifications.cleanup_failed_subject', ['application_name' => $this->applicationName()]) )->fields([ diff --git a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php index 8ab7da53..5e6925f1 100644 --- a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php @@ -19,7 +19,7 @@ public function __construct( public function toMail(): MailMessage { $mailMessage = (new MailMessage()) - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.cleanup_successful_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.cleanup_successful_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])); @@ -34,8 +34,8 @@ public function toSlack(): SlackMessage { return (new SlackMessage()) ->success() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.cleanup_successful_subject_title')) ->attachment(function (SlackAttachment $attachment) { $attachment->fields($this->backupDestinationProperties()->toArray()); @@ -46,7 +46,7 @@ public function toDiscord(): DiscordMessage { return (new DiscordMessage()) ->success() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title(trans('backup::notifications.cleanup_successful_subject_title')) ->fields($this->backupDestinationProperties()->toArray()); } diff --git a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php index 44ed0d1b..424adfce 100644 --- a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php @@ -19,7 +19,7 @@ public function __construct( public function toMail(): MailMessage { $mailMessage = (new MailMessage()) - ->from(config('backup.notifications.mail.from.address', config('mail.from.address')), config('backup.notifications.mail.from.name', config('mail.from.name'))) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.healthy_backup_found_subject', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])) ->line(trans('backup::notifications.healthy_backup_found_body', ['application_name' => $this->applicationName()])); @@ -34,8 +34,8 @@ public function toSlack(): SlackMessage { return (new SlackMessage()) ->success() - ->from(config('backup.notifications.slack.username'), config('backup.notifications.slack.icon')) - ->to(config('backup.notifications.slack.channel')) + ->from($this->config()->notifications->slack->username, $this->config()->notifications->slack->icon) + ->to($this->config()->notifications->slack->channel) ->content(trans('backup::notifications.healthy_backup_found_subject_title', ['application_name' => $this->applicationName()])) ->attachment(function (SlackAttachment $attachment) { $attachment->fields($this->backupDestinationProperties()->toArray()); @@ -46,7 +46,7 @@ public function toDiscord(): DiscordMessage { return (new DiscordMessage()) ->success() - ->from(config('backup.notifications.discord.username'), config('backup.notifications.discord.avatar_url')) + ->from($this->config()->notifications->discord->username, $this->config()->notifications->discord->avatar_url) ->title( trans('backup::notifications.healthy_backup_found_subject_title', [ 'application_name' => $this->applicationName(), diff --git a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php index 22808180..eacb3ff0 100644 --- a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php @@ -19,12 +19,9 @@ public function __construct( public function toMail(): MailMessage { - $address = $this->config()->notifications->mail->from['address'] ?? config('mail.from.address'); - $name = $this->config()->notifications->mail->from['name'] ?? config('mail.from.name'); - $mailMessage = (new MailMessage()) ->error() - ->from($address, $name) + ->from($this->config()->notifications->mail->from->address, $this->config()->notifications->mail->from->name) ->subject(trans('backup::notifications.unhealthy_backup_found_subject', ['application_name' => $this->applicationName()])) ->line(trans('backup::notifications.unhealthy_backup_found_body', ['application_name' => $this->applicationName(), 'disk_name' => $this->diskName()])) ->line($this->problemDescription()); From 754379cfe67485745e6f9b079ab96e71bf3b160c Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:00:54 +0200 Subject: [PATCH 22/33] refactor the Notifiable --- .../customizing-the-notifiable.md | 2 +- src/Notifications/Notifiable.php | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/sending-notifications/customizing-the-notifiable.md b/docs/sending-notifications/customizing-the-notifiable.md index c3b21a82..c3dc1859 100644 --- a/docs/sending-notifications/customizing-the-notifiable.md +++ b/docs/sending-notifications/customizing-the-notifiable.md @@ -20,7 +20,7 @@ class BackupNotifiable extends Notifiable { public function routeNotificationForAnotherNotificationChannel() { - return config('backup.notifications.another_notification_channel.property'); + return $this->config()->notifications->another_notification_channel->property; } } diff --git a/src/Notifications/Notifiable.php b/src/Notifications/Notifiable.php index 419ce283..1321c168 100644 --- a/src/Notifications/Notifiable.php +++ b/src/Notifications/Notifiable.php @@ -3,6 +3,7 @@ namespace Spatie\Backup\Notifications; use Illuminate\Notifications\Notifiable as NotifiableTrait; +use Spatie\Backup\Config\Config; class Notifiable { @@ -11,21 +12,26 @@ class Notifiable /** @return string|array{int, string} */ public function routeNotificationForMail(): string|array { - return config('backup.notifications.mail.to'); + return $this->config()->notifications->mail->to; } public function routeNotificationForSlack(): string { - return config('backup.notifications.slack.webhook_url'); + return $this->config()->notifications->slack->webhookUrl; } public function routeNotificationForDiscord(): string { - return config('backup.notifications.discord.webhook_url'); + return $this->config()->notifications->discord->webhookUrl; } public function getKey(): int { return 1; } + + protected function config(): Config + { + return app(Config::class); + } } From 1513982e2ba14ef1e26d337ffa8632b730285438 Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Tue, 11 Jun 2024 14:01:59 +0000 Subject: [PATCH 23/33] Fix styling --- src/Exceptions/InvalidConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptions/InvalidConfig.php b/src/Exceptions/InvalidConfig.php index 70e71ad5..ebcd218a 100644 --- a/src/Exceptions/InvalidConfig.php +++ b/src/Exceptions/InvalidConfig.php @@ -13,6 +13,6 @@ public static function invalidEmail(string $email): static public static function missingSender(): static { - return new static("No sender email address specified."); + return new static('No sender email address specified.'); } } From f4067e04f0cfcfac578ee6fd1bcfeb41017202bc Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:05:40 +0200 Subject: [PATCH 24/33] drop 8.1 --- .github/workflows/run-tests.yml | 5 +---- src/Config/BackupConfig.php | 7 ++++--- src/Exceptions/InvalidConfig.php | 5 +++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 63a8f070..2e52031d 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - php: [8.3, 8.2, 8.1] + php: [8.3, 8.2] laravel: [11.*, 10.*] stability: [prefer-lowest, prefer-stable] carbon: [^2.63] @@ -26,9 +26,6 @@ jobs: testbench: 8.* - laravel: 11.* testbench: 9.* - exclude: - - laravel: 11.* - php: 8.1 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index dbd53032..1de5347a 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -2,13 +2,11 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Exceptions\InvalidConfig; use Spatie\Backup\Support\Data; class BackupConfig extends Data { - /** - * @param positive-int $tries - */ protected function __construct( public string $name, public SourceConfig $source, @@ -24,6 +22,9 @@ protected function __construct( public int $retryDelay, public ?MonitoredBackupsConfig $monitoredBackups, ) { + if ($this->tries < 1) { + throw InvalidConfig::integerMustBePositive('tries'); + } } /** @param array $data */ diff --git a/src/Exceptions/InvalidConfig.php b/src/Exceptions/InvalidConfig.php index ebcd218a..b2fe64ad 100644 --- a/src/Exceptions/InvalidConfig.php +++ b/src/Exceptions/InvalidConfig.php @@ -15,4 +15,9 @@ public static function missingSender(): static { return new static('No sender email address specified.'); } + + public static function integerMustBePositive(string $name): static + { + return new static("`{$name}` must be a positive number."); + } } From 06662508a7fd9a5b078673e6e82d6da4a2321967 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:19:26 +0200 Subject: [PATCH 25/33] add validation to the Config --- phpstan.neon.dist | 1 + src/Config/CleanupConfig.php | 9 ++++++++- src/Config/DestinationConfig.php | 4 ++++ src/Config/NotificationMailConfig.php | 7 ------- src/Config/NotificationsConfig.php | 4 ++++ src/Exceptions/InvalidConfig.php | 10 ++++++++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 685a823f..c5770235 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,6 +9,7 @@ parameters: tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true + treatPhpDocTypesAsCertain: false ignoreErrors: - '#Unsafe usage of new static#' diff --git a/src/Config/CleanupConfig.php b/src/Config/CleanupConfig.php index 6c1c0b87..31a072e2 100644 --- a/src/Config/CleanupConfig.php +++ b/src/Config/CleanupConfig.php @@ -2,6 +2,7 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Exceptions\InvalidConfig; use Spatie\Backup\Support\Data; use Spatie\Backup\Tasks\Cleanup\CleanupStrategy; @@ -9,7 +10,6 @@ class CleanupConfig extends Data { /** * @param class-string $strategy - * @param positive-int $tries */ protected function __construct( public string $strategy, @@ -17,6 +17,13 @@ protected function __construct( public int $tries, public int $retryDelay, ) { + if ($this->tries < 1) { + throw InvalidConfig::integerMustBePositive('cleanup tries'); + } + + if (! class_exists($this->strategy)) { + throw InvalidConfig::invalidStrategy($this->strategy); + } } /** @param array $data */ diff --git a/src/Config/DestinationConfig.php b/src/Config/DestinationConfig.php index 75484bbc..e983edff 100644 --- a/src/Config/DestinationConfig.php +++ b/src/Config/DestinationConfig.php @@ -2,6 +2,7 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Exceptions\InvalidConfig; use Spatie\Backup\Support\Data; class DestinationConfig extends Data @@ -16,6 +17,9 @@ protected function __construct( public string $filenamePrefix, public array $disks, ) { + if ($compressionLevel > 9 || $compressionLevel < 0) { + throw InvalidConfig::integerMustBeBetween('compression_level', 0, 9); + } } /** @param array $data */ diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index f0072e1b..414c575a 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -21,16 +21,9 @@ protected function __construct( public static function fromArray(array $data): self { if (! filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { - throw InvalidConfig::invalidEmail($data['to']); } - $address = $data['from']['address'] ?? config('mail.from.address'); - - if ($address && ! filter_var($address, FILTER_VALIDATE_EMAIL)) { - throw InvalidConfig::invalidEmail($address); - } - return new self( to: $data['to'], from: NotificationMailSenderConfig::fromArray($data['from'] ?? []), diff --git a/src/Config/NotificationsConfig.php b/src/Config/NotificationsConfig.php index b8594a62..b2045e99 100644 --- a/src/Config/NotificationsConfig.php +++ b/src/Config/NotificationsConfig.php @@ -2,6 +2,7 @@ namespace Spatie\Backup\Config; +use Spatie\Backup\Exceptions\InvalidConfig; use Spatie\Backup\Notifications\BaseNotification; use Spatie\Backup\Notifications\Notifiable; use Spatie\Backup\Support\Data; @@ -19,6 +20,9 @@ protected function __construct( public NotificationSlackConfig $slack, public NotificationDiscordConfig $discord, ) { + if (! class_exists($this->notifiable)) { + throw InvalidConfig::invalidStrategy($this->notifiable); + } } /** @param array $data */ diff --git a/src/Exceptions/InvalidConfig.php b/src/Exceptions/InvalidConfig.php index b2fe64ad..53f8c2f8 100644 --- a/src/Exceptions/InvalidConfig.php +++ b/src/Exceptions/InvalidConfig.php @@ -20,4 +20,14 @@ public static function integerMustBePositive(string $name): static { return new static("`{$name}` must be a positive number."); } + + public static function integerMustBeBetween(string $name, int $low, int $high): static + { + return new static("`{$name}` must be between {$low} and {$high}."); + } + + public static function invalidStrategy(string $class): static + { + return new static("`{$class}` must be a valid strategy class name."); + } } From 58b1173b64183e66bcb3b331f3f2a8be5e0ea61e Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:20:25 +0200 Subject: [PATCH 26/33] migrate phpunit config XML configuration validated against a deprecated schema --- .phpunit.cache/test-results | 1 + phpunit.xml.dist | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 .phpunit.cache/test-results diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results new file mode 100644 index 00000000..794e2fd1 --- /dev/null +++ b/.phpunit.cache/test-results @@ -0,0 +1 @@ +{"version":"pest_2.34.7","defects":{"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_only_the_files":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_includes_files_from_the_local_disks_in_the_backup":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_temporary_directory_from_the_backup":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename_as_option":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_to_a_specific_disk":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_twice_a_day_at_same_time_in_12h_clock":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_previous_local_backups_from_the_backup":7,"P\\Tests\\Events\\BackupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_backup_was_completed_successfully":7,"P\\Tests\\Events\\BackupZipWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_zip_was_created_event_when_the_zip_was_created":7},"times":{"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_count_all_the_files":0.007,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_will_not_take_into_account_non_zip_files":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_handle_empty_disks":0,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_return_all_files_in_order_of_descending_age":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_will_hold_backup_objects":0,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_newest_backup":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_oldest_backup":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_size_of_the_backups":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_need_a_float_type_size":0.001,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_the_disk_of_the_backup":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_the_path_of_the_backup":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_get_backup_as_stream_resource":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_when_its_unable_to_read_the_stream_throws_exception":0.003,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_delete_itself":0.001,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_its_size":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_its_size_even_after_it_has_been_deleted":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_push_backup_extra_option_to_write_stream_if_set":0.004,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_push_empty_default_backup_extra_option_to_write_stream_if_not_set":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_need_a_float_type_size":0,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_only_the_files":0.035,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_includes_files_from_the_local_disks_in_the_backup":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_backup_destination_from_the_backup":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_relative_path":0.017,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_short_relative_path":0.016,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_temporary_directory_from_the_backup":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename_as_option":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_to_a_specific_disk":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_selectively_backup_db":0.257,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_twice_a_day_at_same_time_in_12h_clock":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_try_to_backup_only_the_files_and_only_the_db":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_trying_to_backup_a_non_existing_database":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_trying_to_backup_to_an_non_existing_diskname":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_there_are_no_files_to_be_backed_up":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_avoid_full_path_on_database_backup":0.071,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_appends_the_database_type_to_backup_file_name_to_prevent_overwrite":0.126,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_renames_database_dump_file_extension_when_specified":0.125,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_appends_timestamp_to_database_backup_file_name":0.067,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_trigger_the_backup_failed_event":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_omit_the_backup_failed_event_with_no_notifications_flag":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_compresses_the_database_dump":0.016,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_encrypt_backup_when_notifications_are_disabled":0.108,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_use_different_compression_methods_for_backup_file":0.135,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_previous_local_backups_from_the_backup":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_argument":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_configuration_option":0.011,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_wait_before_trying_again_when_retry__delay_is_configured__with_Sleep_helper_":0.01,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_uses_connection_name_in_place_of_database_name_for_dump_filename":0.067,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_can_remove_old_backups_until_using_less_than_maximum_storage":0.007,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_can_remove_old_backups_from_the_backup_directory":0.4,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_will_leave_non_zip_files_alone":0.007,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_will_never_delete_the_newest_backup":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_trigger_the_cleanup_successful_event":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_omit_the_cleanup_successful_event_when_the_notifications_are_disabled":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_display_correct_used_storage_amount_after_cleanup":0.01,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_argument":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_configuration_option":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_wait_before_trying_again_when_retry__delay_is_configured__with_Sleep_helper_":0.005,"P\\Tests\\Commands\\ListCommandTest::__pest_evaluable_it_can_run_the_list_command":0.007,"P\\Tests\\Commands\\MonitorCommandTest::__pest_evaluable_it_can_run_the_monitor_command":0.068,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instances_of_mysql_and_pgsql_and_mongodb":0.001,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_sqlite_instance":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_mongodb_instance":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instance_from_database_url":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_use_the_read_db_when_one_is_defined":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_use_the_first_read_db_when_multiple_are_defined":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_throw_an_exception_when_creating_an_unknown_type_of_dumper":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_named_options_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_named_options_with_an_array_value_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_arbritrary_options_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instances_of_custom_dumpers":0,"P\\Tests\\Events\\BackupHasFailedTest::__pest_evaluable_it_will_fire_an_event_when_a_backup_has_failed":0.01,"P\\Tests\\Events\\BackupHasFailedTest::__pest_evaluable_it_will_fire_a_backup_failed_event_when_there_are_no_files_or_databases_to_be_backed_up":0.009,"P\\Tests\\Events\\BackupManifestWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_manifest_was_created_event_when_the_manifest_was_created":0.01,"P\\Tests\\Events\\BackupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_backup_was_completed_successfully":0.012,"P\\Tests\\Events\\BackupZipWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_zip_was_created_event_when_the_zip_was_created":0.012,"P\\Tests\\Events\\CleanupHasFailedTest::__pest_evaluable_it_will_fire_an_event_when_a_cleanup_has_failed":0.004,"P\\Tests\\Events\\CleanupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_cleanup_was_completed_successfully":0.005,"P\\Tests\\Events\\DumpingDatabaseTest::__pest_evaluable_it_will_fire_a_dumping_database_event":0.016,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_will_fire_an_event_on_failed_health_check":0.006,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_sends_an_notification_containing_the_exception_message_for_handled_health_check_errors":0.007,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_sends_an_notification_containing_the_exception_for_unexpected_health_check_errors":0.005,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_all_the_files_in_a_directory_and_subdirectories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_from_a_given_subdirectory":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_with_wildcards_from_a_given_subdirectory":0.001,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_files_from_multiple_directories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_from_multiple_directories":0.001,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_returns_an_empty_array_when_not_specifying_any_directories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_returns_an_empty_array_if_everything_is_excluded":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_a_single_file":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_provides_a_factory_method":0,"P\\Tests\\FormatTest::__pest_evaluable_it_can_determine_a_human_readable_filesize":0,"P\\Tests\\FormatTest::__pest_evaluable_it_can_determine_the_age_in_days":0.001,"P\\Tests\\HealthChecks\\IsReachableTest::__pest_evaluable_it_succeeds_when_destination_is_reachable":0.004,"P\\Tests\\HealthChecks\\IsReachableTest::__pest_evaluable_it_fails_when_backup_destination_is_not_reachable":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_succeeds_when_a_fresh_backup_present":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_fails_when_no_backups_are_present":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_fails_when_max_days_has_been_exceeded":0.006,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_accepts_a_shorthand_value_in_config":0.005,"P\\Tests\\HealthChecks\\MaximumStorageInMegabytesTest::__pest_evaluable_it_succeeds_when_a_fresh_backup_is_present":0.006,"P\\Tests\\HealthChecks\\MaximumStorageInMegabytesTest::__pest_evaluable_it_fails_when_max_mb_has_been_exceeded":0.005,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_keeps_archive_unencrypted_without_password":0.001,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(257)":0.004,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(258)":0.006,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(259)":0.008,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_can_not_open_encrypted_archive_without_password":0.004,"P\\Tests\\ManifestTest::__pest_evaluable_it_will_create_an_empty_file_when_it_is_instantiated":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_provides_a_factory_method":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_determine_its_own_path":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_count_the_amount_of_files_in_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_implements_the_countable_interface":0,"P\\Tests\\ManifestTest::__pest_evaluable_a_file_can_be_added_to_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_an_array_of_files_can_be_added_to_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_will_not_add_an_empty_path":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_return_a_generator_to_loop_over_all_the_files_in_the_manifest":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_by_default_when_a_backup_has_failed":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail'])":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail', 'slack'])":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail', 'slack', 'discord'])":0.005,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_it_will_send_backup_failed_notification_once":0.043,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_it_will_send_backup_failed_notification_once_with_retries":0.046,"P\\Tests\\ZipTest::__pest_evaluable_it_can_create_a_zip_file":0,"P\\Tests\\ZipTest::__pest_evaluable_it_can_report_its_own_size":0.001}} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 92ed9fe9..6f21f52f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,15 @@ - - - - src/ - - + tests @@ -13,4 +18,9 @@ + + + src/ + + From dc8a37eee8f7e78d63e278e2418f13a2dca59298 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:22:19 +0200 Subject: [PATCH 27/33] remove phpuit cache --- .gitignore | 1 + .phpunit.cache/test-results | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 .phpunit.cache/test-results diff --git a/.gitignore b/.gitignore index f3ae3118..bf66b2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock vendor .phpunit.result.cache .php-cs-fixer.cache +.phpunit.cache diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index 794e2fd1..00000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":"pest_2.34.7","defects":{"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_only_the_files":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_includes_files_from_the_local_disks_in_the_backup":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_temporary_directory_from_the_backup":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename_as_option":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_to_a_specific_disk":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_twice_a_day_at_same_time_in_12h_clock":7,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_previous_local_backups_from_the_backup":7,"P\\Tests\\Events\\BackupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_backup_was_completed_successfully":7,"P\\Tests\\Events\\BackupZipWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_zip_was_created_event_when_the_zip_was_created":7},"times":{"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_count_all_the_files":0.007,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_will_not_take_into_account_non_zip_files":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_handle_empty_disks":0,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_return_all_files_in_order_of_descending_age":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_will_hold_backup_objects":0,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_newest_backup":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_oldest_backup":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_can_determine_the_size_of_the_backups":0.001,"P\\Tests\\BackupDestination\\BackupCollectionTest::__pest_evaluable_it_need_a_float_type_size":0.001,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_the_disk_of_the_backup":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_the_path_of_the_backup":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_get_backup_as_stream_resource":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_when_its_unable_to_read_the_stream_throws_exception":0.003,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_delete_itself":0.001,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_its_size":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_can_determine_its_size_even_after_it_has_been_deleted":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_push_backup_extra_option_to_write_stream_if_set":0.004,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_push_empty_default_backup_extra_option_to_write_stream_if_not_set":0,"P\\Tests\\BackupDestination\\BackupTest::__pest_evaluable_it_need_a_float_type_size":0,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_only_the_files":0.035,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_includes_files_from_the_local_disks_in_the_backup":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_backup_destination_from_the_backup":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_relative_path":0.017,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_short_relative_path":0.016,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_temporary_directory_from_the_backup":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_using_a_custom_filename_as_option":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_to_a_specific_disk":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_selectively_backup_db":0.257,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_backup_twice_a_day_at_same_time_in_12h_clock":0.007,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_try_to_backup_only_the_files_and_only_the_db":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_trying_to_backup_a_non_existing_database":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_trying_to_backup_to_an_non_existing_diskname":0.004,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_fail_when_there_are_no_files_to_be_backed_up":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_avoid_full_path_on_database_backup":0.071,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_appends_the_database_type_to_backup_file_name_to_prevent_overwrite":0.126,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_renames_database_dump_file_extension_when_specified":0.125,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_appends_timestamp_to_database_backup_file_name":0.067,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_trigger_the_backup_failed_event":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_omit_the_backup_failed_event_with_no_notifications_flag":0.006,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_compresses_the_database_dump":0.016,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_will_encrypt_backup_when_notifications_are_disabled":0.108,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_can_use_different_compression_methods_for_backup_file":0.135,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_excludes_the_previous_local_backups_from_the_backup":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_argument":0.008,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_configuration_option":0.011,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_should_wait_before_trying_again_when_retry__delay_is_configured__with_Sleep_helper_":0.01,"P\\Tests\\Commands\\BackupCommandTest::__pest_evaluable_it_uses_connection_name_in_place_of_database_name_for_dump_filename":0.067,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_can_remove_old_backups_until_using_less_than_maximum_storage":0.007,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_can_remove_old_backups_from_the_backup_directory":0.4,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_will_leave_non_zip_files_alone":0.007,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_will_never_delete_the_newest_backup":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_trigger_the_cleanup_successful_event":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_omit_the_cleanup_successful_event_when_the_notifications_are_disabled":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_display_correct_used_storage_amount_after_cleanup":0.01,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_argument":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_try_again_after_encountering_an_exception_when_using_the_tries_configuration_option":0.005,"P\\Tests\\Commands\\CleanupCommandTest::__pest_evaluable_it_should_wait_before_trying_again_when_retry__delay_is_configured__with_Sleep_helper_":0.005,"P\\Tests\\Commands\\ListCommandTest::__pest_evaluable_it_can_run_the_list_command":0.007,"P\\Tests\\Commands\\MonitorCommandTest::__pest_evaluable_it_can_run_the_monitor_command":0.068,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instances_of_mysql_and_pgsql_and_mongodb":0.001,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_sqlite_instance":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_mongodb_instance":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instance_from_database_url":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_use_the_read_db_when_one_is_defined":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_use_the_first_read_db_when_multiple_are_defined":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_will_throw_an_exception_when_creating_an_unknown_type_of_dumper":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_named_options_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_named_options_with_an_array_value_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_add_arbritrary_options_to_the_dump_command":0,"P\\Tests\\DbDumperFactoryTest::__pest_evaluable_it_can_create_instances_of_custom_dumpers":0,"P\\Tests\\Events\\BackupHasFailedTest::__pest_evaluable_it_will_fire_an_event_when_a_backup_has_failed":0.01,"P\\Tests\\Events\\BackupHasFailedTest::__pest_evaluable_it_will_fire_a_backup_failed_event_when_there_are_no_files_or_databases_to_be_backed_up":0.009,"P\\Tests\\Events\\BackupManifestWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_manifest_was_created_event_when_the_manifest_was_created":0.01,"P\\Tests\\Events\\BackupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_backup_was_completed_successfully":0.012,"P\\Tests\\Events\\BackupZipWasCreatedTest::__pest_evaluable_it_will_fire_a_backup_zip_was_created_event_when_the_zip_was_created":0.012,"P\\Tests\\Events\\CleanupHasFailedTest::__pest_evaluable_it_will_fire_an_event_when_a_cleanup_has_failed":0.004,"P\\Tests\\Events\\CleanupWasSuccessfulTest::__pest_evaluable_it_will_fire_an_event_after_a_cleanup_was_completed_successfully":0.005,"P\\Tests\\Events\\DumpingDatabaseTest::__pest_evaluable_it_will_fire_a_dumping_database_event":0.016,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_will_fire_an_event_on_failed_health_check":0.006,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_sends_an_notification_containing_the_exception_message_for_handled_health_check_errors":0.007,"P\\Tests\\Events\\UnhealthyBackupWasFoundTest::__pest_evaluable_it_sends_an_notification_containing_the_exception_for_unexpected_health_check_errors":0.005,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_all_the_files_in_a_directory_and_subdirectories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_from_a_given_subdirectory":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_with_wildcards_from_a_given_subdirectory":0.001,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_files_from_multiple_directories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_exclude_files_from_multiple_directories":0.001,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_returns_an_empty_array_when_not_specifying_any_directories":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_returns_an_empty_array_if_everything_is_excluded":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_can_select_a_single_file":0,"P\\Tests\\FileSelectionTest::__pest_evaluable_it_provides_a_factory_method":0,"P\\Tests\\FormatTest::__pest_evaluable_it_can_determine_a_human_readable_filesize":0,"P\\Tests\\FormatTest::__pest_evaluable_it_can_determine_the_age_in_days":0.001,"P\\Tests\\HealthChecks\\IsReachableTest::__pest_evaluable_it_succeeds_when_destination_is_reachable":0.004,"P\\Tests\\HealthChecks\\IsReachableTest::__pest_evaluable_it_fails_when_backup_destination_is_not_reachable":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_succeeds_when_a_fresh_backup_present":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_fails_when_no_backups_are_present":0.005,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_fails_when_max_days_has_been_exceeded":0.006,"P\\Tests\\HealthChecks\\MaximumAgeInDaysTest::__pest_evaluable_it_accepts_a_shorthand_value_in_config":0.005,"P\\Tests\\HealthChecks\\MaximumStorageInMegabytesTest::__pest_evaluable_it_succeeds_when_a_fresh_backup_is_present":0.006,"P\\Tests\\HealthChecks\\MaximumStorageInMegabytesTest::__pest_evaluable_it_fails_when_max_mb_has_been_exceeded":0.005,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_keeps_archive_unencrypted_without_password":0.001,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(257)":0.004,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(258)":0.006,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_encrypts_archive_with_password#(259)":0.008,"P\\Tests\\Listeners\\EncryptBackupArchiveTest::__pest_evaluable_it_can_not_open_encrypted_archive_without_password":0.004,"P\\Tests\\ManifestTest::__pest_evaluable_it_will_create_an_empty_file_when_it_is_instantiated":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_provides_a_factory_method":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_determine_its_own_path":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_count_the_amount_of_files_in_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_implements_the_countable_interface":0,"P\\Tests\\ManifestTest::__pest_evaluable_a_file_can_be_added_to_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_an_array_of_files_can_be_added_to_it":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_will_not_add_an_empty_path":0,"P\\Tests\\ManifestTest::__pest_evaluable_it_can_return_a_generator_to_loop_over_all_the_files_in_the_manifest":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_by_default_when_a_backup_has_failed":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail'])":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail', 'slack'])":0,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_will_send_a_notification_via_the_configured_notification_channels#(['mail', 'slack', 'discord'])":0.005,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_it_will_send_backup_failed_notification_once":0.043,"P\\Tests\\Notifications\\EventHandlerTest::__pest_evaluable_it_it_will_send_backup_failed_notification_once_with_retries":0.046,"P\\Tests\\ZipTest::__pest_evaluable_it_can_create_a_zip_file":0,"P\\Tests\\ZipTest::__pest_evaluable_it_can_report_its_own_size":0.001}} \ No newline at end of file From 9c91993ba0d20e27011ff828dd482ba082641b7f Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:31:37 +0200 Subject: [PATCH 28/33] rector fixes --- rector.php | 2 ++ src/BackupDestination/BackupCollection.php | 2 +- src/BackupServiceProvider.php | 4 ++-- src/Commands/ListCommand.php | 6 +++--- src/Config/Config.php | 2 +- src/Config/DestinationConfig.php | 6 +++++- src/Tasks/Backup/BackupJob.php | 2 +- src/Tasks/Backup/BackupJobFactory.php | 2 +- src/Tasks/Backup/Zip.php | 12 +++++------- src/Tasks/Monitor/BackupDestinationStatusFactory.php | 4 ++-- 10 files changed, 23 insertions(+), 19 deletions(-) diff --git a/rector.php b/rector.php index a81f8384..836677e8 100644 --- a/rector.php +++ b/rector.php @@ -15,6 +15,7 @@ use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; +use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector; return RectorConfig::configure() ->withPaths(['config', 'resources', 'src']) @@ -33,4 +34,5 @@ PostIncDecToPreIncDecRector::class, NullableCompareToNullRector::class, AddArrowFunctionReturnTypeRector::class, + AddClosureVoidReturnTypeWhereNoReturnRector::class, ]); diff --git a/src/BackupDestination/BackupCollection.php b/src/BackupDestination/BackupCollection.php index dc998fdf..b3564010 100644 --- a/src/BackupDestination/BackupCollection.php +++ b/src/BackupDestination/BackupCollection.php @@ -16,7 +16,7 @@ public static function createFromFiles(?FileSystem $disk, array $files): self { return (new static($files)) ->filter(fn (string $path) => (new File())->isZipFile($disk, $path)) - ->map(fn (string $path) => new Backup($disk, $path)) + ->map(fn (string $path): \Spatie\Backup\BackupDestination\Backup => new Backup($disk, $path)) ->sortByDesc(fn (Backup $backup) => $backup->date()->timestamp) ->values(); } diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index bf1559e3..92e10d75 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -52,7 +52,7 @@ public function packageRegistered(): void $this->registerDiscordChannel(); - $this->app->scoped(Config::class, function () { + $this->app->scoped(Config::class, function (): \Spatie\Backup\Config\Config { return Config::fromArray(config('backup')); }); } @@ -60,7 +60,7 @@ public function packageRegistered(): void protected function registerDiscordChannel(): void { Notification::resolved(function (ChannelManager $service) { - $service->extend('discord', function ($app) { + $service->extend('discord', function ($app): \Spatie\Backup\Notifications\Channels\Discord\DiscordChannel { return new DiscordChannel(); }); }); diff --git a/src/Commands/ListCommand.php b/src/Commands/ListCommand.php index ac024e50..7e226eeb 100644 --- a/src/Commands/ListCommand.php +++ b/src/Commands/ListCommand.php @@ -39,7 +39,7 @@ protected function displayOverview(Collection $backupDestinationStatuses): stati { $headers = ['Name', 'Disk', 'Reachable', 'Healthy', '# of backups', 'Newest backup', 'Used storage']; - $rows = $backupDestinationStatuses->map(function (BackupDestinationStatus $backupDestinationStatus) { + $rows = $backupDestinationStatuses->map(function (BackupDestinationStatus $backupDestinationStatus): array { return $this->convertToRow($backupDestinationStatus); }); @@ -83,10 +83,10 @@ public function convertToRow(BackupDestinationStatus $backupDestinationStatus): protected function displayFailures(Collection $backupDestinationStatuses): static { $failed = $backupDestinationStatuses - ->filter(function (BackupDestinationStatus $backupDestinationStatus) { + ->filter(function (BackupDestinationStatus $backupDestinationStatus): bool { return $backupDestinationStatus->getHealthCheckFailure() !== null; }) - ->map(function (BackupDestinationStatus $backupDestinationStatus) { + ->map(function (BackupDestinationStatus $backupDestinationStatus): array { return [ $backupDestinationStatus->backupDestination()->backupName(), $backupDestinationStatus->backupDestination()->diskName(), diff --git a/src/Config/Config.php b/src/Config/Config.php index b3667476..e99baa30 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -17,7 +17,7 @@ protected function __construct( /** @internal used for testing */ public static function rebind(): void { - app()->scoped(Config::class, function () { + app()->scoped(Config::class, function (): \Spatie\Backup\Config\Config { return self::fromArray(config('backup')); }); } diff --git a/src/Config/DestinationConfig.php b/src/Config/DestinationConfig.php index e983edff..9894f727 100644 --- a/src/Config/DestinationConfig.php +++ b/src/Config/DestinationConfig.php @@ -17,7 +17,11 @@ protected function __construct( public string $filenamePrefix, public array $disks, ) { - if ($compressionLevel > 9 || $compressionLevel < 0) { + if ($compressionLevel > 9) { + throw InvalidConfig::integerMustBeBetween('compression_level', 0, 9); + } + + if ($compressionLevel < 0) { throw InvalidConfig::integerMustBeBetween('compression_level', 0, 9); } } diff --git a/src/Tasks/Backup/BackupJob.php b/src/Tasks/Backup/BackupJob.php index ad702f87..ad3c0453 100644 --- a/src/Tasks/Backup/BackupJob.php +++ b/src/Tasks/Backup/BackupJob.php @@ -254,7 +254,7 @@ protected function createZipContainingEveryFileInManifest(Manifest $manifest): s protected function dumpDatabases(): array { return $this->dbDumpers - ->map(function (DbDumper $dbDumper, $key) { + ->map(function (DbDumper $dbDumper, string $key): string { consoleOutput()->info("Dumping database {$dbDumper->getDbName()}..."); $dbType = mb_strtolower(basename(str_replace('\\', '/', $dbDumper::class))); diff --git a/src/Tasks/Backup/BackupJobFactory.php b/src/Tasks/Backup/BackupJobFactory.php index 67e98355..a047f6e0 100644 --- a/src/Tasks/Backup/BackupJobFactory.php +++ b/src/Tasks/Backup/BackupJobFactory.php @@ -33,7 +33,7 @@ protected static function createFileSelection(SourceFilesConfig $sourceFiles): F protected static function createDbDumpers(array $dbConnectionNames): Collection { return collect($dbConnectionNames)->mapWithKeys( - fn (string $dbConnectionName) => [$dbConnectionName => DbDumperFactory::createFromConnection($dbConnectionName)] + fn (string $dbConnectionName): array => [$dbConnectionName => DbDumperFactory::createFromConnection($dbConnectionName)] ); } } diff --git a/src/Tasks/Backup/Zip.php b/src/Tasks/Backup/Zip.php index 3fd66167..41181481 100644 --- a/src/Tasks/Backup/Zip.php +++ b/src/Tasks/Backup/Zip.php @@ -111,13 +111,11 @@ public function add(string|iterable $files, ?string $nameInZip = null): self if (is_file($file)) { $this->zipFile->addFile($file, ltrim((string) $nameInZip, DIRECTORY_SEPARATOR)); - if (is_int($compressionMethod)) { - $this->zipFile->setCompressionName( - ltrim($nameInZip ?: $file, DIRECTORY_SEPARATOR), - $compressionMethod, - $compressionLevel - ); - } + $this->zipFile->setCompressionName( + ltrim($nameInZip ?: $file, DIRECTORY_SEPARATOR), + $compressionMethod, + $compressionLevel + ); } $this->fileCount++; diff --git a/src/Tasks/Monitor/BackupDestinationStatusFactory.php b/src/Tasks/Monitor/BackupDestinationStatusFactory.php index 46e47cc0..42c0c6ec 100644 --- a/src/Tasks/Monitor/BackupDestinationStatusFactory.php +++ b/src/Tasks/Monitor/BackupDestinationStatusFactory.php @@ -26,7 +26,7 @@ public static function createForMonitorConfig(MonitoredBackupsConfig $monitorCon public static function createForSingleMonitor(array $monitorConfig): Collection { return collect($monitorConfig['disks']) - ->map(function ($diskName) use ($monitorConfig) { + ->map(function ($diskName) use ($monitorConfig): \Spatie\Backup\Tasks\Monitor\BackupDestinationStatus { $backupDestination = BackupDestination::create($diskName, $monitorConfig['name']); return new BackupDestinationStatus($backupDestination, static::buildHealthChecks($monitorConfig)); @@ -40,7 +40,7 @@ public static function createForSingleMonitor(array $monitorConfig): Collection protected static function buildHealthChecks(array $monitorConfig): array { return collect($monitorConfig['healthChecks']) - ->map(function ($options, $class) { + ->map(function ($options, $class): \Spatie\Backup\Tasks\Monitor\HealthCheck { if (is_int($class)) { $class = $options; $options = []; From dcf6e6d8088c7e108b3d012a1065de1c6ed1c833 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:57:53 +0200 Subject: [PATCH 29/33] cleanup --- composer.json | 2 +- src/BackupServiceProvider.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 11d9c522..ba7e9803 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,7 @@ "test": "vendor/bin/pest --compact", "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes", "analyse": "vendor/bin/phpstan analyse", - "rector": "./vendor/bin/rector --dry-run", + "rector": "vendor/bin/rector --dry-run", "baseline": "./vendor/bin/phpstan analyse --generate-baseline --memory-limit=2G" }, "suggest": { diff --git a/src/BackupServiceProvider.php b/src/BackupServiceProvider.php index 92e10d75..037c5464 100644 --- a/src/BackupServiceProvider.php +++ b/src/BackupServiceProvider.php @@ -52,7 +52,7 @@ public function packageRegistered(): void $this->registerDiscordChannel(); - $this->app->scoped(Config::class, function (): \Spatie\Backup\Config\Config { + $this->app->scoped(Config::class, function (): Config { return Config::fromArray(config('backup')); }); } @@ -60,7 +60,7 @@ public function packageRegistered(): void protected function registerDiscordChannel(): void { Notification::resolved(function (ChannelManager $service) { - $service->extend('discord', function ($app): \Spatie\Backup\Notifications\Channels\Discord\DiscordChannel { + $service->extend('discord', function ($app): DiscordChannel { return new DiscordChannel(); }); }); From a4eb33a7d3ff64b5882d1ee4654a247540ba8238 Mon Sep 17 00:00:00 2001 From: Nielsvanpach Date: Fri, 28 Jun 2024 13:58:19 +0000 Subject: [PATCH 30/33] Fix styling --- src/BackupDestination/BackupDestination.php | 4 +--- src/Config/Config.php | 3 +-- src/Config/MonitoredBackupConfig.php | 3 +-- src/Config/MonitoredBackupsConfig.php | 3 +-- src/Config/NotificationDiscordConfig.php | 3 +-- src/Config/NotificationMailConfig.php | 3 +-- src/Config/NotificationMailSenderConfig.php | 3 +-- src/Config/NotificationSlackConfig.php | 3 +-- src/Config/SourceConfig.php | 3 +-- src/Config/SourceFilesConfig.php | 3 +-- src/Config/StrategyConfig.php | 3 +-- src/Events/BackupHasFailed.php | 3 +-- src/Events/BackupManifestWasCreated.php | 3 +-- src/Events/BackupWasSuccessful.php | 3 +-- src/Events/BackupZipWasCreated.php | 3 +-- src/Events/CleanupHasFailed.php | 3 +-- src/Events/CleanupWasSuccessful.php | 3 +-- src/Events/DumpingDatabase.php | 3 +-- src/Events/HealthyBackupWasFound.php | 3 +-- src/Events/UnhealthyBackupWasFound.php | 3 +-- src/Notifications/EventHandler.php | 3 +-- .../Notifications/BackupHasFailedNotification.php | 3 +-- .../Notifications/BackupWasSuccessfulNotification.php | 3 +-- .../Notifications/CleanupHasFailedNotification.php | 3 +-- .../Notifications/CleanupWasSuccessfulNotification.php | 3 +-- .../Notifications/HealthyBackupWasFoundNotification.php | 3 +-- .../Notifications/UnhealthyBackupWasFoundNotification.php | 3 +-- src/Tasks/Cleanup/CleanupStrategy.php | 3 +-- src/Tasks/Cleanup/Period.php | 3 +-- src/Tasks/Monitor/BackupDestinationStatus.php | 3 +-- src/Tasks/Monitor/HealthCheckFailure.php | 3 +-- src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php | 3 +-- src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php | 3 +-- 33 files changed, 33 insertions(+), 67 deletions(-) diff --git a/src/BackupDestination/BackupDestination.php b/src/BackupDestination/BackupDestination.php index 3ef69882..ec047c98 100644 --- a/src/BackupDestination/BackupDestination.php +++ b/src/BackupDestination/BackupDestination.php @@ -14,9 +14,7 @@ class BackupDestination protected ?BackupCollection $backupCollectionCache = null; - public function __construct(protected ?Filesystem $disk, protected string $backupName, protected string $diskName) - { - } + public function __construct(protected ?Filesystem $disk, protected string $backupName, protected string $diskName) {} public function disk(): Filesystem { diff --git a/src/Config/Config.php b/src/Config/Config.php index e99baa30..78f9787b 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -11,8 +11,7 @@ protected function __construct( public NotificationsConfig $notifications, public MonitoredBackupsConfig $monitoredBackups, public CleanupConfig $cleanup, - ) { - } + ) {} /** @internal used for testing */ public static function rebind(): void diff --git a/src/Config/MonitoredBackupConfig.php b/src/Config/MonitoredBackupConfig.php index c3668a74..e24d5c40 100644 --- a/src/Config/MonitoredBackupConfig.php +++ b/src/Config/MonitoredBackupConfig.php @@ -15,8 +15,7 @@ protected function __construct( public string $name, public array $disks, public array $healthChecks, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/MonitoredBackupsConfig.php b/src/Config/MonitoredBackupsConfig.php index 7d2ae1fd..7962247c 100644 --- a/src/Config/MonitoredBackupsConfig.php +++ b/src/Config/MonitoredBackupsConfig.php @@ -11,8 +11,7 @@ class MonitoredBackupsConfig extends Data */ protected function __construct( public array $monitorBackups, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/NotificationDiscordConfig.php b/src/Config/NotificationDiscordConfig.php index 46ce63f9..adbb3dc7 100644 --- a/src/Config/NotificationDiscordConfig.php +++ b/src/Config/NotificationDiscordConfig.php @@ -10,8 +10,7 @@ protected function __construct( public string $webhookUrl, public string $username, public string $avatar_url, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/NotificationMailConfig.php b/src/Config/NotificationMailConfig.php index 414c575a..65c04231 100644 --- a/src/Config/NotificationMailConfig.php +++ b/src/Config/NotificationMailConfig.php @@ -10,8 +10,7 @@ class NotificationMailConfig extends Data protected function __construct( public string $to, public NotificationMailSenderConfig $from, - ) { - } + ) {} /** * @param array $data diff --git a/src/Config/NotificationMailSenderConfig.php b/src/Config/NotificationMailSenderConfig.php index 3013d9b7..0e674551 100644 --- a/src/Config/NotificationMailSenderConfig.php +++ b/src/Config/NotificationMailSenderConfig.php @@ -10,8 +10,7 @@ class NotificationMailSenderConfig extends Data protected function __construct( public string $address, public ?string $name, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/NotificationSlackConfig.php b/src/Config/NotificationSlackConfig.php index ae02f391..407ce415 100644 --- a/src/Config/NotificationSlackConfig.php +++ b/src/Config/NotificationSlackConfig.php @@ -11,8 +11,7 @@ protected function __construct( public ?string $channel, public ?string $username, public ?string $icon, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/SourceConfig.php b/src/Config/SourceConfig.php index 2bc9ba6d..ce03aeaa 100644 --- a/src/Config/SourceConfig.php +++ b/src/Config/SourceConfig.php @@ -12,8 +12,7 @@ class SourceConfig extends Data protected function __construct( public SourceFilesConfig $files, public array $databases, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/SourceFilesConfig.php b/src/Config/SourceFilesConfig.php index 1fa2b5cc..3cef60d6 100644 --- a/src/Config/SourceFilesConfig.php +++ b/src/Config/SourceFilesConfig.php @@ -16,8 +16,7 @@ protected function __construct( public bool $followLinks, public bool $ignoreUnreadableDirectories, public ?string $relativePath, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Config/StrategyConfig.php b/src/Config/StrategyConfig.php index 2c25e6d0..cf7802b5 100644 --- a/src/Config/StrategyConfig.php +++ b/src/Config/StrategyConfig.php @@ -13,8 +13,7 @@ protected function __construct( public int $keepMonthlyBackupsForMonths, public int $keepYearlyBackupsForYears, public int $deleteOldestBackupsWhenUsingMoreMegabytesThan, - ) { - } + ) {} /** @param array $data */ public static function fromArray(array $data): self diff --git a/src/Events/BackupHasFailed.php b/src/Events/BackupHasFailed.php index 66454cf8..8bf68229 100644 --- a/src/Events/BackupHasFailed.php +++ b/src/Events/BackupHasFailed.php @@ -10,6 +10,5 @@ class BackupHasFailed public function __construct( public Exception $exception, public ?BackupDestination $backupDestination = null, - ) { - } + ) {} } diff --git a/src/Events/BackupManifestWasCreated.php b/src/Events/BackupManifestWasCreated.php index 5d45aa2f..3cb8aec0 100644 --- a/src/Events/BackupManifestWasCreated.php +++ b/src/Events/BackupManifestWasCreated.php @@ -8,6 +8,5 @@ class BackupManifestWasCreated { public function __construct( public Manifest $manifest, - ) { - } + ) {} } diff --git a/src/Events/BackupWasSuccessful.php b/src/Events/BackupWasSuccessful.php index de686fa6..8b562be2 100644 --- a/src/Events/BackupWasSuccessful.php +++ b/src/Events/BackupWasSuccessful.php @@ -8,6 +8,5 @@ class BackupWasSuccessful { public function __construct( public BackupDestination $backupDestination, - ) { - } + ) {} } diff --git a/src/Events/BackupZipWasCreated.php b/src/Events/BackupZipWasCreated.php index 211730d9..4106311f 100644 --- a/src/Events/BackupZipWasCreated.php +++ b/src/Events/BackupZipWasCreated.php @@ -6,6 +6,5 @@ class BackupZipWasCreated { public function __construct( public string $pathToZip, - ) { - } + ) {} } diff --git a/src/Events/CleanupHasFailed.php b/src/Events/CleanupHasFailed.php index 709cb299..6d97ecc5 100644 --- a/src/Events/CleanupHasFailed.php +++ b/src/Events/CleanupHasFailed.php @@ -10,6 +10,5 @@ class CleanupHasFailed public function __construct( public Exception $exception, public ?BackupDestination $backupDestination = null, - ) { - } + ) {} } diff --git a/src/Events/CleanupWasSuccessful.php b/src/Events/CleanupWasSuccessful.php index 4306284c..a9bd8ebe 100644 --- a/src/Events/CleanupWasSuccessful.php +++ b/src/Events/CleanupWasSuccessful.php @@ -8,6 +8,5 @@ class CleanupWasSuccessful { public function __construct( public BackupDestination $backupDestination, - ) { - } + ) {} } diff --git a/src/Events/DumpingDatabase.php b/src/Events/DumpingDatabase.php index a66afe89..98faf17f 100644 --- a/src/Events/DumpingDatabase.php +++ b/src/Events/DumpingDatabase.php @@ -8,6 +8,5 @@ class DumpingDatabase { public function __construct( public DbDumper $dbDumper - ) { - } + ) {} } diff --git a/src/Events/HealthyBackupWasFound.php b/src/Events/HealthyBackupWasFound.php index 75d89cfa..0d76759c 100644 --- a/src/Events/HealthyBackupWasFound.php +++ b/src/Events/HealthyBackupWasFound.php @@ -8,6 +8,5 @@ class HealthyBackupWasFound { public function __construct( public BackupDestinationStatus $backupDestinationStatus, - ) { - } + ) {} } diff --git a/src/Events/UnhealthyBackupWasFound.php b/src/Events/UnhealthyBackupWasFound.php index 77d698e7..503945b1 100644 --- a/src/Events/UnhealthyBackupWasFound.php +++ b/src/Events/UnhealthyBackupWasFound.php @@ -8,6 +8,5 @@ class UnhealthyBackupWasFound { public function __construct( public BackupDestinationStatus $backupDestinationStatus - ) { - } + ) {} } diff --git a/src/Notifications/EventHandler.php b/src/Notifications/EventHandler.php index 6f1fdeec..6289238a 100644 --- a/src/Notifications/EventHandler.php +++ b/src/Notifications/EventHandler.php @@ -17,8 +17,7 @@ class EventHandler { public function __construct( protected Repository $config - ) { - } + ) {} public function subscribe(Dispatcher $events): void { diff --git a/src/Notifications/Notifications/BackupHasFailedNotification.php b/src/Notifications/Notifications/BackupHasFailedNotification.php index 5e59c50d..ba768d3f 100644 --- a/src/Notifications/Notifications/BackupHasFailedNotification.php +++ b/src/Notifications/Notifications/BackupHasFailedNotification.php @@ -13,8 +13,7 @@ class BackupHasFailedNotification extends BaseNotification { public function __construct( public BackupHasFailed $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php index 3ff78c58..c101a074 100644 --- a/src/Notifications/Notifications/BackupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/BackupWasSuccessfulNotification.php @@ -13,8 +13,7 @@ class BackupWasSuccessfulNotification extends BaseNotification { public function __construct( public BackupWasSuccessful $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Notifications/Notifications/CleanupHasFailedNotification.php b/src/Notifications/Notifications/CleanupHasFailedNotification.php index 699c0915..74f3081c 100644 --- a/src/Notifications/Notifications/CleanupHasFailedNotification.php +++ b/src/Notifications/Notifications/CleanupHasFailedNotification.php @@ -13,8 +13,7 @@ class CleanupHasFailedNotification extends BaseNotification { public function __construct( public CleanupHasFailed $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php index 5e6925f1..04b4cb07 100644 --- a/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php +++ b/src/Notifications/Notifications/CleanupWasSuccessfulNotification.php @@ -13,8 +13,7 @@ class CleanupWasSuccessfulNotification extends BaseNotification { public function __construct( public CleanupWasSuccessful $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php index 424adfce..7135e861 100644 --- a/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/HealthyBackupWasFoundNotification.php @@ -13,8 +13,7 @@ class HealthyBackupWasFoundNotification extends BaseNotification { public function __construct( public HealthyBackupWasFound $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php index eacb3ff0..da3840ec 100644 --- a/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php +++ b/src/Notifications/Notifications/UnhealthyBackupWasFoundNotification.php @@ -14,8 +14,7 @@ class UnhealthyBackupWasFoundNotification extends BaseNotification { public function __construct( public UnhealthyBackupWasFound $event, - ) { - } + ) {} public function toMail(): MailMessage { diff --git a/src/Tasks/Cleanup/CleanupStrategy.php b/src/Tasks/Cleanup/CleanupStrategy.php index 59d698f9..6a85c751 100644 --- a/src/Tasks/Cleanup/CleanupStrategy.php +++ b/src/Tasks/Cleanup/CleanupStrategy.php @@ -12,8 +12,7 @@ abstract class CleanupStrategy public function __construct( protected Repository $config, - ) { - } + ) {} abstract public function deleteOldBackups(BackupCollection $backups): void; diff --git a/src/Tasks/Cleanup/Period.php b/src/Tasks/Cleanup/Period.php index 6019413e..d00bcb32 100644 --- a/src/Tasks/Cleanup/Period.php +++ b/src/Tasks/Cleanup/Period.php @@ -9,8 +9,7 @@ class Period public function __construct( protected Carbon $startDate, protected Carbon $endDate - ) { - } + ) {} public function startDate(): Carbon { diff --git a/src/Tasks/Monitor/BackupDestinationStatus.php b/src/Tasks/Monitor/BackupDestinationStatus.php index 35387e6f..b79ee544 100644 --- a/src/Tasks/Monitor/BackupDestinationStatus.php +++ b/src/Tasks/Monitor/BackupDestinationStatus.php @@ -15,8 +15,7 @@ class BackupDestinationStatus public function __construct( protected BackupDestination $backupDestination, protected array $healthChecks = [] - ) { - } + ) {} public function backupDestination(): BackupDestination { diff --git a/src/Tasks/Monitor/HealthCheckFailure.php b/src/Tasks/Monitor/HealthCheckFailure.php index ca97fa6a..94d1b0ce 100644 --- a/src/Tasks/Monitor/HealthCheckFailure.php +++ b/src/Tasks/Monitor/HealthCheckFailure.php @@ -10,8 +10,7 @@ class HealthCheckFailure public function __construct( protected HealthCheck $healthCheck, protected Exception $exception - ) { - } + ) {} public function healthCheck(): HealthCheck { diff --git a/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php b/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php index c25d97bd..0bd33824 100644 --- a/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php +++ b/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php @@ -10,8 +10,7 @@ class MaximumAgeInDays extends HealthCheck { public function __construct( protected int $days = 1 - ) { - } + ) {} public function checkHealth(BackupDestination $backupDestination): void { diff --git a/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php b/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php index 2335808a..9a119ed3 100644 --- a/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php +++ b/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php @@ -10,8 +10,7 @@ class MaximumStorageInMegabytes extends HealthCheck { public function __construct( protected int $maximumSizeInMegaBytes = 5000 - ) { - } + ) {} public function checkHealth(BackupDestination $backupDestination): void { From 53cdc8b8e04c6399f9607f5d96425b6462de81be Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:12:45 +0200 Subject: [PATCH 31/33] update docs for min. requirements --- README.md | 2 +- docs/requirements.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c4b84d9..7af5325d 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ We highly appreciate you sending us a postcard from your hometown, mentioning wh ## Installation and usage -This package requires PHP 8.0 and Laravel 8.0 or higher. +This package requires PHP 8.2 and Laravel 10.0 or higher. You'll find installation instructions and full documentation on https://spatie.be/docs/laravel-backup. ## Using an older version of PHP / Laravel? diff --git a/docs/requirements.md b/docs/requirements.md index 0e4775be..846a52fc 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -3,7 +3,7 @@ title: Requirements weight: 3 --- -This backup package requires **PHP 8.0**, with the [ZIP module](http://php.net/manual/en/book.zip.php) and **Laravel 9.0 or higher**. It's not compatible with Windows servers. +This backup package requires **PHP 8.2**, with the [ZIP module](http://php.net/manual/en/book.zip.php) and **Laravel 9.0 or higher**. It's not compatible with Windows servers. If you are using an older version of Laravel, take a look at one of the previous versions of this package. From 6e53b57df53826dfd964413a8a90230a72502051 Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:15:42 +0200 Subject: [PATCH 32/33] allow null values --- src/Config/BackupConfig.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Config/BackupConfig.php b/src/Config/BackupConfig.php index 1de5347a..dc0791e8 100644 --- a/src/Config/BackupConfig.php +++ b/src/Config/BackupConfig.php @@ -35,8 +35,8 @@ public static function fromArray(array $data): self return new self( name: $data['name'], source: SourceConfig::fromArray($data['source']), - databaseDumpCompressor: $data['database_dump_compressor'], - databaseDumpFileTimestampFormat: $data['database_dump_file_timestamp_format'], + databaseDumpCompressor: $data['database_dump_compressor'] ?? null, + databaseDumpFileTimestampFormat: $data['database_dump_file_timestamp_format'] ?? null, databaseDumpFilenameBase: $data['database_dump_filename_base'], databaseDumpFileExtension: $data['database_dump_file_extension'], destination: DestinationConfig::fromArray($data['destination']), From 5d82d6654e9fb59c5b16960ba5a03f2a35c48dea Mon Sep 17 00:00:00 2001 From: Niels Vanpachtenbeke <10651054+Nielsvanpach@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:24:51 +0200 Subject: [PATCH 33/33] add note on upgrade guide --- UPGRADING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index ff835644..18332c8d 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,6 +1,7 @@ ## From v8 to v9 -- (All keys in the config file are still snake_cased. Rename any camelCased keys to their snake_cased counterparts) +- Ensure your config/backup.php file is in sync with the latest settings. You can copy paste the missing defaults from this [config file](https://github.com/spatie/laravel-backup/blob/main/config/backup.php). +- All keys in the config file are still snake_cased. Rename any camelCased keys to their snake_cased counterparts ## From v7 to v8