Address.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the Geocoder package.
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. *
  8. * @license MIT License
  9. */
  10. namespace Geocoder\Model;
  11. use Geocoder\Location;
  12. /**
  13. * @author William Durand <william.durand1@gmail.com>
  14. */
  15. class Address implements Location
  16. {
  17. /**
  18. * @var Coordinates|null
  19. */
  20. private $coordinates;
  21. /**
  22. * @var Bounds|null
  23. */
  24. private $bounds;
  25. /**
  26. * @var string|int|null
  27. */
  28. private $streetNumber;
  29. /**
  30. * @var string|null
  31. */
  32. private $streetName;
  33. /**
  34. * @var string|null
  35. */
  36. private $subLocality;
  37. /**
  38. * @var string|null
  39. */
  40. private $locality;
  41. /**
  42. * @var string|null
  43. */
  44. private $postalCode;
  45. /**
  46. * @var AdminLevelCollection
  47. */
  48. private $adminLevels;
  49. /**
  50. * @var Country|null
  51. */
  52. private $country;
  53. /**
  54. * @var string|null
  55. */
  56. private $timezone;
  57. /**
  58. * @var string
  59. */
  60. private $providedBy;
  61. /**
  62. * @param string $providedBy
  63. * @param AdminLevelCollection $adminLevels
  64. * @param Coordinates|null $coordinates
  65. * @param Bounds|null $bounds
  66. * @param string|null $streetNumber
  67. * @param string|null $streetName
  68. * @param string|null $postalCode
  69. * @param string|null $locality
  70. * @param string|null $subLocality
  71. * @param Country|null $country
  72. * @param string|null $timezone
  73. */
  74. public function __construct(
  75. string $providedBy,
  76. AdminLevelCollection $adminLevels,
  77. Coordinates $coordinates = null,
  78. Bounds $bounds = null,
  79. string $streetNumber = null,
  80. string $streetName = null,
  81. string $postalCode = null,
  82. string $locality = null,
  83. string $subLocality = null,
  84. Country $country = null,
  85. string $timezone = null
  86. ) {
  87. $this->providedBy = $providedBy;
  88. $this->adminLevels = $adminLevels;
  89. $this->coordinates = $coordinates;
  90. $this->bounds = $bounds;
  91. $this->streetNumber = $streetNumber;
  92. $this->streetName = $streetName;
  93. $this->postalCode = $postalCode;
  94. $this->locality = $locality;
  95. $this->subLocality = $subLocality;
  96. $this->country = $country;
  97. $this->timezone = $timezone;
  98. }
  99. /**
  100. * @return string
  101. */
  102. public function getProvidedBy(): string
  103. {
  104. return $this->providedBy;
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function getCoordinates()
  110. {
  111. return $this->coordinates;
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. public function getBounds()
  117. {
  118. return $this->bounds;
  119. }
  120. /**
  121. * {@inheritdoc}
  122. */
  123. public function getStreetNumber()
  124. {
  125. return $this->streetNumber;
  126. }
  127. /**
  128. * {@inheritdoc}
  129. */
  130. public function getStreetName()
  131. {
  132. return $this->streetName;
  133. }
  134. /**
  135. * {@inheritdoc}
  136. */
  137. public function getLocality()
  138. {
  139. return $this->locality;
  140. }
  141. /**
  142. * {@inheritdoc}
  143. */
  144. public function getPostalCode()
  145. {
  146. return $this->postalCode;
  147. }
  148. /**
  149. * {@inheritdoc}
  150. */
  151. public function getSubLocality()
  152. {
  153. return $this->subLocality;
  154. }
  155. /**
  156. * {@inheritdoc}
  157. */
  158. public function getAdminLevels(): AdminLevelCollection
  159. {
  160. return $this->adminLevels;
  161. }
  162. /**
  163. * {@inheritdoc}
  164. */
  165. public function getCountry()
  166. {
  167. return $this->country;
  168. }
  169. /**
  170. * {@inheritdoc}
  171. */
  172. public function getTimezone()
  173. {
  174. return $this->timezone;
  175. }
  176. /**
  177. * Create an Address with an array. Useful for testing.
  178. *
  179. * @param array $data
  180. *
  181. * @return static
  182. */
  183. public static function createFromArray(array $data)
  184. {
  185. $defaults = [
  186. 'providedBy' => 'n/a',
  187. 'latitude' => null,
  188. 'longitude' => null,
  189. 'bounds' => [
  190. 'south' => null,
  191. 'west' => null,
  192. 'north' => null,
  193. 'east' => null,
  194. ],
  195. 'streetNumber' => null,
  196. 'streetName' => null,
  197. 'locality' => null,
  198. 'postalCode' => null,
  199. 'subLocality' => null,
  200. 'adminLevels' => [],
  201. 'country' => null,
  202. 'countryCode' => null,
  203. 'timezone' => null,
  204. ];
  205. $data = array_merge($defaults, $data);
  206. $adminLevels = [];
  207. foreach ($data['adminLevels'] as $adminLevel) {
  208. if (null === $adminLevel['level'] || 0 === $adminLevel['level']) {
  209. continue;
  210. }
  211. $name = $adminLevel['name'] ?? $adminLevel['code'] ?? null;
  212. if (null === $name || '' === $name) {
  213. continue;
  214. }
  215. $adminLevels[] = new AdminLevel($adminLevel['level'], $name, $adminLevel['code'] ?? null);
  216. }
  217. return new static(
  218. $data['providedBy'],
  219. new AdminLevelCollection($adminLevels),
  220. self::createCoordinates(
  221. $data['latitude'],
  222. $data['longitude']
  223. ),
  224. self::createBounds(
  225. $data['bounds']['south'],
  226. $data['bounds']['west'],
  227. $data['bounds']['north'],
  228. $data['bounds']['east']
  229. ),
  230. $data['streetNumber'],
  231. $data['streetName'],
  232. $data['postalCode'],
  233. $data['locality'],
  234. $data['subLocality'],
  235. self::createCountry($data['country'], $data['countryCode']),
  236. $data['timezone']
  237. );
  238. }
  239. /**
  240. * @param float $latitude
  241. * @param float $longitude
  242. *
  243. * @return Coordinates|null
  244. */
  245. private static function createCoordinates($latitude, $longitude)
  246. {
  247. if (null === $latitude || null === $longitude) {
  248. return null;
  249. }
  250. return new Coordinates($latitude, $longitude);
  251. }
  252. /**
  253. * @param string|null $name
  254. * @param string|null $code
  255. *
  256. * @return Country|null
  257. */
  258. private static function createCountry($name, $code)
  259. {
  260. if (null === $name && null === $code) {
  261. return null;
  262. }
  263. return new Country($name, $code);
  264. }
  265. /**
  266. * @param float $south
  267. * @param float $west
  268. * @param float $north
  269. *
  270. * @return Bounds|null
  271. */
  272. private static function createBounds($south, $west, $north, $east)
  273. {
  274. if (null === $south || null === $west || null === $north || null === $east) {
  275. return null;
  276. }
  277. return new Bounds($south, $west, $north, $east);
  278. }
  279. /**
  280. * {@inheritdoc}
  281. */
  282. public function toArray(): array
  283. {
  284. $adminLevels = [];
  285. foreach ($this->adminLevels as $adminLevel) {
  286. $adminLevels[$adminLevel->getLevel()] = [
  287. 'name' => $adminLevel->getName(),
  288. 'code' => $adminLevel->getCode(),
  289. 'level' => $adminLevel->getLevel(),
  290. ];
  291. }
  292. $lat = null;
  293. $lon = null;
  294. if (null !== $coordinates = $this->getCoordinates()) {
  295. $lat = $coordinates->getLatitude();
  296. $lon = $coordinates->getLongitude();
  297. }
  298. $countryName = null;
  299. $countryCode = null;
  300. if (null !== $country = $this->getCountry()) {
  301. $countryName = $country->getName();
  302. $countryCode = $country->getCode();
  303. }
  304. $noBounds = [
  305. 'south' => null,
  306. 'west' => null,
  307. 'north' => null,
  308. 'east' => null,
  309. ];
  310. return [
  311. 'providedBy' => $this->providedBy,
  312. 'latitude' => $lat,
  313. 'longitude' => $lon,
  314. 'bounds' => null !== $this->bounds ? $this->bounds->toArray() : $noBounds,
  315. 'streetNumber' => $this->streetNumber,
  316. 'streetName' => $this->streetName,
  317. 'postalCode' => $this->postalCode,
  318. 'locality' => $this->locality,
  319. 'subLocality' => $this->subLocality,
  320. 'adminLevels' => $adminLevels,
  321. 'country' => $countryName,
  322. 'countryCode' => $countryCode,
  323. 'timezone' => $this->timezone,
  324. ];
  325. }
  326. }