Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ It also contains methods to control the number of results:
* `limit($limit)`
* `getLimit()`

Both `geocode()` and `reverse()` methods return an array of `Address` objects,
each providing the following API:
### Address & AddressCollection

Both `geocode()` and `reverse()` methods return a collection of `Address`
objects (`AddressCollection`), each providing the following API:

* `getCoordinates()` will return a `Coordinates` object (with `latitude` and
`longitude` properties);
Expand All @@ -137,6 +139,16 @@ each providing the following API:
* `getCountryCode()` will return the ISO `country` code;
* `getTimezone()` will return the `timezone`.

The `AddressCollection` exposes the following methods:

* `count()` (this class implements `Countable`);
* `first()` retrieves the first `Address`;
* `slice($offset, $length = null)` returns `Address` objects between `$offset`
and `length`;
* `get($index)` fetches an `Address` using its `$index`;
* `all()` returns all `Address` objects;
* `getIterator()` (this class implements `IteratorAggregate`).

### Locale Aware Providers

Providers that are _locale aware_ expose the following methods:
Expand Down Expand Up @@ -208,7 +220,7 @@ $reader = new \GeoIp2\Database\Reader('/path/to/database');
$adapter = new \Geocoder\Adapter\GeoIP2Adapter($reader);
$geocoder = new \Geocoder\Provider\GeoIP2($adapter);

