default services conflit ?

This commit is contained in:
armansansd
2022-04-27 11:30:43 +02:00
parent 28190a5749
commit 8bb1064a3b
8132 changed files with 900138 additions and 426 deletions

View File

@@ -0,0 +1,370 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Location;
/**
* @author William Durand <william.durand1@gmail.com>
*/
class Address implements Location
{
/**
* @var Coordinates|null
*/
private $coordinates;
/**
* @var Bounds|null
*/
private $bounds;
/**
* @var string|int|null
*/
private $streetNumber;
/**
* @var string|null
*/
private $streetName;
/**
* @var string|null
*/
private $subLocality;
/**
* @var string|null
*/
private $locality;
/**
* @var string|null
*/
private $postalCode;
/**
* @var AdminLevelCollection
*/
private $adminLevels;
/**
* @var Country|null
*/
private $country;
/**
* @var string|null
*/
private $timezone;
/**
* @var string
*/
private $providedBy;
/**
* @param string $providedBy
* @param AdminLevelCollection $adminLevels
* @param Coordinates|null $coordinates
* @param Bounds|null $bounds
* @param string|null $streetNumber
* @param string|null $streetName
* @param string|null $postalCode
* @param string|null $locality
* @param string|null $subLocality
* @param Country|null $country
* @param string|null $timezone
*/
public function __construct(
string $providedBy,
AdminLevelCollection $adminLevels,
Coordinates $coordinates = null,
Bounds $bounds = null,
string $streetNumber = null,
string $streetName = null,
string $postalCode = null,
string $locality = null,
string $subLocality = null,
Country $country = null,
string $timezone = null
) {
$this->providedBy = $providedBy;
$this->adminLevels = $adminLevels;
$this->coordinates = $coordinates;
$this->bounds = $bounds;
$this->streetNumber = $streetNumber;
$this->streetName = $streetName;
$this->postalCode = $postalCode;
$this->locality = $locality;
$this->subLocality = $subLocality;
$this->country = $country;
$this->timezone = $timezone;
}
/**
* @return string
*/
public function getProvidedBy(): string
{
return $this->providedBy;
}
/**
* {@inheritdoc}
*/
public function getCoordinates()
{
return $this->coordinates;
}
/**
* {@inheritdoc}
*/
public function getBounds()
{
return $this->bounds;
}
/**
* {@inheritdoc}
*/
public function getStreetNumber()
{
return $this->streetNumber;
}
/**
* {@inheritdoc}
*/
public function getStreetName()
{
return $this->streetName;
}
/**
* {@inheritdoc}
*/
public function getLocality()
{
return $this->locality;
}
/**
* {@inheritdoc}
*/
public function getPostalCode()
{
return $this->postalCode;
}
/**
* {@inheritdoc}
*/
public function getSubLocality()
{
return $this->subLocality;
}
/**
* {@inheritdoc}
*/
public function getAdminLevels(): AdminLevelCollection
{
return $this->adminLevels;
}
/**
* {@inheritdoc}
*/
public function getCountry()
{
return $this->country;
}
/**
* {@inheritdoc}
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* Create an Address with an array. Useful for testing.
*
* @param array $data
*
* @return static
*/
public static function createFromArray(array $data)
{
$defaults = [
'providedBy' => 'n/a',
'latitude' => null,
'longitude' => null,
'bounds' => [
'south' => null,
'west' => null,
'north' => null,
'east' => null,
],
'streetNumber' => null,
'streetName' => null,
'locality' => null,
'postalCode' => null,
'subLocality' => null,
'adminLevels' => [],
'country' => null,
'countryCode' => null,
'timezone' => null,
];
$data = array_merge($defaults, $data);
$adminLevels = [];
foreach ($data['adminLevels'] as $adminLevel) {
if (null === $adminLevel['level'] || 0 === $adminLevel['level']) {
continue;
}
$name = $adminLevel['name'] ?? $adminLevel['code'] ?? null;
if (null === $name || '' === $name) {
continue;
}
$adminLevels[] = new AdminLevel($adminLevel['level'], $name, $adminLevel['code'] ?? null);
}
return new static(
$data['providedBy'],
new AdminLevelCollection($adminLevels),
self::createCoordinates(
$data['latitude'],
$data['longitude']
),
self::createBounds(
$data['bounds']['south'],
$data['bounds']['west'],
$data['bounds']['north'],
$data['bounds']['east']
),
$data['streetNumber'],
$data['streetName'],
$data['postalCode'],
$data['locality'],
$data['subLocality'],
self::createCountry($data['country'], $data['countryCode']),
$data['timezone']
);
}
/**
* @param float $latitude
* @param float $longitude
*
* @return Coordinates|null
*/
private static function createCoordinates($latitude, $longitude)
{
if (null === $latitude || null === $longitude) {
return null;
}
return new Coordinates($latitude, $longitude);
}
/**
* @param string|null $name
* @param string|null $code
*
* @return Country|null
*/
private static function createCountry($name, $code)
{
if (null === $name && null === $code) {
return null;
}
return new Country($name, $code);
}
/**
* @param float $south
* @param float $west
* @param float $north
*
* @return Bounds|null
*/
private static function createBounds($south, $west, $north, $east)
{
if (null === $south || null === $west || null === $north || null === $east) {
return null;
}
return new Bounds($south, $west, $north, $east);
}
/**
* {@inheritdoc}
*/
public function toArray(): array
{
$adminLevels = [];
foreach ($this->adminLevels as $adminLevel) {
$adminLevels[$adminLevel->getLevel()] = [
'name' => $adminLevel->getName(),
'code' => $adminLevel->getCode(),
'level' => $adminLevel->getLevel(),
];
}
$lat = null;
$lon = null;
if (null !== $coordinates = $this->getCoordinates()) {
$lat = $coordinates->getLatitude();
$lon = $coordinates->getLongitude();
}
$countryName = null;
$countryCode = null;
if (null !== $country = $this->getCountry()) {
$countryName = $country->getName();
$countryCode = $country->getCode();
}
$noBounds = [
'south' => null,
'west' => null,
'north' => null,
'east' => null,
];
return [
'providedBy' => $this->providedBy,
'latitude' => $lat,
'longitude' => $lon,
'bounds' => null !== $this->bounds ? $this->bounds->toArray() : $noBounds,
'streetNumber' => $this->streetNumber,
'streetName' => $this->streetName,
'postalCode' => $this->postalCode,
'locality' => $this->locality,
'subLocality' => $this->subLocality,
'adminLevels' => $adminLevels,
'country' => $countryName,
'countryCode' => $countryCode,
'timezone' => $this->timezone,
];
}
}

