merge CorrectDatetimeEntityPropertyDefaultToConstructorRector to MoveCurrentDateTimeDefaultInEntityToConstructorRector (#3978)

* merge CorrectDatetimeEntityPropertyDefaultToConstructorRector to MoveCurrentDateTimeDefaultInEntityToConstructorRector

* [rector] merge CorrectDatetimeEntityPropertyDefaultToConstructorRector to MoveCurrentDateTimeDefaultInEntityToConstructorRector

* add Throw Expr to docs

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-08-21 11:47:44 +02:00 committed by GitHub
parent ac4e73b72f
commit 6a442eddd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 57 additions and 250 deletions

View File

@ -3,7 +3,6 @@
declare(strict_types=1);
use Rector\Doctrine\Rector\Class_\ManagerRegistryGetManagerToEntityManagerRector;
use Rector\DoctrineCodeQuality\Rector\Class_\CorrectDatetimeEntityPropertyDefaultToConstructorRector;
use Rector\DoctrineCodeQuality\Rector\Class_\CorrectDefaultTypesOnEntityPropertyRector;
use Rector\DoctrineCodeQuality\Rector\Class_\InitializeDefaultEntityCollectionRector;
use Rector\DoctrineCodeQuality\Rector\Class_\MoveCurrentDateTimeDefaultInEntityToConstructorRector;
@ -20,6 +19,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(MakeEntityDateTimePropertyDateTimeInterfaceRector::class);
$services->set(MoveCurrentDateTimeDefaultInEntityToConstructorRector::class);
$services->set(CorrectDefaultTypesOnEntityPropertyRector::class);
$services->set(CorrectDatetimeEntityPropertyDefaultToConstructorRector::class);
$services->set(ChangeBigIntEntityPropertyToIntTypeRector::class);
};

View File

@ -633,6 +633,22 @@ $someVariable ? true : false
* `$else` - `/** @var Expr Expression for false */`
<br>
### `PhpParser\Node\Expr\Throw_`
* requires arguments on construct
#### Example PHP Code
```php
throw $someVariable;
```
#### Public Properties
* `$expr` - `/** @var Node\Expr Expression */`
<br>
### `PhpParser\Node\Expr\UnaryMinus`
* requires arguments on construct
@ -2524,6 +2540,7 @@ $someVariable
#### Public Properties
* `$name` - `/** @var Identifier|null Parameter name (for named parameters) */`
* `$value` - `/** @var Expr Value to pass */`
* `$byRef` - `/** @var bool Whether to pass by ref */`
* `$unpack` - `/** @var bool Whether to unpack the argument */`

View File

