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 1/9] 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 @@ +<?php + +declare(strict_types=1); + +use Rector\CodeQuality\Rector\ClassMethod\OptionalParametersAfterRequiredRector; +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', + ]) + ->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 2/9] 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 <Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 07:53:49 +0000 Subject: [PATCH 3/9] 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 @@ <?php use Carbon\Carbon; - use Spatie\Backup\Helpers\Format; it('can determine a human readable filesize', function () { diff --git a/tests/Listeners/EncryptBackupArchiveTest.php b/tests/Listeners/EncryptBackupArchiveTest.php index 9ea73acc..756c22d4 100644 --- a/tests/Listeners/EncryptBackupArchiveTest.php +++ b/tests/Listeners/EncryptBackupArchiveTest.php @@ -23,7 +23,7 @@ }); /** - * @param int $algorithm + * @param int $algorithm */ it('encrypts archive with password', function (int $algorithm) { config()->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 @@ <?php -use function PHPUnit\Framework\assertTrue; - use Spatie\Backup\Tests\TestCase; +use function PHPUnit\Framework\assertTrue; + uses(TestCase::class)->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 4/9] 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 5/9] 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 @@ <?php return [ - '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', + '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 @@ <?php return [ - 'exception_message' => '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 <Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:17:10 +0000 Subject: [PATCH 6/9] 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 7/9] 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 8/9] 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\\<int,Spatie\\\\Backup\\\\BackupDestination\\\\Backup\\>\\:\\: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\\<int,Spatie\\\\Backup\\\\BackupDestination\\\\Backup\\>\\:\\: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\\<int,int\\>\\:\\: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\\<int,Spatie\\\\Backup\\\\BackupDestination\\\\Backup\\>\\:\\: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<int,Backup> */ class BackupCollection extends Collection { protected ?float $sizeCache = null; + /** @param array<string> $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<string, string> */ 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<string, mixed> $config + * @return Collection<int, BackupDestination> + */ 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<int> */ protected array $handlesSignals = []; public function __construct() @@ -33,6 +34,7 @@ protected function runningInConsole(): bool return in_array(PHP_SAPI, ['cli', 'phpdbg']); } + /** @return array<int> */ 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<int, BackupDestinationStatus> $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<int, BackupDestinationStatus> $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<int, string> $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<int, mixed> $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<string> */ 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<string, string> */ 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<string, string> */ 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<string> */ 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<string, string> $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<class-string, array<int, string>> $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<int, class-string> */ 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<string, DbDumper> */ protected Collection $dbDumpers; + /** @var Collection<int, BackupDestination> */ protected Collection $backupDestinations; protected string $filename; @@ -56,6 +58,7 @@ public function dontBackupFilesystem(): self return $this; } + /** @param array<string> $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<string, DbDumper> $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<int, BackupDestination> $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<string> */ 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<string, string> */ 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<string, array<string, mixed>> $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<string, mixed> $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<int, string> $dbConnectionNames + * @return Collection<string, DbDumper> + */ 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<DbDumper> */ 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<string, string|array<string>> $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<int, string> */ protected Collection $includeFilesAndDirectories; + /** @var Collection<int, string> */ protected Collection $excludeFilesAndDirectories; protected bool $shouldFollowLinks = false; protected bool $shouldIgnoreUnreadableDirs = false; - public static function create(array|string $includeFilesAndDirectories = []): self + /** @param array<string>|string $includeFilesAndDirectories */ + public static function create(array|string $includeFilesAndDirectories = []): static { return new static($includeFilesAndDirectories); } + /** @param array<string>|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>|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<empty> */ public function selectedFiles(): Generator|array { if ($this->includeFilesAndDirectories->isEmpty()) { @@ -87,18 +93,20 @@ public function selectedFiles(): Generator|array } } + /** @return array<string> */ protected function includedFiles(): array { return $this ->includeFilesAndDirectories - ->filter(fn ($path) => is_file($path))->toArray(); + ->filter(fn (string $path) => is_file($path))->toArray(); } + /** @return array<string> */ 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<string> $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<string> */ 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<string> $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<int, BackupDestination> $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<string, BackupCollection> $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<string, Period> */ 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<string, BackupCollection> $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<int, HealthCheck> $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<int, HealthCheck> */ 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<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfiguration + * @return Collection<int, BackupDestinationStatus> + */ 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<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig + * @return Collection<int, BackupDestinationStatus> + */ 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<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig + * @return array<HealthCheck> + */ + 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<string, mixed> $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 <Nielsvanpach@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:43:33 +0000 Subject: [PATCH 9/9] 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<string, mixed> $config + * @param array<string, mixed> $config * @return Collection<int, BackupDestination> */ 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<int, BackupDestinationStatus> $backupDestinationStatuses + * @param Collection<int, BackupDestinationStatus> $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<string, DbDumper> $dbDumpers + * @param Collection<string, DbDumper> $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<int, string> $dbConnectionNames + * @param array<int, string> $dbConnectionNames * @return Collection<string, DbDumper> */ 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<string> $paths + * @param string|array<string> $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<string> $filePaths + * @param Generator|string|array<string> $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<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfiguration + * @param array{name: string, disks: array<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfiguration * @return Collection<int, BackupDestinationStatus> */ public static function createForMonitorConfig(array $monitorConfiguration): Collection @@ -22,7 +20,7 @@ public static function createForMonitorConfig(array $monitorConfiguration): Coll } /** - * @param array{name: string, disks: array<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig + * @param array{name: string, disks: array<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig * @return Collection<int, BackupDestinationStatus> */ public static function createForSingleMonitor(array $monitorConfig): Collection @@ -36,7 +34,7 @@ public static function createForSingleMonitor(array $monitorConfig): Collection } /** - * @param array{name: string, disks: array<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig + * @param array{name: string, disks: array<string>, health_checks: array<class-string|int, array<string, mixed>>} $monitorConfig * @return array<HealthCheck> */ 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)) {