From 997e7baf9f47169b08727c7f944248408e106acc Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Thu, 8 Oct 2026 12:13:40 +0200 Subject: [PATCH] #125 Small fixes: schedule context decoding, duplicated ROLE_USER, expression-language, naming strategy - ProcessSchedule::getContext(): json_decode() with true (a JSON object gave a stdClass) - User::getRoles(): ROLE_USER no longer duplicated when stored - symfony/expression-language declared (Assert\When), it was only a transitive dependency - docs: the entities expect the underscore_number_aware Doctrine naming strategy Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 1 + composer.json | 1 + docs/index.md | 10 ++++++++++ src/Entity/ProcessSchedule.php | 2 +- src/Entity/User.php | 2 +- tests/Entity/ProcessScheduleTest.php | 4 ++++ tests/Entity/UserTest.php | 8 ++++++++ 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5c14ce..ccb9ace 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Latest * [#111](https://github.com/cleverage/ui-process-bundle/issues/111) `ProcessExecutionDurationFilter`: the filter values are bound as DQL parameters (they were concatenated in the DQL; not exploitable, the form field is numeric). Add tests. * [#113](https://github.com/cleverage/ui-process-bundle/issues/113) HTTP API, synchronous execution: the error message is followed by the id of the process execution (`(process execution: )`), to find its logs in the UI; add `ProcessExecutionManager::getLastProcessExecution()`. Add tests. * [#117](https://github.com/cleverage/ui-process-bundle/issues/117) Schedule validators: `every` expressions checked as the Symfony Scheduler does (`PeriodicalTrigger`): expressions such as `0 seconds`, `yesterday` or `monday` were accepted but stopped the `scheduler_cron` worker, ISO 8601 durations (`PT1H`) were refused; message fixed ("is not a valid \"every\" expression"). A "hashed" cron expression is refused (500). No `TypeError` on `null`. Add tests. +* [#125](https://github.com/cleverage/ui-process-bundle/issues/125) `ProcessSchedule::getContext()` decodes a JSON string as an array; `User::getRoles()` no longer duplicates `ROLE_USER`; `symfony/expression-language` declared (used by `Assert\When`); the `underscore_number_aware` Doctrine naming strategy prerequisite is documented. Add tests. v3.0.2 ------ diff --git a/composer.json b/composer.json index c538091..b51399c 100644 --- a/composer.json +++ b/composer.json @@ -53,6 +53,7 @@ "symfony/doctrine-messenger": "^6.4 || ^7.4 || ^8", "symfony/dotenv": "^6.4 || ^7.4 || ^8", "symfony/event-dispatcher": "^6.4 || ^7.4 || ^8", + "symfony/expression-language": "^6.4 || ^7.4 || ^8", "symfony/filesystem": "^6.4 || ^7.4 || ^8", "symfony/finder": "^6.4 || ^7.4 || ^8", "symfony/form": "^6.4 || ^7.4 || ^8", diff --git a/docs/index.md b/docs/index.md index 5fd9e7c..7c10dc7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -84,6 +84,16 @@ See [users & security](reference/03-users_and_security.md). Supported databases: **MySQL / MariaDB** and **PostgreSQL** (maintained versions). +The entities of the bundle expect the `underscore_number_aware` Doctrine naming strategy (that of the Symfony recipe): +their indexes reference `snake_case` column names (e.g. `start_date`). + +```yaml +# config/packages/doctrine.yaml +doctrine: + orm: + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware +``` + The bundle registers its own Doctrine migrations (`CleverAge\UiProcessBundle\Migrations`). Run them, then create a first user: diff --git a/src/Entity/ProcessSchedule.php b/src/Entity/ProcessSchedule.php index 34f7234..f297de4 100644 --- a/src/Entity/ProcessSchedule.php +++ b/src/Entity/ProcessSchedule.php @@ -76,7 +76,7 @@ public function setProcess(string $process): static */ public function getContext(): array { - return \is_array($this->context) ? $this->context : json_decode($this->context); + return \is_array($this->context) ? $this->context : json_decode($this->context, true); } /** diff --git a/src/Entity/User.php b/src/Entity/User.php index 11532f7..91a20be 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -136,7 +136,7 @@ public function setLocale(?string $locale): self public function getRoles(): array { - return array_merge(['ROLE_USER'], $this->roles); + return array_values(array_unique(array_merge(['ROLE_USER'], $this->roles))); } /** diff --git a/tests/Entity/ProcessScheduleTest.php b/tests/Entity/ProcessScheduleTest.php index ee989b4..30f8b44 100644 --- a/tests/Entity/ProcessScheduleTest.php +++ b/tests/Entity/ProcessScheduleTest.php @@ -72,6 +72,10 @@ public function testGetContextDecodesJsonString(): void (new \ReflectionProperty(ProcessSchedule::class, 'context'))->setValue($schedule, '["a","b"]'); self::assertSame(['a', 'b'], $schedule->getContext()); + + // A JSON object is decoded as an array (it gave a stdClass: TypeError on the return type) + (new \ReflectionProperty(ProcessSchedule::class, 'context'))->setValue($schedule, '{"key":"value"}'); + self::assertSame(['key' => 'value'], $schedule->getContext()); } /** diff --git a/tests/Entity/UserTest.php b/tests/Entity/UserTest.php index 6ddbf4a..d030b08 100644 --- a/tests/Entity/UserTest.php +++ b/tests/Entity/UserTest.php @@ -69,6 +69,14 @@ public function testGettersAndSetters(): void self::assertNull($user->getToken()); } + public function testRoleUserIsNotDuplicated(): void + { + // As stored by UserCreateCommand + $user = (new User())->setRoles(['ROLE_USER', 'ROLE_ADMIN']); + + self::assertSame(['ROLE_USER', 'ROLE_ADMIN'], $user->getRoles()); + } + public function testUserIdentifierRequiresAnEmail(): void { $user = (new User())->setEmail('');