Skip to content

Commit 1fab944

Browse files
authored
Merge pull request #3644 from neos/task/addPhpStan
TASK: Add phpstan
2 parents edf303e + 3055ab8 commit 1fab944

34 files changed

+117
-357
lines changed

.circleci/config.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ jobs:
140140
cd /home/circleci/app/
141141
bin/phpunit -c Build/BuildEssentials/PhpUnit/UnitTests.xml Packages/Application/Neos.Neos.Ui/Tests/Unit
142142
143+
php-linting:
144+
docker:
145+
- image: cimg/php:8.2-node
146+
working_directory: *workspace_root
147+
steps:
148+
- attach_workspace: *attach_workspace
149+
- restore_cache: *restore_app_cache
150+
151+
- run: rm -rf /home/circleci/app/Packages/Application/Neos.Neos.Ui
152+
- run: cd /home/circleci/app/Packages/Application && mv ~/neos-ui-workspace Neos.Neos.Ui
153+
- run: |
154+
cd /home/circleci/app/Packages/Application/Neos.Neos.Ui/Tests/Unit
155+
../../../bin/phpstan analyse
156+
143157
workflows:
144158
version: 2
145159
build_and_test:
@@ -161,3 +175,6 @@ workflows:
161175
- php-unittests:
162176
requires:
163177
- build_flow_app
178+
- php-linting:
179+
requires:
180+
- build_flow_app

Classes/ContentRepository/Service/WorkspaceService.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardIndividualNodesFromWorkspace;
1717
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter;
1818
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
19-
use Neos\ContentRepository\Core\Projection\Workspace\Workspace;
2019
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
2120
use Neos\Neos\FrontendRouting\NodeAddress;
2221
use Neos\Neos\FrontendRouting\NodeAddressFactory;
@@ -128,7 +127,6 @@ public function getAllowedTargetWorkspaces(ContentRepository $contentRepository)
128127
$user = $this->domainUserService->getCurrentUser();
129128

130129
$workspacesArray = [];
131-
/** @var Workspace $workspace */
132130
foreach ($contentRepository->getWorkspaceFinder()->findAll() as $workspace) {
133131
// FIXME: This check should be implemented through a specialized Workspace Privilege or something similar
134132
// Skip workspace not owned by current user
@@ -157,6 +155,7 @@ public function getAllowedTargetWorkspaces(ContentRepository $contentRepository)
157155
return $workspacesArray;
158156
}
159157

