Permalink
Browse files

Create Photon provider (#905)

* Initial commit

* Create Model\PhotonAddress.php

* Add reverse geocoding test

* Update composer.json

* Update README.md

* Apply fixes from StyleCI

* Apply fixes from StyleCI (1)

* Update Photon.php

* Update composer.json

* Revert "Update composer.json"

This reverts commit cb17293.
  • Loading branch information...
jbelien committed Jan 3, 2019
1 parent 1054818 commit db4548013edf68ba50fdcd3a7c3581afad643d41
@@ -135,6 +135,7 @@ Provider | Package | Features | Stats
[Mapzen](https://github.com/geocoder-php/mapzen-provider) | `geocoder-php/mapzen-provider` | address, reverse <br> [Website](https://mapzen.com/documentation/search/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/mapzen-provider/v/stable)](https://packagist.org/packages/geocoder-php/mapzen-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/mapzen-provider/downloads)](https://packagist.org/packages/geocoder-php/mapzen-provider)
[Nominatim](https://github.com/geocoder-php/nominatim-provider) <br> (OpenStreetMap) | `geocoder-php/nominatim-provider` | address, reverse <br> [Website](http://wiki.openstreetmap.org/wiki/Nominatim) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/nominatim-provider/v/stable)](https://packagist.org/packages/geocoder-php/nominatim-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/nominatim-provider/downloads)](https://packagist.org/packages/geocoder-php/nominatim-provider)
[OpenCage](https://github.com/geocoder-php/open-cage-provider) | `geocoder-php/open-cage-provider` | address, reverse <br> [Website](https://opencagedata.com/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/open-cage-provider/v/stable)](https://packagist.org/packages/geocoder-php/open-cage-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/open-cage-provider/downloads)](https://packagist.org/packages/geocoder-php/open-cage-provider)
[Photon](https://github.com/geocoder-php/photon-provider) | `geocoder-php/photon-provider` | address, reverse <br> [Website](https://photon.komoot.de/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/photon-provider/v/stable)](https://packagist.org/packages/geocoder-php/photon-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/photon-provider/downloads)](https://packagist.org/packages/geocoder-php/photon-provider)
[PickPoint](https://github.com/geocoder-php/pickpoint-provider) | `geocoder-php/pickpoint-provider` | address, reverse <br> [Website](https://pickpoint.io/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/pickpoint-provider/v/stable)](https://packagist.org/packages/geocoder-php/pickpoint-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/pickpoint-provider/downloads)](https://packagist.org/packages/geocoder-php/pickpoint-provider)
[TomTom](https://github.com/geocoder-php/tomtom-provider) | `geocoder-php/tomtom-provider` | address, reverse <br> [Website](https://geocoder.tomtom.com/app/view/index) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/tomtom-provider/v/stable)](https://packagist.org/packages/geocoder-php/tomtom-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/tomtom-provider/downloads)](https://packagist.org/packages/geocoder-php/tomtom-provider)
[Yandex](https://github.com/geocoder-php/yandex-provider) | `geocoder-php/yandex-provider` | address, reverse <br> [Website](http://api.yandex.com/maps/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/yandex-provider/v/stable)](https://packagist.org/packages/geocoder-php/yandex-provider) <br>[![Total Downloads](https://poser.pugx.org/geocoder-php/yandex-provider/downloads)](https://packagist.org/packages/geocoder-php/yandex-provider)
@@ -0,0 +1,4 @@
.gitattributes export-ignore
.travis.yml export-ignore
phpunit.xml.dist export-ignore
Tests/ export-ignore
@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml
@@ -0,0 +1,14 @@
language: php
sudo: false

php: 7.2

install:
- composer update --prefer-stable --prefer-dist

script:
- composer test-ci

after_success:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml
@@ -0,0 +1,7 @@
# Change Log

The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.

## 1.0.0

First release of this library.
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2011 — William Durand <william.durand1@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,108 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Provider\Photon\Model;
use Geocoder\Model\Address;
/**
* @author Jonathan Beliën <jbe@geo6.be>
*/
final class PhotonAddress extends Address
{
/**
* @var int|null
*/
private $osmId;
/**
* @var string|null
*/
private $osmType;
/**
* @var \stdclass|null
*/
private $osmTag;
/**
* @return null|int
*/
public function getOSMId()
{
return $this->osmId;
}
/**
* @param null|int $osmId
*
* @return PhotonAddress
*/
public function withOSMId(int $osmId = null): self
{
$new = clone $this;
$new->osmId = $osmId;
return $new;
}
/**
* @return null|string
*/
public function getOSMType()
{
return $this->osmType;
}
/**
* @param null|string $osmType
*
* @return PhotonAddress
*/
public function withOSMType(string $osmType = null): self
{
$new = clone $this;
$new->osmType = $osmType;
return $new;
}
/**
* @return null|object
*/
public function getOSMTag()
{
return $this->osmTag;
}
/**
* @param null|string $key
* @param null|string $value
*
* @return PhotonAddress
*/
public function withOSMTag(string $key = null, string $value = null): self
{
$new = clone $this;
if (!is_null($key) && !is_null($value)) {
$new->osmTag = (object) [
'key' => $key,
'value' => $value,
];
} else {
$new->osmTag = null;
}
return $new;
}
}
@@ -0,0 +1,187 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Provider\Photon;
use Geocoder\Collection;
use Geocoder\Exception\InvalidServerResponse;
use Geocoder\Exception\UnsupportedOperation;
use Geocoder\Location;
use Geocoder\Model\AddressBuilder;
use Geocoder\Model\AddressCollection;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Geocoder\Http\Provider\AbstractHttpProvider;
use Geocoder\Provider\Provider;
use Geocoder\Provider\Photon\Model\PhotonAddress;
use Http\Client\HttpClient;
/**
* @author Niklas Närhinen <niklas@narhinen.net>
* @author Jonathan Beliën <jbe@geo6.be>
*/
final class Photon extends AbstractHttpProvider implements Provider
{
/**
* @var string
*/
private $rootUrl;
/**
* @param HttpClient $client an HTTP client
*
* @return Photon
*/
public static function withKomootServer(HttpClient $client): self
{
return new self($client, 'https://photon.komoot.de');
}
/**
* @param HttpClient $client an HTTP client
* @param string $rootUrl Root URL of the photon server
*/
public function __construct(HttpClient $client, $rootUrl)
{
parent::__construct($client);
$this->rootUrl = rtrim($rootUrl, '/');
}
/**
* {@inheritdoc}
*/
public function geocodeQuery(GeocodeQuery $query): Collection
{
$address = $query->getText();
// This API doesn't handle IPs
if (filter_var($address, FILTER_VALIDATE_IP)) {
throw new UnsupportedOperation('The Photon provider does not support IP addresses.');
}
$url = $this->rootUrl
.'/api?'
.http_build_query([
'q' => $address,
'limit' => $query->getLimit(),
'lang' => $query->getLocale(),
]);
$json = $this->executeQuery($url, $query->getLocale());
if (!isset($json->features) || empty($json->features)) {
return new AddressCollection([]);
}
$results = [];
foreach ($json->features as $feature) {
$results[] = $this->featureToAddress($feature);
}
return new AddressCollection($results);
}
/**
* {@inheritdoc}
*/
public function reverseQuery(ReverseQuery $query): Collection
{
$coordinates = $query->getCoordinates();
$longitude = $coordinates->getLongitude();
$latitude = $coordinates->getLatitude();
$url = $this->rootUrl
.'/reverse?'
.http_build_query([
'lat' => $latitude,
'lon' => $longitude,
'lang' => $query->getLocale(),
]);
$json = $this->executeQuery($url);
if (!isset($json->features) || empty($json->features)) {
return new AddressCollection([]);
}
$results = [];
foreach ($json->features as $feature) {
$results[] = $this->featureToAddress($feature);
}
return new AddressCollection($results);
}
/**
* @param \stdClass $feature
*
* @return Location
*/
private function featureToAddress(\stdClass $feature): Location
{
$builder = new AddressBuilder($this->getName());
$coordinates = $feature->geometry->coordinates;
$properties = $feature->properties;
$builder->setCoordinates(floatval($coordinates[1]), floatval($coordinates[0]));
$builder->setStreetName($properties->street ?? null);
$builder->setStreetNumber($properties->housenumber ?? null);
$builder->setPostalCode($properties->postcode ?? null);
$builder->setLocality($properties->city ?? null);
$builder->setCountry($properties->country ?? null);
if (isset($properties->extent)) {
$builder->setBounds($properties->extent[0], $properties->extent[2], $properties->extent[1], $properties->extent[3]);
}
$address = $builder->build(PhotonAddress::class)
->withOSMId($properties->osm_id ?? null)
->withOSMType($properties->osm_type ?? null)
->withOSMTag(
$properties->osm_key ?? null,
$properties->osm_value ?? null
);
return $address;
}
/**
* {@inheritdoc}
*/
public function getName(): string
{
return 'photon';
}
/**
* @param string $url
*
* @return \stdClass
*/
private function executeQuery(string $url): \stdClass
{
$content = $this->getUrlContents($url);
$json = json_decode($content);
// API error
if (is_null($json)) {
throw InvalidServerResponse::create($url);
}
return $json;
}
}
@@ -0,0 +1,22 @@
# photon Geocoder provider
[![Build Status](https://travis-ci.org/geocoder-php/photon-provider.svg?branch=master)](http://travis-ci.org/geocoder-php/photon-provider)
[![Latest Stable Version](https://poser.pugx.org/geocoder-php/photon-provider/v/stable)](https://packagist.org/packages/geocoder-php/photon-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/photon-provider/downloads)](https://packagist.org/packages/geocoder-php/photon-provider)
[![Monthly Downloads](https://poser.pugx.org/geocoder-php/photon-provider/d/monthly.png)](https://packagist.org/packages/geocoder-php/photon-provider)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/geocoder-php/photon-provider.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/photon-provider)
[![Quality Score](https://img.shields.io/scrutinizer/g/geocoder-php/photon-provider.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/photon-provider)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)

This is the photon provider from the PHP Geocoder. This is a **READ ONLY** repository. See the
[main repo](https://github.com/geocoder-php/Geocoder) for information and documentation.

### Install

```bash
composer require geocoder-php/photon-provider
```

### Contribute

Contributions are very welcome! Send a pull request to the [main repository](https://github.com/geocoder-php/Geocoder) or
report any issues you find on the [issue tracker](https://github.com/geocoder-php/Geocoder/issues).
@@ -0,0 +1 @@
s:354:"{"features":[{"geometry":{"coordinates":[10.0121484,52.0046576],"type":"Point"},"type":"Feature","properties":{"osm_id":15219847,"osm_type":"W","extent":[10.0056473,52.0176648,10.0153227,51.9908144],"country":"Germany","osm_key":"highway","city":"Lamspringe","osm_value":"tertiary","postcode":"31195","state":"Lower Saxony"}}],"type":"FeatureCollection"}";
@@ -0,0 +1 @@
s:1823:"{"features":[{"geometry":{"coordinates":[-0.12770820958562096,51.50344025],"type":"Point"},"type":"Feature","properties":{"osm_id":1879842,"osm_type":"R","extent":[-0.1278356,51.5036483,-0.1273038,51.5032573],"country":"United Kingdom","osm_key":"tourism","housenumber":"10","city":"London","street":"Downing Street","osm_value":"attraction","postcode":"SW1A 2AA","name":"10 Downing Street","state":"England"}},{"geometry":{"coordinates":[-0.1285993,51.5010484],"type":"Point"},"type":"Feature","properties":{"osm_id":2806295309,"osm_type":"N","country":"United Kingdom","osm_key":"office","housenumber":"8\u201310","city":"London","street":"Great George Street","osm_value":"warmonger","postcode":"SW1P 3AE","name":"Finmeccanica UK Ltd","state":"England"}},{"geometry":{"coordinates":[-0.0469504,51.6429794],"type":"Point"},"type":"Feature","properties":{"osm_id":2444967088,"osm_type":"N","country":"United Kingdom","osm_key":"shop","housenumber":"106","city":"London","street":"High Street","osm_value":"car_parts","postcode":"EN3 4EW","name":"UK Garage","state":"England"}},{"geometry":{"coordinates":[-0.029467922558440246,51.58266895],"type":"Point"},"type":"Feature","properties":{"osm_id":201225620,"osm_type":"W","extent":[-0.0295688,51.5827746,-0.029367,51.5825633],"country":"United Kingdom","osm_key":"shop","housenumber":"105","city":"London","street":"High Street","osm_value":"yes","postcode":"E17","name":"Forest Foods (UK)","state":"England"}},{"geometry":{"coordinates":[-0.1419852,51.5171159],"type":"Point"},"type":"Feature","properties":{"osm_id":1265087044,"osm_type":"N","country":"United Kingdom","osm_key":"building","housenumber":"10","city":"London","street":"Little Portland Street","osm_value":"yes","postcode":"W1B 2QD","name":"UK Film Council","state":"England"}}],"type":"FeatureCollection"}";
@@ -0,0 +1 @@
s:421:"{"features":[{"geometry":{"coordinates":[-77.0418817,38.8920977],"type":"Point"},"type":"Feature","properties":{"osm_id":397355101,"osm_type":"W","extent":[-77.0429386,38.8921013,-77.0417246,38.8920977],"country":"United States of America","osm_key":"highway","city":"Washington","osm_value":"primary","postcode":"20005","name":"Constitution Avenue Northwest","state":"District of Columbia"}}],"type":"FeatureCollection"}";
@@ -0,0 +1 @@
s:42:"{"features":[],"type":"FeatureCollection"}";
@@ -0,0 +1 @@
s:457:"{"features":[{"geometry":{"coordinates":[4.360598489890593,50.89634435],"type":"Point"},"type":"Feature","properties":{"osm_id":220754533,"osm_type":"W","extent":[4.3604816,50.8963934,4.3607151,50.896294],"country":"Belgium","osm_key":"building","housenumber":"35","city":"Ville de Bruxelles - Stad Brussel","street":"Avenue Jean de Bologne - Jean de Bolognelaan","osm_value":"yes","postcode":"1020","state":"Brussels-Capital"}}],"type":"FeatureCollection"}";
Oops, something went wrong.

0 comments on commit db45480

Please sign in to comment.