Passed
Push — main ( f1a75b...5851c9 )
by Michael
04:19
created

HasCoupons::redeemOrNullifyCoupon()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 3
dl 0
loc 11
ccs 5
cts 5
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\Couponables;
6
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Relations\MorphToMany;
9
use Illuminate\Support\Str;
10
use MichaelRubel\Couponables\Exceptions\CouponException;
11
use MichaelRubel\Couponables\Models\Contracts\CouponContract;
12
use MichaelRubel\Couponables\Models\Contracts\CouponPivotContract;
13
use MichaelRubel\Couponables\Services\Contracts\CouponServiceContract;
14
use MichaelRubel\EnhancedContainer\Call;
15
16
trait HasCoupons
17
{
18
    /**
19
     * Polymorphic relation to the coupons.
20
     *
21
     * @return MorphToMany
22
     */
23 15
    public function coupons(): MorphToMany
24
    {
25 15
        return $this->morphToMany(app(CouponContract::class), Str::singular(
0 ignored issues
show
Bug introduced by
It seems like morphToMany() 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

25
        return $this->/** @scrutinizer ignore-call */ morphToMany(app(CouponContract::class), Str::singular(
Loading history...
26 15
            config('couponables.pivot_table', 'couponables')
27 15
        ))->withPivot(
28 15
            call(CouponPivotContract::class)->getRedeemedAtColumn()
29
        );
30
    }
31
32
    /**
33
     * Perform coupon verification.
34
     *
35
     * @param string|null $code
36
     *
37
     * @return CouponContract
38
     */
39 1
    public function verifyCoupon(?string $code): CouponContract
40
    {
41 1
        $service = call(CouponServiceContract::class);
42 1
        $proxy   = call($service->verifyCoupon($code, $this));
43
44 1
        return $proxy->getInternal(Call::INSTANCE);
45
    }
46
47
    /**
48
     * Use the coupon.
49
     *
50
     * @param string|null $code
51
     *
52
     * @return CouponContract
53
     */
54 19
    public function redeemCoupon(?string $code): CouponContract
55
    {
56 19
        $service = call(CouponServiceContract::class);
57 19
        $proxy   = call($service->verifyCoupon($code, $this));
58
59 14
        $coupon = $proxy->getInternal(Call::INSTANCE);
60
61 14
        return $service->applyCoupon($coupon, $this);
62
    }
63
64
    /**
65
     * Redeem the coupon.
66
     *
67
     * @param string|null $code
68
     * @param mixed|null  $rescue
69
     * @param bool        $report
70
     *
71
     * @return CouponContract|null
72
     */
73 2
    public function redeemOrNullifyCoupon(?string $code, mixed $rescue = null, bool $report = false): ?CouponContract
74
    {
75 2
        if ($code) {
76 2
            return rescue(
77 2
                callback: fn () => call($this)->redeemCoupon($code),
78
                rescue: $rescue,
79
                report: $report
80
            );
81
        }
82
83 1
        return null;
84
    }
85
86
    /**
87
     * Check if the coupon is already redeemed by the model at least once.
88
     *
89
     * @param string $code
90
     *
91
     * @return bool
92
     */
93 4
    public function isCouponRedeemed(string $code): bool
94
    {
95 4
        $column = call(CouponContract::class)
96 4
            ->getCodeColumn();
97
98 4
        return $this->coupons()
99 4
            ->where($column, $code)
100 4
            ->exists();
101
    }
102
103
    /**
104
     * Check if coupon with this code is already used.
105
     *
106
     * @param string|null $code
107
     *
108
     * @return bool
109
     */
110 3
    public function isCouponAlreadyUsed(?string $code): bool
111
    {
112 3
        return call($this)->isCouponRedeemed($code);
113
    }
114
115
    /**
116
     * Check if the coupon is over limit for the model.
117
     *
118
     * @param string|null $code
119
     *
120
     * @return bool
121
     *
122
     */
123 1
    public function isCouponOverLimit(?string $code): bool
124
    {
125 1
        $service = call(CouponServiceContract::class);
126 1
        $coupon  = $service->getCoupon($code);
127
128 1
        return ! is_null($coupon) && call($coupon)->isOverLimitFor($this);
129
    }
130
}
131