Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
674efb9
Add geo array dumper
norkunas Jul 26, 2016
7e86f60
Implement Httplug (#512)
Nyholm Aug 16, 2016
87431e6
Added example how to use cache
Nyholm Aug 18, 2016
7b8c562
Minor
Nyholm Aug 18, 2016
5efd30d
Moved cache to a cookbook
Nyholm Sep 1, 2016
c4b6c4b
minor
Nyholm Sep 1, 2016
6b200e3
Added info how to configure the HTTP client
Nyholm Sep 1, 2016
7bddfcb
Added full namespace to exceptions (#528)
Nyholm Sep 8, 2016
6de7bc9
Fix bug where cached unit test responses aren't serialised
vicchi Sep 12, 2016
182830c
Add Mapzen provider support
vicchi Sep 12, 2016
0775734
Finalize the providers (#540)
unkind Oct 14, 2016
3317b5a
Creating interfaces to be more SOLID
Nyholm Sep 8, 2016
35fccac
Removed interfaces for value objects
Nyholm Oct 11, 2016
6f8a937
Removed interfaces for value objects
Nyholm Oct 12, 2016
3a30b00
Updated "use" statements
Nyholm Oct 12, 2016
f4bfa7e
bugfix
Nyholm Oct 12, 2016
6674c44
Removed unused "use" statements
Nyholm Oct 12, 2016
d77ba21
bugfix
Nyholm Oct 12, 2016
5d491fa
Added comment
Nyholm Oct 12, 2016
2c9e29f
Added test for empty address
Nyholm Oct 12, 2016
da88d48
Update links for documentation (#542)
willdurand Oct 17, 2016
8fd99d6
Changed name from Position to Location
Nyholm Oct 24, 2016
fc5e82b
Make constructor arguments optional
Nyholm Oct 24, 2016
3fcd48c
We are defined even if (lat, lang) = (0, 0)
Nyholm Oct 24, 2016
bd3f942
Updated variable names
Nyholm Oct 24, 2016
ab073ac
minor
Nyholm Oct 24, 2016
83a45db
Removed some deprecated functions
Nyholm Oct 24, 2016
18c3cc0
Updated changelon
Nyholm Oct 24, 2016
a0eb23a
Updated tests
Nyholm Oct 24, 2016
2703748
Renamed GeocoderResult to Collection
Nyholm Nov 7, 2016
04ddd92
Removed functions in Collection that are covered by the interface it …
Nyholm Nov 7, 2016
76dda38
Removed isDefined function
Nyholm Nov 7, 2016
9372234
Updated changelog with removed isDefined functions
Nyholm Nov 7, 2016
8c651f9
Feature/update googlemaps reverse url (#551)
arubacao Dec 22, 2016
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ composer.lock
composer.phar
phpunit.xml
php-cs-fixer.phar
.puli/
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ env:
- deps=""

php:
- 5.4
- 5.5
- 5.6
- 7.0
Expand All @@ -21,7 +20,7 @@ php:
matrix:
fast_finish: true
include:
- php: 5.4
- php: 5.5
env: deps="low"

before_script:
Expand All @@ -31,4 +30,4 @@ before_script:
- if [ "$deps" = "" ]; then composer install --prefer-dist --no-interaction; fi
- if [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then composer require "geoip/geoip"; fi

script: phpunit --coverage-text
script: ./vendor/bin/phpunit --coverage-text
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
CHANGELOG
=========

### 4.0.0 (2016-xx-xx)

* Added: Interface for `Geocoder\Model\AddressCollection` called `Geocoder\Collection`. Public APIs are updated to type hint for `Geocoder\GeocoderResult`.
* Added: Interface for `Geocoder\Model\Address` called `Geocoder\Location`. Public APIs are updated to type hint for `Geocoder\Location`.
* Changed: `Location::getCoordinates` will return null or a `Coordinates` object with coordinates data. It will never return `Coordinates` without data.
* Changed: `Location::getBounds` will return null or a `Bounds` object with coordinates data. It will never return `Bounds` without data.
* Removed: `AdminLevel::toString` in favor for `AdminLevel::__toString`.
* Removed: `Country::toString` in favor for `Country::__toString`.
* Removed: `Address::getCountryCode` in favor for `Address::getCountry()->getCode()`.
* Removed: `Address::getLongitude` in favor for `Address::getCoordinates()->getLongitude()`.
* Removed: `Address::getLatitude` in favor for `Address::getCoordinates()->getLatitude()`.
* Removed: `Bounds::isDefined` as it is always defined.



### 3.3.0 (2015-12-06)

* Added: timezone field for `FreeGeoIp` provider
Expand Down
46 changes: 33 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ Downloads](https://poser.pugx.org/willdurand/Geocoder/downloads.png)](https://pa
Version](https://poser.pugx.org/willdurand/Geocoder/v/stable.png)](https://packagist.org/packages/willdurand/Geocoder)
![PHP7 ready](https://img.shields.io/badge/PHP7-ready-green.svg)

> **Important:** You are browsing the documentation of Geocoder **3.x**.
Documentation for version **2.x** is available here: [Geocoder 2.x
documentation](https://github.com/geocoder-php/Geocoder/blob/2.x/README.md).
> **Important:** You are browsing the documentation of Geocoder **4.x** (not
> released yet).
>
> Documentation for version **3.x** is available here: [Geocoder 3.x
> documentation](https://github.com/geocoder-php/Geocoder/blob/3.x/README.md).
>
> Documentation for version **2.x** is available here: [Geocoder 2.x
> documentation](https://github.com/geocoder-php/Geocoder/blob/2.x/README.md).

---

Expand All @@ -30,6 +35,7 @@ providing a powerful abstraction layer for geocoding manipulations.
- [GeoIP2](#geoip2)
- [GoogleMaps](#googlemaps)
- [GoogleMapsBusiness](#googlemapsbusiness)
- [Mapzen](#mapzen)
- [MaxMindBinary](#maxmindbinary)
- [Nominatim](#nominatim)
- [TomTom](#tomtom)
Expand All @@ -46,6 +52,7 @@ providing a powerful abstraction layer for geocoding manipulations.
- [Formatters](#formatters)
* [Extending Things](#extending-things)
* [Versioning](#versioning)
* [Cookbook](#cookbook)


Installation
Expand Down Expand Up @@ -73,8 +80,8 @@ since each HTTP-based provider implements
[PSR-7](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md).

```php
$curl = new \Ivory\HttpAdapter\CurlHttpAdapter();
$geocoder = new \Geocoder\Provider\GoogleMaps($curl);
$adapter = new \Http\Adapter\Guzzle6\Client();
$geocoder = new \Geocoder\Provider\GoogleMaps($adapter);

$geocoder->geocode(...);
$geocoder->reverse(...);
Expand Down Expand Up @@ -214,14 +221,14 @@ In order to talk to geocoding APIs, you need HTTP adapters. While it was part of
the library in Geocoder 1.x and 2.x, Geocoder 3.x and upper now relies on the
[PSR-7
Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md)
which defines how HTTP message should be implemented. Choose any library that
follows this PSR and implement the specified interfaces to use with Geocoder.
which defines how HTTP message should be implemented. You can use any library to send HTTP messages
that implements [php-http/client-implementation](https://packagist.org/providers/php-http/client-implementation).

As making choices is rather hard, Geocoder ships with the
[egeloen/http-adapter](https://github.com/egeloen/ivory-http-adapter) library by
default, but it is up to you to choose a different implementation.
To use Guzzle 6 you should run the follwing command:

**Note:** not all providers are HTTP-based.
```
$ composer require php-http/guzzle6-adapter
```

### Providers

Expand All @@ -238,7 +245,8 @@ Chain | `chain` | | | | | meta provider which iterates over a list of providers
[Geonames](http://www.geonames.org/commercial-webservices.html) | `geonames` | yes |no | worldwide | yes | requires registration, no free tier
[Google Maps](https://developers.google.com/maps/documentation/geocoding/) | `google_maps` | yes | supported | worldwide | yes | requires API key. Limit 2500 requests per day
[Google Maps for Business](https://developers.google.com/maps/documentation/business/) | `google_maps_business` | yes | supported | worldwide | yes | requires API key. Limit 100,000 requests per day
[MapQuest](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) | `map_quest` | yes | no | worldwide | yes | both open and [commercial service](http://platform.mapquest.com/geocoding/) require API key
[MapQuest](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) | `map_quest` | yes | no | worldwide | yes | both open and [commercial service](http://platform.mapquest.com/geocoding/) requires API key
[Mapzen](https://mapzen.com/documentation/search/) | `mapzen` | yes | supported | worldwide | yes | requires API key; limited to 6 request/sec, 30,000 request/day
[Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim) | `nominatim` | yes | supported | worldwide | yes | requires a domain name (e.g. local installation)
[OpenCage](http://geocoder.opencagedata.com/) | `opencage` | yes | supported | worldwide | yes | requires API key. 2500 requests/day free
[OpenStreetMap](http://wiki.openstreetmap.org/wiki/Nominatim) | `openstreetmap` | yes | no | worldwide | yes | heavy users (>1q/s) get banned
Expand Down Expand Up @@ -295,6 +303,10 @@ $geocoder = new \Geocoder\Provider\GoogleMaps(
A valid `Client ID` is required. The private key is optional. This provider also
supports SSL, and extends the `GoogleMaps` provider.

##### Mapzen

A valid `API key` is required. This provider also supports SSL.

##### MaxMindBinary

This provider requires a data file, and the
Expand Down Expand Up @@ -360,7 +372,7 @@ when a provider returns a result. The result is returned by `GoogleMaps` because

``` php
$geocoder = new \Geocoder\ProviderAggregator();
$adapter = new \Ivory\HttpAdapter\CurlHttpAdapter();
$adapter = new \Http\Adapter\Guzzle6\Client();

$chain = new \Geocoder\Provider\Chain([
new \Geocoder\Provider\FreeGeoIp($adapter),
Expand Down Expand Up @@ -520,6 +532,14 @@ Major version `2` will reach **end of life on December 2015**.

Version `3.x` is the current major stable version of Geocoder.

Cookbook
--------

We have a small cookbook where you can find examples on common use cases:

* [Caching responses](/docs/cookbook/cache.md)
* [Configuring the HTTP client](/docs/cookbook/http-client.md)


Contributing
------------
Expand Down
16 changes: 12 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@
}
],
"require": {
"php": "^5.4|^7.0",
"egeloen/http-adapter": "~0.8|~1.0",
"igorw/get-in": "~1.0"
"php": "^5.5 || ^7.0",
"igorw/get-in": "^1.0",
"psr/http-message-implementation": "^1.0",
"php-http/client-implementation": "^1.0",
"php-http/message-factory": "^1.0.2",
"php-http/httplug": "^1.0",
"php-http/discovery": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8",
"geoip2/geoip2": "~2.0",
"symfony/stopwatch": "~2.5"
"symfony/stopwatch": "~2.5",
"php-http/message": "^1.0",
"php-http/guzzle6-adapter": "^1.0",
"php-http/mock-client": "^0.3.0"
},
"suggest": {
"ext-geoip": "Enabling the geoip extension allows you to use the MaxMindProvider.",
Expand Down
38 changes: 38 additions & 0 deletions docs/cookbook/cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Caching responses

Many of the APIs are not free so it is a good idea to cache the responses so you
are not paying for the same information twice. The caching is out of scope for this
library but we will show you an example how to properly cache responses with the
HTTPlug [cache plugin](http://php-http.readthedocs.io/en/latest/plugins/cache.html):

```php
use Cache\Adapter\Redis\RedisCachePool;
use Http\Adapter\Guzzle6\Client as GuzzleClient;
use Http\Client\Common\PluginClient;
use Geocoder\Provider\GoogleMaps;

// Get a PSR-6 cache pool
$client = new \Redis();
$client->connect('127.0.0.1', 6379);
$pool = new RedisCachePool($client);

// Give the cache pool to the cache plugin and congure it to ignore
// cache headers and store the response for one year.
$cachePlugin = new CachePlugin($pool, StreamFactoryDiscovery::find(), [
'respect_cache_headers' => false,
'default_ttl' => null,
'cache_lifetime' => 86400*365
]);

$adapter = new GuzzleClient();
$pluginClient = new PluginClient($adapter, [$cachePlugin]);

// Get a geocoder
$geocoder = new GoogleMaps($pluginClient, 'en', null, null, true, 'api-key');

// Query Google Maps servers
$result0 = $geocoder->geocode('foobar');

// This will be retrieved from the cache and not hit Google's servers
$result1 = $geocoder->geocode('foobar');
```
47 changes: 47 additions & 0 deletions docs/cookbook/http-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Configuring the HTTP client

The Geocoder is decoupled from the HTTP client that sends the HTTP messages. This means
that you are responsible for configuring the HTTP client. Usually the default configuration
is good enough but sometime you may want to do something differently.

How you configure the client differs between different clients below are two examples,
one with [Guzzle6 client](https://github.com/guzzle/guzzle) and one with the
[cURL client](https://github.com/php-http/curl-client).

## Guzzle6

```php
use GuzzleHttp\Client as GuzzleClient;
use Http\Adapter\Guzzle6\Client;
use Geocoder\Provider\GoogleMaps;

$config = [
'timeout' => 2.0,
'verify' => false,
];
$guzzle = new GuzzleClient($config);

$adapter = new Client($guzzle);
$geocoder = new GoogleMaps($adapter);

$geocoder->geocode(...);
```


## cURL

```php
use Http\Client\Curl\Client;
use Geocoder\Provider\GoogleMaps;

$options = [
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_SSL_VERIFYPEER => false,
];

$adapter = new Client(null, null, $options);
$geocoder = new GoogleMaps($adapter);

$geocoder->geocode(...);
```

1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<!-- <server name="TOMTOM_MAP_KEY" value="YOUR_MAP_KEY" /> -->
<!-- <server name="GOOGLE_GEOCODING_KEY" value="YOUR_GEOCODING_KEY" /> -->
<!-- <server name="OPENCAGE_API_KEY" value="YOUR_GEOCODING_KEY" /> -->
<!-- <server name="MAPZEN_API_KEY" value="YOUR_MAPZEN_API_KEY" /> -->

</php>
<testsuites>
Expand Down
50 changes: 50 additions & 0 deletions src/Geocoder/Assert.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Geocoder;

class Assert
{
/**
* @param float $value
* @param string $message
*/
public static function latitude($value, $message = '')
{
if (!is_double($value)) {
throw new \InvalidArgumentException(
sprintf($message ?: 'Expected a double. Got: %s', self::typeToString($value))
);
}

if ($value < -90 || $value > 90) {
throw new \InvalidArgumentException(
sprintf($message ?: 'Latitude should be between -90 and 90. Got: %s', $value)
);
}
}

/**
* @param float $value
* @param string $message
*/
public static function longitude($value, $message = '')
{
if (!is_double($value)) {
throw new \InvalidArgumentException(
sprintf($message ?: 'Expected a doable. Got: %s', self::typeToString($value))
);
}

if ($value < -180 || $value > 180) {
throw new \InvalidArgumentException(
sprintf($message ?: 'Latitude should be between -90 and 90. Got: %s', $value)
);
}
}

private static function typeToString($value)
{
return is_object($value) ? get_class($value) : gettype($value);
}

}
38 changes: 38 additions & 0 deletions src/Geocoder/Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Geocoder;

/**
* This is the interface that is always return from a Geocoder.
*
* @author William Durand <william.durand1@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface Collection extends \IteratorAggregate, \Countable
{
/**
* @return Location
*/
public function first();

/**
* @return Location[]
*/
public function slice($offset, $length = null);

/**
* @return bool
*/
public function has($index);

/**
* @return Location
* @throws \OutOfBoundsException
*/
public function get($index);

/**
* @return Location[]
*/
public function all();
}
8 changes: 4 additions & 4 deletions src/Geocoder/Dumper/Dumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@

namespace Geocoder\Dumper;

use Geocoder\Model\Address;
use Geocoder\Location;

/**
* @author William Durand <william.durand1@gmail.com>
*/
interface Dumper
{
/**
* Dumps an `Address` object as a string representation of
* Dumps an `Location` object as a string representation of
* the implemented format.
*
* @param Address $address
* @param Location $location
*
* @return string
*/
public function dump(Address $address);
public function dump(Location $location);
}
Loading