Skip to content

Commit

Permalink
Merge pull request #96 from neos/feature/improve-node-rewrite-v2
Browse files Browse the repository at this point in the history
FEATURE: Improve Node and Node interfaces rewrites (part 2)
  • Loading branch information
mhsdesign authored Nov 28, 2024
2 parents 9794b58 + 863726a commit 03f8f55
Show file tree
Hide file tree
Showing 23 changed files with 820 additions and 21 deletions.
24 changes: 18 additions & 6 deletions config/set/contentrepository-90.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@
use Neos\Rector\ContentRepository90\Rules\NodeGetChildNodesRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetContextGetWorkspaceNameRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetContextGetWorkspaceRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetContextPathRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetDepthRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetDimensionsRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetHiddenBeforeAfterDateTimeRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetIdentifierRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetNodeTypeGetNameRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetNodeTypeRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetParentRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetPathRector;
use Neos\Rector\ContentRepository90\Rules\NodeGetPropertyNamesRector;
use Neos\Rector\ContentRepository90\Rules\NodeIsAutoCreatedRector;
use Neos\Rector\ContentRepository90\Rules\NodeIsHiddenInIndexRector;
use Neos\Rector\ContentRepository90\Rules\NodeIsHiddenRector;
use Neos\Rector\ContentRepository90\Rules\NodeLabelGeneratorRector;
Expand Down Expand Up @@ -174,19 +177,20 @@
// Fusion: node.nodeType.name -> node.nodeTypeName
$rectorConfig->rule(FusionNodeNodeTypeRector::class);
// setHidden
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHidden', '!! Node::setHidden() is not supported by the new CR. Use the "EnableNodeAggregate" or "DisableNodeAggregate" command to change the visibility of the node.');
// isHidden
$rectorConfig->rule(NodeIsHiddenRector::class);
$rectorConfig->rule(FusionNodeHiddenRector::class);
// 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.');
$rectorConfig->rule(NodeGetHiddenBeforeAfterDateTimeRector::class);
// 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.');
// PHP: Covered by NodeGetHiddenBeforeAfterDateTimeRector
$rectorConfig->rule(FusionNodeHiddenBeforeDateTimeRector::class);
// 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.');
// PHP: Covered by NodeGetHiddenBeforeAfterDateTimeRector
// 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.');
// PHP: Covered by NodeGetHiddenBeforeAfterDateTimeRector
$rectorConfig->rule(FusionNodeHiddenAfterDateTimeRector::class);
// setHiddenInIndex
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHiddenInIndex', '!! Node::setHiddenInIndex() is not supported by the new CR. Use the "SetNodeProperties" command to change the property value for "hiddenInMenu".');
Expand All @@ -204,7 +208,7 @@
$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
$rectorConfig->rule(NodeGetContextPathRector::class);
$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
Expand Down Expand Up @@ -239,7 +243,9 @@
$rectorConfig->rule(NodeGetChildNodesRector::class);
// hasChildNodes($nodeTypeFilter) - deprecated
// remove()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'remove', '!! Node::remove() is not supported by the new CR. Use the "RemoveNodeAggregate" command to remove a node.');
// setRemoved()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setRemoved', '!! Node::setRemoved() is not supported by the new CR. Use the "RemoveNodeAggregate" command to remove a node.');
// isRemoved()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'isRemoved', '!! Node::isRemoved() - the new CR *never* returns removed nodes; so you can simplify your code and just assume removed == FALSE in all scenarios.');
$fusionNodePropertyPathToWarningComments[] = new FusionNodePropertyPathToWarningComment('removed', 'Line %LINE: !! node.removed - the new CR *never* returns removed nodes; so you can simplify your code and just assume removed == FALSE in all scenarios.');
Expand All @@ -248,11 +254,17 @@
// hasAccessRestrictions()
// isNodeTypeAllowedAsChildNode()
// moveBefore()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'moveBefore', '!! Node::moveBefore() is not supported by the new CR. Use the "MoveNodeAggregate" command to move a node.');
// moveAfter()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'moveAfter', '!! Node::moveAfter() is not supported by the new CR. Use the "MoveNodeAggregate" command to move a node.');
// moveInto()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'moveInto', '!! Node::moveInto() is not supported by the new CR. Use the "MoveNodeAggregate" command to move a node.');
// copyBefore()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'copyBefore', '!! Node::copyBefore() is not supported by the new CR. Use the "NodeDuplicationService::copyNodesRecursively" to copy a node.');
// copyAfter()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'copyAfter', '!! Node::copyAfter() is not supported by the new CR. Use the "NodeDuplicationService::copyNodesRecursively" to copy a node.');
// copyInto()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'copyInto', '!! Node::copyInto() is not supported by the new CR. Use the "NodeDuplicationService::copyNodesRecursively" to copy a node.');
// getNodeData()
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getNodeData', '!! Node::getNodeData() - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here.');
// getContext()
Expand All @@ -267,7 +279,7 @@
// TODO: Fusion
// createVariantForContext()
// isAutoCreated()
// TODO: PHP
$rectorConfig->rule(NodeIsAutoCreatedRector::class);
$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.');

