HasGift::safeGift()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 4
c 1
b 0
f 1
nc 2
nop 3
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Bavix\Wallet\Traits;
4
5
use function app;
6
use Bavix\Wallet\Interfaces\Mathable;
7
use Bavix\Wallet\Interfaces\Product;
8
use Bavix\Wallet\Interfaces\Wallet;
9
use Bavix\Wallet\Models\Transfer;
10
use Bavix\Wallet\Objects\Bring;
11
use Bavix\Wallet\Services\CommonService;
12
use Bavix\Wallet\Services\DbService;
13
use Bavix\Wallet\Services\LockService;
14
use Bavix\Wallet\Services\WalletService;
15
use Throwable;
16
17
/**
18
 * Trait HasGift.
19
 */
20
trait HasGift
21
{
22
    /**
23
     * Give the goods safely.
24
     *
25
     * @param Wallet $to
26
     * @param Product $product
27
     * @param bool $force
28
     * @return Transfer|null
29
     */
30 3
    public function safeGift(Wallet $to, Product $product, bool $force = null): ?Transfer
31
    {
32
        try {
33 3
            return $this->gift($to, $product, $force);
34 3
        } catch (Throwable $throwable) {
35 3
            return null;
36
        }
37
    }
38
39
    /**
40
     * From this moment on, each user (wallet) can give
41
     * the goods to another user (wallet).
42
     * This functionality can be organized for gifts.
43
     *
44
     * @param Wallet $to
45
     * @param Product $product
46
     * @param bool $force
47
     * @return Transfer
48
     */
49 9
    public function gift(Wallet $to, Product $product, bool $force = null): Transfer
50
    {
51
        return app(LockService::class)->lock($this, __FUNCTION__, function () use ($to, $product, $force) {
52
            /**
53
             * Who's giving? Let's call him Santa Claus.
54
             * @var Wallet $santa
55
             */
56 9
            $santa = $this;
57
58
            /**
59
             * Unfortunately,
60
             * I think it is wrong to make the "assemble" method public.
61
             * That's why I address him like this!
62
             */
63
            return app(DbService::class)->transaction(static function () use ($santa, $to, $product, $force) {
64 9
                $math = app(Mathable::class);
65 9
                $discount = app(WalletService::class)->discount($santa, $product);
66 9
                $amount = $math->sub($product->getAmountProduct($santa), $discount);
67 9
                $meta = $product->getMetaProduct();
68 9
                $fee = app(WalletService::class)
69 9
                    ->fee($product, $amount);
0 ignored issues
show
Bug introduced by
$amount of type string is incompatible with the type integer expected by parameter $amount of Bavix\Wallet\Services\WalletService::fee(). ( Ignorable by Annotation )

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

69
                    ->fee($product, /** @scrutinizer ignore-type */ $amount);
Loading history...
70
71 9
                $commonService = app(CommonService::class);
72
73
                /**
74
                 * Santa pays taxes.
75
                 */
76 9
                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...
77 9
                    $commonService->verifyWithdraw($santa, $math->add($amount, $fee));
0 ignored issues
show
Bug introduced by
$math->add($amount, $fee) of type string is incompatible with the type integer expected by parameter $amount 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

77
                    $commonService->verifyWithdraw($santa, /** @scrutinizer ignore-type */ $math->add($amount, $fee));
Loading history...
78
                }
79
80 8
                $withdraw = $commonService->forceWithdraw($santa, $math->add($amount, $fee), $meta);
0 ignored issues
show
Bug introduced by
It seems like $santa can also be of type Bavix\Wallet\Traits\HasWallet; however, parameter $wallet of Bavix\Wallet\Services\Co...ervice::forceWithdraw() does only seem to accept Bavix\Wallet\Interfaces\Wallet, 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

80
                $withdraw = $commonService->forceWithdraw(/** @scrutinizer ignore-type */ $santa, $math->add($amount, $fee), $meta);
Loading history...
Bug introduced by
$math->add($amount, $fee) of type string is incompatible with the type integer expected by parameter $amount of Bavix\Wallet\Services\Co...ervice::forceWithdraw(). ( Ignorable by Annotation )

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

80
                $withdraw = $commonService->forceWithdraw($santa, /** @scrutinizer ignore-type */ $math->add($amount, $fee), $meta);
Loading history...
81 8
                $deposit = $commonService->deposit($product, $amount, $meta);
0 ignored issues
show
Bug introduced by
$amount of type string is incompatible with the type integer expected by parameter $amount of Bavix\Wallet\Services\CommonService::deposit(). ( Ignorable by Annotation )

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

81
                $deposit = $commonService->deposit($product, /** @scrutinizer ignore-type */ $amount, $meta);
Loading history...
82
83 8
                $from = app(WalletService::class)
84 8
                    ->getWallet($to);
85
86 8
                $transfers = $commonService->assemble([
87 8
                    app(Bring::class)
88 8
                        ->setStatus(Transfer::STATUS_GIFT)
89 8
                        ->setDiscount($discount)
90 8
                        ->setDeposit($deposit)
91 8
                        ->setWithdraw($withdraw)
92 8
                        ->setFrom($from)
93 8
                        ->setTo($product),
94
                ]);
95
96 8
                return current($transfers);
97 9
            });
98 9
        });
99
    }
100
101
    /**
102
     * to give force).
103
     *
104
     * @param Wallet $to
105
     * @param Product $product
106
     * @return Transfer
107
     */
108 3
    public function forceGift(Wallet $to, Product $product): Transfer
109
    {
110 3
        return $this->gift($to, $product, true);
111
    }
112
}
113