Skip to content

Commit 4541b3e

Browse files
committed
IBX-9727: Added type-hints and adapted codebase to PHP8+
1 parent 2c4bfe6 commit 4541b3e

25 files changed

+288
-359
lines changed

phpstan-baseline.neon

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,19 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: '#^Parameter \#1 \$locationId of method Ibexa\\Contracts\\Core\\Repository\\LocationService\:\:loadLocation\(\) expects int, int\|null given\.$#'
5-
identifier: argument.type
6-
count: 1
7-
path: src/bundle/Controller/QueryFieldRestController.php
8-
9-
-
10-
message: '#^Parameter \#1 \$uri of method Ibexa\\Contracts\\Rest\\UriParser\\UriParserInterface\:\:getAttributeFromUri\(\) expects string, string\|null given\.$#'
11-
identifier: argument.type
12-
count: 1
13-
path: src/bundle/Controller/QueryFieldRestController.php
14-
15-
-
16-
message: '#^Argument of an invalid type array\|bool\|float\|int\|string\|null supplied for foreach, only iterables are supported\.$#'
4+
message: '#^Argument of an invalid type array\|bool\|float\|int\|string supplied for foreach, only iterables are supported\.$#'
175
identifier: foreach.nonIterable
186
count: 1
197
path: src/bundle/DependencyInjection/Compiler/FieldDefinitionIdentifierViewMatcherPass.php
208

219
-
22-
message: '#^Cannot access offset \(int\|string\) on non\-empty\-array\|bool\|float\|int\|string\|null\.$#'
10+
message: '#^Cannot access offset \(int\|string\) on non\-empty\-array\|bool\|float\|int\|string\.$#'
2311
identifier: offsetAccess.nonOffsetAccessible
2412
count: 1
2513
path: src/bundle/DependencyInjection/Compiler/FieldDefinitionIdentifierViewMatcherPass.php
2614

2715
-
28-
message: '#^Parameter \#2 \$callback of function array_filter expects \(callable\(int\|string\)\: bool\)\|null, Closure\(mixed\)\: \(0\|1\|false\) given\.$#'
16+
message: '#^Parameter \#2 \$callback of function array_filter expects \(callable\(int\|string\)\: bool\)\|null, Closure\(string\)\: \(0\|1\|false\) given\.$#'
2917
identifier: argument.type
3018
count: 1
3119
path: src/bundle/DependencyInjection/Compiler/FieldDefinitionIdentifierViewMatcherPass.php
@@ -36,36 +24,6 @@ parameters:
3624
count: 1
3725
path: src/bundle/DependencyInjection/Compiler/QueryTypesListPass.php
3826

39-
-
40-
message: '#^Parameter \#1 \$input of static method Symfony\\Component\\Yaml\\Yaml\:\:parse\(\) expects string, string\|false given\.$#'
41-
identifier: argument.type
42-
count: 1
43-
path: src/bundle/DependencyInjection/IbexaFieldTypeQueryExtension.php
44-
45-
-
46-
message: '#^Method Ibexa\\FieldTypeQuery\\ContentView\\QueryResultsInjector\:\:__construct\(\) has parameter \$views with no value type specified in iterable type array\.$#'
47-
identifier: missingType.iterableValue
48-
count: 1
49-
path: src/lib/ContentView/QueryResultsInjector.php
50-
51-
-
52-
message: '#^Property Ibexa\\FieldTypeQuery\\ContentView\\QueryResultsInjector\:\:\$queryFieldService \(Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldLocationService&Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldServiceInterface\) does not accept Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldServiceInterface\.$#'
53-
identifier: assign.propertyType
54-
count: 1
55-
path: src/lib/ContentView/QueryResultsInjector.php
56-
57-
-
58-
message: '#^Property Ibexa\\FieldTypeQuery\\ContentView\\QueryResultsInjector\:\:\$views type has no value type specified in iterable type array\.$#'
59-
identifier: missingType.iterableValue
60-
count: 1
61-
path: src/lib/ContentView/QueryResultsInjector.php
62-
63-
-
64-
message: '#^Property Ibexa\\FieldTypeQuery\\ExceptionSafeQueryFieldService\:\:\$inner \(Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldLocationService&Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldServiceInterface\) does not accept Ibexa\\Contracts\\FieldTypeQuery\\QueryFieldServiceInterface\.$#'
65-
identifier: assign.propertyType
66-
count: 1
67-
path: src/lib/ExceptionSafeQueryFieldService.php
68-
6927
-
7028
message: '#^Generator expects key type string, string\|null given\.$#'
7129
identifier: generator.keyType
@@ -78,38 +36,8 @@ parameters:
7836
count: 1
7937
path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/QueryConverter.php
8038

