Completed
Push — master ( f2ed00...07b62e )
by Antonio Carlos
05:36
created

Hydrator::fixCurrencies()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 3
rs 9.4285
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 31
    public function __construct($config)
52
    {
53 31
        $this->config = $config;
54 31
    }
55
56
    /**
57
     * Can hydrate?
58
     *
59
     * @param $element
60
     * @param $enabled
61
     * @param $countryCode
62
     * @return bool
63
     */
64 20
    protected function canHydrate($element, $enabled, $countryCode)
65
    {
66 20
        return ($enabled || $this->config->get('hydrate.elements.'.$element)) &&
67 20
                ! isset($this->repository->countries[$countryCode]['hydrated'][$element]);
68
    }
69
70
    /**
71
     * @param $countryCode
72
     */
73 20
    protected function createHydrated($countryCode)
74
    {
75 20
        if (! isset($this->repository->countries[$countryCode]['hydrated'])) {
76 20
            $this->repository->countries[$countryCode]['hydrated'] = [];
77
        }
78
79 20
        return $this->repository->countries[$countryCode]['hydrated'];
80
    }
81
82 7
    protected function fixCurrencies($country)
83
    {
84 7
        if (! isset($country['currencies']) && isset($country['currency'])) {
85 1
            $country['currencies'] = $country['currency'];
86
        }
87
88 7
        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 3
    private function hydrateCountries($countries, $elements = null)
99
    {
100 3
        return countriesCollect(
101 3
            $countries->map(function ($country) use ($elements) {
102 3
                return $this->hydrateCountry($country, $elements);
103 3
            })
104
        );
105
    }
106
107
    /**
108
     * Hydrate elements of a country.
109
     *
110
     * @param $country
111
     * @param $elements
112
     * @return mixed
113
     */
114 20
    private function hydrateCountry($country, $elements)
115
    {
116 20
        $countryCode = $country['cca3'];
117
118 20
        $this->addCountry($countryCode, $country);
119
120 20
        foreach ($elements as $element => $enabled) {
121 20
            $this->hydrateCountryElement($countryCode, $element, $enabled);
122
        }
123
124 20
        return $this->getCountry($countryCode);
125
    }
126
127
    /**
128
     * Check if an element is a country.
129
     *
130
     * @param $element
131
     * @return bool
132
     */
133 20
    private function isCountry($element)
134
    {
135 20
        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 7
    private function isCurrenciesArray($data)
145
    {
146 7
        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 3
    private function loadCities($country)
156
    {
157 3
        return $this->repository->getHelper()->loadJson($country['cca3'], 'cities/default')
158 3
                ->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 8
    private function loadStates($country)
168
    {
169 8
        return $this->repository->getHelper()->loadJson($country['cca3'], 'states/default')
170 8
                ->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 3
    private function loadTaxes($country)
180
    {
181 3
        return $this->repository->getHelper()->loadJson($country['cca3'], 'taxes/default')
182 3
                                ->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 20
    protected function needsHydration($countryCode, $element, $enabled = false)
194
    {
195 20
        if (! $this->canHydrate($element, $enabled, $countryCode)) {
196
            return false;
197
        }
198
199 20
        return $this->updateHydrated($countryCode, $element);
200
    }
201
202
    /**
203
     * Hydrate cities.
204
     *
205
     * @param $country
206
     * @return mixed
207
     */
208 3
    public function hydrateCities($country)
209
    {
210 3
        $country['cities'] = $this->loadCities($country);
211
212 3
        return $country;
213
    }
214
215
    /**
216
     * Hydrate states.
217
     *
218
     * @param $country
219
     * @return mixed
220
     */
221 8
    public function hydrateStates($country)
222
    {
223 8
        $country['states'] = $this->loadStates($country);
224
225 8
        return $country;
226
    }
227
228
    /**
229
     * Hydrate taxes.
230
     *
231
     * @param $country
232
     * @return Coollection
233
     */
234 3
    public function hydrateTaxes($country)
235
    {
236 3
        $country['taxes'] = $this->loadTaxes($country);
237
238 3
        return $country;
239
    }
240
241
    /**
242
     * Hydrate topoloy.
243
     *
244
     * @param $country
245
     * @return mixed
246
     */
247 2
    public function hydrateTopology($country)
248
    {
249 2
        $country['topology'] = $this->repository->getTopology($country['cca3']);
250
251 2
        return $country;
252
    }
253
254
    /**
255
     * Hydrate geometry.
256
     *
257
     * @param $country
258
     * @return mixed
259
     */
260 2
    public function hydrateGeometry($country)
261
    {
262 2
        $country['geometry'] = $this->repository->getGeometry($country['cca3']);
263
264 2
        return $country;
265
    }
266
267
    /**
268
     * Get hydration elements.
269
     *
270
     * @param $elements
271
     * @return array|string|mixed
272
     */
273 31
    protected function getHydrationElements($elements)
274
    {
275 31
        $elements = ($elements ?: $this->config->get('hydrate.elements'));
276
277 31
        if (is_string($elements) || is_numeric($elements)) {
278 18
            return [$elements => true];
279
        }
280
281 31
        return $this->checkHydrationElements($elements);
282
    }
283
284
    /**
285
     * Hydrate flag.
286
     *
287
     * @param $country
288
     * @return mixed
289
     */
290 2
    public function hydrateFlag($country)
291
    {
292 2
        $country = countriesCollect($country)->overwrite(
293 2
            ['flag' => $this->repository->makeAllFlags($country)]
294
        );
295
296 2
        return $country;
297
    }
298
299
    /**
300
     * Hydrate borders.
301
     *
302
     * @param $country
303
     * @return mixed
304
     */
305 5
    public function hydrateBorders($country)
306
    {
307 5
        $country['borders'] = isset($country['borders'])
308 5
            ? $country['borders'] = countriesCollect($country['borders'])->map(function ($border) {
309 4
                return $this->repository->call('where', ['cca3', $border])->first();
310 5
            })
311 1
            : countriesCollect();
312
313 5
        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 1
    public function hydrateTimezonesTimes($country)
334
    {
335 1
        $country = $this->hydrateTimezones($country);
336
337 1
        $country['timezones'] = $country->timezones->map(function ($timezone) {
338 1
            return $timezone->overwrite(['times' => $this->repository->findTimezoneTime($timezone['zone_id'])]);
339 1
        });
340
341 1
        return $country;
342
    }
343
344
    /**
345
     * Hydrate currencies.
346
     *
347
     * @param $country
348
     * @return mixed
349
     */
350 7
    public function hydrateCurrencies($country)
351
    {
352 7
        $currencies = [];
353
354 7
        $country = $this->fixCurrencies($country);
355
356 7
        if (isset($country['currencies'])) {
357 7
            $currencies = countriesCollect($country['currencies'])->mapWithKeys(function ($code) {
358 7
                if ($this->isCurrenciesArray($code)) {
359
                    return [
360
                        $code['ISO4217Code'] => $code,
361
                    ];
362
                }
363
364
                return [
365 7
                    $code => $this->repository->loadCurrenciesForCountry($code),
366
                ];
367 7
            });
368
        }
369
370 7
        $country['currencies'] = $currencies;
371
372 7
        return $country;
373
    }
374
375
    /**
376
     * Hydrate a countries collection with languages.
377
     *
378
     * @param \PragmaRX\Coollection\Package\Coollection|array|\stdClass $target
379
     * @param null $elements
380
     * @return \PragmaRX\Coollection\Package\Coollection
381
     */
382 31
    public function hydrate($target, $elements = null)
383
    {
384 31
        $elements = $this->getHydrationElements($elements);
385
386 31
        if (coollect($elements)->count() === 0) {
387 31
            return $target;
388
        }
389
390 20
        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...
391 17
            ? $this->hydrateCountry($target, $elements)
392 20
            : $this->hydrateCountries($target, $elements);
393
    }
394
395
    /**
396
     * Get country by country code.
397
     *
398
     * @param $countryCode
399
     * @return mixed
400
     */
401 20
    public function getCountry($countryCode)
402
    {
403 20
        return countriesCollect($this->repository->countries[$countryCode]);
404
    }
405
406
    /**
407
     * Check and create a country in the repository.
408
     *
409
     * @param $country
410
     * @param $countryCode
411
     */
412 20
    public function addCountry($countryCode, $country)
413
    {
414 20
        if (! isset($this->repository->countries[$countryCode])) {
415 20
            $this->repository->countries[$countryCode] = $country;
416
        }
417 20
    }
418
419
    /**
420
     * Hydrate a country element.
421
     *
422
     * @param $countryCode
423
     * @param $element
424
     * @param $enabled
425
     */
426 20
    public function hydrateCountryElement($countryCode, $element, $enabled)
427
    {
428 20
        if ($this->needsHydration($countryCode, $element, $enabled)) {
429 20
            $this->repository->countries[$countryCode] = $this->{'hydrate'.Str::studly($element)}($this->repository->countries[$countryCode]);
430
        }
431 20
    }
432
433
    /**
434
     * Check hydration elements.
435
     *
436
     * @param $elements
437
     * @return static
438
     */
439
    protected function checkHydrationElements($elements)
440
    {
441 31
        $elements = countriesCollect($elements)->mapWithKeys(function ($value, $key) {
442 31
            if (is_numeric($key)) {
443 1
                $key = $value;
444 1
                $value = true;
445
            }
446
447 31
            return [$key => $value];
448
        })->filter(function ($element) {
449 31
            return $element;
450 31
        });
451
452 31
        return $elements;
453
    }
454
455
    /**
456
     * Repository setter.
457
     *
458
     * @param $repository
459
     */
460 31
    public function setRepository($repository)
461
    {
462 31
        $this->repository = $repository;
463 31
    }
464
465
    /**
466
     * Update hydrated.
467
     *
468
     * @param $countryCode
469
     * @param $element
470
     * @return bool
471
     */
472 20
    protected function updateHydrated($countryCode, $element)
473
    {
474 20
        $hydrated = $this->createHydrated($countryCode);
475
476 20
        $hydrated[$element] = true;
477
478 20
        $this->repository->countries[$countryCode]['hydrated'] = $hydrated;
479
480 20
        return true;
481
    }
482
}
483