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-2018, HiQDev (http://hiqdev.com/) |
||
9 | */ |
||
10 | |||
11 | namespace hiqdev\php\billing\tools; |
||
12 | |||
13 | use hiqdev\php\billing\bill\Bill; |
||
14 | use hiqdev\php\billing\bill\BillInterface; |
||
15 | use hiqdev\php\billing\charge\ChargeInterface; |
||
16 | use hiqdev\php\billing\charge\GeneralizerInterface; |
||
17 | use hiqdev\php\units\QuantityInterface; |
||
18 | use Money\Money; |
||
19 | |||
20 | /** |
||
21 | * @author Andrii Vasyliev <[email protected]> |
||
22 | */ |
||
23 | class Aggregator implements AggregatorInterface |
||
24 | { |
||
25 | /** |
||
26 | * @var GeneralizerInterface |
||
27 | */ |
||
28 | protected $generalizer; |
||
29 | |||
30 | 1 | public function __construct(GeneralizerInterface $generalizer) |
|
31 | { |
||
32 | 1 | $this->generalizer = $generalizer; |
|
33 | 1 | } |
|
34 | |||
35 | /** |
||
36 | * Aggregates given Charges to Bills. Then aggregates them again with DB. |
||
37 | * @param ChargeInterface[]|ChargeInterface[][] $charges |
||
38 | * @return BillInterface[] |
||
39 | */ |
||
40 | 1 | public function aggregateCharges(array $charges): array |
|
41 | { |
||
42 | 1 | $bills = []; |
|
43 | 1 | foreach ($charges as $charge) { |
|
44 | 1 | if (is_array($charge)) { |
|
45 | 1 | $others = $this->aggregateCharges($charge); |
|
46 | 1 | } elseif ($charge instanceof ChargeInterface) { |
|
47 | 1 | $others = [$this->generalizer->createBill($charge)]; |
|
48 | } else { |
||
49 | var_dump($charge);die; |
||
50 | throw new \Exception('not a Charge given to Aggregator'); |
||
0 ignored issues
–
show
|
|||
51 | } |
||
52 | |||
53 | $bills = $this->aggregateBills($bills, $others); |
||
54 | 1 | } |
|
55 | |||
56 | return $bills; |
||
57 | 1 | } |
|
58 | |||
59 | /** |
||
60 | * Aggregate arrays of bills. |
||
61 | * @param BillInterface[] $bills |
||
62 | * @param BillInterface[] $others |
||
63 | * @return BillInterface[] |
||
64 | */ |
||
65 | protected function aggregateBills(array $bills, array $others): array |
||
66 | 1 | { |
|
67 | foreach ($others as $bill) { |
||
68 | 1 | $uid = $bill->getUniqueString(); |
|
69 | 1 | if (empty($bills[$uid])) { |
|
70 | 1 | $bills[$uid] = $bill; |
|
71 | 1 | } else { |
|
72 | $bills[$uid] = $this->aggregateBill($bills[$uid], $bill); |
||
73 | 1 | } |
|
74 | } |
||
75 | |||
76 | return $bills; |
||
77 | 1 | } |
|
78 | |||
79 | /** |
||
80 | * @param BillInterface $first |
||
81 | * @param BillInterface $other |
||
82 | * @return BillInterface |
||
83 | */ |
||
84 | protected function aggregateBill(BillInterface $first, BillInterface $other): BillInterface |
||
85 | 1 | { |
|
86 | return new Bill( |
||
87 | 1 | $this->aggregateId($first, $other), |
|
88 | 1 | $first->getType(), |
|
89 | 1 | $first->getTime(), |
|
90 | 1 | $this->aggregateSum($first, $other), |
|
91 | 1 | $this->aggregateQuantity($first, $other), |
|
92 | 1 | $first->getCustomer(), |
|
93 | 1 | $first->getTarget(), |
|
94 | 1 | $first->getPlan(), |
|
95 | 1 | array_merge($first->getCharges(), $other->getCharges()) |
|
96 | 1 | ); |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param BillInterface $first |
||
101 | * @param BillInterface $other |
||
102 | * @return string|int|null |
||
103 | */ |
||
104 | protected function aggregateId(BillInterface $first, BillInterface $other) |
||
105 | 1 | { |
|
106 | if ($first->getId() === null) { |
||
107 | 1 | return $other->getId(); |
|
108 | 1 | } |
|
109 | if ($other->getId() === null) { |
||
110 | return $first->getId(); |
||
111 | } |
||
112 | if ($first->getId() === $other->getId()) { |
||
113 | return $other->getId(); |
||
114 | } |
||
115 | |||
116 | throw new AggregationException('cannot aggregate bills with different IDs'); |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * @param BillInterface $first |
||
121 | * @param BillInterface $other |
||
122 | * @param ChargeInterface[] $charges |
||
123 | * @return Money |
||
124 | */ |
||
125 | protected function aggregateSum(BillInterface $first, BillInterface $other): Money |
||
126 | 1 | { |
|
127 | return $first->getSum()->add($other->getSum()); |
||
128 | 1 | } |
|
129 | |||
130 | /** |
||
131 | * @param BillInterface $first |
||
132 | * @param BillInterface $other |
||
133 | * @param ChargeInterface[] $charges |
||
134 | * @return QuantityInterface |
||
135 | */ |
||
136 | protected function aggregateQuantity(BillInterface $first, BillInterface $other): QuantityInterface |
||
137 | 1 | { |
|
138 | return $first->getQuantity()->add($other->getQuantity()); |
||
139 | 1 | } |
|
140 | } |
||
141 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.