From 4dd0df5824e59fb5cbd88ef55c453945abd5c705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=2E=20Nagy=20Gerg=C5=91?= Date: Sun, 1 Sep 2024 15:38:34 +0200 Subject: [PATCH] wip --- composer.lock | 128 +++++++++++----------- routes/web.php | 4 + src/Actions/Action.php | 25 ++++- src/Http/Controllers/OptionController.php | 19 ++++ src/Interfaces/Options/Registry.php | 18 +++ src/Models/Option.php | 2 +- src/Options/Group.php | 73 ++++++++++++ src/Options/Registry.php | 46 ++++++++ src/Root.php | 10 +- src/RootServiceProvider.php | 1 + 10 files changed, 255 insertions(+), 71 deletions(-) create mode 100644 src/Http/Controllers/OptionController.php create mode 100644 src/Interfaces/Options/Registry.php create mode 100644 src/Options/Group.php create mode 100644 src/Options/Registry.php diff --git a/composer.lock b/composer.lock index 07e76559..dd801f72 100644 --- a/composer.lock +++ b/composer.lock @@ -2982,16 +2982,16 @@ }, { "name": "symfony/console", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9" + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", - "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9", + "url": "https://api.github.com/repos/symfony/console/zipball/1eed7af6961d763e7832e874d7f9b21c3ea9c111", + "reference": "1eed7af6961d763e7832e874d7f9b21c3ea9c111", "shasum": "" }, "require": { @@ -3055,7 +3055,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.3" + "source": "https://github.com/symfony/console/tree/v7.1.4" }, "funding": [ { @@ -3071,7 +3071,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-15T22:48:53+00:00" }, { "name": "symfony/css-selector", @@ -3438,16 +3438,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca" + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/717c6329886f32dc65e27461f80f2a465412fdca", - "reference": "717c6329886f32dc65e27461f80f2a465412fdca", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", "shasum": "" }, "require": { @@ -3482,7 +3482,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.3" + "source": "https://github.com/symfony/finder/tree/v7.1.4" }, "funding": [ { @@ -3498,7 +3498,7 @@ "type": "tidelift" } ], - "time": "2024-07-24T07:08:44+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/http-foundation", @@ -3579,16 +3579,16 @@ }, { "name": "symfony/http-kernel", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186" + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/db9702f3a04cc471ec8c70e881825db26ac5f186", - "reference": "db9702f3a04cc471ec8c70e881825db26ac5f186", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6efcbd1b3f444f631c386504fc83eeca25963747", + "reference": "6efcbd1b3f444f631c386504fc83eeca25963747", "shasum": "" }, "require": { @@ -3673,7 +3673,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.4" }, "funding": [ { @@ -3689,7 +3689,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T14:58:15+00:00" + "time": "2024-08-30T17:02:28+00:00" }, { "name": "symfony/mailer", @@ -3773,16 +3773,16 @@ }, { "name": "symfony/mime", - "version": "v7.1.2", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc" + "reference": "ccaa6c2503db867f472a587291e764d6a1e58758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/26a00b85477e69a4bab63b66c5dce64f18b0cbfc", - "reference": "26a00b85477e69a4bab63b66c5dce64f18b0cbfc", + "url": "https://api.github.com/repos/symfony/mime/zipball/ccaa6c2503db867f472a587291e764d6a1e58758", + "reference": "ccaa6c2503db867f472a587291e764d6a1e58758", "shasum": "" }, "require": { @@ -3837,7 +3837,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.2" + "source": "https://github.com/symfony/mime/tree/v7.1.4" }, "funding": [ { @@ -3853,7 +3853,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T10:03:55+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4628,16 +4628,16 @@ }, { "name": "symfony/routing", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0" + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", - "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", + "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", "shasum": "" }, "require": { @@ -4689,7 +4689,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.3" + "source": "https://github.com/symfony/routing/tree/v7.1.4" }, "funding": [ { @@ -4705,7 +4705,7 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:10:24+00:00" + "time": "2024-08-29T08:16:25+00:00" }, { "name": "symfony/service-contracts", @@ -4792,16 +4792,16 @@ }, { "name": "symfony/string", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07" + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ea272a882be7f20cad58d5d78c215001617b7f07", - "reference": "ea272a882be7f20cad58d5d78c215001617b7f07", + "url": "https://api.github.com/repos/symfony/string/zipball/6cd670a6d968eaeb1c77c2e76091c45c56bc367b", + "reference": "6cd670a6d968eaeb1c77c2e76091c45c56bc367b", "shasum": "" }, "require": { @@ -4859,7 +4859,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.3" + "source": "https://github.com/symfony/string/tree/v7.1.4" }, "funding": [ { @@ -4875,7 +4875,7 @@ "type": "tidelift" } ], - "time": "2024-07-22T10:25:37+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/translation", @@ -5051,16 +5051,16 @@ }, { "name": "symfony/uid", - "version": "v7.1.1", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277" + "reference": "82177535395109075cdb45a70533aa3d7a521cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/bb59febeecc81528ff672fad5dab7f06db8c8277", - "reference": "bb59febeecc81528ff672fad5dab7f06db8c8277", + "url": "https://api.github.com/repos/symfony/uid/zipball/82177535395109075cdb45a70533aa3d7a521cdf", + "reference": "82177535395109075cdb45a70533aa3d7a521cdf", "shasum": "" }, "require": { @@ -5105,7 +5105,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.1" + "source": "https://github.com/symfony/uid/tree/v7.1.4" }, "funding": [ { @@ -5121,20 +5121,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-08-12T09:59:40+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.3", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f" + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/86af4617cca75a6e28598f49ae0690f3b9d4591f", - "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a5fa7481b199090964d6fd5dab6294d5a870c7aa", + "reference": "a5fa7481b199090964d6fd5dab6294d5a870c7aa", "shasum": "" }, "require": { @@ -5188,7 +5188,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.4" }, "funding": [ { @@ -5204,7 +5204,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:41:01+00:00" + "time": "2024-08-30T16:12:47+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6200,16 +6200,16 @@ }, { "name": "phpmyadmin/sql-parser", - "version": "5.9.1", + "version": "5.10.0", "source": { "type": "git", "url": "https://github.com/phpmyadmin/sql-parser.git", - "reference": "169a9f11f1957ea36607c9b29eac1b48679f1ecc" + "reference": "91d980ab76c3f152481e367f62b921adc38af451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/169a9f11f1957ea36607c9b29eac1b48679f1ecc", - "reference": "169a9f11f1957ea36607c9b29eac1b48679f1ecc", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/91d980ab76c3f152481e367f62b921adc38af451", + "reference": "91d980ab76c3f152481e367f62b921adc38af451", "shasum": "" }, "require": { @@ -6283,20 +6283,20 @@ "type": "other" } ], - "time": "2024-08-13T19:01:01+00:00" + "time": "2024-08-29T20:56:34+00:00" }, { "name": "phpstan/phpstan", - "version": "1.11.11", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" + "reference": "384af967d35b2162f69526c7276acadce534d0e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/384af967d35b2162f69526c7276acadce534d0e1", + "reference": "384af967d35b2162f69526c7276acadce534d0e1", "shasum": "" }, "require": { @@ -6341,7 +6341,7 @@ "type": "github" } ], - "time": "2024-08-19T14:37:29+00:00" + "time": "2024-08-27T09:18:05+00:00" }, { "name": "phpunit/php-code-coverage", @@ -6423,16 +6423,16 @@ }, { "name": "phpunit/php-file-iterator", - "version": "5.0.1", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6ed896bf50bbbfe4d504a33ed5886278c78e4a26", - "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { @@ -6472,7 +6472,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -6480,7 +6480,7 @@ "type": "github" } ], - "time": "2024-07-03T05:06:37+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", diff --git a/routes/web.php b/routes/web.php index 9c884374..6df70b7a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,6 +2,7 @@ use Cone\Root\Http\Controllers\DashboardController; use Cone\Root\Http\Controllers\DownloadController; +use Cone\Root\Http\Controllers\OptionController; use Cone\Root\Http\Controllers\ResourceController; use Illuminate\Support\Facades\Route; @@ -11,6 +12,9 @@ // Download Route::get('/download/{medium:uuid}', DownloadController::class)->name('download'); +// Options +Route::get('/options/{group}', [OptionController::class, 'index'])->name('options.index'); + // Resource Route::get('/{resource}', [ResourceController::class, 'index'])->name('resource.index'); Route::get('/{resource}/create', [ResourceController::class, 'create'])->name('resource.create'); diff --git a/src/Actions/Action.php b/src/Actions/Action.php index 4cef5a16..3609896e 100644 --- a/src/Actions/Action.php +++ b/src/Actions/Action.php @@ -4,6 +4,7 @@ use Closure; use Cone\Root\Exceptions\QueryResolutionException; +use Cone\Root\Exceptions\SaveFormDataException; use Cone\Root\Fields\Field; use Cone\Root\Fields\Relation; use Cone\Root\Http\Controllers\ActionController; @@ -23,11 +24,13 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; use Illuminate\Routing\Router; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\MessageBag; use Illuminate\Support\Str; use JsonSerializable; use Symfony\Component\HttpFoundation\Response; +use Throwable; abstract class Action implements Arrayable, Form, JsonSerializable { @@ -226,12 +229,24 @@ public function handleFormRequest(Request $request, Model $model): void */ public function perform(Request $request): Response { - $this->handleFormRequest($request, $this->resolveQuery($request)->getModel()); + try { + DB::beginTransaction(); - return Redirect::back()->with( - sprintf('alerts.action-%s', $this->getKey()), - Alert::info(__(':action was successful!', ['action' => $this->getName()])) - ); + $this->handleFormRequest($request, $this->resolveQuery($request)->getModel()); + + return Redirect::back()->with( + sprintf('alerts.action-%s', $this->getKey()), + Alert::info(__(':action was successful!', ['action' => $this->getName()])) + ); + + DB::commit(); + } catch (Throwable $exception) { + report($exception); + + DB::rollBack(); + + throw new SaveFormDataException($exception->getMessage()); + } } /** diff --git a/src/Http/Controllers/OptionController.php b/src/Http/Controllers/OptionController.php new file mode 100644 index 00000000..f1b9c5df --- /dev/null +++ b/src/Http/Controllers/OptionController.php @@ -0,0 +1,19 @@ + match (true) { is_null($this->key) => 'string', - default => Root::instance()->options->resolveCast($this->key), + default => Root::instance()->options->repository->resolveCast($this->key), }, ]; } diff --git a/src/Options/Group.php b/src/Options/Group.php new file mode 100644 index 00000000..d357e468 --- /dev/null +++ b/src/Options/Group.php @@ -0,0 +1,73 @@ +getModel())->classBasename()->plural()->kebab()->value(); + } + + /** + * Get the URI key. + */ + public function getUriKey(): string + { + return $this->getKey(); + } + + /** + * Get the name. + */ + public function getName(): string + { + return __(Str::of($this->getModel())->classBasename()->headline()->plural()->value()); + } + + /** + * Make a new Eloquent query instance. + */ + public function query(): Builder + { + return $this->getModelInstance()->newQuery()->with($this->with)->withCount($this->withCount); + } + + /** + * Handle the request. + */ + public function handleFormRequest(Request $request): void + { + $this->validateFormRequest($request); + + try { + DB::beginTransaction(); + + $this->resolveFields($request) + ->authorized($request) + ->visible($request->isMethod('POST') ? 'create' : 'update') + ->persist($request, $model); + + DB::commit(); + } catch (Throwable $exception) { + report($exception); + + DB::rollBack(); + + throw new SaveFormDataException($exception->getMessage()); + } + } +} diff --git a/src/Options/Registry.php b/src/Options/Registry.php new file mode 100644 index 00000000..e009fabf --- /dev/null +++ b/src/Options/Registry.php @@ -0,0 +1,46 @@ +repository = $repository; + } + + /** + * Get or create a new group. + */ + public function group(string $key): Group + { + $this->groups[$key] ??= new Group(Str::headline($key), $key); + + return $this->groups[$key]; + } + + /** + * Get the option groups. + */ + public function groups(): array + { + return $this->groups; + } +} diff --git a/src/Root.php b/src/Root.php index 9297856e..12e805c9 100644 --- a/src/Root.php +++ b/src/Root.php @@ -5,7 +5,7 @@ use Closure; use Cone\Root\Interfaces\Breadcrumbs\Registry as Breadcrumbs; use Cone\Root\Interfaces\Navigation\Registry as Navigation; -use Cone\Root\Interfaces\Options\Repository as Options; +use Cone\Root\Interfaces\Options\Registry as Options; use Cone\Root\Models\User; use Cone\Root\Resources\Resources; use Cone\Root\Widgets\Widgets; @@ -115,6 +115,14 @@ public function boot(): void }, sprintf('%s/{resource}/{resourceModel}/edit', $this->getPath()) => __('Edit'), ]); + + foreach ($this->options->groups() as $group) { + $this->navigation->location('sidebar')->new( + $group->getUri(), + $group->getName(), + ['icon' => $this->getIcon(), 'group' => __('Options')], + ); + } } /** diff --git a/src/RootServiceProvider.php b/src/RootServiceProvider.php index 4676e391..4254d039 100644 --- a/src/RootServiceProvider.php +++ b/src/RootServiceProvider.php @@ -42,6 +42,7 @@ class RootServiceProvider extends ServiceProvider Interfaces\Models\Option::class => Models\Option::class, Interfaces\Models\User::class => Models\User::class, Interfaces\Navigation\Registry::class => Navigation\Registry::class, + Interfaces\Options\Registry::class => Options\Registry::class, Interfaces\Options\Repository::class => Options\Repository::class, ];