From 69b92a5aa835b23ee97ab2f50442e1158b1a792c Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 12:58:04 +0200 Subject: [PATCH 01/16] [ContentCreate] Added int cast to ownerId and sectionId strict properties --- src/lib/Server/Input/Parser/ContentCreate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Server/Input/Parser/ContentCreate.php b/src/lib/Server/Input/Parser/ContentCreate.php index 4565de3a..9cab1f08 100644 --- a/src/lib/Server/Input/Parser/ContentCreate.php +++ b/src/lib/Server/Input/Parser/ContentCreate.php @@ -109,7 +109,7 @@ public function parse(array $data, ParsingDispatcher $parsingDispatcher): RestCo throw new Exceptions\Parser("Missing '_href' attribute for the Section element in ContentCreate."); } - $contentCreateStruct->sectionId = $this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); + $contentCreateStruct->sectionId = (int)$this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); } if (array_key_exists('alwaysAvailable', $data)) { @@ -129,7 +129,7 @@ public function parse(array $data, ParsingDispatcher $parsingDispatcher): RestCo throw new Exceptions\Parser("Missing '_href' attribute for the User element in ContentCreate."); } - $contentCreateStruct->ownerId = $this->uriParser->getAttributeFromUri($data['User']['_href'], 'userId'); + $contentCreateStruct->ownerId = (int)$this->uriParser->getAttributeFromUri($data['User']['_href'], 'userId'); } if (!array_key_exists('fields', $data) || !is_array($data['fields']) || !is_array($data['fields']['field'])) { From acd5d2bd36b300d0b0d2c2f02fbbc5cb6791b18c Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:00:05 +0200 Subject: [PATCH 02/16] [ContentCreate] Defined array shape of ContentCreate::parse `$data` arg --- src/lib/Server/Input/Parser/ContentCreate.php | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/lib/Server/Input/Parser/ContentCreate.php b/src/lib/Server/Input/Parser/ContentCreate.php index 9cab1f08..a26323b9 100644 --- a/src/lib/Server/Input/Parser/ContentCreate.php +++ b/src/lib/Server/Input/Parser/ContentCreate.php @@ -73,8 +73,25 @@ public function __construct( /** * Parse input structure. * - * @param array $data - * @param \Ibexa\Contracts\Rest\Input\ParsingDispatcher $parsingDispatcher + * @param array{ + * LocationCreate: array, + * ContentType: array{_href: string}, + * mainLanguageCode: string, + * Section?: array{_href: string}, + * alwaysAvailable?: bool|string, + * remoteId?: string, + * modificationDate?: string, + * User?: array{_href: string}, + * fields: array{ + * field: array< + * array{ + * fieldDefinitionIdentifier: string, + * fieldValue: mixed, + * languageCode?: string + * } + * > + * } + * } $data * * @return \Ibexa\Rest\Server\Values\RestContentCreateStruct */ From 2609dd7bb16908848fbc275a33332ce1f7faef36 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:00:29 +0200 Subject: [PATCH 03/16] [ContentCreate] Added missing `@throws` to ContentCreate::parse method --- src/lib/Server/Input/Parser/ContentCreate.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/Server/Input/Parser/ContentCreate.php b/src/lib/Server/Input/Parser/ContentCreate.php index a26323b9..0c246982 100644 --- a/src/lib/Server/Input/Parser/ContentCreate.php +++ b/src/lib/Server/Input/Parser/ContentCreate.php @@ -93,7 +93,9 @@ public function __construct( * } * } $data * - * @return \Ibexa\Rest\Server\Values\RestContentCreateStruct + * @throws \DateMalformedStringException + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException */ public function parse(array $data, ParsingDispatcher $parsingDispatcher): RestContentCreateStruct { From 59655459e4e8c4f6d9f01c5b0e0d71b9c6dd7834 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:12:02 +0200 Subject: [PATCH 04/16] [UserCreate] Defined array shape of UserCreate::parse `$data` arg --- src/lib/Server/Input/Parser/UserCreate.php | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/lib/Server/Input/Parser/UserCreate.php b/src/lib/Server/Input/Parser/UserCreate.php index 9b5426fa..cfdc80f6 100644 --- a/src/lib/Server/Input/Parser/UserCreate.php +++ b/src/lib/Server/Input/Parser/UserCreate.php @@ -57,6 +57,30 @@ public function __construct(UserService $userService, ContentTypeService $conten $this->parserTools = $parserTools; } + /** + * @param array{ + * ContentType?: array{_href: string}, + * mainLanguageCode: string, + * login: string, + * email: string, + * password: string, + * Section?: array{_href: string}, + * remoteId?: string, + * enabled?: bool|string, + * fields: array{ + * field: array< + * array{ + * fieldDefinitionIdentifier: string, + * fieldValue: mixed, + * languageCode?: string + * } + * > + * } + * } $data + * + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException + */ public function parse(array $data, ParsingDispatcher $parsingDispatcher): UserCreateStruct { $contentType = null; From 7438dbff419afebc05edf4aeadbc0dafa7921076 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:13:09 +0200 Subject: [PATCH 05/16] [UserCreate] Added int cast to sectionId strict property --- src/lib/Server/Input/Parser/UserCreate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Server/Input/Parser/UserCreate.php b/src/lib/Server/Input/Parser/UserCreate.php index cfdc80f6..6eeda13f 100644 --- a/src/lib/Server/Input/Parser/UserCreate.php +++ b/src/lib/Server/Input/Parser/UserCreate.php @@ -123,7 +123,7 @@ public function parse(array $data, ParsingDispatcher $parsingDispatcher): UserCr throw new Exceptions\Parser("Missing '_href' attribute for the Section element in UserCreate."); } - $userCreateStruct->sectionId = $this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); + $userCreateStruct->sectionId = (int)$this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); } if (array_key_exists('remoteId', $data)) { From 7f55edc1f677a001a02458eb43394a7592f81afa Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:18:09 +0200 Subject: [PATCH 06/16] Added missing type hints to \Ibexa\Rest\Server\Values\RestContentCreateStruct --- .../Server/Values/RestContentCreateStruct.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/lib/Server/Values/RestContentCreateStruct.php b/src/lib/Server/Values/RestContentCreateStruct.php index 2e0a3199..114bff07 100644 --- a/src/lib/Server/Values/RestContentCreateStruct.php +++ b/src/lib/Server/Values/RestContentCreateStruct.php @@ -16,25 +16,15 @@ */ class RestContentCreateStruct extends ValueObject { - /** - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct - */ - public $contentCreateStruct; + public ContentCreateStruct $contentCreateStruct; - /** - * @var \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct - */ - public $locationCreateStruct; + public LocationCreateStruct $locationCreateStruct; - /** - * Construct. - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct $contentCreateStruct - * @param \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct $locationCreateStruct - */ public function __construct(ContentCreateStruct $contentCreateStruct, LocationCreateStruct $locationCreateStruct) { $this->contentCreateStruct = $contentCreateStruct; $this->locationCreateStruct = $locationCreateStruct; + + parent::__construct(); } } From d839603d3a7418aaf19549e00c38fd786ca3a298 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:18:52 +0200 Subject: [PATCH 07/16] [Tests] Replaced literal FQCN usage with `RestContentCreateStruct::class` --- tests/lib/Server/Input/Parser/ContentCreateTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/lib/Server/Input/Parser/ContentCreateTest.php b/tests/lib/Server/Input/Parser/ContentCreateTest.php index aebc6f96..e5cf6506 100644 --- a/tests/lib/Server/Input/Parser/ContentCreateTest.php +++ b/tests/lib/Server/Input/Parser/ContentCreateTest.php @@ -19,6 +19,7 @@ use Ibexa\Rest\Input\FieldTypeParser; use Ibexa\Rest\Server\Input\Parser\ContentCreate; use Ibexa\Rest\Server\Input\Parser\LocationCreate; +use Ibexa\Rest\Server\Values\RestContentCreateStruct; use PHPUnit\Framework\MockObject\MockObject; class ContentCreateTest extends BaseTest @@ -57,7 +58,7 @@ public function testParse(): void $result = $contentCreate->parse($inputArray, $this->getParsingDispatcherMock()); self::assertInstanceOf( - '\\Ibexa\\Rest\\Server\\Values\\RestContentCreateStruct', + RestContentCreateStruct::class, $result, 'ContentCreate not created correctly.' ); From 040e22cdaf29b9579a68d158b195435f79e8d196 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:19:14 +0200 Subject: [PATCH 08/16] [Tests] Dropped unnecessary assertions due to strict types changes --- .../Server/Input/Parser/ContentCreateTest.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/lib/Server/Input/Parser/ContentCreateTest.php b/tests/lib/Server/Input/Parser/ContentCreateTest.php index e5cf6506..8fa446f7 100644 --- a/tests/lib/Server/Input/Parser/ContentCreateTest.php +++ b/tests/lib/Server/Input/Parser/ContentCreateTest.php @@ -63,18 +63,6 @@ public function testParse(): void 'ContentCreate not created correctly.' ); - self::assertInstanceOf( - '\\Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\ContentCreateStruct', - $result->contentCreateStruct, - 'contentCreateStruct not created correctly.' - ); - - self::assertInstanceOf( - '\\Ibexa\\Contracts\\Core\\Repository\\Values\\ContentType\\ContentType', - $result->contentCreateStruct->contentType, - 'contentType not created correctly.' - ); - self::assertEquals( 13, $result->contentCreateStruct->contentType->id, @@ -87,12 +75,6 @@ public function testParse(): void 'mainLanguageCode not created correctly' ); - self::assertInstanceOf( - '\\Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\LocationCreateStruct', - $result->locationCreateStruct, - 'locationCreateStruct not created correctly.' - ); - self::assertEquals( 4, $result->contentCreateStruct->sectionId, From 793efff249d8a3893b76048ef4e850bb6d71298c Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:21:17 +0200 Subject: [PATCH 09/16] [UserGroupCreate] Defined array shape of UserGroupCreate::parse `$data` arg --- .../Server/Input/Parser/UserGroupCreate.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lib/Server/Input/Parser/UserGroupCreate.php b/src/lib/Server/Input/Parser/UserGroupCreate.php index f276d688..469663aa 100644 --- a/src/lib/Server/Input/Parser/UserGroupCreate.php +++ b/src/lib/Server/Input/Parser/UserGroupCreate.php @@ -49,6 +49,26 @@ public function __construct(UserService $userService, ContentTypeService $conten $this->fieldTypeParser = $fieldTypeParser; } + /** + * @param array{ + * ContentType?: array{_href: string}, + * mainLanguageCode: string, + * Section?: array{_href: string}, + * remoteId?: string, + * fields: array{ + * field: array< + * array{ + * fieldDefinitionIdentifier: string, + * fieldValue: mixed, + * languageCode?: string + * } + * > + * } + * } $data + * + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException + */ public function parse(array $data, ParsingDispatcher $parsingDispatcher): UserGroupCreateStruct { $contentType = null; From 7d6b0ce13786f6df5bf01a663996ff31292d2336 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:21:32 +0200 Subject: [PATCH 10/16] [UserGroupCreate] Added int cast to sectionId strict property --- src/lib/Server/Input/Parser/UserGroupCreate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Server/Input/Parser/UserGroupCreate.php b/src/lib/Server/Input/Parser/UserGroupCreate.php index 469663aa..0ce54152 100644 --- a/src/lib/Server/Input/Parser/UserGroupCreate.php +++ b/src/lib/Server/Input/Parser/UserGroupCreate.php @@ -93,7 +93,7 @@ public function parse(array $data, ParsingDispatcher $parsingDispatcher): UserGr throw new Exceptions\Parser("Missing '_href' attribute for the Section element in UserGroupCreate."); } - $userGroupCreateStruct->sectionId = $this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); + $userGroupCreateStruct->sectionId = (int)$this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); } if (array_key_exists('remoteId', $data)) { From 48ec8561c30abf4ecb0454b5866dc8b190fb14de Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:33:45 +0200 Subject: [PATCH 11/16] [Tests] Defined non-nullable `remoteId` property for Location stub of LocationTest --- tests/lib/Server/Output/ValueObjectVisitor/LocationTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/lib/Server/Output/ValueObjectVisitor/LocationTest.php b/tests/lib/Server/Output/ValueObjectVisitor/LocationTest.php index 809be94d..9ae7b9e4 100644 --- a/tests/lib/Server/Output/ValueObjectVisitor/LocationTest.php +++ b/tests/lib/Server/Output/ValueObjectVisitor/LocationTest.php @@ -62,6 +62,7 @@ public function testVisitLocationAttributesResolvesMainLocation( 'priority' => 1, 'sortField' => ApiLocation::SORT_FIELD_DEPTH, 'sortOrder' => ApiLocation::SORT_ORDER_ASC, + 'remoteId' => 'cefb8160c6e88d8ea5ae1f31e0c201fc', 'parentLocationId' => 42, 'contentInfo' => new ContentInfo([ 'id' => $contentId, From 46b9e19644812f1923ef0bb46b406ad08ead365b Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:34:16 +0200 Subject: [PATCH 12/16] [Tests] Fixed non-nullable `parentRemoteId` property for Location stub of RestLocationRootNodeTest --- .../Output/ValueObjectVisitor/RestLocationRootNodeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/Server/Output/ValueObjectVisitor/RestLocationRootNodeTest.php b/tests/lib/Server/Output/ValueObjectVisitor/RestLocationRootNodeTest.php index 13ebe184..dfc9bf7f 100644 --- a/tests/lib/Server/Output/ValueObjectVisitor/RestLocationRootNodeTest.php +++ b/tests/lib/Server/Output/ValueObjectVisitor/RestLocationRootNodeTest.php @@ -36,7 +36,7 @@ public function testVisit() 'invisible' => true, 'explicitlyHidden' => true, 'remoteId' => 'remote-id', - 'parentLocationId' => null, + 'parentLocationId' => 1, 'pathString' => '/1', 'depth' => 3, 'sortField' => Location::SORT_FIELD_PATH, From 862755f2e74d29eefd037ef845dc5c733ff7e7c3 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 13:34:56 +0200 Subject: [PATCH 13/16] [Tests][PHPUnit] Configured UTC timezone for integration tests --- phpunit.integration.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit.integration.xml b/phpunit.integration.xml index 9f5f82b7..6da218fe 100644 --- a/phpunit.integration.xml +++ b/phpunit.integration.xml @@ -5,6 +5,7 @@ beStrictAboutTodoAnnotatedTests="true" verbose="true"> + From c3d690db7bf9ea170f5d65e4695fe9174bf5948f Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 16:52:03 +0200 Subject: [PATCH 14/16] Fixed incorrect default value assignment to Query properties in TrashItemListController --- src/lib/Server/Controller/Trash/TrashItemListController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Server/Controller/Trash/TrashItemListController.php b/src/lib/Server/Controller/Trash/TrashItemListController.php index c40cbee1..ddd6b54b 100644 --- a/src/lib/Server/Controller/Trash/TrashItemListController.php +++ b/src/lib/Server/Controller/Trash/TrashItemListController.php @@ -82,8 +82,8 @@ public function loadTrashItems(Request $request): Trash $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : -1; $query = new Query(); - $query->offset = $offset >= 0 ? $offset : null; - $query->limit = $limit >= 0 ? $limit : null; + $query->offset = max($offset, 0); + $query->limit = max($limit, 0); $trashItems = []; From 71981afd00b69975d9be01b3772555a87f1c974b Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Mon, 7 Jul 2025 12:45:55 +0200 Subject: [PATCH 15/16] [CS] Fixed readability in UserGroupCreate Co-authored-by: Konrad Oboza --- src/lib/Server/Input/Parser/UserGroupCreate.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/Server/Input/Parser/UserGroupCreate.php b/src/lib/Server/Input/Parser/UserGroupCreate.php index 0ce54152..e9b6c963 100644 --- a/src/lib/Server/Input/Parser/UserGroupCreate.php +++ b/src/lib/Server/Input/Parser/UserGroupCreate.php @@ -93,7 +93,10 @@ public function parse(array $data, ParsingDispatcher $parsingDispatcher): UserGr throw new Exceptions\Parser("Missing '_href' attribute for the Section element in UserGroupCreate."); } - $userGroupCreateStruct->sectionId = (int)$this->uriParser->getAttributeFromUri($data['Section']['_href'], 'sectionId'); + $userGroupCreateStruct->sectionId = (int)$this->uriParser->getAttributeFromUri( + $data['Section']['_href'], + 'sectionId' + ); } if (array_key_exists('remoteId', $data)) { From 491a90eb6b2e8aaf40cef63fe501848a856e0ecf Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 3 Jul 2025 22:25:02 +0200 Subject: [PATCH 16/16] [PHPStan] Removed resolved issues from the baseline --- phpstan-baseline.neon | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e938cf0b..ce3b3fbf 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -474,18 +474,6 @@ parameters: count: 1 path: src/lib/Server/Controller/Services.php - - - message: '#^Property Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Query\:\:\$limit \(int\) does not accept int\<0, max\>\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Controller/Trash/TrashItemListController.php - - - - message: '#^Property Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Query\:\:\$offset \(int\) does not accept int\<0, max\>\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Controller/Trash/TrashItemListController.php - - message: '#^Method Ibexa\\Rest\\Server\\Input\\Parser\\AbstractDestinationLocationParser\:\:parse\(\) has Ibexa\\Contracts\\Rest\\Exceptions\\Parser in PHPDoc @throws tag but it''s not thrown\.$#' identifier: throws.unusedType