Passed
Push — master ( ae6cde...76a869 )
by Andrii
17:57
created

BillingContext::enumPrice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 4
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace hiqdev\php\billing\tests\behat\bootstrap;
4
5
use DateTimeImmutable;
6
use hiqdev\php\billing\bill\BillInterface;
7
use hiqdev\php\billing\charge\ChargeInterface;
8
use PHPUnit\Framework\Assert;
9
10
class BillingContext extends BaseContext
11
{
12
    protected $saleTime;
13
14
    protected $bill;
15
16
    protected array $charges = [];
17
18
    /**
19
     * @Given reseller :reseller
20
     */
21
    public function reseller($reseller)
22
    {
23
        $this->builder->buildReseller($reseller);
24
    }
25
26
    /**
27
     * @Given customer :customer
28
     */
29
    public function customer($customer)
30
    {
31
        $this->builder->buildCustomer($customer);
32
    }
33
34
    /**
35
     * @Given manager :manager
36
     */
37
    public function manager($manager)
38
    {
39
        $this->builder->buildManager($manager);
40
    }
41
42
    /**
43
     * @Given /^(grouping )?(\S+) tariff plan (\S+)/
44
     */
45
    public function plan($grouping, $type, $plan)
46
    {
47
        $this->builder->buildPlan($plan, $type, !empty($grouping));
48
    }
49
50
    protected function fullPrice(array $data)
51
    {
52
        $this->builder->buildPrice($data);
53
    }
54
55
    /**
56
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+) for target (\S+)/
57
     */
58
    public function priceWithObject($type, $price, $currency, $unit, $target)
59
    {
60
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit', 'target'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...cy', 'unit', 'target')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
61
    }
62
63
    /**
64
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+) prepaid (\S+)/
65
     */
66
    public function priceWithPrepaid($type, $price, $currency, $unit, $prepaid)
67
    {
68
        $prepaid = "$prepaid $unit";
69
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit', 'prepaid'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...y', 'unit', 'prepaid')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
70
    }
71
72
    /**
73
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+)$/
74
     */
75
    public function price($type, $price, $currency, $unit)
76
    {
77
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...', 'currency', 'unit')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
78
    }
79
80
    /**
81
     * @Given /price for (\S+) is +(\S+) (\S+) per 1 (\S+) and (\S+) (\S+) per 2 (\S+) for target (\S+)/
82
     */
83
    public function enumPrice($type, $price, $currency, $unit, $price2, $currency2, $unit2, $target)
0 ignored issues
show
Unused Code introduced by
The parameter $unit2 is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

83
    public function enumPrice($type, $price, $currency, $unit, $price2, $currency2, /** @scrutinizer ignore-unused */ $unit2, $target)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $currency2 is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

83
    public function enumPrice($type, $price, $currency, $unit, $price2, /** @scrutinizer ignore-unused */ $currency2, $unit2, $target)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
