From a6a4133effcbc241759831124298e18d7fc35a2b Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 29 Oct 2023 14:11:09 +0100 Subject: [PATCH 1/7] TASK: Fix types from `Neos.ContentRepository.Export` --- .../src/Asset/Adapters/DbalAssetLoader.php | 13 ++++---- .../Adapters/FileSystemResourceLoader.php | 6 +++- .../src/Asset/AssetExporter.php | 1 + .../Asset/ValueObject/ImageAdjustmentType.php | 4 +++ .../src/Asset/ValueObject/SerializedAsset.php | 3 +- .../ValueObject/SerializedImageAdjustment.php | 3 +- .../src/Event/ValueObject/ExportFilter.php | 30 ------------------- .../src/Event/ValueObject/ExportedEvent.php | 1 + .../src/Event/ValueObject/ExportedEvents.php | 3 ++ .../src/ExportService.php | 7 +++-- .../src/ExportServiceFactory.php | 1 + .../src/ImportService.php | 8 +++-- .../src/ImportServiceFactory.php | 1 + .../src/Processors/AssetExportProcessor.php | 1 + .../AssetRepositoryImportProcessor.php | 1 + .../src/Processors/EventExportProcessor.php | 4 +++ .../Processors/EventStoreImportProcessor.php | 6 +++- phpstan.neon => phpstan.neon.dist | 3 +- 18 files changed, 50 insertions(+), 46 deletions(-) delete mode 100644 Neos.ContentRepository.Export/src/Event/ValueObject/ExportFilter.php rename phpstan.neon => phpstan.neon.dist (95%) diff --git a/Neos.ContentRepository.Export/src/Asset/Adapters/DbalAssetLoader.php b/Neos.ContentRepository.Export/src/Asset/Adapters/DbalAssetLoader.php index a17b85a8121..2538395b10b 100644 --- a/Neos.ContentRepository.Export/src/Asset/Adapters/DbalAssetLoader.php +++ b/Neos.ContentRepository.Export/src/Asset/Adapters/DbalAssetLoader.php @@ -57,9 +57,8 @@ public function findAssetById(string $assetId): SerializedAsset|SerializedImageV 'neos_media_adjustment_resizeimageadjustment' => ImageAdjustmentType::RESIZE_IMAGE, 'neos_media_adjustment_cropimageadjustment' => ImageAdjustmentType::CROP_IMAGE, 'neos_media_adjustment_qualityimageadjustment' => ImageAdjustmentType::QUALITY_IMAGE, + default => throw new \InvalidArgumentException(sprintf('Invalid "dtype" in image adjustment row. Got "%s"', $imageAdjustmentRow['dtype']), 1698583820) }; - #unset($imageAdjustmentRow['persistence_object_identifier'], $imageAdjustmentRow['imagevariant'], $imageAdjustmentRow['dtype']); - #$imageAdjustmentRow = array_filter($imageAdjustmentRow, static fn ($value) => $value !== null); $imageAdjustments[] = ['type' => $type->value, 'properties' => $type->convertProperties($imageAdjustmentRow)]; } return SerializedImageVariant::fromArray([ @@ -82,11 +81,13 @@ public function findAssetById(string $assetId): SerializedAsset|SerializedImageV unset($row[$key]); } $row['type'] = match ($row['type']) { - 'neos_media_image' => AssetType::IMAGE->value, - 'neos_media_audio' => AssetType::AUDIO->value, - 'neos_media_document' => AssetType::DOCUMENT->value, - 'neos_media_video' => AssetType::VIDEO->value, + 'neos_media_image' => AssetType::IMAGE->value, + 'neos_media_audio' => AssetType::AUDIO->value, + 'neos_media_document' => AssetType::DOCUMENT->value, + 'neos_media_video' => AssetType::VIDEO->value, + default => throw new \InvalidArgumentException(sprintf('Invalid "type" in asset row. Got "%s"', $row['type']), 1698583897) }; + /** @phpstan-ignore-next-line */ return SerializedAsset::fromArray($row); } } diff --git a/Neos.ContentRepository.Export/src/Asset/Adapters/FileSystemResourceLoader.php b/Neos.ContentRepository.Export/src/Asset/Adapters/FileSystemResourceLoader.php index 59bf4a36c0e..6a5e1511759 100644 --- a/Neos.ContentRepository.Export/src/Asset/Adapters/FileSystemResourceLoader.php +++ b/Neos.ContentRepository.Export/src/Asset/Adapters/FileSystemResourceLoader.php @@ -21,6 +21,10 @@ public function getStreamBySha1(string $sha1) if (!is_readable($resourcePath)) { throw new \RuntimeException(sprintf('Resource file "%s" is not readable', $resourcePath), 1658583621); } - return fopen($resourcePath, 'rb'); + $stream = fopen($resourcePath, 'rb'); + if (!is_resource($stream)) { + throw new \RuntimeException(sprintf('Could not open stream to resource file "%s"', $resourcePath), 1698584155); + } + return $stream; } } diff --git a/Neos.ContentRepository.Export/src/Asset/AssetExporter.php b/Neos.ContentRepository.Export/src/Asset/AssetExporter.php index 1b8e7a970d2..3ce343eebb2 100644 --- a/Neos.ContentRepository.Export/src/Asset/AssetExporter.php +++ b/Neos.ContentRepository.Export/src/Asset/AssetExporter.php @@ -7,6 +7,7 @@ final class AssetExporter { + /** @var array */ private array $exportedAssetIds = []; public function __construct( diff --git a/Neos.ContentRepository.Export/src/Asset/ValueObject/ImageAdjustmentType.php b/Neos.ContentRepository.Export/src/Asset/ValueObject/ImageAdjustmentType.php index 217d768df8c..ad614cc0f16 100644 --- a/Neos.ContentRepository.Export/src/Asset/ValueObject/ImageAdjustmentType.php +++ b/Neos.ContentRepository.Export/src/Asset/ValueObject/ImageAdjustmentType.php @@ -8,6 +8,10 @@ enum ImageAdjustmentType: string case CROP_IMAGE = 'CROP_IMAGE'; case QUALITY_IMAGE = 'QUALITY_IMAGE'; + /** + * @param array $data + * @return array + */ public function convertProperties(array $data): array { $data = array_change_key_case($data); diff --git a/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedAsset.php b/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedAsset.php index bbb6b132fe0..dc318575eb2 100644 --- a/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedAsset.php +++ b/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedAsset.php @@ -30,11 +30,12 @@ public static function fromAsset(Asset $asset): self if ($resource === null) { throw new \InvalidArgumentException(sprintf('Failed to load resource for asset "%s"', $asset->getIdentifier()), 1645871592); } - $type = match (TypeHandling::getTypeForValue($asset)) { + $type = match ($typeForValue = TypeHandling::getTypeForValue($asset)) { Image::class => AssetType::IMAGE, Audio::class => AssetType::AUDIO, Document::class => AssetType::DOCUMENT, Video::class => AssetType::VIDEO, + default => throw new \InvalidArgumentException(sprintf('Invalid asset type "%s" for asset "%s"', $typeForValue, $asset->getIdentifier()), 1698584356) }; return new self( $asset->getIdentifier(), diff --git a/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedImageAdjustment.php b/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedImageAdjustment.php index 6449a1e5255..73c504f1434 100644 --- a/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedImageAdjustment.php +++ b/Neos.ContentRepository.Export/src/Asset/ValueObject/SerializedImageAdjustment.php @@ -19,10 +19,11 @@ private function __construct( public static function fromImageAdjustment(ImageAdjustmentInterface $adjustment): self { - $type = match(TypeHandling::getTypeForValue($adjustment)) { + $type = match($typeForValue = TypeHandling::getTypeForValue($adjustment)) { ResizeImageAdjustment::class => ImageAdjustmentType::RESIZE_IMAGE, CropImageAdjustment::class => ImageAdjustmentType::CROP_IMAGE, QualityImageAdjustment::class => ImageAdjustmentType::QUALITY_IMAGE, + default => throw new \InvalidArgumentException(sprintf('Invalid image adjustment type "%s"', $typeForValue), 1698584402) }; return new self($type, $type->convertProperties(ObjectAccess::getGettableProperties($adjustment))); } diff --git a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportFilter.php b/Neos.ContentRepository.Export/src/Event/ValueObject/ExportFilter.php deleted file mode 100644 index fb3d7b507d3..00000000000 --- a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportFilter.php +++ /dev/null @@ -1,30 +0,0 @@ -minimumSequenceNumber); - } - - public function withMinimumSequenceNumber(int $minimumSequenceNumber): self - { - return new self($this->streamName, $minimumSequenceNumber); - } - -} diff --git a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvent.php b/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvent.php index 981f6674b35..ac765f5d3e5 100644 --- a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvent.php +++ b/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvent.php @@ -85,6 +85,7 @@ public function toJson(): string */ public function jsonSerialize(): array { + /** @phpstan-ignore-next-line */ return get_object_vars($this); } } diff --git a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvents.php b/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvents.php index 8fffa5e4438..25736270f0a 100644 --- a/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvents.php +++ b/Neos.ContentRepository.Export/src/Event/ValueObject/ExportedEvents.php @@ -13,6 +13,9 @@ private function __construct( ) { } + /** + * @param iterable $events + */ public static function fromIterable(iterable $events): self { return new self(function () use ($events) { diff --git a/Neos.ContentRepository.Export/src/ExportService.php b/Neos.ContentRepository.Export/src/ExportService.php index 39efb36fcb6..c4f67e2e24d 100644 --- a/Neos.ContentRepository.Export/src/ExportService.php +++ b/Neos.ContentRepository.Export/src/ExportService.php @@ -29,13 +29,14 @@ public function __construct( public function runAllProcessors(\Closure $outputLineFn, bool $verbose = false): void { + /** @var array $processors */ $processors = [ - 'Exporting events' => new EventExportProcessor( + 'Exporting events' => new EventExportProcessor( $this->filesystem, $this->workspaceFinder, $this->eventStore ), - 'Exporting assets' => new AssetExportProcessor( + 'Exporting assets' => new AssetExportProcessor( $this->filesystem, $this->assetRepository, $this->workspaceFinder, @@ -50,7 +51,7 @@ public function runAllProcessors(\Closure $outputLineFn, bool $verbose = false): ); $result = $processor->run(); if ($result->severity === Severity::ERROR) { - throw new \RuntimeException($label . ': ' . $result->message ?? ''); + throw new \RuntimeException($label . ': ' . ($result->message ?? '')); } $outputLineFn(' ' . $result->message); $outputLineFn(); diff --git a/Neos.ContentRepository.Export/src/ExportServiceFactory.php b/Neos.ContentRepository.Export/src/ExportServiceFactory.php index 4db2ae126a5..fe3bd97428f 100644 --- a/Neos.ContentRepository.Export/src/ExportServiceFactory.php +++ b/Neos.ContentRepository.Export/src/ExportServiceFactory.php @@ -12,6 +12,7 @@ /** * @internal + * @implements ContentRepositoryServiceFactoryInterface */ class ExportServiceFactory implements ContentRepositoryServiceFactoryInterface { diff --git a/Neos.ContentRepository.Export/src/ImportService.php b/Neos.ContentRepository.Export/src/ImportService.php index e2ea7ebf390..3228f1ca588 100644 --- a/Neos.ContentRepository.Export/src/ImportService.php +++ b/Neos.ContentRepository.Export/src/ImportService.php @@ -67,7 +67,7 @@ public function runAllProcessors(\Closure $outputLineFn, bool $verbose = false): ); $result = $processor->run(); if ($result->severity === Severity::ERROR) { - throw new \RuntimeException($label . ': ' . $result->message ?? ''); + throw new \RuntimeException($label . ': ' . ($result->message ?? '')); } $outputLineFn(' ' . $result->message); $outputLineFn(); @@ -77,6 +77,10 @@ public function runAllProcessors(\Closure $outputLineFn, bool $verbose = false): private function liveWorkspaceContentStreamExists(): bool { $workspaceStreamName = WorkspaceEventStreamName::fromWorkspaceName(WorkspaceName::forLive())->getEventStreamName(); - return $this->eventStore->load($workspaceStreamName)->getIterator()->current() !== null; + $eventStream = $this->eventStore->load($workspaceStreamName); + foreach ($eventStream as $event) { + return true; + } + return false; } } diff --git a/Neos.ContentRepository.Export/src/ImportServiceFactory.php b/Neos.ContentRepository.Export/src/ImportServiceFactory.php index 01dcd295bbd..fe3b10ce692 100644 --- a/Neos.ContentRepository.Export/src/ImportServiceFactory.php +++ b/Neos.ContentRepository.Export/src/ImportServiceFactory.php @@ -14,6 +14,7 @@ /** * @internal + * @implements ContentRepositoryServiceFactoryInterface */ class ImportServiceFactory implements ContentRepositoryServiceFactoryInterface { diff --git a/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php b/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php index 9703f54e7a8..6b1cee5310b 100644 --- a/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php @@ -25,6 +25,7 @@ */ final class AssetExportProcessor implements ProcessorInterface { + /** @var array */ private array $callbacks = []; public function __construct( diff --git a/Neos.ContentRepository.Export/src/Processors/AssetRepositoryImportProcessor.php b/Neos.ContentRepository.Export/src/Processors/AssetRepositoryImportProcessor.php index 2f5d038a637..b389adababa 100644 --- a/Neos.ContentRepository.Export/src/Processors/AssetRepositoryImportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/AssetRepositoryImportProcessor.php @@ -34,6 +34,7 @@ */ final class AssetRepositoryImportProcessor implements ProcessorInterface { + /** @var array */ private array $callbacks = []; public function __construct( diff --git a/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php b/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php index 5241e4e9d06..37354c7fbac 100644 --- a/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php @@ -18,6 +18,7 @@ */ final class EventExportProcessor implements ProcessorInterface { + /** @var array */ private array $callbacks = []; public function __construct( @@ -64,6 +65,9 @@ public function run(): ProcessorResult /** --------------------------------------- */ + /** + * @phpstan-ignore-next-line currently this private method is unused ... but it does no harm keeping it + */ private function dispatch(Severity $severity, string $message, mixed ...$args): void { $renderedMessage = sprintf($message, ...$args); diff --git a/Neos.ContentRepository.Export/src/Processors/EventStoreImportProcessor.php b/Neos.ContentRepository.Export/src/Processors/EventStoreImportProcessor.php index 5e335674503..9afa36dc0cc 100644 --- a/Neos.ContentRepository.Export/src/Processors/EventStoreImportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/EventStoreImportProcessor.php @@ -34,6 +34,7 @@ */ final class EventStoreImportProcessor implements ProcessorInterface { + /** @var array */ private array $callbacks = []; public function __construct( @@ -97,7 +98,7 @@ public function run(): ProcessorResult new Event( EventId::fromString($event->identifier), Event\EventType::fromString($event->type), - Event\EventData::fromString(\json_encode($event->payload)), + Event\EventData::fromString(\json_encode($event->payload, JSON_THROW_ON_ERROR)), Event\EventMetadata::fromArray($event->metadata) ) ); @@ -188,6 +189,9 @@ private static function extractContentStreamId(array $payload): ContentStreamId return ContentStreamId::fromString($payload['contentStreamId']); } + /** + * @phpstan-ignore-next-line currently this private method is unused ... but it does no harm keeping it + */ private function dispatch(Severity $severity, string $message, mixed ...$args): void { $renderedMessage = sprintf($message, ...$args); diff --git a/phpstan.neon b/phpstan.neon.dist similarity index 95% rename from phpstan.neon rename to phpstan.neon.dist index 94edcc099fe..40321236689 100644 --- a/phpstan.neon +++ b/phpstan.neon.dist @@ -4,9 +4,10 @@ parameters: - Neos.ContentGraph.DoctrineDbalAdapter/src - Neos.ContentGraph.PostgreSQLAdapter/src - Neos.ContentRepository.BehavioralTests/Classes - - Neos.ContentRepository.TestSuite/Classes + - Neos.ContentRepository.Export/src - Neos.ContentRepository.Core/Classes - Neos.ContentRepository.LegacyNodeMigration/Classes + - Neos.ContentRepository.TestSuite/Classes - Neos.Neos/Classes excludePaths: analyse: From 074a472b3cd74d601f51e727f8cc7e173b397fef Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 29 Oct 2023 15:12:20 +0100 Subject: [PATCH 2/7] TASK: Fix types from `Neos.ContentRepository.NodeAccess` --- .../BackReferenceNodesOperation.php | 2 ++ .../BackReferencesOperation.php | 2 ++ .../FlowQueryOperations/ChildrenOperation.php | 1 + .../FlowQueryOperations/FilterOperation.php | 23 +++++++++++-------- .../FlowQueryOperations/PropertyOperation.php | 2 +- .../ReferenceNodesOperation.php | 2 ++ .../ReferencePropertyOperation.php | 4 +++- .../ReferencesOperation.php | 2 ++ .../FlowQueryOperations/RemoveOperation.php | 2 ++ .../FlowQueryOperations/UniqueOperation.php | 4 +++- phpstan.neon.dist | 3 ++- 11 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferenceNodesOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferenceNodesOperation.php index 9be0c0ec39d..d6c137d01af 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferenceNodesOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferenceNodesOperation.php @@ -43,11 +43,13 @@ final class BackReferenceNodesOperation implements OperationInterface */ protected $contentRepositoryRegistry; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $output = []; diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferencesOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferencesOperation.php index a57c73573f6..4330d0902d8 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferencesOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/BackReferencesOperation.php @@ -49,11 +49,13 @@ final class BackReferencesOperation implements OperationInterface */ protected $contentRepositoryRegistry; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $output = []; diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php index a9fa661d1b8..a7fb5b17bac 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php @@ -201,6 +201,7 @@ protected function earlyOptimizationOfFilters(FlowQuery $flowQuery, array $parse // Add filtered nodes to output /** @var Node $filteredNode */ foreach ($filteredOutput as $filteredNode) { + /** @phpstan-ignore-next-line undefined behaviour https://github.com/neos/neos-development-collection/issues/4507#issuecomment-1784123143 */ if (!isset($outputNodeAggregateIds[$filteredNode->nodeAggregateId->value])) { $output[] = $filteredNode; } diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php index 3e1ad35fb14..040dc4703cb 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php @@ -12,8 +12,11 @@ */ use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Eel\FlowQuery\FlowQuery; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; use Neos\Utility\ObjectAccess; +use Neos\Flow\Annotations as Flow; /** * This filter implementation contains specific behavior for use on ContentRepository @@ -31,6 +34,11 @@ */ class FilterOperation extends \Neos\Eel\FlowQuery\Operations\Object\FilterOperation { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + /** * {@inheritdoc} * @@ -41,7 +49,7 @@ class FilterOperation extends \Neos\Eel\FlowQuery\Operations\Object\FilterOperat /** * {@inheritdoc} * - * @param array $context $context onto which this operation should be applied (array or array-like object) + * @param array $context $context onto which this operation should be applied (array or array-like object) * @return boolean true if the operation can be applied onto the $context, false otherwise */ public function canEvaluate($context) @@ -53,7 +61,7 @@ public function canEvaluate($context) * {@inheritdoc} * * @param FlowQuery $flowQuery - * @param array $arguments + * @param array $arguments * @return void */ public function evaluate(FlowQuery $flowQuery, array $arguments) @@ -86,13 +94,8 @@ public function evaluate(FlowQuery $flowQuery, array $arguments) */ protected function matchesPropertyNameFilter($element, $propertyNameFilter) { - /* @var Node $element */ - try { - return ((string)$element->nodeName === $propertyNameFilter); - } catch (\InvalidArgumentException $e) { - // in case the Element has no valid node name, we do not match! - return false; - } + assert($element instanceof Node); + return $element->nodeName?->value === $propertyNameFilter; } /** @@ -142,7 +145,7 @@ protected function evaluateOperator($value, $operator, $operand) } elseif ($operand === Node::class) { return true; } else { - $isOfType = $value->nodeType->isOfType($operand[0] === '!' ? substr($operand, 1) : $operand); + $isOfType = $this->getNodeType($value)->isOfType($operand[0] === '!' ? substr($operand, 1) : $operand); return $operand[0] === '!' ? $isOfType === false : $isOfType; } } elseif ($operator === '!instanceof' && $value instanceof Node) { diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/PropertyOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/PropertyOperation.php index 127a0244727..013f087d04a 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/PropertyOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/PropertyOperation.php @@ -61,7 +61,7 @@ class PropertyOperation extends AbstractOperation * * We can only handle ContentRepository Nodes. * - * @param array $context $context onto which this operation should be applied (array or array-like object) + * @param array $context $context onto which this operation should be applied (array or array-like object) * @return boolean */ public function canEvaluate($context): bool diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferenceNodesOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferenceNodesOperation.php index 489abbe0792..249a28ca21d 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferenceNodesOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferenceNodesOperation.php @@ -42,11 +42,13 @@ final class ReferenceNodesOperation implements OperationInterface */ protected $contentRepositoryRegistry; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $output = []; diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencePropertyOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencePropertyOperation.php index 345b18530ed..6acc86ec061 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencePropertyOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencePropertyOperation.php @@ -29,6 +29,7 @@ final class ReferencePropertyOperation implements OperationInterface { + /** @param array $context */ public function canEvaluate($context): bool { return (isset($context[0]) && $context[0] instanceof Reference); @@ -36,6 +37,7 @@ public function canEvaluate($context): bool /** * @throws FlowQueryException + * @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): mixed { @@ -48,7 +50,7 @@ public function evaluate(FlowQuery $flowQuery, array $arguments): mixed if (!$element instanceof Reference) { return null; } - return $element->properties[$arguments[0]]; + return $element->properties[$arguments[0]] ?? null; } public static function getShortName(): string diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencesOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencesOperation.php index 8b620879b37..e4de83ce9e0 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencesOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ReferencesOperation.php @@ -47,11 +47,13 @@ final class ReferencesOperation implements OperationInterface */ protected $contentRepositoryRegistry; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $output = []; diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/RemoveOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/RemoveOperation.php index a954acc32c2..1b189ddd1e5 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/RemoveOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/RemoveOperation.php @@ -34,11 +34,13 @@ final class RemoveOperation implements OperationInterface { use CreateNodeHashTrait; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $nodeHashesToRemove = []; diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/UniqueOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/UniqueOperation.php index 651e9405e41..113d6bfd7e9 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/UniqueOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/UniqueOperation.php @@ -35,15 +35,17 @@ final class UniqueOperation implements OperationInterface { use CreateNodeHashTrait; + /** @param array $context */ public function canEvaluate($context): bool { return count($context) === 0 || (isset($context[0]) && ($context[0] instanceof Node)); } + /** @param array $arguments */ public function evaluate(FlowQuery $flowQuery, array $arguments): void { $nodesByHash = []; - /** @var Node $contextNode */ + /** @var Node $node */ foreach ($flowQuery->getContext() as $node) { $hash = $this->createNodeHash($node); if (!array_key_exists($hash, $nodesByHash)) { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 40321236689..2c3134647e0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -4,9 +4,10 @@ parameters: - Neos.ContentGraph.DoctrineDbalAdapter/src - Neos.ContentGraph.PostgreSQLAdapter/src - Neos.ContentRepository.BehavioralTests/Classes - - Neos.ContentRepository.Export/src - Neos.ContentRepository.Core/Classes + - Neos.ContentRepository.Export/src - Neos.ContentRepository.LegacyNodeMigration/Classes + - Neos.ContentRepository.NodeAccess/Classes - Neos.ContentRepository.TestSuite/Classes - Neos.Neos/Classes excludePaths: From aa3dbe7cc9b6fc8a08cf2d80e517f66f4ff3cf04 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 29 Oct 2023 15:20:15 +0100 Subject: [PATCH 3/7] TASK: Fix types from `Neos.ContentRepository.StructureAdjustment` --- .../Classes/FlowQueryOperations/FilterOperation.php | 1 + .../src/Adjustment/PropertyAdjustment.php | 2 +- .../src/Adjustment/TetheredNodeAdjustments.php | 3 ++- .../src/StructureAdjustmentServiceFactory.php | 5 ----- phpstan.neon.dist | 1 + 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php index 040dc4703cb..ea212ea5182 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FilterOperation.php @@ -141,6 +141,7 @@ protected function evaluateOperator($value, $operator, $operand) { if ($operator === 'instanceof' && $value instanceof Node) { if ($this->operandIsSimpleType($operand)) { + /** @phpstan-ignore-next-line Flow does not properly declare its types here */ return $this->handleSimpleTypeOperand($operand, $value); } elseif ($operand === Node::class) { return true; diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php index f84c7a74524..c87bdf6a8e4 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php @@ -101,7 +101,7 @@ private function removeProperty(NodeAggregate $nodeAggregate, Node $node, string private function addProperty(NodeAggregate $nodeAggregate, Node $node, string $propertyKey, mixed $defaultValue): EventsToPublish { - $propertyType = $node->nodeType->getPropertyType($propertyKey); + $propertyType = $node->nodeType?->getPropertyType($propertyKey) ?? 'string'; $serializedPropertyValues = SerializedPropertyValues::fromArray([ $propertyKey => new SerializedPropertyValue($defaultValue, $propertyType) ]); diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 994672b390e..7d250715afb 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -111,7 +111,7 @@ function () use ($nodeAggregate, $node, $tetheredNodeName, $expectedTetheredNode $nodeAggregate->nodeAggregateId ); foreach ($tetheredNodeAggregates as $tetheredNodeAggregate) { - /* @var $tetheredNodeAggregate NodeAggregate */ + assert($tetheredNodeAggregate->nodeName !== null); // it's tethered! if (!isset($expectedTetheredNodes[$tetheredNodeAggregate->nodeName->value])) { $foundMissingOrDisallowedTetheredNodes = true; yield StructureAdjustment::createForNodeAggregate( @@ -141,6 +141,7 @@ function () use ($tetheredNodeAggregate) { $actualTetheredChildNodes = []; foreach ($childNodes as $childNode) { if ($childNode->classification->isTethered()) { + assert($childNode->nodeName !== null); // it's tethered! $actualTetheredChildNodes[$childNode->nodeName->value] = $childNode; } } diff --git a/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentServiceFactory.php b/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentServiceFactory.php index e18b224ee62..8d835c29b51 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentServiceFactory.php +++ b/Neos.ContentRepository.StructureAdjustment/src/StructureAdjustmentServiceFactory.php @@ -13,11 +13,6 @@ */ class StructureAdjustmentServiceFactory implements ContentRepositoryServiceFactoryInterface { - - /** - * @param ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies - * @return ContentRepositoryServiceInterface - */ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): StructureAdjustmentService { return new StructureAdjustmentService( diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2c3134647e0..6721fac98b9 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,6 +8,7 @@ parameters: - Neos.ContentRepository.Export/src - Neos.ContentRepository.LegacyNodeMigration/Classes - Neos.ContentRepository.NodeAccess/Classes + - Neos.ContentRepository.StructureAdjustment/src - Neos.ContentRepository.TestSuite/Classes - Neos.Neos/Classes excludePaths: From 0976d919a6268f58e05f827793cd78fecd12c1ea Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Wed, 1 Nov 2023 12:33:10 +0100 Subject: [PATCH 4/7] TASK: Correctly type `Neos.ContentRepositoryRegistry` --- .../Classes/Projection/Projections.php | 8 ++++ .../Command/ContentCommandController.php | 3 +- .../NodeMigrationCommandController.php | 8 +--- ...cessProjectionCatchUpCommandController.php | 5 ++- .../NodeTypeEnrichmentService.php | 6 ++- .../Classes/Configuration/NodeTypesLoader.php | 7 ++-- .../Configuration/SuperTypeConfigResolver.php | 13 +++++++ .../Classes/ContentRepositoryRegistry.php | 8 ++++ .../Factory/Clock/ClockFactoryInterface.php | 1 + .../Factory/Clock/SystemClockFactory.php | 1 + ...tionBasedContentDimensionSourceFactory.php | 1 + ...ContentDimensionSourceFactoryInterface.php | 1 + .../EventStore/DoctrineEventStoreFactory.php | 1 + .../EventStore/EventStoreFactoryInterface.php | 1 + .../DefaultNodeTypeManagerFactory.php | 1 + .../NodeTypeManagerFactoryInterface.php | 1 + ...ojectionCatchUpTriggerFactoryInterface.php | 2 +- .../SubprocessProjectionCatchUpTrigger.php | 2 +- ...processProjectionCatchUpTriggerFactory.php | 1 + .../StaticUserIdProviderFactory.php | 1 + .../UserIdProviderFactoryInterface.php | 1 + .../Infrastructure/GenericObjectFactory.php | 5 ++- .../Normalizer/ProxyAwareObjectNormalizer.php | 14 ++++++- .../PropertyConversionSerializerFactory.php | 38 ------------------- .../Migration/Configuration/Configuration.php | 17 +++++---- .../Configuration/ConfigurationInterface.php | 6 +-- .../Configuration/YamlConfiguration.php | 7 +++- .../Migration/Factory/MigrationFactory.php | 6 +++ .../ExpressionBasedNodeLabelGenerator.php | 20 ++-------- .../Classes/Package.php | 3 ++ .../Service/ProjectionReplayService.php | 9 ++++- phpstan.neon.dist | 1 + 32 files changed, 111 insertions(+), 88 deletions(-) delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Infrastructure/PropertyConversionSerializerFactory.php diff --git a/Neos.ContentRepository.Core/Classes/Projection/Projections.php b/Neos.ContentRepository.Core/Classes/Projection/Projections.php index 1d5d2d6f431..e9910356908 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Projections.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Projections.php @@ -78,6 +78,14 @@ public function has(string $projectionClassName): bool return array_key_exists($projectionClassName, $this->projections); } + /** + * @return list>> + */ + public function getClassNames(): array + { + return array_keys($this->projections); + } + /** * @return \Traversable> */ diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php index 691ebe85b25..af6c9e041d2 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php @@ -180,7 +180,8 @@ public function createVariantsRecursivelyCommand(string $source, string $target, $this->outputLine('Done!'); } - private function createVariantRecursivelyInternal(int $level, NodeAggregateId $parentNodeAggregateId, ContentSubgraphInterface $sourceSubgraph, OriginDimensionSpacePoint $target, ContentStreamId $contentStreamId, ContentRepository $contentRepository) { + private function createVariantRecursivelyInternal(int $level, NodeAggregateId $parentNodeAggregateId, ContentSubgraphInterface $sourceSubgraph, OriginDimensionSpacePoint $target, ContentStreamId $contentStreamId, ContentRepository $contentRepository): void + { $childNodes = $sourceSubgraph->findChildNodes( $parentNodeAggregateId, FindChildNodesFilter::create() diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/NodeMigrationCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/NodeMigrationCommandController.php index 86955520f8f..d600334d299 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/NodeMigrationCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/NodeMigrationCommandController.php @@ -102,13 +102,7 @@ public function kickstartCommand(string $packageKey): void $this->quit(1); } - try { - $createdMigration = $this->nodeMigrationGeneratorService->generateBoilerplateMigrationFileInPackage($packageKey); - } catch (MigrationException $e) { - $this->outputLine(); - $this->outputLine('Error ' . $e->getMessage()); - $this->quit(1); - } + $createdMigration = $this->nodeMigrationGeneratorService->generateBoilerplateMigrationFileInPackage($packageKey); $this->outputLine($createdMigration); $this->outputLine('Your node migration has been created successfully.'); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php index a654d053fcc..d30d9eca6a6 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/SubprocessProjectionCatchUpCommandController.php @@ -4,6 +4,8 @@ namespace Neos\ContentRepositoryRegistry\Command; use Neos\ContentRepository\Core\Projection\CatchUpOptions; +use Neos\ContentRepository\Core\Projection\ProjectionInterface; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger\SubprocessProjectionCatchUpTrigger; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; @@ -24,12 +26,11 @@ class SubprocessProjectionCatchUpCommandController extends CommandController /** * @param string $contentRepositoryIdentifier - * @param string $projectionClassName fully qualified class name of the projection to catch up + * @param class-string> $projectionClassName fully qualified class name of the projection to catch up * @internal */ public function catchupCommand(string $contentRepositoryIdentifier, string $projectionClassName): void { - $contentRepository = $this->contentRepositoryRegistry->get(ContentRepositoryId::fromString($contentRepositoryIdentifier)); $contentRepository->catchUpProjection($projectionClassName, CatchUpOptions::create()); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypeEnrichmentService.php b/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypeEnrichmentService.php index 57621fc6f9c..1254cae2f1a 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypeEnrichmentService.php +++ b/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypeEnrichmentService.php @@ -35,6 +35,10 @@ class NodeTypeEnrichmentService */ protected $resourceManager; + /** + * @param array $fullConfiguration + * @return array + */ public function enrichNodeTypeLabelsConfiguration(array $fullConfiguration): array { $superTypeConfigResolver = new SuperTypeConfigResolver($fullConfiguration); @@ -86,7 +90,7 @@ protected function setPropertyLabels(string $nodeTypeName, array &$configuration $editorName = $propertyConfiguration['ui']['inspector']['editor'] ?? array_reduce($superTypeConfigResolver->getSuperTypesFor($nodeTypeName), function ($editorName, $superTypeName) use ($propertyName, $superTypeConfigResolver) { - if ($editorName !== null || $superTypeName === null) { + if ($editorName !== null) { return $editorName; } $superTypeConfiguration = $superTypeConfigResolver->getLocalConfiguration($superTypeName); diff --git a/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypesLoader.php b/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypesLoader.php index d1666273368..d19628fcdf4 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypesLoader.php +++ b/Neos.ContentRepositoryRegistry/Classes/Configuration/NodeTypesLoader.php @@ -8,7 +8,7 @@ use Neos\Flow\Configuration\Source\YamlSource; use Neos\Flow\Core\ApplicationContext; use Neos\Flow\Core\Bootstrap; -use Neos\Flow\Package\PackageInterface; +use Neos\Flow\Package\FlowPackageInterface; use Neos\Utility\Arrays; use Neos\Utility\Files; @@ -24,6 +24,7 @@ class NodeTypesLoader implements LoaderInterface */ private $configurationBasePath; + /** @phpstan-ignore-next-line FLOW_PATH_CONFIGURATION not found */ public function __construct(YamlSource $yamlSource, string $configurationBasePath = FLOW_PATH_CONFIGURATION, protected readonly ?Bootstrap $bootstrap = null) { $this->yamlSource = $yamlSource; @@ -31,9 +32,9 @@ public function __construct(YamlSource $yamlSource, string $configurationBasePat } /** - * @param PackageInterface[] $packages + * @param FlowPackageInterface[] $packages * @param ApplicationContext $context - * @return array + * @return array * @throws ParseErrorException | ConfigurationException */ public function load(array $packages, ApplicationContext $context): array diff --git a/Neos.ContentRepositoryRegistry/Classes/Configuration/SuperTypeConfigResolver.php b/Neos.ContentRepositoryRegistry/Classes/Configuration/SuperTypeConfigResolver.php index c9d06985477..5a77266f87f 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Configuration/SuperTypeConfigResolver.php +++ b/Neos.ContentRepositoryRegistry/Classes/Configuration/SuperTypeConfigResolver.php @@ -21,12 +21,22 @@ */ class SuperTypeConfigResolver { + /** + * @var array> + */ private array $superTypeCache; + /** + * @param array $fullConfiguration + */ public function __construct(private readonly array $fullConfiguration) { } + /** + * @param string $nodeTypeName + * @return list + */ public function getSuperTypesFor(string $nodeTypeName): array { if (isset($this->superTypeCache[$nodeTypeName])) { @@ -46,6 +56,9 @@ public function getSuperTypesFor(string $nodeTypeName): array return $enabledSuperTypesRecursively; } + /** + * @return array + */ public function getLocalConfiguration(string $nodeTypeName): array { return $this->fullConfiguration[$nodeTypeName] ?? []; diff --git a/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php b/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php index bd4e5fc0492..ef9882db035 100644 --- a/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php +++ b/Neos.ContentRepositoryRegistry/Classes/ContentRepositoryRegistry.php @@ -148,6 +148,7 @@ private function buildFactory(ContentRepositoryId $contentRepositoryId): Content } } + /** @param array $contentRepositorySettings */ private function buildEventStore(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings, ClockInterface $clock): EventStoreInterface { isset($contentRepositorySettings['eventStore']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have eventStore.factoryObjectName configured.', $contentRepositoryId->value); @@ -158,6 +159,7 @@ private function buildEventStore(ContentRepositoryId $contentRepositoryId, array return $eventStoreFactory->build($contentRepositoryId, $contentRepositorySettings['eventStore']['options'] ?? [], $clock); } + /** @param array $contentRepositorySettings */ private function buildNodeTypeManager(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): NodeTypeManager { isset($contentRepositorySettings['nodeTypeManager']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have nodeTypeManager.factoryObjectName configured.', $contentRepositoryId->value); @@ -168,6 +170,7 @@ private function buildNodeTypeManager(ContentRepositoryId $contentRepositoryId, return $nodeTypeManagerFactory->build($contentRepositoryId, $contentRepositorySettings['nodeTypeManager']['options'] ?? []); } + /** @param array $contentRepositorySettings */ private function buildContentDimensionSource(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): ContentDimensionSourceInterface { isset($contentRepositorySettings['contentDimensionSource']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have contentDimensionSource.factoryObjectName configured.', $contentRepositoryId->value); @@ -185,6 +188,7 @@ private function buildContentDimensionSource(ContentRepositoryId $contentReposit } + /** @param array $contentRepositorySettings */ private function buildPropertySerializer(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): Serializer { (isset($contentRepositorySettings['propertyConverters']) && is_array($contentRepositorySettings['propertyConverters'])) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have propertyConverters configured, or the value is no array.', $contentRepositoryId->value); @@ -201,6 +205,7 @@ private function buildPropertySerializer(ContentRepositoryId $contentRepositoryI return new Serializer($normalizers); } + /** @param array $contentRepositorySettings */ private function buildProjectionsFactory(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): ProjectionsAndCatchUpHooksFactory { (isset($contentRepositorySettings['projections']) && is_array($contentRepositorySettings['projections'])) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have projections configured, or the value is no array.', $contentRepositoryId->value); @@ -222,6 +227,7 @@ private function buildProjectionsFactory(ContentRepositoryId $contentRepositoryI return $projectionsFactory; } + /** @param array $contentRepositorySettings */ private function buildProjectionCatchUpTrigger(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): ProjectionCatchUpTriggerInterface { isset($contentRepositorySettings['projectionCatchUpTrigger']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have projectionCatchUpTrigger.factoryObjectName configured.', $contentRepositoryId->value); @@ -232,6 +238,7 @@ private function buildProjectionCatchUpTrigger(ContentRepositoryId $contentRepos return $projectionCatchUpTriggerFactory->build($contentRepositoryId, $contentRepositorySettings['projectionCatchUpTrigger']['options'] ?? []); } + /** @param array $contentRepositorySettings */ private function buildUserIdProvider(ContentRepositoryId $contentRepositoryId, array $contentRepositorySettings): UserIdProviderInterface { isset($contentRepositorySettings['userIdProvider']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have userIdProvider.factoryObjectName configured.', $contentRepositoryId->value); @@ -242,6 +249,7 @@ private function buildUserIdProvider(ContentRepositoryId $contentRepositoryId, a return $userIdProviderFactory->build($contentRepositoryId, $contentRepositorySettings['userIdProvider']['options'] ?? []); } + /** @param array $contentRepositorySettings */ private function buildClock(ContentRepositoryId $contentRepositoryIdentifier, array $contentRepositorySettings): ClockInterface { isset($contentRepositorySettings['clock']['factoryObjectName']) || throw InvalidConfigurationException::fromMessage('Content repository "%s" does not have clock.factoryObjectName configured.', $contentRepositoryIdentifier->value); diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/ClockFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/ClockFactoryInterface.php index fb7df5b79f8..acf8ea6b82e 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/ClockFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/ClockFactoryInterface.php @@ -10,5 +10,6 @@ */ interface ClockFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryIdentifier, array $options): ClockInterface; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/SystemClockFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/SystemClockFactory.php index 0d3e7ce7d68..4607a14cc1d 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/SystemClockFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/Clock/SystemClockFactory.php @@ -10,6 +10,7 @@ */ final class SystemClockFactory implements ClockFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryIdentifier, array $options): ClockInterface { return new SystemClock(); diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ConfigurationBasedContentDimensionSourceFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ConfigurationBasedContentDimensionSourceFactory.php index 5711c66bdff..cf084dd9b14 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ConfigurationBasedContentDimensionSourceFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ConfigurationBasedContentDimensionSourceFactory.php @@ -10,6 +10,7 @@ class ConfigurationBasedContentDimensionSourceFactory implements ContentDimensionSourceFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): ContentDimensionSourceInterface { return new ConfigurationBasedContentDimensionSource( diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ContentDimensionSourceFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ContentDimensionSourceFactoryInterface.php index 1356ecf0db0..38fa2b69b45 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ContentDimensionSourceFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ContentDimensionSource/ContentDimensionSourceFactoryInterface.php @@ -7,5 +7,6 @@ interface ContentDimensionSourceFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): ContentDimensionSourceInterface; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php index e74bfb15368..fd4dee91931 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/DoctrineEventStoreFactory.php @@ -16,6 +16,7 @@ public function __construct( ) { } + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options, ClockInterface $clock): EventStoreInterface { return new DoctrineEventStore( diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/EventStoreFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/EventStoreFactoryInterface.php index 64ec9f79ea8..a650afff784 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/EventStoreFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/EventStore/EventStoreFactoryInterface.php @@ -8,5 +8,6 @@ interface EventStoreFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options, ClockInterface $clock): EventStoreInterface; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php index 1486c4ef1ec..bece2c773c2 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php @@ -16,6 +16,7 @@ public function __construct( ) { } + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): NodeTypeManager { return new NodeTypeManager( diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/NodeTypeManagerFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/NodeTypeManagerFactoryInterface.php index 75d0a7d2f1c..b20c3d3fa9c 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/NodeTypeManagerFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/NodeTypeManagerFactoryInterface.php @@ -7,5 +7,6 @@ interface NodeTypeManagerFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): NodeTypeManager; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php index c110ed797e0..c842b697a9a 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/ProjectionCatchUpTriggerFactoryInterface.php @@ -2,11 +2,11 @@ declare(strict_types=1); namespace Neos\ContentRepositoryRegistry\Factory\ProjectionCatchUpTrigger; -use Neos\ContentRepository\Core\Dimension\ContentDimensionSourceInterface; use Neos\ContentRepository\Core\Projection\ProjectionCatchUpTriggerInterface; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; interface ProjectionCatchUpTriggerFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): ProjectionCatchUpTriggerInterface; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php index 0f63d7c06c9..b109aaf54d4 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTrigger.php @@ -16,7 +16,7 @@ class SubprocessProjectionCatchUpTrigger implements ProjectionCatchUpTriggerInte { /** * @Flow\InjectConfiguration(package="Neos.Flow") - * @var array + * @var array */ protected $flowSettings; diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php index 436937e2c0d..0b35b75664d 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/ProjectionCatchUpTrigger/SubprocessProjectionCatchUpTriggerFactory.php @@ -11,6 +11,7 @@ */ class SubprocessProjectionCatchUpTriggerFactory implements ProjectionCatchUpTriggerFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): ProjectionCatchUpTriggerInterface { return new CatchUpTriggerWithSynchronousOption( diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/StaticUserIdProviderFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/StaticUserIdProviderFactory.php index d8f1818ce17..e0763c4e65b 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/StaticUserIdProviderFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/StaticUserIdProviderFactory.php @@ -12,6 +12,7 @@ */ final class StaticUserIdProviderFactory implements UserIdProviderFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): UserIdProviderInterface { return new StaticUserIdProvider(UserId::forSystemUser()); diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/UserIdProviderFactoryInterface.php b/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/UserIdProviderFactoryInterface.php index 90a2f0474b6..9ba542fafce 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/UserIdProviderFactoryInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/UserIdProvider/UserIdProviderFactoryInterface.php @@ -10,5 +10,6 @@ */ interface UserIdProviderFactoryInterface { + /** @param array $options */ public function build(ContentRepositoryId $contentRepositoryId, array $options): UserIdProviderInterface; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/GenericObjectFactory.php b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/GenericObjectFactory.php index 315453b936e..6c52fdea30b 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/GenericObjectFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/GenericObjectFactory.php @@ -19,7 +19,10 @@ */ final class GenericObjectFactory { - public function create(string $className, ...$arguments) + /** + * @param class-string $className + */ + public function create(string $className, mixed ...$arguments): object { return new $className(...$arguments); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php index ec4bd6c36c8..9dceb86186b 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php +++ b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php @@ -7,13 +7,25 @@ /** * An implementation of the ObjectNormalizer that supports Flow proxy classes + * @phpstan-ignore-next-line we extend a class which is annotated as final :( */ final class ProxyAwareObjectNormalizer extends OriginalObjectNormalizer { + /** + * @param string $class + * @param array $data + * @param array $context + * @param \ReflectionClass $reflectionClass + * @param array|bool $allowedAttributes + */ protected function getConstructor(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes): ?\ReflectionMethod { if (interface_exists(ProxyInterface::class) && $reflectionClass->implementsInterface(ProxyInterface::class)) { - return $reflectionClass->getParentClass()->getConstructor(); + $parentReflectionClass = $reflectionClass->getParentClass(); + if ($parentReflectionClass === false) { + throw new \RuntimeException(sprintf('Proxy error. Class "%s" must have a parent class.', $class), 1698652279); + } + return $parentReflectionClass->getConstructor(); } return $reflectionClass->getConstructor(); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/PropertyConversionSerializerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/PropertyConversionSerializerFactory.php deleted file mode 100644 index 34608667227..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/PropertyConversionSerializerFactory.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ - protected array $propertyConvertersConfiguration; - - public function buildSerializer(): Serializer - { - - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/Configuration.php b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/Configuration.php index 51b99783398..eac88b2f937 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/Configuration.php +++ b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/Configuration.php @@ -19,24 +19,25 @@ abstract class Configuration implements ConfigurationInterface { /** - * @var array + * @var array|null */ - protected $availableVersions = null; + protected ?array $availableVersions = null; /** - * @var array + * @var array */ - protected $loadedVersions = []; + protected array $loadedVersions = []; /** * Returns an array with all available versions. * - * @return array + * @return array */ public function getAvailableVersions() { if ($this->availableVersions === null) { $this->registerAvailableVersions(); + assert($this->availableVersions !== null); } return $this->availableVersions; } @@ -59,7 +60,7 @@ public function isVersionAvailable($version) * Returns the configuration of the given version, if available. * * @param string $version - * @return array + * @return array * @throws MigrationException */ public function getMigrationVersion($version) @@ -91,14 +92,14 @@ protected function isVersionLoaded($version) * Loads a specific version into an array. * * @param string $version - * @return array + * @return array */ abstract protected function loadConfiguration($version); /** * Loads a list of available versions into an array. * - * @return array + * @return void */ abstract protected function registerAvailableVersions(); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/ConfigurationInterface.php b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/ConfigurationInterface.php index 713a9dff92f..42c089e1599 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/ConfigurationInterface.php +++ b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/ConfigurationInterface.php @@ -20,7 +20,7 @@ interface ConfigurationInterface /** * Returns all available versions. * - * @return array + * @return array */ public function getAvailableVersions(); @@ -35,8 +35,8 @@ public function isVersionAvailable($version); /** * Returns the migration configuration with the given version. * - * @param string $version - * @return array + * @param string|int $version + * @return array */ public function getMigrationVersion($version); } diff --git a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/YamlConfiguration.php b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/YamlConfiguration.php index eea8eb121f3..a0c2ca282ab 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/YamlConfiguration.php +++ b/Neos.ContentRepositoryRegistry/Classes/Migration/Configuration/YamlConfiguration.php @@ -38,7 +38,7 @@ class YamlConfiguration extends Configuration /** * Loads a list of available versions into an array. * - * @return array + * @return void * @throws MigrationException */ protected function registerAvailableVersions() @@ -47,6 +47,7 @@ protected function registerAvailableVersions() foreach ($this->packageManager->getAvailablePackages() as $package) { $this->registerVersionInDirectory($package, 'ContentRepository'); } + assert(is_array($this->availableVersions)); ksort($this->availableVersions); } @@ -58,6 +59,7 @@ protected function registerAvailableVersions() */ protected function registerVersionInDirectory(PackageInterface $package, string $directoryName) { + assert(is_array($this->availableVersions)); $possibleMigrationsPath = Files::concatenatePaths([$package->getPackagePath(), 'Migrations', $directoryName]); if (!is_dir($possibleMigrationsPath)) { return; @@ -92,7 +94,7 @@ protected function registerVersionInDirectory(PackageInterface $package, string * Loads a specific version into an array. * * @param string $version - * @return array + * @return array * @throws MigrationException */ protected function loadConfiguration($version) @@ -101,6 +103,7 @@ protected function loadConfiguration($version) throw new MigrationException('The requested YamlConfiguration was not available.', 1345822283); } + assert(is_array($this->availableVersions)); $configuration = $this->yamlSourceImporter->load(substr($this->availableVersions[$version]['filePathAndName'], 0, -5)); return $configuration; } diff --git a/Neos.ContentRepositoryRegistry/Classes/Migration/Factory/MigrationFactory.php b/Neos.ContentRepositoryRegistry/Classes/Migration/Factory/MigrationFactory.php index 7040708b228..7ce03b09d58 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Migration/Factory/MigrationFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Migration/Factory/MigrationFactory.php @@ -28,11 +28,17 @@ class MigrationFactory */ protected $migrationConfiguration; + /** + * @param string $version + */ public function getMigrationForVersion($version): MigrationConfiguration { return new MigrationConfiguration($this->migrationConfiguration->getMigrationVersion($version)); } + /** + * @return array + */ public function getAvailableVersions(): array { return $this->migrationConfiguration->getAvailableVersions(); diff --git a/Neos.ContentRepositoryRegistry/Classes/NodeLabel/ExpressionBasedNodeLabelGenerator.php b/Neos.ContentRepositoryRegistry/Classes/NodeLabel/ExpressionBasedNodeLabelGenerator.php index f43c99290ac..059aa150720 100644 --- a/Neos.ContentRepositoryRegistry/Classes/NodeLabel/ExpressionBasedNodeLabelGenerator.php +++ b/Neos.ContentRepositoryRegistry/Classes/NodeLabel/ExpressionBasedNodeLabelGenerator.php @@ -26,13 +26,12 @@ class ExpressionBasedNodeLabelGenerator implements NodeLabelGeneratorInterface { /** * @Flow\Inject - * @var EelEvaluatorInterface */ - protected $eelEvaluator; + protected EelEvaluatorInterface $eelEvaluator; /** * @Flow\InjectConfiguration(package="Neos.ContentRepository", path="labelGenerator.eel.defaultContext") - * @var array + * @var array */ protected $defaultContextConfiguration; @@ -49,24 +48,11 @@ public function getExpression() return $this->expression; } - /** - * @param string $expression - */ - public function setExpression($expression) + public function setExpression(string $expression): void { $this->expression = $expression; } - /** - * @return void - */ - public function initializeObject() - { - if ($this->eelEvaluator instanceof DependencyProxy) { - $this->eelEvaluator->_activateDependency(); - } - } - /** * Render a node label based on an eel expression or return the expression if it is not valid eel. * @throws \Neos\Eel\Exception diff --git a/Neos.ContentRepositoryRegistry/Classes/Package.php b/Neos.ContentRepositoryRegistry/Classes/Package.php index 771ce6a221d..c51e1712ce7 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Package.php +++ b/Neos.ContentRepositoryRegistry/Classes/Package.php @@ -38,6 +38,7 @@ public function boot(Bootstrap $bootstrap) $dispatcher = $bootstrap->getSignalSlotDispatcher(); $dispatcher->connect(ConfigurationManager::class, 'configurationManagerReady', function (ConfigurationManager $configurationManager) use ($bootstrap) { + /** @phpstan-ignore-next-line FLOW_* */ $configurationManager->registerConfigurationType('NodeTypes', new NodeTypesLoader(new YamlSource(), FLOW_PATH_CONFIGURATION, $bootstrap)); }); @@ -63,6 +64,7 @@ public function boot(Bootstrap $bootstrap) } } + /** @phpstan-ignore-next-line FLOW_* */ $nodeTypeConfigurationFileMonitor->monitorDirectory(FLOW_PATH_CONFIGURATION, 'NodeTypes(\..+)\.yaml'); $nodeTypeConfigurationFileMonitor->detectChanges(); @@ -71,6 +73,7 @@ public function boot(Bootstrap $bootstrap) }); $dispatcher->connect(FileMonitor::class, 'filesHaveChanged', static function (string $fileMonitorIdentifier) use ($bootstrap) { if ($fileMonitorIdentifier === 'ContentRepository_NodeTypesConfiguration') { + /** @phpstan-ignore-next-line flow's object manager needs to be a template */ $bootstrap->getObjectManager()->get(ConfigurationManager::class)->refreshConfiguration(); } }); diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php index 8ff1b8ba568..9dec35da709 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php +++ b/Neos.ContentRepositoryRegistry/Classes/Service/ProjectionReplayService.php @@ -6,7 +6,9 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Projection\CatchUpOptions; +use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\Projections; +use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; /** * Content Repository service to perform Projection replays @@ -37,6 +39,9 @@ public function replayAllProjections(CatchUpOptions $options): void } } + /** + * @return class-string> + */ private function resolveProjectionClassName(string $projectionAliasOrClassName): string { $lowerCaseProjectionName = strtolower($projectionAliasOrClassName); @@ -54,7 +59,7 @@ private function resolveProjectionClassName(string $projectionAliasOrClassName): } /** - * @return array + * @return array>, alias: string}> */ private function projectionClassNamesAndAliases(): array { @@ -63,7 +68,7 @@ private function projectionClassNamesAndAliases(): array 'className' => $projectionClassName, 'alias' => self::projectionAlias($projectionClassName), ], - array_keys(iterator_to_array($this->projections)) + $this->projections->getClassNames() ); } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6721fac98b9..80cb04b8fa0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,6 +10,7 @@ parameters: - Neos.ContentRepository.NodeAccess/Classes - Neos.ContentRepository.StructureAdjustment/src - Neos.ContentRepository.TestSuite/Classes + - Neos.ContentRepositoryRegistry/Classes - Neos.Neos/Classes excludePaths: analyse: From 5cf7810984724b927eda4b476effa05ce3612a78 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Wed, 1 Nov 2023 12:34:55 +0100 Subject: [PATCH 5/7] TASK: Revert broken `MigrateEventsCommand` #4265 This is considered a temporary solution, which was also broken. --- .../MigrateEventsCommandController.php | 37 ----- .../Classes/Service/EventMigrationService.php | 143 ------------------ .../Service/EventMigrationServiceFactory.php | 41 ----- 3 files changed, 221 deletions(-) delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Command/MigrateEventsCommandController.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php delete mode 100644 Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationServiceFactory.php diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/MigrateEventsCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/MigrateEventsCommandController.php deleted file mode 100644 index 9fab788c7df..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Command/MigrateEventsCommandController.php +++ /dev/null @@ -1,37 +0,0 @@ -contentRepositoryRegistry->buildService($contentRepositoryId, $this->eventMigrationServiceFactory); - $eventMigrationService->fillAffectedDimensionSpacePointsInNodePropertiesWereSet($this->outputLine(...)); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php b/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php deleted file mode 100644 index 58560e522e3..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationService.php +++ /dev/null @@ -1,143 +0,0 @@ -contentRepositoryId) - . '_bak_' . date('Y_m_d_H_i_s'); - $outputFn('Backup: copying events table to %s', [$backupEventTableName]); - $this->copyEventTable($backupEventTableName); - - $outputFn('Backup completed. Resetting Graph Projection.'); - $this->contentRepository->resetProjectionState(ContentGraphProjection::class); - - $contentGraphProjection = $this->projections->get(ContentGraphProjection::class); - $contentGraph = $contentGraphProjection->getState(); - assert($contentGraph instanceof ContentGraphInterface); - - $streamName = VirtualStreamName::all(); - $eventStream = $this->eventStore->load($streamName); - foreach ($eventStream as $eventEnvelope) { - if ($eventEnvelope->event->type->value === 'NodePropertiesWereSet') { - $eventData = json_decode($eventEnvelope->event->data->value, true); - if (!isset($eventData['affectedDimensionSpacePoints'])) { - // Replay the projection until before the current NodePropertiesWereSet event - $contentGraphProjection->catchUp( - $eventStream->withMaximumSequenceNumber($eventEnvelope->sequenceNumber->previous()), - $this->contentRepository - ); - - // now we can ask the NodeAggregate (read model) for the covered DSPs. - $nodeAggregate = $contentGraph->findNodeAggregateById( - ContentStreamId::fromString($eventData['contentStreamId']), - NodeAggregateId::fromString($eventData['nodeAggregateId']) - ); - $affectedDimensionSpacePoints = $nodeAggregate->getCoverageByOccupant( - OriginDimensionSpacePoint::fromArray($eventData['originDimensionSpacePoint']) - ); - - // ... and update the event - $eventData['affectedDimensionSpacePoints'] = $affectedDimensionSpacePoints->jsonSerialize(); - $outputFn( - 'Rewriting %s: (%s, Origin: %s) => Affected: %s', - [ - $eventEnvelope->sequenceNumber->value, - $eventEnvelope->event->type->value, - json_encode($eventData['originDimensionSpacePoint']), - json_encode($eventData['affectedDimensionSpacePoints']) - ] - ); - $this->updateEvent($eventEnvelope->sequenceNumber, $eventData); - } - } - } - - $outputFn('Rewriting completed. Now catching up the GraphProjection to final state.'); - $contentGraphProjection->catchUp($eventStream, $this->contentRepository); - - if ($this->projections->has(DocumentUriPathProjection::class)) { - $outputFn('Found DocumentUriPathProjection. Will replay this, as it relies on the updated affectedDimensionSpacePoints'); - $documentUriPathProjection = $this->projections->get(DocumentUriPathProjection::class); - $documentUriPathProjection->reset(); - $documentUriPathProjection->catchUp($eventStream, $this->contentRepository); - } - - $outputFn('All done.'); - } - - - private function updateEvent(SequenceNumber $sequenceNumber, array $eventData) - { - $eventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId); - $this->connection->beginTransaction(); - $this->connection->executeStatement( - 'UPDATE ' . $eventTableName . ' SET payload=:payload WHERE sequencenumber=:sequenceNumber', - [ - 'payload' => json_encode($eventData), - 'sequenceNumber' => $sequenceNumber->value - ] - ); - $this->connection->commit(); - } - - private function copyEventTable(string $backupEventTableName) - { - $eventTableName = DoctrineEventStoreFactory::databaseTableName($this->contentRepositoryId); - $this->connection->executeStatement( - 'CREATE TABLE ' . $backupEventTableName . ' AS - SELECT * - FROM ' . $eventTableName - ); - } -} diff --git a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationServiceFactory.php b/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationServiceFactory.php deleted file mode 100644 index 186ec328347..00000000000 --- a/Neos.ContentRepositoryRegistry/Classes/Service/EventMigrationServiceFactory.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @internal this is currently only used by the {@see MigrateEventsCommandController} - */ -#[Flow\Scope("singleton")] -final class EventMigrationServiceFactory implements ContentRepositoryServiceFactoryInterface -{ - public function __construct( - private readonly Connection $connection, - ) {} - - public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): ContentRepositoryServiceInterface - { - if (!($serviceFactoryDependencies->eventStore instanceof DoctrineEventStore)) { - throw new \RuntimeException('EventMigrationService only works with DoctrineEventStore, ' . get_class($serviceFactoryDependencies->eventStore) . ' given'); - } - - return new EventMigrationService( - $serviceFactoryDependencies->projections, - $serviceFactoryDependencies->contentRepositoryId, - $serviceFactoryDependencies->contentRepository, - $serviceFactoryDependencies->eventStore, - $this->connection - ); - } -} From 275a58ae44abed31719527f53c81c2e6a65d6efc Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Wed, 1 Nov 2023 12:44:06 +0100 Subject: [PATCH 6/7] TASK: Flows command controller doesnt declare its types correctly --- phpstan.neon.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 80cb04b8fa0..108878cd883 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,6 +18,7 @@ parameters: - Neos.Neos/Classes/Controller/Module/User/UserSettingsController.php - Neos.Neos/Classes/Controller/Module/Administration/UsersController.php - Neos.Neos/Classes/Controller/Backend/MenuHelper.php + - Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php rules: - Neos\ContentRepository\BehavioralTests\PhpstanRules\ApiOrInternalAnnotationRule # - Neos\ContentRepository\BehavioralTests\PhpstanRules\InternalMethodsNotAllowedOutsideContentRepositoryRule From 5dee046d353eb1e8526e2287112bf58d2a6931cc Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Thu, 2 Nov 2023 14:15:22 +0100 Subject: [PATCH 7/7] TASK: Require `"symfony/serializer": "^6.3"` --- Neos.ContentRepository.Core/composer.json | 2 +- .../Property/Normalizer/ProxyAwareObjectNormalizer.php | 3 +++ composer.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Neos.ContentRepository.Core/composer.json b/Neos.ContentRepository.Core/composer.json index 8a7598b4d7b..3a7617b0777 100644 --- a/Neos.ContentRepository.Core/composer.json +++ b/Neos.ContentRepository.Core/composer.json @@ -13,7 +13,7 @@ "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", "doctrine/dbal": "^2.6", - "symfony/serializer": "*", + "symfony/serializer": "^6.3", "psr/clock": "^1", "behat/transliterator": "~1.0", "ramsey/uuid": "^3.0 || ^4.0" diff --git a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php index 9dceb86186b..f1c1b1f1f1d 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php +++ b/Neos.ContentRepositoryRegistry/Classes/Infrastructure/Property/Normalizer/ProxyAwareObjectNormalizer.php @@ -7,6 +7,9 @@ /** * An implementation of the ObjectNormalizer that supports Flow proxy classes + * + * Flow issue {@see https://github.com/neos/flow-development-collection/issues/3076#issuecomment-1790701913} + * * @phpstan-ignore-next-line we extend a class which is annotated as final :( */ final class ProxyAwareObjectNormalizer extends OriginalObjectNormalizer diff --git a/composer.json b/composer.json index 7348c34a7bb..d96c2022753 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "neos/error-messages": "*", "neos/utility-objecthandling": "*", "neos/utility-arrays": "*", - "symfony/serializer": "*", + "symfony/serializer": "^6.3", "psr/clock": "^1", "behat/transliterator": "~1.0", "league/flysystem": "^3",