158+
/** @return list<RemoveNode> */
160159
public function predictRemoveNodeFeedbackFromDiscardIndividualNodesFromWorkspaceCommand(
161160
DiscardIndividualNodesFromWorkspace $command,
162161
ContentRepository $contentRepository
@@ -192,7 +191,7 @@ public function predictRemoveNodeFeedbackFromDiscardIndividualNodesFromWorkspace
192191

193192
$childNode = $subgraph->findNodeById($nodeToDiscard->nodeAggregateId);
194193
$parentNode = $subgraph->findParentNode($nodeToDiscard->nodeAggregateId);
195-
if ($parentNode) {
194+
if ($childNode && $parentNode) {
196195
$result[] = new RemoveNode($childNode, $parentNode);
197196
$handledNodes[] = $nodeToDiscard;
198197
}

Classes/Controller/BackendServiceController.php

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
2525
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
2626
use Neos\Eel\FlowQuery\FlowQuery;
27+
use Neos\Eel\FlowQuery\Operations\GetOperation;
2728
use Neos\Flow\Annotations as Flow;
2829
use Neos\Flow\Mvc\ActionRequest;
2930
use Neos\Flow\Mvc\ActionResponse;
@@ -39,7 +40,6 @@
3940
use Neos\Neos\Service\UserService;
4041
use Neos\Neos\Ui\ContentRepository\Service\NeosUiNodeService;
4142
use Neos\Neos\Ui\ContentRepository\Service\WorkspaceService;
42-
use Neos\Neos\Ui\Domain\Model\ChangeCollection;
4343
use Neos\Neos\Ui\Domain\Model\Feedback\Messages\Error;
4444
use Neos\Neos\Ui\Domain\Model\Feedback\Messages\Info;
4545
use Neos\Neos\Ui\Domain\Model\Feedback\Messages\Success;
@@ -50,7 +50,6 @@
5050
use Neos\Neos\Ui\Fusion\Helper\NodeInfoHelper;
5151
use Neos\Neos\Ui\Fusion\Helper\WorkspaceHelper;
5252
use Neos\Neos\Ui\Service\NodeClipboard;
53-
use Neos\Neos\Ui\Service\NodePolicyService;
5453
use Neos\Neos\Ui\Service\PublishingService;
5554
use Neos\Neos\Ui\TypeConverter\ChangeCollectionConverter;
5655
use Neos\Neos\Utility\NodeUriPathSegmentGenerator;
@@ -103,12 +102,6 @@ class BackendServiceController extends ActionController
103102
*/
104103
protected $userService;
105104

106-
/**
107-
* @Flow\Inject
108-
* @var NodePolicyService
109-
*/
110-
protected $nodePolicyService;
111-
112105
/**
113106
* @Flow\Inject
114107
* @var ChangeCollectionConverter
@@ -157,15 +150,13 @@ protected function initializeController(ActionRequest $request, ActionResponse $
157150

158151
/**
159152
* Apply a set of changes to the system
153+
* @param array<int,array<string,mixed>> $changes
160154
*/
161-
/** @phpstan-ignore-next-line */
162155
public function changeAction(array $changes): void
163156
{
164157
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
165158

166-
/** @param array<int,array<string,mixed>> $changes */
167159
$changes = $this->changeCollectionConverter->convert($changes, $contentRepositoryId);
168-
/** @var ChangeCollection $changes */
169160
try {
170161
$count = $changes->count();
171162
$changes->apply();
@@ -208,9 +199,8 @@ public function publishAllAction(): void
208199
/**
209200
* Publish nodes
210201
*
211-
* @param array $nodeContextPaths
202+
* @param list<string> $nodeContextPaths
212203
*/
213-
/** @phpstan-ignore-next-line */
214204
public function publishAction(array $nodeContextPaths, string $targetWorkspaceName): void
215205
{
216206
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
@@ -267,9 +257,8 @@ public function publishAction(array $nodeContextPaths, string $targetWorkspaceNa
267257
/**
268258
* Discard nodes
269259
*
270-
* @param array $nodeContextPaths
260+
* @param list<string> $nodeContextPaths
271261
*/
272-
/** @phpstan-ignore-next-line */
273262
public function discardAction(array $nodeContextPaths): void
274263
{
275264
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
@@ -417,12 +406,11 @@ public function changeBaseWorkspaceAction(string $targetWorkspaceName, string $d
417406
/**
418407
* Persists the clipboard node on copy
419408
*
420-
* @param array $nodes
409+
* @param list<string> $nodes
421410
* @return void
422411
* @throws \Neos\Flow\Property\Exception
423412
* @throws \Neos\Flow\Security\Exception
424413
*/
425-
/** @phpstan-ignore-next-line */
426414
public function copyNodesAction(array $nodes): void
427415
{
428416
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
@@ -450,11 +438,10 @@ public function clearClipboardAction()
450438
/**
451439
* Persists the clipboard node on cut
452440
*
453-
* @param array $nodes
441+
* @param list<string> $nodes
454442
* @throws \Neos\Flow\Property\Exception
455443
* @throws \Neos\Flow\Security\Exception
456444
*/
457-
/** @phpstan-ignore-next-line */
458445
public function cutNodesAction(array $nodes): void
459446
{
460447
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
@@ -489,8 +476,8 @@ public function initializeGetAdditionalNodeMetadataAction(): void
489476

490477
/**
491478
* Fetches all the node information that can be lazy-loaded
479+
* @param list<string> $nodes
492480
*/
493-
/** @phpstan-ignore-next-line */
494481
public function getAdditionalNodeMetadataAction(array $nodes): void
495482
{
496483
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
@@ -513,7 +500,13 @@ public function getAdditionalNodeMetadataAction(array $nodes): void
513500
}, $node->getOtherNodeVariants())));*/
514501
if (!is_null($node)) {
515502
$result[$nodeAddress->serializeForUri()] = [
516-
'policy' => $this->nodePolicyService->getNodePolicyInformation($node),
503+
// todo reimplement nodePolicyService
504+
'policy' => [
505+
'disallowedNodeTypes' => [],
506+
'canRemove' => true,
507+
'canEdit' => true,
508+
'disallowedProperties' => []
509+
]
517510
//'dimensions' => $this->getCurrentDimensionPresetIdentifiersForNode($node),
518511
//'otherNodeVariants' => $otherNodeVariants
519512
];
@@ -549,7 +542,13 @@ public function getPolicyInformationAction(array $nodes): void
549542
$node = $subgraph->findNodeById($nodeAddress->nodeAggregateId);
550543
if (!is_null($node)) {
551544
$result[$nodeAddress->serializeForUri()] = [
552-
'policy' => $this->nodePolicyService->getNodePolicyInformation($node)
545+
// todo reimplement nodePolicyService
546+
'policy' => [
547+
'disallowedNodeTypes' => [],
548+
'canRemove' => true,
549+
'canEdit' => true,
550+
'disallowedProperties' => []
551+
]
553552
];
554553
}
555554
}
@@ -560,28 +559,28 @@ public function getPolicyInformationAction(array $nodes): void
560559
/**
561560
* Build and execute a flow query chain
562561
*
563-
* @param array $chain
562+
* @param list<array{type: string, payload: array<string|int, mixed>}> $chain
564563
*/
565-
/** @phpstan-ignore-next-line */
566564
public function flowQueryAction(array $chain): string
567565
{
568566
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
569567

570568
$createContext = array_shift($chain);
571569
$finisher = array_pop($chain);
572570

573-
/** @var array<int,mixed> $payload */
574571
$payload = $createContext['payload'] ?? [];
575572
$flowQuery = new FlowQuery(array_map(
576573
fn ($envelope) => $this->nodeService->findNodeBySerializedNodeAddress($envelope['$node'], $contentRepositoryId),
577574
$payload
578575
));
579576

580577
foreach ($chain as $operation) {
581-
// @phpstan-ignore-next-line
582-
$flowQuery = call_user_func_array([$flowQuery, $operation['type']], $operation['payload']);
578+
$flowQuery = $flowQuery->__call($operation['type'], $operation['payload']);
583579
}
584580

581+
/** @see GetOperation */
582+
assert(is_callable([$flowQuery, 'get']));
583+
585584
$nodeInfoHelper = new NodeInfoHelper();
586585
$type = $finisher['type'] ?? null;
587586
$result = match ($type) {

Classes/Domain/Model/AbstractFeedback.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
abstract class AbstractFeedback implements FeedbackInterface
1818
{
19-
public function serialize(ControllerContext $controllerContext)
19+
/** @return array<string, mixed> */
20+
public function serialize(ControllerContext $controllerContext): array
2021
{
2122
return [
2223
'type' => $this->getType(),

Classes/Domain/Model/Changes/AbstractCreate.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function getName(): ?string
8787
* @param Node $parentNode
8888
* @param NodeAggregateId|null $succeedingSiblingNodeAggregateId
8989
* @return Node
90-
* @throws InvalidNodeCreationHandlerException|NodeNameIsAlreadyOccupied|NodeException
90+
* @throws InvalidNodeCreationHandlerException|NodeNameIsAlreadyOccupied
9191
*/
9292
protected function createNode(
9393
Node $parentNode,

Classes/Domain/Model/Changes/AbstractStructuralChange.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public function getSiblingDomAddress(): ?RenderedNodeDomAddress
106106
*/
107107
public function getSiblingNode(): ?Node
108108
{
109-
if ($this->siblingDomAddress === null) {
109+
if ($this->siblingDomAddress === null || !$this->getSubject()) {
110110
return null;
111111
}
112112

@@ -152,7 +152,7 @@ protected function finish(Node $node)
152152
// 1) the parent of our new (or copied or moved) node is a ContentCollection;
153153
// so we can directly update an element of this content collection
154154

155-
$contentRepository = $this->contentRepositoryRegistry->get($parentNode->subgraphIdentity->contentRepositoryId);
155+
$contentRepository = $this->contentRepositoryRegistry->get($node->subgraphIdentity->contentRepositoryId);
156156
if ($parentNode && $this->getNodeType($parentNode)->isOfType('Neos.Neos:ContentCollection') &&
157157
// 2) the parent DOM address (i.e. the closest RENDERED node in DOM is actually the ContentCollection;
158158
// and no other node in between

Classes/Domain/Model/Changes/Property.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ public function canApply(): bool
142142
/**
143143
* Applies this change
144144
*
145-
* @throws \Neos\ContentRepository\Exception\NodeException
146145
* @throws ContentStreamDoesNotExistYet
147146
* @throws NodeAggregatesTypeIsAmbiguous
148147
* @throws DimensionSpacePointNotFound

Classes/Domain/Model/Changes/Remove.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public function canApply(): bool
5252
* @throws NodeAggregatesTypeIsAmbiguous
5353
* @throws ContentStreamDoesNotExistYet
5454
* @throws DimensionSpacePointNotFound
55-
* @throws \Neos\ContentRepository\Exception\NodeException
5655
*/
5756
public function apply(): void
5857
{
@@ -79,7 +78,7 @@ public function apply(): void
7978
NodeVariantSelectionStrategy::STRATEGY_ALL_SPECIALIZATIONS,
8079
);
8180
if ($closestDocumentParentNode !== null) {
82-
$command = $command->withRemovalAttachmentPoint($closestDocumentParentNode?->nodeAggregateId);
81+
$command = $command->withRemovalAttachmentPoint($closestDocumentParentNode->nodeAggregateId);
8382
}
8483

8584
$contentRepository = $this->contentRepositoryRegistry->get($subject->subgraphIdentity->contentRepositoryId);

Classes/Domain/Model/Feedback/Operations/Redirect.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ public function isSimilarTo(FeedbackInterface $feedback)
8989
* Serialize the payload for this feedback
9090
*
9191
* @param ControllerContext $controllerContext
92-
* @return array
92+
* @return array<string, string>
9393
*/
94-
public function serializePayload(ControllerContext $controllerContext)
94+
public function serializePayload(ControllerContext $controllerContext): array
9595
{
9696
$node = $this->getNode();
9797
$redirectUri = $this->linkingService->createNodeUri($controllerContext, $node, null, null, true);

Classes/Domain/Model/Feedback/Operations/ReloadContentOutOfBand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ protected function renderContent(ControllerContext $controllerContext): string|R
154154
/**
155155
* @return array<string,mixed>
156156
*/
157-
public function serialize(ControllerContext $controllerContext)
157+
public function serialize(ControllerContext $controllerContext): array
158158
{
159159
try {
160160
return parent::serialize($controllerContext);

Classes/Domain/Model/Feedback/Operations/UpdateNodePreviewUrl.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ public function isSimilarTo(FeedbackInterface $feedback)
9292
* Serialize the payload for this feedback
9393
*
9494
* @param ControllerContext $controllerContext
95-
* @return array
95+
* @return array<string, string>
9696
*/
97-
public function serializePayload(ControllerContext $controllerContext)
97+
public function serializePayload(ControllerContext $controllerContext): array
9898
{
9999
if ($this->node === null) {
100100
$newPreviewUrl = '';

Classes/Domain/Model/FeedbackCollection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function add(FeedbackInterface $feedback)
6060
/**
6161
* Serialize collection to `json_encode`able array
6262
*
63-
* @return array
63+
* @return array<string, mixed>
6464
*/
6565
public function jsonSerialize(): array
6666
{
@@ -76,7 +76,7 @@ public function jsonSerialize(): array
7676
];
7777
}
7878

79-
public function reset()
79+
public function reset(): void
8080
{
8181
$this->feedbacks = [];
8282
}

Classes/Domain/Model/FeedbackInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ interface FeedbackInterface
2020
* in AbstractFeedback, but can be overridden to implement fallback logic in case of errors.
2121
*
2222
* @param ControllerContext $controllerContext
23-
* @return array
23+
* @return array<string, mixed>
2424
*/
25-
public function serialize(ControllerContext $controllerContext);
25+
public function serialize(ControllerContext $controllerContext): array;
2626

2727
/**
2828
* Get the type identifier

Classes/Domain/Model/RenderedNodeDomAddress.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@ public function getFusionPathForContentRendering(): string
9595
/**
9696
* Serialize to json
9797
*
98-
* @return array
98+
* @return array<string, string>
9999
*/
100-
#[\ReturnTypeWillChange]
101-
public function jsonSerialize(): mixed
100+
public function jsonSerialize(): array
102101
{
103102
return [
104103
'contextPath' => $this->getContextPath(),

0 commit comments

Comments
 (0)