84
    {
85
        $sums = [1 => $price, 2 => $price2];
86
        return $this->fullPrice(compact('type', 'sums', 'currency', 'unit', 'target'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...cy', 'unit', 'target')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
87
    }
88
89
    /**
90
     * @Given /^remove and recreate tariff plan (\S+)/
91
     */
92
    public function recreatePlan($plan)
93
    {
94
        $this->builder->recreatePlan($plan);
95
    }
96
97
    /**
98
     * @Given /sale (\S+) for (\S+) plan:(\S+) time:(\S+)/
99
     */
100
    public function sale($id, $target, $plan, $time): void
101
    {
102
        $this->saleTime = $this->prepareTime($time);
103
        $this->builder->buildSale($id, $target, $plan, $this->saleTime);
104
    }
105
106
107
    /**
108
     * @Given /purchase target (\S+) by plan (\S+) at (.+)$/
109
     */
110
    public function purchaseTarget(string $target, string $plan, string $time): void
111
    {
112
        $time = $this->prepareTime($time);
113
        $this->builder->buildPurchase($target, $plan, $time);
114
    }
115
116
    /**
117
     * @Given /resource consumption for (\S+) is (\d+) (\S+) for target (\S+) at (.+)$/
118
     */
119
    public function setConsumption(string $type, int $amount, string $unit, string $target, string $time): void
120
    {
121
        $this->builder->setConsumption($type, $amount, $unit, $target, $time);
122
    }
123
124
    /**
125
     * @Given /perform billing for time (\S+) for sales/
126
     */
127
    public function performBilling(string $time): void
128
    {
129
        $this->builder->performBilling($time);
130
    }
131
132
    /**
133
     * @Given /bill +for (\S+) is +(\S+) (\S+) per (\S+) (\S+) for target (\S+)$/
134
     */
135
    public function bill($type, $sum, $currency, $quantity, $unit, $target)
136
    {
137
        $quantity = $this->prepareQuantity($quantity);
138
        $sum = $this->prepareSum($sum, $quantity);
139
        $bill = $this->findBill([
140
            'type' => $type,
141
            'target' => $target,
142
            'sum' => "$sum $currency",
143
            'quantity' => "$quantity $unit",
144
        ]);
145
        Assert::assertSame($type, $bill->getType()->getName());
146
        Assert::assertSame($target, $bill->getTarget()->getFullName());
147
        Assert::assertEquals($sum*100, $bill->getSum()->getAmount());
148
        Assert::assertSame($currency, $bill->getSum()->getCurrency()->getCode());
149
        Assert::assertEquals($quantity, $bill->getQuantity()->getQuantity());
150
        Assert::assertSame($unit, $bill->getQuantity()->getUnit()->getName());
151
    }
152
153
    public function findBill(array $params): BillInterface
154
    {
155
        $bills = $this->builder->findBills($params);
156
        $this->bill = reset($bills);
157
        $this->charges = $this->bill->getCharges();
158
159
        return $this->bill;
160
    }
161
162
    /**
163
     * @Given /bills number is (\d+) for (\S+) for target (\S+)/
164
     */
165
    public function billsNumber($number, $type, $target)
166
    {
167
        $count = count($this->builder->findBills([
168
            'type' => $type,
169
            'target' => $target,
170
        ]));
171
172
        Assert::assertEquals($number, $count);
173
    }
174
175
    /**
176
     * @Given /charge for (\S+) is +(\S+) (\S+) per (\S+) (\S+) for target (\S+)$/
177
     */
178
    public function chargeWithTarget($type, $amount, $currency, $quantity, $unit, $target)
179
    {
180
        $quantity = $this->prepareQuantity($quantity);
181
        $amount = $this->prepareSum($amount, $quantity);
182
        $charge = $this->findCharge($type, $target);
183
        Assert::assertNotNull($charge);
184
        Assert::assertSame($type, $charge->getType()->getName());
185
        Assert::assertSame($target, $charge->getTarget()->getFullName());
186
        Assert::assertEquals($amount*100, $charge->getSum()->getAmount());
187
        Assert::assertSame($currency, $charge->getSum()->getCurrency()->getCode());
188
        Assert::assertEquals($quantity, $charge->getUsage()->getQuantity());
189
        Assert::assertSame($unit, $charge->getUsage()->getUnit()->getName());
190
    }
191
192
    /**
193
     * @Given /charge for (\S+) is +(\S+) (\S+) per (\S+) (\S+)$/
194
     */
195
    public function charge($type, $amount, $currency, $quantity, $unit)
196
    {
197
        $this->chargeWithTarget($type, $amount, $currency, $quantity, $unit, null);
198
    }
199
200
    public function findCharge($type, $target): ?ChargeInterface
201
    {
202
        foreach ($this->charges as $charge) {
203
            if ($charge->getType()->getName() !== $type) {
204
                continue;
205
            }
206
            if ($charge->getTarget()->getFullName() !== $target) {
207
                continue;
208
            }
209
            return $charge;
210
        }
211
212
        return null;
213
    }
214
215
    public function getNextCharge(): ChargeInterface
216
    {
217
        $charge = current($this->charges);
218
        next($this->charges);
219
220
        return $charge;
221
    }
222
223
    private function prepareTime($time)
224
    {
225
        if ($time === 'midnight second day of this month') {
226
            return date("Y-m-02");
227
        }
228
        if ($time[0] === 'Y') {
229
            return date($time);
230
        }
231
232
        return $time;
233
    }
234
235
    private function prepareQuantity($quantity)
236
    {
237
        if ($quantity[0] === 's') {
238
            return $this->getSaleQuantity();
239
        }
240
        return $quantity;
241
    }
242
243
    private function prepareSum($sum, $quantity)
244
    {
245
        if ($sum[0] === 's') {
246
            $sum = round(substr($sum, 1) * $quantity*100)/100;
247
        }
248
249
        return $sum;
250
    }
251
252
    public function getSaleQuantity()
253
    {
254
        return $this->days2quantity(new DateTimeImmutable($this->saleTime));
255
    }
256
257
    private function days2quantity(DateTimeImmutable $from)
258
    {
259
        $till = new DateTimeImmutable('first day of next month midnight');
260
        $diff = $from->diff($till);
261
        if ($diff->m) {
262
            return 1;
263
        }
264
265
        return $diff->d/date('t');
266
    }
267
}
268