Completed
Push — master ( dd8ca6...ed1ab1 )
by Antonio Carlos
06:33 queued 01:44
created

Hydrator::fixCurrencies()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 1
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PragmaRX\Countries\Package\Services;
4
5
use IlluminateAgnostic\Str\Support\Str;
6
use PragmaRX\Coollection\Package\Coollection;
7
8
class Hydrator
9
{
10
    /**
11
     * All hydrators.
12
     *
13
     * @var
14
     */
15
    const HYDRATORS = [
16
        'borders',
17
        'cities',
18
        'collection',
19
        'countries',
20
        'country',
21
        'currencies',
22
        'flag',
23
        'geometry',
24
        'natural_earth_data',
25
        'states',
26
        'taxes',
27
        'timezones',
28
        'timezones_times',
29
        'topology',
30
    ];
31
32
    /**
33
     * Countries repository.
34
     *
35
     * @var Repository
36
     */
37
    protected $repository;
38
39
    /**
40
     * Config.
41
     *
42
     * @var Config
43
     */
44
    protected $config;
45
46
    /**
47
     * Hydrator constructor.
48
     *
49
     * @param object $config
50
     */
51 34
    public function __construct($config)
52
    {
53 34
        $this->config = $config;
54 34
    }
55
56
    /**
57
     * Can hydrate?
58
     *
59
     * @param $element
60
     * @param $enabled
61
     * @param $countryCode
62
     * @return bool
63
     */
64 31
    protected function canHydrate($element, $enabled, $countryCode)
65
    {
66 31
        return ($enabled || $this->config->get('hydrate.elements.'.$element)) &&
67 31
                ! isset($this->repository->countries[$countryCode]['hydrated'][$element]);
68
    }
69
70
    /**
71
     * @param $countryCode
72
     */
73 31
    protected function createHydrated($countryCode)
74
    {
75 31
        if (! isset($this->repository->countries[$countryCode]['hydrated'])) {
76 31
            $this->repository->countries[$countryCode]['hydrated'] = [];
77
        }
78
79 31
        return $this->repository->countries[$countryCode]['hydrated'];
80
    }
81
82 6
    protected function fixCurrencies($country)
83
    {
84 6
        if (! isset($country['currencies']) && isset($country['currency'])) {
85 1
            $country['currencies'] = $country['currency'];
86
        }
87
88 6
        return $country;
89
    }
90
91
    /**
92
     * Hydrate elements of a collection of countries.
93
     *
94
     * @param $countries
95
     * @param $elements
96
     * @return mixed
97
     */
98 32
    private function hydrateCountries($countries, $elements = null)
99
    {
100 32
        return countriesCollect(
101
            $countries->map(function ($country) use ($elements) {
102 31
                return $this->hydrateCountry($country, $elements);
103 32
            })
104
        );
105
    }
106
107
    /**
108
     * Hydrate elements of a country.
109
     *
110
     * @param $country
111
     * @param $elements
112
     * @return mixed
113
     */
114 31
    private function hydrateCountry($country, $elements)
115
    {
116 31
        $countryCode = $country['cca3'];
117
118 31
        $this->addCountry($countryCode, $country);
119
120 31
        foreach ($elements as $element => $enabled) {
121 31
            $this->hydrateCountryElement($countryCode, $element, $enabled);
122
        }
123
124 31
        return $this->getCountry($countryCode);
125
    }
126
127
    /**
128
     * Check if an element is a country.
129
     *
130
     * @param $element
131
     * @return bool
132
     */
133 32
    private function isCountry($element)
134
    {
135 32
        return ($element instanceof Coollection || \is_array($element)) && isset($element['cca3']);
136
    }
137
138
    /**
139
     * Check it's a currencies array or code.
140
     *
141
     * @param $data
142
     * @return bool
143
     */
144 6
    private function isCurrenciesArray($data)
145
    {
146 6
        return \is_array($data) && isset($data['ISO4217Code']);
147
    }
148
149
    /**
150
     * Load the cities file and merge overloads.
151
     *
152
     * @param $country
153
     * @return mixed
154
     */
155 2
    private function loadCities($country)
156
    {
157 2
        return $this->repository->getHelper()->loadJson($country['cca3'], 'cities/default')
158 2
                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'cities/overload'));
159
    }
160
161
    /**
162
     * Load the states file and merge overloads.
163
     *
164
     * @param $country
165
     * @return mixed
166
     */
167 7
    private function loadStates($country)
