Completed
Push — master ( efa9da...409f18 )
by Freek
02:01 queued 11s
created

Campaign::unsubscribes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
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 Spatie\EmailCampaigns\Enums\CampaignStatus;
9
use Spatie\EmailCampaigns\Jobs\SendCampaignJob;
10
use Spatie\EmailCampaigns\Jobs\SendTestMailJob;
11
use Spatie\EmailCampaigns\Mails\CampaignMailable;
12
use Spatie\EmailCampaigns\Models\Concerns\HasUuid;
13
use Illuminate\Database\Eloquent\Relations\HasMany;
14
use Spatie\EmailCampaigns\Support\Segments\Segment;
15
use Illuminate\Database\Eloquent\Relations\BelongsTo;
16
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
17
use Spatie\EmailCampaigns\Exceptions\CouldNotSendCampaign;
18
use Spatie\EmailCampaigns\Support\Segments\EverySubscriber;
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
            if (! $campaign->status) {
47
                $campaign->status = CampaignStatus::CREATED;
48
            }
49
        });
50
    }
51
52
    public static function scopeSentBetween(Builder $query, Carbon $periodStart, Carbon $periodEnd): void
53
    {
54
        $query
55
            ->where('sent_at', '>=', $periodStart)
56
            ->where('sent_at', '<', $periodEnd);
57
    }
58
59
    public function emailList(): BelongsTo
60
    {
61
        return $this->belongsTo(EmailList::class);
62
    }
63
64
    public function links(): HasMany
65
    {
66
        return $this->hasMany(CampaignLink::class, 'email_campaign_id');
67
    }
68
69
    public function clicks(): HasManyThrough
70
    {
71
        return $this->hasManyThrough(CampaignClick::class, CampaignLink::class, 'email_campaign_id');
72
    }
73
74
    public function opens(): HasMany
75
    {
76
        return $this->hasMany(CampaignOpen::class, 'email_campaign_id');
77
    }
78
79
    public function sends(): HasMany
80
    {
81
        return $this->hasMany(CampaignSend::class, 'email_campaign_id');
82
    }
83
84
    public function unsubscribes(): HasMany
85
    {
86
        return $this->hasMany(CampaignUnsubscribe::class, 'email_campaign_id');
87
    }
88
89
    public function subject(string $subject)
90
    {
91
        $this->ensureUpdatable();
92
93
        $this->update(compact('subject'));
94
95
        return $this;
96
    }
97
98
    public function trackOpens(bool $bool = true)
99
    {
100
        $this->ensureUpdatable();
101
102
        $this->update(['track_opens' => $bool]);
103
104
        return $this;
105
    }
106
107
    public function trackClicks(bool $bool = true)
108
    {
109
        $this->ensureUpdatable();
110
111
        $this->update(['track_clicks' => $bool]);
112
113
        return $this;
114
    }
115
116
    public function useMailable(string $mailableClass)
117
    {
118
        $this->ensureUpdatable();
119
120
        if (! is_a($mailableClass, CampaignMailable::class, true)) {
121
            throw CouldNotSendCampaign::invalidMailableClass($this, $mailableClass);
122
        }
123
124
        $this->update(['mailable_class' => $mailableClass]);
125
126
        return $this;
127
    }
128
129
    public function useSegment(string $segmentClass)
130
    {
131
        $this->ensureUpdatable();
132
133
        if (! is_a($segmentClass, Segment::class, true)) {
134
            throw CouldNotSendCampaign::invalidSegmentClass($this, $segmentClass);
135
        }
136
137
        $this->update(['segment_class' => $segmentClass]);
138
139
        return $this;
140
    }
141
142
    public function to(EmailList $emailList)
143
    {
144
        $this->ensureUpdatable();
145
146
        $this->update(['email_list_id' => $emailList->id]);
147
148
        return $this;
149
    }
150
151
    public function content(string $html)
152
    {
153
        $this->ensureUpdatable();
154
155
        $this->update(compact('html'));
156
157
        return $this;
158
    }
159
160
    public function send()
161
    {
162
        $this->ensureSendable();
163
164
        $this->markAsSending();
165
166
        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...
167
168
        return $this;
169
    }
170
171
    public function sendTo(EmailList $emailList)
172
    {
173
        return $this->to($emailList)->send();
174
    }
175
176
    protected function ensureSendable()
177
    {
178
        if ($this->status === CampaignStatus::SENDING) {
179
            throw CouldNotSendCampaign::beingSent($this);
180
        }
181
182
        if ($this->status === CampaignStatus::SENT) {
183
            throw CouldNotSendCampaign::alreadySent($this);
184
        }
185
186
        if (is_null($this->emailList)) {
187
            throw CouldNotSendCampaign::noListSet($this);
188
        }
189
190
        if (! is_null($this->mailable)) {
191
            return;
192
        }
193
194
        if (empty($this->subject)) {
195
            throw CouldNotSendCampaign::noSubjectSet($this);
196
        }
197
198
        if (empty($this->html)) {
199
            throw CouldNotSendCampaign::noContent($this);
200
        }
201
    }
202
203
    protected function ensureUpdatable(): void
204
    {
205
        if ($this->status === CampaignStatus::SENDING) {
206
            throw CampaignCouldNotUpdate::beingSent($this);
207
        }
208
209
        if ($this->status === CampaignStatus::SENT) {
210
            throw CouldNotSendCampaign::alreadySent($this);
211
        }
212
    }
213
214
    private function markAsSending()
215
    {
216
        $this->update(['status' => CampaignStatus::SENDING]);
217
218
        return $this;
219
    }
220
221
    public function markAsSent(int $numberOfSubscribers)
222
    {
223
        $this->update([
224
            'status' => CampaignStatus::SENT,
225
            'sent_at' => now(),
226
            'statistics_calculated_at' => now(),
227
            'sent_to_number_of_subscribers' => $numberOfSubscribers,
228
        ]);
229
230
        return $this;
231
    }
232
233
    public function wasAlreadySent(): bool
234
    {
235
        return $this->status === CampaignStatus::SENT;
236
    }
237
238
    /**
239
     * @param $email string|array|\Illuminate\Support\Collection
240
     */
241
    public function sendTestMail($emails)
242
    {
243
        collect($emails)->each(function (string $email) {
244
            dispatch(new SendTestMailJob($this, $email));
245
        });
246
    }
247
248
    public function webViewUrl(): string
249
    {
250
        return url(action(CampaignWebviewController::class, $this->uuid));
251
    }
252
253
    public function getMailable(): CampaignMailable
254
    {
255
        $mailableClass = $this->mailable_class ?? CampaignMailable::class;
256
257
        return app($mailableClass);
258
    }
259
260
    public function getSegment(): Segment
261
    {
262
        $segmentClass = $this->segment_class ?? EverySubscriber::class;
263
264
        return app($segmentClass);
265
    }
266
}
267

 

OSZAR »