Completed
Push — master ( ca4577...8a3c51 )
by BENOIT
02:50
created

CurrencyLayerProvider::getExchangeRate()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 20
nop 3
1
<?php
2
3
namespace BenTools\Currency\Provider;
4
5
use BenTools\Currency\Model\CurrencyInterface;
6
use BenTools\Currency\Model\ExchangeRateFactoryInterface;
7
use BenTools\Currency\Model\ExchangeRateInterface;
8
use BenTools\Currency\Model\ExchangeRateNotFoundException;
9
use BenTools\Currency\Model\NativeExchangeRateFactory;
10
use DateTime;
11
use DateTimeImmutable;
12
use DateTimeInterface;
13
use DateTimeZone;
14
use Http\Client\HttpClient;
15
use Http\Discovery\HttpClientDiscovery;
16
use Http\Discovery\MessageFactoryDiscovery;
17
use Http\Message\RequestFactory;
18
use Psr\SimpleCache\CacheInterface;
19
20
class CurrencyLayerProvider implements ExchangeRateProviderInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    private $accessKey;
26
27
    /**
28
     * @var HttpClient|null
29
     */
30
    private $client;
31
32
    /**
33
     * @var RequestFactory|null
34
     */
35
    private $requestFactory;
36
37
    /**
38
     * @var ExchangeRateFactoryInterface|null
39
     */
40
    private $exchangeRateFactory;
41
42
    /**
43
     * OpenExchangeRatesProvider constructor.
44
     * @param string                            $accessKey
45
     * @param HttpClient|null                   $client
46
     * @param RequestFactory|null               $requestFactory
47
     * @param ExchangeRateFactoryInterface|null $exchangeRateFactory
48
     * @param CacheInterface|null               $cache
49
     * @throws \Http\Discovery\Exception\NotFoundException
50
     */
51
    public function __construct(
52
        string $accessKey,
53
        HttpClient $client = null,
54
        RequestFactory $requestFactory = null,
55
        ExchangeRateFactoryInterface $exchangeRateFactory = null,
56
        CacheInterface $cache = null
0 ignored issues
show
Unused Code introduced by
The parameter $cache is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
57
    ) {
58
        $this->accessKey = $accessKey;
59
        $this->client = $client ?? HttpClientDiscovery::find();
60
        $this->requestFactory = $requestFactory ?? MessageFactoryDiscovery::find();
61
        $this->exchangeRateFactory = $exchangeRateFactory ?? new NativeExchangeRateFactory();
62
    }
63
64
    /**
65
     * @inheritDoc
66
     */
67
    public function getExchangeRate(CurrencyInterface $sourceCurrency, CurrencyInterface $targetCurrency, DateTimeInterface $date = null): ExchangeRateInterface
68
    {
69
        if (null === $date) {
70
            $date = new DateTimeImmutable('now', new DateTimeZone('GMT'));
71
        }
72
73
        if ($date instanceof DateTime) {
74
            $date = DateTimeImmutable::createFromMutable($date)->setTimezone(new DateTimeZone('GMT'));
75
        }
76
77
        if (!in_array('USD', [$sourceCurrency->getCode(), $targetCurrency->getCode()])) {
78
            throw new ExchangeRateNotFoundException($sourceCurrency, $targetCurrency, "CurrencyLayer Free plan only provide USD-based currency conversions.");
79
        }
80
81
        // Same currencies
82
        if ($sourceCurrency->getCode() === $targetCurrency->getCode()) {
83
            return $this->exchangeRateFactory->create($sourceCurrency, $targetCurrency, 1);
84
        }
85
86
        // Invert currencies
87
        if ('USD' === $targetCurrency->getCode()) { // CurrencyLayer free plan only provide USD -> *
88
            return $this->getExchangeRate($targetCurrency, $sourceCurrency, $date)->invertCurrencies();
89
        }
90
91
        $url = sprintf('http://apilayer.net/api/historical?access_key=%s&date=%s', $this->accessKey, $date->format('Y-m-d'));
92
        $response = $this->client->sendRequest($this->requestFactory->createRequest('GET', $url));
93
        $json = json_decode((string) $response->getBody(), true);
94
        if (isset($json['quotes'][$sourceCurrency->getCode() . $targetCurrency->getCode()])) {
95
            return $this->exchangeRateFactory->create($sourceCurrency, $targetCurrency, $json['quotes'][$sourceCurrency->getCode() . $targetCurrency->getCode()]);
96
        }
97
98
        throw new ExchangeRateNotFoundException($sourceCurrency, $targetCurrency);
99
    }
100
}
101