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;
14
15
use Geocoder\Exception\ProviderNotRegistered;
16
use Geocoder\Model\Coordinates;
17
use Geocoder\Provider\Provider;
18
use Geocoder\Query\GeocodeQuery;
19
use Geocoder\Query\ReverseQuery;
20
21
/**
22
 * @author William Durand <[email protected]>
23
 */
24
class ProviderAggregator implements Geocoder
25
{
26
    /**
27
     * @var Provider[]
28
     */
29
    private $providers = [];
30
31
    /**
32
     * @var Provider
33
     */
34
    private $provider;
35
36
    /**
37
     * @var int
38
     */
39
    private $limit;
40
41
    /**
42
     * A callable that decided what provider to use.
43
     *
44
     * @var callable
45
     */
46
    private $decider;
47
48 9
    public function __construct(callable $decider = null, int $limit = Geocoder::DEFAULT_RESULT_LIMIT)
49
    {
50 9
        $this->limit = $limit;
51 9
        $this->decider = $decider ?? __CLASS__.'::getProvider';
52
    }
53
54 1
    public function geocodeQuery(GeocodeQuery $query): Collection
55
    {
56 1
        return call_user_func($this->decider, $query, $this->providers, $this->provider)->geocodeQuery($query);
57
    }
58
59 1
    public function reverseQuery(ReverseQuery $query): Collection
60
    {
61 1
        return call_user_func($this->decider, $query, $this->providers, $this->provider)->reverseQuery($query);
62
    }
63
64
    public function getName(): string
65
    {
66
        return 'provider_aggregator';
67
    }
68
69 1
    public function geocode(string $value): Collection
70
    {
71 1
        return $this->geocodeQuery(GeocodeQuery::create($value)
72 1
            ->withLimit($this->limit));
73
    }
74
75 1
    public function reverse(float $latitude, float $longitude): Collection
76
    {
77 1
        return $this->reverseQuery(ReverseQuery::create(new Coordinates($latitude, $longitude))
78 1
            ->withLimit($this->limit));
79
    }
80
81
    /**
82
     * Registers a new provider to the aggregator.
83
     */
84 6
    public function registerProvider(Provider $provider): self
85
    {
86 6
        $this->providers[$provider->getName()] = $provider;
87
88 6
        return $this;
89
    }
90
91
    /**
92
     * Registers a set of providers.
93
     *
94
     * @param Provider[] $providers
95
     */
96 2
    public function registerProviders(array $providers = []): self
97
    {
98 2
        foreach ($providers as $provider) {
99 2
            $this->registerProvider($provider);
100
        }
101
102 2
        return $this;
103
    }
104
105
    /**
106
     * Sets the default provider to use.
107
     */
108 3
    public function using(string $name): self
109
    {
110 3
        if (!isset($this->providers[$name])) {
111 2
            throw ProviderNotRegistered::create($name, array_keys($this->providers));
112
        }
113
114 1
        $this->provider = $this->providers[$name];
115
116 1
        return $this;
117
    }
118
119
    /**
120
     * Returns all registered providers indexed by their name.
121
     *
122
     * @return Provider[]
123
     */
124 1
    public function getProviders(): array
125
    {
126 1
        return $this->providers;
127
    }
128
129
    /**
130
     * Get a provider to use for this query.
131
     *
132
     * @param GeocodeQuery|ReverseQuery $query
133
     * @param Provider[]                $providers
134
     * @param Provider                  $currentProvider
135
     *
136
     * @throws ProviderNotRegistered
137
     */
138 4
    private static function getProvider($query, array $providers, Provider $currentProvider = null): Provider
139
    {
140 4
        if (null !== $currentProvider) {
141 2
            return $currentProvider;
142
        }
143
144 3
        if ([] === $providers) {
145 1
            throw ProviderNotRegistered::noProviderRegistered();
146
        }
147
148
        // Take first
149 2
        $key = key($providers);
150
151 2
        return $providers[$key];
152
    }
153
}
154