View File

@@ -0,0 +1,326 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Exception\InvalidArgument;
use Geocoder\Exception\LogicException;
/**
* A class that builds a Location or any of its subclasses.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class AddressBuilder
{
/**
* @var string
*/
private $providedBy;
/**
* @var Coordinates|null
*/
private $coordinates;
/**
* @var Bounds|null
*/
private $bounds;
/**
* @var string|null
*/
private $streetNumber;
/**
* @var string|null
*/
private $streetName;
/**
* @var string|null
*/
private $locality;
/**
* @var string|null
*/
private $postalCode;
/**
* @var string|null
*/
private $subLocality;
/**
* @var array
*/
private $adminLevels = [];
/**
* @var string|null
*/
private $country;
/**
* @var string|null
*/
private $countryCode;
/**
* @var string|null
*/
private $timezone;
/**
* A storage for extra parameters.
*
* @var array
*/
private $data = [];
/**
* @param string $providedBy
*/
public function __construct(string $providedBy)
{
$this->providedBy = $providedBy;
}
/**
* @param string $class
*
* @return Address
*/
public function build(string $class = Address::class): Address
{
if (!is_a($class, Address::class, true)) {
throw new LogicException('First parameter to LocationBuilder::build must be a class name extending Geocoder\Model\Address');
}
$country = null;
if ((null !== $this->country && '' !== $this->country) || (null !== $this->countryCode && '' !== $this->countryCode)) {
$country = new Country($this->country, $this->countryCode);
}
return new $class(
$this->providedBy,
new AdminLevelCollection($this->adminLevels),
$this->coordinates,
$this->bounds,
$this->streetNumber,
$this->streetName,
$this->postalCode,
$this->locality,
$this->subLocality,
$country,
$this->timezone
);
}
/**
* @param float $south
* @param float $west
* @param float $north
* @param float $east
*
* @return AddressBuilder
*/
public function setBounds($south, $west, $north, $east): self
{
try {
$this->bounds = new Bounds($south, $west, $north, $east);
} catch (InvalidArgument $e) {
$this->bounds = null;
}
return $this;
}
/**
* @param float $latitude
* @param float $longitude
*
* @return AddressBuilder
*/
public function setCoordinates($latitude, $longitude): self
{
try {
$this->coordinates = new Coordinates($latitude, $longitude);
} catch (InvalidArgument $e) {
$this->coordinates = null;
}
return $this;
}
/**
* @param int $level
* @param string $name
* @param string|null $code
*
* @return AddressBuilder
*/
public function addAdminLevel(int $level, string $name, string $code = null): self
{
$this->adminLevels[] = new AdminLevel($level, $name, $code);
return $this;
}
/**
* @param string|null $streetNumber
*
* @return AddressBuilder
*/
public function setStreetNumber($streetNumber): self
{
$this->streetNumber = $streetNumber;
return $this;
}
/**
* @param string|null $streetName
*
* @return AddressBuilder
*/
public function setStreetName($streetName): self
{
$this->streetName = $streetName;
return $this;
}
/**
* @param string|null $locality
*
* @return AddressBuilder
*/
public function setLocality($locality): self
{
$this->locality = $locality;
return $this;
}
/**
* @param string|null $postalCode
*
* @return AddressBuilder
*/
public function setPostalCode($postalCode): self
{
$this->postalCode = $postalCode;
return $this;
}
/**
* @param string|null $subLocality
*
* @return AddressBuilder
*/
public function setSubLocality($subLocality): self
{
$this->subLocality = $subLocality;
return $this;
}
/**
* @param array $adminLevels
*
* @return AddressBuilder
*/
public function setAdminLevels($adminLevels): self
{
$this->adminLevels = $adminLevels;
return $this;
}
/**
* @param string|null $country
*
* @return AddressBuilder
*/
public function setCountry($country): self
{
$this->country = $country;
return $this;
}
/**
* @param string|null $countryCode
*
* @return AddressBuilder
*/
public function setCountryCode($countryCode): self
{
$this->countryCode = $countryCode;
return $this;
}
/**
* @param string|null $timezone
*
* @return AddressBuilder
*/
public function setTimezone($timezone): self
{
$this->timezone = $timezone;
return $this;
}
/**
* @param string $name
* @param mixed $value
*
* @return AddressBuilder
*/
public function setValue(string $name, $value): self
{
$this->data[$name] = $value;
return $this;
}
/**
* @param string $name
* @param mixed|null $default
*
* @return mixed
*/
public function getValue(string $name, $default = null)
{
if ($this->hasValue($name)) {
return $this->data[$name];
}
return $default;
}
/**
* @param string $name
*
* @return bool
*/
public function hasValue(string $name): bool
{
return array_key_exists($name, $this->data);
}
}

