diff --git a/src/Type/Doctrine/Descriptors/BinaryType.php b/src/Type/Doctrine/Descriptors/BinaryType.php index 5b3c848a..21a38092 100644 --- a/src/Type/Doctrine/Descriptors/BinaryType.php +++ b/src/Type/Doctrine/Descriptors/BinaryType.php @@ -2,10 +2,13 @@ namespace PHPStan\Type\Doctrine\Descriptors; +use Composer\InstalledVersions; use PHPStan\Type\MixedType; use PHPStan\Type\ResourceType; use PHPStan\Type\StringType; use PHPStan\Type\Type; +use function class_exists; +use function strpos; class BinaryType implements DoctrineTypeDescriptor { @@ -17,6 +20,10 @@ public function getType(): string public function getWritableToPropertyType(): Type { + if ($this->hasDbal4()) { + return new StringType(); + } + return new ResourceType(); } @@ -30,4 +37,18 @@ public function getDatabaseInternalType(): Type return new StringType(); } + private function hasDbal4(): bool + { + if (!class_exists(InstalledVersions::class)) { + return false; + } + + $dbalVersion = InstalledVersions::getVersion('doctrine/dbal'); + if ($dbalVersion === null) { + return false; + } + + return strpos($dbalVersion, '4.') === 0; + } + } diff --git a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php index 56878cc7..b2297774 100644 --- a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php +++ b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php @@ -28,6 +28,7 @@ use PHPStan\Type\Doctrine\ObjectMetadataResolver; use function array_unshift; use function class_exists; +use function sprintf; use function strpos; use const PHP_VERSION_ID; @@ -271,9 +272,16 @@ public function testSuperclass(?string $objectManagerLoader): void { $this->allowNullablePropertyForRequiredField = false; $this->objectManagerLoader = $objectManagerLoader; + + $dbalVersion = InstalledVersions::getVersion('doctrine/dbal'); + $hasDbal4 = $dbalVersion !== null && strpos($dbalVersion, '4.') === 0; + $this->analyse([__DIR__ . '/data/MyBrokenSuperclass.php'], [ [ - 'Property PHPStan\Rules\Doctrine\ORM\MyBrokenSuperclass::$five type mapping mismatch: database can contain resource but property expects int.', + sprintf( + 'Property PHPStan\Rules\Doctrine\ORM\MyBrokenSuperclass::$five type mapping mismatch: database can contain %s but property expects int.', + $hasDbal4 ? 'string' : 'resource', + ), 17, ], ]); @@ -495,4 +503,33 @@ public function testBugSingleEnum(?string $objectManagerLoader): void $this->analyse([__DIR__ . '/data/bug-single-enum.php'], []); } + /** + * @dataProvider dataObjectManagerLoader + */ + public function testBug659(?string $objectManagerLoader): void + { + $this->allowNullablePropertyForRequiredField = false; + $this->objectManagerLoader = $objectManagerLoader; + + $dbalVersion = InstalledVersions::getVersion('doctrine/dbal'); + $hasDbal4 = $dbalVersion !== null && strpos($dbalVersion, '4.') === 0; + if ($hasDbal4) { + $errors = [ + [ + 'Property PHPStan\Rules\Doctrine\ORM\MyEntity659::$binaryResource type mapping mismatch: database can contain string but property expects resource.', + 31, + ], + ]; + } else { + $errors = [ + [ + 'Property PHPStan\Rules\Doctrine\ORM\MyEntity659::$binaryString type mapping mismatch: database can contain resource but property expects string.', + 25, + ], + ]; + } + + $this->analyse([__DIR__ . '/data/bug-659.php'], $errors); + } + } diff --git a/tests/Rules/Doctrine/ORM/data/bug-659.php b/tests/Rules/Doctrine/ORM/data/bug-659.php new file mode 100644 index 00000000..e4ac3f68 --- /dev/null +++ b/tests/Rules/Doctrine/ORM/data/bug-659.php @@ -0,0 +1,32 @@ += 8.0 + +namespace PHPStan\Rules\Doctrine\ORM; + +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity() + */ +class MyEntity659 +{ + + /** + * @ORM\Id() + * @ORM\GeneratedValue() + * @ORM\Column(type="integer") + * @var int + */ + private $id; + + /** + * @var string + * @ORM\Column(type="binary") + */ + private $binaryString; + + /** + * @var resource + * @ORM\Column(type="binary") + */ + private $binaryResource; +}