Passed
Push — main ( e83696...37db01 )
by Michael
03:45
created

HasCoupons::redeemCouponOr()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\Couponables\Traits;
6
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Relations\MorphToMany;
9
use Illuminate\Support\Str;
10
use MichaelRubel\Couponables\Models\Contracts\CouponContract;
11
use MichaelRubel\Couponables\Services\Contracts\CouponServiceContract;
12
use MichaelRubel\EnhancedContainer\Call;
13
use MichaelRubel\EnhancedContainer\Core\CallProxy;
14
15
trait HasCoupons
16
{
17
    /**
18
     * @var CallProxy
19
     */
20
    protected static CallProxy $bindable;
21
22
    /**
23
     * @var CallProxy
24
     */
25
    protected static CallProxy $bindableService;
26
27
    /**
28
     * Initialize the method binding objects.
29
     *
30
     * @return void
31
     */
32 40
    public function initializeHasCoupons(): void
33
    {
34 40
        self::$bindable        = call($this);
35 40
        self::$bindableService = call(CouponServiceContract::class);
36
    }
37
38
    /**
39
     * Polymorphic relation to the coupons.
40
     *
41
     * @return MorphToMany
42
     */
43 19
    public function coupons(): MorphToMany
44
    {
45 19
        return with(self::$bindableService, fn ($service) => $this->morphToMany(
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

45
        return with(self::$bindableService, fn ($service) => $this->/** @scrutinizer ignore-call */ morphToMany(
Loading history...
46 19
            $service->model->getInternal(Call::INSTANCE),
47 19
            Str::singular(config('couponables.pivot_table', 'couponables'))
48 19
        )->withPivot([
49 19
            $service->pivot->getRedeemedAtColumn(),
50 19
            $service->pivot->getRedeemedTypeColumn(),
51 19
            $service->pivot->getRedeemedIdColumn(),
52
        ]));
53
    }
54
55
    /**
56
     * Check if coupon with this code is already used.
57
     *
58
     * @param string|null $code
59
     *
60
     * @return bool
61
     */
62 5
    public function isCouponAlreadyUsed(?string $code): bool
63
    {
64 5
        $column = self::$bindableService->model->getCodeColumn();
65
66 5
        return $this->coupons()
67 5
            ->where($column, $code)
68 5
            ->exists();
69
    }
70
71
    /**
72
     * Check if the coupon is over limit for the model.
73
     *
74
     * @param string|null $code
75
     *
76
     * @return bool
77
     *
78
     */
79 1
    public function isCouponOverLimit(?string $code): bool
80
    {
81 1
        $coupon = self::$bindableService->getCoupon($code);
82
83 1
        return ! is_null($coupon) && call($coupon)->isOverLimitFor($this);
84
    }
85
86
    /**
87
     * Verify if the coupon is valid.
88
     *
89
     * @param string|null $code
90
     *
91
     * @return CouponContract
92
     */
93 4
    public function verifyCoupon(?string $code): CouponContract
94
    {
95 4
        return self::$bindableService->verifyCoupon($code, $this);
96
    }
97
98
    /**
99
     * Verify and use the coupon.
100
     *
101
     * @param string|null $code
102
     * @param Model|null  $redeemed
103
     *
104
     * @return CouponContract
105
     */
106 25
    public function redeemCoupon(?string $code, ?Model $redeemed = null): CouponContract
107
    {
108 25
        return with(self::$bindableService, function ($service) use ($code, $redeemed) {
109 25
            $coupon = $service->verifyCoupon($code, $this);
110
111 18
            return $service->applyCoupon($coupon, $this, $redeemed);
112
        });
113
    }
114
115
    /**
116
     * Verify the coupon or do something else on fail.
117
     *
118
     * @param string|null $code
119
     * @param mixed|null  $callback
120
     *
121
     * @return mixed
122
     */
123 3
    public function verifyCouponOr(?string $code, mixed $callback = null): mixed
124
    {
125 3
        return rescue(
126 3
            fn () => self::$bindable->verifyCoupon($code),
127
            $callback,
128
            false
129
        );
130
    }
131
132
    /**
133
     * Redeem the coupon or do something else on fail.
134
     *
135
     * @param string|null $code
136
     * @param mixed|null  $callback
137
     *
138
     * @return mixed
139
     */
140 3
    public function redeemCouponOr(?string $code, mixed $callback = null): mixed
141
    {
142 3
        return rescue(
143 3
            fn () => self::$bindable->redeemCoupon($code, null),
144
            $callback,
145
            false
146
        );
147
    }
148
149
    /**
150
     * Redeem the code using model.
151
     *
152
     * @param Model       $model
153
     * @param string|null $couponCode
154
     *
155
     * @return CouponContract
156
     */
157 1
    public function redeemBy(Model $model, ?string $couponCode): CouponContract
158
    {
159 1
        return with(self::$bindableService, function ($service) use ($couponCode, $model) {
160 1
            $coupon = $service->verifyCoupon($couponCode, $model);
161
162 1
            return $service->applyCoupon($coupon, $model, $this);
163
        });
164
    }
165
}
166