Completed
Push — master ( 792da3...114083 )
by Mike
56:58
created

ProviderAndDumperAggregator::toJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php namespace Geocoder\Laravel;
2
3
/**
4
 * This file is part of the Geocoder Laravel package.
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author Mike Bronner <[email protected]>
9
 * @license    MIT License
10
 */
11
12
use Geocoder\Dumper\GeoJson;
13
use Geocoder\Dumper\Gpx;
14
use Geocoder\Dumper\Kml;
15
use Geocoder\Dumper\Wkb;
16
use Geocoder\Dumper\Wkt;
17
use Geocoder\Geocoder;
18
use Geocoder\Laravel\Exceptions\InvalidDumperException;
19
use Geocoder\ProviderAggregator;
20
use Geocoder\Query\GeocodeQuery;
21
use Geocoder\Query\Query;
22
use Geocoder\Query\ReverseQuery;
23
use Illuminate\Support\Collection;
24
use ReflectionClass;
25
26
/**
27
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
28
 */
29
class ProviderAndDumperAggregator
30
{
31
    protected $aggregator;
32
    protected $limit;
33
    protected $results;
34 24
35
    public function __construct()
36 24
    {
37 24
        $this->aggregator = new ProviderAggregator();
38 24
        $this->results = collect();
39
    }
40
41
    /**
42
     * @deprecated Use `get()` instead.
43 1
     */
44
    public function all() : array
45 1
    {
46
        return $this->results->all();
47
    }
48 17
49
    public function get() : Collection
50 17
    {
51
        return $this->results;
52
    }
53 2
54
    public function toJson() : string
55 2
    {
56 2
        return $this
57
            ->dump("geojson")
58
            ->first();
59
    }
60
61
    public function dump(string $dumper) : Collection
62
    {
63 2
        $dumperClasses = collect([
64 1
            'geojson' => GeoJson::class,
65 1
            'gpx' => Gpx::class,
66 1
            'kml' => Kml::class,
67
            'wkb' => Wkb::class,
68 1
            'wkt' => Wkt::class,
69
        ]);
70
71 1
        if (!$dumperClasses->has($dumper)) {
72 1
            $errorMessage = implode('', [
73 1
                "The dumper specified ('{$dumper}') is invalid. Valid dumpers ",
74
                "are: geojson, gpx, kml, wkb, wkt.",
75 1
            ]);
76 1
            throw new InvalidDumperException($errorMessage);
77 1
        }
78
79
        $dumperClass = $dumperClasses->get($dumper);
80 1
        $dumper = new $dumperClass;
81
        $results = collect($this->results->all());
82 1
83 1
        return $results->map(function ($result) use ($dumper) {
84 1
            return $dumper->dump($result);
85 1
        });
86 1
    }
87 1
88 1 View Code Duplication
    public function geocode(string $value) : self
89
    {
90
        $cacheKey = str_slug(strtolower(urlencode($value)));
91 1
        $this->results = $this->cacheRequest($cacheKey, [$value], "geocode");
92
93 1
        return $this;
94
    }
95
96 1
    public function geocodeQuery(GeocodeQuery $query) : self
97
    {
98 1
        $cacheKey = serialize($query);
99 1
        $this->results = $this->cacheRequest($cacheKey, [$query], "geocodeQuery");
100 1
101 1
        return $this;
102 1
    }
103 1
104 1
    public function getLimit() : int
105
    {
106
        return $this->limit;
107 1
    }
108
109 1
    public function getName() : string
110
    {
111
        return $this->aggregator->getName();
112 1
    }
113
114 1
    public function limit(int $limit) : self
115
    {
116
        $this->aggregator = new ProviderAggregator(null, $limit);
117 16
        $this->registerProvidersFromConfig(collect(config('geocoder.providers')));
118
        $this->limit = $limit;
119 16
120 16
        return $this;
121 16
    }
122 16
123 16
    /**
124 16
     * @deprecated Use `getProviders()` instead.
125 16
     */
126
    public function getProvider()
127
    {
128 16
        return $this->getProviders()->first();
129
    }
130 16
131
    public function getProviders() : Collection
132
    {
133 1
        return collect($this->aggregator->getProviders());
134
    }
135 1
136 1
    public function registerProvider($provider) : self
137 1
    {
138 1
        $this->aggregator->registerProvider($provider);
139 1
140 1
        return $this;
141 1
    }
142
143
    public function registerProviders(array $providers = []) : self
144 1
    {
145
        $this->aggregator->registerProviders($providers);
146 1
147
        return $this;
148
    }
149 1
150
    public function registerProvidersFromConfig(Collection $providers) : self
151 1
    {
152 1
        $this->registerProviders($this->getProvidersFromConfiguration($providers));
153 1
154
        return $this;
155 1
    }
156
157 View Code Duplication
    public function reverse(float $latitude, float $longitude) : self
158 1
    {
159
        $cacheKey = str_slug(strtolower(urlencode("{$latitude}-{$longitude}")));
160 1
        $this->results = $this->cacheRequest($cacheKey, [$latitude, $longitude], "reverse");
161
162
        return $this;
163 1
    }
164
165 1
    public function reverseQuery(ReverseQuery $query) : self
166
    {
167 1
        $cacheKey = serialize($query);
168
        $this->results = $this->cacheRequest($cacheKey, [$query], "reverseQuery");
169
170 24
        return $this;
171
    }
172 24
173
    public function using(string $name) : self
174 24
    {
175
        $this->aggregator = $this->aggregator->using($name);
176
177 5
        return $this;
178
    }
179 5
180
    protected function cacheRequest(string $cacheKey, array $queryElements, string $queryType)
181 5
    {
182
        $hashedCacheKey = sha1($cacheKey);
183
        $duration = config("geocoder.cache.duration", 0);
184 2
        $store = config('geocoder.cache.store');
185
186 2
        $result = app("cache")
187
            ->store($store)
188
            ->remember($hashedCacheKey, $duration, function () use ($cacheKey, $queryElements, $queryType) {
189
                return [
190
                    "key" => $cacheKey,
191
                    "value" => collect($this->aggregator->{$queryType}(...$queryElements)),
192 1
                ];
193
            });
194 1
        $result = $this->preventCacheKeyHashCollision(
195
            $result,
196
            $hashedCacheKey,
197 24
            $cacheKey,
198
            $queryElements,
199 24
            $queryType
200
        );
201 24
        $this->removeEmptyCacheEntry($result, $hashedCacheKey);
202
203
        return $result;
204
    }
205
206 24
    protected function getAdapterClass(string $provider) : string
207 24
    {
208 24
        $specificAdapters = collect([
209
            'Geocoder\Provider\GeoIP2\GeoIP2' => 'Geocoder\Provider\GeoIP2\GeoIP2Adapter',
210 24
            'Geocoder\Provider\MaxMindBinary\MaxMindBinary' => '',
211 24
        ]);
212
213
        if ($specificAdapters->has($provider)) {
214 24
            return $specificAdapters->get($provider);
215 24
        }
216
217 24
        return config('geocoder.adapter');
218
    }
219
220 24
    protected function getArguments(array $arguments, string $provider) : array
221
    {
222 24
        if ($provider === 'Geocoder\Provider\Chain\Chain') {
223 24
            return $this->getProvidersFromConfiguration(
224 24
                collect(config('geocoder.providers.Geocoder\Provider\Chain\Chain'))
225
            );
226
        }
227
228 24
        $adapter = $this->getAdapterClass($provider);
229
        $reader = null;
230 24
231 24
        if ($adapter) {
232
            if ($this->requiresReader($provider)) {
233
                $reader = config('geocoder.reader');
234 24
            }
235
236
            array_unshift($arguments, new $adapter($reader));
237 24
        }
238
239 24
        return $arguments;
240 24
    }
241
242
    protected function getProvidersFromConfiguration(Collection $providers) : array
243
    {
244 24
        $providers = $providers->map(function ($arguments, $provider) {
245
            $arguments = $this->getArguments($arguments, $provider);
246
            $reflection = new ReflectionClass($provider);
247
248 24
            if ($provider === 'Geocoder\Provider\Chain\Chain') {
249
                return $reflection->newInstance($arguments);
250
            }
251 19
252
            return $reflection->newInstanceArgs($arguments);
253 19
        });
254
255 19
        return $providers->toArray();
256 1
    }
257
258 19
    protected function preventCacheKeyHashCollision(
259
        array $result,
260
        string $hashedCacheKey,
261
        string $cacheKey,
262
        array $queryElements,
263
        string $queryType
264
    ) {
265
        if ($result["key"] === $cacheKey) {
266
            return $result["value"];
267
        }
268
269
        app("cache")
270
            ->store(config('geocoder.cache.store'))
271
            ->forget($hashedCacheKey);
272
273
        return $this->cacheRequest($cacheKey, $queryElements, $queryType);
274
    }
275
276
    protected function removeEmptyCacheEntry(Collection $result, string $cacheKey)
277
    {
278
        if ($result && $result->isEmpty()) {
279
            app('cache')->forget($cacheKey);
280
        }
281
    }
282
283
    protected function requiresReader(string $class) : bool
284
    {
285
        $specificAdapters = collect([
286
            'Geocoder\Provider\GeoIP2\GeoIP2',
287
        ]);
288
289
        return $specificAdapters->contains($class);
290
    }
291
}
292