Commit c331301f by banice

站点搜索完成

parent ecf40581
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/25
* Time: 下午8:53
*/
namespace App\Console\Commands\station;
use App\model\SiteModel;
use Illuminate\Console\Command;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Geotools;
use DB;
class GeoHash extends Command
{
protected $description = '计算geo_hash';
protected $signature = 'geo:station';
/**
* @throws \Exception
*/
public function handle()
{
$sites = SiteModel::all(['id', 'longitude', 'latitude'])->toArray();
$geoTools = new Geotools();
foreach ($sites as $site) {
$coorToGeoHash = new Coordinate($site['longitude'] . ',' . $site['latitude']);
$coorToGeoHash = new Coordinate([$site['latitude'], $site['longitude']]);
$encoded = $geoTools->geohash()->encode($coorToGeoHash, 5);
$geoHashValue = $encoded->getGeohash();
DB::table('sites')->where('id', $site['id'])->update([
'geo_hash' => $geoHashValue
]);
}
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@
namespace App\Console;
use App\Console\Commands\box\door\SyncState;
use App\Console\Commands\station\GeoHash;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
......@@ -17,6 +18,7 @@ class Kernel extends ConsoleKernel
//
SyncState::class,
GeoHash::class,
];
/**
......
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/25
* Time: 上午9:03
*/
namespace App\Http\Controllers\v1\station;
use App\Http\Controllers\Controller;
use App\model\SiteModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use League\Geotools\Geotools;
use Validator;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
class NeighbourController extends Controller
{
private function test()
{
}
public function get(Request $request)
{
$validator = Validator::make($request->all(),
[
'lng' => 'required',
'lat' => 'required'
]);
if ($validator->fails()) {
abort(400, $validator->errors()->first());
}
$geoTools = new Geotools();
$lng = $request->get('lng');
$lat = $request->get('lat');
$centerPoint = new Coordinate([$lat, $lng]);
$encoded = $geoTools->geohash()->encode($centerPoint, 5);
$geoHashValue = $encoded->getGeohash();//比对相同的value
Log::debug($geoHashValue);
$sites = SiteModel::where('geo_hash', $geoHashValue)->get(['longitude', 'latitude', 'img', 'status', 'name', 'id', 'province', 'city', 'area', 'area_name', 'address', 'service_time'])->toArray();
$neighbourSite = [];
foreach ($sites as $site) {
$point = new Coordinate([$site['latitude'], $site['longitude']]);
$distance = $geoTools->distance()->setFrom($centerPoint)->setTo($point);
$distanceValue = $distance->flat();
if ($distanceValue <= 2000) {
$tmp = $site;
if (blank($site['area'])) {
$tmp['area'] = '';
}
$tmp['distance'] = $distanceValue;
array_push($neighbourSite, $tmp);
}
}
$sitesCount = count($neighbourSite);
$data = [];
$data['site_count'] = $sitesCount;
if ($sitesCount !== 0) {
$data['site'] = $neighbourSite;
}
return $this->response->array($this->getResponseCode() + ['data' => $data]);
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/25
* Time: 上午9:22
*/
namespace App\model;
use Illuminate\Database\Eloquent\Model;
class SiteModel extends Model
{
protected $table = 'sites';
}
\ No newline at end of file
......@@ -19,7 +19,8 @@
"spatie/array-to-xml": "^2.7",
"overtrue/laravel-lang": "^3.0",
"barryvdh/laravel-ide-helper": "^2.5",
"bschmitt/laravel-amqp": "^2.0"
"bschmitt/laravel-amqp": "^2.0",
"league/geotools": "^0.8.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
......
......@@ -68,6 +68,8 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\v1', 'prefix' => 'api/
});
$api->get('sites/neighbour', 'station\NeighbourController@get');
});
......
../league/geotools/bin/geotools
\ No newline at end of file
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\Adapter\Common\Exception\InvalidArgumentException;
use Cache\TagInterop\TaggableCacheItemInterface;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class CacheItem implements PhpCacheItem
{
/**
* @type array
*/
private $prevTags = [];
/**
* @type array
*/
private $tags = [];
/**
* @type \Closure
*/
private $callable;
/**
* @type string
*/
private $key;
/**
* @type mixed
*/
private $value;
/**
* The expiration timestamp is the source of truth. This is the UTC timestamp
* when the cache item expire. A value of zero means it never expires. A nullvalue
* means that no expiration is set.
*
* @type int|null
*/
private $expirationTimestamp = null;
/**
* @type bool
*/
private $hasValue = false;
/**
* @param string $key
* @param \Closure|bool $callable or boolean hasValue
*/
public function __construct($key, $callable = null, $value = null)
{
$this->key = $key;
if ($callable === true) {
$this->hasValue = true;
$this->value = $value;
} elseif ($callable !== false) {
// This must be a callable or null
$this->callable = $callable;
}
}
/**
* {@inheritdoc}
*/
public function getKey()
{
return $this->key;
}
/**
* {@inheritdoc}
*/
public function set($value)
{
$this->value = $value;
$this->hasValue = true;
$this->callable = null;
return $this;
}
/**
* {@inheritdoc}
*/
public function get()
{
if (!$this->isHit()) {
return;
}
return $this->value;
}
/**
* {@inheritdoc}
*/
public function isHit()
{
$this->initialize();
if (!$this->hasValue) {
return false;
}
if ($this->expirationTimestamp !== null) {
return $this->expirationTimestamp > time();
}
return true;
}
/**
* {@inheritdoc}
*/
public function getExpirationTimestamp()
{
return $this->expirationTimestamp;
}
/**
* {@inheritdoc}
*/
public function expiresAt($expiration)
{
if ($expiration instanceof \DateTimeInterface) {
$this->expirationTimestamp = $expiration->getTimestamp();
} elseif (is_int($expiration) || null === $expiration) {
$this->expirationTimestamp = $expiration;
} else {
throw new InvalidArgumentException('Cache item ttl/expiresAt must be of type integer or \DateTimeInterface.');
}
return $this;
}
/**
* {@inheritdoc}
*/
public function expiresAfter($time)
{
if ($time === null) {
$this->expirationTimestamp = null;
} elseif ($time instanceof \DateInterval) {
$date = new \DateTime();
$date->add($time);
$this->expirationTimestamp = $date->getTimestamp();
} elseif (is_int($time)) {
$this->expirationTimestamp = time() + $time;
} else {
throw new InvalidArgumentException('Cache item ttl/expiresAfter must be of type integer or \DateInterval.');
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getPreviousTags()
{
$this->initialize();
return $this->prevTags;
}
/**
* {@inheritdoc}
*/
public function getTags()
{
return $this->tags;
}
/**
* {@inheritdoc}
*/
public function setTags(array $tags)
{
$this->tags = [];
$this->tag($tags);
return $this;
}
/**
* Adds a tag to a cache item.
*
* @param string|string[] $tags A tag or array of tags
*
* @throws InvalidArgumentException When $tag is not valid.
*
* @return TaggableCacheItemInterface
*/
private function tag($tags)
{
$this->initialize();
if (!is_array($tags)) {
$tags = [$tags];
}
foreach ($tags as $tag) {
if (!is_string($tag)) {
throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', is_object($tag) ? get_class($tag) : gettype($tag)));
}
if (isset($this->tags[$tag])) {
continue;
}
if (!isset($tag[0])) {
throw new InvalidArgumentException('Cache tag length must be greater than zero');
}
if (isset($tag[strcspn($tag, '{}()/\@:')])) {
throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:', $tag));
}
$this->tags[$tag] = $tag;
}
return $this;
}
/**
* If callable is not null, execute it an populate this object with values.
*/
private function initialize()
{
if ($this->callable !== null) {
// $func will be $adapter->fetchObjectFromCache();
$func = $this->callable;
$result = $func();
$this->hasValue = $result[0];
$this->value = $result[1];
$this->prevTags = isset($result[2]) ? $result[2] : [];
$this->expirationTimestamp = null;
if (isset($result[3]) && is_int($result[3])) {
$this->expirationTimestamp = $result[3];
}
$this->callable = null;
}
}
/**
* @internal This function should never be used and considered private.
*
* Move tags from $tags to $prevTags
*/
public function moveTagsToPrevious()
{
$this->prevTags = $this->tags;
$this->tags = [];
}
}
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## 1.1.0
### Added
- Support for storing binary data
### Fixed
- Issue with one character variables
### Changed
- Tests are now extending `PHPUnit\Framework\TestCase`
## 1.0.0
* No changes since 0.4.0.
## 0.4.0
### Added
* `AbstractCachePool` has 4 new abstract methods: `getList`, `removeList`, `appendListItem` and `removeListItem`.
* `AbstractCachePool::invalidateTags` and `AbstractCachePool::invalidateTags`
* Added interfaces for our items and pools `PhpCachePool` and `PhpCacheItem`
* Trait to help adapters to support tags. `TagSupportWithArray`.
### Changed
* First parameter to `AbstractCachePool::storeItemInCache` must be a `PhpCacheItem`.
* Return value from `AbstractCachePool::fetchObjectFromCache` must be a an array with 4 values. Added expiration timestamp.
* `HasExpirationDateInterface` is replaced by `HasExpirationTimestampInterface`
* We do not work with `\DateTime` internally anymore. We work with timestamps.
## 0.3.3
### Fixed
* Bugfix when you fetch data from the cache storage that was saved as "non-tagging item" but fetch as a tagging item.
## 0.3.2
### Added
* Cache pools do implement `LoggerAwareInterface`
## 0.3.0
### Changed
* The `AbstractCachePool` does not longer implement `TaggablePoolInterface`. However, the `CacheItem` does still implement `TaggableItemInterface`.
* `CacheItem::getKeyFromTaggedKey` has been removed
* The `CacheItem`'s second parameter is a callable that must return an array with 3 elements; [`hasValue`, `value`, `tags`].
## 0.2.0
* No changelog before this version
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
use Psr\Cache\CacheException as CacheExceptionInterface;
/**
* A base exception. All exceptions in this organization will extend this exception.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
abstract class CacheException extends \RuntimeException implements CacheExceptionInterface
{
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
/**
* If an exception is caused by a pool or by the cache storage.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class CachePoolException extends CacheException
{
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
use Psr\Cache\InvalidArgumentException as CacheInvalidArgumentException;
use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInvalidArgumentException;
class InvalidArgumentException extends CacheException implements CacheInvalidArgumentException, SimpleCacheInvalidArgumentException
{
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface HasExpirationTimestampInterface
{
/**
* The timestamp when the object expires.
*
* @return int|null
*/
public function getExpirationTimestamp();
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* This trait provides common routines for safely encoding binary and non-UTF8 data in
* JSON. This is needed for components that use JSON natively (currently, the MongoDB
* adapter and EncryptedCachePool).
*
* @author Stephen Clouse <stephen.clouse@noaa.gov>
*/
trait JsonBinaryArmoring
{
private static $ESCAPE_JSON_CHARACTERS = [
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
"\x08", "\x09", "\x0A", "\x0B", "\x0C", "\x0D", "\x0E", "\x0F",
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
"\x18", "\x19", "\x1A", "\x1B", "\x1C", "\x1D", "\x1E", "\x1F",
];
private static $ENCODED_JSON_CHARACTERS = [
'\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007',
'\u0008', '\u0009', '\u000A', '\u000B', '\u000C', '\u000D', '\u000E', '\u000F',
'\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016', '\u0017',
'\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F',
];
/**
* Armor a value going into a JSON document.
*
* @param string $value
*
* @return string
*/
protected static function jsonArmor($value)
{
return str_replace(
static::$ESCAPE_JSON_CHARACTERS,
static::$ENCODED_JSON_CHARACTERS,
utf8_encode($value)
);
}
/**
* De-armor a value from a JSON document.
*
* @param string $value
*
* @return string
*/
protected static function jsonDeArmor($value)
{
return utf8_decode(str_replace(
static::$ENCODED_JSON_CHARACTERS,
static::$ESCAPE_JSON_CHARACTERS,
$value
));
}
}
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\TagInterop\TaggableCacheItemInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface PhpCacheItem extends HasExpirationTimestampInterface, TaggableCacheItemInterface
{
/**
* Get the current tags. These are not the same tags as getPrevious tags. This
* is the tags that has been added to the item after the item was fetched from
* the cache storage.
*
* WARNING: This is generally not the function you want to use. Please see
* `getPreviousTags`.
*
* @return array
*/
public function getTags();
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\TagInterop\TaggableCacheItemPoolInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface PhpCachePool extends TaggableCacheItemPoolInterface
{
/**
* {@inheritdoc}
*
* @return PhpCacheItem
*/
public function getItem($key);
/**
* {@inheritdoc}
*
* @return array|\Traversable|PhpCacheItem[]
*/
public function getItems(array $keys = []);
}
# Common PSR-6 Cache pool
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/adapter-common/v/stable)](https://packagist.org/packages/cache/adapter-common)
[![codecov.io](https://codecov.io/github/php-cache/adapter-common/coverage.svg?branch=master)](https://codecov.io/github/php-cache/adapter-common?branch=master)
[![Total Downloads](https://poser.pugx.org/cache/adapter-common/downloads)](https://packagist.org/packages/cache/adapter-common)
[![Monthly Downloads](https://poser.pugx.org/cache/adapter-common/d/monthly.png)](https://packagist.org/packages/cache/adapter-common)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This repository contains shared classes and interfaces used by the PHP Cache organisation. To read about
features like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com).
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* This trait could be used by adapters that do not have a native support for lists.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
trait TagSupportWithArray
{
/**
* Get a value from the storage.
*
* @param string $name
*
* @return mixed
*/
abstract public function getDirectValue($name);
/**
* Set a value to the storage.
*
* @param string $name
* @param mixed $value
*/
abstract public function setDirectValue($name, $value);
/**
* {@inheritdoc}
*/
protected function appendListItem($name, $value)
{
$data = $this->getDirectValue($name);
if (!is_array($data)) {
$data = [];
}
$data[] = $value;
$this->setDirectValue($name, $data);
}
/**
* {@inheritdoc}
*/
protected function getList($name)
{
$data = $this->getDirectValue($name);
if (!is_array($data)) {
$data = [];
}
return $data;
}
/**
* {@inheritdoc}
*/
protected function removeList($name)
{
$this->setDirectValue($name, []);
return true;
}
/**
* {@inheritdoc}
*/
protected function removeListItem($name, $key)
{
$data = $this->getList($name);
foreach ($data as $i => $value) {
if ($key === $value) {
unset($data[$i]);
}
}
return $this->setDirectValue($name, $data);
}
}
{
"name": "cache/adapter-common",
"description": "Common classes for PSR-6 adapters",
"type": "library",
"license": "MIT",
"minimum-stability": "dev",
"prefer-stable": true,
"keywords": [
"cache",
"psr-6",
"tag"
],
"homepage": "http://www.php-cache.com/en/latest/",
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"require": {
"php": "^5.6 || ^7.0",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0",
"psr/log": "^1.0",
"cache/tag-interop": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.21",
"cache/integration-tests": "^0.16"
},
"autoload": {
"psr-4": {
"Cache\\Adapter\\Common\\": ""
}
},
"autoload-dev": {
"psr-4": {
"Cache\\Adapter\\Common\\Tests\\": "Tests/"
},
"exclude-from-classmap": [
"/Tests/"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\PHPArray;
use Cache\Adapter\Common\AbstractCachePool;
use Cache\Adapter\Common\CacheItem;
use Cache\Adapter\Common\PhpCacheItem;
use Cache\Hierarchy\HierarchicalCachePoolTrait;
use Cache\Hierarchy\HierarchicalPoolInterface;
/**
* Array cache pool. You could set a limit of how many items you want to be stored to avoid memory leaks.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class ArrayCachePool extends AbstractCachePool implements HierarchicalPoolInterface
{
use HierarchicalCachePoolTrait;
/**
* @type PhpCacheItem[]
*/
private $cache;
/**
* @type array
* A map to hold keys
*/
private $keyMap = [];
/**
* @type int
* The maximum number of keys in the map
*/
private $limit;
/**
* @type int
* The next key that we should remove from the cache
*/
private $currentPosition = 0;
/**
* @param int $limit the amount if items stored in the cache. Using a limit will reduce memory leaks.
* @param array $cache
*/
public function __construct($limit = null, array &$cache = [])
{
$this->cache = &$cache;
$this->limit = $limit;
}
/**
* {@inheritdoc}
*/
protected function getItemWithoutGenerateCacheKey($key)
{
if (isset($this->deferred[$key])) {
/** @type CacheItem $item */
$item = clone $this->deferred[$key];
$item->moveTagsToPrevious();
return $item;
}
return $this->fetchObjectFromCache($key);
}
/**
* {@inheritdoc}
*/
protected function fetchObjectFromCache($key)
{
$keyString = $this->getHierarchyKey($key);
if (!isset($this->cache[$keyString])) {
return [false, null, [], null];
}
list($data, $tags, $timestamp) = $this->cache[$keyString];
if (is_object($data)) {
$data = clone $data;
}
return [true, $data, $tags, $timestamp];
}
/**
* {@inheritdoc}
*/
protected function clearAllObjectsFromCache()
{
$this->cache = [];
return true;
}
/**
* {@inheritdoc}
*/
protected function clearOneObjectFromCache($key)
{
$this->commit();
$path = null;
$keyString = $this->getHierarchyKey($key, $path);
if (isset($this->cache[$path])) {
$this->cache[$path]++;
} else {
$this->cache[$path] = 0;
}
$this->clearHierarchyKeyCache();
unset($this->cache[$keyString]);
return true;
}
/**
* {@inheritdoc}
*/
protected function storeItemInCache(PhpCacheItem $item, $ttl)
{
$key = $this->getHierarchyKey($item->getKey());
$value = $item->get();
if (is_object($value)) {
$value = clone $value;
}
$this->cache[$key] = [$value, $item->getTags(), $item->getExpirationTimestamp()];
if ($this->limit !== null) {
// Remove the oldest value
if (isset($this->keyMap[$this->currentPosition])) {
unset($this->cache[$this->keyMap[$this->currentPosition]]);
}
// Add the new key to the current position
$this->keyMap[$this->currentPosition] = $key;
// Increase the current position
$this->currentPosition = ($this->currentPosition + 1) % $this->limit;
}
return true;
}
/**
* {@inheritdoc}
*/
protected function getDirectValue($key)
{
if (isset($this->cache[$key])) {
return $this->cache[$key];
}
}
/**
* {@inheritdoc}
*/
protected function getList($name)
{
if (!isset($this->cache[$name])) {
$this->cache[$name] = [];
}
return $this->cache[$name];
}
/**
* {@inheritdoc}
*/
protected function removeList($name)
{
unset($this->cache[$name]);
return true;
}
/**
* {@inheritdoc}
*/
protected function appendListItem($name, $key)
{
$this->cache[$name][] = $key;
}
/**
* {@inheritdoc}
*/
protected function removeListItem($name, $key)
{
if (isset($this->cache[$name])) {
foreach ($this->cache[$name] as $i => $item) {
if ($item === $key) {
unset($this->cache[$name][$i]);
}
}
}
}
}
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## UNRELEASED
## 1.1.0
### Fixed
* Missing tag warning fixed
## 1.0.0
### Fixed
* Fixed `$path` variable not initialized in `clearOneObjectFromCache`.
## 0.5.0
### Added
* Support for the new `TaggableCacheItemPoolInterface`.
* Support for PSR-16 SimpleCache
### Changed
* The behavior of `CacheItem::getTags()` has changed. It will not return the tags stored in the cache storage.
### Removed
* `CacheItem::getExpirationDate()`. Use `CacheItem::getExpirationTimestamp()`
* `CacheItem::getTags()`. Use `CacheItem::getPreviousTags()`
* `CacheItem::addTag()`. Use `CacheItem::setTags()`
## 0.4.2
### Changed
* Using `cache/hierarchical-cache:^0.3`
## 0.4.1
* No changelog before this version
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.
# Array PSR-6 Cache pool
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/array-adapter/v/stable)](https://packagist.org/packages/cache/array-adapter)
[![codecov.io](https://codecov.io/github/php-cache/array-adapter/coverage.svg?branch=master)](https://codecov.io/github/array-cache/apc-adapter?branch=master)
[![Total Downloads](https://poser.pugx.org/cache/array-adapter/downloads)](https://packagist.org/packages/cache/array-adapter)
[![Monthly Downloads](https://poser.pugx.org/cache/array-adapter/d/monthly.png)](https://packagist.org/packages/cache/array-adapter)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This is a PSR-6 cache implementation using PHP array. It is a part of the PHP Cache organisation. To read about
features like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com).
### Install
```bash
composer require cache/array-adapter
```
### Use
You do not need to do any configuration to use the `ArrayCachePool`.
```php
$pool = new ArrayCachePool();
```
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).
{
"name": "cache/array-adapter",
"description": "A PSR-6 cache implementation using a php array. This implementation supports tags",
"type": "library",
"license": "MIT",
"minimum-stability": "dev",
"prefer-stable": true,
"keywords": [
"cache",
"psr-6",
"array",
"tag"
],
"homepage": "http://www.php-cache.com/en/latest/",
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"require": {
"php": "^5.6 || ^7.0",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0",
"cache/adapter-common": "^1.0",
"cache/hierarchical-cache": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.21",
"cache/integration-tests": "^0.16"
},
"provide": {
"psr/cache-implementation": "^1.0",
"psr/simple-cache-implementation": "^1.0"
},
"autoload": {
"psr-4": {
"Cache\\Adapter\\PHPArray\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## UNRELEASED
## 1.0.0
No changes since 0.4.0
## 0.4.0
### Changed
* `HierarchicalCachePoolTrait::getValueFormStore` was renamed to `HierarchicalCachePoolTrait::getDirectValue`
### Removed
* Dependency to `cache/taggable-cache`.
## 0.3.0
### Changed
The `HierarchicalPoolInterface` extends `CacheItemPoolInterface`
## 0.2.1
No changelog before this version
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Hierarchy;
use Cache\Adapter\Common\AbstractCachePool;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
trait HierarchicalCachePoolTrait
{
/**
* A temporary cache for keys.
*
* @type array
*/
private $keyCache = [];
/**
* Get a value from the storage.
*
* @param string $name
*
* @return mixed
*/
abstract public function getDirectValue($name);
/**
* Get a key to use with the hierarchy. If the key does not start with HierarchicalPoolInterface::SEPARATOR
* this will return an unalterered key. This function supports a tagged key. Ie "foo:bar".
*
* @param string $key The original key
* @param string &$pathKey A cache key for the path. If this key is changed everything beyond that path is changed.
*
* @return string
*/
protected function getHierarchyKey($key, &$pathKey = null)
{
if (!$this->isHierarchyKey($key)) {
return $key;
}
$key = $this->explodeKey($key);
$keyString = '';
// The comments below is for a $key = ["foo!tagHash", "bar!tagHash"]
foreach ($key as $name) {
// 1) $keyString = "foo!tagHash"
// 2) $keyString = "foo!tagHash![foo_index]!bar!tagHash"
$keyString .= $name;
$pathKey = sha1('path'.AbstractCachePool::SEPARATOR_TAG.$keyString);
if (isset($this->keyCache[$pathKey])) {
$index = $this->keyCache[$pathKey];
} else {
$index = $this->getDirectValue($pathKey);
$this->keyCache[$pathKey] = $index;
}
// 1) $keyString = "foo!tagHash![foo_index]!"
// 2) $keyString = "foo!tagHash![foo_index]!bar!tagHash![bar_index]!"
$keyString .= AbstractCachePool::SEPARATOR_TAG.$index.AbstractCachePool::SEPARATOR_TAG;
}
// Assert: $pathKey = "path!foo!tagHash![foo_index]!bar!tagHash"
// Assert: $keyString = "foo!tagHash![foo_index]!bar!tagHash![bar_index]!"
// Make sure we do not get awfully long (>250 chars) keys
return sha1($keyString);
}
/**
* Clear the cache for the keys.
*/
protected function clearHierarchyKeyCache()
{
$this->keyCache = [];
}
/**
* A hierarchy key MUST begin with the separator.
*
* @param string $key
*
* @return bool
*/
private function isHierarchyKey($key)
{
return substr($key, 0, 1) === HierarchicalPoolInterface::HIERARCHY_SEPARATOR;
}
/**
* This will take a hierarchy key ("|foo|bar") with tags ("|foo|bar!tagHash") and return an array with
* each level in the hierarchy appended with the tags. ["foo!tagHash", "bar!tagHash"].
*
* @param string $key
*
* @return array
*/
private function explodeKey($string)
{
list($key, $tag) = explode(AbstractCachePool::SEPARATOR_TAG, $string.AbstractCachePool::SEPARATOR_TAG);
if ($key === HierarchicalPoolInterface::HIERARCHY_SEPARATOR) {
$parts = ['root'];
} else {
$parts = explode(HierarchicalPoolInterface::HIERARCHY_SEPARATOR, $key);
// remove first element since it is always empty and replace it with 'root'
$parts[0] = 'root';
}
return array_map(function ($level) use ($tag) {
return $level.AbstractCachePool::SEPARATOR_TAG.$tag;
}, $parts);
}
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Hierarchy;
use Psr\Cache\CacheItemPoolInterface;
/**
* Let you use hierarchy if you start your tag key with the HIERARCHY_SEPARATOR.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface HierarchicalPoolInterface extends CacheItemPoolInterface
{
const HIERARCHY_SEPARATOR = '|';
}
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.
# Hierarchical PSR-6 cache pool
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/hierarchical-cache/v/stable)](https://packagist.org/packages/cache/hierarchical-cache)
[![codecov.io](https://codecov.io/github/php-cache/hierarchical-cache/coverage.svg?branch=master)](https://codecov.io/github/php-cache/hierarchical-cache?branch=master)
[![Total Downloads](https://poser.pugx.org/cache/hierarchical-cache/downloads)](https://packagist.org/packages/cache/hierarchical-cache)
[![Monthly Downloads](https://poser.pugx.org/cache/hierarchical-cache/d/monthly.png)](https://packagist.org/packages/cache/hierarchical-cache)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This is an implementation for the PSR-6 for an hierarchical cache architecture.
If you have a cache key like `|users|:uid|followers|:fid|likes` where `:uid` and `:fid` are arbitrary integers. You
may flush all followers by flushing `|users|:uid|followers`.
It is a part of the PHP Cache organisation. To read about features like tagging and hierarchy support please read
the shared documentation at [www.php-cache.com](http://www.php-cache.com).
### Install
```bash
composer require cache/hierarchical-cache
```
### Use
Read the [documentation on usage](http://www.php-cache.com/en/latest/hierarchy/).
### Implement
Read the [documentation on implementation](http://www.php-cache.com/en/latest/implementing-cache-pools/hierarchy/).
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).
{
"name": "cache/hierarchical-cache",
"description": "A helper trait and interface to your PSR-6 cache to support hierarchical keys.",
"type": "library",
"license": "MIT",
"keywords": [
"cache",
"psr-6",
"hierarchy",
"hierarchical"
],
"homepage": "http://www.php-cache.com/en/latest/",
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"require": {
"php": "^5.6 || ^7.0",
"psr/cache": "^1.0",
"cache/adapter-common": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.21"
},
"autoload": {
"psr-4": {
"Cache\\Hierarchy\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}
This is a READ ONLY repository.
Please make your pull request to https://github.com/php-cache/cache
Thank you for contributing.
language: php
sudo: false
matrix:
include:
- php: 7.0
cache:
directories:
- "$HOME/.composer/cache"
install:
- composer update --prefer-dist --prefer-stable
script:
- ./vendor/bin/phpunit --coverage-clover=coverage.xml
after_success:
- pip install --user codecov && codecov
notifications:
email: false
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## 1.0.0
First release
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.
# Tag support for PSR-6 Cache
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/tag-interop/v/stable)](https://packagist.org/packages/cache/tag-interop)
[![Total Downloads](https://poser.pugx.org/cache/tag-interop/downloads)](https://packagist.org/packages/cache/tag-interop)
[![Monthly Downloads](https://poser.pugx.org/cache/tag-interop/d/monthly.png)](https://packagist.org/packages/cache/tag-interop)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This repository holds two interfaces for tagging. These interfaces will make their
way into PHP Fig. Representatives from Symfony, PHP-cache and Drupal has worked
together to agree on these interfaces.
### Install
```bash
composer require cache/tag-interop
```
### Use
Read the [documentation on usage](http://www.php-cache.com/).
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\TagInterop;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
/**
* An item that supports tags. This interface is a soon-to-be-PSR.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
interface TaggableCacheItemInterface extends CacheItemInterface
{
/**
* Get all existing tags. These are the tags the item has when the item is
* returned from the pool.
*
* @return array
*/
public function getPreviousTags();
/**
* Overwrite all tags with a new set of tags.
*
* @param string[] $tags An array of tags
*
* @throws InvalidArgumentException When a tag is not valid.
*
* @return TaggableCacheItemInterface
*/
public function setTags(array $tags);
}
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\TagInterop;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
/**
* Interface for invalidating cached items using tags. This interface is a soon-to-be-PSR.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
interface TaggableCacheItemPoolInterface extends CacheItemPoolInterface
{
/**
* Invalidates cached items using a tag.
*
* @param string $tag The tag to invalidate
*
* @throws InvalidArgumentException When $tags is not valid
*
* @return bool True on success
*/
public function invalidateTag($tag);
/**
* Invalidates cached items using tags.
*
* @param string[] $tags An array of tags to invalidate
*
* @throws InvalidArgumentException When $tags is not valid
*
* @return bool True on success
*/
public function invalidateTags(array $tags);
/**
* {@inheritdoc}
*
* @return TaggableCacheItemInterface
*/
public function getItem($key);
/**
* {@inheritdoc}
*
* @return array|\Traversable|TaggableCacheItemInterface[]
*/
public function getItems(array $keys = []);
}
{
"name": "cache/tag-interop",
"type": "library",
"description": "Framework interoperable interfaces for tags",
"keywords": [
"cache",
"psr6",
"tag",
"psr"
],
"homepage": "http://www.php-cache.com/en/latest/",
"license": "MIT",
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
},
{
"name": "Nicolas Grekas ",
"email": "p@tchwork.com",
"homepage": "https://github.com/nicolas-grekas"
}
],
"require": {
"php": "^5.5 || ^7.0",
"psr/cache": "^1.0"
},
"autoload": {
"psr-4": {
"Cache\\TagInterop\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
}
}
......@@ -16,6 +16,7 @@ return array(
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => $vendorDir . '/laravel/lumen-framework/src/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
'f4e9c7747917193061b46ee142399603' => $vendorDir . '/dingo/api/src/helpers.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'f960e77410032f236cef8c56617b313e' => $vendorDir . '/overtrue/laravel-lang/src/helpers.php',
......
......@@ -14,8 +14,11 @@ return array(
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\Inflector\\' => array($vendorDir . '/symfony/inflector'),
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
......@@ -27,15 +30,20 @@ return array(
'Spatie\\ArrayToXml\\' => array($vendorDir . '/spatie/array-to-xml/src'),
'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'PhpAmqpLib\\' => array($vendorDir . '/php-amqplib/php-amqplib/PhpAmqpLib'),
'Overtrue\\LaravelLang\\' => array($vendorDir . '/overtrue/laravel-lang/src'),
'Namshi\\JOSE\\' => array($vendorDir . '/namshi/jose/src/Namshi/JOSE'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'Lib\\' => array($baseDir . '/Lib'),
'League\\Geotools\\Tests\\' => array($vendorDir . '/league/geotools/tests'),
'League\\Geotools\\' => array($vendorDir . '/league/geotools/src'),
'League\\Fractal\\' => array($vendorDir . '/league/fractal/src'),
'Lcobucci\\JWT\\' => array($vendorDir . '/lcobucci/jwt/src'),
'Laravel\\Lumen\\' => array($vendorDir . '/laravel/lumen-framework/src'),
......@@ -64,9 +72,11 @@ return array(
'Illuminate\\Bus\\' => array($vendorDir . '/illuminate/bus'),
'Illuminate\\Broadcasting\\' => array($vendorDir . '/illuminate/broadcasting'),
'Illuminate\\Auth\\' => array($vendorDir . '/illuminate/auth'),
'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Geocoder\\' => array($vendorDir . '/willdurand/geocoder'),
'Flc\\Dysms\\' => array($vendorDir . '/flc/dysms/src'),
'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
......@@ -83,6 +93,10 @@ return array(
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Composer\\' => array($vendorDir . '/composer/composer/src/Composer'),
'Cache\\TagInterop\\' => array($vendorDir . '/cache/tag-interop'),
'Cache\\Hierarchy\\' => array($vendorDir . '/cache/hierarchical-cache'),
'Cache\\Adapter\\PHPArray\\' => array($vendorDir . '/cache/array-adapter'),
'Cache\\Adapter\\Common\\' => array($vendorDir . '/cache/adapter-common'),
'Bschmitt\\Amqp\\Test\\' => array($vendorDir . '/bschmitt/laravel-amqp/test'),
'Bschmitt\\Amqp\\' => array($vendorDir . '/bschmitt/laravel-amqp/src'),
'Barryvdh\\LaravelIdeHelper\\' => array($vendorDir . '/barryvdh/laravel-ide-helper/src'),
......
......@@ -17,6 +17,7 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => __DIR__ . '/..' . '/laravel/lumen-framework/src/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
'f4e9c7747917193061b46ee142399603' => __DIR__ . '/..' . '/dingo/api/src/helpers.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'f960e77410032f236cef8c56617b313e' => __DIR__ . '/..' . '/overtrue/laravel-lang/src/helpers.php',
......@@ -42,8 +43,11 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\Serializer\\' => 29,
'Symfony\\Component\\Routing\\' => 26,
'Symfony\\Component\\PropertyAccess\\' => 33,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\Inflector\\' => 28,
'Symfony\\Component\\HttpKernel\\' => 29,
'Symfony\\Component\\HttpFoundation\\' => 33,
'Symfony\\Component\\Finder\\' => 25,
......@@ -56,12 +60,18 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'Seld\\PharUtils\\' => 15,
'Seld\\JsonLint\\' => 14,
),
'R' =>
array (
'React\\Promise\\' => 14,
'React\\EventLoop\\' => 16,
),
'P' =>
array (
'Psr\\SimpleCache\\' => 16,
'Psr\\Log\\' => 8,
'Psr\\Http\\Message\\' => 17,
'Psr\\Container\\' => 14,
'Psr\\Cache\\' => 10,
'PhpAmqpLib\\' => 11,
),
'O' =>
......@@ -79,6 +89,8 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'L' =>
array (
'Lib\\' => 4,
'League\\Geotools\\Tests\\' => 22,
'League\\Geotools\\' => 16,
'League\\Fractal\\' => 15,
'Lcobucci\\JWT\\' => 13,
'Laravel\\Lumen\\' => 14,
......@@ -114,11 +126,16 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'Illuminate\\Broadcasting\\' => 24,
'Illuminate\\Auth\\' => 16,
),
'H' =>
array (
'Http\\Discovery\\' => 15,
),
'G' =>
array (
'GuzzleHttp\\Psr7\\' => 16,
'GuzzleHttp\\Promise\\' => 19,
'GuzzleHttp\\' => 11,
'Geocoder\\' => 9,
),
'F' =>
array (
......@@ -144,6 +161,10 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'Composer\\Semver\\' => 16,
'Composer\\CaBundle\\' => 18,
'Composer\\' => 9,
'Cache\\TagInterop\\' => 17,
'Cache\\Hierarchy\\' => 16,
'Cache\\Adapter\\PHPArray\\' => 23,
'Cache\\Adapter\\Common\\' => 21,
),
'B' =>
array (
......@@ -192,14 +213,26 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/symfony/translation',
),
'Symfony\\Component\\Serializer\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/serializer',
),
'Symfony\\Component\\Routing\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/routing',
),
'Symfony\\Component\\PropertyAccess\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/property-access',
),
'Symfony\\Component\\Process\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/process',
),
'Symfony\\Component\\Inflector\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/inflector',
),
'Symfony\\Component\\HttpKernel\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/http-kernel',
......@@ -244,6 +277,14 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
),
'React\\Promise\\' =>
array (
0 => __DIR__ . '/..' . '/react/promise/src',
),
'React\\EventLoop\\' =>
array (
0 => __DIR__ . '/..' . '/react/event-loop/src',
),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
......@@ -260,6 +301,10 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'Psr\\Cache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/cache/src',
),
'PhpAmqpLib\\' =>
array (
0 => __DIR__ . '/..' . '/php-amqplib/php-amqplib/PhpAmqpLib',
......@@ -280,6 +325,14 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/../..' . '/Lib',
),
'League\\Geotools\\Tests\\' =>
array (
0 => __DIR__ . '/..' . '/league/geotools/tests',
),
'League\\Geotools\\' =>
array (
0 => __DIR__ . '/..' . '/league/geotools/src',
),
'League\\Fractal\\' =>
array (
0 => __DIR__ . '/..' . '/league/fractal/src',
......@@ -392,6 +445,10 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/illuminate/auth',
),
'Http\\Discovery\\' =>
array (
0 => __DIR__ . '/..' . '/php-http/discovery/src',
),
'GuzzleHttp\\Psr7\\' =>
array (
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
......@@ -404,6 +461,10 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
),
'Geocoder\\' =>
array (
0 => __DIR__ . '/..' . '/willdurand/geocoder',
),
'Flc\\Dysms\\' =>
array (
0 => __DIR__ . '/..' . '/flc/dysms/src',
......@@ -468,6 +529,22 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/composer/composer/src/Composer',
),
'Cache\\TagInterop\\' =>
array (
0 => __DIR__ . '/..' . '/cache/tag-interop',
),
'Cache\\Hierarchy\\' =>
array (
0 => __DIR__ . '/..' . '/cache/hierarchical-cache',
),
'Cache\\Adapter\\PHPArray\\' =>
array (
0 => __DIR__ . '/..' . '/cache/array-adapter',
),
'Cache\\Adapter\\Common\\' =>
array (
0 => __DIR__ . '/..' . '/cache/adapter-common',
),
'Bschmitt\\Amqp\\Test\\' =>
array (
0 => __DIR__ . '/..' . '/bschmitt/laravel-amqp/test',
......
tests export-ignore
.scrutinizer.yml export-ignore
.travis.yml export-ignore
vendor/
composer.lock
composer.phar
phpunit.xml
php-cs-fixer.phar
CHANGELOG
=========
0.8.0 (2018-02-22)
-----------------
### Added
- We use `willdurand/geocoder` 4.
- Add a method to vertex to compute the determinant with another vertex
- `ArrayCollection::merge`
- `BoundingBox::merge`
- `BoundingBoxInterface::merge`
- `BoundingBoxInterface::getAsPolygon`
- Added abstract class `GeometryCollection`
- Added `GeometryInterface`
- Added `MultiPolygon`
### Changes
- Renamed `BoundingBox::getPolygon` to `BoundingBox::getAsPolygon`
- `PolygonInterface` extends `GeometryInterface`
### Fixed
- Decimal-Degrees parser from Decimal-Minutes
### Removed
- Removed `AbstractGeotools` class in favor of `CoordinateCouple`. Also added constants to `GeotoolsInterface`.
- Our HTTP layer in favor of HTTPlug
- Our cache layer in favor of PSR-6
0.7.0 (2016-02-03)
------------------
* Updated: `Point` is now `Vertex` [BC break]
* Updated: use `Predis` 1.0 version
* Updated: tests against PHP7
* Updated: documentation and badges
* Added: allow Symfony console, property-access and serializer ~3.0
0.6.0 (2015-10-11)
------------------
* Fixed: cache layer: Redis, Memcached and MongoDB
* Added: cache possibility in CLI
* Added: 10:10 algorithm
* Updated: symfony console, serializer and property-access to ~2.7
0.5.0 (2015-10-10)
------------------
* Updated: use Geocoder 3.2.x
* Added: Polygon class
* Added: Bounding box class
* Fixed: division by zero in vincenty algorithm
* Dropped: PHP 5.3 and stub to JsonSerializable
* Updated: switch from async to promise
* Updated: documentation
* Added: code of conduct
0.4.0 (2014-07-30)
------------------
* Uses: PSR-4
* Removed: not relevant autoloads
* Fixed: tests
* Fixed: typos
0.3.3 (2014-05-16)
------------------
* Fixed: HHVM compatible tested on `HipHop VM 3.1.0-dev+2014.05.15`
* Added: falling tests in Distance with same coordinates (@kornrunner)
* Fixed: division by zero in computing distance between 2 identical coordinates (@kornrunner)
* Added: `setFromString` method to create and modify coordinate + doc - fix #31
* Fixed: coordinate parsing issue
0.3.2 (2014-03-15)
------------------
* Updated: geotools CLI moved in bin folder
* Updated: use Geocoder 2.4.x
* Added: great circle formula and CLI + tests
* Added: test against php 5.6
* Updated: repo name
* Added: coverage and scrutinizer-ci badges
* Updated: organisation name
* Added: test against HHVM
0.3.1 (2013-11-16)
------------------
* Updated: use Geocoder 2.3.x
* Updated: use SensioLabs Insight
* Updated: documentation
* Fixed: travis, packagist and sensiolabs insight badges
* Fixed: tests
0.3.0 (2013-07-19)
------------------
* Updated: loep (The League of Extraordinary Packages) is now owner
* Updated: use Geocoder 2.0.0
0.2.4 (2013-05-03)
------------------
* Updated: made it working with Geocoder 1.5.0
* Updated: integration with frameworks in features list
* Added: integration with Silex
* Added: integration with frameworks
* Updated: Contribution doc
* Added: memcached and mongo extensions to travis-ci
* Added: mongodb service to travis-ci
* Added: expire to Memcached cache - fix #26
* Added: expire to Redis cache + test - fix #26
0.2.3 (2013-03-29)
------------------
* Updated: MongoDB test coverage
* Added: Memcached cache test - fix #22
* Refactored: Redis and MongoDB caches tests
* Added: MongoDB cache test - fix #22
* Added: Redis cache test - fix #22
* Added: Memcached cache - fix #24
0.2.2 (2013-03-26)
------------------
* Added: Redis cache - fix #23
* Updated: MongoDB cache search by key
* Fixed: MangoDB cache
* Updated: doc with try .. catch bloc
* Fixed: Batch test for php 5.3
* Added: Cache interface + mongoDB - fix #2
* Refactored: Point test
0.2.1 (2013-03-16)
------------------
* Added: arcgis_online provider
* Merge branch 'BatchImproved'
* Fixed: batched result object embed provider's name, query and exception string - fix #6
* Added: Geocoder dev-master as require-dev
* Fixed: CLI tests
0.2.0 (2013-03-12)
------------------
* Fixed: empty ellipsoid name throws an exception now
* Added: Ellipsoid support to Point, Convert and Distance CLI - fix #7
* Added: Ellipsoid support to Point CLI
* Added: Ellipsoid support to Distance CLI
* Added: Ellipsoid support to Convert CLI
* Added: TomTom provier to CLI - fix #14
* Changed: mile parameter to mi in Distance to be more consistent [BC break]
0.1.12 (2013-03-08)
-------------------
* Added: command exemples and refactoring
* Added: help to geocoding and reverse geocoding CLI
* Fixed: homepage in composer.json
* Updated: doc and composer.json
* Fixed: php warning in CLI on wrong providers constuction arguments
* Updated: list of contributors
* Updated: geohash doc
0.1.11 (2013-03-05)
-------------------
* Added: international feet unit to CLI + test - fix #10
* Updated: relative links to absolute ones
* Added: ip_geo_base and baidu as CLI providers - fix #8
* Fixed: feet unit + test
* Added International Feet as a unit
* Added a bunch of tests.
0.1.10 (2013-02-27)
-------------------
* Added: support of different ellipsoid + doc + tests - fix #5
* Refactored: Doc + CLI commands + tests
* Improved: geocoder:geocode and geocoder:reverse CLI + tests
* Added: lowerize() method using mbstring extension
0.1.9 (2013-02-24)
------------------
* Added: dumper option to geocoder:geocode CLI + test
* Fixed: composer.json
* Added: cURL requirement for tests and CLI
* Removed: old files
* Fixed: finalCardinal() into CLI + test
0.1.8 (2013-02-21)
------------------
* Refactored: getAdapter and getProvider in CLI
* Added: CLI for Geocoder class + tests
* Added: CLI for Geocoder class + tests
* Updated: composer installation info
* Added: logo to CLI
* Fixed: travis-ci config
* Added: finalBearing() to CLI + test
* Added: finalCardinal() method + test
* Updated: cardinal() method to initialCardinal() [BC break]
* Added: finalBearing() + test
* Renamed: bearing() method to initialBearing() [BC break]
0.1.7 (2013-02-20)
------------------
* Added: CLI for Convert class + tests
* Added: CLI for Geohash class + tests
* Updated: doc with internal links
* Fixed: CLI include paths
0.1.6 (2013-02-20)
------------------
* Added: CLI for Distance and Point classes + tests
* Updated: phpunit bootstrap
* Updated: composer installation info
* Updated: Convert UTM zone exceptions are covered
* Updated: Point and Distance chainable logic and refactoring [BC break]
* Added: UTM conversion + tests + doc
* Updated: geodetic datum into doc
0.1.5 (2013-02-13)
------------------
* Added: Convert class, tests and doc
* Updated: doc about Coordinate class
* Updated: method visibility in Coordinate class
* Added: Coordinate class support different DMS coordinates
* Fixed: thrown message on invalid coordinate
* Fixed: typo calculate to compute
0.1.4 (2013-02-10)
------------------
* Updated: Batch class test
* Added: test to AbstractGeotools class
* Refactored: Batch tests
* Updated: doc with a better batch exemple
* Added: batch a set of values/coordinates againt a set of providers + tests
* Fixed: changelog list
0.1.3 (2013-02-09)
------------------
* Added: geohash ref to the doc
* Refactored: tests
* Added: Geohash class, tests and doc
* Added: normalize methods to Coordinate class
* Updated: Coordinate support string in its constructor
* Updated: Testcase's expects methods
* Updated: test to Batch class
* Refactored: Batch test class
* Updated: TestCase stub clases
0.1.2 (2013-02-08)
------------------
* Fixed: test to be compatible with PHP 5.3.x
* Added: test to Distance class
* Added: test to Batch class
* Added: test to Point class
* Updated: test to Getools class with a CoordinateInterface stub
* Updated: Contributing doc
* Updated: test to Geotools class
* Added: test to Coordinate class
* Added: test to Geotools class
0.1.1 (2013-02-06)
------------------
* Fixed: the minimum-stability of React/Async
0.1.0 (2013-02-06)
------------------
* Added: Contributing doc
* Added: Travis-ci to the doc
* Added: stillmaintained.com to the doc
* Initial import
CONTRIBUTING
============
Contributions are **welcome** and be fully **credited** <3
**Geotools** will use the [Symfony2 Coding Standard](http://symfony.com/doc/current/contributing/code/standards.html).
The easiest way to apply these conventions is to install [PHP_CodeSniffer](http://pear.php.net/package/PHP_CodeSniffer)
and the [Opensky Symfony2 Coding Standard](https://github.com/opensky/Symfony2-coding-standard).
You may be interested in [PHP Coding Standards Fixer](https://github.com/fabpot/PHP-CS-Fixer).
Installation
------------
``` bash
$ pear install PHP_CodeSniffer
$ cd `pear config-get php_dir`/PHP/CodeSniffer/Standards
$ git clone git://github.com/opensky/Symfony2-coding-standard.git Symfony2
$ phpcs --config-set default_standard Symfony2
```
Usage
-----
``` bash
$ phpcs src/
```
**Happy coding** !
Copyright (c) 2013 Antoine Corcy <contact@sbin.dk>
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.
#!/usr/bin/env php
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
function includeIfExists($file)
{
if (file_exists($file)) {
return include $file;
}
}
if (!extension_loaded('curl') || !function_exists('curl_init')) {
die(<<<EOT
cURL has to be enabled!
EOT
);
}
if ((!$loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) &&
(!$loader = includeIfExists(__DIR__ . '/../../../autoload.php'))) {
die(<<<EOT
You must set up the project dependencies, run the following commands:
$ wget http://getcomposer.org/composer.phar
OR
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar install --dev
EOT
);
}
use League\Geotools\CLI\Application;
use League\Geotools\CLI\Command\Convert;
use League\Geotools\CLI\Command\Distance;
use League\Geotools\CLI\Command\Geocoder;
use League\Geotools\CLI\Command\Geohash;
use League\Geotools\CLI\Command\Vertex;
use League\Geotools\Geotools;
$geotools = new Geotools;
$console = new Application;
$console->setName('Geotools :: Geo-related tools PHP 5.3+ library');
$console->setVersion($geotools::VERSION);
$console->add(new Convert\DM);
$console->add(new Convert\DMS);
$console->add(new Convert\UTM);
$console->add(new Distance\All);
$console->add(new Distance\Flat);
$console->add(new Distance\GreatCircle);
$console->add(new Distance\Haversine);
$console->add(new Distance\Vincenty);
$console->add(new Geocoder\Geocode);
$console->add(new Geocoder\Reverse);
$console->add(new Geohash\Decode);
$console->add(new Geohash\Encode);
$console->add(new Vertex\Destination);
$console->add(new Vertex\FinalBearing);
$console->add(new Vertex\FinalCardinal);
$console->add(new Vertex\InitialBearing);
$console->add(new Vertex\InitialCardinal);
$console->add(new Vertex\Middle);
$console->run();
{
"name" : "league/geotools",
"type" : "library",
"description" : "Geo-related tools PHP 7.0+ library",
"keywords" : ["geotools", "geometry", "geocoder", "geocoding", "geoip", "bounds", "distance", "batch", "async"],
"homepage" : "http://geotools-php.org/",
"license" : "MIT",
"authors" : [{
"name" : "Antoine Corcy",
"email" : "contact@sbin.dk",
"homepage" : "http://sbin.dk",
"role" : "Developer"
}],
"support" : {
"email" : "support@geotools-php.org",
"issues" : "https://github.com/thephpleague/geotools/issues",
"source" : "https://github.com/thephpleague/geotools"
},
"replace" : {
"toin0u/geotools" : "*"
},
"require" : {
"php" : "^7.0",
"psr/cache" : "^1.0",
"willdurand/geocoder" : "^4.2",
"react/promise" : "^2.2",
"symfony/console" : "^2.7 || ^3.0 || ^4.0",
"symfony/property-access" : "^2.7 || ^3.0 || ^4.0",
"symfony/serializer" : "^2.7 || ^3.0 || ^4.0",
"react/event-loop" : "0.4.*",
"php-http/discovery" : "^1.0",
"cache/array-adapter" : "^1.0"
},
"require-dev" : {
"phpunit/phpunit" : "^6.5.5 || ^7.0"
},
"autoload" : {
"psr-4" : {
"League\\Geotools\\" : "src",
"League\\Geotools\\Tests\\" : "tests"
}
},
"bin" : ["bin/geotools"],
"extra" : {
"branch-alias" : {
"dev-master" : "0.7-dev"
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php"
>
<testsuites>
<testsuite name="Geotools Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
</whitelist>
</filter>
</phpunit>
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools;
/**
* @author Gabriel Bull <me@gabrielbull.com>
*/
class ArrayCollection implements \Countable, \IteratorAggregate, \ArrayAccess, \JsonSerializable
{
/**
* @var array
*/
protected $elements;
/**
* @param array $elements
*/
public function __construct(array $elements = array())
{
$this->elements = $elements;
}
/**
* @return array
*/
public function toArray()
{
return $this->elements;
}
/**
* {@inheritDoc}
*/
public function jsonSerialize()
{
return $this->elements;
}
/**
* {@inheritDoc}
*/
public function offsetExists($offset)
{
return isset($this->elements[$offset]) || array_key_exists($offset, $this->elements);
}
/**
* {@inheritDoc}
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* {@inheritDoc}
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}
/**
* {@inheritDoc}
*/
public function offsetUnset($offset)
{
return $this->remove($offset);
}
/**
* {@inheritDoc}
*/
public function count()
{
return count($this->elements);
}
/**
* {@inheritDoc}
*/
public function getIterator()
{
return new \ArrayIterator($this->elements);
}
/**
* @param string $key
* @return null|mixed
*/
public function get($key)
{
if (isset($this->elements[$key])) {
return $this->elements[$key];
}
return null;
}
/**
* @param string $key
* @param mixed $value
*/
public function set($key, $value)
{
$this->elements[$key] = $value;
}
/**
* @param mixed $value
* @return bool
*/
public function add($value)
{
$this->elements[] = $value;
return true;
}
/**
* @param string $key
* @return null|mixed
*/
public function remove($key)
{
if (isset($this->elements[$key]) || array_key_exists($key, $this->elements)) {
$removed = $this->elements[$key];
unset($this->elements[$key]);
return $removed;
}
return null;
}
/**
* @param ArrayCollection $collection
* @return ArrayCollection
*/
public function merge(ArrayCollection $collection)
{
$merged = clone $this;
foreach ($collection as $key => $element) {
if (is_int($key)) {
$merged->add($element);
} else {
$merged->set($key, $element);
}
}
return $merged;
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\Batch;
use Geocoder\Location;
use Geocoder\Model\Address;
use Geocoder\Model\Coordinates;
/**
* BatchGeocoded class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class BatchGeocoded
{
/**
* The name of the provider.
*
* @var string
*/
protected $providerName;
/**
* The query.
*
* @var string
*/
protected $query;
/**
* The exception message.
*
* @var string
*/
protected $exception;
/**
* The Location object.
*
* @var Location
*/
protected $address;
/**
* Get the name of the provider.
*
* @return string The name of the provider.
*/
public function getProviderName()
{
return $this->providerName;
}
/**
* Set the name of the provider.
*
* @param string $providerName The name of the provider.
*/
public function setProviderName($providerName)
{
$this->providerName = $providerName;
}
/**
* Get the query.
*
* @return string The query.
*/
public function getQuery()
{
return $this->query;
}
/**
* Set the query.
*
* @param string $query The query.
*/
public function setQuery($query)
{
$this->query = $query;
}
/**
* Get the exception message.
*
* @return string The exception message.
*/
public function getExceptionMessage()
{
return $this->exception;
}
/**
* Set the exception message.
*
* @param string $exception The exception message.
*/
public function setExceptionMessage($exception)
{
$this->exception = $exception;
}
/**
* Get the address
*
* @return Location
*/
public function getAddress()
{
return $this->address;
}
/**
* Set the address
*
* @param Location $address
*/
public function setAddress($address)
{
$this->address = $address;
}
/**
* Returns an array of coordinates (latitude, longitude).
*
* @return Coordinates|null
*/
public function getCoordinates()
{
if (null === $this->address) {
return null;
}
return $this->address->getCoordinates();
}
/**
* Returns the latitude value.
*
* @return double
*/
public function getLatitude()
{
if (null === $coordinates = $this->getCoordinates()) {
return null;
}
return $coordinates->getLatitude();
}
/**
* Returns the longitude value.
*
* @return double
*/
public function getLongitude()
{
if (null === $coordinates = $this->getCoordinates()) {
return null;
}
return $coordinates->getLongitude();
}
/**
* Create an instance from an array, used from cache libraries.
*
* @param array $data
*/
public function fromArray(array $data = [])
{
if (isset($data['providerName'])) {
$this->providerName = $data['providerName'];
}
if (isset($data['query'])) {
$this->query = $data['query'];
}
if (isset($data['exception'])) {
$this->exception = $data['exception'];
}
//GeoCoder Address::createFromArray expects longitude/latitude keys
$data['address']['longitude'] = $data['address']['coordinates']['longitude'] ?? null;
$data['address']['latitude'] = $data['address']['coordinates']['latitude'] ?? null;
// Shortcut to create the address and set it in this class
$this->setAddress(Address::createFromArray($data['address']));
}
/**
* Router all other methods call directly to our address object
*
* @param $method
* @param $args
* @return mixed
*/
public function __call($method, $args)
{
if (null === $this->address) {
return null;
}
return call_user_func_array([$this->address, $method], $args);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\Batch;
use Geocoder\Collection;
use League\Geotools\Exception\InvalidArgumentException;
use Psr\Cache\CacheItemPoolInterface;
/**
* Batch interface
*
* @author Antoine Corcy <contact@sbin.dk>
*/
interface BatchInterface
{
/**
* Set an array of closures to geocode.
* If a provider throws an exception it will return an empty AddressCollection.
*
* @param string|array $values A value or an array of values to geocode.
*
* @return BatchInterface
*
* @throws InvalidArgumentException
*/
public function geocode($values);
/**
* Set an array of closures to reverse geocode.
* If a provider throws an exception it will return an empty AddressCollection.
*
* @param \League\Geotools\Coordinate\CoordinateInterface|array $coordinates A coordinate or an array of coordinates to reverse.
*
* @return BatchInterface
*
* @throws InvalidArgumentException
*/
public function reverse($coordinates);
/**
* Returns an array of AddressCollection processed in serie.
*
* @return Collection[]
*
* @throws \Exception
*/
public function serie();
/**
* Returns an array of AddressCollection processed in parallel.
*
* @return Collection[]
*
* @throws \Exception
*/
public function parallel();
/**
* Set the cache object to use.
*
* @param CacheItemPoolInterface $cache The cache object to use.
*
* @return BatchInterface
*/
public function setCache(CacheItemPoolInterface $cache);
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\Batch;
use Geocoder\Location;
/**
* BatchResult class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class BatchResult
{
/**
* The name of the provider.
*
* @var string
*/
protected $providerName;
/**
* The query.
*
* @var string
*/
protected $query;
/**
* The exception message.
*
* @var string
*/
protected $exception;
/**
* Construct a Geocoded object with the provider name, its query and exception if any.
*
* @param string $providerName The name of the provider.
* @param string $query The query.
* @param string $exception The exception message if any.
*/
public function __construct($providerName, $query, $exception = '')
{
$this->providerName = $providerName;
$this->query = $query;
$this->exception = $exception;
}
/**
* {@inheritDoc}
*/
public function createFromAddress(Location $address)
{
$result = $this->newInstance();
$result->setAddress($address);
return $result;
}
/**
* {@inheritDoc}
*/
public function newInstance()
{
$batchGeocoded = new BatchGeocoded;
$batchGeocoded->setProviderName($this->providerName);
$batchGeocoded->setQuery($this->query);
$batchGeocoded->setExceptionMessage($this->exception);
return $batchGeocoded;
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\BoundingBox;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\CoordinateCollection;
use League\Geotools\Coordinate\CoordinateInterface;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Exception\InvalidArgumentException;
use League\Geotools\Polygon\Polygon;
use League\Geotools\Polygon\PolygonInterface;
/**
* @author Gabriel Bull <me@gabrielbull.com>
*/
class BoundingBox implements BoundingBoxInterface
{
/**
* The latitude of the north coordinate
*
* @var float|string|integer
*/
private $north;
/**
* The longitude of the east coordinate
*
* @var float|string|integer
*/
private $east;
/**
* The latitude of the south coordinate
*
* @var float|string|integer
*/
private $south;
/**
* The longitude of the west coordinate
*
* @var float|string|integer
*/
private $west;
/**
* @var boolean
*/
private $hasCoordinate = false;
/**
* @var Ellipsoid
*/
private $ellipsoid;
/**
* @var integer
*/
private $precision = 8;
/**
* @param PolygonInterface|CoordinateInterface $object
*/
public function __construct($object = null)
{
if ($object instanceof PolygonInterface) {
$this->setPolygon($object);
} elseif ($object instanceof CoordinateInterface) {
$this->addCoordinate($object);
} elseif (null !== $object) {
throw new \InvalidArgumentException;
}
}
private function createBoundingBoxForPolygon(PolygonInterface $polygon)
{
$this->hasCoordinate = false;
$this->west = $this->east = $this->north = $this->south = null;
foreach ($polygon->getCoordinates() as $coordinate) {
$this->addCoordinate($coordinate);
}
}
/**
* @param CoordinateInterface $coordinate
*/
private function addCoordinate(CoordinateInterface $coordinate)
{
if ($this->ellipsoid === null) {
$this->ellipsoid = $coordinate->getEllipsoid();
} elseif ($this->ellipsoid != $coordinate->getEllipsoid()) {
throw new InvalidArgumentException("Ellipsoids don't match");
}
$latitude = $coordinate->getLatitude();
$longitude = $coordinate->getLongitude();
if (!$this->hasCoordinate) {
$this->setNorth($latitude);
$this->setSouth($latitude);
$this->setEast($longitude);
$this->setWest($longitude);
} else {
if (bccomp($latitude, $this->getSouth(), $this->getPrecision()) === -1) {
$this->setSouth($latitude);
}
if (bccomp($latitude, $this->getNorth(), $this->getPrecision()) === 1) {
$this->setNorth($latitude);
}
if (bccomp($longitude, $this->getEast(), $this->getPrecision()) === 1) {
$this->setEast($longitude);
}
if (bccomp($longitude, $this->getWest(), $this->getPrecision()) === -1) {
$this->setWest($longitude);
}
}
$this->hasCoordinate = true;
}
/**
* @param CoordinateInterface $coordinate
* @return bool
*/
public function pointInBoundingBox(CoordinateInterface $coordinate)
{
if (bccomp($coordinate->getLatitude(), $this->getSouth(), $this->getPrecision()) === -1 ||
bccomp($coordinate->getLatitude(), $this->getNorth(), $this->getPrecision()) === 1 ||
bccomp($coordinate->getLongitude(), $this->getEast(), $this->getPrecision()) === 1 ||
bccomp($coordinate->getLongitude(), $this->getWest(), $this->getPrecision()) === -1
) {
return false;
}
return true;
}
/**
* @return PolygonInterface
*/
public function getAsPolygon()
{
if (!$this->hasCoordinate) {
return null;
}
$nw = new Coordinate(array($this->north, $this->west), $this->ellipsoid);
return new Polygon(
new CoordinateCollection(
array(
$nw,
new Coordinate(array($this->north, $this->east), $this->ellipsoid),
new Coordinate(array($this->south, $this->east), $this->ellipsoid),
new Coordinate(array($this->south, $this->west), $this->ellipsoid),
$nw
),
$this->ellipsoid
)
);
}
/**
* @param PolygonInterface $polygon
* @return $this
*/
public function setPolygon(PolygonInterface $polygon)
{
$this->createBoundingBoxForPolygon($polygon);
return $this;
}
/**
* {@inheritDoc}
*/
public function getNorth()
{
return $this->north;
}
/**
* @param float|string|integer $north
* @return $this
*/
public function setNorth($north)
{
$this->north = $north;
return $this;
}
/**
* {@inheritDoc}
*/
public function getEast()
{
return $this->east;
}
/**
* @param float|string|integer $east
* @return $this
*/
public function setEast($east)
{
$this->east = $east;
return $this;
}
/**
* {@inheritDoc}
*/
public function getSouth()
{
return $this->south;
}
/**
* @param float|string|integer $south
* @return $this
*/
public function setSouth($south)
{
$this->south = $south;
return $this;
}
/**
* {@inheritDoc}
*/
public function getWest()
{
return $this->west;
}
/**
* @param float|string|integer $west
* @return $this
*/
public function setWest($west)
{
$this->west = $west;
return $this;
}
/**
* @return integer
*/
public function getPrecision()
{
return $this->precision;
}
/**
* @param integer $precision
* @return $this
*/
public function setPrecision($precision)
{
$this->precision = $precision;
return $this;
}
/**
* @param BoundingBoxInterface $boundingBox
* @return BoundingBoxInterface
*/
public function merge(BoundingBoxInterface $boundingBox)
{
$bbox = clone $this;
$newCoordinates = $boundingBox->getAsPolygon()->getCoordinates();
foreach ($newCoordinates as $coordinate) {
$bbox->addCoordinate($coordinate);
}
return $bbox;
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\BoundingBox;
use League\Geotools\Polygon\PolygonInterface;
/**
* @author Gabriel Bull <me@gabrielbull.com>
*/
interface BoundingBoxInterface
{
/**
* @return float|string|integer
*/
public function getNorth();
/**
* @return float|string|integer
*/
public function getEast();
/**
* @return float|string|integer
*/
public function getSouth();
/**
* @return float|string|integer
*/
public function getWest();
/**
* @return PolygonInterface
*/
public function getAsPolygon();
/**
* @param BoundingBoxInterface $boundingBox
* @return BoundingBoxInterface
*/
public function merge(BoundingBoxInterface $boundingBox);
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI;
use League\Geotools\CLI\Output\ConsoleOutput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Antoine Corcy <contact@sbin.dk>
*/
class Application extends \Symfony\Component\Console\Application
{
/**
* @var string
*/
private $logo = '
________ __ .__
/ _____/ ____ _____/ |_ ____ ____ | | ______
/ \ ____/ __ \/ _ \ __\/ _ \ / _ \| | / ___/
\ \_\ \ ___( <_> ) | ( <_> | <_> ) |__\___ \
\______ /\___ >____/|__| \____/ \____/|____/____ >
\/ \/ \/
';
/**
* {@inheritdoc}
*/
public function getHelp()
{
return $this->logo . parent::getHelp();
}
/**
* {@inheritdoc}
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
parent::run($input, new ConsoleOutput);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Convert;
use League\Geotools\Convert\ConvertInterface;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line convert:dm class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class DM extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('convert:dm')
->setDescription('Convert and format decimal degrees coordinates to decimal minutes coordinate')
->addArgument('coordinate', InputArgument::REQUIRED, 'The "Lat,Long" coordinate')
->addOption('format', null, InputOption::VALUE_REQUIRED,
'If set, the format of the converted decimal minutes coordinate', ConvertInterface::DEFAULT_DM_FORMAT)
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with an output format</info>:
%command.full_name% "40.446195, -79.948862" <comment>--format="%P%D°%N %p%d°%n"</comment>
<info>Example with FISCHER_1968 ellipsoid</info>:
%command.full_name% "40.446195, -79.948862" <comment>--ellipsoid=FISCHER_1968</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$coordinate = new Coordinate($input->getArgument('coordinate'), $ellipsoid);
$geotools = new Geotools;
$output->writeln(sprintf(
'<value>%s</value>',
$geotools->convert($coordinate)->toDM($input->getOption('format'))
));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Convert;
use League\Geotools\Convert\ConvertInterface;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line convert:dms class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class DMS extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('convert:dms')
->setDescription('Convert and format decimal degrees coordinates to degrees minutes seconds coordinate')
->addArgument('coordinate', InputArgument::REQUIRED, 'The "Lat,Long" coordinate')
->addOption('format', null, InputOption::VALUE_REQUIRED,
'If set, the format of the converted degrees minutes seconds coordinate',
ConvertInterface::DEFAULT_DMS_FORMAT)
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with an output format</info>:
%command.full_name% "40.446195, -79.948862" <comment>--format="%P%D:%M:%S, %p%d:%m:%s"</comment>
<info>Example with BESSEL_1841 ellipsoid</info>:
%command.full_name% "40.446195, -79.948862" <comment>--ellipsoid=BESSEL_1841</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$coordinate = new Coordinate($input->getArgument('coordinate'), $ellipsoid);
$geotools = new Geotools;
$output->writeln(sprintf(
'<value>%s</value>',
$geotools->convert($coordinate)->toDMS($input->getOption('format'))
));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Convert;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line convert:utm class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class UTM extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('convert:utm')
->setDescription('Convert decimal degrees coordinates in the Universal Transverse Mercator projection')
->addArgument('coordinate', InputArgument::REQUIRED, 'The "Lat,Long" coordinate')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with CLARKE_1866 ellipsoid</info>:
%command.full_name% "40.446195, -79.948862" <comment>--ellipsoid=CLARKE_1866</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$coordinate = new Coordinate($input->getArgument('coordinate'), $ellipsoid);
$geotools = new Geotools;
$output->writeln(sprintf(
'<value>%s</value>',
$geotools->convert($coordinate)->toUTM()
));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Distance;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line distance:all class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class All extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('distance:all')
->setDescription('Compute the distance between 2 coordinates using all algorithms, in meters by default')
->addArgument('origin', InputArgument::REQUIRED, 'The origin "Lat,Long" coordinate')
->addArgument('destination', InputArgument::REQUIRED, 'The destination "Lat,Long" coordinate')
->addOption('km', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in kilometers')
->addOption('mi', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in miles')
->addOption('ft', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in feet')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with AIRY ellipsoid</info>:
%command.full_name% "40° 26.7717, -79° 56.93172" "30°16′57″N 029°48′32″W" <comment>--ellipsoid=AIRY</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$from = new Coordinate($input->getArgument('origin'), $ellipsoid);
$to = new Coordinate($input->getArgument('destination'), $ellipsoid);
$geotools = new Geotools;
$distance = $geotools->distance()->setFrom($from)->setTo($to);
if ($input->getOption('km')) {
$distance->in('km');
}
if ($input->getOption('mi')) {
$distance->in('mi');
}
if ($input->getOption('ft')) {
$distance->in('ft');
}
$result = array();
$result[] = sprintf('<label>Flat:</label> <value>%s</value>', $distance->flat());
$result[] = sprintf('<label>Haversine:</label> <value>%s</value>', $distance->haversine());
$result[] = sprintf('<label>Vincenty:</label> <value>%s</value>', $distance->vincenty());
$output->writeln($result);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Distance;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line distance:flat class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Flat extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('distance:flat')
->setDescription('Compute the distance between 2 coordinates using the flat algorithm, in meters by default')
->addArgument('origin', InputArgument::REQUIRED, 'The origin "Lat,Long" coordinate')
->addArgument('destination', InputArgument::REQUIRED, 'The destination "Lat,Long" coordinate')
->addOption('km', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in kilometers')
->addOption('mi', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in miles')
->addOption('ft', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in feet')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with WGS60 ellipsoid and output in kilometers</info>:
%command.full_name% "40° 26.7717, -79° 56.93172" "30°16′57″N 029°48′32″W" <comment>--ellipsoid=WGS60 --km</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$from = new Coordinate($input->getArgument('origin'), $ellipsoid);
$to = new Coordinate($input->getArgument('destination'), $ellipsoid);
$geotools = new Geotools;
$distance = $geotools->distance()->setFrom($from)->setTo($to);
if ($input->getOption('km')) {
$distance->in('km');
}
if ($input->getOption('mi')) {
$distance->in('mi');
}
if ($input->getOption('ft')) {
$distance->in('ft');
}
$output->writeln(sprintf('<value>%s</value>', $distance->flat()));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Distance;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line distance:great-circle class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class GreatCircle extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('distance:great-circle')
->setDescription('Compute the distance between 2 coordinates using the spherical trigonometry, in meters by default')
->addArgument('origin', InputArgument::REQUIRED, 'The origin "Lat,Long" coordinate')
->addArgument('destination', InputArgument::REQUIRED, 'The destination "Lat,Long" coordinate')
->addOption('km', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in kilometers')
->addOption('mi', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in miles')
->addOption('ft', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in feet')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with WGS60 ellipsoid and output in kilometers</info>:
%command.full_name% "40° 26.7717, -79° 56.93172" "30°16′57″N 029°48′32″W" <comment>--ellipsoid=WGS60 --km</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$from = new Coordinate($input->getArgument('origin'), $ellipsoid);
$to = new Coordinate($input->getArgument('destination'), $ellipsoid);
$geotools = new Geotools;
$distance = $geotools->distance()->setFrom($from)->setTo($to);
if ($input->getOption('km')) {
$distance->in('km');
}
if ($input->getOption('mi')) {
$distance->in('mi');
}
if ($input->getOption('ft')) {
$distance->in('ft');
}
$output->writeln(sprintf('<value>%s</value>', $distance->greatCircle()));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Distance;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line distance:haversine class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Haversine extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('distance:haversine')
->setDescription('Compute the distance between 2 coordinates using the haversine algorithm, in meters by default')
->addArgument('origin', InputArgument::REQUIRED, 'The origin "Lat,Long" coordinate')
->addArgument('destination', InputArgument::REQUIRED, 'The destination "Lat,Long" coordinate')
->addOption('km', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in kilometers')
->addOption('mi', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in miles')
->addOption('ft', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in feet')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with WGS66 ellipsoid and output in feet</info>:
%command.full_name% "40° 26.7717, -79° 56.93172" "30°16′57″N 029°48′32″W" <comment>--ellipsoid=WGS66 --ft</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$from = new Coordinate($input->getArgument('origin'), $ellipsoid);
$to = new Coordinate($input->getArgument('destination'), $ellipsoid);
$geotools = new Geotools;
$distance = $geotools->distance()->setFrom($from)->setTo($to);
if ($input->getOption('km')) {
$distance->in('km');
}
if ($input->getOption('mi')) {
$distance->in('mi');
}
if ($input->getOption('ft')) {
$distance->in('ft');
}
$output->writeln(sprintf('<value>%s</value>', $distance->haversine()));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Distance;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Coordinate\Ellipsoid;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line distance:vincenty class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Vincenty extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$availableEllipsoids = Ellipsoid::getAvailableEllipsoidNames();
$this
->setName('distance:vincenty')
->setDescription('Compute the distance between 2 coordinates using the vincenty algorithm, in meters by default')
->addArgument('origin', InputArgument::REQUIRED, 'The origin "Lat,Long" coordinate')
->addArgument('destination', InputArgument::REQUIRED, 'The destination "Lat,Long" coordinate')
->addOption('km', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in kilometers')
->addOption('mi', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in miles')
->addOption('ft', null, InputOption::VALUE_NONE, 'If set, the distance will be shown in feet')
->addOption('ellipsoid', null, InputOption::VALUE_REQUIRED,
'If set, the name of the ellipsoid to use', Ellipsoid::WGS84)
->setHelp(<<<EOT
<info>Available ellipsoids</info>: $availableEllipsoids
<info>Example with WGS72 ellipsoid and output in miles</info>:
%command.full_name% "40° 26.7717, -79° 56.93172" "30°16′57″N 029°48′32″W" <comment>--ellipsoid=WGS72 --mi</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ellipsoid = Ellipsoid::createFromName($input->getOption('ellipsoid'));
$from = new Coordinate($input->getArgument('origin'), $ellipsoid);
$to = new Coordinate($input->getArgument('destination'), $ellipsoid);
$geotools = new Geotools;
$distance = $geotools->distance()->setFrom($from)->setTo($to);
if ($input->getOption('km')) {
$distance->in('km');
}
if ($input->getOption('mi')) {
$distance->in('mi');
}
if ($input->getOption('ft')) {
$distance->in('ft');
}
$output->writeln(sprintf('<value>%s</value>', $distance->vincenty()));
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Geocoder;
use Psr\Cache\CacheItemPoolInterface;
/**
* Command class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Command extends \Symfony\Component\Console\Command\Command
{
/**
* Available providers.
*
* @var array
*/
private $providers = [
'free_geo_ip' => 'FreeGeoIp',
'host_ip' => 'HostIp',
'ip_info_db' => 'IpInfoDb',
'google_maps' => 'GoogleMaps',
'google_maps_business' => 'GoogleMapsBusiness',
'bing_maps' => 'BingMaps',
'openstreetmaps' => 'OpenStreetMap',
'cloudmade' => 'CloudMade',
'geoip' => 'Geoip',
'map_quest' => 'MapQuest',
'oio_rest' => 'OIORest',
'geocoder_ca' => 'GeocoderCa',
'geocoder_us' => 'GeocoderUs',
'ign_openls' => 'IGNOpenLS',
'data_science_toolkit' => 'DataScienceToolkit',
'yandex' => 'Yandex',
'geo_plugin' => 'GeoPlugin',
'geo_ips' => 'GeoIPs',
'maxmind' => 'MaxMind',
'geonames' => 'Geonames',
'ip_geo_base' => 'IpGeoBase',
'baidu' => 'Baidu',
'tomtom' => 'TomTom',
'arcgis_online' => 'ArcGISOnline',
];
/**
* Available dumpers.
*
* @var array
*/
private $dumpers = [
'gpx' => 'Gpx',
'geojson' => 'GeoJson',
'kml' => 'Kml',
'wkb' => 'Wkb',
'wkt' => 'Wkt',
];
/**
* @param string $factoryCallable
*
* @return CacheItemPoolInterface
*/
protected function getCache($factoryCallable)
{
$factoryCallable = $this->lowerize((trim($factoryCallable)));
if (!is_callable($factoryCallable)) {
throw new \LogicException(sprintf('Cache must be called with a valid callable on the format "Example\Acme::create". "%s" given.', $factoryCallable));
}
$psr6 = call_user_func($factoryCallable);
if (!$psr6 instanceof CacheItemPoolInterface) {
throw new \LogicException('Return value of factory callable must be a CacheItemPoolInterface');
}
return $psr6;
}
/**
* Returns the provider class name.
* The default provider is Google Maps.
*
* @param string $provider The name of the provider to use.
*
* @return string The name of the provider class to use.
*/
protected function getProvider($provider)
{
$provider = $this->lowerize((trim($provider)));
$provider = array_key_exists($provider, $this->providers)
? $this->providers[$provider]
: $this->providers['google_maps'];
return '\\Geocoder\\Provider\\' . $provider . $provider;
}
/**
* Returns the list of available providers sorted by alphabetical order.
*
* @return string The list of available providers comma separated.
*/
protected function getProviders()
{
ksort($this->providers);
return implode(', ', array_keys($this->providers));
}
/**
* Returns the dumper class name.
* The default dumper is WktDumper.
*
* @param string $dumper The name of the dumper to use.
*
* @return string The name of the dumper class to use.
*/
protected function getDumper($dumper)
{
$dumper = $this->lowerize((trim($dumper)));
$dumper = array_key_exists($dumper, $this->dumpers)
? $this->dumpers[$dumper]
: $this->dumpers['wkt'];
return '\\Geocoder\\Dumper\\' . $dumper;
}
/**
* Returns the list of available dumpers sorted by alphabetical order.
*
* @return string The list of available dumpers comma separated.
*/
protected function getDumpers()
{
ksort($this->dumpers);
return implode(', ', array_keys($this->dumpers));
}
/**
* Make a string lowercase.
*
* @param string $string A string to lowercase.
*
* @return string The lowercased string.
*/
private function lowerize($string)
{
return extension_loaded('mbstring') ? mb_strtolower($string, 'UTF-8') : strtolower($string);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Geocoder;
use Geocoder\ProviderAggregator;
use Http\Discovery\HttpClientDiscovery;
use League\Geotools\Batch\Batch;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line geocoder:geocode class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Geocode extends Command
{
protected function configure()
{
$this
->setName('geocoder:geocode')
->setDescription('Geocode a street-address, IPv4 or IPv6 against a provider with an adapter')
->addArgument('value', InputArgument::REQUIRED, 'The street-address, IPv4 or IPv6 to geocode')
->addOption('provider', null, InputOption::VALUE_REQUIRED,
'If set, the name of the provider to use, Google Maps by default', 'google_maps')
->addOption('cache', null, InputOption::VALUE_REQUIRED,
'If set, the name of a factory method that will create a PSR-6 cache. "Example\Acme::create"')
->addOption('raw', null, InputOption::VALUE_NONE,
'If set, the raw format of the reverse geocoding result')
->addOption('json', null, InputOption::VALUE_NONE,
'If set, the json format of the reverse geocoding result')
->addOption('dumper', null, InputOption::VALUE_REQUIRED,
'If set, the name of the dumper to use, no dumper by default')
->addOption('args', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'If set, the provider constructor arguments like api key, locale, region, ssl, toponym and service')
->setHelp(<<<EOT
<info>Available providers</info>: {$this->getProviders()} <comment>(some providers need arguments)</comment>
<info>Available dumpers</info>: {$this->getDumpers()}
<info>Use the default provider with the socket adapter and dump the output in WKT standard</info>:
%command.full_name% paris <comment>--adapter=socket --dumper=wkt</comment>
<info>Use the OpenStreetMaps provider with the default adapter</info>:
%command.full_name% paris <comment>--provider=openstreetmaps</comment>
<info>Use the FreeGeoIp provider with the socket adapter</info>
%command.full_name% 74.200.247.59 <comment>--provider="free_geo_ip" --adapter="socket"</comment>
<info>Use the default provider with the french locale and region via SSL</info>:
%command.full_name% "Tagensvej 47, Copenhagen" <comment>--args=da_DK --args=Denmark --args="true"</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$geocoder = new ProviderAggregator;
$httpClient = HttpClientDiscovery::find();
$provider = $this->getProvider($input->getOption('provider'));
if ($input->getOption('args')) {
$args = is_array($input->getOption('args'))
? implode(',', $input->getOption('args'))
: $input->getOption('args');
$geocoder->registerProvider(new $provider($httpClient, $args));
} else {
$geocoder->registerProvider(new $provider($httpClient));
}
$batch = new Batch($geocoder);
if ($input->getOption('cache')) {
$batch->setCache($this->getCache($input->getOption('cache')));
}
$geocoded = $batch->geocode($input->getArgument('value'))->parallel();
$address = $geocoded[0]->first();
if ($input->getOption('raw')) {
$result = array();
$result[] = sprintf('<label>HttpClient</label>: <value>%s</value>', get_class($httpClient));
$result[] = sprintf('<label>Provider</label>: <value>%s</value>', $provider);
$result[] = sprintf('<label>Cache</label>: <value>%s</value>', isset($cache) ? $cache : 'None');
if ($input->getOption('args')) {
$result[] = sprintf('<label>Arguments</label>: <value>%s</value>', $args);
}
$result[] = '---';
$coordinates = $address->getCoordinates();
$result[] = sprintf('<label>Latitude</label>: <value>%s</value>', null !== $coordinates ? $coordinates->getLatitude() : '');
$result[] = sprintf('<label>Longitude</label>: <value>%s</value>', null !== $coordinates ? $coordinates->getLongitude() : '');
if ($address->getBounds()) {
$bounds = $address->getBounds()->toArray();
$result[] = '<label>Bounds</label>';
$result[] = sprintf(' - <label>South</label>: <value>%s</value>', $bounds['south']);
$result[] = sprintf(' - <label>West</label>: <value>%s</value>', $bounds['west']);
$result[] = sprintf(' - <label>North</label>: <value>%s</value>', $bounds['north']);
$result[] = sprintf(' - <label>East</label>: <value>%s</value>', $bounds['east']);
}
$result[] = sprintf('<label>Street Number</label>: <value>%s</value>', $address->getStreetNumber());
$result[] = sprintf('<label>Street Name</label>: <value>%s</value>', $address->getStreetName());
$result[] = sprintf('<label>Zipcode</label>: <value>%s</value>', $address->getPostalCode());
$result[] = sprintf('<label>City</label>: <value>%s</value>', $address->getLocality());
$result[] = sprintf('<label>City District</label>: <value>%s</value>', $address->getSublocality());
if (null !== $adminLevels = $address->getAdminLevels()) {
$result[] = '<label>Admin Levels</label>';
foreach ($adminLevels as $adminLevel) {
$result[] = sprintf(' - <label>%s</label>: <value>%s</value>', $adminLevel->getCode(), $adminLevel->getName());
}
}
$country = $address->getCountry();
$result[] = sprintf('<label>Country</label>: <value>%s</value>', null !== $country ? $country->getName() : '');
$result[] = sprintf('<label>Country Code</label>: <value>%s</value>', null !== $country ? $country->getCode() : '');
$result[] = sprintf('<label>Timezone</label>: <value>%s</value>', $address->getTimezone());
} elseif ($input->getOption('json')) {
$result = sprintf('<value>%s</value>', json_encode($address->toArray()));
} elseif ($input->getOption('dumper')) {
$dumper = $this->getDumper($input->getOption('dumper'));
$dumper = new $dumper;
$result = sprintf('<value>%s</value>', $dumper->dump($address));
} else {
$coordinates = $address->getCoordinates();
$result = '<value>null, null</value>';
if (null !== $coordinates) {
$result = sprintf('<value>%s, %s</value>', $coordinates->getLatitude(), $coordinates->getLongitude());
}
}
$output->writeln($result);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Geocoder;
use Geocoder\Formatter\StringFormatter;
use Geocoder\ProviderAggregator;
use Http\Discovery\HttpClientDiscovery;
use League\Geotools\Batch\Batch;
use League\Geotools\Coordinate\Coordinate;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line geocoder:reverse class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Reverse extends Command
{
protected function configure()
{
$this
->setName('geocoder:reverse')
->setDescription('Reverse geocode street address, IPv4 or IPv6 against a provider with an adapter')
->addArgument('coordinate', InputArgument::REQUIRED, 'The coordinate to reverse')
->addOption('provider', null, InputOption::VALUE_REQUIRED,
'If set, the name of the provider to use, Google Maps by default', 'google_maps')
->addOption('cache', null, InputOption::VALUE_REQUIRED,
'If set, the name of the cache to use, Redis by default')
->addOption('raw', null, InputOption::VALUE_NONE,
'If set, the raw format of the reverse geocoding result')
->addOption('json', null, InputOption::VALUE_NONE,
'If set, the json format of the reverse geocoding result')
->addOption('args', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'If set, the provider constructor arguments like api key, locale, region, ssl, toponym and service')
->addOption('format', null, InputOption::VALUE_REQUIRED,
'If set, the format of the reverse geocoding result', '%S %n, %z %L')
->setHelp(<<<EOT
<info>Available providers</info>: {$this->getProviders()} <comment>(some providers need arguments)</comment>
<info>Available dumpers</info>: {$this->getDumpers()}
<info>Use the default provider with the socket adapter and format the output</info>:
%command.full_name% "48.8631507, 2.388911" <comment>--format="%L, %R, %C" --adapter=socket</comment>
<info>Use the OpenStreetMaps provider with the default adapter</info>:
%command.full_name% "48.8631507, 2.388911" <comment>--provider=openstreetmaps</comment>
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$coordinate = new Coordinate($input->getArgument('coordinate'));
$geocoder = new ProviderAggregator;
$httpClient = HttpClientDiscovery::find();
$provider = $this->getProvider($input->getOption('provider'));
if ($input->getOption('args')) {
$args = is_array($input->getOption('args'))
? implode(',', $input->getOption('args'))
: $input->getOption('args');
$geocoder->registerProvider(new $provider($httpClient, $args));
} else {
$geocoder->registerProvider(new $provider($httpClient));
}
$batch = new Batch($geocoder);
if ($input->getOption('cache')) {
$batch->setCache( $this->getCache($input->getOption('cache')));
}
$reversed = $batch->reverse($coordinate)->parallel();
$address = $reversed[0]->first();
if ($input->getOption('raw')) {
$result = array();
$result[] = sprintf('<label>HttpClient</label>: <value>%s</value>', get_class($httpClient));
$result[] = sprintf('<label>Provider</label>: <value>%s</value>', $provider);
$result[] = sprintf('<label>Cache</label>: <value>%s</value>', isset($cache) ? $cache : 'None');
if ($input->getOption('args')) {
$result[] = sprintf('<label>Arguments</label>: <value>%s</value>', $args);
}
$result[] = '---';
$coordinates = $address->getCoordinates();
$result[] = sprintf('<label>Latitude</label>: <value>%s</value>', null !== $coordinates ? $coordinates->getLatitude() : '');
$result[] = sprintf('<label>Longitude</label>: <value>%s</value>', null !== $coordinates ? $coordinates->getLongitude() : '');
if ($address->getBounds()) {
$bounds = $address->getBounds()->toArray();
$result[] = '<label>Bounds</label>';
$result[] = sprintf(' - <label>South</label>: <value>%s</value>', $bounds['south']);
$result[] = sprintf(' - <label>West</label>: <value>%s</value>', $bounds['west']);
$result[] = sprintf(' - <label>North</label>: <value>%s</value>', $bounds['north']);
$result[] = sprintf(' - <label>East</label>: <value>%s</value>', $bounds['east']);
}
$result[] = sprintf('<label>Street Number</label>: <value>%s</value>', $address->getStreetNumber());
$result[] = sprintf('<label>Street Name</label>: <value>%s</value>', $address->getStreetName());
$result[] = sprintf('<label>Zipcode</label>: <value>%s</value>', $address->getPostalCode());
$result[] = sprintf('<label>City</label>: <value>%s</value>', $address->getLocality());
$result[] = sprintf('<label>City District</label>: <value>%s</value>', $address->getSubLocality());
if ( NULL !== $adminLevels = $address->getAdminLevels() ) {
$result[] = '<label>Admin Levels</label>';
foreach ($adminLevels as $adminLevel) {
$result[] = sprintf(' - <label>%s</label>: <value>%s</value>', $adminLevel->getCode(), $adminLevel->getName());
}
}
$country = $address->getCountry();
$result[] = sprintf('<label>Country</label>: <value>%s</value>', null !== $country ? $country->getName() : '');
$result[] = sprintf('<label>Country Code</label>: <value>%s</value>', null !== $country ? $country->getCode() : '');
$result[] = sprintf('<label>Timezone</label>: <value>%s</value>', $address->getTimezone());
} elseif ($input->getOption('json')) {
$result = sprintf('<value>%s</value>', json_encode($address->toArray()));
} else {
$result = (new StringFormatter)->format($address, $input->getOption('format'));
}
$output->writeln($result);
}
}
<?php
/*
* This file is part of the Geotools library.
*
* (c) Antoine Corcy <contact@sbin.dk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Geotools\CLI\Command\Geohash;
use League\Geotools\Geotools;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command-line geohash:decode class
*
* @author Antoine Corcy <contact@sbin.dk>
*/
class Decode extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$this
->setName('geohash:decode')
->setDescription('Decode a geo hash string to a coordinate')
->addArgument('geohash', InputArgument::REQUIRED, 'The geo hash to decode to coordinate')
->setHelp(<<<EOT
<info>Example</info>: %command.full_name% spey61y
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$geotools = new Geotools;
$coordinate = $geotools->geohash()->decode($input->getArgument('geohash'))->getCoordinate();
$output->writeln(sprintf(
'<value>%s, %s</value>',
$coordinate->getLatitude(), $coordinate->getLongitude()
));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment