diff --git a/.composer.json b/.composer.json index 78fce2e7486..fc12c2ff3a7 100644 --- a/.composer.json +++ b/.composer.json @@ -15,7 +15,7 @@ "scripts": { "lint:phpcs-psr12": "../../bin/phpcs --colors --standard=PSR12 ./Neos.ContentGraph.DoctrineDbalAdapter/src ./Neos.ContentGraph.PostgreSQLAdapter/src ./Neos.ContentRepository.BehavioralTests/Classes ./Neos.ContentRepository.TestSuite/Classes ./Neos.ContentRepository.Core/Classes ./Neos.Neos/Classes", "lint:phpcs": [ - "@lint:phpcs-psr12 --exclude=Generic.Files.LineLength" + "@lint:phpcs-psr12 --exclude=Generic.Files.LineLength,PSR1.Files.SideEffects" ], "lint:phpstan": "../../bin/phpstan analyse", "lint:distributionintegrity": "[ -d 'Neos.ContentRepository' ] && { echo 'Package Neos.ContentRepository should not exist.' 1>&2; exit 1; } || exit 0;", diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php index 7794a3879d5..0ac6f2e1aad 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php @@ -57,13 +57,16 @@ public function __construct( /** * @param array $nodeRow Node Row from projection (_node table) - * @throws NodeTypeNotFoundException */ public function mapNodeRowToNode( array $nodeRow, DimensionSpacePoint $dimensionSpacePoint, VisibilityConstraints $visibilityConstraints ): Node { + $nodeType = $this->nodeTypeManager->hasNodeType($nodeRow['nodetypename']) + ? $this->nodeTypeManager->getNodeType($nodeRow['nodetypename']) + : null; + return new Node( ContentSubgraphIdentity::create( $this->contentRepositoryId, @@ -75,7 +78,7 @@ public function mapNodeRowToNode( OriginDimensionSpacePoint::fromJsonString($nodeRow['origindimensionspacepoint']), NodeAggregateClassification::from($nodeRow['classification']), NodeTypeName::fromString($nodeRow['nodetypename']), - $this->nodeTypeManager->getNodeType($nodeRow['nodetypename']), + $nodeType, $this->createPropertyCollectionFromJsonString($nodeRow['properties']), isset($nodeRow['name']) ? NodeName::fromString($nodeRow['name']) : null, Timestamps::create( diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/NodeFactory.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/NodeFactory.php index 42b5ae409f5..4ea8b4956f2 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/NodeFactory.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/NodeFactory.php @@ -23,6 +23,7 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Subtree; use Neos\ContentRepository\Core\Projection\ContentGraph\Subtrees; use Neos\ContentRepository\Core\Projection\ContentGraph\Timestamps; +use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFoundException; use Neos\ContentRepository\Core\SharedModel\Node\ReferenceName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; @@ -71,8 +72,11 @@ public function mapNodeRowToNode( ?DimensionSpacePoint $dimensionSpacePoint = null, ?ContentStreamId $contentStreamId = null ): Node { - $nodeType = $this->nodeTypeManager->getNodeType($nodeRow['nodetypename']); - $result = new Node( + $nodeType = $this->nodeTypeManager->hasNodeType($nodeRow['nodetypename']) + ? $this->nodeTypeManager->getNodeType($nodeRow['nodetypename']) + : null; + + return new Node( ContentSubgraphIdentity::create( $this->contentRepositoryId, $contentStreamId ?: ContentStreamId::fromString($nodeRow['contentstreamid']), @@ -97,8 +101,6 @@ public function mapNodeRowToNode( isset($nodeRow['originallastmodified']) ? self::parseDateTimeString($nodeRow['originallastmodified']) : null, ), ); - - return $result; } /** diff --git a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php index 08e8b622a4f..bfcb0806fc9 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php @@ -74,16 +74,6 @@ public function usingTheFollowingContentDimensions(TableNode $contentDimensions) public function usingTheFollowingNodeTypes(PyStringNode $serializedNodeTypesConfiguration): void { GherkinPyStringNodeBasedNodeTypeManagerFactory::initializeWithPyStringNode($serializedNodeTypesConfiguration); - GherkinPyStringNodeBasedNodeTypeManagerFactory::$fallbackNodeTypeName = null; - } - - /** - * @Given /^using the following node types with fallback to "([^"]*)":$/ - */ - public function usingTheFollowingNodeTypesWithFallback(string $fallbackNodeTypeName, PyStringNode $serializedNodeTypesConfiguration): void - { - GherkinPyStringNodeBasedNodeTypeManagerFactory::initializeWithPyStringNode($serializedNodeTypesConfiguration); - GherkinPyStringNodeBasedNodeTypeManagerFactory::$fallbackNodeTypeName = $fallbackNodeTypeName; } /** @@ -136,30 +126,6 @@ public function iChangeTheNodeTypesInContentRepositoryTo( } } - /** - * @Given /^I change the node types in content repository "([^"]*)" with fallback "([^"]*)" to:$/ - */ - public function iChangeTheNodeTypesInContentRepositoryWithFallbackTo( - string $contentRepositoryId, - string $fallbackNodeTypeName, - PyStringNode $serializedNodeTypesConfiguration - ): void { - if (!array_key_exists($contentRepositoryId, $this->contentRepositories)) { - throw new \DomainException('undeclared content repository ' . $contentRepositoryId); - } else { - $contentRepository = $this->contentRepositories[$contentRepositoryId]; - GherkinPyStringNodeBasedNodeTypeManagerFactory::initializeWithPyStringNode( - $serializedNodeTypesConfiguration, - $fallbackNodeTypeName - ); - GherkinTableNodeBasedContentDimensionSourceFactory::$contentDimensionsToUse = $contentRepository->getContentDimensionSource(); - $this->contentRepositories[$contentRepositoryId] = $this->createContentRepository(ContentRepositoryId::fromString($contentRepositoryId)); - if ($this->currentContentRepository->id->value === $contentRepositoryId) { - $this->currentContentRepository = $this->contentRepositories[$contentRepositoryId]; - } - } - } - protected function setUpContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository { /** diff --git a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/GherkinPyStringNodeBasedNodeTypeManagerFactory.php b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/GherkinPyStringNodeBasedNodeTypeManagerFactory.php index 4bc5bd2cdb3..aaa78d4816e 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/GherkinPyStringNodeBasedNodeTypeManagerFactory.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/GherkinPyStringNodeBasedNodeTypeManagerFactory.php @@ -31,8 +31,6 @@ final class GherkinPyStringNodeBasedNodeTypeManagerFactory implements NodeTypeMa { public static ?NodeTypeManager $nodeTypesToUse = null; - public static ?string $fallbackNodeTypeName = null; - /** * @param array $options */ @@ -44,7 +42,7 @@ public function build(ContentRepositoryId $contentRepositoryId, array $options): return self::$nodeTypesToUse; } - public static function initializeWithPyStringNode(PyStringNode $nodeTypesToUse, ?string $fallbackNodeTypeName = null): void + public static function initializeWithPyStringNode(PyStringNode $nodeTypesToUse): void { self::$nodeTypesToUse = new NodeTypeManager( fn (): array => Yaml::parse($nodeTypesToUse->getRaw()), @@ -54,12 +52,11 @@ public function create(NodeType $nodeType): NodeLabelGeneratorInterface return new class implements NodeLabelGeneratorInterface { public function getLabel(Node $node): string { - return $node->nodeType->getLabel(); + return $node->nodeTypeName->value; } }; } - }, - $fallbackNodeTypeName + } ); } diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature index 910e7134a67..3b433612102 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_Dimensions.feature @@ -50,11 +50,8 @@ Feature: Adjust node types with a node migration # Actual Test ######################## # we remove the Document node type (which still exists in the CR) - When I change the node types in content repository "default" with fallback "Neos.ContentRepository:Fallback" to: + When I change the node types in content repository "default" to: """yaml - # !!fallback node is needed!! - TODO DISCUSS - 'Neos.ContentRepository:Fallback': [] - 'Neos.ContentRepository:Root': constraints: nodeTypes: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature index d5d84d3b0d9..511099385b9 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/EventSourced/Migration/NodeTypeAdjustment_NoDimensions.feature @@ -48,11 +48,8 @@ Feature: Adjust node types with a node migration # Actual Test ######################## # we remove the Document node type (which still exists in the CR) - And I change the node types in content repository "default" with fallback "Neos.ContentRepository:Fallback" to: + And I change the node types in content repository "default" to: """yaml - # !!fallback node is needed!! - TODO DISCUSS - 'Neos.ContentRepository:Fallback': [] - 'Neos.ContentRepository:Root': constraints: nodeTypes: diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature index 8122ebecf33..428038ea425 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/StructureAdjustment/UnknownNodeType.feature @@ -5,11 +5,10 @@ Feature: Unknown node types Background: Given using no content dimensions - And using the following node types with fallback to "Neos.ContentRepository:Fallback": + And using the following node types: """yaml 'Neos.ContentRepository:Root': [] 'Neos.ContentRepository.Testing:Document': [] - 'Neos.ContentRepository:Fallback': [] """ And using identifier "default", I define a content repository And I am in content repository "default" @@ -40,10 +39,9 @@ Feature: Unknown node types Then I expect no needed structure adjustments for type "Neos.ContentRepository.Testing:Document" Scenario: When removing "Neos.ContentRepository.Testing:Document", we find a missing node type. - Given I change the node types in content repository "default" with fallback "Neos.ContentRepository:Fallback" to: + Given I change the node types in content repository "default" to: """yaml 'Neos.ContentRepository:Root': [] - 'Neos.ContentRepository:Fallback': [] """ Then I expect the following structure adjustments for type "Neos.ContentRepository.Testing:Document": | Type | nodeAggregateId | diff --git a/Neos.ContentRepository.Core/Classes/NodeType/NodeType.php b/Neos.ContentRepository.Core/Classes/NodeType/NodeType.php index 2c37600f027..8684aed30a3 100644 --- a/Neos.ContentRepository.Core/Classes/NodeType/NodeType.php +++ b/Neos.ContentRepository.Core/Classes/NodeType/NodeType.php @@ -223,15 +223,6 @@ protected function applyPostprocessing(array $fullConfiguration): array return $fullConfiguration; } - /** - * Returns the name of this node type - * @deprecated use "name" property directly - */ - public function getName(): string - { - return $this->name->value; - } - /** * Return boolean true if marked abstract */ @@ -663,7 +654,7 @@ protected function traverseSuperTypes( string $constraintNodeTypeName, int $distance ): ?int { - if ($currentNodeType->getName() === $constraintNodeTypeName) { + if ($currentNodeType->name->value === $constraintNodeTypeName) { return $distance; } diff --git a/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php b/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php index a2f2be011a8..9fa0f00408b 100644 --- a/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php +++ b/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php @@ -40,8 +40,7 @@ class NodeTypeManager public function __construct( private readonly \Closure $nodeTypeConfigLoader, - private readonly NodeLabelGeneratorFactoryInterface $nodeLabelGeneratorFactory, - private readonly ?string $fallbackNodeTypeName + private readonly NodeLabelGeneratorFactoryInterface $nodeLabelGeneratorFactory ) { } @@ -120,28 +119,13 @@ public function getNodeType(string|NodeTypeName $nodeTypeName): NodeType return $this->cachedNodeTypes[$nodeTypeName]; } - if ($this->fallbackNodeTypeName === null) { - throw new NodeTypeNotFoundException( - sprintf( - 'The node type "%s" is not available and no fallback NodeType is configured.', - $nodeTypeName - ), - 1316598370 - ); - } - - if (!$this->hasNodeType($this->fallbackNodeTypeName)) { - throw new NodeTypeNotFoundException( - sprintf( - 'The node type "%s" is not available and the configured fallback NodeType "%s" is not available.', - $nodeTypeName, - $this->fallbackNodeTypeName - ), - 1438166322 - ); - } - - return $this->getNodeType($this->fallbackNodeTypeName); + throw new NodeTypeNotFoundException( + sprintf( + 'The node type "%s" is not available', + $nodeTypeName + ), + 1316598370 + ); } /** diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php index 545bc06f71b..6d2e63d2037 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php @@ -34,13 +34,13 @@ * * @api Note: The constructor is not part of the public API */ -final class Node +final readonly class Node { /** * @internal */ public function __construct( - public readonly ContentSubgraphIdentity $subgraphIdentity, + public ContentSubgraphIdentity $subgraphIdentity, /** * NodeAggregateId (identifier) of this node * This is part of the node's "Read Model" identity, whis is defined by: @@ -50,15 +50,23 @@ public function __construct( * With the above information, you can fetch a Subgraph using {@see ContentGraphInterface::getSubgraph()}. * or {@see \Neos\ContentRepositoryRegistry\ContentRepositoryRegistry::subgraphForNode()} */ - public readonly NodeAggregateId $nodeAggregateId, + public NodeAggregateId $nodeAggregateId, /** * returns the DimensionSpacePoint the node is at home in. Usually needed to address a Node in a NodeAggregate * in order to update it. */ - public readonly OriginDimensionSpacePoint $originDimensionSpacePoint, - public readonly NodeAggregateClassification $classification, - public readonly NodeTypeName $nodeTypeName, - public readonly NodeType $nodeType, + public OriginDimensionSpacePoint $originDimensionSpacePoint, + public NodeAggregateClassification $classification, + /** + * The node's node type name; always set, even if unknown to the NodeTypeManager + */ + public NodeTypeName $nodeTypeName, + /** + * The node's node type, null if unknown to the NodeTypeManager + * @deprecated Don't rely on this too much, as the capabilities of the NodeType here will probably change a lot; + * Ask the {@see NodeTypeManager} instead + */ + public ?NodeType $nodeType, /** * Returns all properties of this node. References are NOT part of this API; * there you need to check getReference() and getReferences(). @@ -67,9 +75,9 @@ public function __construct( * * @param PropertyCollection $properties Property values, indexed by their name */ - public readonly PropertyCollection $properties, - public readonly ?NodeName $nodeName, - public readonly Timestamps $timestamps, + public PropertyCollection $properties, + public ?NodeName $nodeName, + public Timestamps $timestamps, ) { } @@ -108,7 +116,7 @@ public function hasProperty(string $propertyName): bool */ public function getLabel(): string { - return $this->nodeType->getNodeLabelGenerator()->getLabel($this); + return $this->nodeType?->getNodeLabelGenerator()->getLabel($this) ?: $this->nodeTypeName->value; } public function equals(Node $other): bool diff --git a/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php b/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php index 0dc9812c21c..60dfb8741bd 100644 --- a/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php +++ b/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php @@ -38,12 +38,11 @@ public function setUp(): void * * @param array $nodeTypesFixtureData */ - protected function prepareNodeTypeManager(array $nodeTypesFixtureData, string $fallbackNodeTypeName = '') + protected function prepareNodeTypeManager(array $nodeTypesFixtureData) { $this->nodeTypeManager = new NodeTypeManager( fn() => $nodeTypesFixtureData, - new DefaultNodeLabelGeneratorFactory(), - $fallbackNodeTypeName + new DefaultNodeLabelGeneratorFactory() ); } @@ -133,8 +132,7 @@ protected function prepareNodeTypeManager(array $nodeTypesFixtureData, string $f 'Neos.ContentRepository.Testing:Page2' => false, 'Neos.ContentRepository.Testing:Page3' => null ] - ], - 'Neos.ContentRepository:FallbackNode' => [] + ] ]; /** @@ -173,37 +171,6 @@ public function getNodeTypeThrowsExceptionForUnknownNodeType() $this->nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:TextFooBarNotHere'); } - /** - * @test - */ - public function getNodeTypeThrowsExceptionIfNoFallbackNodeTypeIsConfigured() - { - $this->expectException(NodeTypeNotFoundException::class); - $this->nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:TextFooBarNotHere'); - } - - /** - * @test - */ - public function getNodeTypeThrowsExceptionIfConfiguredFallbackNodeTypeCantBeFound() - { - $this->expectException(NodeTypeNotFoundException::class); - $this->prepareNodeTypeManager($this->nodeTypesFixture, 'Neos.ContentRepository:NonExistingFallbackNode'); - $this->nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:TextFooBarNotHere'); - } - - /** - * @test - */ - public function getNodeTypeReturnsFallbackNodeTypeIfConfigured() - { - $this->prepareNodeTypeManager($this->nodeTypesFixture, 'Neos.ContentRepository:FallbackNode'); - - $expectedNodeType = $this->nodeTypeManager->getNodeType('Neos.ContentRepository:FallbackNode'); - $fallbackNodeType = $this->nodeTypeManager->getNodeType('Neos.ContentRepository.Testing:TextFooBarNotHere'); - self::assertSame($expectedNodeType, $fallbackNodeType); - } - /** * @test */ @@ -243,8 +210,7 @@ public function getNodeTypesReturnsRegisteredNodeTypes() 'Neos.ContentRepository.Testing:Page', 'Neos.ContentRepository.Testing:Page2', 'Neos.ContentRepository.Testing:Page3', - 'Neos.ContentRepository.Testing:DocumentWithSupertypes', - 'Neos.ContentRepository:FallbackNode' + 'Neos.ContentRepository.Testing:DocumentWithSupertypes' ]; self::assertEquals($expectedNodeTypes, array_keys($this->nodeTypeManager->getNodeTypes())); } diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php index 0dfa463e7ee..a8b1c362855 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php @@ -7,23 +7,21 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; +use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; +use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePointSet; use Neos\ContentRepository\Core\EventStore\Events; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved; -use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; -use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePointSet; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; -use Neos\ContentRepository\Core\SharedModel\User\UserId; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\EventStore\Model\EventStream\ExpectedVersion; class DisallowedChildNodeAdjustment { use RemoveNodeAggregateTrait; - use LoadNodeTypeTrait; public function __construct( private readonly ContentRepository $contentRepository, @@ -37,19 +35,17 @@ public function __construct( */ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generator { - $nodeType = $this->loadNodeType($nodeTypeName); - - if ($nodeType === null) { + if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) { // no adjustments for unknown node types return; } foreach ($this->projectedNodeIterator->nodeAggregatesOfType($nodeTypeName) as $nodeAggregate) { - $nodeType = $this->loadNodeType($nodeAggregate->nodeTypeName); - if ($nodeType === null) { + if (!$this->nodeTypeManager->hasNodeType($nodeAggregate->nodeTypeName)) { // unknown child node type, so we skip this test as we won't be able to find out node type constraints continue; } + $nodeType = $this->nodeTypeManager->getNodeType($nodeAggregate->nodeTypeName); // Here, we iterate over the covered dimension space points of the node aggregate one by one; // as it can happen that the constraint is only violated in e.g. "AT", but not in "DE". @@ -70,8 +66,8 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat $allowedByParent = true; $parentNodeType = null; if ($parentNode !== null) { - $parentNodeType = $this->loadNodeType($parentNode->nodeTypeName); - if ($parentNodeType !== null) { + if ($this->nodeTypeManager->hasNodeType($parentNode->nodeTypeName)) { + $parentNodeType = $this->nodeTypeManager->getNodeType($parentNode->nodeTypeName); $allowedByParent = $parentNodeType->allowsChildNodeType($nodeType); } } @@ -84,8 +80,8 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat && $parentNode->classification->isTethered() && !is_null($parentNode->nodeName) ) { - $grandparentNodeType = $this->loadNodeType($grandparentNode->nodeTypeName); - if ($grandparentNodeType !== null) { + if ($this->nodeTypeManager->hasNodeType($grandparentNode->nodeTypeName)) { + $grandparentNodeType = $this->nodeTypeManager->getNodeType($grandparentNode->nodeTypeName); $allowedByGrandparent = $grandparentNodeType->allowsGrandchildNodeType( $parentNode->nodeName->value, $nodeType @@ -153,9 +149,4 @@ private function removeNodeInSingleDimensionSpacePoint( ExpectedVersion::ANY() ); } - - protected function getNodeTypeManager(): NodeTypeManager - { - return $this->nodeTypeManager; - } } diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/LoadNodeTypeTrait.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/LoadNodeTypeTrait.php deleted file mode 100644 index 2728d52caad..00000000000 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/LoadNodeTypeTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -getNodeTypeManager()->getNodeType($nodeTypeName->value); - if (!$nodeTypeName->equals($nodeType->name)) { - // the $nodeTypeName was different than the fetched node type; so that means - // that the FallbackNodeType has been returned. - return null; - } - return $nodeType; - } catch (NodeTypeNotFoundException $e) { - // the $nodeTypeName was not found; so we need to remove all nodes of this type. - // This case applies if the fallbackNodeType is not configured. - return null; - } - } -} diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php index 2f45a28127b..f84c7a74524 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php @@ -18,8 +18,6 @@ class PropertyAdjustment { - use LoadNodeTypeTrait; - public function __construct( private readonly ProjectedNodeIterator $projectedNodeIterator, private readonly NodeTypeManager $nodeTypeManager @@ -31,11 +29,12 @@ public function __construct( */ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generator { - $nodeType = $this->loadNodeType($nodeTypeName); - if ($nodeType === null) { + if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) { // In case we cannot find the expected tethered nodes, this fix cannot do anything. return; } + $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); + $expectedPropertiesFromNodeType = array_filter($nodeType->getProperties(), fn ($value) => $value !== null); foreach ($this->projectedNodeIterator->nodeAggregatesOfType($nodeTypeName) as $nodeAggregate) { @@ -132,9 +131,4 @@ private function publishNodePropertiesWereSet( ExpectedVersion::ANY() ); } - - protected function getNodeTypeManager(): NodeTypeManager - { - return $this->nodeTypeManager; - } } diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 7bff3925f22..aa50bb0324b 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -32,7 +32,6 @@ class TetheredNodeAdjustments { use NodeVariationInternals; use RemoveNodeAggregateTrait; - use LoadNodeTypeTrait; use TetheredNodeInternals; public function __construct( @@ -48,11 +47,12 @@ public function __construct( */ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generator { - $nodeType = $this->loadNodeType($nodeTypeName); - if ($nodeType === null) { + if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) { // In case we cannot find the expected tethered nodes, this fix cannot do anything. return; } + $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); + $expectedTetheredNodes = $nodeType->getAutoCreatedChildNodes(); foreach ($this->projectedNodeIterator->nodeAggregatesOfType($nodeTypeName) as $nodeAggregate) { @@ -204,11 +204,6 @@ protected function getInterDimensionalVariationGraph(): DimensionSpace\InterDime return $this->interDimensionalVariationGraph; } - protected function getNodeTypeManager(): NodeTypeManager - { - return $this->nodeTypeManager; - } - /** * array key: name of tethered child node. Value: the Node itself. * @param array $actualTetheredChildNodes diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/UnknownNodeTypeAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/UnknownNodeTypeAdjustment.php index 903ae844770..e80657f3602 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/UnknownNodeTypeAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/UnknownNodeTypeAdjustment.php @@ -10,7 +10,6 @@ class UnknownNodeTypeAdjustment { use RemoveNodeAggregateTrait; - use LoadNodeTypeTrait; public function __construct( private readonly ProjectedNodeIterator $projectedNodeIterator, @@ -23,8 +22,7 @@ public function __construct( */ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generator { - $nodeType = $this->loadNodeType($nodeTypeName); - if ($nodeType === null) { + if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) { // node type is not existing right now. yield from $this->removeAllNodesOfType($nodeTypeName); } @@ -47,9 +45,4 @@ function () use ($nodeAggregate) { ); } } - - protected function getNodeTypeManager(): NodeTypeManager - { - return $this->nodeTypeManager; - } } diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php index c32ebe72467..691ebe85b25 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php @@ -188,7 +188,8 @@ private function createVariantRecursivelyInternal(int $level, NodeAggregateId $p foreach ($childNodes as $childNode) { if ($childNode->classification->isRegular()) { - if ($childNode->nodeType->isOfType('Neos.Neos:Document')) { + $childNodeType = $contentRepository->getNodeTypeManager()->getNodeType($childNode->nodeTypeName); + if ($childNodeType->isOfType('Neos.Neos:Document')) { $this->output("%s- %s\n", [ str_repeat(' ', $level), $childNode->getProperty('uriPathSegment') ?? $childNode->nodeAggregateId->value @@ -203,7 +204,7 @@ private function createVariantRecursivelyInternal(int $level, NodeAggregateId $p $target ))->block(); } catch (DimensionSpacePointIsAlreadyOccupied $e) { - if ($childNode->nodeType->isOfType('Neos.Neos:Document')) { + if ($childNodeType->isOfType('Neos.Neos:Document')) { $this->output("%s (already exists)\n", [ str_repeat(' ', $level) ]); diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/NodeTypesCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/NodeTypesCommandController.php index 6901a5c6132..faf64e498b4 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/NodeTypesCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/NodeTypesCommandController.php @@ -39,11 +39,12 @@ public function showCommand(string $nodeTypeName, ?string $path = null, string $ $contentRepositoryId = ContentRepositoryId::fromString($contentRepository); $nodeTypeManager = $this->contentRepositoryRegistry->get($contentRepositoryId)->getNodeTypeManager(); - $nodeType = $nodeTypeManager->getNodeType($nodeTypeName); - if (!$nodeType) { + if (!$nodeTypeManager->hasNodeType($nodeTypeName)) { $this->outputLine('NodeType "%s" was not found!', [$nodeTypeName]); $this->quit(); } + + $nodeType = $nodeTypeManager->getNodeType($nodeTypeName); $yaml = Yaml::dump( $path ? $nodeType->getConfiguration($path) @@ -71,7 +72,7 @@ public function listCommand(?string $filter = null, bool $includeAbstract = true $nodeTypesFound = 0; $nodeTypeNameSpacesWithNodeTypeNames = []; foreach ($nodeTypeManager->getNodeTypes($includeAbstract) as $nodeType) { - $nodeTypeName = $nodeType->getName(); + $nodeTypeName = $nodeType->name->value; if (!$filter || str_contains($nodeTypeName, $filter)) { [$nameSpace] = explode(":", $nodeTypeName, 2); $nodeTypeNameSpacesWithNodeTypeNames[$nameSpace][] = $nodeTypeName; diff --git a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php index 2e587e187e6..3eb010d5c10 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php +++ b/Neos.ContentRepositoryRegistry/Classes/Factory/NodeTypeManager/DefaultNodeTypeManagerFactory.php @@ -7,12 +7,12 @@ use Neos\ContentRepositoryRegistry\Configuration\NodeTypeEnrichmentService; use Neos\Flow\Configuration\ConfigurationManager; -class DefaultNodeTypeManagerFactory implements NodeTypeManagerFactoryInterface +readonly class DefaultNodeTypeManagerFactory implements NodeTypeManagerFactoryInterface { public function __construct( - private readonly ConfigurationManager $configurationManager, - private readonly ObjectManagerBasedNodeLabelGeneratorFactory $nodeLabelGeneratorFactory, - private readonly NodeTypeEnrichmentService $nodeTypeEnrichmentService, + private ConfigurationManager $configurationManager, + private ObjectManagerBasedNodeLabelGeneratorFactory $nodeLabelGeneratorFactory, + private NodeTypeEnrichmentService $nodeTypeEnrichmentService, ) { } @@ -24,8 +24,7 @@ function () { $configuration = $this->configurationManager->getConfiguration('NodeTypes'); return $this->nodeTypeEnrichmentService->enrichNodeTypeLabelsConfiguration($configuration); }, - $this->nodeLabelGeneratorFactory, - $options['fallbackNodeTypeName'] ?? null, + $this->nodeLabelGeneratorFactory ); } } diff --git a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml index 44117db2c43..b8bea873b15 100644 --- a/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml +++ b/Neos.ContentRepositoryRegistry/Configuration/Settings.yaml @@ -21,8 +21,6 @@ Neos: nodeTypeManager: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\NodeTypeManager\DefaultNodeTypeManagerFactory - options: - fallbackNodeTypeName: Neos.Neos:FallbackNode contentDimensionSource: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\ContentDimensionSource\ConfigurationBasedContentDimensionSourceFactory diff --git a/Neos.Neos/Classes/Controller/Backend/ContentController.php b/Neos.Neos/Classes/Controller/Backend/ContentController.php index 431ebe35270..e6072a7bbc4 100644 --- a/Neos.Neos/Classes/Controller/Backend/ContentController.php +++ b/Neos.Neos/Classes/Controller/Backend/ContentController.php @@ -14,15 +14,12 @@ namespace Neos\Neos\Controller\Backend; -use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; -use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; -use Neos\Flow\I18n\EelHelper\TranslationHelper; use Neos\Flow\Mvc\Controller\ActionController; use Neos\Flow\Mvc\Exception\NoSuchArgumentException; use Neos\Flow\Persistence\Exception\IllegalObjectTypeException; @@ -45,6 +42,7 @@ use Neos\Neos\Controller\BackendUserTranslationTrait; use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult; use Neos\Neos\TypeConverter\EntityToIdentityConverter; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * The Neos ContentModule controller; providing backend functionality for the Content Module. @@ -54,6 +52,10 @@ class ContentController extends ActionController { use BackendUserTranslationTrait; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; /** * @Flow\Inject @@ -103,9 +105,6 @@ class ContentController extends ActionController */ protected $propertyMapper; - #[Flow\Inject] - protected ContentRepositoryRegistry $contentRepositoryRegistry; - /** * Initialize property mapping as the upload usually comes from the Inspector JavaScript * @throws NoSuchArgumentException @@ -413,12 +412,12 @@ public function masterPluginsAction(string $workspaceName = 'live', array $dimen final protected function findClosestDocumentNode(Node $node): ?Node { + $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); while ($node instanceof Node) { - if ($node->nodeType->isOfType('Neos.Neos:Document')) { + if ($this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_DOCUMENT)) { return $node; } - $node = $this->contentRepositoryRegistry->subgraphForNode($node) - ->findParentNode($node->nodeAggregateId); + $node = $subgraph->findParentNode($node->nodeAggregateId); } return null; diff --git a/Neos.Neos/Classes/Controller/Frontend/NodeController.php b/Neos.Neos/Classes/Controller/Frontend/NodeController.php index d7ef5446465..34c64b2ab69 100644 --- a/Neos.Neos/Classes/Controller/Frontend/NodeController.php +++ b/Neos.Neos/Classes/Controller/Frontend/NodeController.php @@ -15,13 +15,11 @@ namespace Neos\Neos\Controller\Frontend; use Neos\ContentRepository\Core\ContentRepository; -use Neos\ContentRepository\Core\Projection\ContentGraph\AbsoluteNodePath; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphWithRuntimeCaches\ContentSubgraphWithRuntimeCaches; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphWithRuntimeCaches\InMemoryCache; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindSubtreeFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; use Neos\ContentRepository\Core\Projection\ContentGraph\Nodes; use Neos\ContentRepository\Core\Projection\ContentGraph\Subtree; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; @@ -37,6 +35,7 @@ use Neos\Flow\Utility\Now; use Neos\Neos\Domain\Model\RenderingMode; use Neos\Neos\Domain\Service\NodeSiteResolvingService; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\Domain\Service\RenderingModeService; use Neos\Neos\FrontendRouting\Exception\InvalidShortcutException; use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException; @@ -45,6 +44,7 @@ use Neos\Neos\FrontendRouting\NodeShortcutResolver; use Neos\Neos\FrontendRouting\NodeUriBuilder; use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; use Neos\Neos\View\FusionView; /** @@ -52,11 +52,10 @@ */ class NodeController extends ActionController { - /** - * @Flow\Inject - * @var ContentRepositoryRegistry - */ - protected $contentRepositoryRegistry; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; /** * @Flow\Inject @@ -165,7 +164,7 @@ public function previewAction(string $node): void ); } - if ($nodeInstance->nodeType->isOfType('Neos.Neos:Shortcut') && $nodeAddress->isInLiveWorkspace()) { + if ($this->getNodeType($nodeInstance)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT) && $nodeAddress->isInLiveWorkspace()) { $this->handleShortcutNode($nodeAddress, $contentRepository); } @@ -240,7 +239,7 @@ public function showAction(string $node, bool $showInvisible = false): void throw new NodeNotFoundException('The requested node does not exist', 1596191460); } - if ($nodeInstance->nodeType->isOfType('Neos.Neos:Shortcut')) { + if ($this->getNodeType($nodeInstance)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT)) { $this->handleShortcutNode($nodeAddress, $contentRepository); } @@ -336,7 +335,7 @@ private function fillCacheWithContentNodes( $subtree = $subgraph->findSubtree( $nodeAggregateId, - FindSubtreeFilter::create(nodeTypeConstraints: '!Neos.Neos:Document', maximumLevels: 20) + FindSubtreeFilter::create(nodeTypeConstraints: '!' . NodeTypeNameFactory::NAME_DOCUMENT, maximumLevels: 20) ); if ($subtree === null) { return; diff --git a/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php b/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php index 5cc1a00fb17..44c3e8ef1a4 100755 --- a/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php +++ b/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php @@ -186,7 +186,7 @@ public function updateSiteAction(Site $site, $newSiteNodeName) try { $sitesNode = $contentRepository->getContentGraph()->findRootNodeAggregateByType( $liveWorkspace->currentContentStreamId, - NodeTypeName::fromString('Neos.Neos:Sites') + NodeTypeNameFactory::forSites() ); } catch (\Exception $exception) { throw new \InvalidArgumentException( @@ -253,7 +253,7 @@ public function newSiteAction(Site $site = null) $sitePackages = $this->packageManager->getFilteredPackages('available', 'neos-site'); - $documentNodeTypes = $contentRepository->getNodeTypeManager()->getSubNodeTypes('Neos.Neos:Document', false); + $documentNodeTypes = $contentRepository->getNodeTypeManager()->getSubNodeTypes(NodeTypeNameFactory::forDocument(), false); $generatorServiceIsAvailable = $this->packageManager->isPackageAvailable('Neos.SiteKickstarter'); $generatorServices = []; diff --git a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php index 98a1c25cb1b..8712cf3ba8f 100644 --- a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php +++ b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php @@ -15,52 +15,54 @@ namespace Neos\Neos\Controller\Module\Management; use Neos\ContentRepository\Core\ContentRepository; -use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Command\CreateWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\WorkspaceAlreadyExists; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\ChangeWorkspaceOwner; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\DeleteWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\RenameWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardIndividualNodesFromWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishIndividualNodesFromWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishWorkspace; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Dto\NodeIdsToPublishOrDiscard; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Dto\NodeIdToPublishOrDiscard; +use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\WorkspaceAlreadyExists; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindAncestorNodesFilter; +use Neos\ContentRepository\Core\SharedModel\Node\NodeName; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; +use Neos\Flow\I18n\Exception\IndexOutOfBoundsException; +use Neos\Flow\I18n\Exception\InvalidFormatPlaceholderException; +use Neos\Flow\Mvc\Exception\StopActionException; +use Neos\Neos\Domain\Model\SiteNodeName; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; +use Neos\Neos\PendingChangesProjection\ChangeFinder; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; -use Neos\ContentRepository\Core\SharedModel\Node\NodeName; +use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Command\CreateWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardIndividualNodesFromWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishIndividualNodesFromWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\RenameWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\DeleteWorkspace; +use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\ChangeWorkspaceOwner; +use Neos\Neos\FrontendRouting\NodeAddress; +use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepository\Core\SharedModel\User\UserId; +use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceDescription; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceTitle; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Diff\Diff; use Neos\Diff\Renderer\Html\HtmlArrayRenderer; -use Neos\Error\Messages\Message; +use Neos\Neos\Controller\Module\ModuleTranslationTrait; use Neos\Flow\Annotations as Flow; -use Neos\Flow\I18n\Exception\IndexOutOfBoundsException; -use Neos\Flow\I18n\Exception\InvalidFormatPlaceholderException; +use Neos\Error\Messages\Message; use Neos\Flow\Mvc\ActionRequest; -use Neos\Flow\Mvc\Exception\StopActionException; use Neos\Flow\Package\PackageManager; use Neos\Flow\Property\PropertyMapper; use Neos\Flow\Security\Context; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Model\ImageInterface; use Neos\Neos\Controller\Module\AbstractModuleController; -use Neos\Neos\Controller\Module\ModuleTranslationTrait; -use Neos\Neos\Domain\Model\SiteNodeName; use Neos\Neos\Domain\Model\User; use Neos\Neos\Domain\Repository\SiteRepository; use Neos\Neos\Domain\Service\UserService; -use Neos\Neos\Domain\Service\WorkspaceNameBuilder; -use Neos\Neos\FrontendRouting\NodeAddress; -use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult; -use Neos\Neos\PendingChangesProjection\ChangeFinder; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; +use Neos\Neos\Domain\Service\WorkspaceNameBuilder; /** * The Neos Workspaces module controller @@ -70,6 +72,10 @@ class WorkspacesController extends AbstractModuleController { use ModuleTranslationTrait; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; /** * @Flow\Inject @@ -101,12 +107,6 @@ class WorkspacesController extends AbstractModuleController */ protected $packageManager; - /** - * @var ContentRepositoryRegistry - * @Flow\Inject - */ - protected $contentRepositoryRegistry; - /** * Display a list of unpublished content * @@ -790,7 +790,7 @@ protected function computeSiteChanges(Workspace $selectedWorkspace, ContentRepos foreach ($ancestors as $ancestor) { $pathSegment = $ancestor->nodeName ?: NodeName::fromString($ancestor->nodeAggregateId->value); $nodePathSegments[] = $pathSegment; - if ($ancestor->nodeType->isOfType('Neos.Neos:Document')) { + if ($this->getNodeType($ancestor)->isOfType(NodeTypeNameFactory::NAME_DOCUMENT)) { $documentPathSegments[] = $pathSegment; if (is_null($documentNode)) { $documentNode = $ancestor; @@ -833,8 +833,9 @@ protected function computeSiteChanges(Workspace $selectedWorkspace, ContentRepos $contentRepository ) ]; - if ($node->nodeType->isOfType('Neos.Neos:Node')) { - $change['configuration'] = $node->nodeType->getFullConfiguration(); + $nodeType = $this->getNodeType($node); + if ($nodeType->isOfType('Neos.Neos:Node')) { + $change['configuration'] = $nodeType->getFullConfiguration(); } $siteChanges[$siteNodeName]['documents'][$documentPath]['changes'][$relativePath] = $change; } @@ -904,7 +905,7 @@ protected function renderContentChanges( $contentChanges = []; - $changeNodePropertiesDefaults = $changedNode->nodeType->getDefaultValuesForProperties(); + $changeNodePropertiesDefaults = $this->getNodeType($changedNode)->getDefaultValuesForProperties(); $renderer = new HtmlArrayRenderer(); foreach ($changedNode->properties as $propertyName => $changedPropertyValue) { @@ -1021,7 +1022,7 @@ protected function renderSlimmedDownContent($propertyValue) */ protected function getPropertyLabel($propertyName, Node $changedNode) { - $properties = $changedNode->nodeType->getProperties(); + $properties = $this->getNodeType($changedNode)->getProperties(); if ( !isset($properties[$propertyName]) || !isset($properties[$propertyName]['ui']['label']) diff --git a/Neos.Neos/Classes/Controller/Service/NodesController.php b/Neos.Neos/Classes/Controller/Service/NodesController.php index f9bfdf3f638..e649ffc87f3 100644 --- a/Neos.Neos/Classes/Controller/Service/NodesController.php +++ b/Neos.Neos/Classes/Controller/Service/NodesController.php @@ -29,6 +29,7 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateIds; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepository\Core\NodeType\NodeTypeConstraintParser; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTypeConstraints; @@ -114,7 +115,7 @@ public function indexAction( array|string $nodeIds = [], string $workspaceName = 'live', array $dimensions = [], - array $nodeTypes = ['Neos.Neos:Document'], + array $nodeTypes = [NodeTypeNameFactory::NAME_DOCUMENT], string $contextNode = null, array|string $nodeIdentifiers = [] ): void { @@ -435,7 +436,7 @@ protected function adoptNodeAndParents( )->block(); if ($copyContent === true) { - $contentNodeConstraint = NodeTypeConstraints::fromFilterString('!Neos.Neos:Document'); + $contentNodeConstraint = NodeTypeConstraints::fromFilterString('!' . NodeTypeNameFactory::NAME_DOCUMENT); $this->createNodeVariantsForChildNodes( $contentStreamId, $identifier, diff --git a/Neos.Neos/Classes/Domain/Service/NodeSiteResolvingService.php b/Neos.Neos/Classes/Domain/Service/NodeSiteResolvingService.php index 0807b96ccd3..49aa0564179 100644 --- a/Neos.Neos/Classes/Domain/Service/NodeSiteResolvingService.php +++ b/Neos.Neos/Classes/Domain/Service/NodeSiteResolvingService.php @@ -15,21 +15,20 @@ namespace Neos\Neos\Domain\Service; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; -use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphIdentity; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Neos\FrontendRouting\NodeAddress; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; #[Flow\Scope('singleton')] class NodeSiteResolvingService { - /** - * @Flow\Inject - * @var ContentRepositoryRegistry - */ - protected $contentRepositoryRegistry; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; public function findSiteNodeForNodeAddress( NodeAddress $nodeAddress, @@ -51,8 +50,8 @@ public function findSiteNodeForNodeAddress( } $previousNode = null; do { - if ($node->nodeType->isOfType('Neos.Neos:Sites')) { - // the Site node is the one one level underneath the "Sites" node. + if ($this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_SITES)) { + // the Site node is the one level underneath the "Sites" node. return $previousNode; } $previousNode = $node; diff --git a/Neos.Neos/Classes/Domain/Service/NodeTypeNameFactory.php b/Neos.Neos/Classes/Domain/Service/NodeTypeNameFactory.php index 67542aa2327..6af5e3827b1 100644 --- a/Neos.Neos/Classes/Domain/Service/NodeTypeNameFactory.php +++ b/Neos.Neos/Classes/Domain/Service/NodeTypeNameFactory.php @@ -20,16 +20,39 @@ #[Flow\Proxy(false)] final class NodeTypeNameFactory { + public const NAME_CONTENT = 'Neos.Neos:Content'; + public const NAME_CONTENT_COLLECTION = 'Neos.Neos:ContentCollection'; public const NAME_DOCUMENT = 'Neos.Neos:Document'; + public const NAME_FALLBACK = 'Neos.Neos:FallbackNode'; + public const NAME_SHORTCUT = 'Neos.Neos:Shortcut'; public const NAME_SITE = 'Neos.Neos:Site'; public const NAME_SITES = 'Neos.Neos:Sites'; - public const NAME_FALLBACK = 'Neos.Neos:FallbackNode'; + + public static function forContent(): NodeTypeName + { + return NodeTypeName::fromString(self::NAME_CONTENT); + } + + public static function forContentCollection(): NodeTypeName + { + return NodeTypeName::fromString(self::NAME_CONTENT_COLLECTION); + } public static function forDocument(): NodeTypeName { return NodeTypeName::fromString(self::NAME_DOCUMENT); } + public static function forFallback(): NodeTypeName + { + return NodeTypeName::fromString(self::NAME_FALLBACK); + } + + public static function forShortcut(): NodeTypeName + { + return NodeTypeName::fromString(self::NAME_SHORTCUT); + } + public static function forSite(): NodeTypeName { return NodeTypeName::fromString(self::NAME_SITE); @@ -39,9 +62,4 @@ public static function forSites(): NodeTypeName { return NodeTypeName::fromString(self::NAME_SITES); } - - public static function forFallback(): NodeTypeName - { - return NodeTypeName::fromString(self::NAME_FALLBACK); - } } diff --git a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php index e676f4579c0..b24f43096c1 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php +++ b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php @@ -18,7 +18,6 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Factory\ContentRepositoryId; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; @@ -26,12 +25,17 @@ use Neos\Neos\Domain\Model\Site; use Neos\Neos\Domain\Repository\DomainRepository; use Neos\Neos\Domain\Repository\SiteRepository; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; #[Flow\Scope('singleton')] final class SiteNodeUtility { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + public function __construct( - private readonly ContentRepositoryRegistry $contentRepositoryRegistry, private readonly DomainRepository $domainRepository, private readonly SiteRepository $siteRepository ) { @@ -42,8 +46,8 @@ public function findSiteNode(Node $node): Node $previousNode = null; $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); do { - if ($node->nodeType->isOfType('Neos.Neos:Sites')) { - // the Site node is the one one level underneath the "Sites" node. + if ($this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_SITES)) { + // the Site node is the one level underneath the "Sites" node. if (is_null($previousNode)) { break; } @@ -78,7 +82,7 @@ public function findCurrentSiteNode( $rootNodeAggregate = $contentRepository->getContentGraph() ->findRootNodeAggregateByType( $contentStreamId, - NodeTypeName::fromString('Neos.Neos:Sites') + NodeTypeNameFactory::forSites() ); $sitesNode = $subgraph->findNodeById($rootNodeAggregate->nodeAggregateId); if ($sitesNode) { diff --git a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php index 5e9ce9ce471..7c4ee09b84c 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php +++ b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php @@ -69,7 +69,7 @@ public function removeSiteNode(SiteNodeName $siteNodeName): void foreach ($this->contentRepository->getContentStreamFinder()->findAllIds() as $contentStreamId) { $sitesNodeAggregate = $contentGraph->findRootNodeAggregateByType( $contentStreamId, - NodeTypeName::fromString('Neos.Neos:Sites') + NodeTypeNameFactory::forSites() ); $siteNodeAggregates = $contentGraph->findChildNodeAggregatesByName( $contentStreamId, @@ -97,14 +97,16 @@ public function createSiteNodeIfNotExists(Site $site, string $nodeTypeName): voi $liveContentStreamId, NodeTypeNameFactory::forSites() ); - $siteNodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); - - if ($siteNodeType->getName() === 'Neos.Neos:FallbackNode') { + try { + $this->nodeTypeManager->getNodeType($nodeTypeName); + } catch (NodeTypeNotFoundException $exception) { throw new NodeTypeNotFoundException( 'Cannot create a site using a non-existing node type.', - 1412372375 + 1412372375, + $exception ); } + $siteNodeAggregate = $this->contentRepository->getContentGraph()->findChildNodeAggregatesByName( $liveContentStreamId, $sitesNodeIdentifier, diff --git a/Neos.Neos/Classes/EventLog/Integrations/ContentRepositoryIntegrationService.php b/Neos.Neos/Classes/EventLog/Integrations/ContentRepositoryIntegrationService.php index 1fc2ec1bd52..94c807e6cad 100644 --- a/Neos.Neos/Classes/EventLog/Integrations/ContentRepositoryIntegrationService.php +++ b/Neos.Neos/Classes/EventLog/Integrations/ContentRepositoryIntegrationService.php @@ -17,10 +17,11 @@ use Doctrine\ORM\EntityManagerInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; -use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; +use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\Flow\Annotations as Flow; use Neos\Flow\Persistence\PersistenceManagerInterface; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * Monitors Neos.ContentRepository changes @@ -30,6 +31,11 @@ */ class ContentRepositoryIntegrationService extends AbstractIntegrationService { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + public const NODE_ADDED = 'Node.Added'; public const NODE_UPDATED = 'Node.Updated'; public const NODE_LABEL_CHANGED = 'Node.LabelChanged'; @@ -51,9 +57,6 @@ class ContentRepositoryIntegrationService extends AbstractIntegrationService */ protected $persistenceManager; - #[Flow\Inject] - protected ContentRepositoryRegistry $contentRepositoryRegistry; - /** * @var array */ @@ -412,7 +415,7 @@ public function afterNodePublishing(Node $node, Workspace $targetWorkspace) $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); $documentNode = $node; - while ($documentNode !== null && !$documentNode->nodeType->isAggregate()) { + while ($documentNode !== null && !$this->getNodeType($documentNode)->isAggregate()) { $documentNode = $subgraph->findParentNode($documentNode->nodeAggregateId); } diff --git a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php index f2150759fde..193d349526e 100644 --- a/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php +++ b/Neos.Neos/Classes/FrontendRouting/Projection/DocumentUriPathProjection.php @@ -41,6 +41,7 @@ use Neos\EventStore\Model\EventEnvelope; use Neos\EventStore\Model\EventStore\SetupResult; use Neos\Neos\Domain\Model\SiteNodeName; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException; /** @@ -704,7 +705,7 @@ private function isDocumentNodeType(NodeTypeName $nodeTypeName): bool // HACK: We consider the currently configured node type of the given node. // This is a deliberate side effect of this projector! $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); - return $nodeType->isOfType('Neos.Neos:Document'); + return $nodeType->isOfType(NodeTypeNameFactory::NAME_DOCUMENT); } private function isShortcutNodeType(NodeTypeName $nodeTypeName): bool @@ -712,7 +713,7 @@ private function isShortcutNodeType(NodeTypeName $nodeTypeName): bool // HACK: We consider the currently configured node type of the given node. // This is a deliberate side effect of this projector! $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); - return $nodeType->isOfType('Neos.Neos:Shortcut'); + return $nodeType->isOfType(NodeTypeNameFactory::NAME_SHORTCUT); } private function tryGetNode(\Closure $closure): ?DocumentNodeInfo diff --git a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php index 71a64e4a356..e66d617b834 100644 --- a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php +++ b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php @@ -255,7 +255,7 @@ protected function getAllImplementedNodeTypeNames(NodeType $nodeType) function (array $types, NodeType $superType) use ($self) { return array_merge($types, $self->getAllImplementedNodeTypeNames($superType)); }, - [$nodeType->getName()] + [$nodeType->name->value] ); $types = array_unique($types); diff --git a/Neos.Neos/Classes/Fusion/Helper/NodeHelper.php b/Neos.Neos/Classes/Fusion/Helper/NodeHelper.php index 9530edde9d6..54384747a8b 100644 --- a/Neos.Neos/Classes/Fusion/Helper/NodeHelper.php +++ b/Neos.Neos/Classes/Fusion/Helper/NodeHelper.php @@ -14,23 +14,30 @@ namespace Neos\Neos\Fusion\Helper; +use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\ContentRepository\Core\Projection\ContentGraph\AbsoluteNodePath; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\CountAncestorNodesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindAncestorNodesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\Flow\Annotations as Flow; use Neos\Eel\ProtectedContextAwareInterface; use Neos\Neos\Domain\Exception; use Neos\Neos\Presentation\VisualNodePath; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; +use Neos\Flow\Annotations as Flow; /** * Eel helper for ContentRepository Nodes */ class NodeHelper implements ProtectedContextAwareInterface { + use NodeTypeWithFallbackProvider { + getNodeType as getNodeTypeInternal; + } + #[Flow\Inject] protected ContentRepositoryRegistry $contentRepositoryRegistry; @@ -42,8 +49,8 @@ class NodeHelper implements ProtectedContextAwareInterface */ public function nearestContentCollection(Node $node, string $nodePath): Node { - $contentCollectionType = 'Neos.Neos:ContentCollection'; - if ($node->nodeType->isOfType($contentCollectionType)) { + $contentCollectionType = NodeTypeNameFactory::NAME_CONTENT_COLLECTION; + if ($this->isOfType($node, $contentCollectionType)) { return $node; } else { if ($nodePath === '') { @@ -63,7 +70,7 @@ public function nearestContentCollection(Node $node, string $nodePath): Node ? $subgraph->findNodeByAbsolutePath($nodePath) : $subgraph->findNodeByPath($nodePath, $node->nodeAggregateId); - if ($subNode !== null && $subNode->nodeType->isOfType($contentCollectionType)) { + if ($subNode !== null && $this->isOfType($subNode, $contentCollectionType)) { return $subNode; } else { $nodePathOfNode = VisualNodePath::fromAncestors( @@ -81,7 +88,7 @@ public function nearestContentCollection(Node $node, string $nodePath): Node $contentCollectionType, $nodePathOfNode->value, $nodePath->serializeToString(), - $node->nodeType->name->value + $node->nodeTypeName->value ), 1389352984); } } @@ -123,14 +130,15 @@ public function path(Node $node): string /** * If this node type or any of the direct or indirect super types * has the given name. - * - * @param Node $node - * @param string $nodeType - * @return bool */ public function isOfType(Node $node, string $nodeType): bool { - return $node->nodeType->isOfType($nodeType); + return $this->getNodeTypeInternal($node)->isOfType($nodeType); + } + + public function getNodeType(Node $node): NodeType + { + return $this->getNodeTypeInternal($node); } public function serializedNodeAddress(Node $node): string diff --git a/Neos.Neos/Classes/Fusion/Helper/NodeLabelToken.php b/Neos.Neos/Classes/Fusion/Helper/NodeLabelToken.php index b68638890f4..cf63385c03c 100644 --- a/Neos.Neos/Classes/Fusion/Helper/NodeLabelToken.php +++ b/Neos.Neos/Classes/Fusion/Helper/NodeLabelToken.php @@ -15,10 +15,12 @@ namespace Neos\Neos\Fusion\Helper; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Eel\Helper\StringHelper; use Neos\Eel\ProtectedContextAwareInterface; use Neos\Flow\Annotations as Flow; use Neos\Flow\I18n\EelHelper\TranslationHelper; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * Provides a chainable interface to build a label for a nodetype @@ -26,6 +28,11 @@ */ class NodeLabelToken implements ProtectedContextAwareInterface { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + /** * @Flow\Inject * @var TranslationHelper @@ -140,9 +147,9 @@ public function evaluate(): string */ protected function resolveLabelFromNodeType(): void { - $this->label = $this->translationHelper->translate($this->node->nodeType->getLabel()) ?: ''; + $this->label = $this->translationHelper->translate($this->getNodeType($this->node)->getLabel()) ?: ''; if (empty($this->label)) { - $this->label = $this->node->nodeType->getName(); + $this->label = $this->node->nodeTypeName->value; } if (empty($this->postfix) && $this->node->nodeName !== null && $this->node->classification->isTethered()) { diff --git a/Neos.Neos/Classes/Fusion/MenuItemsImplementation.php b/Neos.Neos/Classes/Fusion/MenuItemsImplementation.php index 57692489567..dfb9a4f51d4 100644 --- a/Neos.Neos/Classes/Fusion/MenuItemsImplementation.php +++ b/Neos.Neos/Classes/Fusion/MenuItemsImplementation.php @@ -22,6 +22,7 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTypeConstraintsWithSubNodeTypes; use Neos\ContentRepository\Core\Projection\ContentGraph\Subtree; use Neos\Fusion\Exception as FusionException; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; /** * A Fusion Menu object @@ -86,7 +87,7 @@ public function getFilter() { $filter = $this->fusionValue('filter'); if ($filter === null) { - $filter = 'Neos.Neos:Document'; + $filter = NodeTypeNameFactory::NAME_DOCUMENT; } return $filter; @@ -266,7 +267,7 @@ function (Node $node) use ( $traversedHierarchy = []; $nodeTypeConstraintsWithSubNodeTypes = NodeTypeConstraintsWithSubNodeTypes::create( $this->getNodeTypeConstraints()->withAdditionalDisallowedNodeType( - NodeTypeName::fromString('Neos.Neos:Sites') + NodeTypeNameFactory::forSites() ), $contentRepository->getNodeTypeManager() ); diff --git a/Neos.Neos/Classes/Fusion/PluginImplementation.php b/Neos.Neos/Classes/Fusion/PluginImplementation.php index fc9a0da7e74..43db3bcbdf2 100644 --- a/Neos.Neos/Classes/Fusion/PluginImplementation.php +++ b/Neos.Neos/Classes/Fusion/PluginImplementation.php @@ -198,7 +198,7 @@ protected function getPluginNamespace(): string return $nodeArgumentNamespace; } - $nodeArgumentNamespace = $this->node->nodeType->getName(); + $nodeArgumentNamespace = $this->node->nodeTypeName->value; $nodeArgumentNamespace = str_replace(':', '-', $nodeArgumentNamespace); $nodeArgumentNamespace = str_replace('.', '_', $nodeArgumentNamespace); $nodeArgumentNamespace = strtolower($nodeArgumentNamespace); diff --git a/Neos.Neos/Classes/NodeTypePostprocessor/DefaultPropertyEditorPostprocessor.php b/Neos.Neos/Classes/NodeTypePostprocessor/DefaultPropertyEditorPostprocessor.php index 1e1bd397c98..5011dff1227 100644 --- a/Neos.Neos/Classes/NodeTypePostprocessor/DefaultPropertyEditorPostprocessor.php +++ b/Neos.Neos/Classes/NodeTypePostprocessor/DefaultPropertyEditorPostprocessor.php @@ -47,7 +47,7 @@ class DefaultPropertyEditorPostprocessor implements NodeTypePostprocessorInterfa */ public function process(NodeType $nodeType, array &$configuration, array $options): void { - $nodeTypeName = $nodeType->getName(); + $nodeTypeName = $nodeType->name->value; if (isset($configuration['properties']) && is_array($configuration['properties'])) { foreach ($configuration['properties'] as $propertyName => &$propertyConfiguration) { if (!isset($propertyConfiguration['type'])) { diff --git a/Neos.Neos/Classes/Routing/Cache/RouteCacheFlusher.php b/Neos.Neos/Classes/Routing/Cache/RouteCacheFlusher.php index be49d9cf6cf..14507af46af 100644 --- a/Neos.Neos/Classes/Routing/Cache/RouteCacheFlusher.php +++ b/Neos.Neos/Classes/Routing/Cache/RouteCacheFlusher.php @@ -16,8 +16,11 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Routing\RouterCachingService; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * This service flushes Route caches triggered by node changes. @@ -26,6 +29,11 @@ */ class RouteCacheFlusher { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + /** * @Flow\Inject * @var RouterCachingService @@ -50,7 +58,7 @@ public function registerNodeChange(Node $node) if (in_array($identifier, $this->tagsToFlush)) { return; } - if (!$node->nodeType->isOfType('Neos.Neos:Document')) { + if (!$this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_DOCUMENT)) { return; } $this->tagsToFlush[] = $identifier; diff --git a/Neos.Neos/Classes/Service/Mapping/NodeTypeStringConverter.php b/Neos.Neos/Classes/Service/Mapping/NodeTypeStringConverter.php index d525b32fb54..faab7553e7d 100644 --- a/Neos.Neos/Classes/Service/Mapping/NodeTypeStringConverter.php +++ b/Neos.Neos/Classes/Service/Mapping/NodeTypeStringConverter.php @@ -59,7 +59,7 @@ public function convertFrom( PropertyMappingConfigurationInterface $configuration = null ) { if ($source instanceof NodeType) { - return $source->getName(); + return $source->name->value; } return ''; diff --git a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php index f3a96315ec6..e626cfd37a8 100644 --- a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php +++ b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php @@ -71,9 +71,9 @@ public function generateNodeTypeSchema() } $schema['inheritanceMap']['subTypes'][$nodeTypeName] = []; - foreach ($this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), true) as $subNodeType) { + foreach ($this->nodeTypeManager->getSubNodeTypes($nodeType->name, true) as $subNodeType) { /** @var NodeType $subNodeType */ - $schema['inheritanceMap']['subTypes'][$nodeTypeName][] = $subNodeType->getName(); + $schema['inheritanceMap']['subTypes'][$nodeTypeName][] = $subNodeType->name->value; } } diff --git a/Neos.Neos/Classes/Utility/NodeTypeWithFallbackProvider.php b/Neos.Neos/Classes/Utility/NodeTypeWithFallbackProvider.php new file mode 100644 index 00000000000..5cc304c3fc1 --- /dev/null +++ b/Neos.Neos/Classes/Utility/NodeTypeWithFallbackProvider.php @@ -0,0 +1,27 @@ +contentRepositoryRegistry->get($node->subgraphIdentity->contentRepositoryId)->getNodeTypeManager(); + + return $nodeTypeManager->hasNodeType($node->nodeTypeName) + ? $nodeTypeManager->getNodeType($node->nodeTypeName) + : $nodeTypeManager->getNodeType(NodeTypeNameFactory::forFallback()); + } +} diff --git a/Neos.Neos/Classes/View/FusionView.php b/Neos.Neos/Classes/View/FusionView.php index e9c2ba43ab7..29a469857d8 100644 --- a/Neos.Neos/Classes/View/FusionView.php +++ b/Neos.Neos/Classes/View/FusionView.php @@ -27,9 +27,11 @@ use Neos\Neos\Domain\Model\RenderingMode; use Neos\Neos\Domain\Repository\SiteRepository; use Neos\Neos\Domain\Service\FusionService; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\Domain\Service\SiteNodeUtility; use Neos\Neos\Domain\Service\RenderingModeService; use Neos\Neos\Exception; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; use Psr\Http\Message\ResponseInterface; /** @@ -38,6 +40,10 @@ class FusionView extends AbstractView { use FusionViewI18nTrait; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; /** * @Flow\Inject @@ -54,12 +60,6 @@ class FusionView extends AbstractView #[Flow\Inject] protected RenderingModeService $renderingModeService; - /** - * @Flow\Inject - * @var ContentRepositoryRegistry - */ - protected $contentRepositoryRegistry; - /** * Renders the view * @@ -196,7 +196,7 @@ public function getFusionPath() protected function getClosestDocumentNode(Node $node): ?Node { $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); - while ($node !== null && !$node->nodeType->isOfType('Neos.Neos:Document')) { + while ($node !== null && !$this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_DOCUMENT)) { $node = $subgraph->findParentNode($node->nodeAggregateId); } diff --git a/Neos.Neos/Classes/ViewHelpers/Backend/DocumentBreadcrumbPathViewHelper.php b/Neos.Neos/Classes/ViewHelpers/Backend/DocumentBreadcrumbPathViewHelper.php index 6505fe97b78..4ca88d29f08 100644 --- a/Neos.Neos/Classes/ViewHelpers/Backend/DocumentBreadcrumbPathViewHelper.php +++ b/Neos.Neos/Classes/ViewHelpers/Backend/DocumentBreadcrumbPathViewHelper.php @@ -18,23 +18,24 @@ use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; use Neos\FluidAdaptor\Core\ViewHelper\AbstractViewHelper; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * Render a bread crumb path by using the labels of documents leading to the given node path */ class DocumentBreadcrumbPathViewHelper extends AbstractViewHelper { + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; + /** * @var boolean */ protected $escapeOutput = false; - /** - * @Flow\Inject - * @var ContentRepositoryRegistry - */ - protected $contentRepositoryRegistry; - public function initializeArguments(): void { parent::initializeArguments(); @@ -50,7 +51,7 @@ public function render(): mixed $currentNode = $node; while ($currentNode instanceof Node) { - if ($currentNode->nodeType->isOfType('Neos.Neos:Document')) { + if ($this->getNodeType($currentNode)->isOfType(NodeTypeNameFactory::NAME_DOCUMENT)) { $documentNodes[] = $currentNode; } $currentNode = $subgraph->findParentNode($currentNode->nodeAggregateId); diff --git a/Neos.Neos/Classes/ViewHelpers/Link/NodeViewHelper.php b/Neos.Neos/Classes/ViewHelpers/Link/NodeViewHelper.php index d2885f59ed4..bb81fab4a05 100644 --- a/Neos.Neos/Classes/ViewHelpers/Link/NodeViewHelper.php +++ b/Neos.Neos/Classes/ViewHelpers/Link/NodeViewHelper.php @@ -18,10 +18,11 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; +use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; +use Neos\Neos\Domain\Service\NodeTypeNameFactory; use Neos\Neos\FrontendRouting\NodeAddress; use Neos\Neos\FrontendRouting\NodeAddressFactory; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; use Neos\Flow\Http\Exception as HttpException; use Neos\Flow\Log\ThrowableStorageInterface; @@ -36,6 +37,7 @@ use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException; use Neos\Neos\FrontendRouting\NodeShortcutResolver; use Neos\Neos\FrontendRouting\NodeUriBuilder; +use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** * A view helper for creating links with URIs pointing to nodes. @@ -125,6 +127,10 @@ class NodeViewHelper extends AbstractTagBasedViewHelper { use FusionContextTrait; + use NodeTypeWithFallbackProvider; + + #[Flow\Inject] + protected ContentRepositoryRegistry $contentRepositoryRegistry; /** * @var string @@ -143,12 +149,6 @@ class NodeViewHelper extends AbstractTagBasedViewHelper */ protected $nodeShortcutResolver; - /** - * @Flow\Inject - * @var ContentRepositoryRegistry - */ - protected $contentRepositoryRegistry; - /** * @Flow\Inject * @var ThrowableStorageInterface @@ -298,7 +298,7 @@ public function render(): string json_encode($subgraph, JSON_PARTIAL_OUTPUT_ON_ERROR) ), 1601372444)); } - if ($resolvedNode && $resolvedNode->nodeType->isOfType('Neos.Neos:Shortcut')) { + if ($resolvedNode && $this->getNodeType($resolvedNode)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT)) { try { $shortcutNodeAddress = $this->nodeShortcutResolver->resolveShortcutTarget( $nodeAddress, diff --git a/Neos.Neos/Configuration/Settings.yaml b/Neos.Neos/Configuration/Settings.yaml index 16a96abe01f..edbc123e2cb 100755 --- a/Neos.Neos/Configuration/Settings.yaml +++ b/Neos.Neos/Configuration/Settings.yaml @@ -512,11 +512,6 @@ Neos: neos-plugin: Plugins ContentRepository: - # This instructs neos to fallback to the given type if a node type can't be found (because it was removed or has - # been renamed for example). The default "Neos.Neos:FallbackNode" renders a warning in backend and is ignored - # in frontend rendering - fallbackNodeType: 'Neos.Neos:FallbackNode' - # Definition of available content dimensions. Additional content dimensions may be defined in third-party packages # or via global settings. # diff --git a/Neos.Neos/NodeTypes/Content/FallbackNode.yaml b/Neos.Neos/NodeTypes/FallbackNode.yaml similarity index 100% rename from Neos.Neos/NodeTypes/Content/FallbackNode.yaml rename to Neos.Neos/NodeTypes/FallbackNode.yaml diff --git a/Neos.Neos/Configuration/NodeTypes.Sites.yaml b/Neos.Neos/NodeTypes/Root/Sites.yaml similarity index 100% rename from Neos.Neos/Configuration/NodeTypes.Sites.yaml rename to Neos.Neos/NodeTypes/Root/Sites.yaml diff --git a/Neos.Neos/Resources/Private/Fusion/Prototypes/Content.fusion b/Neos.Neos/Resources/Private/Fusion/Prototypes/Content.fusion index fbd82078ffd..ced9c9d367f 100644 --- a/Neos.Neos/Resources/Private/Fusion/Prototypes/Content.fusion +++ b/Neos.Neos/Resources/Private/Fusion/Prototypes/Content.fusion @@ -18,7 +18,7 @@ prototype(Neos.Neos:Content) < prototype(Neos.Fusion:Template) { # attributes.class.@process.nodeType > # } # in your site's Fusion if you don't need that behavior. - attributes.class.@process.nodeType = ${Array.push(value, String.toLowerCase(String.pregReplace(node.nodeType.name, '/[[:^alnum:]]/', '-')))} + attributes.class.@process.nodeType = ${Array.push(value, String.toLowerCase(String.pregReplace(node.nodeTypeName.value, '/[[:^alnum:]]/', '-')))} # The following line must not be removed as it adds required meta data to all content elements in backend @process.contentElementWrapping { diff --git a/Neos.Neos/Resources/Private/Fusion/Prototypes/ContentCase.fusion b/Neos.Neos/Resources/Private/Fusion/Prototypes/ContentCase.fusion index 5a0a7152f0e..79bce3f566e 100644 --- a/Neos.Neos/Resources/Private/Fusion/Prototypes/ContentCase.fusion +++ b/Neos.Neos/Resources/Private/Fusion/Prototypes/ContentCase.fusion @@ -6,6 +6,6 @@ prototype(Neos.Neos:ContentCase) < prototype(Neos.Fusion:Case) { default { @position = 'end' condition = true - type = ${node.nodeType.name} + type = ${Neos.Node.getNodeType(node).name.value} } } diff --git a/Neos.Neos/Resources/Private/Fusion/RawContent/Node.fusion b/Neos.Neos/Resources/Private/Fusion/RawContent/Node.fusion index c977e308285..47ac7fb8562 100644 --- a/Neos.Neos/Resources/Private/Fusion/RawContent/Node.fusion +++ b/Neos.Neos/Resources/Private/Fusion/RawContent/Node.fusion @@ -1,6 +1,6 @@ prototype(Neos.Neos:RawContent.Node) < prototype(Neos.Neos:ContentComponent) { - nodeType = ${node.nodeType.name} + nodeType = ${node.nodeTypeName.value} renderer = Neos.Fusion:Case { custom { diff --git a/Neos.Neos/Resources/Private/Fusion/RootCase.fusion b/Neos.Neos/Resources/Private/Fusion/RootCase.fusion index 1cb7a12197b..ea6596c38e7 100644 --- a/Neos.Neos/Resources/Private/Fusion/RootCase.fusion +++ b/Neos.Neos/Resources/Private/Fusion/RootCase.fusion @@ -30,9 +30,9 @@ root { documentType { @position = 'end 9998' condition = Neos.Fusion:CanRender { - type = ${documentNode.nodeType.name} + type = ${documentNode.nodeTypeName.value} } - type = ${documentNode.nodeType.name} + type = ${documentNode.nodeTypeName.value} } default { @@ -53,7 +53,7 @@ root { error { @position = 'end 10001' condition = true - type = ${documentNode.nodeType.name} + type = ${documentNode.nodeTypeName.value} } @cache { diff --git a/Neos.Neos/Resources/Private/Templates/Service/Nodes/Index.html b/Neos.Neos/Resources/Private/Templates/Service/Nodes/Index.html index 95b517807d9..7f112b3b14a 100644 --- a/Neos.Neos/Resources/Private/Templates/Service/Nodes/Index.html +++ b/Neos.Neos/Resources/Private/Templates/Service/Nodes/Index.html @@ -27,7 +27,7 @@

{neos:backend.translate(id: 'service.nodes.title', value: 'Nodes')}

({node.nodeAggregateId.value}) - [{node.nodeType.name}] + [{node.nodeTypeName.value}] {neos:backend.translate(id: 'service.nodes.show', value: 'Show')} diff --git a/Neos.Neos/Resources/Private/Templates/Service/Nodes/Show.html b/Neos.Neos/Resources/Private/Templates/Service/Nodes/Show.html index 34f2ff8a711..7c1f2816b76 100644 --- a/Neos.Neos/Resources/Private/Templates/Service/Nodes/Show.html +++ b/Neos.Neos/Resources/Private/Templates/Service/Nodes/Show.html @@ -25,7 +25,7 @@

{neos:backend.translate(id: 'node', value: 'Node')}: {node.label}

_type - {node.nodeType.name} + {node.nodeTypeName.value} diff --git a/Neos.Neos/Tests/Functional/Fusion/NodeHelperTest.php b/Neos.Neos/Tests/Functional/Fusion/NodeHelperTest.php index af9b5918047..7ae29c33826 100644 --- a/Neos.Neos/Tests/Functional/Fusion/NodeHelperTest.php +++ b/Neos.Neos/Tests/Functional/Fusion/NodeHelperTest.php @@ -13,8 +13,11 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\Factory\ContentRepositoryId; +use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValue; +use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; +use Neos\ContentRepository\Core\NodeType\DefaultNodeLabelGeneratorFactory; use Neos\ContentRepository\Core\NodeType\NodeType; +use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphIdentity; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; @@ -24,6 +27,7 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateClassification; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\TestSuite\Unit\NodeSubjectProvider; use Neos\Fusion\Tests\Functional\FusionObjects\AbstractFusionObjectTest; use PHPUnit\Framework\MockObject\MockObject; @@ -117,44 +121,44 @@ protected function setUp(): void { $this->markTestSkipped('Skipped until we find a better way to mock node read models (see https://github.com/neos/neos-development-collection/issues/4317)'); parent::setUp(); + $nodeSubjectProvider = new NodeSubjectProvider(); + + $nodeTypeName = NodeTypeName::fromString('Neos.Neos:Content.Text'); + // todo injecting the mocked nodeType in the node doesnt matter, as the nodeType is fetched from the nodeTypeManager in the NodeHelper + $textNodeType = new NodeType( + $nodeTypeName, + [], + [ + 'ui' => [ + 'label' => 'Content.Text' + ] + ], + new NodeTypeManager( + fn () => [], + new DefaultNodeLabelGeneratorFactory() + ), + new DefaultNodeLabelGeneratorFactory() + ); - $nodeType = $this - ->getMockBuilder(NodeType::class) - ->setMethods(['getName', 'getLabel']) - ->disableOriginalConstructor() - ->getMock(); - $nodeType - ->method('getName') - ->willReturn('Neos.Neos:Content.Text'); - $nodeType - ->method('getLabel') - ->willReturn('Content.Text'); - - $textNodeProperties = $this - ->getMockBuilder(PropertyCollection::class) - ->getMock(); - $textNodeProperties - ->method('offsetExists') - ->willReturnCallback(function ($arg) { - return $arg === 'title' || $arg === 'text'; - }); - $textNodeProperties - ->method('offsetGet') - ->willReturnCallback(function ($arg) { - if ($arg === 'title') { - return 'Some title'; - } - if ($arg === 'text') { - return 'Some text'; - } - return null; - }); + $textNodeProperties = new PropertyCollection( + SerializedPropertyValues::fromArray([ + 'title' => new SerializedPropertyValue( + 'Some title', + 'string' + ), + 'text' => new SerializedPropertyValue( + 'Some text', + 'string' + ), + ]), + $nodeSubjectProvider->propertyConverter + ); $now = new \DateTimeImmutable(); $this->textNode = new Node( ContentSubgraphIdentity::create( - ContentRepositoryId::fromString("cr"), + $contentRepositoryId, ContentStreamId::fromString("cs"), DimensionSpacePoint::fromArray([]), VisibilityConstraints::withoutRestrictions() @@ -162,8 +166,8 @@ protected function setUp(): void NodeAggregateId::fromString("na"), OriginDimensionSpacePoint::fromArray([]), NodeAggregateClassification::CLASSIFICATION_REGULAR, - NodeTypeName::fromString("nt"), - $nodeType, + $nodeTypeName, + $textNodeType, $textNodeProperties, null, Timestamps::create($now, $now, null, null) diff --git a/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php b/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php index f0d8d3d6ac1..f5c64ffef50 100644 --- a/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php +++ b/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php @@ -42,8 +42,7 @@ public function setUp(): void $this->nodeTypeSchemaBuilder = NodeTypeSchemaBuilder::create( new NodeTypeManager( fn() => $configurationManager->getConfiguration('NodeTypes'), - $nodeLabelGeneratorFactory, - null + $nodeLabelGeneratorFactory ) ); $this->schema = $this->nodeTypeSchemaBuilder->generateNodeTypeSchema(); diff --git a/Neos.Neos/Tests/Unit/NodeTypePostprocessor/DefaultPropertyEditorPostprocessorTest.php b/Neos.Neos/Tests/Unit/NodeTypePostprocessor/DefaultPropertyEditorPostprocessorTest.php index 7bffae66acd..b0c1d52fafa 100644 --- a/Neos.Neos/Tests/Unit/NodeTypePostprocessor/DefaultPropertyEditorPostprocessorTest.php +++ b/Neos.Neos/Tests/Unit/NodeTypePostprocessor/DefaultPropertyEditorPostprocessorTest.php @@ -1,6 +1,6 @@ inject($postprocessor, 'dataTypesDefaultConfiguration', $dataTypesDefaultConfiguration); $this->inject($postprocessor, 'editorDefaultConfiguration', $editorDefaultConfiguration); - $mockNodeType = $this->getMockBuilder(NodeType::class)->disableOriginalConstructor()->getMock(); - $mockNodeType->method('getName')->willReturn('Some.NodeType:Name'); + $mockNodeType = new NodeType( + NodeTypeName::fromString('Some.NodeType:Name'), + [], + [], + new NodeTypeManager( + fn () => [], + new DefaultNodeLabelGeneratorFactory() + ), + new DefaultNodeLabelGeneratorFactory() + ); $postprocessor->process($mockNodeType, $configuration, []); return $configuration; } diff --git a/Neos.NodeTypes.Navigation/Resources/Private/Fusion/Root.fusion b/Neos.NodeTypes.Navigation/Resources/Private/Fusion/Root.fusion index 4b6b91414fd..b4c1a4b2e40 100644 --- a/Neos.NodeTypes.Navigation/Resources/Private/Fusion/Root.fusion +++ b/Neos.NodeTypes.Navigation/Resources/Private/Fusion/Root.fusion @@ -12,7 +12,7 @@ prototype(Neos.NodeTypes.Navigation:Navigation) < prototype(Neos.Neos:Menu) { maximumLevels = ${q(node).property('maximumLevels')} maximumLevels.@process.1 = ${String.toInteger(value)} - attributes.class.@process.nodeType = ${Array.push(value, String.toLowerCase(String.pregReplace(node.nodeType.name, '/[[:^alnum:]]/', '-')))} + attributes.class.@process.nodeType = ${Array.push(value, String.toLowerCase(String.pregReplace(node.nodeTypeName.value, '/[[:^alnum:]]/', '-')))} active.attributes = Neos.Fusion:Attributes { class = 'active' diff --git a/composer.json b/composer.json index 1c558eff5f0..7348c34a7bb 100644 --- a/composer.json +++ b/composer.json @@ -91,7 +91,7 @@ "scripts": { "lint:phpcs-psr12": "../../bin/phpcs --colors --standard=PSR12 ./Neos.ContentGraph.DoctrineDbalAdapter/src ./Neos.ContentGraph.PostgreSQLAdapter/src ./Neos.ContentRepository.BehavioralTests/Classes ./Neos.ContentRepository.TestSuite/Classes ./Neos.ContentRepository.Core/Classes ./Neos.Neos/Classes", "lint:phpcs": [ - "@lint:phpcs-psr12 --exclude=Generic.Files.LineLength" + "@lint:phpcs-psr12 --exclude=Generic.Files.LineLength,PSR1.Files.SideEffects" ], "lint:phpstan": "../../bin/phpstan analyse", "lint:distributionintegrity": "[ -d 'Neos.ContentRepository' ] && { echo 'Package Neos.ContentRepository should not exist.' 1>&2; exit 1; } || exit 0;",