diff --git a/composer.json b/composer.json index 69e3b72..a024e3c 100644 --- a/composer.json +++ b/composer.json @@ -25,32 +25,33 @@ } ], "require": { - "php": "^8.2", - "spatie/laravel-package-tools": "^1.16", - "illuminate/contracts": "^10.0||^11.0||^12.0" + "php": "^8.3 || ^8.2", + "illuminate/contracts": "^10.0||^11.0||^12.0", + "spatie/laravel-package-tools": "^1.16" }, "require-dev": { + "tightenco/duster": "^3.2", + "driftingly/rector-laravel": "^1.2", + "larastan/larastan": "^2.9", "laravel/pint": "^1.14", "nunomaduro/collision": "^8.1.1||^7.10.0", - "larastan/larastan": "^2.9", "orchestra/testbench": "^9.0.0||^8.22.0", "pestphp/pest": "^2.34", "pestphp/pest-plugin-arch": "^2.7", "pestphp/pest-plugin-laravel": "^2.3", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3" + "phpstan/phpstan-phpunit": "^1.3", + "rector/rector": "^1.2" }, "autoload": { "psr-4": { - "Msamgan\\LaravelEnvKeysChecker\\": "src/", - "Msamgan\\LaravelEnvKeysChecker\\Database\\Factories\\": "database/factories/" + "Msamgan\\LaravelEnvKeysChecker\\": "src/" } }, "autoload-dev": { "psr-4": { - "Msamgan\\LaravelEnvKeysChecker\\Tests\\": "tests/", - "Workbench\\App\\": "workbench/app/" + "Msamgan\\LaravelEnvKeysChecker\\Tests\\": "tests/" } }, "scripts": { @@ -69,7 +70,7 @@ "analyse": "vendor/bin/phpstan analyse", "test": "vendor/bin/pest", "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/pint" + "format": "./vendor/bin/rector process && vendor/bin/pint && ./vendor/bin/duster fix" }, "config": { "sort-packages": true, diff --git a/config/env-keys-checker.php b/config/env-keys-checker.php index a25d4d2..4a67e15 100644 --- a/config/env-keys-checker.php +++ b/config/env-keys-checker.php @@ -1,11 +1,13 @@ explode(',', env('KEYS_CHECKER_IGNORE_FILES', '')), + 'ignore_files' => explode(',', (string) env('KEYS_CHECKER_IGNORE_FILES', '')), // List of all the env keys to ignore while checking the env keys - 'ignore_keys' => explode(',', env('KEYS_CHECKER_IGNORE_KEYS', '')), + 'ignore_keys' => explode(',', (string) env('KEYS_CHECKER_IGNORE_KEYS', '')), // strategy to add the missing keys to the .env file // ask: will ask the user to add the missing keys @@ -15,7 +17,7 @@ // List of all the .env.* files to be checked if they // are present in the .gitignore file - 'gitignore_files' => explode(',', env('KEYS_CHECKER_GITIGNORE_FILES', '.env')), + 'gitignore_files' => explode(',', (string) env('KEYS_CHECKER_GITIGNORE_FILES', '.env')), // Master .env file to be used for syncing the keys 'master_env' => env('MASTER_ENV', '.env'), diff --git a/pint.json b/pint.json index 7eb5048..d2c1abc 100644 --- a/pint.json +++ b/pint.json @@ -1,11 +1,64 @@ { "preset": "laravel", + "notPath": [ + "tests/TestCase.php" + ], "rules": { + "array_push": true, + "backtick_to_shell_exec": true, + "date_time_immutable": true, + "declare_strict_types": true, + "lowercase_keywords": true, + "lowercase_static_reference": true, + "final_class": true, + "final_internal_class": true, + "final_public_method_for_abstract_class": true, + "fully_qualified_strict_types": true, + "global_namespace_import": { + "import_classes": true, + "import_constants": true, + "import_functions": true + }, + "mb_str_functions": true, + "modernize_types_casting": true, + "new_with_parentheses": false, + "no_superfluous_elseif": true, + "no_useless_else": true, + "no_multiple_statements_per_line": true, + "ordered_class_elements": { + "order": [ + "use_trait", + "case", + "constant", + "constant_public", + "constant_protected", + "constant_private", + "property_public", + "property_protected", + "property_private", + "construct", + "destruct", + "magic", + "phpunit", + "method_abstract", + "method_public_static", + "method_public", + "method_protected_static", + "method_protected", + "method_private_static", + "method_private" + ], + "sort_algorithm": "none" + }, + "ordered_interfaces": true, + "ordered_traits": true, + "protected_to_private": true, + "self_accessor": true, + "self_static_accessor": true, + "strict_comparison": true, + "visibility_required": true, "concat_space": { "spacing": "one" - }, - "ordered_imports": { - "sort_algorithm": "alpha" } } } diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..18a873c --- /dev/null +++ b/rector.php @@ -0,0 +1,34 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/config', + __DIR__ . '/tests', + ])->withPhpSets(php83: true) + ->withPhpVersion(PhpVersion::PHP_83) + ->withPreparedSets( + deadCode: true, + codeQuality: true, + typeDeclarations: true, + privatization: true, + instanceOf: true, + earlyReturn: true, + carbon: true, + )->withSets([ + LaravelSetList::LARAVEL_110, + LaravelSetList::LARAVEL_CODE_QUALITY, + LaravelSetList::LARAVEL_IF_HELPERS, + LaravelSetList::LARAVEL_ARRAY_STR_FUNCTION_TO_STATIC_CALL, + LaravelSetList::LARAVEL_FACADE_ALIASES_TO_FULL_NAMES, + LaravelSetList::LARAVEL_ELOQUENT_MAGIC_METHOD_TO_QUERY_BUILDER, + LaravelSetList::LARAVEL_CONTAINER_STRING_TO_FULLY_QUALIFIED_NAME, + LaravelSetList::LARAVEL_ARRAYACCESS_TO_METHOD_CALL, + LaravelSetList::LARAVEL_COLLECTION, + ])->withImportNames(importDocBlockNames: false); diff --git a/src/Actions/AddKeys.php b/src/Actions/AddKeys.php index c9b134d..2b79911 100644 --- a/src/Actions/AddKeys.php +++ b/src/Actions/AddKeys.php @@ -1,14 +1,16 @@ each(function ($missingKey) { + $missingKeys->each(function (array $missingKey): void { $filePath = base_path($missingKey['envFile']); $envContent = file($filePath); diff --git a/src/Actions/CheckKeys.php b/src/Actions/CheckKeys.php index bce0d7a..2a6e5d5 100644 --- a/src/Actions/CheckKeys.php +++ b/src/Actions/CheckKeys.php @@ -1,19 +1,21 @@ each(function ($envFile) use ($keyData, $missingKeys) { + collect($envFiles)->each(function ($envFile) use ($keyData, $missingKeys): void { $envContent = file($envFile); $keyExists = false; foreach ($envContent as $line) { - if (str_starts_with($line, $keyData['key'])) { + if (str_starts_with($line, (string) $keyData['key'])) { $keyExists = true; break; } diff --git a/src/Actions/FilterFiles.php b/src/Actions/FilterFiles.php new file mode 100644 index 0000000..37d9b63 --- /dev/null +++ b/src/Actions/FilterFiles.php @@ -0,0 +1,16 @@ +reject(callback: fn ($file): bool => in_array(needle: basename((string) $file), haystack: $ignoredFiles)) + ->reject(callback: fn ($file): bool => str_ends_with(haystack: basename((string) $file), needle: '.encrypted')) + ->toArray(); + } +} diff --git a/src/Actions/GetKeys.php b/src/Actions/GetKeys.php index 821ca54..9422263 100644 --- a/src/Actions/GetKeys.php +++ b/src/Actions/GetKeys.php @@ -1,10 +1,12 @@ map(function ($file) use ($ignoredKeys, $withComments) { - $collection = collect(file($file))->map(function ($line, $index) use ($file) { + $collection = collect(file($file))->map(function ($line, $index) use ($file): array { [$key] = explode('=', $line); return [ @@ -27,14 +29,10 @@ public function handle(array|string $files, ?bool $withComments = false): Collec }); if (! $withComments) { - $collection = $collection->filter(function ($item) { - return $item['key'] !== "\n" && ! str_starts_with($item['key'], '#'); - }); + $collection = $collection->filter(fn ($item): bool => $item['key'] !== "\n" && ! str_starts_with($item['key'], '#')); } - return $collection->filter(function ($keyData) use ($ignoredKeys) { - return ! in_array($keyData['key'], $ignoredKeys); - }); + return $collection->reject(fn ($keyData): bool => in_array($keyData['key'], $ignoredKeys)); }) ->flatten(1) ->unique('key'); diff --git a/src/Commands/EnvInGitIgnoreCommand.php b/src/Commands/EnvInGitIgnoreCommand.php index d65d2e3..9051c56 100644 --- a/src/Commands/EnvInGitIgnoreCommand.php +++ b/src/Commands/EnvInGitIgnoreCommand.php @@ -1,11 +1,13 @@ each(callback: function ($file) use ($gitIgnoreContent, $missingFiles) { + collect(value: $filesToCheck)->each(callback: function ($file) use ($gitIgnoreContent, $missingFiles): void { if (! in_array(needle: $file, haystack: $gitIgnoreContent)) { $missingFiles->push(values: $file); } diff --git a/src/Commands/EnvKeysSyncCommand.php b/src/Commands/EnvKeysSyncCommand.php index 27d1e5d..662c1cd 100644 --- a/src/Commands/EnvKeysSyncCommand.php +++ b/src/Commands/EnvKeysSyncCommand.php @@ -1,11 +1,14 @@ call('env:keys-check', [ '--auto-add' => 'none', @@ -28,30 +31,26 @@ public function handle(): int return self::FAILURE; } - $envFiles = glob(pattern: base_path(path: '.env*')); - $ignoredFiles = config(key: 'env-keys-checker.ignore_files', default: []); + $envFiles = $this->getEnvs(); + $ignoredFiles = $this->getFilesToIgnore(); - if (empty($envFiles)) { + if ($envFiles === []) { $this->showFailureInfo(message: 'No .env files found.'); return self::FAILURE; } - $envFiles = collect(value: $envFiles)->filter(callback: function ($file) use ($ignoredFiles) { - return ! in_array(needle: basename(path: $file), haystack: $ignoredFiles); - })->toArray(); + $envFiles = $filterFiles->handle(envFiles: $envFiles, ignoredFiles: $ignoredFiles); - if (empty($envFiles)) { + if ($envFiles === []) { $this->showFailureInfo(message: 'No .env files found.'); return self::FAILURE; } - $envFiles = collect(value: $envFiles)->filter(callback: function ($file) { - return basename(path: $file) !== $this->getMasterEnv(); - }); + $envFiles = collect(value: $envFiles)->filter(callback: fn ($file): bool => basename(path: (string) $file) !== $this->getMasterEnv()); - $envFiles->each(callback: function ($envFile) { + $envFiles->each(callback: function ($envFile): void { $totalKeysFromMaster = count(value: file(filename: $this->getMasterEnv())); for ($line = 1; $line <= $totalKeysFromMaster; $line++) { $keyMaster = $this->getKeyFromFileOnLine(file: $this->getMasterEnv(), line: $line); @@ -93,12 +92,12 @@ public function handle(): int private function getMasterEnv(): string { - return config(key: 'env-keys-checker.master_env', default: '.env'); + return (string) config(key: 'env-keys-checker.master_env', default: '.env'); } private function getKeyFromFileOnLine(string $file, int $line): string { - return file(filename: $file)[$line - 1]; + return file(filename: $file)[$line - 1] ?? ''; } private function checkIfComment(string $line): bool @@ -122,11 +121,9 @@ private function checkIfEmptyLine(string $line): bool private function moveKeyToLine(string $file, string $key, int $toLine): void { $lines = file(filename: $file); - $keyLine = array_filter(array: $lines, callback: function ($line) use ($key) { - return str_starts_with($line, $key); - }); + $keyLine = array_filter(array: $lines, callback: fn ($line): bool => str_starts_with($line, $key)); - if (empty($keyLine)) { + if ($keyLine === []) { return; } diff --git a/src/Commands/KeysCheckerCommand.php b/src/Commands/KeysCheckerCommand.php index 1a399cc..0933125 100644 --- a/src/Commands/KeysCheckerCommand.php +++ b/src/Commands/KeysCheckerCommand.php @@ -1,20 +1,22 @@ getEnvs(); - $ignoredFiles = config(key: 'env-keys-checker.ignore_files', default: []); + $ignoredFiles = $this->getFilesToIgnore(); $autoAddOption = $this->option(key: 'auto-add'); $autoAddAvailableOptions = ['ask', 'auto', 'none']; @@ -40,7 +42,7 @@ public function handle(GetKeys $getKeys, CheckKeys $checkKeys, AddKeys $addKeys) return self::FAILURE; } - if (empty($envFiles)) { + if ($envFiles === []) { if (! $this->option(key: 'no-display')) { $this->showFailureInfo(message: 'No .env files found.'); } @@ -48,11 +50,9 @@ public function handle(GetKeys $getKeys, CheckKeys $checkKeys, AddKeys $addKeys) return self::FAILURE; } - $envFiles = collect(value: $envFiles)->filter(callback: function ($file) use ($ignoredFiles) { - return ! in_array(needle: basename($file), haystack: $ignoredFiles); - })->toArray(); + $envFiles = $filterFiles->handle(envFiles: $envFiles, ignoredFiles: $ignoredFiles); - if (empty($envFiles)) { + if ($envFiles === []) { if (! $this->option(key: 'no-display')) { $this->showFailureInfo(message: 'No .env files found.'); } @@ -117,13 +117,11 @@ private function showMissingKeysTable(Collection $missingKeys): void { table( headers: ['Line', 'Key', 'Is missing in'], - rows: $missingKeys->map(callback: function ($missingKey) { - return [ - $missingKey['line'], - $missingKey['key'], - $missingKey['envFile'], - ]; - })->toArray() + rows: $missingKeys->map(callback: fn ($missingKey): array => [ + $missingKey['line'], + $missingKey['key'], + $missingKey['envFile'], + ])->toArray() ); } } diff --git a/src/Concerns/HelperFunctions.php b/src/Concerns/HelperFunctions.php index 6748a79..72b6efd 100644 --- a/src/Concerns/HelperFunctions.php +++ b/src/Concerns/HelperFunctions.php @@ -1,5 +1,7 @@ expect(['dd', 'dump', 'ray']) ->each->not->toBeUsed(); diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php index 5d36321..f9c207b 100644 --- a/tests/ExampleTest.php +++ b/tests/ExampleTest.php @@ -1,5 +1,7 @@ toBeTrue(); }); diff --git a/tests/LaravelEnvKeysCheckerCommandTest.php b/tests/LaravelEnvKeysCheckerCommandTest.php index 009899a..73ac4de 100644 --- a/tests/LaravelEnvKeysCheckerCommandTest.php +++ b/tests/LaravelEnvKeysCheckerCommandTest.php @@ -1,6 +1,8 @@ artisan('env:keys-check --auto-add=none') ->assertExitCode(0); }); diff --git a/tests/Pest.php b/tests/Pest.php index d880183..f0a7fb2 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,5 +1,7 @@ in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php index 2477fc4..ef28bd3 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,26 +5,22 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Msamgan\LaravelEnvKeysChecker\LaravelEnvKeysCheckerServiceProvider; use Orchestra\Testbench\TestCase as Orchestra; +use Override; class TestCase extends Orchestra { + #[Override] protected function setUp(): void { parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Msamgan\\LaravelEnvKeysChecker\\Database\\Factories\\' . class_basename($modelName) . 'Factory' + fn (string $modelName): string => 'Msamgan\\LaravelEnvKeysChecker\\Database\\Factories\\' . class_basename($modelName) . 'Factory' ); } - protected function getPackageProviders($app) - { - return [ - LaravelEnvKeysCheckerServiceProvider::class, - ]; - } - - public function getEnvironmentSetUp($app) + #[Override] + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); @@ -33,4 +29,12 @@ public function getEnvironmentSetUp($app) $migration->up(); */ } + + #[Override] + protected function getPackageProviders($app) + { + return [ + LaravelEnvKeysCheckerServiceProvider::class, + ]; + } } diff --git a/tlint.json b/tlint.json new file mode 100644 index 0000000..9c53e11 --- /dev/null +++ b/tlint.json @@ -0,0 +1,3 @@ +{ + "disabled": ["QualifiedNamesOnlyForClassName", "RemoveLeadingSlashNamespaces"] +}