Passed
Push — master ( 373e60...256112 )
by Dmitry
25:12 queued 10:02
created

AbstractPrice::jsonSerialize()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 41
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 41
ccs 2
cts 2
cp 1
rs 8.6026
cc 7
nc 64
nop 0
crap 7
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
    public function jsonSerialize(): array
150
    {
151
        $data = [
152
            'id' => $this->id,
153
            'class' => (new \ReflectionClass($this))->getShortName(),
154
            'type' => $this->getType()->getName(),
155
            'type_id' => $this->getType()->getId(),
156
            'object_id' => $this->getTarget()->getId(),
157 21
            'object' => [
158 21
                'id' => $this->getTarget()->getId(),
159
                'name' => $this->getTarget()->getName(),
160
                'type' => $this->getTarget()->getType(),
161
            ],
162
            'plan_id' => $this->getPlan()?->getId(),
163
        ];
164
165
        if ($this instanceof PriceWithSubpriceInterface) {
166
            $data['subprice'] = $this->getSubprices()->values();
167
        }
168
169
        if ($this instanceof PriceWithRateInterface) {
170
            $data['rate'] = $this->getRate();
171
        }
172
173
        if ($this instanceof PriceWithUnitInterface) {
174
            $data['unit'] = $this->getUnit()->getName();
175
        }
176
177
        if ($this instanceof PriceWithCurrencyInterface) {
178
            $data['currency'] = $this->getCurrency()->getCode();
179
        }
180
181
        if ($this instanceof PriceWithSumsInterface) {
182
            $data['sums'] = $this->getSums()->values();
183
        }
184
185
        if ($this instanceof PriceWithQuantityInterface) {
186
            $data['quantity'] = $this->getPrepaid()->getQuantity();
187
        }
188
189
        return $data;
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195
    public function isApplicable(ActionInterface $action): bool
196
    {
197
        /* sorry, debugging facility
198
        var_dump([
199
            'action.target'     => $action->getTarget(),
200
            'price.target'      => $this->getTarget(),
201
            'action.type'       => $action->getType(),
202
            'price.type'        => $this->getType(),
203
            'target matches'    => $action->getTarget()->matches($this->getTarget()),
204
            'type matches'      => $action->getType()->matches($this->getType()),
205
        ]); */
206
        return $action->getTarget()->matches($this->getTarget()) &&
207
               $action->getType()->matches($this->getType());
208
    }
209
}
210