Code

< 40 %
40-60 %
> 60 %
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