rector/src/Rector/Dynamic/PropertyToMethodRector.php

120 lines
3.0 KiB
PHP
Raw Normal View History

2017-11-18 15:20:10 +00:00
<?php declare(strict_types=1);
namespace Rector\Rector\Dynamic;
use PhpParser\Node;
2017-11-18 15:48:20 +00:00
use PhpParser\Node\Expr\Assign;
2017-11-18 15:20:10 +00:00
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
2017-12-10 00:13:25 +00:00
use PhpParser\Node\Identifier;
use Rector\Node\NodeFactory;
2017-11-18 15:20:10 +00:00
use Rector\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Rector\AbstractRector;
2017-11-18 15:48:20 +00:00
/**
* Example - from:
* - $result = $object->property;
* - $object->property = $value;
*
* To
* - $result = $object->getProperty();
* - $object->setProperty($value);
*/
2017-11-18 15:20:10 +00:00
final class PropertyToMethodRector extends AbstractRector
{
/**
* class => [
* property => [getMethod, setMethod]
* ]
*
* @var string[][][]
*/
private $perClassPropertyToMethods = [];
/**
2017-11-18 15:48:20 +00:00
* @var string
2017-11-18 15:20:10 +00:00
*/
2017-11-18 15:48:20 +00:00
private $activeMethod;
2017-11-18 15:20:10 +00:00
/**
* @var PropertyFetchAnalyzer
*/
private $propertyFetchAnalyzer;
/**
* @var NodeFactory
*/
private $nodeFactory;
2017-11-18 15:20:10 +00:00
/**
2017-12-09 20:58:33 +00:00
* @param string[][][] $perClassOldToNewProperties
2017-11-18 15:20:10 +00:00
*/
public function __construct(
array $perClassOldToNewProperties,
PropertyFetchAnalyzer $propertyFetchAnalyzer,
NodeFactory $nodeFactory
) {
2017-11-18 15:20:10 +00:00
$this->perClassPropertyToMethods = $perClassOldToNewProperties;
$this->propertyFetchAnalyzer = $propertyFetchAnalyzer;
$this->nodeFactory = $nodeFactory;
2017-11-18 15:20:10 +00:00
}
public function isCandidate(Node $node): bool
{
2017-11-18 15:48:20 +00:00
if (! $node instanceof Assign) {
2017-11-18 15:20:10 +00:00
return false;
}
2017-11-18 15:48:20 +00:00
// setter
if ($node->var instanceof PropertyFetch) {
return $this->processPropertyFetchCandidate($node->var, 'set');
}
2017-11-18 15:20:10 +00:00
2017-11-18 15:48:20 +00:00
// getter
if ($node->expr instanceof PropertyFetch) {
return $this->processPropertyFetchCandidate($node->expr, 'get');
2017-11-18 15:20:10 +00:00
}
return false;
}
/**
2017-11-18 15:48:20 +00:00
* @param Assign $assignNode
2017-11-18 15:20:10 +00:00
*/
2017-11-18 15:48:20 +00:00
public function refactor(Node $assignNode): ?Node
2017-11-18 15:20:10 +00:00
{
2017-11-18 15:48:20 +00:00
// setter
if ($assignNode->var instanceof PropertyFetch) {
$args = $this->nodeFactory->createArgs([
$assignNode->expr,
]);
2017-11-18 15:48:20 +00:00
return new MethodCall($assignNode->var->var, $this->activeMethod, $args);
}
// getter
if ($assignNode->expr instanceof PropertyFetch) {
$assignNode->expr = new MethodCall($assignNode->expr->var, $this->activeMethod);
}
return null;
}
private function processPropertyFetchCandidate(PropertyFetch $propertyFetchNode, string $type): bool
{
foreach ($this->perClassPropertyToMethods as $class => $propertyToMethods) {
$properties = array_keys($propertyToMethods);
if ($this->propertyFetchAnalyzer->isTypeAndProperties($propertyFetchNode, $class, $properties)) {
2017-12-10 00:13:25 +00:00
/** @var Identifier $identifierNode */
$identifierNode = $propertyFetchNode->name;
$this->activeMethod = $propertyToMethods[$identifierNode->toString()][$type];
2017-11-18 15:48:20 +00:00
return true;
}
}
return false;
2017-11-18 15:20:10 +00:00
}
}