diff --git a/src/Console/CreateProviderCommand.php b/src/Console/CreateProviderCommand.php new file mode 100644 index 00000000..b81831ba --- /dev/null +++ b/src/Console/CreateProviderCommand.php @@ -0,0 +1,203 @@ +argument('provider'); + + if (in_array($provider, array_keys(config('services')))) { + warning("A service configuration already exists for $provider."); + + if (!confirm(label: 'Do you want to overwrite it?', default: false)) { + return self::INVALID; + } + } + + $this->addEnvironmentVariables(); + $this->addServicesToConfig(); + + return self::SUCCESS; + } + + /** + * Prompt for missing input arguments using the returned questions. + */ + protected function promptForMissingArgumentsUsing(): array + { + return [ + 'provider' => fn() => search( + label: 'Which provider would you like to create a configuration for?', + options: fn(string $search) => array_values(array_filter( + array_diff(Providers::all(), config('socialstream.providers')), + fn($choice) => str_contains(strtolower($choice), strtolower($search)) + )), + placeholder: 'Search...', + scroll: 10, + ), + 'client' => fn() => text( + label: 'Client ID?', + required: true, + ), + 'secret' => fn() => text( + label: 'Client Secret', + required: true, + ), + ]; + } + + private function addEnvironmentVariables(): void + { + $provider = Str::of($this->argument('provider'))->replace('-', '_')->upper()->toString(); + + $clientIdKey = $provider . '_CLIENT_ID'; + $clientSecretKey = $provider . '_CLIENT_SECRET'; + $redirectKey = $provider . '_REDIRECT'; + + table( + headers: ['Variable', 'Value'], + rows: [ + ['variable' => $clientIdKey, 'value' => $this->argument('client')], + ['variable' => $clientSecretKey, 'value' => $this->argument('secret')], + ['variable' => $redirectKey, 'value' => route('oauth.redirect', $this->argument('provider'))], + ], + ); + + if (! confirm('Do you want to add the environment variables to your .env file?')) { + return; + } + + $dotEnvContents = file_get_contents( + filename: base_path('.env.example') + ); + + if ( + str_contains(haystack: $dotEnvContents, needle: $clientIdKey) || + str_contains(haystack: $dotEnvContents, needle: $clientSecretKey) + ) { + warning(message: 'Environment variables already exist for this provider.'); + + if (! confirm('Do you want to continue', required: true)) { + return; + }; + } + + $comment = Str::of($provider)->lower()->headline()->toString(); + + file_put_contents( + filename: base_path('.env'), + data: Str::of(string: $dotEnvContents) + ->append(PHP_EOL) + ->append("# $comment Credentials".PHP_EOL) + ->append("$clientIdKey=".$this->argument('client').PHP_EOL) + ->append("$clientSecretKey=".$this->argument('secret').PHP_EOL) + ->append("$redirectKey=".'"${APP_URL}/'.trim($this->buildRedirectPath(), '/').'"'.PHP_EOL) + ->toString(), + ); + + if (! confirm('Do you want to add the environment variables to your .env.example file?', required: true)) { + return; + } + + file_put_contents( + filename: base_path('.env.example'), + data: Str::of( + string: file_get_contents( + filename: base_path('.env.example') + ) + ) + ->append(PHP_EOL) + ->append("# $comment Credentials".PHP_EOL) + ->append("$clientIdKey=".PHP_EOL) + ->append("$clientSecretKey=".PHP_EOL) + ->append("$redirectKey=".PHP_EOL) + ->toString(), + ); + } + + private function addServicesToConfig(): void + { + $provider = $this->argument('provider'); + $envProvider = Str::of($this->argument('provider'))->replace('-', '_')->upper()->toString(); + + if (config("services.$provider")) { + \Laravel\Prompts\info("Config already set in services.$provider"); + + return; + } + + $search1 = << [ + 'client_id' => env("{$envProvider}_CLIENT_ID"), + 'client_secret' => env("{$envProvider}_CLIENT_SECRET"), + 'redirect' => env("{$envProvider}_REDIRECT"), + ], +]; +PHP; + + file_put_contents( + filename: config_path('services.php'), + data: Str::of( + string: file_get_contents( + filename: config_path('services.php'), + ) + ) + ->replace($search1, $search2) + ->replace( + search: $search2, + replace: $replace + ) + ->toString(), + ); + } + + private function buildRedirectPath(): string + { + return '/oauth/'.$this->argument('provider').'/callback'; + } +}