Skip to content

Commit

Permalink
TASK Refactor node properties
Browse files Browse the repository at this point in the history
  • Loading branch information
dlubitz committed Nov 3, 2023
1 parent 3cae4c0 commit 538b9e7
Show file tree
Hide file tree
Showing 14 changed files with 484 additions and 7 deletions.
35 changes: 28 additions & 7 deletions config/set/contentrepository-90.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
use Neos\Rector\ContentRepository90\Rules\ContextIsInBackendRector;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\Rector\ContentRepository90\Rules\FusionPrimaryContentRector;
use Neos\Rector\Generic\ValueObject\FusionFlowQueryNodePropertyToWarningComment;
use Neos\Rector\ContentRepository90\Rules\FusionNodeContextPathRector;
use Neos\Rector\ContentRepository90\Rules\FusionNodeAutoCreatedRector;

return static function (RectorConfig $rectorConfig): void {
// Register FusionFileProcessor. All Fusion Rectors will be auto-registered at this processor.
Expand Down Expand Up @@ -93,13 +96,16 @@
$methodCallToWarningComments = [];


$fusionFlowQueryPropertyToComments = [];
/**
* Neos\ContentRepository\Domain\Model\NodeInterface
*/
// setName
// getName
$methodCallToPropertyFetches[] = new MethodCallToPropertyFetch(NodeLegacyStub::class, 'getName', 'nodeName');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_name', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_name")" to "VARIABLE.nodeName.value". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getLabel -> compatible with ES CR node (nothing to do)
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_label', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_label")" to "VARIABLE.label". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setProperty
// hasProperty -> compatible with ES CR Node (nothing to do)
// getProperty -> compatible with ES CR Node (nothing to do)
Expand All @@ -116,56 +122,64 @@
// setNodeType
// getNodeType: NodeType
$methodCallToPropertyFetches[] = new MethodCallToPropertyFetch(NodeLegacyStub::class, 'getNodeType', 'nodeType');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_nodeType', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_nodeType")" to "VARIABLE.nodeType". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setHidden
// isHidden
$rectorConfig->rule(NodeIsHiddenRector::class);
// TODO: Fusion NodeAccess
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hidden', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_hidden")". Use the NodeHiddenStateFinder of CR to determine the hidden state. ');
// TODO: Fusion NodeAccess
// setHiddenBeforeDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHiddenBeforeDateTime', '!! Node::setHiddenBeforeDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// getHiddenBeforeDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getHiddenBeforeDateTime', '!! Node::getHiddenBeforeDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionNodePropertyPathToWarningComments[] = new FusionNodePropertyPathToWarningComment('hiddenBeforeDateTime', 'Line %LINE: !! node.hiddenBeforeDateTime is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenBeforeDateTime', 'Line %LINE: !! "q(VARIABLE).property("_hiddenBeforeDateTime")" is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// setHiddenAfterDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHiddenAfterDateTime', '!! Node::setHiddenAfterDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// getHiddenAfterDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getHiddenAfterDateTime', '!! Node::getHiddenAfterDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionNodePropertyPathToWarningComments[] = new FusionNodePropertyPathToWarningComment('hiddenAfterDateTime', 'Line %LINE: !! node.hiddenAfterDateTime is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenAfterDateTime', 'Line %LINE: !! "q(VARIABLE).property("_hiddenAfterDateTime")" is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// setHiddenInIndex
// isHiddenInIndex
$rectorConfig->rule(NodeIsHiddenInIndexRector::class);
// Fusion: .hiddenInIndex -> node.properties._hiddenInIndex
$rectorConfig->rule(FusionNodeHiddenInIndexRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenInIndex', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_hiddenInIndex")" to "VARIABLE.properties._hiddenInIndex". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setAccessRoles
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setAccessRoles', '!! Node::setAccessRoles() is not supported by the new CR.');
// getAccessRoles
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getAccessRoles', '!! Node::getAccessRoles() is not supported by the new CR.');
// getPath
$rectorConfig->rule(NodeGetPathRector::class);
// Fusion: .depth -> Neos.NodeAccess.depth(node)
$rectorConfig->rule(FusionNodePathRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_path', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_path")" to "Neos.Node.path(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getContextPath
// TODO: PHP
// TODO: Fusion
// - NodeAddress + LOG (WARNING)
// TODO: PHP
$rectorConfig->rule(FusionNodeContextPathRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_contextPath', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getDepth
$rectorConfig->rule(NodeGetDepthRector::class);
// Fusion: .depth -> Neos.Node.depth(node)
$rectorConfig->rule(FusionNodeDepthRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_depth', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_depth")" to "Neos.Node.depth(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setWorkspace -> internal
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setWorkspace', '!! Node::setWorkspace() was always internal, and the workspace system has been fundamentally changed with the new CR. Try to rewrite your code around Content Streams.');
// getWorkspace
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getWorkspace', '!! Node::getWorkspace() does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity.');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_workspace', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_workspace")". It does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity.');
// getIdentifier
$rectorConfig->rule(NodeGetIdentifierRector::class);
$rectorConfig->rule(FusionNodeIdentifierRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_identifier', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_identifier")" to "VARIABLE.nodeAggregateId.value". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setIndex -> internal
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setIndex', '!! Node::setIndex() was always internal. To reorder nodes, use the "MoveNodeAggregate" command');
// getIndex
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getIndex', '!! Node::getIndex() is not supported. You can fetch all siblings and inspect the ordering');
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_index', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_index")". You can fetch all siblings and inspect the ordering.');
// getParent -> Node
$rectorConfig->rule(NodeGetParentRector::class);
// Fusion: .parent -> Neos.NodeAccess.findParent(node)
$rectorConfig->rule(FusionNodeParentRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_parent', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_parent")" to "q(VARIABLE).parent().get(0)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getParentPath - deprecated
// createNode
// createSingleNode -> internal
Expand Down Expand Up @@ -204,8 +218,15 @@
// TODO: Fusion
// createVariantForContext()
// isAutoCreated()
// TODO: PHP
$rectorConfig->rule(FusionNodeAutoCreatedRector::class);
$fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_autoCreated', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');

// getOtherNodeVariants()

$rectorConfig->ruleWithConfiguration(FusionNodePropertyPathToWarningCommentRector::class, $fusionFlowQueryPropertyToComments);


/**
* Neos\ContentRepository\Domain\Projection\Content\NodeInterface
*/
Expand Down
33 changes: 33 additions & 0 deletions src/ContentRepository90/Rules/FusionNodeAutoCreatedRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Neos\Rector\ContentRepository90\Rules;

use Neos\Rector\Core\FusionProcessing\EelExpressionTransformer;
use Neos\Rector\Core\FusionProcessing\FusionRectorInterface;
use Neos\Rector\Utility\CodeSampleLoader;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

class FusionNodeAutoCreatedRector implements FusionRectorInterface
{

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('Fusion: Rewrite node.autoCreated to node.classification.tethered', __CLASS__);
}

public function refactorFileContent(string $fileContent): string
{
return EelExpressionTransformer::parse($fileContent)
->process(fn(string $eelExpression) => preg_replace(
'/(node|documentNode|site)\.autoCreated/',
'$1.classification.tethered',
$eelExpression
))
->addCommentsIfRegexMatches(
'/\.autoCreated/',
'// TODO 9.0 migration: Line %LINE: !! You very likely need to rewrite "VARIABLE.autoCreated" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'
)->getProcessedContent();
}
}
33 changes: 33 additions & 0 deletions src/ContentRepository90/Rules/FusionNodeContextPathRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Neos\Rector\ContentRepository90\Rules;

use Neos\Rector\Core\FusionProcessing\EelExpressionTransformer;
use Neos\Rector\Core\FusionProcessing\FusionRectorInterface;
use Neos\Rector\Utility\CodeSampleLoader;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

class FusionNodeContextPathRector implements FusionRectorInterface
{

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('Fusion: Rewrite node.contextPath to Neos.Node.serializedNodeAddress(node)', __CLASS__);
}

public function refactorFileContent(string $fileContent): string
{
return EelExpressionTransformer::parse($fileContent)
->process(fn(string $eelExpression) => preg_replace(
'/(node|documentNode|site)\.contextPath/',
'Neos.Node.serializedNodeAddress($1)',
$eelExpression
))
->addCommentsIfRegexMatches(
'/\.contextPath/',
'// TODO 9.0 migration: Line %LINE: !! You very likely need to rewrite "VARIABLE.contextPath" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'
)->getProcessedContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Neos\Rector\Generic\Rules;

use Neos\Rector\Core\FusionProcessing\AfxParser\AfxParserException;
use Neos\Rector\Core\FusionProcessing\EelExpressionTransformer;
use Neos\Rector\Core\FusionProcessing\FusionParser\Exception\ParserException;
use Neos\Rector\Core\FusionProcessing\FusionRectorInterface;
use Neos\Rector\Core\FusionProcessing\Helper\RegexCommentTemplatePair;
use Neos\Rector\Utility\CodeSampleLoader;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;
use Neos\Rector\Generic\ValueObject\FusionFlowQueryNodePropertyToWarningComment;

class FusionFlowQueryNodePropertyToWarningCommentRector implements FusionRectorInterface, ConfigurableRectorInterface
{

use AllTraits;

/** @var FusionFlowQueryNodePropertyToWarningComment[] */
private array $fusionFlowQueryNodePropertyToWarningComments = [];

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('Fusion: Adds a warning comment when the defined property is used within an FlowQuery "property()".', __CLASS__, [
new FusionFlowQueryNodePropertyToWarningComment('_autoCreated', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.')
]);
}

/**
* @throws ParserException
* @throws AfxParserException
*/
public function refactorFileContent(string $fileContent): string
{

$regexWarningMessagePairs = [];
foreach ($this->fusionFlowQueryNodePropertyToWarningComments as $flowQueryNodePropertyToWarningComment) {
$property = $flowQueryNodePropertyToWarningComment->property;
$regexWarningMessagePairs[] = new RegexCommentTemplatePair(
"/\.property\(('|\")$property('|\")\)/",
(string)self::todoCommentAttribute($flowQueryNodePropertyToWarningComment->warningMessage)
);

}

return EelExpressionTransformer::parse($fileContent)
->addCommentsIfRegexesMatch($regexWarningMessagePairs)
->getProcessedContent();

}

/**
* @param FusionFlowQueryNodePropertyToWarningComment[] $configuration
*/
public function configure(array $configuration): void
{
Assert::allIsAOf($configuration, FusionFlowQueryNodePropertyToWarningComment::class);
$this->fusionFlowQueryNodePropertyToWarningComments = $configuration;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Neos\Rector\Generic\ValueObject;

class FusionFlowQueryNodePropertyToWarningComment
{
public function __construct(
public readonly string $property,
public readonly string $warningMessage,
)
{
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {

renderer = Neos.Fusion:Component {

#
# pass down props
#
attributes = ${node.autoCreated || documentNode.autoCreated}

#
# the `checked` state is calculated outside the renderer to allow` overriding via `attributes`
#
checked = false
checked.@process.checkMultiValue = ${Array.indexOf(field.getCurrentMultivalueStringified(), field.getTargetValueStringified()) > -1}
checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}

renderer = afx`
<input
type="checkbox"
name={node.autoCreated}
value={someOtherVariable.autoCreated}
checked={props.checked}
{...node.autoCreated}
/>
`
}
}
-----
// TODO 9.0 migration: Line 26: !! You very likely need to rewrite "VARIABLE.autoCreated" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {

renderer = Neos.Fusion:Component {

#
# pass down props
#
attributes = ${node.classification.tethered || documentNode.classification.tethered}

#
# the `checked` state is calculated outside the renderer to allow` overriding via `attributes`
#
checked = false
checked.@process.checkMultiValue = ${Array.indexOf(field.getCurrentMultivalueStringified(), field.getTargetValueStringified()) > -1}
checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}

renderer = afx`
<input
type="checkbox"
name={node.classification.tethered}
value={someOtherVariable.autoCreated}
checked={props.checked}
{...node.classification.tethered}
/>
`
}
}
Loading

0 comments on commit 538b9e7

Please sign in to comment.