168
    {
169 7
        return $this->repository->getHelper()->loadJson($country['cca3'], 'states/default')
170 7
                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'states/overload'));
171
    }
172
173
    /**
174
     * Load the taxes file and merge overloads.
175
     *
176
     * @param $country
177
     * @return mixed
178
     */
179 2
    private function loadTaxes($country)
180
    {
181 2
        return $this->repository->getHelper()->loadJson($country['cca3'], 'taxes/default')
182 2
                                ->overwrite($this->repository->getHelper()->loadJson($country['cca3'], 'taxes/overload'));
183
    }
184
185
    /**
186
     * Check if an element needs hydrated.
187
     *
188
     * @param $countryCode
189
     * @param $element
190
     * @param bool $enabled
191
     * @return bool
192
     */
193 31
    protected function needsHydration($countryCode, $element, $enabled = false)
194
    {
195 31
        if (! $this->canHydrate($element, $enabled, $countryCode)) {
196 29
            return false;
197
        }
198
199 31
        return $this->updateHydrated($countryCode, $element);
200
    }
201
202
    /**
203
     * Hydrate cities.
204
     *
205
     * @param $country
206
     * @return mixed
207
     */
208 2
    public function hydrateCities($country)
209
    {
210 2
        $country['cities'] = $this->loadCities($country);
211
212 2
        return $country;
213
    }
214
215
    /**
216
     * Hydrate states.
217
     *
218
     * @param $country
219
     * @return mixed
220
     */
221 7
    public function hydrateStates($country)
222
    {
223 7
        $country['states'] = $this->loadStates($country);
224
225 7
        return $country;
226
    }
227
228
    /**
229
     * Hydrate taxes.
230
     *
231
     * @param $country
232
     * @return Coollection
233
     */
234 2
    public function hydrateTaxes($country)
235
    {
236 2
        $country['taxes'] = $this->loadTaxes($country);
237
238 2
        return $country;
239
    }
240
241
    /**
242
     * Hydrate topoloy.
243
     *
244
     * @param $country
245
     * @return mixed
246
     */
247 1
    public function hydrateTopology($country)
248
    {
249 1
        $country['topology'] = $this->repository->getTopology($country['cca3']);
250
251 1
        return $country;
252
    }
253
254
    /**
255
     * Hydrate geometry.
256
     *
257
     * @param $country
258
     * @return mixed
259
     */
260 1
    public function hydrateGeometry($country)
261
    {
262 1
        $country['geometry'] = $this->repository->getGeometry($country['cca3']);
263
264 1
        return $country;
265
    }
266
267
    /**
268
     * Get hydration elements.
269
     *
270
     * @param $elements
271
     * @return array|string|mixed
272
     */
273 32
    protected function getHydrationElements($elements)
274
    {
275 32
        $elements = ($elements ?: $this->config->get('hydrate.elements'));
276
277 32
        if (\is_string($elements) || is_numeric($elements)) {
278 19
            return [$elements => true];
279
        }
280
281 32
        return $this->checkHydrationElements($elements);
282
    }
283
284
    /**
285
     * Hydrate flag.
286
     *
287
     * @param $country
288
     * @return mixed
289
     */
290 31
    public function hydrateFlag($country)
291
    {
292 31
        $country = countriesCollect($country)->overwrite(
293 31
            ['flag' => $this->repository->makeAllFlags($country)]
294
        );
295
296 31
        return $country;
297
    }
298
299
    /**
300
     * Hydrate borders.
301
     *
302
     * @param $country
303
     * @return mixed
304
     */
305 4
    public function hydrateBorders($country)
306
    {
307 4
        $country['borders'] = isset($country['borders'])
308
            ? $country['borders'] = countriesCollect($country['borders'])->map(function ($border) {
309 3
                return $this->repository->call('where', ['cca3', $border])->first();
310 4
            })
311 1
            : countriesCollect();
312
313 4
        return $country;
314
    }
315
316
    /**
317
     * Hydrate timezones.
318
     *
319
     * @param $country
320
     * @return mixed
321
     */
322 5
    public function hydrateTimezones($country)
323
    {
324 5
        return $country->overwrite(['timezones' => $this->repository->findTimezones($country['cca3'])]);
325
    }
326
327
    /**
328
     * Hydrate all times for a country timezones.
329
     *
330
     * @param $country
331
     * @return mixed
332
     */
333 2
    public function hydrateTimezonesTimes($country)
