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

HasCoupons   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 0 Features 1
Metric Value
eloc 27
dl 0
loc 113
ccs 31
cts 31
cp 1
rs 10
c 6
b 0
f 1
wmc 9

7 Methods

Rating   Name   Duplication   Size   Complexity  
A redeemCoupon() 0 8 1
A verifyCoupon() 0 6 1
A isCouponRedeemed() 0 8 1
A isCouponOverLimit() 0 6 2
A coupons() 0 6 1
A isCouponAlreadyUsed() 0 3 1
A redeemOrNullifyCoupon() 0 11 2
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