diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index 49d10a486b..f14c38b362 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -15,8 +15,10 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory; use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\MappingException as OrmMappingException; +use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\Type; @@ -26,7 +28,7 @@ use Symfony\Component\PropertyInfo\Type; * * @author Kévin Dunglas */ -class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface +class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface { private $entityManager; private $classMetadataFactory; @@ -51,12 +53,8 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE */ public function getProperties($class, array $context = []) { - try { - $metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class); - } catch (MappingException $exception) { - return; - } catch (OrmMappingException $exception) { - return; + if (null === $metadata = $this->getMetadata($class)) { + return null; } $properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames()); @@ -77,12 +75,8 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE */ public function getTypes($class, $property, array $context = []) { - try { - $metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class); - } catch (MappingException $exception) { - return; - } catch (OrmMappingException $exception) { - return; + if (null === $metadata = $this->getMetadata($class)) { + return null; } if ($metadata->hasAssociation($property)) { @@ -176,6 +170,39 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE } } + /** + * {@inheritdoc} + */ + public function isReadable($class, $property, array $context = []) + { + return null; + } + + /** + * {@inheritdoc} + */ + public function isWritable($class, $property, array $context = []) + { + if ( + null === ($metadata = $this->getMetadata($class)) + || ClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType + || !\in_array($property, $metadata->getIdentifierFieldNames(), true) + ) { + return null; + } + + return false; + } + + private function getMetadata(string $class): ?ClassMetadata + { + try { + return $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class); + } catch (MappingException | OrmMappingException $exception) { + return null; + } + } + /** * Determines whether an association is nullable. * diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index ace1d447c2..dd5200117c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -16,6 +16,7 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\Tools\Setup; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineGeneratedValue; use Symfony\Component\PropertyInfo\Type; /** @@ -223,4 +224,13 @@ class DoctrineExtractorTest extends TestCase { $this->assertNull($this->createExtractor($legacy)->getTypes('Not\Exist', 'baz')); } + + public function testGeneratedValueNotWritable() + { + $extractor = $this->createExtractor(); + $this->assertFalse($extractor->isWritable(DoctrineGeneratedValue::class, 'id')); + $this->assertNull($extractor->isReadable(DoctrineGeneratedValue::class, 'id')); + $this->assertNull($extractor->isWritable(DoctrineGeneratedValue::class, 'foo')); + $this->assertNull($extractor->isReadable(DoctrineGeneratedValue::class, 'foo')); + } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineGeneratedValue.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineGeneratedValue.php new file mode 100644 index 0000000000..8418b5e591 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineGeneratedValue.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\GeneratedValue; +use Doctrine\ORM\Mapping\Id; + +/** + * @author Kévin Dunglas + * + * @Entity + */ +class DoctrineGeneratedValue +{ + /** + * @Id + * @GeneratedValue(strategy="AUTO") + * @Column(type="integer") + */ + public $id; + + /** + * @Column + */ + public $foo; +}