Skip to content

Commit c9e152b

Browse files
authored
Merge pull request #239 from romaricdrigon/feat-217
Address annotation can be used over a getter
2 parents 35fbe83 + b855586 commit c9e152b

File tree

5 files changed

+220
-5
lines changed

5 files changed

+220
-5
lines changed

Doctrine/ORM/GeocoderListener.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
namespace Bazinga\GeocoderBundle\Doctrine\ORM;
1414

15+
use Bazinga\GeocoderBundle\Mapping\ClassMetadata;
1516
use Bazinga\GeocoderBundle\Mapping\Driver\DriverInterface;
1617
use Doctrine\Common\EventSubscriber;
1718
use Doctrine\ORM\Event\OnFlushEventArgs;
@@ -84,8 +85,15 @@ public function onFlush(OnFlushEventArgs $args)
8485

8586
private function geocodeEntity($entity)
8687
{
88+
/** @var ClassMetadata $metadata */
8789
$metadata = $this->driver->loadMetadataFromObject($entity);
88-
$address = $metadata->addressProperty->getValue($entity);
90+
91+
if (null !== $metadata->addressGetter) {
92+
$address = $metadata->addressGetter->invoke($entity);
93+
} else {
94+
$address = $metadata->addressProperty->getValue($entity);
95+
}
96+
8997
$results = $this->geocoder->geocodeQuery(GeocodeQuery::create($address));
9098

9199
if (!empty($results)) {

Mapping/ClassMetadata.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ class ClassMetadata
3131
* @var \ReflectionProperty
3232
*/
3333
public $longitudeProperty;
34+
35+
/**
36+
* @var \ReflectionMethod
37+
*/
38+
public $addressGetter;
3439
}

Mapping/Driver/AnnotationDriver.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ public function loadMetadataFromObject($object)
6262
}
6363
}
6464

65+
foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
66+
if ($this->reader->getMethodAnnotation($method, Annotations\Address::class)) {
67+
if (0 !== $method->getNumberOfRequiredParameters()) {
68+
throw new \Exception('You can not use a method requiring parameters with @Address annotation!');
69+
}
70+
71+
$metadata->addressGetter = $method;
72+
}
73+
}
74+
6575
return $metadata;
6676
}
6777
}

