Created
September 17, 2021 09:37
-
-
Save jobee/f81717df954c1024f39cc308b422bb6d to your computer and use it in GitHub Desktop.
Neos CMS - Command controller example to cleanup inline-editable properties
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 Your\Package\Command; | |
use Doctrine\ORM\EntityManagerInterface; | |
use Neos\ContentRepository\Domain\Model\NodeType; | |
use Neos\ContentRepository\Domain\Model\Workspace; | |
use Neos\ContentRepository\Domain\Service\NodeTypeManager; | |
use Neos\Flow\Cli\CommandController; | |
use Neos\Flow\Persistence\PersistenceManagerInterface; | |
use Neos\Flow\Annotations as Flow; | |
use Neos\Neos\Controller\CreateContentContextTrait; | |
use Neos\Neos\Domain\Service\ContentDimensionPresetSourceInterface; | |
use Neos\ContentRepository\Domain\Service\ContentDimensionCombinator; | |
use Neos\Eel\FlowQuery\FlowQuery; | |
use Neos\ContentRepository\Domain\Model\NodeInterface; | |
use Neos\ContentRepository\Domain\Repository\WorkspaceRepository; | |
/** | |
* @Flow\Scope("singleton") | |
*/ | |
class NodeDataCommandController extends CommandController | |
{ | |
use CreateContentContextTrait; | |
/** | |
* Formatting rules get applied top to bottom with preg_replace() | |
* We also run a general trim() after | |
* | |
* @var array | |
*/ | |
protected $formattingRules = array( | |
// remove all <span> leftovers | |
'/<\/span><span>/' => '', | |
// replace all non-breaking spaces with whitespace | |
'/ /' => ' ', | |
// replace multiple whitespaces with a single one | |
'/\s+/' => ' ', | |
// trim whitespaces within <p> tags | |
'/<p>\s/' => '<p>', | |
'/\s<\/p>/' => '</p>', | |
); | |
/** | |
* @Flow\Inject | |
* @var NodeTypeManager | |
*/ | |
protected $nodeTypeManager; | |
/** | |
* @Flow\Inject | |
* @var ContentDimensionPresetSourceInterface | |
*/ | |
protected $contentDimensionPresetSource; | |
/** | |
* @Flow\Inject | |
* @var ContentDimensionCombinator | |
*/ | |
protected $contentDimensionCombinator; | |
/** | |
* @Flow\Inject | |
* @var WorkspaceRepository | |
*/ | |
protected $workspaceRepository; | |
/** | |
* @Flow\Inject | |
* @var PersistenceManagerInterface | |
*/ | |
protected $persistenceManager; | |
/** | |
* @Flow\Inject | |
* @var EntityManagerInterface | |
*/ | |
protected $entityManager; | |
/** | |
* Apply formatting rules on all text properties | |
* | |
* @param boolean $verbose | |
* @param boolean $dryRun | |
* @param string $nodeType | |
* @return void | |
*/ | |
public function cleanupInlineEditablePropertiesCommand($verbose = false, $dryRun = false, $nodeTypeName = null) | |
{ | |
if ($dryRun) | |
$this->output->outputLine('Dry run enabled!'); | |
else { | |
$question = $this->output->ask('<comment>Do you really want to apply all formatting rules? - 1.) run --dry-run before - 2.) Make sure you have a database backup! (y/N)</comment>', 'n'); | |
if ($question == 'n') | |
exit; | |
} | |
$this->output->outputLine('<comment>Apply formatting rules on all inline-editable properties...</comment>'); | |
$countTotalUpdatedNodes = 0; | |
foreach ($this->nodeTypeManager->getNodeTypes() as $nodeType) { | |
/** @var NodeType $nodeType */ | |
if ($nodeTypeName && $nodeType->getName() !== $nodeTypeName) | |
continue; | |
if ($nodeType->isAbstract()) | |
continue; | |
if (!($nodeType->isOfType('Neos.Neos:Content') || $nodeType->isOfType('Neos.Neos:Document'))) | |
continue; | |
$properties = array_keys($nodeType->getProperties()); | |
$properties = array_filter($properties, function ($propertyName) use ($nodeType) { | |
return $nodeType->getConfiguration('properties.' . $propertyName . '.ui.inlineEditable') === true; | |
}); | |
if (empty($properties)) { | |
continue; | |
} | |
$this->outputLine(sprintf('NodeType <fg=white;bg=blue>%s</> contains <fg=yellow>%s</> inline editable properties...', $nodeType->getName(), count($properties))); | |
foreach ($this->workspaceRepository->findAll() as $workspace) { | |
/** @var Workspace $workspace */ | |
if ($workspace->getNodeCount() <= 1) | |
continue; | |
$this->outputLine(sprintf('<fg=yellow>Checking "%s" workspace:</>', $workspace->getName())); | |
foreach ($this->contentDimensionCombinator->getAllAllowedCombinations() as $contentDimensionCombination) { | |
$countNodes = 0; | |
$countUpdatedNodes = 0; | |
$updatedProperties = []; | |
$dimensionContext = null; | |
$dimensionContext = $this->createContentContext($workspace->getName(), $contentDimensionCombination); | |
// Get existing nodes for the current context | |
$q = new FlowQuery(array($dimensionContext->getRootNode())); | |
$nodes = $q->context([ | |
'invisibleContentShown' => true, | |
'removedContentShown' => true, | |
'inaccessibleContentShown' => true | |
])->find('[instanceof ' . $nodeType->getName() . ']')->get(); | |
foreach ($nodes as $node) { | |
if (!$node instanceof NodeInterface) | |
continue; | |
if($node->getWorkspace()->getName() !== $workspace->getName()) | |
continue; | |
$countNodes++; | |
$nodeUpdates = 0; | |
foreach ($properties as $propertyName) { | |
$propertyValue = $node->getProperty($propertyName); | |
$propertyValueFormatted = $propertyValue; | |
foreach ($this->formattingRules as $pattern => $replacement) { | |
$propertyValueFormatted = preg_replace($pattern, $replacement, $propertyValueFormatted); | |
} | |
$propertyValueFormatted = trim($propertyValueFormatted); | |
if ($propertyValueFormatted == $propertyValue) | |
continue; | |
$nodeUpdates++; | |
if (isset($updatedProperties[$propertyName])) { | |
$updatedProperties[$propertyName]++; | |
} else { | |
$updatedProperties[$propertyName] = 1; | |
} | |
if ($dryRun !== true) | |
$node->setProperty($propertyName, $propertyValueFormatted); | |
if ($verbose) | |
$this->outputLine(sprintf('%s %s | <fg=yellow>"%s"</> => <fg=green>"%s"</>', $node->getIdentifier(), $propertyName, $propertyValue, $propertyValueFormatted)); | |
} | |
if (!empty($nodeUpdates)) | |
$countUpdatedNodes++; | |
} | |
if ($countUpdatedNodes) { | |
$countTotalUpdatedNodes += $countUpdatedNodes; | |
$this->outputLine(sprintf('=> <fg=blue>%s/%s</> nodes updated in %s - %s', $countUpdatedNodes, $countNodes, json_encode($contentDimensionCombination), json_encode($updatedProperties))); | |
} | |
} | |
} | |
} | |
$this->outputLine(); | |
$this->outputLine('SUMMARY'); | |
$this->outputLine(sprintf('<fg=blue>=> %s nodes updated in total</>', $countTotalUpdatedNodes)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment