Completed
Push — master ( 789244...b6d79a )
by Freek
01:28
created

Campaign::getMailable()   A

Complexity

Conditions 2
Paths 2

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 2
nc 2
nop 0
1
<?php
2
3
namespace Spatie\EmailCampaigns\Models;
4
5
use Carbon\Carbon;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Mail\Mailable;
9
use Spatie\EmailCampaigns\Enums\CampaignStatus;
10
use Spatie\EmailCampaigns\Jobs\SendCampaignJob;
11
use Spatie\EmailCampaigns\Jobs\SendTestMailJob;
12
use Spatie\EmailCampaigns\Mails\CampaignMailable;
13
use Spatie\EmailCampaigns\Mails\UsedInCampaign;
14
use Spatie\EmailCampaigns\Models\Concerns\HasUuid;
15
use Illuminate\Database\Eloquent\Relations\HasMany;
16
use Illuminate\Database\Eloquent\Relations\BelongsTo;
17
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
18
use Spatie\EmailCampaigns\Exceptions\CouldNotSendCampaign;
19
use Spatie\EmailCampaigns\Exceptions\CampaignCouldNotUpdate;
20
use Spatie\EmailCampaigns\Http\Controllers\CampaignWebviewController;
21
22
class Campaign extends Model
23
{
24
    use HasUuid;
25
26
    public $table = 'email_campaigns';
27
28
    protected $guarded = [];
29
30
    public $casts = [
31
        'track_opens' => 'boolean',
32
        'track_clicks' => 'boolean',
33
        'open_rate' => 'integer',
34
        'click_rate' => 'integer',
35
        'send_to_number_of_subscribers' => 'integer',
36
        'sent_at' => 'datetime',
37
        'requires_double_opt_in' => 'boolean',
38
        'statistics_calculated_at' => 'datetime',
39
    ];
40
41
    public static function boot()
42
    {
43
        parent::boot();
44
45
        static::creating(function (Campaign $campaign) {
46
            $campaign->status = CampaignStatus::CREATED;
47
        });
48
    }
49
50
    public static function scopeSentBetween(Builder $query, Carbon $periodStart, Carbon $periodEnd): void
51
    {
52
        $query
53
            ->where('sent_at', '>=', $periodStart)
54
            ->where('sent_at', '<', $periodEnd);
55
    }
56
57
    public function emailList(): BelongsTo
58
    {
59
        return $this->belongsTo(EmailList::class);
60
    }
61
62
    public function links(): HasMany
63
    {
64
        return $this->hasMany(CampaignLink::class, 'email_campaign_id');
65
    }
66
67
    public function clicks(): HasManyThrough
68
    {
69
        return $this->hasManyThrough(CampaignClick::class, CampaignLink::class, 'email_campaign_id');
70
    }
71
72
    public function opens(): HasMany
73
    {
74
        return $this->hasMany(CampaignOpen::class, 'email_campaign_id');
75
    }
76
77
    public function sends(): HasMany
78
    {
79
        return $this->hasMany(CampaignSend::class, 'email_campaign_id');
80
    }
81
82
    public function subject(string $subject)
83
    {
84
        $this->ensureUpdatable();
85
86
        $this->update(compact('subject'));
87
88
        return $this;
89
    }
90
91
    public function trackOpens(bool $bool = true)
92
    {
93
        $this->ensureUpdatable();
94
95
        $this->update(['track_opens' => $bool]);
96
97
        return $this;
98
    }
99
100
    public function trackClicks(bool $bool = true)
101
    {
102
        $this->ensureUpdatable();
103
104
        $this->update(['track_clicks' => $bool]);
105
106
        return $this;
107
    }
108
109
    public function useMailable(string $mailableClass)
110
    {
111
        if (! is_a($mailableClass, CampaignMailable::class, true)) {
112
            throw CouldNotSendCampaign::invalidMailableClass($this, $mailableClass);
113
        }
114
115
        $this->update(['mailable_class' => $mailableClass]);
116
117
        return $this;
118
    }
119
120
    public function to(EmailList $emailList)
121
    {
122
        $this->ensureUpdatable();
123
124
        $this->update(['email_list_id' => $emailList->id]);
125
126
        return $this;
127
    }
128
129
    public function content(string $html)
130
    {
131
        $this->ensureUpdatable();
132
133
        $this->update(compact('html'));
134
135
        return $this;
136
    }
137
138
    public function send()
139
    {
140
        $this->ensureSendable();
141
142
        $this->markAsSending();
143
144
        dispatch(new SendCampaignJob($this, $this->emailList));
0 ignored issues
show
Unused Code introduced by
The call to SendCampaignJob::__construct() has too many arguments starting with $this->emailList.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
145
146
        return $this;
147
    }
148
149
    public function sendTo(EmailList $emailList)
150
    {
151
        return $this->to($emailList)->send();
152
    }
153
154
    protected function ensureSendable()
155
    {
156
        if ($this->status === CampaignStatus::SENDING) {
157
            throw CouldNotSendCampaign::beingSent($this);
158
        }
159
160
        if ($this->status === CampaignStatus::SENT) {
161
            throw CouldNotSendCampaign::alreadySent($this);
162
        }
163
164
        if (is_null($this->emailList)) {
165
            throw CouldNotSendCampaign::noListSet($this);
166
        }
167
168
        if (! is_null($this->mailable)) {
169
            return;
170
        }
171
172
        if (empty($this->subject)) {
173
            throw CouldNotSendCampaign::noSubjectSet($this);
174
        }
175
176
        if (empty($this->html)) {
177
            throw CouldNotSendCampaign::noContent($this);
178
        }
179
    }
180
181
    protected function ensureUpdatable(): void
182
    {
183
        if ($this->status === CampaignStatus::SENDING) {
184
            throw CampaignCouldNotUpdate::beingSent($this);
185
        }
186
187
        if ($this->status === CampaignStatus::SENT) {
188
            throw CouldNotSendCampaign::alreadySent($this);
189
        }
190
    }
191
192
    private function markAsSending()
193
    {
194
        $this->update(['status' => CampaignStatus::SENDING]);
195
196
        return $this;
197
    }
198
199
    public function markAsSent(int $numberOfSubscribers)
200
    {
201
        $this->update([
202
            'status' => CampaignStatus::SENT,
203
            'sent_at' => now(),
204
            'statistics_calculated_at' => now(),
205
            'sent_to_number_of_subscribers' => $numberOfSubscribers,
206
        ]);
207
208
        return $this;
209
    }
210
211
    public function wasAlreadySent(): bool
212
    {
213
        return $this->status === CampaignStatus::SENT;
214
    }
215
216
    /**
217
     * @param $email string|array|\Illuminate\Support\Collection
218
     */
219
    public function sendTestMail($emails)
220
    {
221
        collect($emails)->each(function (string $email) {
222
            dispatch(new SendTestMailJob($this, $email));
223
        });
224
    }
225
226
    public function webViewUrl(): string
227
    {
228
        return url(action(CampaignWebviewController::class, $this->uuid));
229
    }
230
231
    public function getMailable(): CampaignMailable
232
    {
233
        $mailableClass = $this->mailable_class ?? CampaignMailable::class;
234
235
        $mailable = app($mailableClass);
236
        if (! $mailable instanceof CampaignMailable) {
237
            throw CouldNotSendCampaign::invalidMailableClass($this, $mailableClass);
238
        }
239
240
        return $mailable;
241
    }
242
}
243