EmailList   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 8

Importance

Changes 0
Metric Value
wmc 17
lcom 3
cbo 8
dl 0
loc 116
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A subscribers() 0 4 1
A allSubscribers() 0 4 1
A subscriptions() 0 4 1
A allSubscriptions() 0 4 1
A campaigns() 0 4 1
A subscribe() 0 6 1
A subscribeNow() 0 6 1
A createSubscriber() 0 18 2
A isSubscribed() 0 12 3
A getSubscription() 0 7 1
A unsubscribe() 0 14 3
A getSubscriptionStatus() 0 11 1
1
<?php
2
3
namespace Spatie\EmailCampaigns\Models;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Support\Facades\Validator;
8
use Spatie\EmailCampaigns\Models\Concerns\HasUuid;
9
use Illuminate\Database\Eloquent\Relations\HasMany;
10
use Spatie\EmailCampaigns\Enums\SubscriptionStatus;
11
use Spatie\EmailCampaigns\Exceptions\CouldNotSubscribe;
12
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
13
14
class EmailList extends Model
15
{
16
    use HasUuid;
17
18
    public $guarded = [];
19
20
    public $casts = [
21
        'requires_double_opt_in' => 'boolean',
22
    ];
23
24
    public function subscribers(): BelongsToMany
25
    {
26
        return $this->allSubscribers()->wherePivot('status', SubscriptionStatus::SUBSCRIBED);
27
    }
28
29
    public function allSubscribers(): BelongsToMany
30
    {
31
        return $this->belongsToMany(Subscriber::class, 'email_list_subscriptions', 'email_list_id', 'email_list_subscriber_id');
32
    }
33
34
    public function subscriptions(): HasMany
35
    {
36
        return $this->hasMany(Subscription::class)->where('status', SubscriptionStatus::SUBSCRIBED);
37
    }
38
39
    public function allSubscriptions(): HasMany
40
    {
41
        return $this->hasMany(Subscription::class);
42
    }
43
44
    public function campaigns(): HasMany
45
    {
46
        return $this->hasMany(Campaign::class);
47
    }
48
49
    public function subscribe(string $email, array $attributes = [], array $extraAttributes = []): Subscription
50
    {
51
        $subscriber = $this->createSubscriber($email, $attributes, $extraAttributes);
52
53
        return $subscriber->subscribeTo($this);
54
    }
55
56
    public function subscribeNow(string $email, array $attributes = [], array $extraAttributes = []): Subscription
57
    {
58
        $subscriber = $this->createSubscriber($email, $attributes, $extraAttributes);
59
60
        return $subscriber->subscribeNowTo($this);
61
    }
62
63
    protected function createSubscriber(string $email, array $attributes = [], $extraAttributes = []): Subscriber
64
    {
65
        if (Validator::make(compact('email'), ['email' => 'email'])->fails()) {
66
            throw CouldNotSubscribe::invalidEmail($email);
67
        }
68
69
        /** @var \Spatie\EmailCampaigns\Models\Subscriber $subscriber */
70
        $subscriber = Subscriber::firstOrCreate([
71
            'email' => $email,
72
        ]);
73
74
        $subscriber->fill($attributes);
75
76
        $subscriber->extra_attributes = $extraAttributes;
77
        $subscriber->save();
78
79
        return $subscriber;
80
    }
81
82
    public function isSubscribed(string $email): bool
83
    {
84
        if (! $subscriber = Subscriber::findForEmail($email)) {
85
            return false;
86
        }
87
88
        if (! $subscription = $this->getSubscription($subscriber)) {
89
            return false;
90
        }
91
92
        return $subscription->status === SubscriptionStatus::SUBSCRIBED;
93
    }
94
95
    public function getSubscription(Subscriber $subscriber): ?Subscription
96
    {
97
        return Subscription::query()
98
            ->where('email_list_id', $this->id)
99
            ->where('email_list_subscriber_id', $subscriber->id)
100
            ->first();
101
    }
102
103
    public function unsubscribe(string $email): bool
104
    {
105
        if (! $subscriber = Subscriber::findForEmail($email)) {
106
            return false;
107
        }
108
109
        if (! $subscription = $this->getSubscription($subscriber)) {
110
            return false;
111
        }
112
113
        $subscription->markAsUnsubscribed();
114
115
        return true;
116
    }
117
118
    public function getSubscriptionStatus(string $email): ?string
119
    {
120
        $subscription = Subscription::query()
0 ignored issues
show
Bug introduced by
The method first does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloq...ns\QueriesRelationships.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
121
            ->where('email_list_id', $this->id)
122
            ->whereHas('subscriber', function (Builder $query) use ($email) {
123
                $query->where('email', $email);
124
            })
125
            ->first();
126
127
        return optional($subscription)->status;
128
    }
129
}
130