AbstractPrice::setPlan()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 3
c 1
b 0
f 1
nc 2
nop 1
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 10
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\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;
0 ignored issues
show
Bug introduced by
The type hiqdev\php\billing\type\TypeInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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
        if ($price->isZero()) {
135 13
            return $price;
136
        }
137
138 1
        $stringQty = sprintf('%.14F', $usage->getQuantity());
139
140 1
        $sum = $price->multiply($stringQty, Money::ROUND_HALF_UP);
141
        if ($sum->isZero() && !$quantity->isZero()) {
142
            // If there is any usage, but sum is zero, we should charge at least 1 cent
143
            $sum = $price->multiply($stringQty, Money::ROUND_UP);
144
        }
145
146 21
        return $sum;
147
    }
148
149
    /**
150
     * What purpose of this method? Because it looks like duplicate of PriceHydrator::extract()
151
     * Where we are using the result of this method?
152
     * Magic calls can't be determined and I don't know what can be broken if we change the method result.
153
     * Which structure must have the result, because array can contain anything?
154
     *
155
     * @return array
156
     */
157 21
    public function jsonSerialize(): array
158 21
    {
159
        $res = array_filter(get_object_vars($this));
160
        unset($res['plan']);
161
162
        return $res;
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    public function isApplicable(ActionInterface $action): bool
169
    {
170
        /* sorry, debugging facility
171
        var_dump([
172
            'action.target'     => $action->getTarget(),
173
            'price.target'      => $this->getTarget(),
174
            'action.type'       => $action->getType(),
175
            'price.type'        => $this->getType(),
176
            'target matches'    => $action->getTarget()->matches($this->getTarget()),
177
            'type matches'      => $action->getType()->matches($this->getType()),
178
        ]); */
179
        return $action->getTarget()->matches($this->getTarget()) &&
180
               $action->getType()->matches($this->getType());
181
    }
182
}
183