mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-31 08:20:53 +00:00
[IDE-refactoring cleanup] Remove rather custom PassFactoryToEntityRector and NewUniqueObjectToEntityFactoryRector rules, better use PHPStorm there (#783)
* Remove rather custom PassFactoryToEntityRector and NewUniqueObjectToEntityFactoryRector rules, better use PHPStorm there * cleanup * Remove StaticTypeToSetterInjectionRector, use PHPStorm for these refactorings
This commit is contained in:
parent
130b634b5e
commit
541e40b48f
|
@ -1,4 +1,4 @@
|
|||
# 477 Rules Overview
|
||||
# 474 Rules Overview
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
|||
|
||||
- [Removing](#removing) (6)
|
||||
|
||||
- [RemovingStatic](#removingstatic) (8)
|
||||
- [RemovingStatic](#removingstatic) (5)
|
||||
|
||||
- [Renaming](#renaming) (11)
|
||||
|
||||
|
@ -132,31 +132,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
$someObject = new SomeExampleClass;
|
||||
-$someObject->someMethod();
|
||||
+$someObject->someMethod(true);
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
```php
|
||||
use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector;
|
||||
use Rector\Arguments\ValueObject\ArgumentAdder;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\SymfonyPhpConfig\ValueObjectInliner;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(ArgumentAdderRector::class)
|
||||
->call('configure', [[
|
||||
ArgumentAdderRector::ADDED_ARGUMENTS => ValueObjectInliner::inline([
|
||||
new ArgumentAdder('SomeExampleClass', 'someMethod', 0, 'someArgument', true, 'SomeType', null),
|
||||
]),
|
||||
]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
class MyCustomClass extends SomeExampleClass
|
||||
{
|
||||
- public function someMethod()
|
||||
|
@ -9107,177 +9083,6 @@ Change static method and local-only calls to non-static
|
|||
|
||||
<br>
|
||||
|
||||
### NewUniqueObjectToEntityFactoryRector
|
||||
|
||||
Convert new X to new factories
|
||||
|
||||
:wrench: **configure it!**
|
||||
|
||||
- class: [`Rector\RemovingStatic\Rector\Class_\NewUniqueObjectToEntityFactoryRector`](../rules/RemovingStatic/Rector/Class_/NewUniqueObjectToEntityFactoryRector.php)
|
||||
|
||||
```php
|
||||
use Rector\RemovingStatic\Rector\Class_\NewUniqueObjectToEntityFactoryRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(NewUniqueObjectToEntityFactoryRector::class)
|
||||
->call('configure', [[
|
||||
NewUniqueObjectToEntityFactoryRector::TYPES_TO_SERVICES => ['ClassName'],
|
||||
]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
+ public function __construct(AnotherClassFactory $anotherClassFactory)
|
||||
+ {
|
||||
+ $this->anotherClassFactory = $anotherClassFactory;
|
||||
+ }
|
||||
+
|
||||
public function run()
|
||||
{
|
||||
- return new AnotherClass;
|
||||
+ return $this->anotherClassFactory->create();
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
public function someFun()
|
||||
{
|
||||
return StaticClass::staticMethod();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### PassFactoryToUniqueObjectRector
|
||||
|
||||
Convert new `X/Static::call()` to factories in entities, pass them via constructor to each other
|
||||
|
||||
:wrench: **configure it!**
|
||||
|
||||
- class: [`Rector\RemovingStatic\Rector\Class_\PassFactoryToUniqueObjectRector`](../rules/RemovingStatic/Rector/Class_/PassFactoryToUniqueObjectRector.php)
|
||||
|
||||
```php
|
||||
use Rector\RemovingStatic\Rector\Class_\PassFactoryToUniqueObjectRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(PassFactoryToUniqueObjectRector::class)
|
||||
->call('configure', [[
|
||||
PassFactoryToUniqueObjectRector::TYPES_TO_SERVICES => ['StaticClass'],
|
||||
]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
+ public function __construct(AnotherClassFactory $anotherClassFactory)
|
||||
+ {
|
||||
+ $this->anotherClassFactory = $anotherClassFactory;
|
||||
+ }
|
||||
+
|
||||
public function run()
|
||||
{
|
||||
- return new AnotherClass;
|
||||
+ return $this->anotherClassFactory->create();
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
+ public function __construct(StaticClass $staticClass)
|
||||
+ {
|
||||
+ $this->staticClass = $staticClass;
|
||||
+ }
|
||||
+
|
||||
public function someFun()
|
||||
{
|
||||
- return StaticClass::staticMethod();
|
||||
+ return $this->staticClass->staticMethod();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+final class AnotherClassFactory
|
||||
+{
|
||||
+ /**
|
||||
+ * @var StaticClass
|
||||
+ */
|
||||
+ private $staticClass;
|
||||
+
|
||||
+ public function __construct(StaticClass $staticClass)
|
||||
+ {
|
||||
+ $this->staticClass = $staticClass;
|
||||
+ }
|
||||
+
|
||||
+ public function create(): AnotherClass
|
||||
+ {
|
||||
+ return new AnotherClass($this->staticClass);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### StaticTypeToSetterInjectionRector
|
||||
|
||||
Changes types to setter injection
|
||||
|
||||
:wrench: **configure it!**
|
||||
|
||||
- class: [`Rector\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector`](../rules/RemovingStatic/Rector/Class_/StaticTypeToSetterInjectionRector.php)
|
||||
|
||||
```php
|
||||
use Rector\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(StaticTypeToSetterInjectionRector::class)
|
||||
->call('configure', [[
|
||||
StaticTypeToSetterInjectionRector::STATIC_TYPES => ['SomeStaticClass'],
|
||||
]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
final class CheckoutEntityFactory
|
||||
{
|
||||
+ /**
|
||||
+ * @var SomeStaticClass
|
||||
+ */
|
||||
+ private $someStaticClass;
|
||||
+
|
||||
+ public function setSomeStaticClass(SomeStaticClass $someStaticClass)
|
||||
+ {
|
||||
+ $this->someStaticClass = $someStaticClass;
|
||||
+ }
|
||||
+
|
||||
public function run()
|
||||
{
|
||||
- return SomeStaticClass::go();
|
||||
+ return $this->someStaticClass->go();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Renaming
|
||||
|
||||
### PseudoNamespaceToNamespaceRector
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService;
|
||||
|
||||
class SomeClassWithMoreArguments
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return new AnotherClassWithMoreArguments(10);
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClassWithMoreArguments
|
||||
{
|
||||
private $number;
|
||||
|
||||
public function __construct($number)
|
||||
{
|
||||
$this->number = $number;
|
||||
}
|
||||
|
||||
public function someFun()
|
||||
{
|
||||
return TurnMeToService::someStaticCall(5, $this->number);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService;
|
||||
|
||||
class SomeClassWithMoreArguments
|
||||
{
|
||||
public function __construct(private \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClassWithMoreArgumentsFactory $anotherClassWithMoreArgumentsFactory)
|
||||
{
|
||||
}
|
||||
public function run()
|
||||
{
|
||||
return $this->anotherClassWithMoreArgumentsFactory->create(10);
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClassWithMoreArguments
|
||||
{
|
||||
private $number;
|
||||
|
||||
public function __construct($number, private \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService $turnMeToService)
|
||||
{
|
||||
$this->number = $number;
|
||||
}
|
||||
|
||||
public function someFun()
|
||||
{
|
||||
return $this->turnMeToService->someStaticCall(5, $this->number);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\EasyTesting\StaticFixtureSplitter;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class PassFactoryToEntityRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
|
||||
$expectedFactoryFilePath = StaticFixtureSplitter::getTemporaryPath() . '/AnotherClassWithMoreArgumentsFactory.php';
|
||||
|
||||
$this->assertFileExists($expectedFactoryFilePath);
|
||||
$this->assertFileEquals(
|
||||
__DIR__ . '/Source/ExpectedAnotherClassWithMoreArgumentsFactory.php',
|
||||
$expectedFactoryFilePath
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureWithMultipleArguments');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture;
|
||||
|
||||
final class AnotherClassFactory
|
||||
{
|
||||
/**
|
||||
* @var \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService
|
||||
*/
|
||||
private $turnMeToService;
|
||||
public function __construct(\Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService $turnMeToService)
|
||||
{
|
||||
$this->turnMeToService = $turnMeToService;
|
||||
}
|
||||
public function create(): \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClass
|
||||
{
|
||||
return new \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClass($this->turnMeToService);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture;
|
||||
|
||||
final class AnotherClassWithMoreArgumentsFactory
|
||||
{
|
||||
/**
|
||||
* @var \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService
|
||||
*/
|
||||
private $turnMeToService;
|
||||
public function __construct(\Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService $turnMeToService)
|
||||
{
|
||||
$this->turnMeToService = $turnMeToService;
|
||||
}
|
||||
public function create($number): \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClassWithMoreArguments
|
||||
{
|
||||
return new \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClassWithMoreArguments($number, $this->turnMeToService);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source;
|
||||
|
||||
final class TurnMeToService
|
||||
{
|
||||
public static function someStaticCall()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\RemovingStatic\Rector\Class_\NewUniqueObjectToEntityFactoryRector;
|
||||
use Rector\RemovingStatic\Rector\Class_\PassFactoryToUniqueObjectRector;
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Fixture\AnotherClassWithMoreArguments;
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$typesToServices = [TurnMeToService::class, AnotherClassWithMoreArguments::class];
|
||||
|
||||
$services->set(PassFactoryToUniqueObjectRector::class)
|
||||
->call('configure', [[
|
||||
PassFactoryToUniqueObjectRector::TYPES_TO_SERVICES => $typesToServices,
|
||||
]]);
|
||||
|
||||
$services->set(NewUniqueObjectToEntityFactoryRector::class)
|
||||
->call('configure', [[
|
||||
NewUniqueObjectToEntityFactoryRector::TYPES_TO_SERVICES => $typesToServices,
|
||||
]]);
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactory;
|
||||
|
||||
final class CheckoutEntityFactory
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return GenericEntityFactory::make();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactory;
|
||||
|
||||
final class CheckoutEntityFactory
|
||||
{
|
||||
/**
|
||||
* @var \Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactory
|
||||
*/
|
||||
private $genericEntityFactory;
|
||||
public function setGenericEntityFactory(\Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactory $genericEntityFactory): void
|
||||
{
|
||||
$this->genericEntityFactory = $genericEntityFactory;
|
||||
}
|
||||
public function run()
|
||||
{
|
||||
return $this->genericEntityFactory->make();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactoryWithInterface;
|
||||
|
||||
final class TheSameButWithImplements
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return GenericEntityFactoryWithInterface::make();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Fixture;
|
||||
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactoryWithInterface;
|
||||
|
||||
final class TheSameButWithImplements implements \ParentSetterEnforcingInterface
|
||||
{
|
||||
/**
|
||||
* @var \Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactoryWithInterface
|
||||
*/
|
||||
private $genericEntityFactoryWith;
|
||||
public function setGenericEntityFactoryWith(\Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactoryWithInterface $genericEntityFactoryWith): void
|
||||
{
|
||||
$this->genericEntityFactoryWith = $genericEntityFactoryWith;
|
||||
}
|
||||
public function run()
|
||||
{
|
||||
return $this->genericEntityFactoryWith->make();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source;
|
||||
|
||||
use phpDocumentor\Reflection\Types\Integer;
|
||||
|
||||
final class GenericEntityFactory
|
||||
{
|
||||
public static function make(): Integer
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source;
|
||||
|
||||
use phpDocumentor\Reflection\Types\Integer;
|
||||
|
||||
final class GenericEntityFactoryWithInterface
|
||||
{
|
||||
public static function make(): Integer
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class StaticTypeToSetterInjectionRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector;
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactory;
|
||||
use Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\Source\GenericEntityFactoryWithInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(StaticTypeToSetterInjectionRector::class)
|
||||
->call('configure', [[
|
||||
StaticTypeToSetterInjectionRector::STATIC_TYPES => [
|
||||
GenericEntityFactory::class,
|
||||
// with adding a parent interface to the class
|
||||
'ParentSetterEnforcingInterface' => GenericEntityFactoryWithInterface::class,
|
||||
],
|
||||
]]);
|
||||
};
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\Printer;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
|
||||
use Rector\Core\Provider\CurrentFileProvider;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\SmartFileSystem\SmartFileSystem;
|
||||
|
||||
final class FactoryClassPrinter
|
||||
{
|
||||
public function __construct(
|
||||
private BetterStandardPrinter $betterStandardPrinter,
|
||||
private SmartFileSystem $smartFileSystem,
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private CurrentFileProvider $currentFileProvider
|
||||
) {
|
||||
}
|
||||
|
||||
public function printFactoryForClass(Class_ $factoryClass, Class_ $oldClass): void
|
||||
{
|
||||
$parentNode = $oldClass->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentNode instanceof Namespace_) {
|
||||
$newNamespace = clone $parentNode;
|
||||
$newNamespace->stmts = [];
|
||||
$newNamespace->stmts[] = $factoryClass;
|
||||
$nodeToPrint = $newNamespace;
|
||||
} else {
|
||||
$nodeToPrint = $factoryClass;
|
||||
}
|
||||
|
||||
$factoryClassFilePath = $this->createFactoryClassFilePath($oldClass);
|
||||
$factoryClassContent = $this->betterStandardPrinter->prettyPrintFile([$nodeToPrint]);
|
||||
|
||||
$this->smartFileSystem->dumpFile($factoryClassFilePath, $factoryClassContent);
|
||||
}
|
||||
|
||||
private function createFactoryClassFilePath(Class_ $oldClass): string
|
||||
{
|
||||
$file = $this->currentFileProvider->getFile();
|
||||
|
||||
$smartFileInfo = $file->getSmartFileInfo();
|
||||
|
||||
$directoryPath = Strings::before($smartFileInfo->getRealPath(), DIRECTORY_SEPARATOR, -1);
|
||||
$resolvedOldClass = $this->nodeNameResolver->getName($oldClass);
|
||||
if ($resolvedOldClass === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$bareClassName = Strings::after($resolvedOldClass, '\\', -1) . 'Factory.php';
|
||||
|
||||
return $directoryPath . DIRECTORY_SEPARATOR . $bareClassName;
|
||||
}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\PostRector\Collector\PropertyToAddCollector;
|
||||
use Rector\PostRector\ValueObject\PropertyMetadata;
|
||||
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* Depends on @see PassFactoryToUniqueObjectRector
|
||||
*
|
||||
* @see \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\PassFactoryToEntityRectorTest
|
||||
*/
|
||||
final class NewUniqueObjectToEntityFactoryRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const TYPES_TO_SERVICES = 'types_to_services';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const FACTORY = 'Factory';
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $matchedObjectTypes = [];
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $serviceObjectTypes = [];
|
||||
|
||||
public function __construct(
|
||||
private PropertyNaming $propertyNaming,
|
||||
private PropertyToAddCollector $propertyToAddCollector
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Convert new X to new factories', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return new AnotherClass;
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
public function someFun()
|
||||
{
|
||||
return StaticClass::staticMethod();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function __construct(AnotherClassFactory $anotherClassFactory)
|
||||
{
|
||||
$this->anotherClassFactory = $anotherClassFactory;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this->anotherClassFactory->create();
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
public function someFun()
|
||||
{
|
||||
return StaticClass::staticMethod();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::TYPES_TO_SERVICES => ['ClassName'],
|
||||
]
|
||||
), ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): Class_
|
||||
{
|
||||
$this->matchedObjectTypes = [];
|
||||
|
||||
// collect classes with new to factory in all classes
|
||||
|
||||
$this->traverseNodesWithCallable($node->stmts, function (Node $node): ?MethodCall {
|
||||
if (! $node instanceof New_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = $this->getName($node->class);
|
||||
if ($class === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isClassMatching($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$objectType = new FullyQualifiedObjectType($class);
|
||||
$this->matchedObjectTypes[] = $objectType;
|
||||
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType) . self::FACTORY;
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
|
||||
return new MethodCall($propertyFetch, 'create', $node->args);
|
||||
});
|
||||
|
||||
foreach ($this->matchedObjectTypes as $matchedObjectType) {
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($matchedObjectType) . self::FACTORY;
|
||||
$propertyType = new FullyQualifiedObjectType($matchedObjectType->getClassName() . self::FACTORY);
|
||||
|
||||
$propertyMetadata = new PropertyMetadata($propertyName, $propertyType, Class_::MODIFIER_PRIVATE);
|
||||
$this->propertyToAddCollector->addPropertyToClass($node, $propertyMetadata);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed[]> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$typesToServices = $configuration[self::TYPES_TO_SERVICES] ?? [];
|
||||
foreach ($typesToServices as $typeToService) {
|
||||
$this->serviceObjectTypes[] = new ObjectType($typeToService);
|
||||
}
|
||||
}
|
||||
|
||||
private function isClassMatching(string $class): bool
|
||||
{
|
||||
foreach ($this->serviceObjectTypes as $serviceObjectType) {
|
||||
if ($serviceObjectType->isInstanceOf($class)->yes()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\PostRector\Collector\PropertyToAddCollector;
|
||||
use Rector\PostRector\ValueObject\PropertyMetadata;
|
||||
use Rector\RemovingStatic\Printer\FactoryClassPrinter;
|
||||
use Rector\RemovingStatic\StaticTypesInClassResolver;
|
||||
use Rector\RemovingStatic\UniqueObjectFactoryFactory;
|
||||
use Rector\RemovingStatic\UniqueObjectOrServiceDetector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\RemovingStatic\Rector\Class_\PassFactoryToEntityRector\PassFactoryToEntityRectorTest
|
||||
*/
|
||||
final class PassFactoryToUniqueObjectRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const TYPES_TO_SERVICES = 'types_to_services';
|
||||
|
||||
/**
|
||||
* @var ObjectType[]
|
||||
*/
|
||||
private array $serviceObjectTypes = [];
|
||||
|
||||
public function __construct(
|
||||
private StaticTypesInClassResolver $staticTypesInClassResolver,
|
||||
private PropertyNaming $propertyNaming,
|
||||
private UniqueObjectOrServiceDetector $uniqueObjectOrServiceDetector,
|
||||
private UniqueObjectFactoryFactory $uniqueObjectFactoryFactory,
|
||||
private FactoryClassPrinter $factoryClassPrinter,
|
||||
private PropertyToAddCollector $propertyToAddCollector
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Convert new X/Static::call() to factories in entities, pass them via constructor to each other',
|
||||
[
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return new AnotherClass;
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
public function someFun()
|
||||
{
|
||||
return StaticClass::staticMethod();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function __construct(AnotherClassFactory $anotherClassFactory)
|
||||
{
|
||||
$this->anotherClassFactory = $anotherClassFactory;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this->anotherClassFactory->create();
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
public function __construct(StaticClass $staticClass)
|
||||
{
|
||||
$this->staticClass = $staticClass;
|
||||
}
|
||||
|
||||
public function someFun()
|
||||
{
|
||||
return $this->staticClass->staticMethod();
|
||||
}
|
||||
}
|
||||
|
||||
final class AnotherClassFactory
|
||||
{
|
||||
/**
|
||||
* @var StaticClass
|
||||
*/
|
||||
private $staticClass;
|
||||
|
||||
public function __construct(StaticClass $staticClass)
|
||||
{
|
||||
$this->staticClass = $staticClass;
|
||||
}
|
||||
|
||||
public function create(): AnotherClass
|
||||
{
|
||||
return new AnotherClass($this->staticClass);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::TYPES_TO_SERVICES => ['StaticClass'],
|
||||
]
|
||||
), ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class, StaticCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StaticCall|Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Class_) {
|
||||
return $this->refactorClass($node);
|
||||
}
|
||||
|
||||
foreach ($this->serviceObjectTypes as $serviceObjectType) {
|
||||
if (! $this->isObjectType($node->class, $serviceObjectType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// is this object created via new somewhere else? use factory!
|
||||
$variableName = $this->propertyNaming->fqnToVariableName($serviceObjectType);
|
||||
$thisPropertyFetch = new PropertyFetch(new Variable('this'), $variableName);
|
||||
|
||||
return new MethodCall($thisPropertyFetch, $node->name, $node->args);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed[]> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$typesToServices = $configuration[self::TYPES_TO_SERVICES] ?? [];
|
||||
foreach ($typesToServices as $typeToService) {
|
||||
$this->serviceObjectTypes[] = new ObjectType($typeToService);
|
||||
}
|
||||
}
|
||||
|
||||
private function refactorClass(Class_ $class): Class_
|
||||
{
|
||||
$staticTypesInClass = $this->staticTypesInClassResolver->collectStaticCallTypeInClass(
|
||||
$class,
|
||||
$this->serviceObjectTypes
|
||||
);
|
||||
|
||||
foreach ($staticTypesInClass as $staticTypeInClass) {
|
||||
$variableName = $this->propertyNaming->fqnToVariableName($staticTypeInClass);
|
||||
|
||||
$propertyMetadata = new PropertyMetadata($variableName, $staticTypeInClass, Class_::MODIFIER_PRIVATE);
|
||||
$this->propertyToAddCollector->addPropertyToClass($class, $propertyMetadata);
|
||||
|
||||
// is this an object? create factory for it next to this :)
|
||||
if ($this->uniqueObjectOrServiceDetector->isUniqueObject()) {
|
||||
$factoryClass = $this->uniqueObjectFactoryFactory->createFactoryClass($class, $staticTypeInClass);
|
||||
|
||||
$this->factoryClassPrinter->printFactoryForClass($factoryClass, $class);
|
||||
}
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\RemovingStatic\Rector\Class_\StaticTypeToSetterInjectionRector\StaticTypeToSetterInjectionRectorTest
|
||||
*/
|
||||
final class StaticTypeToSetterInjectionRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const STATIC_TYPES = 'static_types';
|
||||
|
||||
/**
|
||||
* @var array<class-string|int, class-string>
|
||||
*/
|
||||
private array $staticTypes = [];
|
||||
|
||||
public function __construct(
|
||||
private PropertyNaming $propertyNaming,
|
||||
private PhpDocTypeChanger $phpDocTypeChanger
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
// custom made only for Elasticr
|
||||
return new RuleDefinition('Changes types to setter injection', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
final class CheckoutEntityFactory
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return SomeStaticClass::go();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
final class CheckoutEntityFactory
|
||||
{
|
||||
/**
|
||||
* @var SomeStaticClass
|
||||
*/
|
||||
private $someStaticClass;
|
||||
|
||||
public function setSomeStaticClass(SomeStaticClass $someStaticClass)
|
||||
{
|
||||
$this->someStaticClass = $someStaticClass;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this->someStaticClass->go();
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::STATIC_TYPES => ['SomeStaticClass'],
|
||||
]
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class, StaticCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StaticCall|Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Class_) {
|
||||
return $this->processClass($node);
|
||||
}
|
||||
|
||||
foreach ($this->staticTypes as $staticType) {
|
||||
$objectType = new ObjectType($staticType);
|
||||
if (! $this->isObjectType($node->class, $objectType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$variableName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $variableName);
|
||||
|
||||
return new MethodCall($propertyFetch, $node->name, $node->args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<class-string|int, class-string>> $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$this->staticTypes = $configuration[self::STATIC_TYPES] ?? [];
|
||||
}
|
||||
|
||||
private function processClass(Class_ $class): Class_
|
||||
{
|
||||
foreach ($this->staticTypes as $implements => $staticType) {
|
||||
$objectType = new ObjectType($staticType);
|
||||
|
||||
$containsEntityFactoryStaticCall = (bool) $this->betterNodeFinder->findFirst(
|
||||
$class->stmts,
|
||||
fn (Node $node): bool => $this->isEntityFactoryStaticCall($node, $objectType)
|
||||
);
|
||||
|
||||
if (! $containsEntityFactoryStaticCall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_string($implements)) {
|
||||
$class->implements[] = new FullyQualified($implements);
|
||||
}
|
||||
|
||||
$variableName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$setEntityFactoryMethod = $this->nodeFactory->createSetterClassMethod($variableName, $objectType);
|
||||
|
||||
$entityFactoryProperty = $this->nodeFactory->createPrivateProperty($variableName);
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($entityFactoryProperty);
|
||||
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $objectType);
|
||||
|
||||
$class->stmts = array_merge([$entityFactoryProperty, $setEntityFactoryMethod], $class->stmts);
|
||||
break;
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
private function isEntityFactoryStaticCall(Node $node, ObjectType $objectType): bool
|
||||
{
|
||||
if (! $node instanceof StaticCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isObjectType($node->class, $objectType);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
|
||||
|
||||
final class StaticTypesInClassResolver
|
||||
{
|
||||
public function __construct(
|
||||
private SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
|
||||
private NodeTypeResolver $nodeTypeResolver
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectType[] $objectTypes
|
||||
* @return ObjectType[]
|
||||
*/
|
||||
public function collectStaticCallTypeInClass(Class_ $class, array $objectTypes): array
|
||||
{
|
||||
$staticTypesInClass = [];
|
||||
|
||||
$this->simpleCallableNodeTraverser->traverseNodesWithCallable($class->stmts, function (Node $class) use (
|
||||
$objectTypes,
|
||||
&$staticTypesInClass
|
||||
) {
|
||||
if (! $class instanceof StaticCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($objectTypes as $objectType) {
|
||||
if ($this->nodeTypeResolver->isObjectType($class->class, $objectType)) {
|
||||
$staticTypesInClass[] = $objectType;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return $staticTypesInClass;
|
||||
}
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\ClassBuilder;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\MethodBuilder;
|
||||
use Symplify\Astral\ValueObject\NodeBuilder\ParamBuilder;
|
||||
|
||||
final class UniqueObjectFactoryFactory
|
||||
{
|
||||
public function __construct(
|
||||
private NodeFactory $nodeFactory,
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private PropertyNaming $propertyNaming,
|
||||
private StaticTypeMapper $staticTypeMapper,
|
||||
private PhpDocTypeChanger $phpDocTypeChanger,
|
||||
private PhpDocInfoFactory $phpDocInfoFactory
|
||||
) {
|
||||
}
|
||||
|
||||
public function createFactoryClass(Class_ $class, ObjectType $objectType): Class_
|
||||
{
|
||||
$className = $this->nodeNameResolver->getName($class);
|
||||
if ($className === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$name = $className . 'Factory';
|
||||
|
||||
$shortName = $this->resolveClassShortName($name);
|
||||
|
||||
$factoryClassBuilder = new ClassBuilder($shortName);
|
||||
$factoryClassBuilder->makeFinal();
|
||||
|
||||
$properties = $this->createPropertiesFromTypes($objectType);
|
||||
$factoryClassBuilder->addStmts($properties);
|
||||
|
||||
// constructor
|
||||
$constructorClassMethod = $this->createConstructMethod($objectType);
|
||||
$factoryClassBuilder->addStmt($constructorClassMethod);
|
||||
|
||||
// create
|
||||
$classMethod = $this->createCreateMethod($class, $className, $properties);
|
||||
$factoryClassBuilder->addStmt($classMethod);
|
||||
|
||||
return $factoryClassBuilder->getNode();
|
||||
}
|
||||
|
||||
private function resolveClassShortName(string $name): string
|
||||
{
|
||||
if (\str_contains($name, '\\')) {
|
||||
return (string) Strings::after($name, '\\', -1);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Property[]
|
||||
*/
|
||||
private function createPropertiesFromTypes(ObjectType $objectType): array
|
||||
{
|
||||
$properties = [];
|
||||
$properties[] = $this->createPropertyFromObjectType($objectType);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function createConstructMethod(ObjectType $objectType): ClassMethod
|
||||
{
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$paramBuilder = new ParamBuilder($propertyName);
|
||||
|
||||
$typeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($objectType, TypeKind::PARAM());
|
||||
if ($typeNode !== null) {
|
||||
$paramBuilder->setType($typeNode);
|
||||
}
|
||||
|
||||
$params = [$paramBuilder->getNode()];
|
||||
|
||||
$assigns = $this->createAssignsFromParams($params);
|
||||
|
||||
$methodBuilder = new MethodBuilder(MethodName::CONSTRUCT);
|
||||
$methodBuilder->makePublic();
|
||||
$methodBuilder->addParams($params);
|
||||
$methodBuilder->addStmts($assigns);
|
||||
|
||||
return $methodBuilder->getNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Property[] $properties
|
||||
*/
|
||||
private function createCreateMethod(Class_ $class, string $className, array $properties): ClassMethod
|
||||
{
|
||||
$new = new New_(new FullyQualified($className));
|
||||
|
||||
$constructClassMethod = $class->getMethod(MethodName::CONSTRUCT);
|
||||
$params = [];
|
||||
if ($constructClassMethod !== null) {
|
||||
foreach ($constructClassMethod->params as $param) {
|
||||
$params[] = $param;
|
||||
$new->args[] = new Arg($param->var);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$propertyName = $this->nodeNameResolver->getName($property);
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
$new->args[] = new Arg($propertyFetch);
|
||||
}
|
||||
|
||||
$return = new Return_($new);
|
||||
|
||||
$methodBuilder = new MethodBuilder('create');
|
||||
$methodBuilder->setReturnType(new FullyQualified($className));
|
||||
$methodBuilder->makePublic();
|
||||
$methodBuilder->addStmt($return);
|
||||
$methodBuilder->addParams($params);
|
||||
|
||||
return $methodBuilder->getNode();
|
||||
}
|
||||
|
||||
private function createPropertyFromObjectType(ObjectType $objectType): Property
|
||||
{
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
|
||||
$property = $this->nodeFactory->createPrivateProperty($propertyName);
|
||||
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
|
||||
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $objectType);
|
||||
|
||||
return $property;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Param[] $params
|
||||
*
|
||||
* @return Assign[]
|
||||
*/
|
||||
private function createAssignsFromParams(array $params): array
|
||||
{
|
||||
$assigns = [];
|
||||
|
||||
/** @var Param $param */
|
||||
foreach ($params as $param) {
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $param->var->name);
|
||||
$assigns[] = new Assign($propertyFetch, new Variable($param->var->name));
|
||||
}
|
||||
|
||||
return $assigns;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\RemovingStatic;
|
||||
|
||||
final class UniqueObjectOrServiceDetector
|
||||
{
|
||||
public function isUniqueObject(): bool
|
||||
{
|
||||
// ideas:
|
||||
// hook in container?
|
||||
// has scalar arguments?
|
||||
// is created by new X in the code? → add "NewNodeCollector"
|
||||
|
||||
// fallback for now :)
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user