Test Failed
Push — main ( 58bc73...59f881 )
by Michael
03:41
created

HasCoupons::redeemCoupon()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 3
b 0
f 0
nc 1
nop 1
dl 0
loc 8
ccs 2
cts 2
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 16
    public function coupons(): MorphToMany
24
    {
25 16
        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 16
            config('couponables.pivot_table', 'couponables')
27 16
        ))->withPivot(
28 16
            call(CouponPivotContract::class)->getRedeemedAtColumn()
29
        );
30
    }
31
32
    /**
33
     * Perform coupon verification.
34
     *
35
     * @param string|null $code
36
     *
37
     * @return CouponContract
38
     */
39 4
    public function verifyCoupon(?string $code): CouponContract
40
    {
41 4
        $service = call(CouponServiceContract::class);
42 4
        $proxy   = call($service->verifyCoupon($code, $this));
43
44 2
        return $proxy->getInternal(Call::INSTANCE);
45
    }
46
47
    /**
48
     * Verify the coupon or do something else on fail.
49
     *
50
     * @param string|null $code
51
     * @param mixed|null $callback
52
     * @param bool $report
53
     *
54
     * @return mixed
55
     */
56 3
    public function verifyCouponOr(?string $code, mixed $callback = null, bool $report = false): mixed
57
    {
58 3
        return rescue(
59 3
            callback: fn () => call($this)->verifyCoupon($code),
60
            rescue: $callback,
61
            report: $report
62
        );
63
    }
64
65
    /**
66
     * Use the coupon.
67
     *
68
     * @param string|null $code
69
     *
70
     * @return CouponContract
71
     */
72
    public function redeemCoupon(?string $code): CouponContract
73
    {
74
        $service = call(CouponServiceContract::class);
75
        $proxy   = call($service->verifyCoupon($code, $this));
76 2
77
        $coupon = $proxy->getInternal(Call::INSTANCE);
78 2
79
        return $service->applyCoupon($coupon, $this);
80
    }
81
82
    /**
83
     * Redeem the coupon or do something else on fail.
84
     *
85
     * @param string|null $code
86
     * @param mixed|null $callback
87
     * @param bool $report
88 22
     *
89
     * @return mixed
90 22
     */
91 22
    public function redeemCouponOr(?string $code, mixed $callback = null, bool $report = false): mixed
92
    {
93 15
        return rescue(
94
            callback: fn () => call($this)->redeemCoupon($code),
95 15
            rescue: $callback,
96
            report: $report
97
        );
98
    }
99
100
    /**
101
     * Check if the coupon is already redeemed by the model at least once.
102
     *
103
     * @param string $code
104
     *
105
     * @return bool
106
     */
107 3
    public function isCouponRedeemed(string $code): bool
108
    {
109 3
        $column = call(CouponContract::class)
110 3
            ->getCodeColumn();
111
112
        return $this->coupons()
113
            ->where($column, $code)
114
            ->exists();
115
    }
116
117
    /**
118
     * Check if coupon with this code is already used.
119
     *
120
     * @param string|null $code
121
     *
122
     * @return bool
123
     */
124
    public function isCouponAlreadyUsed(?string $code): bool
125
    {
126
        return call($this)->isCouponRedeemed($code);
127 2
    }
128
129 2
    /**
130
     * Check if the coupon is over limit for the model.
131
     *
132
     * @param string|null $code
133
     *
134
     * @return bool
135
     *
136
     */
137
    public function isCouponOverLimit(?string $code): bool
138
    {
139 4
        $service = call(CouponServiceContract::class);
140
        $coupon  = $service->getCoupon($code);
141 4
142 4
        return ! is_null($coupon) && call($coupon)->isOverLimitFor($this);
143
    }
144
}
145