MemoryRepository   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 172
Duplicated Lines 56.4 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 97
loc 172
c 0
b 0
f 0
wmc 30
lcom 1
cbo 3
ccs 55
cts 55
cp 1
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A save() 0 13 3
A delete() 9 9 2
A has() 8 8 2
A get() 12 12 3
B latest() 24 24 7
A all() 20 20 4
A count() 0 4 1
A getRateKey() 8 8 1
A paginate() 16 16 6

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/*
3
 * This file is part of the Exchange Rate package, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\ExchangeRate\Repository;
11
12
use RunOpenCode\ExchangeRate\Contract\RateInterface;
13
use RunOpenCode\ExchangeRate\Contract\RepositoryInterface;
14
use RunOpenCode\ExchangeRate\Enum\RateType;
15
use RunOpenCode\ExchangeRate\Exception\ExchangeRateException;
16
use RunOpenCode\ExchangeRate\Utils\RateFilterUtil;
17
18
/**
19
 * Class MemoryRepository
20
 *
21
 * Memory repository is useful for unit testing only.
22
 *
23
 * @package RunOpenCode\ExchangeRate\Repository
24
 */
25
class MemoryRepository implements RepositoryInterface
26
{
27
    /**
28
     * @var RateInterface[]
29
     */
30
    private $rates;
31
32 21
    public function __construct()
33
    {
34 21
        $this->rates = [];
35 21
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 15
    public function save(array $rates)
41
    {
42
        /**
43
         * @var RateInterface $rate
44
         */
45 15
        foreach ($rates as $rate) {
46 15
            $this->rates[$this->getRateKey($rate->getCurrencyCode(), $rate->getDate(), $rate->getRateType(), $rate->getSourceName())] = $rate;
47
        }
48
49 15
        uasort($this->rates, function (RateInterface $rate1, RateInterface $rate2) {
50 5
            return ($rate1->getDate() > $rate2->getDate()) ? -1 : 1;
51 15
        });
52 15
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 1 View Code Duplication
    public function delete(array $rates)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
58
    {
59
        /**
60
         * @var RateInterface $rate
61
         */
62 1
        foreach ($rates as $rate) {
63 1
            unset($this->rates[$this->getRateKey($rate->getCurrencyCode(), $rate->getDate(), $rate->getRateType(), $rate->getSourceName())]);
64
        }
65 1
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 13 View Code Duplication
    public function has($sourceName, $currencyCode, \DateTime $date = null, $rateType = RateType::MEDIAN)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
    {
72 13
        if ($date === null) {
73 2
            $date = new \DateTime('now');
74
        }
75
76 13
        return array_key_exists($this->getRateKey($currencyCode, $date, $rateType, $sourceName), $this->rates);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82 10 View Code Duplication
    public function get($sourceName, $currencyCode, \DateTime $date = null, $rateType = RateType::MEDIAN)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
83
    {
84 10
        if ($date === null) {
85 3
            $date = new \DateTime('now');
86
        }
87
88 10
        if ($this->has($sourceName, $currencyCode, $date, $rateType)) {
89 8
            return $this->rates[$this->getRateKey($currencyCode, $date, $rateType, $sourceName)];
90
        }
91
92 2
        throw new ExchangeRateException(sprintf('Could not fetch rate for rate currency code "%s" and rate type "%s" on date "%s".', $currencyCode, $rateType, $date->format('Y-m-d')));
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 4 View Code Duplication
    public function latest($sourceName, $currencyCode, $rateType = RateType::MEDIAN, \DateTimeInterface $date = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
99
    {
100
        /**
101
         * @var RateInterface $rate
102
         */
103 4
        foreach ($this->rates as $rate) {
104
105
            if (null !== $date && $date < $rate->getDate()) {
106 2
                continue;
107
            }
108 2
109
            if (
110 2
                $rate->getSourceName() === $sourceName
111
                &&
112 2
                $rate->getCurrencyCode() === $currencyCode
113
                &&
114
                $rate->getRateType() === $rateType
115
            ) {
116 2
                return $rate;
117
            }
118
        }
119
120
        throw new ExchangeRateException(sprintf('Could not fetch latest rate for rate currency code "%s" and rate type "%s" from source "%s".', $currencyCode, $rateType, $sourceName));
121
    }
122 3
123
    /**
124 3
     * {@inheritdoc}
125 1
     */
126 View Code Duplication
    public function all(array $criteria = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
    {
128 2
        if (count($criteria) == 0) {
129
            return $this->rates;
130
        }
131
132
        $result = array();
133 2
134
        /**
135 2
         * @var RateInterface $rate
136 2
         */
137
        foreach ($this->rates as $rate) {
138
139
            if (RateFilterUtil::matches($rate, $criteria)) {
140 2
                $result[] = $rate;
141
            }
142
        }
143
144
        return $this->paginate($result, $criteria);
145
    }
146 1
147
    /**
148 1
     * {@inheritdoc}
149
     */
150
    public function count()
151
    {
152
        return count($this->rates);
153
    }
154
155
    /**
156
     * Builds rate key to speed up search.
157
     *
158
     * @param string $currencyCode
159
     * @param \DateTime $date
160 18
     * @param string $rateType
161
     * @param string $sourceName
162 18
     * @return string
163 18
     */
164 18 View Code Duplication
    protected function getRateKey($currencyCode, $date, $rateType, $sourceName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165 18
    {
166
        return str_replace(
167
            array('%currency_code%', '%date%', '%rate_type%', '%source_name%'),
168
            array($currencyCode, $date->format('Y-m-d'), $rateType, $sourceName),
169
            '%currency_code%_%date%_%rate_type%_%source_name%'
170
        );
171
    }
172
173
    /**
174
     * Extract requested page from filter criteria.
175
     *
176 2
     * @param array $rates Rates to filter for pagination.
177
     * @param array $criteria Filter criteria.
178 2
     * @return RateInterface[] Paginated rates.
179 1
     */
180 View Code Duplication
    protected function paginate(array $rates, $criteria)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
    {
182 1
        if (!array_key_exists('offset', $criteria) && !array_key_exists('limit', $criteria)) {
183 1
            return $rates;
184 1
        }
185
186 1
        $range = array();
187 1
        $offset = array_key_exists('offset', $criteria) ? $criteria['offset'] : 0;
188
        $limit = min((array_key_exists('limit', $criteria) ? $criteria['limit'] : count($rates)) + $offset, count($rates));
189
190 1
        for ($i = $offset; $i < $limit; $i++) {
191
            $range[] = $rates[$i];
192
        }
193
194
        return $range;
195
    }
196
}
197