From a79bdc518c9af9391548b337ac44e0872e417718 Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Wed, 9 Sep 2026 13:42:41 +0200 Subject: [PATCH 1/3] IBX-12046: Removed Symfony 8 deprecated code usage - Validator\Constraints\Password: replaced getDefaultOption()-less positional-options constructor with named-argument constructor (#[HasNamedArguments]), keeping a deprecated options-array BC path (trigger_deprecation) for existing callers; UserAccountPassword inherits it unchanged. - Content\View\Filter\ContentEditViewFilter: replaced deprecated Request::get() with an explicit attributes/query/request bag lookup. --- .../View/Filter/ContentEditViewFilter.php | 7 +++- src/lib/Validator/Constraints/Password.php | 37 ++++++++++++++++++- .../Validator/Constraints/PasswordTest.php | 34 +++++++++++++++++ .../Constraints/PasswordValidatorTest.php | 8 +--- .../Constraints/UserAccountPasswordTest.php | 21 +++++++++++ .../UserAccountPasswordValidatorTest.php | 8 +--- 6 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/lib/Content/View/Filter/ContentEditViewFilter.php b/src/lib/Content/View/Filter/ContentEditViewFilter.php index 609d7f07..949d332b 100644 --- a/src/lib/Content/View/Filter/ContentEditViewFilter.php +++ b/src/lib/Content/View/Filter/ContentEditViewFilter.php @@ -100,7 +100,12 @@ public function handleContentEditForm(FilterViewBuilderParametersEvent $event): $event->getParameters()->add([ 'form' => $form->handleRequest($request), - 'validate' => (bool)$request->get('validate', false), + 'validate' => (bool)( + $request->attributes->get('validate') + ?? $request->query->get('validate') + ?? $request->request->get('validate') + ?? false + ), ]); } diff --git a/src/lib/Validator/Constraints/Password.php b/src/lib/Validator/Constraints/Password.php index ff3b44f7..9b269066 100644 --- a/src/lib/Validator/Constraints/Password.php +++ b/src/lib/Validator/Constraints/Password.php @@ -9,6 +9,7 @@ namespace Ibexa\ContentForms\Validator\Constraints; use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType; +use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; /** @@ -16,10 +17,44 @@ */ class Password extends Constraint { - public string $message = 'ez.user.password.invalid'; + protected const string MESSAGE = 'ez.user.password.invalid'; + + public string $message = self::MESSAGE; public ?ContentType $contentType; + /** + * @param array|null $options Deprecated options array + * @param array|null $groups + */ + #[HasNamedArguments] + public function __construct( + ?array $options = null, + ?ContentType $contentType = null, + ?string $message = null, + ?array $groups = null, + mixed $payload = null + ) { + if ($options !== null) { + trigger_deprecation( + 'ibexa/content-forms', + '6.0', + 'Passing an options array to "%s" is deprecated, use named arguments instead.', + static::class + ); + + $contentType ??= $options['contentType'] ?? null; + $message ??= $options['message'] ?? null; + $groups ??= $options['groups'] ?? null; + $payload ??= $options['payload'] ?? null; + } + + parent::__construct(null, $groups, $payload); + + $this->contentType = $contentType; + $this->message = $message ?? static::MESSAGE; + } + public function getTargets(): array { return [self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT]; diff --git a/tests/lib/Validator/Constraints/PasswordTest.php b/tests/lib/Validator/Constraints/PasswordTest.php index da147b2d..bad99360 100644 --- a/tests/lib/Validator/Constraints/PasswordTest.php +++ b/tests/lib/Validator/Constraints/PasswordTest.php @@ -10,8 +10,12 @@ use Ibexa\ContentForms\Validator\Constraints\Password; use Ibexa\ContentForms\Validator\Constraints\PasswordValidator; +use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType; use PHPUnit\Framework\TestCase; +/** + * @covers \Ibexa\ContentForms\Validator\Constraints\Password + */ final class PasswordTest extends TestCase { private Password $constraint; @@ -41,4 +45,34 @@ public function testGetTargets(): void $this->constraint->getTargets() ); } + + public function testNamedArguments(): void + { + $contentType = $this->createMock(ContentType::class); + $payload = new \stdClass(); + + $constraint = new Password( + contentType: $contentType, + message: 'Custom message', + groups: ['custom'], + payload: $payload + ); + + self::assertSame($contentType, $constraint->contentType); + self::assertSame('Custom message', $constraint->message); + self::assertSame(['custom'], $constraint->groups); + self::assertSame($payload, $constraint->payload); + } + + public function testLegacyOptionsArray(): void + { + $contentType = $this->createMock(ContentType::class); + + $constraint = new Password([ + 'contentType' => $contentType, + ]); + + self::assertSame($contentType, $constraint->contentType); + self::assertSame('ez.user.password.invalid', $constraint->message); + } } diff --git a/tests/lib/Validator/Constraints/PasswordValidatorTest.php b/tests/lib/Validator/Constraints/PasswordValidatorTest.php index 1940a042..65fde0cd 100644 --- a/tests/lib/Validator/Constraints/PasswordValidatorTest.php +++ b/tests/lib/Validator/Constraints/PasswordValidatorTest.php @@ -72,9 +72,7 @@ public function testValid(): void ->expects(self::never()) ->method('buildViolation'); - $this->validator->validate($password, new Password([ - 'contentType' => $contentType, - ])); + $this->validator->validate($password, new Password(contentType: $contentType)); } public function testInvalid(): void @@ -117,9 +115,7 @@ public function testInvalid(): void ->expects(self::once()) ->method('addViolation'); - $this->validator->validate('pass', new Password([ - 'contentType' => $contentType, - ])); + $this->validator->validate('pass', new Password(contentType: $contentType)); } public function dataProviderForValidateNotSupportedValueType(): array diff --git a/tests/lib/Validator/Constraints/UserAccountPasswordTest.php b/tests/lib/Validator/Constraints/UserAccountPasswordTest.php index 0a357146..e16ab88c 100644 --- a/tests/lib/Validator/Constraints/UserAccountPasswordTest.php +++ b/tests/lib/Validator/Constraints/UserAccountPasswordTest.php @@ -10,6 +10,7 @@ use Ibexa\ContentForms\Validator\Constraints\UserAccountPassword; use Ibexa\ContentForms\Validator\Constraints\UserAccountPasswordValidator; +use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; @@ -36,4 +37,24 @@ public function testGetTargets(): void { self::assertSame([Constraint::CLASS_CONSTRAINT, Constraint::PROPERTY_CONSTRAINT], $this->constraint->getTargets()); } + + public function testNamedArguments(): void + { + $contentType = $this->createMock(ContentType::class); + + $constraint = new UserAccountPassword(contentType: $contentType); + + self::assertSame($contentType, $constraint->contentType); + } + + public function testLegacyOptionsArray(): void + { + $contentType = $this->createMock(ContentType::class); + + $constraint = new UserAccountPassword([ + 'contentType' => $contentType, + ]); + + self::assertSame($contentType, $constraint->contentType); + } } diff --git a/tests/lib/Validator/Constraints/UserAccountPasswordValidatorTest.php b/tests/lib/Validator/Constraints/UserAccountPasswordValidatorTest.php index 448d7ad3..7bd31a7b 100644 --- a/tests/lib/Validator/Constraints/UserAccountPasswordValidatorTest.php +++ b/tests/lib/Validator/Constraints/UserAccountPasswordValidatorTest.php @@ -81,9 +81,7 @@ public function testValid(): void ->expects(self::never()) ->method('buildViolation'); - $this->validator->validate($userAccount, new UserAccountPassword([ - 'contentType' => $contentType, - ])); + $this->validator->validate($userAccount, new UserAccountPassword(contentType: $contentType)); } public function testInvalid(): void @@ -126,8 +124,6 @@ public function testInvalid(): void ->expects(self::once()) ->method('addViolation'); - $this->validator->validate($userAccount, new UserAccountPassword([ - 'contentType' => $contentType, - ])); + $this->validator->validate($userAccount, new UserAccountPassword(contentType: $contentType)); } } From 96ed8bacce6a5bf1e9d25ff40ace5a4c2e8ba91c Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Thu, 10 Sep 2026 11:32:47 +0200 Subject: [PATCH 2/3] IBX-12046: Read the edit view 'validate' flag from the query string only Nothing in the platform sets this flag as a route attribute or form field; a query-string flag on the edit URL is the only source, so the generic three-bag lookup inherited from Request::get() is dropped. --- src/lib/Content/View/Filter/ContentEditViewFilter.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/lib/Content/View/Filter/ContentEditViewFilter.php b/src/lib/Content/View/Filter/ContentEditViewFilter.php index 949d332b..ccc9d83b 100644 --- a/src/lib/Content/View/Filter/ContentEditViewFilter.php +++ b/src/lib/Content/View/Filter/ContentEditViewFilter.php @@ -100,12 +100,7 @@ public function handleContentEditForm(FilterViewBuilderParametersEvent $event): $event->getParameters()->add([ 'form' => $form->handleRequest($request), - 'validate' => (bool)( - $request->attributes->get('validate') - ?? $request->query->get('validate') - ?? $request->request->get('validate') - ?? false - ), + 'validate' => $request->query->getBoolean('validate'), ]); } From 18dbb18cde0094bd9a953b4437a54664b844cffc Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Fri, 11 Sep 2026 11:10:25 +0200 Subject: [PATCH 3/3] IBX-12046: Dropped the options-array constructor path from the Password constraint 6.0 is a major and Symfony 8 removes options-array support from Constraint itself; every in-repo caller and the only subclass already use named arguments, and no other package instantiates these constraints. --- src/lib/Validator/Constraints/Password.php | 16 ---------------- tests/lib/Validator/Constraints/PasswordTest.php | 12 ------------ .../Constraints/UserAccountPasswordTest.php | 11 ----------- 3 files changed, 39 deletions(-) diff --git a/src/lib/Validator/Constraints/Password.php b/src/lib/Validator/Constraints/Password.php index 9b269066..4d794ba2 100644 --- a/src/lib/Validator/Constraints/Password.php +++ b/src/lib/Validator/Constraints/Password.php @@ -24,31 +24,15 @@ class Password extends Constraint public ?ContentType $contentType; /** - * @param array|null $options Deprecated options array * @param array|null $groups */ #[HasNamedArguments] public function __construct( - ?array $options = null, ?ContentType $contentType = null, ?string $message = null, ?array $groups = null, mixed $payload = null ) { - if ($options !== null) { - trigger_deprecation( - 'ibexa/content-forms', - '6.0', - 'Passing an options array to "%s" is deprecated, use named arguments instead.', - static::class - ); - - $contentType ??= $options['contentType'] ?? null; - $message ??= $options['message'] ?? null; - $groups ??= $options['groups'] ?? null; - $payload ??= $options['payload'] ?? null; - } - parent::__construct(null, $groups, $payload); $this->contentType = $contentType; diff --git a/tests/lib/Validator/Constraints/PasswordTest.php b/tests/lib/Validator/Constraints/PasswordTest.php index bad99360..736f6981 100644 --- a/tests/lib/Validator/Constraints/PasswordTest.php +++ b/tests/lib/Validator/Constraints/PasswordTest.php @@ -63,16 +63,4 @@ public function testNamedArguments(): void self::assertSame(['custom'], $constraint->groups); self::assertSame($payload, $constraint->payload); } - - public function testLegacyOptionsArray(): void - { - $contentType = $this->createMock(ContentType::class); - - $constraint = new Password([ - 'contentType' => $contentType, - ]); - - self::assertSame($contentType, $constraint->contentType); - self::assertSame('ez.user.password.invalid', $constraint->message); - } } diff --git a/tests/lib/Validator/Constraints/UserAccountPasswordTest.php b/tests/lib/Validator/Constraints/UserAccountPasswordTest.php index e16ab88c..a100cf2b 100644 --- a/tests/lib/Validator/Constraints/UserAccountPasswordTest.php +++ b/tests/lib/Validator/Constraints/UserAccountPasswordTest.php @@ -46,15 +46,4 @@ public function testNamedArguments(): void self::assertSame($contentType, $constraint->contentType); } - - public function testLegacyOptionsArray(): void - { - $contentType = $this->createMock(ContentType::class); - - $constraint = new UserAccountPassword([ - 'contentType' => $contentType, - ]); - - self::assertSame($contentType, $constraint->contentType); - } }