From d2f3d617f9b9977589aba0deb1fc23fc78ca4b49 Mon Sep 17 00:00:00 2001 From: Vic Luijkx Date: Tue, 16 Jan 2024 18:45:10 +0100 Subject: [PATCH] Improve DX using connections. (#159) * Fix date error on error widget * Improve plus icon alignment * Fix validation for eloquent redirects * Revert "Fix validation for eloquent redirects" This reverts commit dbff7f09612a542c0eb75675986e322d1cdd0272. * Do not use redirect connection for eloquent * Small improvements * Revert "Small improvements" This reverts commit 397cce2c588671a5018cd751f9bf5bca0c162061. * Split connections * Improve alignment plus icon on errors widget as well * Add back right-margins * Clearify migration names and use seperate publish tag * Update documentation for split connections * Allow a `default` config value to use laravel default connection * Fix styling * Fix heading indentation * Make quotes more consistent * Revert "Make quotes more consistent" This reverts commit 17c736552b53b6c1537973c9472ef75771d10730. * Small text improvements * Use correct migration names * Remove outdated informatiion. People can read the up-to-date documentation instead. * Capitalize `Laravel` * Text improvement * Fix typo * Rename database from `errors` to `redirect` if needed * Fix tests * Add backwards compatibility for `connection` configuration * Improve backward compatibility * Fix styling * Use singular version which reads better * Improve readability * Code style fix --------- Co-authored-by: vluijkx --- DOCUMENTATION.md | 36 ++--- README.md | 20 +-- config/redirect.php | 25 ++-- .../create_eloquent_redirect_table.php.stub | 30 ----- ... => create_redirect_error_tables.php.stub} | 2 +- .../create_redirect_redirects_table.php.stub | 28 ++++ src/Data/Error.php | 10 +- src/Data/Hit.php | 10 +- src/Eloquent/Redirects/RedirectModel.php | 14 +- src/RedirectServiceProvider.php | 123 ++++++++++++++---- tests/TestCase.php | 4 +- 11 files changed, 192 insertions(+), 110 deletions(-) delete mode 100644 database/migrations/create_eloquent_redirect_table.php.stub rename database/migrations/{create_redirect_tables.php.stub => create_redirect_error_tables.php.stub} (95%) create mode 100644 database/migrations/create_redirect_redirects_table.php.stub diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 876045c..af1d2f9 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -44,7 +44,7 @@ Widgets can be added to the dashboard by modifying the widgets array in the `con ```php // config/statamic/cp.php - + 'widgets' => [ [ 'type' => 'errors', @@ -58,44 +58,46 @@ Widgets can be added to the dashboard by modifying the widgets array in the `con Like the default widgets of Statamic, you can also configure `title`& `width` of the widgets. -### Logging errors +## Logging errors By default, Statamic Redirect will create error logs, you can disable this by setting the `log_errors` config value to `false`. -### Logging individual hits +## Logging individual hits By default, Statamic Redirect will also keep individual hits for each error, you can disable this by setting the `log_hits` config value to `false`. -### Create entry redirects +## Create entry redirects By default, Statamic Redirect will create redirects when the URI of an entry changes. You can disable this by setting the `create_entry_redirects` config value to `false`. -### Deleting entry conflicting redirects +## Deleting entry conflicting redirects By default, Statamic Redirect will delete redirects when a saved entry's URI conflicts with the redirect. You can disable this by setting the `delete_conflicting_redirects` config value to `false`. -### Cleaning errors +## Cleaning errors The amount of errors can grow quickly, Statamic Redirect includes a scheduled command that by default cleans up errors older than 1 month. You can disable the cleaning by setting the `clean_errors` config value to `false`. Or change the date range by changing the `clean_older_than` config value. This accepts a value that is parsed by PHP's [createfromdatestring](http://php.net/manual/en/dateinterval.createfromdatestring.php) function. -> Make sure your [Schedule](https://laravel.com/docs/8.x/scheduling#introduction) is running for error cleaning to work. +> Make sure your [Schedule](https://laravel.com/docs/8.x/scheduling#introduction) is running for error cleaning to work. -### Different storage +## Different storage -If you want to use a different storage method for the Errors or Redirects, you can change them in the config file. +If you want to use a different storage method for errors or redirects, change them in the config file. -These should implement `\Rias\StatamicRedirect\Repositories\ErrorRepository` and `\Rias\StatamicRedirect\Repositories\RedirectRepository` respectively. +### Errors -In the future this addon will come with some extra Repositories by default, without a need to code your own. +By default, errors are stored using the built-in `redirect-sqlite` connection. Picking another connection can be useful when logging a lot of errors & hits. To do this, change the `error_connection` config value. Provide `default` to use the default Laravel connection. -You can switch the storing & retrieving of Errors & Redirects to the Eloquent repositories provided, this can be useful if you're logging a lot of errors & hits. +> [!NOTE] +> When using a connection other than `redirect-sqlite`, make sure to publish (and run) the corresponding migration using `php artisan vendor:publish --tag="statamic-redirect-error-migrations"`. -```php -// config/statamic/redirect.php +### Redirects -'error_repository' => \Rias\StatamicRedirect\Eloquent\Errors\EloquentErrorRepository::class, +By default, errors are stored in the `content/redirects` folder. Update the `redirect_store` config value to use a different folder. -'redirect_repository' => \Rias\StatamicRedirect\Eloquent\Redirects\EloquentRedirectRepository::class, -``` +It is also possible to store your redirects in the database. To do this, change the `redirect_connection` config value. Provide `default` to use the default Laravel connection. + +> [!NOTE] +> When using a connection other than `stache` or `redirect-sqlite`, make sure to publish (and run) the corresponding migration using `php artisan vendor:publish --tag="statamic-redirect-redirect-migrations"`. diff --git a/README.md b/README.md index e074ce7..f49fc5f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Read more in [the documentation](https://statamic.com/addons/rias/redirect/docs) ## License -Redirect requires a license to be used while on a production site. +Redirect requires a license to be used while on a production site. You can purchase one at https://statamic.com/addons/rias/redirect. You may use Redirect without a license while developing locally. @@ -32,22 +32,4 @@ Require it using Composer. composer require rias/statamic-redirect ``` -Publish the assets: - -``` -php artisan vendor:publish --provider="Rias\StatamicRedirect\RedirectServiceProvider" -``` - -## Using the Eloquent repositories - -You can switch the storing & retrieving of Errors & Redirects to the Eloquent repositories provided, this can be useful if you're logging a lot of errors & hits. - -```php -// config/statamic/redirect.php - -'error_repository' => \Rias\StatamicRedirect\Eloquent\Errors\EloquentErrorRepository::class, - -'redirect_repository' => \Rias\StatamicRedirect\Eloquent\Redirects\EloquentRedirectRepository::class, -``` - Brought to you by [Rias](https://rias.be) diff --git a/config/redirect.php b/config/redirect.php index 385f8f6..29d1b7d 100644 --- a/config/redirect.php +++ b/config/redirect.php @@ -51,23 +51,30 @@ 'keep_unique_errors' => 1000, /* - * The database connection redirect should use to store errors - * by default this is the included 'redirect' connection - * that uses an sqlite database in storage. + * The database connection used to store errors. By default + * this is the included 'redirect-sqlite'. Use + * 'default' to use the Laravel default. */ - 'connection' => 'redirect', + 'error_connection' => env('REDIRECT_ERROR_CONNECTION', 'redirect-sqlite'), /* - * Customize where on filesystem the redirects are being stored + * The database connection used to store redirects. By + * default this is the included 'stache' connection. + * Use 'default' to use the Laravel default. + */ + 'redirect_connection' => env('REDIRECT_REDIRECT_CONNECTION', 'stache'), + + /* + * Customize where on filesystem the redirects are being stored in stache. * Useful when using a non-conventional setup where data should * not be inside the usual content/redirects folder */ 'redirect_store' => base_path('content/redirects'), - + /* * Customise the redirect repository you want to use for data - * storage. Change to \Rias\StatamicRedirect\Eloquent\Redirects\RedirectRepository::class - * for eloquent storage, or create your own custom repository + * storage. Provide null to automaticly use a repository + * based on the 'redirect_connection'. */ - 'redirect_repository' => \Rias\StatamicRedirect\Stache\Redirects\RedirectRepository::class, + 'redirect_repository' => null, ]; diff --git a/database/migrations/create_eloquent_redirect_table.php.stub b/database/migrations/create_eloquent_redirect_table.php.stub deleted file mode 100644 index e718719..0000000 --- a/database/migrations/create_eloquent_redirect_table.php.stub +++ /dev/null @@ -1,30 +0,0 @@ -create('redirects', function (Blueprint $table): void { - $table->uuid('id')->unique()->index(); - $table->string('source')->index(); - $table->string('destination'); - $table->char('match_type', 10); - $table->char('type', 10); - $table->string('site')->index(); - $table->integer('order')->nullable(); - $table->boolean('enabled'); - $table->timestamps(); - }); - } - - public function down() - { - Schema::connection(config('statamic.redirect.connection', 'redirect')) - ->dropIfExists('redirects'); - } -} diff --git a/database/migrations/create_redirect_tables.php.stub b/database/migrations/create_redirect_error_tables.php.stub similarity index 95% rename from database/migrations/create_redirect_tables.php.stub rename to database/migrations/create_redirect_error_tables.php.stub index 3011600..f4847d5 100644 --- a/database/migrations/create_redirect_tables.php.stub +++ b/database/migrations/create_redirect_error_tables.php.stub @@ -5,7 +5,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Rias\StatamicRedirect\Data\Error; -class CreateRedirectTables extends Migration +class CreateRedirectErrorTables extends Migration { public function up() { diff --git a/database/migrations/create_redirect_redirects_table.php.stub b/database/migrations/create_redirect_redirects_table.php.stub new file mode 100644 index 0000000..addd339 --- /dev/null +++ b/database/migrations/create_redirect_redirects_table.php.stub @@ -0,0 +1,28 @@ +uuid('id')->unique()->index(); + $table->string('source')->index(); + $table->string('destination'); + $table->char('match_type', 10); + $table->char('type', 10); + $table->string('site')->index(); + $table->integer('order')->nullable(); + $table->boolean('enabled'); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('redirects'); + } +} diff --git a/src/Data/Error.php b/src/Data/Error.php index 04e0a3e..765f388 100644 --- a/src/Data/Error.php +++ b/src/Data/Error.php @@ -19,7 +19,15 @@ class Error extends Model public function getConnectionName() { - return config('statamic.redirect.connection', 'redirect'); + if (config('statamic.redirect.connection') !== null) { + return config('statamic.redirect.connection'); + } + + if (config('statamic.redirect.error_connection') === 'default') { + return config('database.default'); + } + + return config('statamic.redirect.error_connection', 'redirect-sqlite'); } protected static function booted() diff --git a/src/Data/Hit.php b/src/Data/Hit.php index 1017915..5c8d6a7 100644 --- a/src/Data/Hit.php +++ b/src/Data/Hit.php @@ -17,6 +17,14 @@ class Hit extends Model public function getConnectionName() { - return config('statamic.redirect.connection', 'redirect'); + if (config('statamic.redirect.connection') !== null) { + return config('statamic.redirect.connection'); + } + + if (config('statamic.redirect.error_connection') === 'default') { + return config('database.default'); + } + + return config('statamic.redirect.error_connection', 'redirect-sqlite'); } } diff --git a/src/Eloquent/Redirects/RedirectModel.php b/src/Eloquent/Redirects/RedirectModel.php index 0b29c02..7007431 100644 --- a/src/Eloquent/Redirects/RedirectModel.php +++ b/src/Eloquent/Redirects/RedirectModel.php @@ -8,15 +8,23 @@ class RedirectModel extends Model { use HasUuids; - + protected $guarded = []; protected $casts = []; - + protected $table = 'redirects'; public function getConnectionName() { - return config('statamic.redirect.connection', 'redirect'); + if (config('statamic.redirect.connection') !== null) { + return config('statamic.redirect.connection'); + } + + if (config('statamic.redirect.redirect_connection') === 'default') { + return config('database.default'); + } + + return config('statamic.redirect.redirect_connection', 'redirect-sqlite'); } } diff --git a/src/RedirectServiceProvider.php b/src/RedirectServiceProvider.php index 5913f2f..5d3cb66 100644 --- a/src/RedirectServiceProvider.php +++ b/src/RedirectServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Schema; use Rias\StatamicRedirect\Commands\CleanErrorsCommand; use Rias\StatamicRedirect\Contracts\RedirectRepository; +use Rias\StatamicRedirect\Eloquent\Redirects\RedirectRepository as EloquentRedirectRepository; use Rias\StatamicRedirect\Events\RedirectSaved; use Rias\StatamicRedirect\Http\Filters\ErrorHandled; use Rias\StatamicRedirect\Http\Filters\MatchType; @@ -16,6 +17,7 @@ use Rias\StatamicRedirect\Http\Middleware\HandleNotFound; use Rias\StatamicRedirect\Listeners\CacheOldUri; use Rias\StatamicRedirect\Listeners\CreateRedirect; +use Rias\StatamicRedirect\Stache\Redirects\RedirectRepository as StacheRedirectRepository; use Rias\StatamicRedirect\Stache\Redirects\RedirectStore; use Rias\StatamicRedirect\UpdateScripts\AddHitsCount; use Rias\StatamicRedirect\UpdateScripts\ClearErrors; @@ -72,7 +74,7 @@ public function register() $this->registerAddonConfig(); $this->app->singleton(RedirectRepository::class, function () { - $class = config('statamic.redirect.redirect_repository'); + $class = $this->getRedirectRepository(); return new $class($this->app['stache']); }); @@ -86,20 +88,6 @@ public function boot() CleanErrorsCommand::class, ]); - if ($this->app->runningInConsole()) { - if (! class_exists('CreateRedirectTables')) { - $this->publishes([ - __DIR__ . '/../database/migrations/create_redirect_tables.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_redirect_tables.php'), - ], 'migrations'); - } - - if (! class_exists('CreateEloquentRedirectTable')) { - $this->publishes([ - __DIR__ . '/../database/migrations/create_eloquent_redirect_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_eloquent_redirect_table.php'), - ], 'redirect-eloquent-migrations'); - } - } - Statamic::booted(function () { $router = $this->app->make(Router::class); $router->prependMiddlewareToGroup('statamic.web', HandleNotFound::class); @@ -121,6 +109,31 @@ public function boot() ->bootDatabase() ->bootPermissions(); }); + + if (! $this->app->runningInConsole()) { + return; + } + + $this->publishes([ + __DIR__ . '/../database/migrations/create_redirect_error_tables.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_redirect_error_tables.php'), + ], 'statamic-redirect-error-migrations'); + + $this->publishes([ + __DIR__ . '/../database/migrations/create_redirect_redirects_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_redirect_redirects_table.php'), + ], 'statamic-redirect-redirect-migrations'); + } + + protected function getRedirectRepository() + { + if (config('statamic.redirect.redirect_repository') !== null) { + return config('statamic.redirect.redirect_repository'); + } + + if (config('statamic.redirect.redirect_connection') !== 'stache') { + return EloquentRedirectRepository::class; + } + + return StacheRedirectRepository::class; } protected function bootAddonViews() @@ -173,7 +186,29 @@ protected function bootDatabase() File::ensureDirectoryExists(storage_path('redirect')); - $sqlitePath = storage_path('redirect/errors.sqlite'); + $sqlitePath = storage_path('redirect/redirect.sqlite'); + $this->ensureDatabaseExists($sqlitePath); + + app('config')->set('database.connections.redirect-sqlite', [ + 'driver' => 'sqlite', + 'database' => $sqlitePath, + ]); + + $this->bootDatabaseForErrors(); + $this->bootDatabaseForRedirects(); + + return $this; + } + + protected function ensureDatabaseExists($sqlitePath) + { + $oldSqlitePath = storage_path('redirect/errors.sqlite'); + + if (! file_exists($sqlitePath) && file_exists($oldSqlitePath)) { + File::move($oldSqlitePath, $sqlitePath); + + return; + } if (! file_exists($sqlitePath)) { File::put($sqlitePath, ''); @@ -183,25 +218,59 @@ protected function bootDatabase() File::put($gitIgnorePath, "*\n!.gitignore"); } } + } - app('config')->set('database.connections.redirect', [ - 'driver' => 'sqlite', - 'database' => $sqlitePath, - ]); + protected function bootDatabaseForErrors() + { + if ( + config('statamic.redirect.error_connection', 'redirect-sqlite') !== 'redirect-sqlite' && + ! $this->generalConnectionIsBuiltinSqlite() + ) { + return; + } + + if (Schema::connection('redirect-sqlite')->hasTable('errors')) { + return; + } - if (! Schema::connection(config('statamic.redirect.connection', 'redirect'))->hasTable('errors')) { - $defaultConnection = DB::getDefaultConnection(); + $defaultConnection = DB::getDefaultConnection(); + DB::setDefaultConnection('redirect-sqlite'); + require_once(__DIR__ . '/../database/migrations/create_redirect_error_tables.php.stub'); + (new \CreateRedirectErrorTables())->up(); + DB::setDefaultConnection($defaultConnection); + } + + protected function bootDatabaseForRedirects() + { + if ( + config('statamic.redirect.redirect_connection', 'stache') !== 'redirect-sqlite' && + ! $this->generalConnectionIsBuiltinSqlite() + ) { + return; + } - DB::setDefaultConnection(config('statamic.redirect.connection', 'redirect')); + if (Schema::connection('redirect-sqlite')->hasTable('redirects')) { + return; + } - require_once(__DIR__ . '/../database/migrations/create_redirect_tables.php.stub'); + $defaultConnection = DB::getDefaultConnection(); + DB::setDefaultConnection('redirect-sqlite'); + require_once(__DIR__ . '/../database/migrations/create_redirect_redirects_table.php.stub'); + (new \CreateRedirectRedirectsTable())->up(); + DB::setDefaultConnection($defaultConnection); + } - (new \CreateRedirectTables())->up(); + protected function generalConnectionIsBuiltinSqlite() + { + if (config('statamic.redirect.connection') === 'redirect-sqlite') { + return true; + } - DB::setDefaultConnection($defaultConnection); + if (config('statamic.redirect.connection') === 'redirect') { + return true; } - return $this; + return false; } protected function registerAddonConfig() diff --git a/tests/TestCase.php b/tests/TestCase.php index b7c4ecb..669fd31 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -92,8 +92,8 @@ protected function defineDatabaseMigrations(): void { $this->artisan('migrate', ['--database' => 'testing']); - include_once __DIR__ . '/../database/migrations/create_redirect_tables.php.stub'; - (new \CreateRedirectTables())->up(); + include_once __DIR__ . '/../database/migrations/create_redirect_error_tables.php.stub'; + (new \CreateRedirectErrorTables())->up(); } /**