Completed
Push — master ( db6fea...5e07c3 )
by Andreu
02:48 queued 01:21
created

CurrencyFactory::buildFromISOCode()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5.0144

Importance

Changes 0
Metric Value
dl 0
loc 20
c 0
b 0
f 0
ccs 11
cts 12
cp 0.9167
rs 8.8571
cc 5
eloc 13
nc 3
nop 1
crap 5.0144
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Adsmurai\Currency;
6
7
use Adsmurai\Currency\Contracts\Currency as CurrencyContract;
8
use Adsmurai\Currency\Contracts\CurrencyFactory as CurrencyFactoryContract;
9
use Adsmurai\Currency\Errors\InvalidCurrenciesDataError;
10
use Adsmurai\Currency\Errors\UnsupportedCurrencyISOCodeError;
11
12
final class CurrencyFactory implements CurrencyFactoryContract
13
{
14
    const DEFAULT_DATA_PATH = __DIR__.'/Data/CurrencyTypes.php';
15
16
    /** @var array */
17
    private $data;
18
19
    /** @var Currency[] */
20
    private $currencies;
21
22 112
    private function __construct(array $data)
23
    {
24 112
        $this->data = $data;
25 112
        $this->currencies = [];
26 112
    }
27
28 112
    public static function fromDataPath(string $dataPath = self::DEFAULT_DATA_PATH): CurrencyFactory
29
    {
30
        /** @var array $data */
31 112
        $data = include $dataPath;
32
33 112
        return self::fromDataArray($data);
34
    }
35
36 122
    public static function fromDataArray(array $data): CurrencyFactory
37
    {
38 122
        self::validateCurrenciesData($data);
39
40 112
        return new self($data);
41
    }
42
43
    /**
44
     * @param array $currenciesData
45
     *
46
     * @throws InvalidCurrenciesDataError
47
     */
48 122
    private static function validateCurrenciesData(array $currenciesData)
49
    {
50 122
        if (empty($currenciesData)) {
51 1
            throw new InvalidCurrenciesDataError();
52
        }
53
54 121
        foreach ($currenciesData as $ISOCode => $currencyData) {
55
            if (
56 121
                !self::hasValidISOCode($ISOCode)
57 121
                || !self::hasValidSymbol($currencyData)
58 121
                || !self::hasValidSymbolPlacement($currencyData)
59 121
                || !self::hasValidNumFractionalDigits($currencyData)
60
            ) {
61 121
                throw new InvalidCurrenciesDataError();
62
            }
63
        }
64 112
    }
65
66 112
    private static function hasValidISOCode($ISOCode): bool
67
    {
68 112
        return \is_string($ISOCode) && !empty($ISOCode);
69
    }
70
71 112
    private static function hasValidSymbol(array $currencyData): bool
72
    {
73
        return
74 112
            isset($currencyData['symbol'])
75 112
            && \is_string($currencyData['symbol'])
76 112
            && !empty($currencyData['symbol']);
77
    }
78
79 112
    private static function hasValidSymbolPlacement(array $currencyData): bool
80
    {
81
        return
82 112
            isset($currencyData['symbolPlacement'])
83 112
            && \is_int($currencyData['symbolPlacement'])
84 112
            && \in_array(
85 112
                $currencyData['symbolPlacement'],
86
                [
87 112
                    CurrencyContract::BEFORE_PLACEMENT,
88 112
                    CurrencyContract::AFTER_PLACEMENT,
89
                ]
90
            );
91
    }
92
93 112
    private static function hasValidNumFractionalDigits(array $currencyData): bool
94
    {
95 112
        return isset($currencyData['numFractionalDigits']) && \is_int($currencyData['numFractionalDigits']);
96
    }
97
98 113
    public function buildFromISOCode(string $ISOCode): CurrencyContract
99
    {
100 113
        if (!isset($this->data[$ISOCode])) {
101 1
            throw new UnsupportedCurrencyISOCodeError($ISOCode);
102
        }
103
104 112
        if (!isset($this->currencies[$ISOCode])) {
105 112
            $this->currencies[$ISOCode] = new Currency(
106
                $ISOCode,
107 112
                $this->data[$ISOCode]['symbol'],
108 112
                $this->data[$ISOCode]['numFractionalDigits'],
109 112
                $this->data[$ISOCode]['symbolPlacement'],
110 112
                (isset($this->data[$ISOCode]['name']) && !empty($this->data[$ISOCode]['name']))
111
                    ? $this->data[$ISOCode]['name']
112 112
                    : ''
113
            );
114
        }
115
116 112
        return $this->currencies[$ISOCode];
117
    }
118
119
    /** @return string[] */
120 1
    public function getSupportedCurrencyISOCodes(): array
121
    {
122 1
        return \array_keys($this->data);
123
    }
124
}
125