Completed
Push — master ( 989be6...c8fc2e )
by Freek
01:40
created

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