diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index bb2f8056..5f064031 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -284,6 +284,27 @@ Replace `Doctrine\ORM\Event\LifecycleEventArgs` with specific event classes base ## TypedPropertyFromColumnTypeRector + +:wrench: **configure it!** + +- class: [`Rector\Transform\Rector\Attribute\AttributeKeyToClassConstFetchRector`](../rules/Transform/Rector/Attribute/AttributeKeyToClassConstFetchRector.php) + +```php +ruleWithConfiguration(TypedPropertyFromColumnTypeRector::class, [ + TypedPropertyFromColumnTypeRector::DEFAULT_NULLABLE_COLUMN => true, + ]); +}; +``` + Complete `@var` annotations or types based on @ORM\Column - class: [`Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromColumnTypeRector`](../rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php) diff --git a/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php b/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php index 25179ed1..3023c628 100644 --- a/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php +++ b/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php @@ -10,24 +10,27 @@ use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; -use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; -use Rector\Core\Php\PhpVersionProvider; +use Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface; use Rector\Core\Rector\AbstractRector; -use Rector\Core\ValueObject\PhpVersion; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\Doctrine\NodeManipulator\ColumnPropertyTypeResolver; use Rector\Doctrine\NodeManipulator\NullabilityColumnPropertyTypeResolver; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator; use Rector\VersionBonding\Contract\MinPhpVersionInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; +use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Doctrine\Tests\CodeQuality\Rector\Property\TypedPropertyFromColumnTypeRector\TypedPropertyFromColumnTypeRectorTest */ -final class TypedPropertyFromColumnTypeRector extends AbstractRector implements MinPhpVersionInterface +final class TypedPropertyFromColumnTypeRector extends AbstractRector implements MinPhpVersionInterface, AllowEmptyConfigurableRectorInterface { + public const DEFAULT_NULLABLE_COLUMN = 'default_nullable_column'; + + private bool $defaultNullableColumn = true; + public function __construct( private readonly PropertyTypeDecorator $propertyTypeDecorator, private readonly ColumnPropertyTypeResolver $columnPropertyTypeResolver, @@ -38,7 +41,7 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Complete @var annotations or types based on @ORM\Column', [ - new CodeSample( + new ConfiguredCodeSample( <<<'CODE_SAMPLE' use Doctrine\ORM\Mapping as ORM; @@ -62,7 +65,11 @@ class SimpleColumn private string|null $name = null; } CODE_SAMPLE - ), + , + [ + self::DEFAULT_NULLABLE_COLUMN => true, + ] + ), ]); } @@ -83,7 +90,7 @@ public function refactor(Node $node): Property|null return null; } - $isNullable = $this->nullabilityColumnPropertyTypeResolver->isNullable($node); + $isNullable = $this->nullabilityColumnPropertyTypeResolver->isNullable($node, $this->defaultNullableColumn); $propertyType = $this->columnPropertyTypeResolver->resolve($node, $isNullable); if (! $propertyType instanceof Type || $propertyType instanceof MixedType) { @@ -116,6 +123,15 @@ public function refactor(Node $node): Property|null return $node; } + + public function configure(array $configuration): void + { + $defaultNullableColumn = $configuration[self::DEFAULT_NULLABLE_COLUMN] ?? (bool) current($configuration); + Assert::boolean($defaultNullableColumn); + + $this->defaultNullableColumn = $defaultNullableColumn; + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::TYPED_PROPERTIES; diff --git a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php index 8ce1e0df..399897c1 100644 --- a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php +++ b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php @@ -31,7 +31,7 @@ public function __construct( ) { } - public function isNullable(Property $property): bool + public function isNullable(Property $property, bool $defaultNullableColumn): bool { $nullableExpr = $this->attributeFinder->findAttributeByClassArgByName( $property, @@ -44,19 +44,19 @@ public function isNullable(Property $property): bool } $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); - return $this->isNullableColumn($phpDocInfo); + return $this->isNullableColumn($phpDocInfo, $defaultNullableColumn); } - private function isNullableColumn(PhpDocInfo $phpDocInfo): bool + private function isNullableColumn(PhpDocInfo $phpDocInfo, bool $defaultNullableColumn): bool { $doctrineAnnotationTagValueNode = $phpDocInfo->findOneByAnnotationClass(self::COLUMN_CLASS); if (! $doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return true; + return $defaultNullableColumn; } $nullableValueArrayItemNode = $doctrineAnnotationTagValueNode->getValue('nullable'); if (! $nullableValueArrayItemNode instanceof ArrayItemNode) { - return true; + return $defaultNullableColumn; } return $nullableValueArrayItemNode->value instanceof ConstExprTrueNode;