Skip to content

Commit

Permalink
Merge pull request #98 from neos/feature/signal-slot-warning
Browse files Browse the repository at this point in the history
FEATURE: Add warnings for removed signals
  • Loading branch information
mhsdesign authored Nov 28, 2024
2 parents 03f8f55 + da9f9c5 commit 549f6f8
Show file tree
Hide file tree
Showing 12 changed files with 684 additions and 1 deletion.
61 changes: 60 additions & 1 deletion config/set/contentrepository-90.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
use Neos\Rector\Generic\Rules\InjectServiceIfNeededRector;
use Neos\Rector\Generic\Rules\MethodCallToWarningCommentRector;
use Neos\Rector\Generic\Rules\RemoveInjectionsRector;
use Neos\Rector\Generic\Rules\SignalSlotToWarningCommentRector;
use Neos\Rector\Generic\Rules\ToStringToMethodCallOrPropertyFetchRector;
use Neos\Rector\Generic\ValueObject\AddInjection;
use Neos\Rector\Generic\ValueObject\FusionFlowQueryNodePropertyToWarningComment;
Expand All @@ -77,6 +78,7 @@
use Neos\Rector\Generic\ValueObject\MethodCallToWarningComment;
use Neos\Rector\Generic\ValueObject\RemoveInjection;
use Neos\Rector\Generic\ValueObject\RemoveParentClass;
use Neos\Rector\Generic\ValueObject\SignalSlotToWarningComment;
use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\Rector\Name\RenameClassRector;
Expand Down Expand Up @@ -419,6 +421,63 @@
*/
$rectorConfig->rule(WorkspaceGetNameRector::class);

/**
* Signals and Slots
* https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots
*/
$signalsAndSlotsToComment = [];
// Neos\ContentRepository\Domain\Service\PublishingService
// - nodePublished
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Service\PublishingService::class, 'nodePublished', 'The signal "nodePublished" on "PublishingService" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodeDiscarded
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Service\PublishingService::class, 'nodeDiscarded', 'The signal "nodeDiscarded" on "PublishingService" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// Neos\ContentRepository\Domain\Service\Context
// - beforeAdoptNode
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Service\Context::class, 'beforeAdoptNode', 'The signal "beforeAdoptNode" on "Context" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - afterAdoptNode
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Service\Context::class, 'afterAdoptNode', 'The signal "afterAdoptNode" on "Context" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// Neos\ContentRepository\Domain\Repository\NodeDataRepository
// - repositoryObjectsPersisted
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Repository\NodeDataRepository::class, 'repositoryObjectsPersisted', 'The signal "repositoryObjectsPersisted" on "NodeDataRepository" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// Neos\ContentRepository\Domain\Model\Workspace
// - baseWorkspaceChanged
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Workspace::class, 'baseWorkspaceChanged', 'The signal "baseWorkspaceChanged" on "Workspace" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - beforeNodePublishing
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Workspace::class, 'beforeNodePublishing', 'The signal "beforeNodePublishing" on "Workspace" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - afterNodePublishing
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Workspace::class, 'afterNodePublishing', 'The signal "afterNodePublishing" on "Workspace" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// Neos\ContentRepository\Domain\Model\NodeData
// - nodePathChanged
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\NodeData::class, 'nodePathChanged', 'The signal "nodePathChanged" on "NodeData" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// Neos\ContentRepository\Domain\Model\Node
// - beforeNodeMove
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'beforeNodeMove', 'The signal "beforeNodeMove" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - afterNodeMove
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'afterNodeMove', 'The signal "afterNodeMove" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - beforeNodeCopy
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'beforeNodeCopy', 'The signal "beforeNodeCopy" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - afterNodeCopy
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'afterNodeCopy', 'The signal "afterNodeCopy" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodePathChanged
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'nodePathChanged', 'The signal "nodePathChanged" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - beforeNodeCreate
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'beforeNodeCreate', 'The signal "beforeNodeCreate" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - afterNodeCreate
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'afterNodeCreate', 'The signal "afterNodeCreate" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodeAdded
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'nodeAdded', 'The signal "nodeAdded" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodeUpdated
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'nodeUpdated', 'The signal "nodeUpdated" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodeRemoved
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'nodeRemoved', 'The signal "nodeRemoved" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - beforeNodePropertyChange
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'beforeNodePropertyChange', 'The signal "beforeNodePropertyChange" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');
// - nodePropertyChanged
$signalsAndSlotsToComment[] = new SignalSlotToWarningComment(\Neos\ContentRepository\Domain\Model\Node::class, 'nodePropertyChanged', 'The signal "nodePropertyChanged" on "Node" has been removed. Please check https://docs.neos.io/api/upgrade-instructions/9/signals-and-slots for further information, how to replace a signal.');