Expand Down
106 changes: 100 additions & 6 deletions docs/rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 61 Rules Overview
# 64 Rules Overview

## ContentDimensionCombinatorGetAllAllowedCombinationsRector

Expand Down Expand Up @@ -1359,7 +1359,7 @@ return static function (RectorConfig $rectorConfig): void {

## NodeGetContextGetWorkspaceNameRector

`"NodeInterface::getContext()::getWorkspace()"` will be rewritten
`"NodeInterface::getContext()::getWorkspaceName()"` will be rewritten

- class: [`Neos\Rector\ContentRepository90\Rules\NodeGetContextGetWorkspaceNameRector`](../src/ContentRepository90/Rules/NodeGetContextGetWorkspaceNameRector.php)

Expand Down Expand Up @@ -1409,6 +1409,31 @@ return static function (RectorConfig $rectorConfig): void {

<br>

## NodeGetContextPathRector

`"NodeInterface::getContextPath()"` will be rewritten

- class: [`Neos\Rector\ContentRepository90\Rules\NodeGetContextPathRector`](../src/ContentRepository90/Rules/NodeGetContextPathRector.php)

```diff
<?php

use Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub;

class SomeClass
{
public function run(NodeLegacyStub $node)
{
- return $node->getContextPath();
+ return \Neos\ContentRepository\Core\SharedModel\Node\NodeAddress::fromNode($node)->toJson();
}
}

?>
```

<br>

## NodeGetDepthRector

`"NodeInterface::getDepth()"` will be rewritten
Expand Down Expand Up @@ -1437,7 +1462,7 @@ return static function (RectorConfig $rectorConfig): void {

## NodeGetDimensionsRector

`"NodeInterface::getChildNodes()"` will be rewritten
`"NodeInterface::getDimensions()"` will be rewritten

- class: [`Neos\Rector\ContentRepository90\Rules\NodeGetDimensionsRector`](../src/ContentRepository90/Rules/NodeGetDimensionsRector.php)

Expand All @@ -1462,6 +1487,51 @@ return static function (RectorConfig $rectorConfig): void {

<br>

## NodeGetHiddenBeforeAfterDateTimeRector

`"NodeInterface::getHiddenBeforeDateTime()",` `"NodeInterface::setHiddenBeforeDateTime()",` `"NodeInterface::getHiddenAfterDateTime()"` and `"NodeInterface::setHiddenAfterDateTime()"` will be rewritten

- class: [`Neos\Rector\ContentRepository90\Rules\NodeGetHiddenBeforeAfterDateTimeRector`](../src/ContentRepository90/Rules/NodeGetHiddenBeforeAfterDateTimeRector.php)

```diff
<?php

use Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub;

class SomeClass
{
public function nodeHiddenBeforeDateTime(NodeLegacyStub $node)
{
- $dateTime = $node->getHiddenBeforeDateTime();
+ // TODO 9.0 migration: Timed publishing has been conceptually changed and has been extracted into a dedicated package. Please check https://github.com/neos/timeable-node-visibility for further details.

+ $dateTime = $node->getProperty('enableAfterDateTime');
+ // TODO 9.0 migration: Timed publishing has been conceptually changed and has been extracted into a dedicated package. Please check https://github.com/neos/timeable-node-visibility for further details.
+ // Use the "SetNodeProperties" command to change property values for "enableAfterDateTime" or "disableAfterDateTime".
+
+
$node->setHiddenBeforeDateTime($dateTime);
}

public function nodeHiddenAfterDateTime(NodeLegacyStub $node)
{
- $dateTime = $node->getHiddenAfterDateTime();
+ // TODO 9.0 migration: Timed publishing has been conceptually changed and has been extracted into a dedicated package. Please check https://github.com/neos/timeable-node-visibility for further details.
+
+ $dateTime = $node->getProperty('disableAfterDateTime');
+ // TODO 9.0 migration: Timed publishing has been conceptually changed and has been extracted into a dedicated package. Please check https://github.com/neos/timeable-node-visibility for further details.
+ // Use the "SetNodeProperties" command to change property values for "enableAfterDateTime" or "disableAfterDateTime".
+

$node->setHiddenAfterDateTime($dateTime);
}
}

?>
```

<br>

## NodeGetIdentifierRector

`"NodeInterface::getIdentifier()"` will be rewritten
Expand Down Expand Up @@ -1533,8 +1603,7 @@ return static function (RectorConfig $rectorConfig): void {
public function run(NodeLegacyStub $node)
{
- $nodeType = $node->getNodeType();
+ // TODO 9.0 migration: Make this code aware of multiple Content Repositories.
+ $contentRepository = $this->contentRepositoryRegistry->get(\Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId::fromString('default'));
+ $contentRepository = $this->contentRepositoryRegistry->get($node->contentRepositoryId);
+ $nodeType = $contentRepository->getNodeTypeManager()->getNodeType($node->nodeTypeName);
}
}
Expand Down Expand Up @@ -1623,6 +1692,31 @@ return static function (RectorConfig $rectorConfig): void {

<br>

## NodeIsAutoCreatedRector

"NodeInterface::isAutoCreated" will be rewritten

- class: [`Neos\Rector\ContentRepository90\Rules\NodeIsAutoCreatedRector`](../src/ContentRepository90/Rules/NodeIsAutoCreatedRector.php)

```diff
<?php

use Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub;

class SomeClass
{
public function run(NodeLegacyStub $node)
{
- $bool = $node->isAutoCreated();
+ $bool = $node->classification->isTethered();
}
}

?>
```

<br>

## NodeIsHiddenInIndexRector

`"NodeInterface::isHiddenInIndex()"` will be rewritten
Expand Down Expand Up @@ -1808,7 +1902,7 @@ return static function (RectorConfig $rectorConfig): void {
$nodeName = NodeName::fromString('name');
$nodeType = $node->getNodeType();
- $type = $nodeType->getTypeOfAutoCreatedChildNode($nodeName);
+ // TODO 9.0 migration: Make this code aware of multiple Content Repositories.
+ // TODO 9.0 migration: Make this code aware of multiple Content Repositories. If you have a Node object around you can use $node->contentRepositoryId.
+ $contentRepository = $this->contentRepositoryRegistry->get(\Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId::fromString('default'));
+ $type = $contentRepository->getNodeTypeManager()->getNodeType($nodeType->tetheredNodeTypeDefinitions->get($nodeName));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ final class NodeGetContextGetWorkspaceNameRector extends AbstractRector

public function __construct(
private readonly NodesToAddCollector $nodesToAddCollector
)
{
) {
}

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('"NodeInterface::getContext()::getWorkspace()" will be rewritten', __CLASS__);
return CodeSampleLoader::fromFile('"NodeInterface::getContext()::getWorkspaceName()" will be rewritten', __CLASS__);
}

/**
Expand Down
61 changes: 61 additions & 0 deletions src/ContentRepository90/Rules/NodeGetContextPathRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare (strict_types=1);

namespace Neos\Rector\ContentRepository90\Rules;

use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress;
use Neos\Rector\Utility\CodeSampleLoader;
use PhpParser\Node;
use PHPStan\Type\ObjectType;
use Rector\Core\Rector\AbstractRector;
use Rector\PostRector\Collector\NodesToAddCollector;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class NodeGetContextPathRector extends AbstractRector
{
use AllTraits;

public function __construct(
private readonly NodesToAddCollector $nodesToAddCollector
) {
}

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('"NodeInterface::getContextPath()" will be rewritten', __CLASS__);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [\PhpParser\Node\Expr\MethodCall::class];
}

/**
* @param \PhpParser\Node\Expr\MethodCall $node
*/
public function refactor(Node $node): ?Node
{
assert($node instanceof Node\Expr\MethodCall);

if (!$this->isObjectType($node->var, new ObjectType(\Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub::class))) {
return null;
}
if (!$this->isName($node->name, 'getContextPath')) {
return null;
}


return
$this->nodeFactory->createMethodCall(
$this->nodeFactory->createStaticCall(
NodeAddress::class,
'fromNode',
[$node->var]),
'toJson'
);
}
}
13 changes: 7 additions & 6 deletions src/ContentRepository90/Rules/NodeGetDimensionsRector.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

declare (strict_types=1);

namespace Neos\Rector\ContentRepository90\Rules;

use Neos\Rector\Utility\CodeSampleLoader;
Expand All @@ -16,26 +17,26 @@ final class NodeGetDimensionsRector extends AbstractRector

public function __construct(
private readonly NodesToAddCollector $nodesToAddCollector
)
{
) {
}

public function getRuleDefinition() : RuleDefinition
public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('"NodeInterface::getChildNodes()" will be rewritten', __CLASS__);
return CodeSampleLoader::fromFile('"NodeInterface::getDimensions()" will be rewritten', __CLASS__);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
public function getNodeTypes(): array
{
return [\PhpParser\Node\Expr\MethodCall::class];
}

/**
* @param \PhpParser\Node\Expr\MethodCall $node
*/
public function refactor(Node $node) : ?Node
public function refactor(Node $node): ?Node
{
assert($node instanceof Node\Expr\MethodCall);

Expand Down
Loading

0 comments on commit 03f8f55

Please sign in to comment.