$address = $geocoder->geocode('74.200.247.59');
$address = $geocoder->geocode('74.200.247.59')->first();
```

### TomTom
Expand Down
72 changes: 72 additions & 0 deletions src/Geocoder/Model/AddressCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Geocoder\Model;

final class AddressCollection implements \IteratorAggregate, \Countable
{
/**
* @var Address[]
*/
private $addresses;

public function __construct(array $addresses = [])
{
$this->addresses = array_values($addresses);
}

/**
* {@inheritDoc}
*/
public function getIterator()
{
return new \ArrayIterator($this->all());
}

/**
* {@inheritDoc}
*/
public function count()
{
return count($this->addresses);
}

/**
* @return Address
*/
public function first()
{
if (empty($this->addresses)) {
return null;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return null here? IIRC we can't get 0 results as it would lead to a NoResult exception earlier in the execution flow:

try {
    $address = $geocoder->geocode('foobar')->first();
} catch (NoResult $e) {
    $address = null;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think we can remove null here. We always have at least one Address in the collection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I would not remove it since the class might be used elsewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't thought it could used somewhere else :S

}

return reset($this->addresses);
}

/**
* @return Address[]
*/
public function slice($offset, $length = null)
{
return array_slice($this->addresses, $offset, $length);
}

/**
* @return Address
*/
public function get($index)
{
if (!isset($this->addresses[$index])) {
throw new \OutOfBoundsException(sprintf('The index "%s" does not exist in this collection.', $index));
}

return $this->addresses[$index];
}

/**
* @return Address[]
*/
public function all()
{
return $this->addresses;
}
}
2 changes: 1 addition & 1 deletion src/Geocoder/Model/AddressFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function createFromArray(array $results)
);
}

return $addresses;
return new AddressCollection($addresses);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Geocoder/Provider/IpInfoDb.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class IpInfoDb extends AbstractHttpProvider implements Provider
private $endpointUrl;

/**
* @param HttpAdapterInterface $adapter An HTTP adapter.
* @param string $apiKey An API key.
* @param HttpAdapterInterface $adapter An HTTP adapter.
* @param string $apiKey An API key.
* @param string $precision The endpoint precision. Either "city" or "country" (faster)
*
* @throws Geocoder\Exception\InvalidArgument
Expand Down
5 changes: 2 additions & 3 deletions tests/Geocoder/Tests/Model/AddressFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function testCreateFromArray()
[ 'streetNumber' => 3 ],
]);

$this->assertTrue(is_array($addresses));
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $addresses);
$this->assertCount(3, $addresses);

$i = 1;
Expand All @@ -52,8 +52,7 @@ public function testFormatStringWithLeadingNumeral()
$addresses = $this->factory->createFromArray([
[ 'streetName' => '1st ave 1A' ],
]);
$address = current($addresses);

$this->assertEquals('1st ave 1A', $address->getStreetName());
$this->assertEquals('1st ave 1A', $addresses->first()->getStreetName());
}
}
28 changes: 14 additions & 14 deletions tests/Geocoder/Tests/Provider/ArcGISOnlineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ public function testGeocodeWithRealAddress()
$provider = new ArcGISOnline($this->getAdapter());
$results = $provider->geocode('10 avenue Gambetta, Paris, France');

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(5, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.863279997000461, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3890199980004354, $result->getLongitude(), '', 0.0001);
Expand All @@ -106,11 +106,11 @@ public function testGeocodeWithRealAddressAndHttps()
$provider = new ArcGISOnline($this->getAdapter(), null, true);
$results = $provider->geocode('10 avenue Gambetta, Paris, France');

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(5, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.863279997000461, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3890199980004354, $result->getLongitude(), '', 0.0001);
Expand Down Expand Up @@ -176,11 +176,11 @@ public function testReverseWithRealCoordinates()
$provider = new ArcGISOnline($this->getAdapter());
$results = $provider->reverse(48.863279997000461, 2.3890199980004354);

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(1, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.863279997000461, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3890199980004354, $result->getLongitude(), '', 0.0001);
Expand All @@ -205,11 +205,11 @@ public function testReverseWithRealCoordinatesWithHttps()
$provider = new ArcGISOnline($this->getAdapter(), null, true);
$results = $provider->reverse(48.863279997000461, 2.3890199980004354);

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(1, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.863279997000461, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3890199980004354, $result->getLongitude(), '', 0.0001);
Expand All @@ -234,11 +234,11 @@ public function testGeocodeWithCity()
$provider = new ArcGISOnline($this->getAdapter());
$results = $provider->geocode('Hannover');

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(5, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(52.370518568000477, $result->getLatitude(), '', 0.0001);
$this->assertEquals(9.7332166860004463, $result->getLongitude(), '', 0.0001);
Expand All @@ -258,7 +258,7 @@ public function testGeocodeWithCity()
$this->assertNull($result->getTimezone());

/** @var \Geocoder\Model\Address $result */
$result = $results[1];
$result = $results->get(1);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(47.111386795000499, $result->getLatitude(), '', 0.0001);
$this->assertEquals(-101.4265391569997, $result->getLongitude(), '', 0.0001);
Expand All @@ -268,7 +268,7 @@ public function testGeocodeWithCity()
$this->assertEquals('USA', $result->getCountry()->getCode());

/** @var \Geocoder\Model\Address $result */
$result = $results[2];
$result = $results->get(2);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(39.391768472000479, $result->getLatitude(), '', 0.0001);
$this->assertEquals(-77.440257128999633, $result->getLongitude(), '', 0.0001);
Expand All @@ -278,7 +278,7 @@ public function testGeocodeWithCity()
$this->assertEquals('USA', $result->getCountry()->getCode());

/** @var \Geocoder\Model\Address $result */
$result = $results[3];
$result = $results->get(3);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(53.174198173, $result->getLatitude(), '', 0.0001);
$this->assertEquals(8.5069383810005, $result->getLongitude(), '', 0.0001);
Expand All @@ -289,7 +289,7 @@ public function testGeocodeWithCity()
$this->assertEquals('DEU', $result->getCountry()->getCode());

/** @var \Geocoder\Model\Address $result */
$result = $results[4];
$result = $results->get(4);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(-26.281805980999593, $result->getLatitude(), '', 0.0001);
$this->assertEquals(-48.849389793999649, $result->getLongitude(), '', 0.0001);
Expand Down
24 changes: 12 additions & 12 deletions tests/Geocoder/Tests/Provider/BingMapsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ public function testGeocodeReturnsMultipleResults()
$provider = new BingMaps($this->getMockAdapterReturns($json), 'api_key', 'fr_FR');
$results = $provider->geocode('10 avenue Gambetta, Paris, France');

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(3, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.86321675999999, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.3887721299999995, $result->getLongitude(), '', 0.01);
Expand All @@ -116,7 +116,7 @@ public function testGeocodeReturnsMultipleResults()
$this->assertNull($result->getTimezone());

/** @var \Geocoder\Model\Address $result */
$result = $results[1];
$result = $results->get(1);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.81342781, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.32503767, $result->getLongitude(), '', 0.01);
Expand All @@ -134,7 +134,7 @@ public function testGeocodeReturnsMultipleResults()
$this->assertEquals('France', $result->getCountry()->getName());

/** @var \Geocoder\Model\Address $result */
$result = $results[2];
$result = $results->get(2);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.81014147, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.43568048, $result->getLongitude(), '', 0.01);
Expand All @@ -161,11 +161,11 @@ public function testReverseReturnsSingleResult()
$provider = new BingMaps($this->getMockAdapterReturns($json), 'api_key');
$results = $provider->reverse(48.86321648955345, 2.3887719959020615);

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(1, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.86321648955345, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3887719959020615, $result->getLongitude(), '', 0.0001);
Expand Down Expand Up @@ -195,11 +195,11 @@ public function testGeocodeWithRealAddressReturnsMultipleResults()
$provider = new BingMaps($this->getAdapter(), $_SERVER['BINGMAPS_API_KEY'], 'fr-FR');
$results = $provider->geocode('10 avenue Gambetta, Paris, France');

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(3, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.86321675999999, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.3887721299999995, $result->getLongitude(), '', 0.01);
Expand All @@ -220,7 +220,7 @@ public function testGeocodeWithRealAddressReturnsMultipleResults()
$this->assertNull($result->getTimezone());

/** @var \Geocoder\Model\Address $result */
$result = $results[1];
$result = $results->get(1);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.81342781, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.32503767, $result->getLongitude(), '', 0.01);
Expand All @@ -238,7 +238,7 @@ public function testGeocodeWithRealAddressReturnsMultipleResults()
$this->assertEquals('France', $result->getCountry()->getName());

/** @var \Geocoder\Model\Address $result */
$result = $results[2];
$result = $results->get(2);
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.81014147, $result->getLatitude(), '', 0.01);
$this->assertEquals(2.43568048, $result->getLongitude(), '', 0.01);
Expand Down Expand Up @@ -285,11 +285,11 @@ public function testReverseWithRealCoordinatesReturnsSingleResult()
$provider = new BingMaps($this->getAdapter(), $_SERVER['BINGMAPS_API_KEY']);
$results = $provider->reverse(48.86321648955345, 2.3887719959020615);

$this->assertInternalType('array', $results);
$this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
$this->assertCount(1, $results);

/** @var \Geocoder\Model\Address $result */
$result = $results[0];
$result = $results->first();
$this->assertInstanceOf('\Geocoder\Model\Address', $result);
$this->assertEquals(48.86321648955345, $result->getLatitude(), '', 0.0001);
$this->assertEquals(2.3887719959020615, $result->getLongitude(), '', 0.0001);
Expand Down
Loading