From acd5e18168327092176c539c9540c329c0b0594e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Mon, 2 Sep 2024 15:14:56 +0200 Subject: [PATCH 1/6] wip --- database/factories/SettingFactory.php | 26 ++++++++++ ...9_02_111321_create_root_settings_table.php | 29 +++++++++++ routes/web.php | 5 ++ src/Http/Controllers/SettingController.php | 26 ++++++++++ src/Interfaces/Models/Setting.php | 8 ++++ src/Interfaces/Settings/Registry.php | 8 ++++ src/Interfaces/Settings/Repository.php | 8 ++++ src/Models/Setting.php | 48 +++++++++++++++++++ src/Root.php | 7 +++ src/RootServiceProvider.php | 3 ++ src/Settings/Group.php | 30 ++++++++++++ src/Settings/Registry.php | 27 +++++++++++ src/Settings/Repository.php | 20 ++++++++ 13 files changed, 245 insertions(+) create mode 100644 database/factories/SettingFactory.php create mode 100644 database/migrations/2024_09_02_111321_create_root_settings_table.php create mode 100644 src/Http/Controllers/SettingController.php create mode 100644 src/Interfaces/Models/Setting.php create mode 100644 src/Interfaces/Settings/Registry.php create mode 100644 src/Interfaces/Settings/Repository.php create mode 100644 src/Models/Setting.php create mode 100644 src/Settings/Group.php create mode 100644 src/Settings/Registry.php create mode 100644 src/Settings/Repository.php diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php new file mode 100644 index 00000000..2f60e75f --- /dev/null +++ b/database/factories/SettingFactory.php @@ -0,0 +1,26 @@ + + */ + protected $model = Setting::class; + + /** + * Define the model's default state. + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2024_09_02_111321_create_root_settings_table.php b/database/migrations/2024_09_02_111321_create_root_settings_table.php new file mode 100644 index 00000000..407de160 --- /dev/null +++ b/database/migrations/2024_09_02_111321_create_root_settings_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('key')->unique(); + $table->text('value')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('root_settings'); + } +}; diff --git a/routes/web.php b/routes/web.php index 9c884374..53c9c9ce 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,7 @@ use Cone\Root\Http\Controllers\DashboardController; use Cone\Root\Http\Controllers\DownloadController; use Cone\Root\Http\Controllers\ResourceController; +use Cone\Root\Http\Controllers\SettingController; use Illuminate\Support\Facades\Route; // Dashboard @@ -11,6 +12,10 @@ // Download Route::get('/download/{medium:uuid}', DownloadController::class)->name('download'); +// Settings +Route::get('/settings/{group}', [SettingController::class, 'show'])->name('settings.show'); +Route::patch('/settings/{group}', [SettingController::class, 'update'])->name('settings.update'); + // Resource Route::get('/{resource}', [ResourceController::class, 'index'])->name('resource.index'); Route::get('/{resource}/create', [ResourceController::class, 'create'])->name('resource.create'); diff --git a/src/Http/Controllers/SettingController.php b/src/Http/Controllers/SettingController.php new file mode 100644 index 00000000..6504d6fa --- /dev/null +++ b/src/Http/Controllers/SettingController.php @@ -0,0 +1,26 @@ + + */ + protected $fillable = [ + 'key', + 'value', + ]; + + /** + * The table associated with the model. + * + * @var string + */ + protected $table = 'root_settings'; + + /** + * Get the proxied interface. + */ + public static function getProxiedInterface(): string + { + return Contract::class; + } + + /** + * Create a new factory instance for the model. + */ + protected static function newFactory(): SettingFactory + { + return SettingFactory::new(); + } +} diff --git a/src/Root.php b/src/Root.php index e37b570d..8d8d54b8 100644 --- a/src/Root.php +++ b/src/Root.php @@ -5,6 +5,7 @@ use Closure; use Cone\Root\Interfaces\Breadcrumbs\Registry as Breadcrumbs; use Cone\Root\Interfaces\Navigation\Registry as Navigation; +use Cone\Root\Interfaces\Settings\Registry as Settings; use Cone\Root\Models\User; use Cone\Root\Resources\Resources; use Cone\Root\Widgets\Widgets; @@ -55,6 +56,11 @@ class Root */ public readonly Breadcrumbs $breadcrumbs; + /** + * The settings instance. + */ + public readonly Settings $settings; + /** * The auth resolver. */ @@ -75,6 +81,7 @@ public function __construct(Application $app) $this->widgets = new Widgets; $this->navigation = $app->make(Navigation::class); $this->breadcrumbs = $app->make(Breadcrumbs::class); + $this->settings = $app->make(Settings::class); $this->timezone = $app['config']->get('app.timezone'); } diff --git a/src/RootServiceProvider.php b/src/RootServiceProvider.php index 3c32b339..0b6e4009 100644 --- a/src/RootServiceProvider.php +++ b/src/RootServiceProvider.php @@ -39,8 +39,11 @@ class RootServiceProvider extends ServiceProvider Interfaces\Models\Medium::class => Models\Medium::class, Interfaces\Models\Meta::class => Models\Meta::class, Interfaces\Models\Notification::class => Models\Notification::class, + Interfaces\Models\Setting::class => Models\Setting::class, Interfaces\Models\User::class => Models\User::class, Interfaces\Navigation\Registry::class => Navigation\Registry::class, + Interfaces\Settings\Registry::class => Settings\Registry::class, + Interfaces\Settings\Repository::class => Settings\Repository::class, ]; /** diff --git a/src/Settings/Group.php b/src/Settings/Group.php new file mode 100644 index 00000000..d7b7cf0e --- /dev/null +++ b/src/Settings/Group.php @@ -0,0 +1,30 @@ +repository = $repository; + } +} diff --git a/src/Settings/Repository.php b/src/Settings/Repository.php new file mode 100644 index 00000000..9846d725 --- /dev/null +++ b/src/Settings/Repository.php @@ -0,0 +1,20 @@ + Date: Thu, 10 Oct 2024 17:56:19 +0200 Subject: [PATCH 2/6] wip --- src/Casts/SettingValue.php | 42 +++++++++++++++++++++++++++++++++++++ src/Models/Setting.php | 11 ++++++++++ src/Settings/Group.php | 30 -------------------------- src/Settings/Registry.php | 5 ----- src/Settings/Repository.php | 29 +++++++++++++++++++++---- 5 files changed, 78 insertions(+), 39 deletions(-) create mode 100644 src/Casts/SettingValue.php delete mode 100644 src/Settings/Group.php diff --git a/src/Casts/SettingValue.php b/src/Casts/SettingValue.php new file mode 100644 index 00000000..bf2327d6 --- /dev/null +++ b/src/Casts/SettingValue.php @@ -0,0 +1,42 @@ +key = $key; + } + + /** + * Cast the given value. + * + * @param array $attributes + */ + public function get(Model $model, string $key, mixed $value, array $attributes): mixed + { + return $value; + } + + /** + * Prepare the given value for storage. + * + * @param array $attributes + */ + public function set(Model $model, string $key, mixed $value, array $attributes): mixed + { + return $value; + } +} diff --git a/src/Models/Setting.php b/src/Models/Setting.php index 6574735a..83ecb5b1 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -2,6 +2,7 @@ namespace Cone\Root\Models; +use Cone\Root\Casts\SettingValue; use Cone\Root\Database\Factories\SettingFactory; use Cone\Root\Interfaces\Models\Setting as Contract; use Cone\Root\Traits\InteractsWithProxy; @@ -45,4 +46,14 @@ protected static function newFactory(): SettingFactory { return SettingFactory::new(); } + + /** + * Get the attributes that should be cast. + */ + protected function casts(): array + { + return [ + 'value' => SettingValue::class.':'.$this->key, + ]; + } } diff --git a/src/Settings/Group.php b/src/Settings/Group.php deleted file mode 100644 index d7b7cf0e..00000000 --- a/src/Settings/Group.php +++ /dev/null @@ -1,30 +0,0 @@ - Date: Fri, 11 Oct 2024 08:32:17 +0200 Subject: [PATCH 3/6] wip --- src/Casts/SettingValue.php | 42 -------- src/Http/Controllers/SettingController.php | 26 ----- src/Models/Setting.php | 11 -- src/Settings/Repository.php | 113 ++++++++++++++++++--- 4 files changed, 100 insertions(+), 92 deletions(-) delete mode 100644 src/Casts/SettingValue.php delete mode 100644 src/Http/Controllers/SettingController.php diff --git a/src/Casts/SettingValue.php b/src/Casts/SettingValue.php deleted file mode 100644 index bf2327d6..00000000 --- a/src/Casts/SettingValue.php +++ /dev/null @@ -1,42 +0,0 @@ -key = $key; - } - - /** - * Cast the given value. - * - * @param array $attributes - */ - public function get(Model $model, string $key, mixed $value, array $attributes): mixed - { - return $value; - } - - /** - * Prepare the given value for storage. - * - * @param array $attributes - */ - public function set(Model $model, string $key, mixed $value, array $attributes): mixed - { - return $value; - } -} diff --git a/src/Http/Controllers/SettingController.php b/src/Http/Controllers/SettingController.php deleted file mode 100644 index 6504d6fa..00000000 --- a/src/Http/Controllers/SettingController.php +++ /dev/null @@ -1,26 +0,0 @@ - SettingValue::class.':'.$this->key, - ]; - } } diff --git a/src/Settings/Repository.php b/src/Settings/Repository.php index b0fb3026..a13df7e0 100644 --- a/src/Settings/Repository.php +++ b/src/Settings/Repository.php @@ -2,40 +2,127 @@ namespace Cone\Root\Settings; +use ArrayAccess; use Cone\Root\Interfaces\Settings\Repository as Contract; use Cone\Root\Models\Setting; +use Illuminate\Contracts\Support\Arrayable; -class Repository implements Contract +class Repository implements Arrayable, ArrayAccess, Contract { + /** + * The repository cache. + */ protected array $cache = []; - public function __construct() + /** + * Get the setting model. + */ + public function model(): Setting { - // + return Setting::proxy(); } - public function model(): Setting + /** + * Get the value for the given key. + */ + public function get(string $key, mixed $default = null, bool $fresh = false): mixed { - return Setting::proxy(); + if ($this->offsetExists($key) && ! $fresh) { + return $this->offsetGet($key); + } + + $model = $this->model()->newQuery()->firstWhere('key', '=', $key); + + if (! is_null($model)) { + $this->offsetSet($key, $model->value); + } + + return $this->cache[$key] ?? $default; + } + + /** + * Set the value for the given key. + */ + public function set(string $key, mixed $value): void + { + $model = $this->model()->newQuery()->updateOrCreate( + ['key' => $key], + ['value' => $value] + ); + + $this->offsetSet($key, $model->value); + } + + /** + * Delete the given keys. + */ + public function delete(string|array $keys): void + { + foreach ((array) $keys as $key) { + $this->offsetUnset($key); + } + + $this->model()->newQuery()->whereIn('key', (array) $keys)->delete(); + } + + /** + * Flush the cache. + */ + public function flush(): void + { + $this->cache = []; + } + + /** + * Convert the repository to an array. + */ + public function toArray(): array + { + return $this->cache; } - public function get() + /** + * Determine if an item exists at an offset. + * + * @param TKey $key + */ + public function offsetExists($key): bool { - // + return isset($this->cache[$key]); } - public function set() + /** + * Get an item at a given offset. + * + * @param TKey $key + */ + public function offsetGet($key): mixed { - // + return $this->cache[$key]; } - public function delete() + /** + * Set the item at a given offset. + * + * @param TKey|null $key + * @param TValue $value + */ + public function offsetSet($key, $value): void { - // + if (is_null($key)) { + $this->cache[] = $value; + } else { + $this->cache[$key] = $value; + } } - public function cast(string $key, string $type) + /** + * Unset the item at a given offset. + * + * @param TKey $key + */ + public function offsetUnset($key): void { - // + unset($this->cache[$key]); } } From d7dcfa4e068fdd56c53356c8b318c209fa61132b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Fri, 11 Oct 2024 08:41:24 +0200 Subject: [PATCH 4/6] wip --- src/Settings/Registry.php | 5 +++++ src/Settings/Repository.php | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Settings/Registry.php b/src/Settings/Registry.php index 2e52e547..22c6159c 100644 --- a/src/Settings/Registry.php +++ b/src/Settings/Registry.php @@ -19,4 +19,9 @@ public function __construct(Repository $repository) { $this->repository = $repository; } + + public function __call(string $name, array $arguments): mixed + { + return call_user_func_array([$this->repository, $name], $arguments); + } } diff --git a/src/Settings/Repository.php b/src/Settings/Repository.php index a13df7e0..e15e143a 100644 --- a/src/Settings/Repository.php +++ b/src/Settings/Repository.php @@ -43,7 +43,7 @@ public function get(string $key, mixed $default = null, bool $fresh = false): mi /** * Set the value for the given key. */ - public function set(string $key, mixed $value): void + public function set(string $key, mixed $value): mixed { $model = $this->model()->newQuery()->updateOrCreate( ['key' => $key], @@ -51,6 +51,8 @@ public function set(string $key, mixed $value): void ); $this->offsetSet($key, $model->value); + + return $this->offsetGet($key); } /** @@ -73,6 +75,14 @@ public function flush(): void $this->cache = []; } + /** + * Get all the settings. + */ + public function all(): array + { + return $this->toArray(); + } + /** * Convert the repository to an array. */ From ed3573440ec229b8c4f6ef5b7899d315b2e1d749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Fri, 11 Oct 2024 08:59:01 +0200 Subject: [PATCH 5/6] wip --- src/Models/Setting.php | 12 ++++++++ src/Settings/Registry.php | 3 ++ src/Settings/Repository.php | 60 ++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/Models/Setting.php b/src/Models/Setting.php index 6574735a..d6cd7fc5 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -45,4 +45,16 @@ protected static function newFactory(): SettingFactory { return SettingFactory::new(); } + + /** + * Cast the value attribute to the given type. + */ + public function castValue(?string $type = null): void + { + if (is_null($type)) { + unset($this->casts['value']); + } else { + $this->casts['value'] = $type; + } + } } diff --git a/src/Settings/Registry.php b/src/Settings/Registry.php index 22c6159c..63600bd6 100644 --- a/src/Settings/Registry.php +++ b/src/Settings/Registry.php @@ -20,6 +20,9 @@ public function __construct(Repository $repository) $this->repository = $repository; } + /** + * Dynamically call the given method. + */ public function __call(string $name, array $arguments): mixed { return call_user_func_array([$this->repository, $name], $arguments); diff --git a/src/Settings/Repository.php b/src/Settings/Repository.php index e15e143a..fea0572f 100644 --- a/src/Settings/Repository.php +++ b/src/Settings/Repository.php @@ -14,6 +14,11 @@ class Repository implements Arrayable, ArrayAccess, Contract */ protected array $cache = []; + /** + * The value casts. + */ + protected array $casts = []; + /** * Get the setting model. */ @@ -22,6 +27,48 @@ public function model(): Setting return Setting::proxy(); } + /** + * Set the value cast. + */ + public function cast(string $key, string $type): void + { + $this->casts[$key] = $type; + } + + /** + * Merge the casts. + */ + public function mergeCasts(array $casts): void + { + $this->casts = array_merge($this->casts, $casts); + } + + /** + * Remove the given casts. + */ + public function removeCasts(string|array $keys): void + { + foreach ((array) $keys as $key) { + unset($this->casts[$key]); + } + } + + /** + * Remove the given casts. + */ + public function clearCasts(): void + { + $this->casts = []; + } + + /** + * Get the value casts. + */ + public function getCasts(): array + { + return $this->casts; + } + /** * Get the value for the given key. */ @@ -34,6 +81,8 @@ public function get(string $key, mixed $default = null, bool $fresh = false): mi $model = $this->model()->newQuery()->firstWhere('key', '=', $key); if (! is_null($model)) { + $model->castValue($this->casts[$key] ?? null); + $this->offsetSet($key, $model->value); } @@ -45,10 +94,13 @@ public function get(string $key, mixed $default = null, bool $fresh = false): mi */ public function set(string $key, mixed $value): mixed { - $model = $this->model()->newQuery()->updateOrCreate( - ['key' => $key], - ['value' => $value] - ); + $model = $this->model()->newQuery()->firstOrNew(['key' => $key]); + + $model->castValue($this->casts[$key] ?? null); + + $model->fill(['value' => $value]); + + $model->save(); $this->offsetSet($key, $model->value); From 21ac4621c3230f9868bf6c6dc98f6e6b700ad596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Sun, 13 Oct 2024 15:53:53 +0200 Subject: [PATCH 6/6] settings --- database/factories/SettingFactory.php | 3 +- routes/web.php | 5 -- src/Interfaces/Settings/Registry.php | 5 +- src/Interfaces/Settings/Repository.php | 57 ++++++++++++++++++++- src/Models/Setting.php | 10 ++-- src/Settings/Registry.php | 8 +++ src/Settings/Repository.php | 33 +++++++++--- tests/Settings/SettingsTest.php | 70 ++++++++++++++++++++++++++ 8 files changed, 171 insertions(+), 20 deletions(-) create mode 100644 tests/Settings/SettingsTest.php diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php index 2f60e75f..69db050a 100644 --- a/database/factories/SettingFactory.php +++ b/database/factories/SettingFactory.php @@ -20,7 +20,8 @@ class SettingFactory extends Factory public function definition(): array { return [ - // + 'key' => $this->faker->slug(1), + 'value' => mt_rand(10, 1000), ]; } } diff --git a/routes/web.php b/routes/web.php index 53c9c9ce..9c884374 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,7 +3,6 @@ use Cone\Root\Http\Controllers\DashboardController; use Cone\Root\Http\Controllers\DownloadController; use Cone\Root\Http\Controllers\ResourceController; -use Cone\Root\Http\Controllers\SettingController; use Illuminate\Support\Facades\Route; // Dashboard @@ -12,10 +11,6 @@ // Download Route::get('/download/{medium:uuid}', DownloadController::class)->name('download'); -// Settings -Route::get('/settings/{group}', [SettingController::class, 'show'])->name('settings.show'); -Route::patch('/settings/{group}', [SettingController::class, 'update'])->name('settings.update'); - // Resource Route::get('/{resource}', [ResourceController::class, 'index'])->name('resource.index'); Route::get('/{resource}/create', [ResourceController::class, 'create'])->name('resource.create'); diff --git a/src/Interfaces/Settings/Registry.php b/src/Interfaces/Settings/Registry.php index 33b3ab10..ac10d0fc 100644 --- a/src/Interfaces/Settings/Registry.php +++ b/src/Interfaces/Settings/Registry.php @@ -4,5 +4,8 @@ interface Registry { - // + /** + * Get the repository instance. + */ + public function getRepository(): Repository; } diff --git a/src/Interfaces/Settings/Repository.php b/src/Interfaces/Settings/Repository.php index 2ece89dd..f616d6e3 100644 --- a/src/Interfaces/Settings/Repository.php +++ b/src/Interfaces/Settings/Repository.php @@ -2,7 +2,62 @@ namespace Cone\Root\Interfaces\Settings; +use Cone\Root\Models\Setting; + interface Repository { - // + /** + * Get the setting model. + */ + public function model(): Setting; + + /** + * Set the value cast. + */ + public function cast(string $key, string $type): void; + + /** + * Merge the casts. + */ + public function mergeCasts(array $casts): void; + + /** + * Remove the given casts. + */ + public function removeCasts(string|array $keys): void; + + /** + * Remove the given casts. + */ + public function clearCasts(): void; + + /** + * Get the value casts. + */ + public function getCasts(): array; + + /** + * Get the value for the given key. + */ + public function get(string $key, mixed $default = null, bool $fresh = false): mixed; + + /** + * Set the value for the given key. + */ + public function set(string $key, mixed $value): mixed; + + /** + * Delete the given keys. + */ + public function delete(string|array $keys): void; + + /** + * Flush the cache. + */ + public function flush(): void; + + /** + * Get all the settings. + */ + public function all(): array; } diff --git a/src/Models/Setting.php b/src/Models/Setting.php index d6cd7fc5..9d852f5f 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -49,12 +49,14 @@ protected static function newFactory(): SettingFactory /** * Cast the value attribute to the given type. */ - public function castValue(?string $type = null): void + public function castValue(?string $type = null): static { - if (is_null($type)) { - unset($this->casts['value']); - } else { + if (! is_null($type)) { $this->casts['value'] = $type; + } else { + unset($this->casts['value']); } + + return $this; } } diff --git a/src/Settings/Registry.php b/src/Settings/Registry.php index 63600bd6..39db241a 100644 --- a/src/Settings/Registry.php +++ b/src/Settings/Registry.php @@ -20,6 +20,14 @@ public function __construct(Repository $repository) $this->repository = $repository; } + /** + * Get the repository instance. + */ + public function getRepository(): Repository + { + return $this->repository; + } + /** * Dynamically call the given method. */ diff --git a/src/Settings/Repository.php b/src/Settings/Repository.php index fea0572f..018011b8 100644 --- a/src/Settings/Repository.php +++ b/src/Settings/Repository.php @@ -6,6 +6,7 @@ use Cone\Root\Interfaces\Settings\Repository as Contract; use Cone\Root\Models\Setting; use Illuminate\Contracts\Support\Arrayable; +use Illuminate\Database\Eloquent\Builder; class Repository implements Arrayable, ArrayAccess, Contract { @@ -27,6 +28,14 @@ public function model(): Setting return Setting::proxy(); } + /** + * Get the base query for the repository. + */ + public function query(): Builder + { + return $this->model()->newQuery(); + } + /** * Set the value cast. */ @@ -78,15 +87,23 @@ public function get(string $key, mixed $default = null, bool $fresh = false): mi return $this->offsetGet($key); } - $model = $this->model()->newQuery()->firstWhere('key', '=', $key); + return $this->refresh($key, $default); + } - if (! is_null($model)) { - $model->castValue($this->casts[$key] ?? null); + /** + * Refresh the given key. + */ + public function refresh(string $key, mixed $default = null): mixed + { + $model = $this->query()->firstWhere('key', '=', $key); - $this->offsetSet($key, $model->value); - } + $value = is_null($model) + ? $default + : $model->castValue($this->casts[$key] ?? null)->value; + + $this->offsetSet($key, $value); - return $this->cache[$key] ?? $default; + return $value; } /** @@ -94,7 +111,7 @@ public function get(string $key, mixed $default = null, bool $fresh = false): mi */ public function set(string $key, mixed $value): mixed { - $model = $this->model()->newQuery()->firstOrNew(['key' => $key]); + $model = $this->query()->firstOrNew(['key' => $key]); $model->castValue($this->casts[$key] ?? null); @@ -116,7 +133,7 @@ public function delete(string|array $keys): void $this->offsetUnset($key); } - $this->model()->newQuery()->whereIn('key', (array) $keys)->delete(); + $this->query()->whereIn('key', (array) $keys)->delete(); } /** diff --git a/tests/Settings/SettingsTest.php b/tests/Settings/SettingsTest.php new file mode 100644 index 00000000..03f03673 --- /dev/null +++ b/tests/Settings/SettingsTest.php @@ -0,0 +1,70 @@ +registry = new Registry(new Repository); + } + + public function test_setting_can_be_set(): void + { + $value = $this->registry->set('foo', 'bar'); + $this->assertSame('bar', $value); + + $this->assertDatabaseHas('root_settings', ['key' => 'foo', 'value' => 'bar']); + } + + public function test_setting_value_with_cast(): void + { + $this->registry->cast('ran_at', 'datetime'); + + $value = $this->registry->get('ran_at'); + $this->assertNull($value); + + $value = $this->registry->set('ran_at', $now = Date::now()); + $this->assertSame( + $now->__toString(), + $this->registry->query()->firstWhere('key', 'ran_at')->value + ); + + $this->assertSame( + $now->__toString(), + $this->registry->get('ran_at')->__toString() + ); + } + + public function test_setting_can_be_get(): void + { + $value = $this->registry->get('foo'); + $this->assertNull($value); + + $value = $this->registry->get('foo', 'bar'); + $this->assertSame('bar', $value); + } + + public function test_setting_can_be_deleted(): void + { + $value = $this->registry->set('foo', 'bar'); + $this->assertSame('bar', $value); + + $value = $this->registry->get('foo'); + $this->assertSame('bar', $value); + + $this->registry->delete('foo'); + $this->assertNull($this->registry->get('foo')); + + $this->assertDatabaseMissing('root_settings', ['key' => 'foo']); + } +}