81-
-
82-
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:isExpression\(\) has parameter \$expression with no type specified\.$#'
83-
identifier: missingType.parameter
84-
count: 1
85-
path: src/lib/QueryFieldService.php
86-
87-
-
88-
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:prepareQuery\(\) has parameter \$extraParameters with no value type specified in iterable type array\.$#'
89-
identifier: missingType.iterableValue
90-
count: 1
91-
path: src/lib/QueryFieldService.php
92-
9339
-
9440
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:resolveExpression\(\) has parameter \$variables with no value type specified in iterable type array\.$#'
9541
identifier: missingType.iterableValue
9642
count: 1
9743
path: src/lib/QueryFieldService.php
98-
99-
-
100-
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:resolveParameters\(\) has parameter \$expressions with no value type specified in iterable type array\.$#'
101-
identifier: missingType.iterableValue
102-
count: 1
103-
path: src/lib/QueryFieldService.php
104-
105-
-
106-
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:resolveParameters\(\) has parameter \$variables with no value type specified in iterable type array\.$#'
107-
identifier: missingType.iterableValue
108-
count: 1
109-
path: src/lib/QueryFieldService.php
110-
111-
-
112-
message: '#^Method Ibexa\\FieldTypeQuery\\QueryFieldService\:\:resolveParameters\(\) return type has no value type specified in iterable type array\.$#'
113-
identifier: missingType.iterableValue
114-
count: 1
115-
path: src/lib/QueryFieldService.php

spec/ContentView/FieldDefinitionIdentifierMatcherSpec.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
* @copyright Copyright (C) Ibexa AS. All rights reserved.
55
* @license For full copyright and license information view LICENSE file distributed with this source code.
66
*/
7+
declare(strict_types=1);
78

8-
namespace spec\Ibexa\FieldTypeQuery\ContentView;
9+
namespace spec\Ibexa\FieldTypeQuery\spec\ContentView;
910

1011
use Ibexa\Contracts\Core\Repository\ContentTypeService;
1112
use Ibexa\Contracts\Core\Repository\Repository;
@@ -20,15 +21,15 @@
2021
use Ibexa\FieldTypeQuery\ContentView\FieldDefinitionIdentifierMatcher;
2122
use PhpSpec\ObjectBehavior;
2223

