Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Add migration for NodeSearchService #99

Merged
merged 2 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config/set/contentrepository-90.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
use Neos\Rector\ContentRepository90\Rules\NodeIsHiddenInIndexRector;
use Neos\Rector\ContentRepository90\Rules\NodeIsHiddenRector;
use Neos\Rector\ContentRepository90\Rules\NodeLabelGeneratorRector;
use Neos\Rector\ContentRepository90\Rules\NodeSearchServiceRector;
use Neos\Rector\ContentRepository90\Rules\NodeTypeAllowsGrandchildNodeTypeRector;
use Neos\Rector\ContentRepository90\Rules\NodeTypeGetAutoCreatedChildNodesRector;
use Neos\Rector\ContentRepository90\Rules\NodeTypeGetNameRector;
Expand Down Expand Up @@ -389,6 +390,11 @@
// ContentDimensionCombinator::getAllAllowedCombinations
$rectorConfig->rule(ContentDimensionCombinatorGetAllAllowedCombinationsRector::class);

/**
* Neos\Neos\Domain\Service\NodeSearchService
*/
$rectorConfig->rule(NodeSearchServiceRector::class);


/**
* Neos\ContentRepository\Domain\Factory\NodeFactory
Expand Down
138 changes: 134 additions & 4 deletions docs/rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 61 Rules Overview
# 63 Rules Overview

## ContentDimensionCombinatorGetAllAllowedCombinationsRector

Expand Down Expand Up @@ -1533,8 +1533,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 @@ -1700,6 +1699,52 @@ return static function (RectorConfig $rectorConfig): void {

<br>

## NodeSearchServiceRector

`"NodeSearchService::findDescendantNodes()"` will be rewritten

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

```diff
<?php

namespace Neos\Rector\Test;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\ContentRepository\Domain\Service\Context;

class SomeClass extends AnotherClass
{
/**
* @var \Neos\Neos\Domain\Service\NodeSearchService
*/
private $nodeSearchService;

public function startingPointNodeIsGiven(Node $node, Context $context)
{
$term = "term";
$searchNodeTypes = [];
- $nodes = $this->nodeSearchService->findByProperties($term, $searchNodeTypes, $context, $node);
+ // TODO 9.0 migration: This could be a suitable replacement. Please check if all your requirements are still fulfilled.
+ $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);
+ $nodes = $subgraph->findDescendantNodes($node->aggregateId, \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::create(nodeTypes: \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::create(\Neos\ContentRepository\Core\NodeType\NodeTypeNames::fromStringArray($searchNodeTypes), \Neos\ContentRepository\Core\NodeType\NodeTypeNames::createEmpty()), searchTerm: $term));
}

