Passed
Push — master ( 364662...9798b7 )
by Andrii
02:56
created

AbstractPrice::calculateSum()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 14
ccs 6
cts 8
cp 0.75
crap 3.1406
rs 10
c 1
b 0
f 0
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\price;
12
13
use hiqdev\php\billing\action\ActionInterface;
14
use hiqdev\php\billing\charge\ChargeModifier;
15
use hiqdev\php\billing\charge\SettableChargeModifierTrait;
16
use hiqdev\php\billing\Exception\CannotReassignException;
17
use hiqdev\php\billing\plan\PlanInterface;
18
use hiqdev\php\billing\target\TargetInterface;
19
use hiqdev\php\billing\type\TypeInterface;
20
use hiqdev\php\units\QuantityInterface;
21
use Money\Money;
22
23
/**
24
 * Price.
25
 * @see PriceInterface
26
 * By default Price is applicable when same target and same type as Action.
27
 * But it can be different e.g. same price for all targets when certain type.
28
 *
29
 * @author Andrii Vasyliev <[email protected]>
30
 */
31
abstract class AbstractPrice implements PriceInterface, ChargeModifier
32
{
33
    use SettableChargeModifierTrait;
34
35
    /**
36
     * @var integer
37
     */
38
    protected $id;
39
40
    /**
41
     * @var TypeInterface
42
     */
43
    protected $type;
44
45
    /**
46
     * @var TargetInterface
47
     */
48
    protected $target;
49
50
    /**
51
     * @var PlanInterface|null
52
     */
53
    protected $plan;
54
55 41
    public function __construct(
56
                            $id,
57
        TypeInterface $type,
58
        TargetInterface $target,
59
        PlanInterface $plan = null
60
    ) {
61 41
        $this->id = $id;
62 41
        $this->type = $type;
63 41
        $this->target = $target;
64 41
        $this->plan = $plan;
65 41
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 4
    public function getId()
71
    {
72 4
        return $this->id;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 25
    public function getType()
79
    {
80 25
        return $this->type;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 25
    public function getTarget()
87
    {
88 25
        return $this->target;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94 1
    public function getPlan(): ?PlanInterface
95
    {
96 1
        return $this->plan;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function hasPlan()
103
    {
104
        return $this->plan !== null;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function setPlan(PlanInterface $plan)
111
    {
112
        if ($this->hasPlan()) {
113
            throw new CannotReassignException('price plan');
114
        }
115
        $this->plan = $plan;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     * Default sum calculation method: sum = price * usage.
121
     */
122 13
    public function calculateSum(QuantityInterface $quantity): ?Money
123
    {
124 13
        $usage = $this->calculateUsage($quantity);
125 13
        if ($usage === null) {
126
            return null;
127
        }
128
129 13
        $price = $this->calculatePrice($quantity);
130 13
        if ($price === null) {
131
            return null;
132
        }
133
134
        /// TODO add configurable rounding mode later
135 13
        return $price->multiply($usage->getQuantity(), Money::ROUND_UP);
136
    }
137
138 1
    public function jsonSerialize()
139
    {
140 1
        return array_filter(get_object_vars($this));
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 21
    public function isApplicable(ActionInterface $action): bool
147
    {
148
        /* sorry, debugging facility
149
        var_dump([
150
            'action.target'     => $action->getTarget(),
151
            'price.target'      => $this->getTarget(),
152
            'action.type'       => $action->getType(),
153
            'price.type'        => $this->getType(),
154
            'target matches'    => $action->getTarget()->matches($this->getTarget()),
155
            'type matches'      => $action->getType()->matches($this->getType()),
156
        ]); */
157 21
        return $action->getTarget()->matches($this->getTarget()) &&
158 21
               $action->getType()->matches($this->getType());
159
    }
160
}
161