From f3f293139a382c25cc12a547016b18697ee4b0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Nork=C5=ABnas?= Date: Mon, 22 Dec 2025 06:55:21 +0200 Subject: [PATCH] Allow stringable object to be used to geocode address --- src/Doctrine/ORM/GeocoderListener.php | 13 +++-- src/Mapping/Driver/AttributeDriver.php | 2 +- .../Entity/DummyWithStringableGetter.php | 56 +++++++++++++++++++ .../Fixtures/Entity/StringableAddress.php | 31 ++++++++++ tests/Functional/GeocoderListenerTest.php | 42 ++++++++++++++ 5 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 tests/Functional/Fixtures/Entity/DummyWithStringableGetter.php create mode 100644 tests/Functional/Fixtures/Entity/StringableAddress.php diff --git a/src/Doctrine/ORM/GeocoderListener.php b/src/Doctrine/ORM/GeocoderListener.php index 7df6b1c..1104b56 100644 --- a/src/Doctrine/ORM/GeocoderListener.php +++ b/src/Doctrine/ORM/GeocoderListener.php @@ -57,7 +57,7 @@ public function onFlush(OnFlushEventArgs $args): void $this->geocodeEntity($metadata, $entity); $uow->recomputeSingleEntityChangeSet( - $em->getClassMetadata(get_class($entity)), + $em->getClassMetadata($entity::class), $entity ); } @@ -76,7 +76,7 @@ public function onFlush(OnFlushEventArgs $args): void $this->geocodeEntity($metadata, $entity); $uow->recomputeSingleEntityChangeSet( - $em->getClassMetadata(get_class($entity)), + $em->getClassMetadata($entity::class), $entity ); } @@ -92,11 +92,16 @@ private function geocodeEntity(ClassMetadata $metadata, object $entity): void $address = ''; } - if (empty($address) || !is_string($address)) { + if (!is_string($address) && !$address instanceof \Stringable) { return; } - $results = $this->geocoder->geocodeQuery(GeocodeQuery::create($address)); + $addressString = (string) $address; + if ('' === $addressString) { + return; + } + + $results = $this->geocoder->geocodeQuery(GeocodeQuery::create($addressString)); if (!$results->isEmpty()) { $result = $results->first(); diff --git a/src/Mapping/Driver/AttributeDriver.php b/src/Mapping/Driver/AttributeDriver.php index b3dd63a..1631d98 100644 --- a/src/Mapping/Driver/AttributeDriver.php +++ b/src/Mapping/Driver/AttributeDriver.php @@ -40,7 +40,7 @@ public function loadMetadataFromObject(object $object): ClassMetadata $attributes = $reflection->getAttributes(Attributes\Geocodeable::class); if ([] === $attributes) { - throw new MappingException(sprintf('The class "%s" is not geocodeable', get_class($object))); + throw new MappingException(sprintf('The class "%s" is not geocodeable', $object::class)); } $args = []; diff --git a/tests/Functional/Fixtures/Entity/DummyWithStringableGetter.php b/tests/Functional/Fixtures/Entity/DummyWithStringableGetter.php new file mode 100644 index 0000000..3ba3e32 --- /dev/null +++ b/tests/Functional/Fixtures/Entity/DummyWithStringableGetter.php @@ -0,0 +1,56 @@ +address = $address; + } + + #[Address] + public function getAddress(): StringableAddress + { + return $this->address; + } +} diff --git a/tests/Functional/Fixtures/Entity/StringableAddress.php b/tests/Functional/Fixtures/Entity/StringableAddress.php new file mode 100644 index 0000000..d3817b7 --- /dev/null +++ b/tests/Functional/Fixtures/Entity/StringableAddress.php @@ -0,0 +1,31 @@ +address; + } +} diff --git a/tests/Functional/GeocoderListenerTest.php b/tests/Functional/GeocoderListenerTest.php index ab669de..a910953 100644 --- a/tests/Functional/GeocoderListenerTest.php +++ b/tests/Functional/GeocoderListenerTest.php @@ -17,6 +17,8 @@ use Bazinga\GeocoderBundle\Tests\Functional\Fixtures\Entity\DummyWithGetter; use Bazinga\GeocoderBundle\Tests\Functional\Fixtures\Entity\DummyWithInvalidGetter; use Bazinga\GeocoderBundle\Tests\Functional\Fixtures\Entity\DummyWithProperty; +use Bazinga\GeocoderBundle\Tests\Functional\Fixtures\Entity\DummyWithStringableGetter; +use Bazinga\GeocoderBundle\Tests\Functional\Fixtures\Entity\StringableAddress; use Doctrine\Bundle\DoctrineBundle\ConnectionFactory; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\ORM\Configuration; @@ -177,6 +179,46 @@ public function testPersistForGetter(): void self::assertNotEquals($clone->getLongitude(), $dummy->getLongitude()); } + public function testPersistForStringableGetter(): void + { + self::bootKernel(['config' => static function (TestKernel $kernel) { + $kernel->addTestConfig(__DIR__.'/config/framework.yml'); + + if ($kernel::VERSION_ID >= 60000) { + $kernel->addTestConfig(__DIR__.'/config/framework_sf6.yml'); + } + + $kernel->addTestConfig(__DIR__.'/config/listener.yml'); + $kernel->addTestConfig(__DIR__.'/config/listener_'.(PHP_VERSION_ID >= 80000 ? 'php8' : 'php7').'.yml'); + }]); + + $container = self::getContainer(); + $container->set('http_client', self::createHttpClientForBerlinQuery()); + + $em = $container->get('doctrine.orm.entity_manager'); + + $tool = new SchemaTool($em); + $tool->createSchema($em->getMetadataFactory()->getAllMetadata()); + + $dummy = new DummyWithStringableGetter(); + $dummy->setAddress(new StringableAddress('Berlin, Germany')); + + $em->persist($dummy); + $em->flush(); + + self::assertNotNull($dummy->latitude); + self::assertNotNull($dummy->longitude); + + $clone = clone $dummy; + $dummy->setAddress(new StringableAddress('Paris, France')); + + $em->persist($dummy); + $em->flush(); + + self::assertNotEquals($clone->latitude, $dummy->latitude); + self::assertNotEquals($clone->longitude, $dummy->longitude); + } + public function testPersistForInvalidGetter(): void { self::bootKernel(['config' => static function (TestKernel $kernel) {