Created
November 8, 2019 10:26
-
-
Save skurfuerst/beb644cc81af76eca7a321bb00dc07ee to your computer and use it in GitHub Desktop.
Make Nodes Unique
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace My\Package\Command; | |
use Neos\ContentRepository\Domain\Model\NodeInterface; | |
use Neos\ContentRepository\Domain\Service\ContextFactoryInterface; | |
use Neos\ContentRepository\Domain\Service\NodeServiceInterface; | |
use Neos\Flow\Cli\CommandController; | |
use Neos\Flow\Annotations as Flow; | |
class NodeNameUniquenessMigrationCommandController extends CommandController | |
{ | |
/** | |
* @Flow\Inject | |
* @var ContextFactoryInterface | |
*/ | |
protected $contextFactory; | |
/** | |
* @Flow\Inject | |
* @var NodeServiceInterface | |
*/ | |
protected $nodeService; | |
/** | |
* @param string $contentDimension | |
* @param string $contentDimensionValue | |
*/ | |
public function fixCommand($contentDimension = null, $contentDimensionValue = null) | |
{ | |
$contextProperties = [ | |
'workspaceName' => 'live', | |
'invisibleContentShown' => true, | |
'inaccessibleContentShown' => true, | |
'removedContentShown' => true | |
]; | |
if ($contentDimension && $contentDimensionValue) { | |
$this->outputLine('!!! Multilanguage case: ' . $contentDimension . ' - ' . $contentDimensionValue); | |
$contextProperties['dimensions'] = [ | |
$contentDimension => [$contentDimensionValue] | |
]; | |
$contextProperties['targetDimensions'] = [ | |
$contentDimension => $contentDimensionValue | |
]; | |
} else { | |
$this->outputLine('Single-Dimension Case'); | |
} | |
$context = $this->contextFactory->create($contextProperties); | |
$rootNode = $context->getNode('/')->getNode('sites/oekokiste-site'); | |
// We fill this list incrementally to store which node names we have already seen. If we found a seen node name, we start | |
// to rename. | |
$nodeNamesOfNonAutoCreatedChildNodes = []; | |
$this->traverseNodeTreeAndDetectNeededRenames($rootNode, $nodeNamesOfNonAutoCreatedChildNodes); | |
$this->outputLine('Done.'); | |
} | |
protected function traverseNodeTreeAndDetectNeededRenames(NodeInterface $node, &$nodeNamesOfNonAutoCreatedChildNodes) { | |
// auto-created nodes (like "main" or "spalte-1") will have name collisions; so we ignore them | |
if (!$node->isAutoCreated()) { | |
if (array_key_exists($node->getName(), $nodeNamesOfNonAutoCreatedChildNodes)) { | |
$newNodeName = $this->nodeService->generateUniqueNodeName($node->getParentPath()); | |
$this->outputLine('Duplicate: %s -> %s at path %s', [ | |
$node->getName(), | |
$newNodeName, | |
$node->getPath() | |
] | |
); | |
// This updates the node names recursively - I always feared that some parts inside here | |
// would break when being called repeatedly; but it seems to work just fine. That | |
// was the biggest risk for me. | |
// Phew ;-) | |
$node->setName($newNodeName); | |
} | |
$nodeNamesOfNonAutoCreatedChildNodes[$node->getName()] = true; | |
} | |
// Traverse to all children. | |
// NOTE: $node->getChildNodes() works DESPITE having maybe renamed $node (and thus the children's paths as well). | |
// We're lucky today :-) | |
foreach ($node->getChildNodes() as $childNode) { | |
$this->traverseNodeTreeAndDetectNeededRenames($childNode, $nodeNamesOfNonAutoCreatedChildNodes); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment