Completed
Branch master (5f2681)
by Stojan
04:08 queued 02:05
created

HtmlParser::getRates()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
/*
3
 * This file is part of the Exchange Rate package, an RunOpenCode project.
4
 *
5
 * Implementation of exchange rate crawler for Banca Intesa Serbia, http://www.bancaintesa.rs.
6
 *
7
 * (c) 2016 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\BancaIntesaSerbia\Parser;
13
14
use RunOpenCode\ExchangeRate\Contract\RateInterface;
15
use RunOpenCode\ExchangeRate\Model\Rate;
16
use RunOpenCode\ExchangeRate\BancaIntesaSerbia\Api;
17
use Symfony\Component\DomCrawler\Crawler;
18
19
/**
20
 * Class HtmlParser
21
 *
22
 * Parse HTML document with daily rates from Banca Intesa Serbia.
23
 *
24
 * @package RunOpenCode\ExchangeRate\BancaIntesaSerbia\Parser
25
 */
26
class HtmlParser
27
{
28
    /**
29
     * @var RateInterface[]
30
     */
31
    private $rates;
32
33
    /**
34
     * @var \DateTime
35
     */
36
    private $date;
37
38
    /**
39
     * @var string
40
     */
41
    private $html;
42
43
    /**
44
     * HtmlParser constructor.
45
     * @param $node string
46
     * @param $date \DateTime
47
     */
48 10
    public function __construct($node, \DateTime $date)
49
    {
50 10
        $this->html = $node;
51 10
        $this->date = $date;
52 10
    }
53
54
    /**
55
     * @return array|\RunOpenCode\ExchangeRate\Contract\RateInterface[]
56
     */
57 10
    public function getRates()
58
    {
59 10
        if (!$this->rates) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->rates of type RunOpenCode\ExchangeRate\Contract\RateInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
60 10
            $this->rates = $this->parseHtml($this->html, $this->date);
61 10
        }
62
63 10
        return $this->rates;
64
    }
65
66
    /**
67
     * @param $html string
68
     * @param \DateTime $date
69
     * @return array
70
     */
71 10
    private function parseHtml($html, \DateTime $date)
72
    {
73 10
        $crawler = new Crawler($html);
74 10
        $crawler = $crawler->filter('table');
75
76 10
        return $this->extractRates($crawler, $date);
77
    }
78
79
    /**
80
     * @param Crawler $crawler
81
     * @param \DateTime $date
82
     * @return array
83
     */
84 10
    private function extractRates(Crawler $crawler, \DateTime $date)
85
    {
86 10
        $rates = array();
87
88
        $crawler->filter('tr')->each(function (Crawler $node) use ($date, &$rates) {
89
90 10
            $row = $this->parseRow($node);
91
92 10
            if (null !== $row) {
93
94 10
                $rates[] = $this->buildRate(
95 10
                    $row['default'] / $row['unit'],
96 10
                    $row['currencyCode'],
97 10
                    'default',
98
                    $date
99 10
                );
100
101 10
                $rates[] = $this->buildRate(
102 10
                    $row['foreign_exchange_buying'] / $row['unit'],
103 10
                    $row['currencyCode'],
104 10
                    'foreign_exchange_buying',
105
                    $date
106 10
                );
107
108 10
                $rates[] = $this->buildRate(
109 10
                    $row['foreign_exchange_selling'] / $row['unit'],
110 10
                    $row['currencyCode'],
111 10
                    'foreign_exchange_selling',
112 10
                    $this->date
113 10
                );
114
115 10
                $rates[] = $this->buildRate(
116 10
                    $row['foreign_cash_buying'] / $row['unit'],
117 10
                    $row['currencyCode'],
118 10
                    'foreign_cash_buying',
119 10
                    $this->date
120 10
                );
121
122 10
                $rates[] = $this->buildRate(
123 10
                    $row['foreign_cash_selling'] / $row['unit'],
124 10
                    $row['currencyCode'],
125 10
                    'foreign_cash_selling',
126 10
                    $this->date
127 10
                );
128
129 10
            }
130 10
        });
131
132
        /**
133
         * @var Rate $rate
134
         */
135 10
        foreach ($rates as $key => $rate){
136 10
            if (!$rate->getValue()) {
137 10
                unset($rates[$key]);
138 10
            }
139 10
        }
140
141
142 10
        return $rates;
143
    }
144
145 10
    private function parseRow(Crawler $crawler)
146
    {
147
        $currentRow = array(
148
            'currencyCode' => ''
149 10
        );
150
151 10
        $crawler->filter('td')->each(function (Crawler $node, $i) use (&$currentRow) {
152
153
            switch ($i) {
154 10
                case 1:
155 10
                    $currentRow['currencyCode'] = trim($node->text());
156 10
                    break;
157 10
                case 2:
158 10
                    $currentRow['unit'] = (int)trim($node->text());
159 10
                    break;
160 10
                case 3:
161 10
                    $currentRow['foreign_exchange_buying'] = (float)trim($node->text());
162 10
                    break;
163 10
                case 4:
164 10
                    $currentRow['default'] = (float)trim($node->text());
165 10
                    break;
166 10
                case 5:
167 10
                    $currentRow['foreign_exchange_selling'] = (float)trim($node->text());
168 10
                    break;
169 10
                case 6:
170 10
                    $currentRow['foreign_cash_buying'] = (float)trim($node->text());
171 10
                    break;
172 10
                case 7:
173 10
                    $currentRow['foreign_cash_selling'] = (float)trim($node->text());
174 10
                    break;
175
            }
176 10
        });
177
178 10
        return strlen($currentRow['currencyCode']) === 3 ? $currentRow : null;
179
    }
180
181 10
    private function buildRate($value, $currencyCode, $rateType, $date) {
182
183 10
        return new Rate(
184 10
            Api::NAME,
185 10
            $value,
186 10
            $currencyCode,
187 10
            $rateType,
188 10
            $date,
189 10
            'RSD',
190 10
            new \DateTime('now'),
191 10
            new \DateTime('now')
192 10
        );
193
    }
194
}
195