Skip to content

Commit

Permalink
FEATURE: Introduce TetheredNodeTypeDefinitions VO
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed May 14, 2024
1 parent 1e8c4e7 commit 0e55e7e
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 9 deletions.
24 changes: 16 additions & 8 deletions Neos.ContentRepository.Core/Classes/NodeType/NodeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ final class NodeType
*/
protected bool $initialized = false;

private ?TetheredNodeTypeDefinitions $tetheredNodeTypeDefinitions = null;

/**
* @param NodeTypeName $name Name of the node type
* @param array<string,NodeType|null> $declaredSuperTypes Parent types instances of this node type, if null it should be unset
Expand Down Expand Up @@ -491,21 +493,27 @@ public function getDefaultValuesForProperties(): array
*/
public function hasTetheredNode(NodeName $nodeName): bool
{
$this->initialize();
return (bool)$this->getNodeTypeNameOfTetheredNode($nodeName);
return $this->getTetheredNodeTypeDefinitions()->contain($nodeName);
}

public function getNodeTypeNameOfTetheredNode(NodeName $nodeName): ?NodeTypeName
public function getTetheredNodeTypeDefinitions(): TetheredNodeTypeDefinitions
{
if ($this->tetheredNodeTypeDefinitions) {
return $this->tetheredNodeTypeDefinitions;
}
$this->initialize();
foreach ($this->fullConfiguration['childNodes'] ?? [] as $rawChildNodeName => $configurationForChildNode) {

$childNodeConfiguration = $this->getConfiguration('childNodes') ?? [];
$tetheredNodeTypeDefinitions = [];
foreach ($childNodeConfiguration as $childNodeName => $configurationForChildNode) {
if (isset($configurationForChildNode['type'])) {
if (NodeName::transliterateFromString($rawChildNodeName)->equals($nodeName)) {
return NodeTypeName::fromString($configurationForChildNode['type']);
}
$tetheredNodeTypeDefinitions[] = new TetheredNodeTypeDefinition(
NodeName::transliterateFromString($childNodeName),
NodeTypeName::fromString($configurationForChildNode['type'])
);
}
}
return null;
return $this->tetheredNodeTypeDefinitions = TetheredNodeTypeDefinitions::fromArray($tetheredNodeTypeDefinitions);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public function getTetheredNodesConfigurationForNodeType(NodeTypeName $nodeTypeN
public function isNodeTypeAllowedAsChildToTetheredNode(NodeTypeName $parentNodeTypeName, NodeName $tetheredNodeName, NodeTypeName $nodeTypeNameToCheck): bool
{
$parentNodeType = $this->getNodeType($parentNodeTypeName);
$nodeTypeNameOfTetheredNode = $parentNodeType?->getNodeTypeNameOfTetheredNode($tetheredNodeName);
$nodeTypeNameOfTetheredNode = $parentNodeType?->getTetheredNodeTypeDefinitions()->get($tetheredNodeName)?->nodeTypeName;
if (!$parentNodeType || !$nodeTypeNameOfTetheredNode) {
// Cannot determine if grandchild is allowed, because the given child node name is not auto-created.
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of the Neos.ContentRepository package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\ContentRepository\Core\NodeType;

use Neos\ContentRepository\Core\SharedModel\Node\NodeName;

/**
* @api
*/
final readonly class TetheredNodeTypeDefinition
{
public function __construct(
public NodeName $name,
public NodeTypeName $nodeTypeName
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\Core\NodeType;

/*
* This file is part of the Neos.ContentRepository package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\ContentRepository\Core\SharedModel\Node\NodeName;

/**
* @api
* @implements \IteratorAggregate<TetheredNodeTypeDefinition>
*/
final class TetheredNodeTypeDefinitions implements \IteratorAggregate
{
/**
* @var array<string, TetheredNodeTypeDefinition>
*/
private array $tetheredNodeTypeDefinitions;

private function __construct(TetheredNodeTypeDefinition ...$tetheredNodeTypeDefinitions)
{
/** @var array<string, TetheredNodeTypeDefinition> $tetheredNodeTypeDefinitions */
$this->tetheredNodeTypeDefinitions = $tetheredNodeTypeDefinitions;
}

/**
* @param array<TetheredNodeTypeDefinition> $tetheredNodeTypeDefinitions
*/
public static function fromArray(array $tetheredNodeTypeDefinitions): self
{
$tetheredNodeTypeDefinitionDefinitionByName = [];
foreach ($tetheredNodeTypeDefinitions as $index => $tetheredNodeTypeDefinitionDefinition) {
$tetheredNodeTypeDefinitionDefinition instanceof TetheredNodeTypeDefinition || throw new \InvalidArgumentException(sprintf('expected instance of %s, got: %s at index %s', TetheredNodeTypeDefinition::class, get_debug_type($tetheredNodeTypeDefinitionDefinition), $index), 1713549511);
!array_key_exists($tetheredNodeTypeDefinitionDefinition->name->value, $tetheredNodeTypeDefinitionDefinitionByName) || throw new \InvalidArgumentException(sprintf('Tethered node type definition with name "%s" is already registered at index %s', $tetheredNodeTypeDefinitionDefinition->name->value, $index), 1713549527);
$tetheredNodeTypeDefinitionDefinitionByName[$tetheredNodeTypeDefinitionDefinition->name->value] = $tetheredNodeTypeDefinitionDefinition;
}
return new self(...$tetheredNodeTypeDefinitionDefinitionByName);
}

public function contain(NodeName|string $nodeName): bool
{
if ($nodeName instanceof NodeName) {
$nodeName = $nodeName->value;
}
return array_key_exists($nodeName, $this->tetheredNodeTypeDefinitions);
}

public function get(NodeName|string $nodeName): ?TetheredNodeTypeDefinition
{
if ($nodeName instanceof NodeName) {
$nodeName = $nodeName->value;
}
return $this->tetheredNodeTypeDefinitions[$nodeName] ?? null;
}

public function getIterator(): \Traversable
{
return yield from $this->tetheredNodeTypeDefinitions;
}

/**
* @return array<TetheredNodeTypeDefinition>
*/
public function toArray(): array
{
return $this->tetheredNodeTypeDefinitions;
}
}

0 comments on commit 0e55e7e

Please sign in to comment.