Completed
Push — master ( 9e3f36...d6692d )
by Freek
01:30
created

Campaign::getSegment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
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 Illuminate\Mail\Mailable;
9
use Spatie\EmailCampaigns\Support\Segments\EverySubscriber;
10
use Spatie\EmailCampaigns\Support\Segments\Segment;
11
use Spatie\EmailCampaigns\Enums\CampaignStatus;
12
use Spatie\EmailCampaigns\Jobs\SendCampaignJob;
13
use Spatie\EmailCampaigns\Jobs\SendTestMailJob;
14
use Spatie\EmailCampaigns\Mails\CampaignMailable;
15
use Spatie\EmailCampaigns\Mails\UsedInCampaign;
16
use Spatie\EmailCampaigns\Models\Concerns\HasUuid;
17
use Illuminate\Database\Eloquent\Relations\HasMany;
18
use Illuminate\Database\Eloquent\Relations\BelongsTo;
19
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
20
use Spatie\EmailCampaigns\Exceptions\CouldNotSendCampaign;
21
use Spatie\EmailCampaigns\Exceptions\CampaignCouldNotUpdate;
22
use Spatie\EmailCampaigns\Http\Controllers\CampaignWebviewController;
23
24
class Campaign extends Model
25
{
26
    use HasUuid;
27
28
    public $table = 'email_campaigns';
29
30
    protected $guarded = [];
31
32
    public $casts = [
33
        'track_opens' => 'boolean',
34
        'track_clicks' => 'boolean',
35
        'open_rate' => 'integer',
36
        'click_rate' => 'integer',
37
        'send_to_number_of_subscribers' => 'integer',
38
        'sent_at' => 'datetime',
39
        'requires_double_opt_in' => 'boolean',
40
        'statistics_calculated_at' => 'datetime',
41
    ];
42
43
    public static function boot()
44
    {
45
        parent::boot();
46
47
        static::creating(function (Campaign $campaign) {
48
            $campaign->status = CampaignStatus::CREATED;
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 subject(string $subject)
85
    {
86
        $this->ensureUpdatable();
87
88
        $this->update(compact('subject'));
89
90
        return $this;
91
    }
92
93
    public function trackOpens(bool $bool = true)
94
    {
95
        $this->ensureUpdatable();
96
97
        $this->update(['track_opens' => $bool]);
98
99
        return $this;
100
    }
101
102
    public function trackClicks(bool $bool = true)
103
    {
104
        $this->ensureUpdatable();
105
106
        $this->update(['track_clicks' => $bool]);
107
108
        return $this;
109
    }
110
111
    public function useMailable(string $mailableClass)
112
    {
113
        $this->ensureUpdatable();
114
115
        if (! is_a($mailableClass, CampaignMailable::class, true)) {
116
            throw CouldNotSendCampaign::invalidMailableClass($this, $mailableClass);
117
        }
118
119
        $this->update(['mailable_class' => $mailableClass]);
120
121
        return $this;
122
    }
123
124
    public function useSegment(string $segmentClass)
125
    {
126
        $this->ensureUpdatable();
127
128
        if (! is_a($segmentClass, Segment::class, true)) {
129
            throw CouldNotSendCampaign::invalidSegmentClass($this, $segmentClass);
130
        }
131
132
        $this->update(['segment_class' => $segmentClass]);
133
134
        return $this;
135
    }
136
137
    public function to(EmailList $emailList)
138
    {
139
        $this->ensureUpdatable();
140
141
        $this->update(['email_list_id' => $emailList->id]);
142
143
        return $this;
144
    }
145
146
    public function content(string $html)
147
    {
148
        $this->ensureUpdatable();
149
150
        $this->update(compact('html'));
151
152
        return $this;
153
    }
154
155
    public function send()
156
    {
157
        $this->ensureSendable();
158
159
        $this->markAsSending();
160
161
        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...
162
163
        return $this;
164
    }
165
166
    public function sendTo(EmailList $emailList)
167
    {
168
        return $this->to($emailList)->send();
169
    }
170
171
    protected function ensureSendable()
172
    {
173
        if ($this->status === CampaignStatus::SENDING) {
174
            throw CouldNotSendCampaign::beingSent($this);
175
        }
176
177
        if ($this->status === CampaignStatus::SENT) {
178
            throw CouldNotSendCampaign::alreadySent($this);
179
        }
180
181
        if (is_null($this->emailList)) {
182
            throw CouldNotSendCampaign::noListSet($this);
183
        }
184
185
        if (! is_null($this->mailable)) {
186
            return;
187
        }
188
189
        if (empty($this->subject)) {
190
            throw CouldNotSendCampaign::noSubjectSet($this);
191
        }
192
193
        if (empty($this->html)) {
194
            throw CouldNotSendCampaign::noContent($this);
195
        }
196
    }
197
198
    protected function ensureUpdatable(): void
199
    {
200
        if ($this->status === CampaignStatus::SENDING) {
201
            throw CampaignCouldNotUpdate::beingSent($this);
202
        }
203
204
        if ($this->status === CampaignStatus::SENT) {
205
            throw CouldNotSendCampaign::alreadySent($this);
206
        }
207
    }
208
209
    private function markAsSending()
210
    {
211
        $this->update(['status' => CampaignStatus::SENDING]);
212
213
        return $this;
214
    }
215
216
    public function markAsSent(int $numberOfSubscribers)
217
    {
218
        $this->update([
219
            'status' => CampaignStatus::SENT,
220
            'sent_at' => now(),
221
            'statistics_calculated_at' => now(),
222
            'sent_to_number_of_subscribers' => $numberOfSubscribers,
223
        ]);
224
225
        return $this;
226
    }
227
228
    public function wasAlreadySent(): bool
229
    {
230
        return $this->status === CampaignStatus::SENT;
231
    }
232
233
    /**
234
     * @param $email string|array|\Illuminate\Support\Collection
235
     */
236
    public function sendTestMail($emails)
237
    {
238
        collect($emails)->each(function (string $email) {
239
            dispatch(new SendTestMailJob($this, $email));
240
        });
241
    }
242
243
    public function webViewUrl(): string
244
    {
245
        return url(action(CampaignWebviewController::class, $this->uuid));
246
    }
247
248
    public function getMailable(): CampaignMailable
249
    {
250
        $mailableClass = $this->mailable_class ?? CampaignMailable::class;
251
252
        return app($mailableClass);
253
    }
254
255
    public function getSegment(): Segment
256
    {
257
        $segmentClass = $this->segment_class ?? EverySubscriber::class;
258
259
        return app($segmentClass);
260
    }
261
}
262