Passed
Pull Request — master (#67)
by
unknown
14:21
created

ProgressivePriceThresholds::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 12
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace hiqdev\php\billing\price;
6
7
use hiqdev\php\units\Quantity;
8
use InvalidArgumentException;
9
use Money\Money;
10
11
final class ProgressivePriceThresholds
12
{
13
    /** @var ProgressivePriceThreshold[] */
14
    public array $thresholds;
15
16
    private int $priceRate = 0;
17
18
    /**
19
     * @param ProgressivePriceThreshold[] $thresholds
20
     */
21
   public function __construct(array $thresholds)
22
   {
23
       foreach ($thresholds as $threshold) {
24
           $this->add(ProgressivePriceThreshold::createFromScalar(
25
                    (string) $threshold['price'],
26
                    (string) $threshold['currency'],
27
                    (string) $threshold['quantity'],
28
                    (string) $threshold['unit'],
29
               )
30
           );
31
       }
32
       $this->priceRate = PriceHelper::calculatePriceRate((string)$threshold['price']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $threshold seems to be defined by a foreach iteration on line 23. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
33
   }
34
35
   public function add(ProgressivePriceThreshold $threshold): void
36
   {
37
      $this->checkCurrency($threshold->price());
38
      $this->checkUnit($threshold->quantity());
39
      $this->appendThresholds($threshold);
40
   }
41
42
    public function get(): array
43
    {
44
        $this->prepareThresholds();
45
        return $this->thresholds;
46
    }
47
48
    public function getPriceRate(): int
49
    {
50
        return $this->priceRate;
51
    }
52
53
    private function prepareThresholds(): void
54
    {
55
        usort($this->thresholds, function (ProgressivePriceThreshold $a, ProgressivePriceThreshold $b) {
56
            if ($b->quantity()->equals($a->quantity())) {
57
                return $b->price()->getAmount() <=> $a->price()->getAmount();
58
            }
59
            return $b->quantity()->getQuantity() <=> $a->quantity()->getQuantity();
60
        });
61
    }
62
63
    private function checkCurrency(Money $price): void
64
    {
65
        if (empty($this->thresholds)) {
66
            return;
67
        }
68
69
        $last = $this->thresholds[array_key_last($this->thresholds)];
70
71
        if (!$last->price()->getCurrency()->equals($price->getCurrency())
72
        ) {
73
            throw new InvalidArgumentException(sprintf(
74
                "Progressive price with threshold currency %s is not valid to other threshold currency %s",
75
                $last->price()->getCurrency()->getCode(),
76
                $price->getCurrency()->getCode()
77
            ));
78
        }
79
    }
80
81
    private function checkUnit(Quantity $prepaid): void
82
    {
83
        if (empty($this->thresholds)) {
84
            return;
85
        }
86
87
        $last = $this->thresholds[array_key_last($this->thresholds)];
88
89
        if (!$last->quantity()->getUnit()->isConvertible($prepaid->getUnit())) {
90
            throw new InvalidArgumentException(sprintf(
91
                "Progressive price with threshold unit %s is not convertible to other threshold unit %s",
92
                $last->quantity()->getUnit()->getName(),
93
                $prepaid->getUnit()->getName()
94
            ));
95
        }
96
    }
97
98
    private function appendThresholds(ProgressivePriceThreshold $threshold): void
99
    {
100
        $this->thresholds[] = $threshold;
101
    }
102
}
103