View File

@@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Collection;
use Geocoder\Exception\CollectionIsEmpty;
use Geocoder\Exception\OutOfBounds;
use Geocoder\Location;
use Traversable;
final class AddressCollection implements Collection
{
/**
* @var Location[]
*/
private $locations;
/**
* @param Location[] $locations
*/
public function __construct(array $locations = [])
{
$this->locations = array_values($locations);
}
/**
* {@inheritdoc}
*/
public function getIterator(): Traversable
{
return new \ArrayIterator($this->all());
}
/**
* {@inheritdoc}
*/
public function count(): int
{
return count($this->locations);
}
/**
* {@inheritdoc}
*/
public function first(): Location
{
if ([] === $this->locations) {
throw new CollectionIsEmpty();
}
return reset($this->locations);
}
/**
* {@inheritdoc}
*/
public function isEmpty(): bool
{
return [] === $this->locations;
}
/**
* @return Location[]
*/
public function slice(int $offset, int $length = null)
{
return array_slice($this->locations, $offset, $length);
}
/**
* @return bool
*/
public function has(int $index): bool
{
return isset($this->locations[$index]);
}
/**
* {@inheritdoc}
*/
public function get(int $index): Location
{
if (!isset($this->locations[$index])) {
throw new OutOfBounds(sprintf('The index "%s" does not exist in this collection.', $index));
}
return $this->locations[$index];
}
/**
* {@inheritdoc}
*/
public function all(): array
{
return $this->locations;
}
}

