CartPay::payCart()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
eloc 21
nc 2
nop 2
dl 0
loc 33
ccs 19
cts 19
cp 1
crap 4
rs 9.584
c 2
b 0
f 1
1
<?php
2
3
namespace Bavix\Wallet\Traits;
4
5
use function array_unique;
6
use Bavix\Wallet\Exceptions\ProductEnded;
7
use Bavix\Wallet\Interfaces\Product;
8
use Bavix\Wallet\Models\Transfer;
9
use Bavix\Wallet\Objects\Cart;
10
use Bavix\Wallet\Services\CommonService;
11
use Bavix\Wallet\Services\DbService;
12
use function count;
13
use Illuminate\Database\Eloquent\ModelNotFoundException;
14
use Throwable;
15
16
trait CartPay
17
{
18
    use HasWallet;
19
20
    /**
21
     * @param Cart $cart
22
     * @return Transfer[]
23
     * @throws
24
     */
25 9
    public function payFreeCart(Cart $cart): array
26
    {
27 9
        if (! $cart->canBuy($this)) {
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Objects\Cart::canBuy(). ( Ignorable by Annotation )

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

27
        if (! $cart->canBuy(/** @scrutinizer ignore-type */ $this)) {
Loading history...
28 3
            throw new ProductEnded(trans('wallet::errors.product_stock'));
0 ignored issues
show
Bug introduced by
It seems like trans('wallet::errors.product_stock') can also be of type array and array; however, parameter $message of Bavix\Wallet\Exceptions\...uctEnded::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

28
            throw new ProductEnded(/** @scrutinizer ignore-type */ trans('wallet::errors.product_stock'));
Loading history...
29
        }
30
31 9
        app(CommonService::class)
32 9
            ->verifyWithdraw($this, 0, true);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $wallet of Bavix\Wallet\Services\Co...rvice::verifyWithdraw(). ( Ignorable by Annotation )

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

32
            ->verifyWithdraw(/** @scrutinizer ignore-type */ $this, 0, true);
Loading history...
33
34 9
        $self = $this;
35
36
        return app(DbService::class)->transaction(static function () use ($self, $cart) {
37 9
            $results = [];
38 9
            foreach ($cart->getItems() as $product) {
39 9
                $results[] = app(CommonService::class)->forceTransfer(
40 9
                    $self,
0 ignored issues
show
Bug introduced by
$self of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $from of Bavix\Wallet\Services\Co...ervice::forceTransfer(). ( Ignorable by Annotation )

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

40
                    /** @scrutinizer ignore-type */ $self,
Loading history...
41
                    $product,
42 9
                    0,
43 9
                    $product->getMetaProduct(),
44 9
                    Transfer::STATUS_PAID
45
                );
46
            }
47
48 9
            return $results;
49 9
        });
50
    }
51
52
    /**
53
     * @param Cart $cart
54
     * @param bool $force
55
     * @return Transfer[]
56
     */
57 2
    public function safePayCart(Cart $cart, bool $force = null): array
58
    {
59
        try {
60 2
            return $this->payCart($cart, $force);
61 2
        } catch (Throwable $throwable) {
62 2
            return [];
63
        }
64
    }
65
66
    /**
67
     * @param Cart $cart
68
     * @param bool $force
69
     * @return Transfer[]
70
     * @throws
71
     */
72 25
    public function payCart(Cart $cart, bool $force = null): array
73
    {
74 25
        if (! $cart->canBuy($this, $force)) {
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Objects\Cart::canBuy(). ( Ignorable by Annotation )

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

74
        if (! $cart->canBuy(/** @scrutinizer ignore-type */ $this, $force)) {
Loading history...
75 4
            throw new ProductEnded(trans('wallet::errors.product_stock'));
0 ignored issues
show
Bug introduced by
It seems like trans('wallet::errors.product_stock') can also be of type array and array; however, parameter $message of Bavix\Wallet\Exceptions\...uctEnded::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

75
            throw new ProductEnded(/** @scrutinizer ignore-type */ trans('wallet::errors.product_stock'));
Loading history...
76
        }
77
78 25
        $self = $this;
79
80
        return app(DbService::class)->transaction(static function () use ($self, $cart, $force) {
81 25
            $results = [];
82 25
            foreach ($cart->getItems() as $product) {
83 25
                if ($force) {
84 3
                    $results[] = app(CommonService::class)->forceTransfer(
85 3
                        $self,
0 ignored issues
show
Bug introduced by
$self of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $from of Bavix\Wallet\Services\Co...ervice::forceTransfer(). ( Ignorable by Annotation )

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

85
                        /** @scrutinizer ignore-type */ $self,
Loading history...
86
                        $product,
87 3
                        $product->getAmountProduct($self),
0 ignored issues
show
Bug introduced by
It seems like $product->getAmountProduct($self) can also be of type double; however, parameter $amount of Bavix\Wallet\Services\Co...ervice::forceTransfer() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

87
                        /** @scrutinizer ignore-type */ $product->getAmountProduct($self),
Loading history...
Bug introduced by
$self of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Interfaces\...uct::getAmountProduct(). ( Ignorable by Annotation )

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

87
                        $product->getAmountProduct(/** @scrutinizer ignore-type */ $self),
Loading history...
88 3
                        $product->getMetaProduct(),
89 3
                        Transfer::STATUS_PAID
90
                    );
91
92 3
                    continue;
93
                }
94
95 22
                $results[] = app(CommonService::class)->transfer(
96 22
                    $self,
0 ignored issues
show
Bug introduced by
$self of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $from of Bavix\Wallet\Services\CommonService::transfer(). ( Ignorable by Annotation )

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

96
                    /** @scrutinizer ignore-type */ $self,
Loading history...
97
                    $product,
98 22
                    $product->getAmountProduct($self),
0 ignored issues
show
Bug introduced by
It seems like $product->getAmountProduct($self) can also be of type double; however, parameter $amount of Bavix\Wallet\Services\CommonService::transfer() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

98
                    /** @scrutinizer ignore-type */ $product->getAmountProduct($self),
Loading history...
99 22
                    $product->getMetaProduct(),
100 22
                    Transfer::STATUS_PAID
101
                );
102
            }
103
104 25
            return $results;
105 25
        });
106
    }
107
108
    /**
109
     * @param Cart $cart
110
     * @return Transfer[]
111
     * @throws
112
     */
113 3
    public function forcePayCart(Cart $cart): array
114
    {
115 3
        return $this->payCart($cart, true);
116
    }
117
118
    /**
119
     * @param Cart $cart
120
     * @param bool $force
121
     * @param bool $gifts
122
     * @return bool
123
     */
124 9
    public function safeRefundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
125
    {
126
        try {
127 9
            return $this->refundCart($cart, $force, $gifts);
128 9
        } catch (Throwable $throwable) {
129 9
            return false;
130
        }
131
    }
132
133
    /**
134
     * @param Cart $cart
135
     * @param bool $force
136
     * @param bool $gifts
137
     * @return bool
138
     * @throws
139
     */
140 25
    public function refundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
141
    {
142 25
        $self = $this;
143
144
        return app(DbService::class)->transaction(static function () use ($self, $cart, $force, $gifts) {
145 25
            $results = [];
146 25
            $transfers = $cart->alreadyBuy($self, $gifts);
0 ignored issues
show
Bug introduced by
$self of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Objects\Cart::alreadyBuy(). ( Ignorable by Annotation )

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

146
            $transfers = $cart->alreadyBuy(/** @scrutinizer ignore-type */ $self, $gifts);
Loading history...
147 25
            if (count($transfers) !== count($cart)) {
148 9
                throw (new ModelNotFoundException())
149 9
                    ->setModel($self->transfers()->getMorphClass());
150
            }
151
152 23
            foreach ($cart->getItems() as $key => $product) {
153 23
                $transfer = $transfers[$key];
154 23
                $transfer->load('withdraw.wallet');
155
156 23
                if (! $force) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $force of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
157 23
                    app(CommonService::class)->verifyWithdraw(
158 23
                        $product,
159 23
                        $transfer->deposit->amount
160
                    );
161
                }
162
163 23
                app(CommonService::class)->forceTransfer(
164 23
                    $product,
0 ignored issues
show
Bug introduced by
$product of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $from of Bavix\Wallet\Services\Co...ervice::forceTransfer(). ( Ignorable by Annotation )

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

164
                    /** @scrutinizer ignore-type */ $product,
Loading history...
165 23
                    $transfer->withdraw->wallet,
166 23
                    $transfer->deposit->amount,
167 23
                    $product->getMetaProduct()
0 ignored issues
show
Bug introduced by
It seems like getMetaProduct() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

167
                    $product->/** @scrutinizer ignore-call */ 
168
                              getMetaProduct()
Loading history...
168
                );
169
170 23
                $results[] = $transfer->update([
171 23
                    'status' => Transfer::STATUS_REFUND,
172 23
                    'status_last' => $transfer->status,
173
                ]);
174
            }
175
176 23
            return count(array_unique($results)) === 1;
177 25
        });
178
    }
179
180
    /**
181
     * @param Cart $cart
182
     * @param bool $gifts
183
     * @return bool
184
     * @throws
185
     */
186 3
    public function forceRefundCart(Cart $cart, bool $gifts = null): bool
187
    {
188 3
        return $this->refundCart($cart, true, $gifts);
189
    }
190
191
    /**
192
     * @param Cart $cart
193
     * @param bool $force
194
     * @return bool
195
     */
196 4
    public function safeRefundGiftCart(Cart $cart, bool $force = null): bool
197
    {
198
        try {
199 4
            return $this->refundGiftCart($cart, $force);
200 4
        } catch (Throwable $throwable) {
201 4
            return false;
202
        }
203
    }
204
205
    /**
206
     * @param Cart $cart
207
     * @param bool $force
208
     * @return bool
209
     * @throws
210
     */
211 4
    public function refundGiftCart(Cart $cart, bool $force = null): bool
212
    {
213 4
        return $this->refundCart($cart, $force, true);
214
    }
215
216
    /**
217
     * @param Cart $cart
218
     * @return bool
219
     * @throws
220
     */
221 3
    public function forceRefundGiftCart(Cart $cart): bool
222
    {
223 3
        return $this->refundGiftCart($cart, true);
224
    }
225
226
    /**
227
     * Checks acquired product your wallet.
228
     *
229
     * @param Product $product
230
     * @param bool $gifts
231
     * @return null|Transfer
232
     */
233 35
    public function paid(Product $product, bool $gifts = null): ?Transfer
234
    {
235 35
        return current(app(Cart::class)->addItem($product)->alreadyBuy($this, $gifts)) ?: null;
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Objects\Cart::alreadyBuy(). ( Ignorable by Annotation )

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

235
        return current(app(Cart::class)->addItem($product)->alreadyBuy(/** @scrutinizer ignore-type */ $this, $gifts)) ?: null;
Loading history...
236
    }
237
}
238