Completed
Push — master ( 409074...888a1a )
by Freek
01:16
created

Campaign::sendTestMail()   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 1
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 Illuminate\Database\Eloquent\Relations\HasMany;
11
use Illuminate\Database\Eloquent\Relations\BelongsTo;
12
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
13
use Spatie\EmailCampaigns\Exceptions\CampaignCouldNotBeSent;
14
use Spatie\EmailCampaigns\Exceptions\CampaignCouldNotBeUpdated;
15
use Spatie\EmailCampaigns\Jobs\SendTestMailJob;
16
17
class Campaign extends Model
18
{
19
    public $table = 'email_campaigns';
20
21
    protected $guarded = [];
22
23
    public $casts = [
24
        'track_opens' => 'bool',
25
        'track_clicks' => 'boolean',
26
        'open_rate' => 'integer',
27
        'click_rate' => 'integer',
28
        'send_to_number_of_subscribers' => 'integer',
29
        'sent_at' => 'datetime',
30
        'requires_double_opt_in' => 'boolean',
31
        'statistics_calculated_at' => 'datetime',
32
    ];
33
34
    public static function boot()
35
    {
36
        parent::boot();
37
38
        static::creating(function (Campaign $campaign) {
39
            $campaign->status = CampaignStatus::CREATED;
40
        });
41
    }
42
43
    public static function scopeSentBetween(Builder $query, Carbon $periodStart, Carbon $periodEnd): void
44
    {
45
        $query
46
            ->where('sent_at', '>=', $periodStart)
47
            ->where('sent_at', '<', $periodEnd);
48
    }
49
50
    public function emailList(): BelongsTo
51
    {
52
        return $this->belongsTo(EmailList::class);
53
    }
54
55
    public function links(): HasMany
56
    {
57
        return $this->hasMany(CampaignLink::class, 'email_campaign_id');
58
    }
59
60
    public function clicks(): HasManyThrough
61
    {
62
        return $this->hasManyThrough(CampaignClick::class, CampaignLink::class, 'email_campaign_id');
63
    }
64
65
    public function opens(): HasMany
66
    {
67
        return $this->hasMany(CampaignOpen::class);
68
    }
69
70
    public function sends(): HasMany
71
    {
72
        return $this->hasMany(CampaignSend::class, 'email_campaign_id');
73
    }
74
75
    public function subject(string $subject)
76
    {
77
        $this->ensureUpdatable();
78
79
        $this->update(compact('subject'));
80
81
        return $this;
82
    }
83
84
    public function trackOpens(bool $bool = true)
85
    {
86
        $this->ensureUpdatable();
87
88
        $this->update(['track_opens' => $bool]);
89
90
        return $this;
91
    }
92
93
    public function trackClicks(bool $bool = true)
94
    {
95
        $this->ensureUpdatable();
96
97
        $this->update(['track_clicks' => $bool]);
98
99
        return $this;
100
    }
101
102
    public function to(EmailList $emailList)
103
    {
104
        $this->ensureUpdatable();
105
106
        $this->update(['email_list_id' => $emailList->id]);
107
108
        return $this;
109
    }
110
111
    public function content(string $html)
112
    {
113
        $this->ensureUpdatable();
114
115
        $this->update(compact('html'));
116
117
        return $this;
118
    }
119
120
    public function send()
121
    {
122
        $this->ensureSendable();
123
124
        $this->markAsSending();
125
126
        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...
127
128
        return $this;
129
    }
130
131
    public function sendTo(EmailList $emailList)
132
    {
133
        return $this->to($emailList)->send();
134
    }
135
136
    protected function ensureSendable()
137
    {
138
        if ($this->status === CampaignStatus::SENDING) {
139
            throw CampaignCouldNotBeSent::beingSent($this);
140
        }
141
142
        if ($this->status === CampaignStatus::SENT) {
143
            throw CampaignCouldNotBeSent::alreadySent($this);
144
        }
145
146
        if (empty($this->subject)) {
147
            throw CampaignCouldNotBeSent::noSubjectSet($this);
148
        }
149
150
        if (is_null($this->emailList)) {
151
            throw CampaignCouldNotBeSent::noListSet($this);
152
        }
153
154
        if (empty($this->html)) {
155
            throw CampaignCouldNotBeSent::noContent($this);
156
        }
157
    }
158
159
    protected function ensureUpdatable(): void
160
    {
161
        if ($this->status === CampaignStatus::SENDING) {
162
            throw CampaignCouldNotBeUpdated::beingSent($this);
163
        }
164
165
        if ($this->status === CampaignStatus::SENT) {
166
            throw CampaignCouldNotBeSent::alreadySent($this);
167
        }
168
    }
169
170
    private function markAsSending()
171
    {
172
        $this->update(['status' => CampaignStatus::SENDING]);
173
174
        return $this;
175
    }
176
177
    public function markAsSent(int $numberOfSubscribers)
178
    {
179
        $this->update([
180
            'status' => CampaignStatus::SENT,
181
            'sent_at' => now(),
182
            'statistics_calculated_at' => now(),
183
            'sent_to_number_of_subscribers' => $numberOfSubscribers,
184
        ]);
185
186
        return $this;
187
    }
188
189
    public function wasAlreadySent(): bool
190
    {
191
        return $this->status === CampaignStatus::SENT;
192
    }
193
194
    /**
195
     * @param $email string|array|\Illuminate\Support\Collection
196
     */
197
    public function sendTestMail($emails)
198
    {
199
        collect($emails)->each(function(string $email) {
200
            dispatch(new SendTestMailJob($this, $email));
201
        });
202
    }
203
}
204