View File

@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
/**
* @author William Durand <william.durand1@gmail.com>
*/
final class AdminLevel
{
/**
* @var int
*/
private $level;
/**
* @var string
*/
private $name;
/**
* @var string|null
*/
private $code;
/**
* @param int $level
* @param string $name
* @param string|null $code
*/
public function __construct(int $level, string $name, string $code = null)
{
$this->level = $level;
$this->name = $name;
$this->code = $code;
}
/**
* Returns the administrative level.
*
* @return int Level number [1,5]
*/
public function getLevel(): int
{
return $this->level;
}
/**
* Returns the administrative level name.
*
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* Returns the administrative level short name.
*
* @return string|null
*/
public function getCode()
{
return $this->code;
}
/**
* Returns a string with the administrative level name.
*
* @return string
*/
public function __toString(): string
{
return $this->getName();
}
}

View File

@@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Exception\CollectionIsEmpty;
use Geocoder\Exception\InvalidArgument;
use Geocoder\Exception\OutOfBounds;
use Traversable;
/**
* @author Giorgio Premi <giosh94mhz@gmail.com>
*/
final class AdminLevelCollection implements \IteratorAggregate, \Countable
{
const MAX_LEVEL_DEPTH = 5;
/**
* @var AdminLevel[]
*/
private $adminLevels;
/**
* @param AdminLevel[] $adminLevels
*/
public function __construct(array $adminLevels = [])
{
$this->adminLevels = [];
foreach ($adminLevels as $adminLevel) {
$level = $adminLevel->getLevel();
$this->checkLevel($level);
if ($this->has($level)) {
throw new InvalidArgument(sprintf('Administrative level %d is defined twice', $level));
}
$this->adminLevels[$level] = $adminLevel;
}
ksort($this->adminLevels, SORT_NUMERIC);
}
/**
* {@inheritdoc}
*/
public function getIterator(): Traversable
{
return new \ArrayIterator($this->all());
}
/**
* {@inheritdoc}
*/
public function count(): int
{
return count($this->adminLevels);
}
/**
* @return AdminLevel
*
* @throws CollectionIsEmpty
*/
public function first(): AdminLevel
{
if ([] === $this->adminLevels) {
throw new CollectionIsEmpty();
}
return reset($this->adminLevels);
}
/**
* @param int $offset
* @param int|null $length
*
* @return AdminLevel[]
*/
public function slice(int $offset, int $length = null): array
{
return array_slice($this->adminLevels, $offset, $length, true);
}
/**
* @return bool
*/
public function has(int $level): bool
{
return isset($this->adminLevels[$level]);
}
/**
* @return AdminLevel
*
* @throws \OutOfBoundsException
* @throws InvalidArgument
*/
public function get(int $level): AdminLevel
{
$this->checkLevel($level);
if (!isset($this->adminLevels[$level])) {
throw new InvalidArgument(sprintf('Administrative level %d is not set for this address', $level));
}
return $this->adminLevels[$level];
}
/**
* @return AdminLevel[]
*/
public function all(): array
{
return $this->adminLevels;
}
/**
* @param int $level
*
* @throws \OutOfBoundsException
*/
private function checkLevel(int $level)
{
if ($level <= 0 || $level > self::MAX_LEVEL_DEPTH) {
throw new OutOfBounds(sprintf('Administrative level should be an integer in [1,%d], %d given', self::MAX_LEVEL_DEPTH, $level));
}
}
}

