diff --git a/src/Actions/AddKeys.php b/src/Actions/AddKeys.php new file mode 100644 index 0000000..c9b134d --- /dev/null +++ b/src/Actions/AddKeys.php @@ -0,0 +1,43 @@ +each(function ($missingKey) { + $filePath = base_path($missingKey['envFile']); + $envContent = file($filePath); + + $lineDiff = count($envContent) - $missingKey['line']; + if ($lineDiff < 0) { + $envContent = $this->appendEmptyLines(file: $filePath, numberOfLines: abs($lineDiff)); + } + + array_splice( + $envContent, $missingKey['line'] - 1, 0, $missingKey['key'] . '=""' . PHP_EOL + ); + + if ($missingKey['is_next_line_empty']) { + array_splice($envContent, $missingKey['line'], 0, PHP_EOL); + } + + file_put_contents($filePath, $envContent); + }); + } + + private function appendEmptyLines(string $file, int $numberOfLines = 1): array + { + $envContent = file($file); + $lastLine = count($envContent); + + for ($i = 0; $i < $numberOfLines; $i++) { + array_splice($envContent, $lastLine, 0, PHP_EOL); + } + + return $envContent; + } +} diff --git a/src/Actions/CheckKeys.php b/src/Actions/CheckKeys.php new file mode 100644 index 0000000..bce0d7a --- /dev/null +++ b/src/Actions/CheckKeys.php @@ -0,0 +1,32 @@ +each(function ($envFile) use ($keyData, $missingKeys) { + $envContent = file($envFile); + $keyExists = false; + + foreach ($envContent as $line) { + if (str_starts_with($line, $keyData['key'])) { + $keyExists = true; + break; + } + } + + if (! $keyExists) { + $missingKeys->push([ + 'line' => $keyData['line'], + 'key' => $keyData['key'], + 'is_next_line_empty' => $keyData['is_next_line_empty'], + 'envFile' => basename($envFile), + ]); + } + }); + } +} diff --git a/src/Actions/GetKeys.php b/src/Actions/GetKeys.php new file mode 100644 index 0000000..edfa7ac --- /dev/null +++ b/src/Actions/GetKeys.php @@ -0,0 +1,36 @@ +map(function ($file) use ($ignoredKeys) { + return collect(file($file))->map(function ($line, $index) use ($file) { + [$key] = explode('=', $line); + + return [ + 'key' => $key, + 'line' => $index + 1, + 'is_next_line_empty' => isset(file($file)[$index + 1]) && file($file)[$index + 1] === "\n", + ]; + })->filter(function ($item) { + return $item['key'] !== "\n" && ! str_starts_with($item['key'], '#'); + })->filter(function ($keyData) use ($ignoredKeys) { + return ! in_array($keyData['key'], $ignoredKeys); + }); + }) + ->flatten(1) + ->unique('key'); + } +} diff --git a/src/Commands/LaravelEnvKeysCheckerCommand.php b/src/Commands/LaravelEnvKeysCheckerCommand.php index 7be733d..ef277e9 100644 --- a/src/Commands/LaravelEnvKeysCheckerCommand.php +++ b/src/Commands/LaravelEnvKeysCheckerCommand.php @@ -3,18 +3,21 @@ namespace Msamgan\LaravelEnvKeysChecker\Commands; use Illuminate\Console\Command; -use Illuminate\Support\Collection; use function Laravel\Prompts\confirm; use function Laravel\Prompts\table; +use Msamgan\LaravelEnvKeysChecker\Actions\AddKeys; +use Msamgan\LaravelEnvKeysChecker\Actions\CheckKeys; +use Msamgan\LaravelEnvKeysChecker\Actions\GetKeys; + class LaravelEnvKeysCheckerCommand extends Command { public $signature = 'env:keys-check {--auto-add=}'; public $description = 'Check if all keys in .env file are present across all .env files. Like .env, .env.example, .env.testing, etc.'; - public function handle(): int + public function handle(GetKeys $getKeys, CheckKeys $checkKeys, AddKeys $addKeys): int { $envFiles = glob(base_path('.env*')); @@ -40,11 +43,11 @@ public function handle(): int return ! in_array(basename($file), $ignoredFiles); })->toArray(); - $keys = $this->getAllKeys($envFiles); + $keys = $getKeys->handle(files: $envFiles); $missingKeys = collect(); - $keys->each(function ($keyData) use ($envFiles, $missingKeys) { - $this->checkForKeyInFile($keyData, $envFiles, $missingKeys); + $keys->each(function ($keyData) use ($envFiles, $missingKeys, $checkKeys) { + $checkKeys->handle(keyData: $keyData, envFiles: $envFiles, missingKeys: $missingKeys); }); if ($missingKeys->isEmpty()) { @@ -55,87 +58,31 @@ public function handle(): int table( headers: ['Line', 'Key', 'Is missing in'], - rows: $missingKeys, + rows: $missingKeys->map(function ($missingKey) { + return [ + $missingKey['line'], + $missingKey['key'], + $missingKey['envFile'], + ]; + })->toArray() ); if ($autoAddStrategy === 'ask') { $confirmation = confirm('Do you want to add the missing keys to the .env files?'); if ($confirmation) { - $this->addKeysToFile($missingKeys, $envFiles); + $addKeys->handle(missingKeys: $missingKeys); } return self::SUCCESS; } if ($autoAddStrategy === 'auto') { - $this->addKeysToFile($missingKeys, $envFiles); + $addKeys->handle(missingKeys: $missingKeys); return self::SUCCESS; } return self::FAILURE; } - - private function getAllKeys($files): Collection - { - $ignoredKeys = config('env-keys-checker.ignore_keys', []); - - $files = is_array($files) - ? collect($files) - : collect([$files]); - - return $files - ->map(function ($file) use ($ignoredKeys) { - return collect(file($file))->map(function ($line, $index) { - [$key] = explode('=', $line); - - return [ - 'key' => $key, - 'line' => $index + 1, - ]; - })->filter(function ($item) { - return $item['key'] !== "\n" && ! str_starts_with($item['key'], '#'); - })->filter(function ($keyData) use ($ignoredKeys) { - return ! in_array($keyData['key'], $ignoredKeys); - }); - }) - ->flatten(1) - ->unique('key'); - } - - private function checkForKeyInFile($keyData, $envFiles, $missingKeys): void - { - collect($envFiles)->each(function ($envFile) use ($keyData, $missingKeys) { - $envContent = file($envFile); - $keyExists = false; - - foreach ($envContent as $line) { - if (str_starts_with($line, $keyData['key'])) { - $keyExists = true; - break; - } - } - - if (! $keyExists) { - $missingKeys->push([ - 'line' => $keyData['line'], - 'key' => $keyData['key'], - 'envFile' => basename($envFile), - ]); - } - }); - } - - private function addKeysToFile($missingKeys, array $envFiles): void - { - $missingKeys->each(function ($missingKey) { - $filePath = base_path($missingKey['envFile']); - $envContent = file($filePath); - array_splice($envContent, $missingKey['line'] - 1, 0, $missingKey['key'] . '=""' . PHP_EOL); - file_put_contents($filePath, $envContent); - }); - - $this->info('=> Missing keys added to all .env files.'); - } }