1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the Geocoder package. |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | * |
||
10 | * @license MIT License |
||
11 | */ |
||
12 | |||
13 | namespace Geocoder\Provider\Chain; |
||
14 | |||
15 | use Geocoder\Collection; |
||
16 | use Geocoder\Model\AddressCollection; |
||
17 | use Geocoder\Provider\Provider; |
||
18 | use Geocoder\Query\GeocodeQuery; |
||
19 | use Geocoder\Query\ReverseQuery; |
||
20 | use Psr\Log\LoggerAwareInterface; |
||
21 | use Psr\Log\LoggerAwareTrait; |
||
22 | use Psr\Log\LogLevel; |
||
23 | |||
24 | /** |
||
25 | * @author Markus Bachmann <[email protected]> |
||
26 | */ |
||
27 | final class Chain implements Provider, LoggerAwareInterface |
||
28 | { |
||
29 | use LoggerAwareTrait; |
||
30 | |||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | private $geocodeQueryLogLevel = LogLevel::ALERT; |
||
35 | |||
36 | /** |
||
37 | * @var string |
||
38 | */ |
||
39 | private $reverseQueryLogLevel = LogLevel::ALERT; |
||
40 | |||
41 | /** |
||
42 | * @var Provider[] |
||
43 | */ |
||
44 | private $providers = []; |
||
45 | |||
46 | /** |
||
47 | * @param Provider[] $providers |
||
48 | */ |
||
49 | 4 | public function __construct(array $providers = []) |
|
50 | { |
||
51 | 4 | $this->providers = $providers; |
|
52 | } |
||
53 | |||
54 | public function setGeocodeQueryLogLevel(string $level) |
||
55 | { |
||
56 | $this->geocodeQueryLogLevel = $level; |
||
57 | } |
||
58 | |||
59 | public function setReverseQueryLogLevel(string $level) |
||
60 | { |
||
61 | $this->reverseQueryLogLevel = $level; |
||
62 | } |
||
63 | |||
64 | 1 | public function geocodeQuery(GeocodeQuery $query): Collection |
|
65 | { |
||
66 | 1 | foreach ($this->providers as $provider) { |
|
67 | try { |
||
68 | 1 | $result = $provider->geocodeQuery($query); |
|
69 | |||
70 | 1 | if (!$result->isEmpty()) { |
|
71 | 1 | return $result; |
|
72 | } |
||
73 | 1 | } catch (\Throwable $e) { |
|
74 | 1 | $this->log( |
|
75 | 1 | $this->geocodeQueryLogLevel, |
|
76 | 1 | 'Provider "{providerName}" could not geocode address: "{address}".', |
|
77 | 1 | [ |
|
78 | 1 | 'exception' => $e, |
|
79 | 1 | 'providerName' => $provider->getName(), |
|
80 | 1 | 'address' => $query->getText(), |
|
81 | 1 | ] |
|
82 | 1 | ); |
|
83 | } |
||
84 | } |
||
85 | |||
86 | return new AddressCollection(); |
||
87 | } |
||
88 | |||
89 | 1 | public function reverseQuery(ReverseQuery $query): Collection |
|
90 | { |
||
91 | 1 | foreach ($this->providers as $provider) { |
|
92 | try { |
||
93 | 1 | $result = $provider->reverseQuery($query); |
|
94 | |||
95 | 1 | if (!$result->isEmpty()) { |
|
96 | 1 | return $result; |
|
97 | } |
||
98 | 1 | } catch (\Throwable $e) { |
|
99 | 1 | $coordinates = $query->getCoordinates(); |
|
100 | |||
101 | 1 | $this->log( |
|
102 | 1 | $this->reverseQueryLogLevel, |
|
103 | 1 | 'Provider "{providerName}" could not reverse geocode coordinates: {latitude}, {longitude}".', |
|
104 | 1 | [ |
|
105 | 1 | 'exception' => $e, |
|
106 | 1 | 'providerName' => $provider->getName(), |
|
107 | 1 | 'latitude' => $coordinates->getLatitude(), |
|
108 | 1 | 'longitude' => $coordinates->getLongitude(), |
|
109 | 1 | ] |
|
110 | 1 | ); |
|
111 | } |
||
112 | } |
||
113 | |||
114 | return new AddressCollection(); |
||
115 | } |
||
116 | |||
117 | 1 | public function getName(): string |
|
118 | { |
||
119 | 1 | return 'chain'; |
|
120 | } |
||
121 | |||
122 | /** |
||
123 | * Adds a provider. |
||
124 | */ |
||
125 | 1 | public function add(Provider $provider): self |
|
126 | { |
||
127 | 1 | $this->providers[] = $provider; |
|
128 | |||
129 | 1 | return $this; |
|
130 | } |
||
131 | |||
132 | 2 | private function log($level, $message, array $context = []) |
|
133 | { |
||
134 | 2 | if ($this->logger) { |
|
135 | $this->logger->log($level, $message, $context); |
||
136 | } |
||
137 | } |
||
138 | } |
||
139 |