View File

@@ -0,0 +1,125 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Assert;
/**
* @author William Durand <william.durand1@gmail.com>
*/
final class Bounds
{
/**
* @var float
*/
private $south;
/**
* @var float
*/
private $west;
/**
* @var float
*/
private $north;
/**
* @var float
*/
private $east;
/**
* @param float $south South bound, also min latitude
* @param float $west West bound, also min longitude
* @param float $north North bound, also max latitude
* @param float $east East bound, also max longitude
*/
public function __construct($south, $west, $north, $east)
{
Assert::notNull($south);
Assert::notNull($west);
Assert::notNull($north);
Assert::notNull($east);
$south = (float) $south;
$north = (float) $north;
$west = (float) $west;
$east = (float) $east;
Assert::latitude($south);
Assert::latitude($north);
Assert::longitude($west);
Assert::longitude($east);
$this->south = $south;
$this->west = $west;
$this->north = $north;
$this->east = $east;
}
/**
* Returns the south bound.
*
* @return float
*/
public function getSouth(): float
{
return $this->south;
}
/**
* Returns the west bound.
*
* @return float
*/
public function getWest(): float
{
return $this->west;
}
/**
* Returns the north bound.
*
* @return float
*/
public function getNorth(): float
{
return $this->north;
}
/**
* Returns the east bound.
*
* @return float
*/
public function getEast(): float
{
return $this->east;
}
/**
* Returns an array with bounds.
*
* @return array
*/
public function toArray(): array
{
return [
'south' => $this->getSouth(),
'west' => $this->getWest(),
'north' => $this->getNorth(),
'east' => $this->getEast(),
];
}
}

View File

@@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Assert;
/**
* @author William Durand <william.durand1@gmail.com>
*/
final class Coordinates
{
/**
* @var float
*/
private $latitude;
/**
* @var float
*/
private $longitude;
/**
* @param float $latitude
* @param float $longitude
*/
public function __construct($latitude, $longitude)
{
Assert::notNull($latitude);
Assert::notNull($longitude);
$latitude = (float) $latitude;
$longitude = (float) $longitude;
Assert::latitude($latitude);
Assert::longitude($longitude);
$this->latitude = $latitude;
$this->longitude = $longitude;
}
/**
* Returns the latitude.
*
* @return float
*/
public function getLatitude(): float
{
return $this->latitude;
}
/**
* Returns the longitude.
*
* @return float
*/
public function getLongitude(): float
{
return $this->longitude;
}
/**
* Returns the coordinates as a tuple.
*
* @return array
*/
public function toArray(): array
{
return [$this->getLongitude(), $this->getLatitude()];
}
}

View File

@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Model;
use Geocoder\Exception\InvalidArgument;
/**
* A Country has either a name or a code. A Country will never be without data.
*
* @author William Durand <william.durand1@gmail.com>
*/
final class Country
{
/**
* @var string|null
*/
private $name;
/**
* @var string|null
*/
private $code;
/**
* @param string $name
* @param string $code
*/
public function __construct(string $name = null, string $code = null)
{
if (null === $name && null === $code) {
throw new InvalidArgument('A country must have either a name or a code');
}
$this->name = $name;
$this->code = $code;
}
/**
* Returns the country name.
*
* @return string|null
*/
public function getName()
{
return $this->name;
}
/**
* Returns the country ISO code.
*
* @return string|null
*/
public function getCode()
{
return $this->code;
}
/**
* Returns a string with the country name.
*
* @return string
*/
public function __toString(): string
{
return $this->getName() ?: '';
}
}