diff --git a/composer.json b/composer.json index ed2f79bd..12670b1c 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "illuminate/contracts": "^10.0|^11.0", "illuminate/http": "^10.0|^11.0", "illuminate/support": "^10.0|^11.0", + "laravel/prompts": "^0.1.15", "pusher/pusher-php-server": "^7.2", "ratchet/rfc6455": "^0.3.1", "react/socket": "^1.14", diff --git a/src/Console/Commands/InstallCommand.php b/src/Console/Commands/InstallCommand.php new file mode 100644 index 00000000..519c4963 --- /dev/null +++ b/src/Console/Commands/InstallCommand.php @@ -0,0 +1,152 @@ +addEnviromentVariables(); + $this->publishConfiguration(); + $this->enableBroadcasting(); + $this->updateBroadcastingDriver(); + + $this->components->info('Reverb installed successfully.'); + } + + /** + * Adds the Reverb configuration to the environment. + */ + protected function addEnviromentVariables(): void + { + if (File::missing($env = app()->environmentFile())) { + return; + } + + $contents = File::get($env); + $appId = random_int(100000, 999999); + $appKey = Str::lower(Str::random(20)); + $appSecret = Str::lower(Str::random(20)); + + $variables = Arr::where([ + 'REVERB_APP_ID' => "REVERB_APP_ID={$appId}", + 'REVERB_APP_KEY' => "REVERB_APP_KEY={$appKey}", + 'REVERB_APP_SECRET' => "REVERB_APP_SECRET={$appSecret}", + 'REVERB_HOST' => 'REVERB_HOST="0.0.0.0"', + 'REVERB_PORT' => 'REVERB_PORT=8080', + 'REVERB_SCHEME' => 'REVERB_SCHEME=http', + 'REVERB_NEW_LINE' => null, + 'VITE_REVERB_APP_KEY' => 'VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"', + 'VITE_REVERB_HOST' => 'VITE_REVERB_HOST="${REVERB_HOST}"', + 'VITE_REVERB_PORT' => 'VITE_REVERB_PORT="${REVERB_PORT}"', + 'VITE_REVERB_SCHEME' => 'VITE_REVERB_SCHEME="${REVERB_SCHEME}"', + ], function ($value, $key) use ($contents) { + return ! Str::contains($contents, PHP_EOL.$key); + }); + + $variables = trim(implode(PHP_EOL, $variables)); + + if ($variables === '') { + return; + } + + File::append( + $env, + Str::endsWith($contents, PHP_EOL) ? PHP_EOL.$variables.PHP_EOL : PHP_EOL.PHP_EOL.$variables.PHP_EOL, + ); + } + + /** + * Publishes the Reverb configuration file. + */ + protected function publishConfiguration(): void + { + $this->callSilently('vendor:publish', [ + '--provider' => 'Laravel\Reverb\ReverbServiceProvider', + '--tag' => 'reverb-config', + ]); + } + + /** + * Enable the Laravel broadcasting functionality. + */ + protected function enableBroadcasting(): void + { + if (File::exists(base_path('routes/channels.php'))) { + return; + } + + $enable = confirm('Would you like to enable event broadcasting?', default: true); + + if (! $enable) { + return; + } + + if (version_compare($this->laravel->version(), '11.0', '<')) { + $this->enableBroadcastServiceProvider(); + + return; + } + + $this->callSilently('install:broadcasting'); + } + + /** + * Uncomment the BroadcastServiceProvider in the application configuration. + */ + protected function enableBroadcastServiceProvider(): void + { + $config = File::get(app()->configPath('app.php')); + + if (Str::contains($config, '// App\Providers\BroadcastServiceProvider::class')) { + File::replaceInFile( + '// App\Providers\BroadcastServiceProvider::class', + 'App\Providers\BroadcastServiceProvider::class', + app()->configPath('app.php'), + ); + } + } + + /** + * Update the configured broadcasting driver. + */ + protected function updateBroadcastingDriver(): void + { + $enable = confirm('Would you like to enable the Reverb broadcasting driver?', default: true); + + if (! $enable || File::missing($env = app()->environmentFile())) { + return; + } + + File::put( + $env, + Str::of(File::get($env))->replaceMatches('/(BROADCAST_(?:DRIVER|CONNECTION))=\w*/', function (array $matches) { + return $matches[1].'=reverb'; + }) + ); + } +} diff --git a/src/ReverbServiceProvider.php b/src/ReverbServiceProvider.php index f51afb2b..dac8c97e 100644 --- a/src/ReverbServiceProvider.php +++ b/src/ReverbServiceProvider.php @@ -4,6 +4,7 @@ use Illuminate\Foundation\Application; use Illuminate\Support\ServiceProvider; +use Laravel\Reverb\Console\Commands\InstallCommand; use Laravel\Reverb\Contracts\Logger; use Laravel\Reverb\Loggers\NullLogger; use Laravel\Reverb\Pulse\Reverb; @@ -33,6 +34,8 @@ public function register(): void public function boot(): void { if ($this->app->runningInConsole()) { + $this->commands(InstallCommand::class); + $this->publishes([ __DIR__.'/../config/reverb.php' => config_path('reverb.php'), ], ['reverb', 'reverb-config']);