Completed
Push — master ( 4cd582...789244 )
by Freek
01:51
created

EmailList::getSubscriptionStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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