Completed
Push — master ( f79ff7...908aca )
by Dmitry
15:25 queued 10:35
created

src/tools/Aggregator.php (1 issue)

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;
0 ignored issues
show
Security Debugging Code introduced by
var_dump($charge) looks like debug code. Are you sure you do not want to remove it?
Loading history...
50
                throw new \Exception('not a Charge given to Aggregator');
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