2019-10-13 05:59:52 +00:00
< ? php
2021-05-09 20:15:43 +00:00
declare ( strict_types = 1 );
2022-06-06 17:12:56 +00:00
namespace Rector\Renaming\Rector\PropertyFetch ;
2017-10-21 22:04:15 +00:00
2022-06-06 17:12:56 +00:00
use PhpParser\Node ;
use PhpParser\Node\Expr\PropertyFetch ;
use PhpParser\Node\Identifier ;
use PhpParser\Node\Stmt\ClassLike ;
use PhpParser\Node\Stmt\Property ;
use PhpParser\Node\VarLikeIdentifier ;
use PHPStan\Type\ObjectType ;
2024-01-02 02:40:38 +00:00
use Rector\Contract\Rector\ConfigurableRectorInterface ;
use Rector\Rector\AbstractRector ;
2022-06-06 17:12:56 +00:00
use Rector\Renaming\ValueObject\RenameProperty ;
2022-06-07 09:18:30 +00:00
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample ;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition ;
2024-04-01 16:51:34 +00:00
use RectorPrefix202404\Webmozart\Assert\Assert ;
2019-09-03 09:11:45 +00:00
/**
2021-03-12 22:20:25 +00:00
* @ see \Rector\Tests\Renaming\Rector\PropertyFetch\RenamePropertyRector\RenamePropertyRectorTest
2019-09-03 09:11:45 +00:00
*/
2022-06-07 08:22:29 +00:00
final class RenamePropertyRector extends AbstractRector implements ConfigurableRectorInterface
2017-10-21 22:04:15 +00:00
{
/**
2020-09-12 21:19:08 +00:00
* @ var RenameProperty []
2017-10-21 22:04:15 +00:00
*/
2020-08-26 10:54:53 +00:00
private $renamedProperties = [];
2022-11-24 14:31:52 +00:00
/**
* @ var bool
*/
private $hasChanged = \false ;
2022-06-07 08:22:29 +00:00
public function getRuleDefinition () : RuleDefinition
2018-04-08 11:51:26 +00:00
{
2022-06-07 08:22:29 +00:00
return new RuleDefinition ( 'Replaces defined old properties by new ones.' , [ new ConfiguredCodeSample ( '$someObject->someOldProperty;' , '$someObject->someNewProperty;' , [ new RenameProperty ( 'SomeClass' , 'someOldProperty' , 'someNewProperty' )])]);
2018-04-08 11:51:26 +00:00
}
2018-08-14 22:12:41 +00:00
/**
2021-02-27 00:06:15 +00:00
* @ return array < class - string < Node >>
2018-08-14 22:12:41 +00:00
*/
2021-05-09 20:15:43 +00:00
public function getNodeTypes () : array
2017-10-21 22:04:15 +00:00
{
2022-06-07 08:22:29 +00:00
return [ PropertyFetch :: class , ClassLike :: class ];
2017-10-21 22:04:15 +00:00
}
/**
2021-12-10 10:22:23 +00:00
* @ param PropertyFetch | ClassLike $node
2017-10-21 22:04:15 +00:00
*/
2022-06-07 08:22:29 +00:00
public function refactor ( Node $node ) : ? Node
2017-10-21 22:04:15 +00:00
{
2022-06-07 08:22:29 +00:00
if ( $node instanceof ClassLike ) {
2023-07-09 11:49:50 +00:00
$this -> hasChanged = \false ;
2022-11-24 14:31:52 +00:00
foreach ( $this -> renamedProperties as $renamedProperty ) {
$this -> renameProperty ( $node , $renamedProperty );
}
if ( $this -> hasChanged ) {
return $node ;
}
return null ;
2017-10-25 16:04:34 +00:00
}
2023-06-10 13:02:37 +00:00
return $this -> refactorPropertyFetch ( $node );
2017-10-21 22:04:15 +00:00
}
2021-05-02 10:46:55 +00:00
/**
2021-11-28 17:01:20 +00:00
* @ param mixed [] $configuration
2021-05-02 10:46:55 +00:00
*/
2021-12-10 10:22:23 +00:00
public function configure ( array $configuration ) : void
2020-07-29 23:39:41 +00:00
{
2022-06-07 08:22:29 +00:00
Assert :: allIsAOf ( $configuration , RenameProperty :: class );
2022-02-18 01:46:17 +00:00
$this -> renamedProperties = $configuration ;
2020-07-29 23:39:41 +00:00
}
2022-06-07 08:22:29 +00:00
private function renameProperty ( ClassLike $classLike , RenameProperty $renameProperty ) : void
2021-09-04 07:43:00 +00:00
{
2021-11-09 13:36:07 +00:00
$classLikeName = ( string ) $this -> nodeNameResolver -> getName ( $classLike );
2021-09-05 03:12:49 +00:00
$renamePropertyObjectType = $renameProperty -> getObjectType ();
$className = $renamePropertyObjectType -> getClassName ();
2022-06-07 08:22:29 +00:00
$classLikeNameObjectType = new ObjectType ( $classLikeName );
$classNameObjectType = new ObjectType ( $className );
2021-10-20 17:23:41 +00:00
$isSuperType = $classNameObjectType -> isSuperTypeOf ( $classLikeNameObjectType ) -> yes ();
if ( $classLikeName !== $className && ! $isSuperType ) {
2021-09-05 03:12:49 +00:00
return ;
}
2021-09-04 07:43:00 +00:00
$property = $classLike -> getProperty ( $renameProperty -> getOldProperty ());
2022-06-07 08:22:29 +00:00
if ( ! $property instanceof Property ) {
2021-09-04 07:43:00 +00:00
return ;
}
2021-09-05 03:12:49 +00:00
$newProperty = $renameProperty -> getNewProperty ();
$targetNewProperty = $classLike -> getProperty ( $newProperty );
2022-06-07 08:22:29 +00:00
if ( $targetNewProperty instanceof Property ) {
2021-09-05 03:12:49 +00:00
return ;
}
2022-11-24 14:31:52 +00:00
$this -> hasChanged = \true ;
2022-06-07 08:22:29 +00:00
$property -> props [ 0 ] -> name = new VarLikeIdentifier ( $newProperty );
2021-09-04 07:43:00 +00:00
}
2023-06-10 13:02:37 +00:00
private function refactorPropertyFetch ( PropertyFetch $propertyFetch ) : ? PropertyFetch
2021-09-04 07:43:00 +00:00
{
foreach ( $this -> renamedProperties as $renamedProperty ) {
$oldProperty = $renamedProperty -> getOldProperty ();
if ( ! $this -> isName ( $propertyFetch , $oldProperty )) {
continue ;
}
2023-03-22 14:20:22 +00:00
if ( ! $this -> isObjectType ( $propertyFetch -> var , $renamedProperty -> getObjectType ())) {
continue ;
}
2022-06-07 08:22:29 +00:00
$propertyFetch -> name = new Identifier ( $renamedProperty -> getNewProperty ());
2021-09-04 07:43:00 +00:00
return $propertyFetch ;
}
return null ;
}
2017-10-21 22:04:15 +00:00
}