23-
class FieldDefinitionIdentifierMatcherSpec extends ObjectBehavior
24+
final class FieldDefinitionIdentifierMatcherSpec extends ObjectBehavior
2425
{
25-
private const CONTENT_TYPE_ID_WITHOUT_FIELD_DEFINITION = 2;
26-
private const CONTENT_TYPE_IDENTIFIER_WITHOUT_FIELD_DEFINITION = 'type_matching_without_field_def';
26+
private const string CONTENT_TYPE_ID_WITHOUT_FIELD_DEFINITION = 2;
27+
private const string CONTENT_TYPE_IDENTIFIER_WITHOUT_FIELD_DEFINITION = 'type_matching_without_field_def';
2728

28-
private const CONTENT_TYPE_ID_WITH_FIELD_DEFINITION = 3;
29-
private const CONTENT_TYPE_IDENTIFIER_WITH_FIELD_DEFINITION = 'type_matching_with_field_def';
29+
private const string CONTENT_TYPE_ID_WITH_FIELD_DEFINITION = 3;
30+
private const string CONTENT_TYPE_IDENTIFIER_WITH_FIELD_DEFINITION = 'type_matching_with_field_def';
3031

31-
public const FIELD_DEFINITION_IDENTIFIER = 'field_definition';
32+
public const string FIELD_DEFINITION_IDENTIFIER = 'field_definition';
3233

3334
public function it_is_initializable(): void
3435
{

spec/ContentView/QueryResultsInjectorSpec.php

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,30 @@
44
* @copyright Copyright (C) Ibexa AS. All rights reserved.
55
* @license For full copyright and license information view LICENSE file distributed with this source code.
66
*/
7+
declare(strict_types=1);
78

89
namespace spec\Ibexa\FieldTypeQuery\ContentView;
910

11+
use Ibexa\Contracts\FieldTypeQuery\QueryFieldLocationService;
1012
use Ibexa\Contracts\FieldTypeQuery\QueryFieldServiceInterface;
1113
use Ibexa\Core\MVC\Symfony\View\ContentView;
1214
use Ibexa\Core\MVC\Symfony\View\Event\FilterViewParametersEvent;
1315
use Ibexa\Core\MVC\Symfony\View\ViewEvents;
1416
use Ibexa\Core\Repository\Values\Content\Content;
15-
use Ibexa\FieldTypeQuery\ContentView\QueryResultsInjector;
1617
use Pagerfanta\Pagerfanta;
1718
use PhpSpec\ObjectBehavior;
1819
use Prophecy\Argument;
1920
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2021
use Symfony\Component\HttpFoundation\RequestStack;
2122
use Webmozart\Assert\Assert;
2223

23-
class QueryResultsInjectorSpec extends ObjectBehavior
24+
final class QueryResultsInjectorSpec extends ObjectBehavior
2425
{
25-
public const FIELD_VIEW = 'content_query_field';
26-
public const OTHER_VIEW = 'anything_else';
27-
public const ITEM_VIEW = 'line';
28-
public const VIEWS = ['field' => self::FIELD_VIEW, 'item' => self::ITEM_VIEW];
29-
public const FIELD_DEFINITION_IDENTIFIER = 'query_field';
26+
public const string FIELD_VIEW = 'content_query_field';
27+
public const string OTHER_VIEW = 'anything_else';
28+
public const string ITEM_VIEW = 'line';
29+
public const array VIEWS = ['field' => self::FIELD_VIEW, 'item' => self::ITEM_VIEW];
30+
public const string FIELD_DEFINITION_IDENTIFIER = 'query_field';
3031

3132
private ContentView $view;
3233

@@ -50,13 +51,8 @@ public function __construct()
5051
);
5152
}
5253

53-
public function it_is_initializable(): void
54-
{
55-
$this->shouldHaveType(QueryResultsInjector::class);
56-
}
57-
5854
public function let(
59-
QueryFieldServiceInterface $queryFieldService,
55+
QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService,
6056
FilterViewParametersEvent $event,
6157
RequestStack $requestStack
6258
): void {
@@ -72,15 +68,15 @@ public function let(
7268
}
7369

7470
public function it_throws_an_InvalidArgumentException_if_no_item_view_is_provided(
75-
QueryFieldServiceInterface $queryFieldService,
71+
QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService,
7672
RequestStack $requestStack
7773
): void {
7874
$this->beConstructedWith($queryFieldService, ['field' => self::FIELD_VIEW], $requestStack);
7975
$this->shouldThrow(\InvalidArgumentException::class)->duringInstantiation();
8076
}
8177

8278
public function it_throws_an_InvalidArgumentException_if_no_field_view_is_provided(
83-
QueryFieldServiceInterface $queryFieldService,
79+
QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService,
8480
RequestStack $requestStack
8581
): void {
8682
$this->beConstructedWith($queryFieldService, ['item' => 'field'], $requestStack);
@@ -97,15 +93,16 @@ public function it_subscribes_to_the_FILTER_VIEW_PARAMETERS_View_Event(): void
9793
$this->getSubscribedEvents()->shouldSubscribeTo(ViewEvents::FILTER_VIEW_PARAMETERS);
9894
}
9995

100-
public function it_does_nothing_for_non_field_views(QueryFieldServiceInterface $queryFieldService): void
96+
public function it_does_nothing_for_non_field_views(QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService): void
10197
{
10298
$this->event->getView()->setViewType(self::OTHER_VIEW);
10399
$this->injectQueryResults($this->event);
104100
$queryFieldService->getPaginationConfiguration(Argument::any())->shouldNotHaveBeenCalled();
105101
}
106102

107-
public function it_adds_the_query_results_for_the_field_view_without_pagination(QueryFieldServiceInterface $queryFieldService): void
108-
{
103+
public function it_adds_the_query_results_for_the_field_view_without_pagination(
104+
QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService
105+
): void {
109106
$content = $this->createContentItem();
110107

111108
$queryFieldService
@@ -128,9 +125,12 @@ public function it_adds_the_query_results_for_the_field_view_without_pagination(
128125
Assert::eq($parameters->get('items'), $this->getResults());
129126
}
130127

128+
/**
129+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
130+
*/
131131
public function it_adds_the_query_results_for_the_field_view_with_pagination(
132132
FilterViewParametersEvent $event,
133-
QueryFieldServiceInterface $queryFieldService
133+
QueryFieldServiceInterface&QueryFieldLocationService $queryFieldService
134134
): void {
135135
$content = $this->createContentItem();
136136

@@ -156,6 +156,9 @@ public function it_adds_the_query_results_for_the_field_view_with_pagination(
156156
Assert::isInstanceOf($parameters->get('items'), Pagerfanta::class);
157157
}
158158

159+
/**
160+
* @return array<string, callable>
161+
*/
159162
public function getMatchers(): array
160163
{
161164
return [
@@ -170,6 +173,9 @@ private function createContentItem(): Content
170173
return new Content();
171174
}
172175

176+
/**
177+
* @return \Ibexa\Core\Repository\Values\Content\Content[]
178+
*/
173179
private function getResults(): array
174180
{
175181
return [

src/bundle/Controller/QueryFieldRestController.php

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* @copyright Copyright (C) Ibexa AS. All rights reserved.
55
* @license For full copyright and license information view LICENSE file distributed with this source code.
66
*/
7+
declare(strict_types=1);
78

89
namespace Ibexa\Bundle\FieldTypeQuery\Controller;
910

@@ -22,36 +23,24 @@
2223
use Ibexa\Rest\Server\Values\RestContent;
2324
use Symfony\Component\HttpFoundation\Request;
2425

25-
final class QueryFieldRestController
26+
final readonly class QueryFieldRestController
2627
{
27-
private QueryFieldService $queryFieldService;
28-
29-
private ContentService $contentService;
30-
31-
private ContentTypeService $contentTypeService;
32-
33-
private LocationService $locationService;
34-
35-
private UriParserInterface $uriParser;
36-
37-
private ContentService\RelationListFacadeInterface $relationListFacade;
38-
3928
public function __construct(
40-
QueryFieldService $queryFieldService,
41-
ContentService $contentService,
42-
ContentTypeService $contentTypeService,
43-
LocationService $locationService,
44-
UriParserInterface $uriParser,
45-
ContentService\RelationListFacadeInterface $relationListFacade
29+
private QueryFieldService $queryFieldService,
30+
private ContentService $contentService,
31+
private ContentTypeService $contentTypeService,
32+
private LocationService $locationService,
33+
private UriParserInterface $uriParser,
34+
private ContentService\RelationListFacadeInterface $relationListFacade
4635
) {
47-
$this->queryFieldService = $queryFieldService;
48-
$this->contentService = $contentService;
49-
$this->contentTypeService = $contentTypeService;
50-
$this->locationService = $locationService;
51-
$this->uriParser = $uriParser;
52-
$this->relationListFacade = $relationListFacade;
5336
}
5437

38+
/**
39+
* @throws \Ibexa\Contracts\Rest\Exceptions\NotFoundException
40+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
41+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
42+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
43+
*/
5544
public function getResults(
5645
Request $request,
5746
int $contentId,
@@ -89,11 +78,18 @@ public function getResults(
8978
return new RestValues\ContentList(
9079
array_map(
9180
function (Content $content): RestContent {
81+
$contentInfo = $content->getContentInfo();
82+
if ($contentInfo->getMainLocationId() === null) {
83+
throw new NotFoundException(
84+
sprintf('Content with ID "%s" has no main location.', $contentInfo->getId())
85+
);
86+
}
87+
9288
return new RestContent(
93-
$content->contentInfo,
94-
$this->locationService->loadLocation($content->contentInfo->mainLocationId),
89+
$content->getContentInfo(),
90+
$this->locationService->loadLocation($contentInfo->getMainLocationId()),
9591
$content,
96-
$this->getContentType($content->contentInfo),
92+
$this->getContentType($contentInfo),
9793
iterator_to_array($this->relationListFacade->getRelations($content->getVersionInfo()))
9894
);
9995
},
@@ -116,11 +112,19 @@ private function getContentType(ContentInfo $contentInfo): ContentType
116112

117113
/**
118114
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
115+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
119116
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
120117
*/
121118
private function loadLocationByPath(Request $request): Location
122119
{
123-
$locationHrefParts = explode('/', $this->uriParser->getAttributeFromUri($request->query->get('location'), 'locationPath'));
120+
$locationHrefParts = explode(
121+
'/',
122+
$this->uriParser->getAttributeFromUri(
123+
$request->query->get('location') ?? '',
124+
'locationPath'
125+
)
126+
);
127+
124128
$locationId = array_pop($locationHrefParts);
125129

126130
return $this->locationService->loadLocation((int)$locationId);

src/bundle/DependencyInjection/Compiler/ConfigurableFieldDefinitionMapperPass.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
* Adds the configuration for the query field type to the ibexa.graphql.schema.content.mapping.field_definition_type
1515
* configuration variable.
1616
*/
17-
class ConfigurableFieldDefinitionMapperPass implements CompilerPassInterface
17+
final class ConfigurableFieldDefinitionMapperPass implements CompilerPassInterface
1818
{
19-
public const PARAMETER = 'ibexa.graphql.schema.content.mapping.field_definition_type';
19+
public const string PARAMETER = 'ibexa.graphql.schema.content.mapping.field_definition_type';
2020

2121
public function process(ContainerBuilder $container): void
2222
{

0 commit comments

Comments
 (0)