<?php declare(strict_types=1); namespace FriendsOfTYPO3\Rector\TYPO3\Rector\Extbase; use Rector\Core\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use PhpParser\Node\Param; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PHPStan\Type\ObjectType; use Rector\Core\NodeManipulator\ClassDependencyManipulator; use Rector\PostRector\ValueObject\PropertyMetadata; final class InjectMethodToConstructorInjectionRector extends AbstractRector { private $classDependencyManipulator; public function __construct(ClassDependencyManipulator $classDependencyManipulator) { $this->classDependencyManipulator = $classDependencyManipulator; } public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( '', [ new CodeSample(<<<'CODE_SAMPLE' namespace App\Service; use \TYPO3\CMS\Core\Cache\CacheManager; class Service { private CacheManager $cacheManager; public function injectCacheManager(CacheManager $cacheManager): void { $this->cacheManager = $cacheManager; } } CODE_SAMPLE, <<<'CODE_SAMPLE' namespace App\Service; use \TYPO3\CMS\Core\Cache\CacheManager; class Service { private CacheManager $cacheManager; public function __construct(CacheManager $cacheManager) { $this->cacheManager = $cacheManager; } } CODE_SAMPLE ) ] ); } /** * List of nodes this class checks, classes that implements \PhpParser\Node * See beautiful map of all nodes https://github.com/rectorphp/rector/blob/master/docs/NodesOverview.md * * @return class-string[] */ public function getNodeTypes(): array { return [Class_::class]; } /** * Process Node of matched type */ public function refactor(Node $node): ?Node { /** @var Class_ $node */ if ($this->shouldSkip($node)) { return null; } $injectMethods = array_filter($node->getMethods(), function ($classMethod) { return strncmp((string)$classMethod->name, 'inject', 6) === 0; }); if ($injectMethods === []) { return null; } foreach ($injectMethods as $injectMethod) { $params = $injectMethod->getParams(); if (empty($params)) { continue; } reset($params); /** @var Param $param */ $param = current($params); if (!$param->type instanceof FullyQualified) { continue; } $this->classDependencyManipulator->addConstructorDependency( $node, new PropertyMetadata( (string)$param->var->name, new ObjectType((string)$param->type), Class_::MODIFIER_PROTECTED ) ); $this->removeNodeFromStatements($node, $injectMethod); } return $node; } private function shouldSkip(Class_ $class): bool { return $class->getMethods() === []; } }