334
    {
335 2
        $country = $this->hydrateTimezones($country);
336
337
        $country['timezones'] = $country->timezones->map(function ($timezone) {
338 2
            return $timezone->overwrite(['times' => $this->repository->findTimezoneTime($timezone['zone_id'])]);
339 2
        });
340
341 2
        return $country;
342
    }
343
344
    /**
345
     * Hydrate currencies.
346
     *
347
     * @param $country
348
     * @return mixed
349
     */
350 6
    public function hydrateCurrencies($country)
351
    {
352 6
        $currencies = [];
353
354 6
        $country = $this->fixCurrencies($country);
355
356 6
        if (isset($country['currencies'])) {
357
            $currencies = countriesCollect($country['currencies'])->mapWithKeys(function ($code, $currencyCode) use ($country) {
358 6
                if ($this->isCurrenciesArray($code)) {
359
                    return [
360
                        $code['ISO4217Code'] => $code,
361
                    ];
362
                }
363
364 6
                if (is_object($code)) {
365 1
                    $code = $currencyCode;
366
                }
367
368
                return [
369 6
                    $code => $this->repository->loadCurrenciesForCountry($code),
370
                ];
371 6
            });
372
        }
373
374 6
        $country['currencies'] = $currencies;
375
376 6
        return $country;
377
    }
378
379
    /**
380
     * Hydrate a countries collection with languages.
381
     *
382
     * @param \PragmaRX\Coollection\Package\Coollection|array|\stdClass $target
383
     * @param null $elements
384
     * @return \PragmaRX\Coollection\Package\Coollection
385
     */
386 32
    public function hydrate($target, $elements = null)
387
    {
388 32
        $elements = $this->getHydrationElements($elements);
389
390 32
        if (coollect($elements)->count() === 0) {
391
            return $target;
392
        }
393
394 32
        return $this->isCountry($target->toArray())
0 ignored issues
show
Bug introduced by
The method toArray does only exist in PragmaRX\Coollection\Package\Coollection, but not in stdClass.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
395 17
            ? $this->hydrateCountry($target, $elements)
396 32
            : $this->hydrateCountries($target, $elements);
397
    }
398
399
    /**
400
     * Get country by country code.
401
     *
402
     * @param $countryCode
403
     * @return mixed
404
     */
405 31
    public function getCountry($countryCode)
406
    {
407 31
        return countriesCollect($this->repository->countries[$countryCode]);
408
    }
409
410
    /**
411
     * Check and create a country in the repository.
412
     *
413
     * @param $country
414
     * @param $countryCode
415
     */
416 31
    public function addCountry($countryCode, $country)
417
    {
418 31
        if (! isset($this->repository->countries[$countryCode])) {
419 31
            $this->repository->countries[$countryCode] = $country;
420
        }
421 31
    }
422
423
    /**
424
     * Hydrate a country element.
425
     *
426
     * @param $countryCode
427
     * @param $element
428
     * @param $enabled
429
     */
430 31
    public function hydrateCountryElement($countryCode, $element, $enabled)
431
    {
432 31
        if ($this->needsHydration($countryCode, $element, $enabled)) {
433 31
            $this->repository->countries[$countryCode] = $this->{'hydrate'.Str::studly($element)}($this->repository->countries[$countryCode]);
434
        }
435 31
    }
436
437
    /**
438
     * Check hydration elements.
439
     *
440
     * @param $elements
441
     * @return static
442
     */
443 32
    protected function checkHydrationElements($elements)
444
    {
445
        $elements = countriesCollect($elements)->mapWithKeys(function ($value, $key) {
446 32
            if (is_numeric($key)) {
447
                $key = $value;
448
                $value = true;
449
            }
450
451 32
            return [$key => $value];
452
        })->filter(function ($element) {
453 32
            return $element;
454 32
        });
455
456 32
        return $elements;
457
    }
458
459
    /**
460
     * Repository setter.
461
     *
462
     * @param $repository
463
     */
464 34
    public function setRepository($repository)
465
    {
466 34
        $this->repository = $repository;
467 34
    }
468
469
    /**
470
     * Update hydrated.
471
     *
472
     * @param $countryCode
473
     * @param $element
474
     * @return bool
475
     */
476 31
    protected function updateHydrated($countryCode, $element)
477
    {
478 31
        $hydrated = $this->createHydrated($countryCode);
479
480 31
        $hydrated[$element] = true;
481
482 31
        $this->repository->countries[$countryCode]['hydrated'] = $hydrated;
483
484 31
        return true;
485
    }
486
}
487