Passed
Push — main ( af0b5b...33d355 )
by Michael
04:04
created

HasCoupons::redeemCoupon()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
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 3
    public function verifyCoupon(?string $code): CouponContract
40
    {
41 3
        $service = call(CouponServiceContract::class);
42 3
        $proxy   = call($service->verifyCoupon($code, $this));
43
44 2
        return $proxy->getInternal(Call::INSTANCE);
45
    }
46
47
    /**
48
     * Redeem the coupon.
49
     *
50
     * @param string|null $code
51
     * @param mixed|null  $rescue
52
     * @param bool        $report
53
     *
54
     * @return CouponContract|null
55
     */
56 2
    public function verifyOrNullifyCoupon(?string $code, mixed $rescue = null, bool $report = false): ?CouponContract
57
    {
58 2
        if ($code) {
59 2
            return rescue(
60 2
                callback: fn () => call($this)->verifyCoupon($code),
61
                rescue: $rescue,
62
                report: $report
63
            );
64
        }
65
66 1
        return null;
67
    }
68
69
    /**
70
     * Use the coupon.
71
     *
72
     * @param string|null $code
73
     *
74
     * @return CouponContract
75
     */
76 19
    public function redeemCoupon(?string $code): CouponContract
77
    {
78 19
        $service = call(CouponServiceContract::class);
79 19
        $proxy   = call($service->verifyCoupon($code, $this));
80
81 14
        $coupon = $proxy->getInternal(Call::INSTANCE);
82
83 14
        return $service->applyCoupon($coupon, $this);
84
    }
85
86
    /**
87
     * Redeem the coupon.
88
     *
89
     * @param string|null $code
90
     * @param mixed|null  $rescue
91
     * @param bool        $report
92
     *
93
     * @return CouponContract|null
94
     */
95 2
    public function redeemOrNullifyCoupon(?string $code, mixed $rescue = null, bool $report = false): ?CouponContract
96
    {
97 2
        if ($code) {
98 2
            return rescue(
99 2
                callback: fn () => call($this)->redeemCoupon($code),
100
                rescue: $rescue,
101
                report: $report
102
            );
103
        }
104
105 1
        return null;
106
    }
107
108
    /**
109
     * Check if the coupon is already redeemed by the model at least once.
110
     *
111
     * @param string $code
112
     *
113
     * @return bool
114
     */
115 4
    public function isCouponRedeemed(string $code): bool
116
    {
117 4
        $column = call(CouponContract::class)
118 4
            ->getCodeColumn();
119
120 4
        return $this->coupons()
121 4
            ->where($column, $code)
122 4
            ->exists();
123
    }
124
125
    /**
126
     * Check if coupon with this code is already used.
127
     *
128
     * @param string|null $code
129
     *
130
     * @return bool
131
     */
132 3
    public function isCouponAlreadyUsed(?string $code): bool
133
    {
134 3
        return call($this)->isCouponRedeemed($code);
135
    }
136
137
    /**
138
     * Check if the coupon is over limit for the model.
139
     *
140
     * @param string|null $code
141
     *
142
     * @return bool
143
     *
144
     */
145 1
    public function isCouponOverLimit(?string $code): bool
146
    {
147 1
        $service = call(CouponServiceContract::class);
148 1
        $coupon  = $service->getCoupon($code);
149
150 1
        return ! is_null($coupon) && call($coupon)->isOverLimitFor($this);
151
    }
152
}
153