@ -1,4 +1,4 @@
# All 565 Rectors Overview
# All 564 Rectors Overview
- [Projects](#projects)
---
@ -14,7 +14,7 @@
- [Decomplex](#decomplex) (1)
- [Decouple](#decouple) (1)
- [Doctrine](#doctrine) (17)
- [DoctrineCodeQuality](#doctrinecodequality) (8)
- [DoctrineCodeQuality](#doctrinecodequality) (7)
- [DoctrineGedmoToKnplabs](#doctrinegedmotoknplabs) (7)
- [Downgrade](#downgrade) (1)
- [DynamicTypeAnalysis](#dynamictypeanalysis) (3)
@ -3975,37 +3975,6 @@ Change array to ArrayCollection in setParameters method of query builder
<br><br>
### `CorrectDatetimeEntityPropertyDefaultToConstructorRector`
- class: [`Rector\DoctrineCodeQuality\Rector\Class_\CorrectDatetimeEntityPropertyDefaultToConstructorRector`](/../master/rules/doctrine-code-quality/src/Rector/Class_/CorrectDatetimeEntityPropertyDefaultToConstructorRector.php)
- [test fixtures](/../master/rules/doctrine-code-quality/tests/Rector/Property/CorrectDatetimeEntityPropertyDefaultToConstructorRector/Fixture)
Change default value in string on datetime property to entity constructor
```diff
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
{
/**
- * @ORM\Column(name="log_cas", type="datetime", nullable=false, options={"default"="1900-01-01 00=00=00"})
+ * @ORM\Column(name="log_cas", type="datetime", nullable=false)
*/
- private $when = '1900-01-01 00:00:00';
+ private $when;
+
+ public function __construct()
+ {
+ $this->when = new DateTime('1900-01-01 00:00:00');
+ }
}
```
<br><br>
### `CorrectDefaultTypesOnEntityPropertyRector`
- class: [`Rector\DoctrineCodeQuality\Rector\Property\CorrectDefaultTypesOnEntityPropertyRector`](/../master/rules/doctrine-code-quality/src/Rector/Property/CorrectDefaultTypesOnEntityPropertyRector.php)

View File

@ -11,6 +11,7 @@ use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Expression;
final class ValueAssignFactory
@ -27,7 +28,7 @@ final class ValueAssignFactory
{
$propertyFetch = $this->createPropertyFetch($propertyName);
$newDateTime = $this->createNewDateTime();
$newDateTime->args[] = new Arg($defaultExpr);
$this->addDateTimeArgumentIfNotDefault($defaultExpr, $newDateTime);
$assign = new Assign($propertyFetch, $newDateTime);
@ -43,4 +44,13 @@ final class ValueAssignFactory
{
return new New_(new FullyQualified('DateTime'));
}
private function addDateTimeArgumentIfNotDefault(Expr $defaultExpr, New_ $dateTimeNew): void
{
if ($defaultExpr instanceof String_ && ($defaultExpr->value === 'now' || $defaultExpr->value === 'now()')) {
return;
}
$dateTimeNew->args[] = new Arg($defaultExpr);
}
}

View File

@ -1,149 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\DoctrineCodeQuality\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\DoctrineCodeQuality\NodeAnalyzer\ColumnDatetimePropertyAnalyzer;
use Rector\DoctrineCodeQuality\NodeFactory\ValueAssignFactory;
use Rector\DoctrineCodeQuality\NodeManipulator\ColumnDatetimePropertyManipulator;
use Rector\DoctrineCodeQuality\NodeManipulator\ConstructorManipulator;
/**
* @see https://stackoverflow.com/a/7698687/1348344
*
* @todo possible merge with
* @see MoveCurrentDateTimeDefaultInEntityToConstructorRector
*
* @see \Rector\DoctrineCodeQuality\Tests\Rector\Property\CorrectDatetimeEntityPropertyDefaultToConstructorRector\CorrectDatetimeEntityPropertyDefaultToConstructorRectorTest
*/
final class CorrectDatetimeEntityPropertyDefaultToConstructorRector extends AbstractRector
{
/**
* @var ColumnDatetimePropertyAnalyzer
*/
private $columnDatetimePropertyAnalyzer;
/**
* @var ValueAssignFactory
*/
private $valueAssignFactory;
/**
* @var ConstructorManipulator
*/
private $constructorManipulator;
/**
* @var ColumnDatetimePropertyManipulator
*/
private $columnDatetimePropertyManipulator;
public function __construct(
ColumnDatetimePropertyAnalyzer $columnDatetimePropertyAnalyzer,
ValueAssignFactory $valueAssignFactory,
ConstructorManipulator $constructorManipulator,
ColumnDatetimePropertyManipulator $columnDatetimePropertyManipulator
) {
$this->columnDatetimePropertyAnalyzer = $columnDatetimePropertyAnalyzer;
$this->valueAssignFactory = $valueAssignFactory;
$this->constructorManipulator = $constructorManipulator;
$this->columnDatetimePropertyManipulator = $columnDatetimePropertyManipulator;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Change default value in string on datetime property to entity constructor', [
new CodeSample(
<<<'PHP'
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
{
/**
* @ORM\Column(name="log_cas", type="datetime", nullable=false, options={"default"="1900-01-01 00=00=00"})
*/
private $when = '1900-01-01 00:00:00';
}
PHP
,
<<<'PHP'
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
{
/**
* @ORM\Column(name="log_cas", type="datetime", nullable=false)
*/
private $when;
public function __construct()
{
$this->when = new DateTime('1900-01-01 00:00:00');
}
}
PHP
),
]);
}
/**
* @return array<int, string>
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
foreach ($node->getProperties() as $property) {
$this->refactorProperty($property, $node);
}
return $node;
}
private function refactorProperty(Property $property, Class_ $class): void
{
// nothing to change → skip
$onlyProperty = $property->props[0];
if ($onlyProperty->default === null) {
return;
}
$columnTagValueNode = $this->columnDatetimePropertyAnalyzer->matchDateTimeColumnTagValueNodeInProperty(
$property
);
if ($columnTagValueNode === null) {
return;
}
$defaultValue = $onlyProperty->default;
$onlyProperty->default = null;
$this->columnDatetimePropertyManipulator->removeDefaultOption($columnTagValueNode);
/** @var string $propertyName */
$propertyName = $this->getName($onlyProperty);
$expression = $this->valueAssignFactory->createDefaultDateTimeWithValueAssign($propertyName, $defaultValue);
$this->constructorManipulator->addStmtToConstructor($class, $expression);
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\DoctrineCodeQuality\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\Core\Rector\AbstractRector;
@ -111,68 +112,55 @@ PHP
*/
public function getNodeTypes(): array
{
return [Class_::class, Property::class];
return [Class_::class];
}
/**
* @param Class_|Property $node
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if ($node instanceof Property) {
return $this->refactorProperty($node);
foreach ($node->getProperties() as $property) {
$this->refactorProperty($property, $node);
}
if ($node instanceof Class_) {
return $this->refactorClass($node);
}
return null;
return $node;
}
private function refactorProperty(Property $property): ?Property
private function refactorProperty(Property $property, Class_ $class): ?Property
{
if (! $this->isObjectType($property, 'DateTimeInterface')) {
return null;
}
$columnTagValueNode = $this->columnDatetimePropertyAnalyzer->matchDateTimeColumnTagValueNodeInProperty(
$property
);
if ($columnTagValueNode === null) {
return null;
}
// 1. remove default options from database level
$this->columnDatetimePropertyManipulator->removeDefaultOption($columnTagValueNode);
// 2. remove default value
$this->refactorClass($class, $property);
// 3. remove default from property
$onlyProperty = $property->props[0];
$onlyProperty->default = null;
return $property;
}
private function refactorClass(Class_ $class): ?Class_
private function refactorClass(Class_ $class, Property $property): void
{
foreach ($class->getProperties() as $property) {
if (! $this->isObjectType($property, 'DateTimeInterface')) {
return null;
}
/** @var string $propertyName */
$propertyName = $this->getName($property);
$onlyProperty = $property->props[0];
$columnTagValueNode = $this->columnDatetimePropertyAnalyzer->matchDateTimeColumnTagValueNodeInProperty(
$property
);
/** @var Expr $defaultExpr */
$defaultExpr = $onlyProperty->default;
if ($columnTagValueNode === null) {
continue;
}
$expression = $this->valueAssignFactory->createDefaultDateTimeWithValueAssign($propertyName, $defaultExpr);
/** @var string $propertyName */
$propertyName = $this->getName($property);
$assign = $this->valueAssignFactory->createDefaultDateTimeAssign($propertyName);
$this->constructorManipulator->addStmtToConstructor($class, $assign);
}
return $class;
$this->constructorManipulator->addStmtToConstructor($class, $expression);
}
}

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\CorrectDatetimeEntityPropertyDefaultToConstructorRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class CorrectDatetimeEntityPropertyDefaultToConstructorRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return \Rector\DoctrineCodeQuality\Rector\Class_\CorrectDatetimeEntityPropertyDefaultToConstructorRector::class;
}
}

View File

@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
class MoveFullDate
{
/**
* @ORM\Column(type="datetime", nullable=false, options={"default"="1900-01-01 00=00=00"})
@ -26,7 +26,7 @@ use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
class MoveFullDate
{
/**
* @ORM\Column(type="datetime", nullable=false)

View File

@ -6,6 +6,7 @@ namespace Rector\DoctrineCodeQuality\Tests\Rector\Property\MoveCurrentDateTimeDe
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\DoctrineCodeQuality\Rector\Class_\MoveCurrentDateTimeDefaultInEntityToConstructorRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MoveCurrentDateTimeDefaultInEntityToConstructorRectorTest extends AbstractRectorTestCase
@ -25,6 +26,6 @@ final class MoveCurrentDateTimeDefaultInEntityToConstructorRectorTest extends Ab
protected function getRectorClass(): string
{
return \Rector\DoctrineCodeQuality\Rector\Class_\MoveCurrentDateTimeDefaultInEntityToConstructorRector::class;
return MoveCurrentDateTimeDefaultInEntityToConstructorRector::class;
}
}

View File

@ -46,6 +46,7 @@ use PhpParser\Node\Expr\ShellExec;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Expr\Ternary;
use PhpParser\Node\Expr\Throw_ as ThrowExpr;
use PhpParser\Node\Expr\UnaryMinus;
use PhpParser\Node\Expr\UnaryPlus;
use PhpParser\Node\Expr\Variable;
@ -434,6 +435,8 @@ final class DumpNodesCommand extends AbstractCommand
$node = new NullsafeMethodCall($someVariableNode, new Identifier(self::SOME_METHOD));
} elseif ($nodeClass === NullsafePropertyFetch::class) {
$node = new NullsafePropertyFetch($someVariableNode, new Identifier('somePropety'));
} elseif ($nodeClass === ThrowExpr::class) {
$node = new Throw_($someVariableNode);
} else {
throw new ShouldNotHappenException(sprintf(
'Implement a new printer for "%s" node in "%s"',