Passed
Pull Request — master (#67)
by
unknown
13:46
created

ProgressivePriceThresholds   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 34
c 1
b 0
f 0
dl 0
loc 82
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 4 1
A add() 0 5 1
A prepareThresholds() 0 7 2
A __construct() 0 8 2
A checkUnit() 0 13 3
A appendThresholds() 0 3 1
A checkCurrency() 0 14 3
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
   private array $thresholds;
15
16
    /**
17
     * @param ProgressivePriceThreshold[] $thresholds
18
     */
19
   public function __construct(array $thresholds)
20
   {
21
       foreach ($thresholds as $threshold) {
22
           $this->add(ProgressivePriceThreshold::createFromScalar(
23
                   $threshold['price'],
24
                   $threshold['currency'],
25
                   $threshold['quantity'],
26
                   $threshold['unit'],
27
               )
28
           );
29
       }
30
   }
31
32
   public function add(ProgressivePriceThreshold $threshold): void
33
   {
34
      $this->checkCurrency($threshold->price());
35
      $this->checkUnit($threshold->quantity());
36
      $this->appendThresholds($threshold);
37
   }
38
39
    public function get(): array
40
    {
41
        $this->prepareThresholds();
42
        return $this->thresholds;
43
    }
44
45
    private function prepareThresholds(): void
46
    {
47
        usort($this->thresholds, function (ProgressivePriceThreshold $a, ProgressivePriceThreshold $b) {
48
            if ($b->quantity()->equals($a->quantity())) {
49
                return $b->price()->getAmount() <=> $a->price()->getAmount();
50
            }
51
            return $b->quantity()->getQuantity() <=> $a->quantity()->getQuantity();
52
        });
53
    }
54
55
    private function checkCurrency(Money $price): void
56
    {
57
        if (empty($this->thresholds)) {
58
            return;
59
        }
60
61
        $last = $this->thresholds[array_key_last($this->thresholds)];
62
63
        if (!$last->price()->getCurrency()->equals($price->getCurrency())
64
        ) {
65
            throw new InvalidArgumentException(sprintf(
66
                "Progressive price with threshold currency %s is not valid to other threshold currency %s",
67
                $last->price()->getCurrency()->getCode(),
68
                $price->getCurrency()->getCode()
69
            ));
70
        }
71
    }
72
73
    private function checkUnit(Quantity $prepaid): void
74
    {
75
        if (empty($this->thresholds)) {
76
            return;
77
        }
78
79
        $last = $this->thresholds[array_key_last($this->thresholds)];
80
81
        if (!$last->quantity()->getUnit()->isConvertible($prepaid->getUnit())) {
82
            throw new InvalidArgumentException(sprintf(
83
                "Progressive price with threshold unit %s is not convertible to other threshold unit %s",
84
                $last->quantity()->getUnit()->getName(),
85
                $prepaid->getUnit()->getName()
86
            ));
87
        }
88
    }
89
90
    private function appendThresholds(ProgressivePriceThreshold $threshold): void
91
    {
92
        $this->thresholds[] = $threshold;
93
    }
94
}
95