Resources/doc/doctrine.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,37 @@ class User
3434
}
3535
```
3636

37+
Instead of annotating a property, you can also annotate a getter:
38+
39+
```php
40+
41+
use Bazinga\GeocoderBundle\Mapping\Annotations as Geocoder;
42+
43+
/**
44+
* @Geocoder\Geocodeable
45+
*/
46+
class User
47+
{
48+
/**
49+
* @Geocoder\Latitude
50+
*/
51+
private $latitude;
52+
53+
/**
54+
* @Geocoder\Longitude
55+
*/
56+
private $longitude;
57+
58+
/**
59+
* @Geocoder\Address
60+
*/
61+
public function getAddress(): string
62+
{
63+
// Your code...
64+
}
65+
}
66+
```
67+
3768
Secondly, register the Doctrine event listener and its dependencies in your `services.yaml` file.
3869
You have to indicate which provider to use to reverse geocode the address. Here we use `acme` provider we declared in bazinga_geocoder configuration earlier.
3970

Tests/Doctrine/ORM/GeocoderListenerTest.php

Lines changed: 165 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ protected function setUp()
7474

7575
$sm = new SchemaTool($this->em);
7676
$sm->createSchema([
77-
$this->em->getClassMetadata('Bazinga\GeocoderBundle\Tests\Doctrine\ORM\Dummy'),
77+
$this->em->getClassMetadata('Bazinga\GeocoderBundle\Tests\Doctrine\ORM\DummyWithProperty'),
78+
$this->em->getClassMetadata('Bazinga\GeocoderBundle\Tests\Doctrine\ORM\DummyWithGetter'),
79+
$this->em->getClassMetadata('Bazinga\GeocoderBundle\Tests\Doctrine\ORM\DummyWithInvalidGetter'),
7880
]);
7981
}
8082

81-
public function testPersist()
83+
public function testPersistForProperty()
8284
{
83-
$dummy = new Dummy();
85+
$dummy = new DummyWithProperty();
8486
$dummy->address = 'Berlin, Germany';
8587

8688
$this->em->persist($dummy);
@@ -98,13 +100,46 @@ public function testPersist()
98100
$this->assertNotEquals($clone->latitude, $dummy->latitude);
99101
$this->assertNotEquals($clone->longitude, $dummy->longitude);
100102
}
103+
104+
public function testPersistForGetter()
105+
{
106+
$dummy = new DummyWithGetter();
107+
$dummy->setAddress('Berlin, Germany');
108+
109+
$this->em->persist($dummy);
110+
$this->em->flush();
111+
112+
$this->assertNotNull($dummy->getLatitude());
113+
$this->assertNotNull($dummy->getLongitude());
114+
115+
$clone = clone $dummy;
116+
$dummy->setAddress('Paris, France');
117+
118+
$this->em->persist($dummy);
119+
$this->em->flush();
120+
121+
$this->assertNotEquals($clone->getLatitude(), $dummy->getLatitude());
122+
$this->assertNotEquals($clone->getLongitude(), $dummy->getLongitude());
123+
}
124+
125+
public function testPersistForInvalidGetter()
126+
{
127+
$dummy = new DummyWithInvalidGetter();
128+
$dummy->setAddress('Berlin, Germany');
129+
130+
$this->em->persist($dummy);
131+
132+
$this->expectException(\Exception::class);
133+
134+
$this->em->flush();
135+
}
101136
}
102137

103138
/**
104139
* @Geocodeable
105140
* @Entity
106141
*/
107-
class Dummy
142+
class DummyWithProperty
108143
{
109144
/**
110145
* @Id @GeneratedValue
@@ -130,3 +165,129 @@ class Dummy
130165
*/
131166
public $address;
132167
}
168+
169+
/**
170+
* @Geocodeable
171+
* @Entity
172+
*/
173+
class DummyWithGetter
174+
{
175+
/**
176+
* @Id @GeneratedValue
177+
* @Column(type="integer")
178+
*/
179+
private $id;
180+
181+
/**
182+
* @Latitude
183+
* @Column
184+
*/
185+
private $latitude;
186+
187+
/**
188+
* @Longitude
189+
* @Column
190+
*/
191+
private $longitude;
192+
193+
/**
194+
* @Column
195+
*/
196+
private $_address;
197+
198+
public function setAddress($address)
199+
{
200+
$this->_address = $address;
201+
}
202+
203+
/**
204+
* @Address
205+
*/
206+
public function getAddress()
207+
{
208+
return $this->_address;
209+
}
210+
211+
public function getLatitude()
212+
{
213+
return $this->latitude;
214+
}
215+
216+
public function setLatitude($latitude)
217+
{
218+
$this->latitude = $latitude;
219+
}
220+
221+
public function getLongitude()
222+
{
223+
return $this->longitude;
224+
}
225+
226+
public function setLongitude($longitude)
227+
{
228+
$this->longitude = $longitude;
229+
}
230+
}
231+
232+
/**
233+
* @Geocodeable
234+
* @Entity
235+
*/
236+
class DummyWithInvalidGetter
237+
{
238+
/**
239+
* @Id @GeneratedValue
240+
* @Column(type="integer")
241+
*/
242+
private $id;
243+
244+
/**
245+
* @Latitude
246+
* @Column
247+
*/
248+
private $latitude;
249+
250+
/**
251+
* @Longitude
252+
* @Column
253+
*/
254+
private $longitude;
255+
256+
/**
257+
* @Column
258+
*/
259+
private $_address;
260+
261+
public function setAddress($address)
262+
{
263+
$this->_address = $address;
264+
}
265+
266+
/**
267+
* @Address
268+
*/
269+
public function getAddress($requiredParameter)
270+
{
271+
return $this->_address;
272+
}
273+
274+
public function getLatitude()
275+
{
276+
return $this->latitude;
277+
}
278+
279+
public function setLatitude($latitude)
280+
{
281+
$this->latitude = $latitude;
282+
}
283+
284+
public function getLongitude()
285+
{
286+
return $this->longitude;
287+
}
288+
289+
public function setLongitude($longitude)
290+
{
291+
$this->longitude = $longitude;
292+
}
293+
}

0 commit comments

Comments
 (0)