Aggregator::aggregateId()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 5.024

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 13
rs 10
ccs 3
cts 5
cp 0.6
crap 5.024
1
<?php
2
/**
3
 * PHP Billing Library
4
 *
5
 * @link      https://github.com/hiqdev/php-billing
6
 * @package   php-billing
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2017-2020, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\php\billing\tools;
12
13
use hiqdev\php\billing\action\UsageInterval;
14
use hiqdev\php\billing\bill\Bill;
15
use hiqdev\php\billing\bill\BillInterface;
16
use hiqdev\php\billing\charge\ChargeInterface;
17
use hiqdev\php\billing\charge\GeneralizerInterface;
18
use hiqdev\php\units\QuantityInterface;
19
use Money\Money;
20
21
/**
22
 * @author Andrii Vasyliev <[email protected]>
23
 */
24
class Aggregator implements AggregatorInterface
25
{
26
    /**
27
     * @var GeneralizerInterface
28
     */
29
    protected $generalizer;
30
31 1
    public function __construct(GeneralizerInterface $generalizer)
32
    {
33 1
        $this->generalizer = $generalizer;
34 1
    }
35
36
    /**
37
     * Aggregates given Charges to Bills. Then aggregates them again with DB.
38
     * @param ChargeInterface[]|ChargeInterface[][] $charges
39
     * @return BillInterface[]
40
     */
41 1
    public function aggregateCharges(array $charges): array
42
    {
43 1
        $bills = [];
44 1
        foreach ($charges as $charge) {
45 1
            if (is_array($charge)) {
46
                $others = $this->aggregateCharges($charge);
47 1
            } elseif ($charge instanceof ChargeInterface) {
48 1
                $others = [$this->generalizer->createBill($charge)];
49
            } else {
50
                throw new AggregationException('Not a Charge given to Aggregator');
51
            }
52
53 1
            $bills = $this->aggregateBills($bills, $others);
54
        }
55
56 1
        return $bills;
57
    }
58
59
    /**
60
     * Aggregate arrays of bills.
61
     * @param BillInterface[] $bills
62
     * @param BillInterface[] $others
63
     * @return BillInterface[]
64
     */
65 1
    protected function aggregateBills(array $bills, array $others): array
66
    {
67 1
        foreach ($others as $bill) {
68 1
            $uid = $bill->getUniqueString();
69 1
            if (empty($bills[$uid])) {
70 1
                $bills[$uid] = $bill;
71
            } else {
72 1
                $bills[$uid] = $this->aggregateBill($bills[$uid], $bill);
73
            }
74
        }
75
76 1
        return $bills;
77
    }
78
79 1
    protected function aggregateBill(BillInterface $first, BillInterface $other): BillInterface
80
    {
81 1
        $bill = new Bill(
82 1
            $this->aggregateId($first, $other),
83 1
            $first->getType(),
84 1
            $first->getTime(),
85 1
            $this->aggregateSum($first, $other),
86 1
            $this->aggregateQuantity($first, $other),
87 1
            $first->getCustomer(),
88 1
            $first->getTarget(),
89 1
            $first->getPlan(),
90 1
            array_merge($first->getCharges(), $other->getCharges())
91
        );
92
93
        $bill->setUsageInterval($this->aggregateUsageInterval($first, $other));
94
95
        return $bill;
96
    }
97 1
98
    protected function aggregateUsageInterval(BillInterface $first, BillInterface $other): UsageInterval
99 1
    {
100 1
        return $first->getUsageInterval()->extend($other->getUsageInterval());
101
    }
102
103
    /**
104
     * @return string|int|null
105
     */
106
    protected function aggregateId(BillInterface $first, BillInterface $other)
107
    {
108
        if ($first->getId() === null) {
0 ignored issues
show
introduced by
The condition $first->getId() === null is always false.
Loading history...
109
            return $other->getId();
110
        }
111
        if ($other->getId() === null) {
0 ignored issues
show
introduced by
The condition $other->getId() === null is always false.
Loading history...
112 1
            return $first->getId();
113
        }
114 1
        if ($first->getId() === $other->getId()) {
115
            return $other->getId();
116
        }
117 1
118
        throw new AggregationException('cannot aggregate bills with different IDs');
119 1
    }
120 1
121
    protected function aggregateSum(BillInterface $first, BillInterface $other): Money
122
    {
123
        return $first->getSum()->add($other->getSum());
124
    }
125
126
    protected function aggregateQuantity(BillInterface $first, BillInterface $other): QuantityInterface
127
    {
128
        if ($first->getQuantity()->isConvertible($other->getQuantity()->getUnit())) {
129
            return $first->getQuantity()->add($other->getQuantity());
130
        }
131
132
        return $first->getQuantity();
133
    }
134
}
135