public function startingPointNodeIsNotGiven(Context $context)
{
$term = "term";
$searchNodeTypes = [];
- $nodes = $this->nodeSearchService->findByProperties($term, $searchNodeTypes, $context);
+ // TODO 9.0 migration: The replacement needs a node as starting point for the search. Please provide a node, to make this replacement working.
+ $node = 'we-need-a-node-here';
+ $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);
+ $nodes = $subgraph->findDescendantNodes($node->aggregateId, \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::create(nodeTypes: \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::create(\Neos\ContentRepository\Core\NodeType\NodeTypeNames::fromStringArray($searchNodeTypes), \Neos\ContentRepository\Core\NodeType\NodeTypeNames::createEmpty()), searchTerm: $term));
}
}
```

<br>

## NodeTypeAllowsGrandchildNodeTypeRector

"$nodeType->allowsGrandchildNodeType($parentNodeName, `$nodeType)"` will be rewritten.
Expand Down Expand Up @@ -1808,7 +1853,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 Expand Up @@ -1984,6 +2029,91 @@ return static function (RectorConfig $rectorConfig): void {

<br>

## SignalSlotToWarningCommentRector

"Warning comments for various non-supported signals

:wrench: **configure it!**

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

```php
<?php

declare(strict_types=1);

use Neos\Rector\Generic\Rules\SignalSlotToWarningCommentRector;
use Neos\Rector\Generic\ValueObject\SignalSlotToWarningComment;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$containerConfigurator->extension('rectorConfig', [
[
'class' => SignalSlotToWarningCommentRector::class,
'configuration' => [
new SignalSlotToWarningComment('PhpParser\Node', 'beforeMove', '!! This signal "beforeMove" on Node doesn\'t exist anymore'),
],
],
]);
};
```


```diff
<?php

use Neos\Flow\Core\Bootstrap;
use Neos\Flow\Package\Package as BasePackage;
use Neos\Flow\SignalSlot\Dispatcher;
use Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub;

class Package extends BasePackage
{
public function boot(Bootstrap $bootstrap)
{
/** @var Dispatcher $dispatcher */
$dispatcher = $bootstrap->getSignalSlotDispatcher();
+ // TODO 9.0 migration: Signal "beforeMove" doesn't exist anymore

+
$dispatcher->connect(
NodeLegacyStub::class,
'beforeMove',
SomeOtherClass::class,
'someMethod'
);
+ // TODO 9.0 migration: Signal "afterMove" doesn't exist anymore
+

$dispatcher->connect(
'Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub',
'afterMove',
SomeOtherClass::class,
'someMethod'
);

$dispatcher->connect(
NodeLegacyStub::class,
'otherMethod',
SomeOtherClass::class,
'someMethod'
);

$dispatcher->connect(
OtherClass::class,
'afterMove',
SomeOtherClass::class,
'someMethod'
);
}
}

?>
```

<br>

## ToStringToMethodCallOrPropertyFetchRector

Turns defined code uses of `"__toString()"` method to specific method calls or property fetches.
Expand Down
121 changes: 121 additions & 0 deletions src/ContentRepository90/Rules/NodeSearchServiceRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare (strict_types=1);

namespace Neos\Rector\ContentRepository90\Rules;

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 NodeSearchServiceRector extends AbstractRector
{
use AllTraits;

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

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('"NodeSearchService::findDescendantNodes()" 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\Neos\Domain\Service\NodeSearchService::class))) {
return null;
}
if (!$this->isName($node->name, 'findByProperties')) {
return null;
}

if (!isset($node->args[3])) {
$nodeExpr = self::assign('node', new \PhpParser\Node\Scalar\String_('we-need-a-node-here'));
$nodeNode = $nodeExpr->expr->var;

$this->nodesToAddCollector->addNodesBeforeNode(
[
self::withTodoComment('The replacement needs a node as starting point for the search. Please provide a node, to make this replacement working.', $nodeExpr),
$subgraphNode = self::assign('subgraph', $this->this_contentRepositoryRegistry_subgraphForNode($nodeNode)),
],
$node
);

} else {
$this->nodesToAddCollector->addNodesBeforeNode(
[
self::withTodoComment('This could be a suitable replacement. Please check if all your requirements are still fulfilled.',
$subgraphNode = self::assign('subgraph', $this->this_contentRepositoryRegistry_subgraphForNode($node->args[3]->value))
)
],
$node

);
$nodeNode = $node->args[3]->value;

}

return $this->nodeFactory->createMethodCall(
$subgraphNode->expr->var,
'findDescendantNodes',
[
$this->nodeFactory->createPropertyFetch(
$nodeNode,
'aggregateId'
),
$this->nodeFactory->createStaticCall(
\Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::class,
'create',
[
'nodeTypes' => $this->nodeFactory->createStaticCall(
\Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::class,
'create',
[
$this->nodeFactory->createStaticCall(
\Neos\ContentRepository\Core\NodeType\NodeTypeNames::class,
'fromStringArray',
[
$node->args[1]->value,
]
),
$this->nodeFactory->createStaticCall(
\Neos\ContentRepository\Core\NodeType\NodeTypeNames::class,
'createEmpty',
),
]
),
'searchTerm' => $node->args[0]->value,
]
)
]
);
}
}

/**
* \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::create(
* nodeTypes: \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::create(
* \Neos\ContentRepository\Core\NodeType\NodeTypeNames::fromStringArray($searchNodeTypes),
* \Neos\ContentRepository\Core\NodeType\NodeTypeNames::createEmpty()
* ),
* searchTerm: $term
* )
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Neos\Rector\Test;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\ContentRepository\Domain\Service\Context;

class SomeClass extends AnotherClass
{
/**
* @var \Neos\Neos\Domain\Service\NodeSearchService
*/
private $nodeSearchService;

public function startingPointNodeIsGiven(Node $node, Context $context)
{
$term = "term";
$searchNodeTypes = [];
$nodes = $this->nodeSearchService->findByProperties($term, $searchNodeTypes, $context, $node);
}

public function startingPointNodeIsNotGiven(Context $context)
{
$term = "term";
$searchNodeTypes = [];
$nodes = $this->nodeSearchService->findByProperties($term, $searchNodeTypes, $context);
}
}

-----
<?php

namespace Neos\Rector\Test;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\ContentRepository\Domain\Service\Context;

class SomeClass extends AnotherClass
{
/**
* @var \Neos\Neos\Domain\Service\NodeSearchService
*/
private $nodeSearchService;

public function startingPointNodeIsGiven(Node $node, Context $context)
{
$term = "term";
$searchNodeTypes = [];
// TODO 9.0 migration: This could be a suitable replacement. Please check if all your requirements are still fulfilled.
$subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);
$nodes = $subgraph->findDescendantNodes($node->aggregateId, \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::create(nodeTypes: \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::create(\Neos\ContentRepository\Core\NodeType\NodeTypeNames::fromStringArray($searchNodeTypes), \Neos\ContentRepository\Core\NodeType\NodeTypeNames::createEmpty()), searchTerm: $term));
}

public function startingPointNodeIsNotGiven(Context $context)
{
$term = "term";
$searchNodeTypes = [];
// TODO 9.0 migration: The replacement needs a node as starting point for the search. Please provide a node, to make this replacement working.
$node = 'we-need-a-node-here';
$subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);
$nodes = $subgraph->findDescendantNodes($node->aggregateId, \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindDescendantNodesFilter::create(nodeTypes: \Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria::create(\Neos\ContentRepository\Core\NodeType\NodeTypeNames::fromStringArray($searchNodeTypes), \Neos\ContentRepository\Core\NodeType\NodeTypeNames::createEmpty()), searchTerm: $term));
}
}

Loading
Loading