$rectorConfig->ruleWithConfiguration(SignalSlotToWarningCommentRector::class, $signalsAndSlotsToComment);


/**
* Neos.Fusion:Attributes
*/
Expand Down Expand Up @@ -488,7 +547,7 @@

// We can only add one rule per class name. As workaround, we need to alias the RenameClassRector, so we are able to
// add this rule twice.
if (!class_exists(\Alias\RenameClassRectorLegacy::class)){
if (!class_exists(\Alias\RenameClassRectorLegacy::class)) {
class_alias(RenameClassRector::class, \Alias\RenameClassRectorLegacy::class);
}
$rectorConfig->ruleWithConfiguration(\Alias\RenameClassRectorLegacy::class, [
Expand Down
107 changes: 107 additions & 0 deletions src/Generic/Rules/SignalSlotToWarningCommentRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare (strict_types=1);

namespace Neos\Rector\Generic\Rules;

use Neos\Flow\SignalSlot\Dispatcher;
use Neos\Rector\Generic\ValueObject\MethodCallToWarningComment;
use Neos\Rector\Generic\ValueObject\SignalSlotToWarningComment;
use Neos\Rector\Utility\CodeSampleLoader;
use PhpParser\Node;
use PHPStan\Type\ObjectType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\PostRector\Collector\NodesToAddCollector;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;
use Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub;

final class SignalSlotToWarningCommentRector extends AbstractRector implements ConfigurableRectorInterface
{
use AllTraits;

/**
* @var SignalSlotToWarningComment[]
*/
private array $signalSlotToWarningComments = [];

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

public function getRuleDefinition(): RuleDefinition
{
return CodeSampleLoader::fromFile('"Warning comments for various non-supported signals', __CLASS__, [
new SignalSlotToWarningComment(Node::class, 'beforeMove', '!! This signal "beforeMove" on Node doesn\'t exist anymore')
]);
}

/**
* @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->isName($node->name, 'connect')) {
return null;
}

if (!$this->isObjectType($node->var, new ObjectType(Dispatcher::class))) {
return null;
}

foreach ($this->signalSlotToWarningComments as $signalSlotToWarningComment) {
$className = null;
if ($node->args[0]->value instanceof Node\Expr\ClassConstFetch) {
$className = (string) $node->args[0]->value->class;
} elseif ($node->args[0]->value instanceof Node\Scalar) {
$className = (string)$node->args[0]->value->value;
}

if ($className !== $signalSlotToWarningComment->className){
continue;
}

$methodName = null;
if ($node->args[1]->value instanceof Node\Scalar\String_) {
$methodName = (string)$node->args[1]->value->value;
}

if ($methodName !== $signalSlotToWarningComment->signalName) {
continue;
}

$this->nodesToAddCollector->addNodesBeforeNode(
[
self::todoComment($signalSlotToWarningComment->warningMessage)
],
$node
);

return $node;
}
return null;
}


/**
* @param mixed[] $configuration
*/
public function configure(array $configuration) : void
{
Assert::allIsAOf($configuration, SignalSlotToWarningComment::class);
$this->signalSlotToWarningComments = $configuration;
}
}
15 changes: 15 additions & 0 deletions src/Generic/ValueObject/SignalSlotToWarningComment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace Neos\Rector\Generic\ValueObject;

class SignalSlotToWarningComment
{
public function __construct(
public readonly string $className,
public readonly string $signalName,
public readonly string $warningMessage,
)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?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();

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

$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'
);
}
}

?>
-----
<?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'
);
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Neos\Rector\Tests\Generic\Rules\ToStringToPropertyFetchRector;

use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class SignalSlotToWarningCommentRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $fileInfo): void
{
$this->doTestFile($fileInfo);
}

/**
* @return \Iterator<string>
*/
public function provideData(): \Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?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 {
$rectorConfig->ruleWithConfiguration(SignalSlotToWarningCommentRector::class, [
new SignalSlotToWarningComment(Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub::class, 'beforeMove', 'Signal "beforeMove" doesn\'t exist anymore'),
new SignalSlotToWarningComment(Neos\Rector\ContentRepository90\Legacy\NodeLegacyStub::class, 'afterMove', 'Signal "afterMove" doesn\'t exist anymore'),
]);
};
Loading

0 comments on commit 549f6f8

Please sign in to comment.