Completed
Push — master ( 6253d9...eb0c57 )
by Nikola
12:54
created

WebPageSource::fetch()   B

Complexity

Conditions 7
Paths 15

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 15
cts 15
cp 1
rs 8.4906
c 0
b 0
f 0
cc 7
nc 15
nop 3
crap 7
1
<?php
2
/*
3
 * This file is part of the Exchange Rate package, an RunOpenCode project.
4
 *
5
 * Implementation of exchange rate crawler for National Bank of Serbia, http://www.nbs.rs.
6
 *
7
 * (c) 2017 RunOpenCode
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
namespace RunOpenCode\ExchangeRate\NationalBankOfSerbia\Source;
13
14
use RunOpenCode\ExchangeRate\Contract\RateInterface;
15
use RunOpenCode\ExchangeRate\Contract\SourceInterface;
16
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Api;
17
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Enum\RateType;
18
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Exception\RuntimeException;
19
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Exception\SourceNotAvailableException;
20
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Util\NbsBrowser;
21
use RunOpenCode\ExchangeRate\NationalBankOfSerbia\Parser\XmlParser;
22
use RunOpenCode\ExchangeRate\Utils\CurrencyCodeUtil;
23
24
/**
25
 * Class WebPageSource
26
 *
27
 * Fetch rates from National Bank of Serbia website, as public user, without using their API service.
28
 *
29
 * @package RunOpenCode\ExchangeRate\NationalBankOfSerbia\Source
30
 */
31
final class WebPageSource implements SourceInterface
32
{
33
    /**
34
     * @var array
35
     */
36
    private $cache;
37
38
    /**
39
     * @var NbsBrowser
40
     */
41
    private $browser;
42
43
    /**
44
     * WebPageSource constructor.
45
     *
46
     * @param NbsBrowser|null $browser
47
     */
48 8
    public function __construct(NbsBrowser $browser = null)
49
    {
50 8
        $this->browser = ($browser !== null) ? $browser : new NbsBrowser();
51 8
        $this->cache = array();
52 8
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 4
    public function getName()
58
    {
59 4
        return Api::NAME;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 7
    public function fetch($currencyCode, $rateType = RateType::MEDIAN, \DateTime $date = null)
66
    {
67 7
        $currencyCode = CurrencyCodeUtil::clean($currencyCode);
68
69 7
        if (!Api::supports($currencyCode, $rateType)) {
70 1
            throw new RuntimeException(sprintf('National Bank of Serbia does not supports currency code "%s" for rate type "%s".', $currencyCode, $rateType));
71
        }
72
73 6
        if ($date === null) {
74 6
            $date = new \DateTime('now');
75
        }
76
77 6
        if (!array_key_exists($rateType, $this->cache)) {
78
79
            try {
80 6
                $this->load($date, $rateType);
81 1
            } catch (\Exception $e) {
82 1
                throw new SourceNotAvailableException(sprintf('Unable to load data from "%s" for "%s" of rate type "%s".', $this->getName(), $currencyCode, $rateType), 0, $e);
83
            }
84
        }
85
86 5
        if (!array_key_exists($rateType, $this->cache)) {
87 1
            throw new RuntimeException(sprintf('API Changed: source "%s" does not provide rate type "%s".', $this->getName(), $rateType));
88
        }
89
90 4
        if (array_key_exists($currencyCode, $this->cache[$rateType])) {
91 3
            return $this->cache[$rateType][$currencyCode];
92
        }
93
94 1
        throw new RuntimeException(sprintf('API Changed: source "%s" does not provide currency code "%s" for rate type "%s".', $this->getName(), $currencyCode, $rateType));
95
    }
96
97
    /**
98
     * Load rates from National Bank of Serbia website.
99
     *
100
     * @param \DateTime $date
101
     * @param string $rateType
102
     * @throws SourceNotAvailableException
103
     */
104 6
    private function load(\DateTime $date, $rateType)
105
    {
106 6
        $parser = new XmlParser();
107
108
        /**
109
         * @var RateInterface[] $rates
110
         */
111 6
        $rates = $parser->parse($this->browser->getXmlDocument($date, $rateType));
112
113
        /**
114
         * @var RateInterface $rate
115
         */
116 5
        foreach ($rates as $rate) {
117
118 4
            if (!array_key_exists($rate->getRateType(), $this->cache)) {
119 4
                $this->cache[$rate->getRateType()] = array();
120
            }
121
122 4
            $this->cache[$rate->getRateType()][$rate->getCurrencyCode()] = $rate;
123
        }
124 5
    }
125
}
126