LaravelInvites::notBefore()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace mathewparet\LaravelInvites;
4
5
use mathewparet\LaravelInvites\Exceptions\InvalidInvitationCodeException;
6
use mathewparet\LaravelInvites\Exceptions\InvalidEmailIdException;
7
use mathewparet\LaravelInvites\Exceptions\InvitationNotYetActiveException;
8
use mathewparet\LaravelInvites\Exceptions\InvitationExpiredException;
9
use mathewparet\LaravelInvites\Exceptions\InvitationNotValidWithEmailException;
10
use mathewparet\LaravelInvites\Exceptions\MaximumUseOfCodeException;
11
use mathewparet\LaravelInvites\Exceptions\LaravelInvitesException;
12
use mathewparet\LaravelInvites\Exceptions\AnEmailCanHaveOnlyOneInvitation;
13
14
use mathewparet\LaravelInvites\Mail\InvitationMail;
15
16
use Illuminate\Support\Facades\Mail;
17
18
use Carbon\Carbon;
19
use Validator;
20
21
use mathewparet\LaravelInvites\Models\Invite;
22
23
class LaravelInvites
24
{
25
    private $number_of_invites = 1;
26
    private $data = [];
27
28
    /**
29
     * Initialize the data attributes and reset values
30
     * 
31
     * @return void
32
     */
33
    private function initializeData()
34
    {
35
        $this->data = ['allowed_count' => 1];
36
    }
37
38
    public function __construct()
39
    {
40
        $this->initializeData();
41
    }
42
43
    /**
44
     * Get the invites from DB
45
     * 
46
     * @return mixed
47
     */
48
    public function get()
49
    {
50
        if (!blank(optional($this->data)['email'])) {
51
                    $result = Invite::valid()->whereEmail($this->data['email'])->first();
52
        } else {
53
                    $result = Invite::valid()->get();
54
        }
55
56
        $this->initializeData();
57
58
        return $result;
59
    }
60
61
    /**
62
     * Set the email property for generating or getting invitation
63
     * 
64
     * @param string $email
65
     * 
66
     * @return \mathewparet\LaravelInvites\Facades\LaravelInvites
67
     */
68
    public function for($email = null)
69
    {
70
        if (!$email)
71
        {
72
            unset($this->data['email']);
73
            return $this;
74
        }
75
76
        $validator = Validator::make(compact('email'), [
77
            'email'=>'required|email'
78
        ]);
79
        if ($validator->fails()) {
80
                    throw new InvalidEmailIdException;
81
        }
82
83
        $this->data['email'] = $email;
84
85
        return $this;
86
    }
87
88
    /**
89
     * Create a single invite model
90
     * 
91
     * @return \mathewparet\LaravelInvites\Models\Invite
92
     */
93
    private function prepareSingle()
94
    {
95
        $invite = Invite::create($this->data);
96
97
        if ($invite->email && config('laravelinvites.mail.enabled', true)) {
0 ignored issues
show
Bug introduced by
The property email does not seem to exist on mathewparet\LaravelInvites\Models\Invite. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
98
                    Mail::to($invite->email)->send(new InvitationMail($invite));
99
        }
100
101
        return $invite;
102
    }
103
104
    /**
105
     * Get the validity start date for the invitation
106
     * 
107
     * @param \Carbon\Carbon $date
108
     * @return \mathewparet\LaravelInvites\Facades\LaravelInvites
109
     */
110
    public function validFrom(Carbon $date)
111
    {
112
        $this->data['valid_from'] = $date;
113
114
        return $this;
115
    }
116
117
    /**
118
     * Generate the requested invitations
119
     * 
120
     * @return mixed
121
     */
122
    private function prepare()
123
    {
124
        if ($this->number_of_invites == 1) {
125
                    return $this->prepareSingle();
126
        }
127
128
        $invites = [];
129
130
        for ($i = 0; $i < $this->number_of_invites; $i++)
131
        {
132
            $invites[] = $this->prepareSingle();
133
        }
134
135
        return $invites;
136
    }
137
138
    /**
139
     * Validate email ID before generating invitation code
140
     * 
141
     * @param integer $number_of_invites
142
     * 
143
     * @throws \mathewparet\LaravelInvites\Exceptions\AnEmailCanHaveOnlyOneInvitation
144
     */
145
    private function validateEmailBeforeGeneration($number_of_invites = 1)
146
    {
147
        if (optional($this->data)['email'] && !blank($this->data['email']))
148
        {
149
            if ($number_of_invites > 1 || $this->data['allowed_count'] > 1) {
150
                            throw new AnEmailCanHaveOnlyOneInvitation;
151
            }
152
153
            $validator = Validator::make($this->data, [
154
                'email'=>'unique:'.config('laravelinvites.table').',email'
155
            ]);
156
157
            if ($validator->fails()) {
158
                            throw new AnEmailCanHaveOnlyOneInvitation;
159
            }
160
        }
161
    }
162
163
    /**
164
     * Generate invitations
165
     * 
166
     * @param integer $number_of_invites | default = 1
167
     * 
168
     * @return mixed array of invitations generated
169
     */
170
    public function generate($number_of_invites = 1)
171
    {
172
        $this->validateEmailBeforeGeneration($number_of_invites);
173
174
        $this->number_of_invites = $number_of_invites;
175
176
        $invitations = $this->prepare();
177
        
178
        $this->initializeData();
179
180
        return $invitations;
181
    }
182
183
    /**
184
     * Set the number of uses allowed for this invite
185
     * 
186
     * @param integer $num_allowed
187
     * 
188
     * @return \mathewparet\LaravelInvites\Facades\LaravelInvites
189
     */
190
    public function allow($num_allowed = 1)
191
    {
192
        $this->data['allowed_count'] = $num_allowed;
193
194
        return $this;
195
    }
196
197
    /**
198
     * Generate a single invitiation to be used only by a specific email
199
     * 
200
     * @param string $email
201
     * 
202
     * @return mixed the invitation record
203
     */
204
    public function generateFor($email)
205
    {
206
        $this->for($email);
207
208
        return $this->generate(1);
209
    }
210
211
    /**
212
     * Set expiry to never expire
213
     * 
214
     * @return \mathewparet\LaravelInvites\Facades\LaravelInvites
215
     */
216
    public function withoutExpiry()
217
    {
218
        $this->data['valid_upto'] = null;
219
220
        return $this;
221
    }
222
223
    /**
224
     * Set an expiry date
225
     * 
226
     * @param \Carbon\Carbon $data
227
     */
228
    public function setExpiry(Carbon $date)
229
    {
230
        $this->data['valid_upto'] = $date;
231
232
        return $this;
233
    }
234
235
    /**
236
     * Find an invitation by code
237
     * 
238
     * @param string $code
239
     *
240
     * @return \mathewparet\LaravelInvites\Models\Invite $invite
241
     */
242
    public function find($code)
243
    {
244
        return Invite::whereCode($code)->firstOrFail();
245
    }
246
247
    /**
248
     * Identify the email attribute name from validator parameter
249
     * 
250
     * @param Array $parameters
251
     * 
252
     * @return string
253
     */
254
    private function getEmailParameter($parameters)
255
    {
256
        return $parameters[0] ?: 'email';
257
    }
258
    
259
    /**
260
     * Validate the form submission for a valid invitation code.
261
     * This is extended through validator.
262
     * 
263
     * @param String $attribute
264
     * @param String $value
265
     * @param Array $parameters
266
     * @param Validator $validator
267
     * 
268
     * @return boolean
269
     * 
270
     * @throws \mathewparet\LaravelInvites\Exceptions\LaravelInvitesException
271
     */
272
    public function validate(/** @scrutinizer ignore-unused */ $attribute, /** @scrutinizer ignore-unused */ $value, $parameters, $validator)
273
    {
274
        $emailFieldName = $this->getEmailParameter($parameters);
275
276
        try {
277
            /** @scrutinizer ignore-call */ 
278
            $validator_data = $validator->getData();
279
            $email = $validator_data[$emailFieldName];
280
281
            $this->check($value, $email);
282
            return true;
283
        } catch (InvalidInvitationCodeException $e)
284
        {
285
            $validator->errors()->add($attribute, 'Invalid invitation code');
1 ignored issue
show
Bug introduced by
The method errors() does not exist on Illuminate\Support\Facades\Validator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

285
            $validator->/** @scrutinizer ignore-call */ 
286
                        errors()->add($attribute, 'Invalid invitation code');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
286
            return false;
287
        } catch (InvitationNotYetActiveException $e)
288
        {
289
            $validator->errors()->add($attribute, 'Invitation code is not valid yet');
290
            return false;
291
        } catch (InvitationExpiredException $e)
292
        {
293
            $validator->errors()->add($attribute, 'Invitation expired');
294
            return false;
295
        } catch (InvitationNotValidWithEmailException $e)
296
        {
297
            $validator->errors()->add($attribute, 'Invitation code is not valid with the provided '.$emailFieldName);
298
            return false;
299
        } catch (MaximumUseOfCodeException $e)
300
        {
301
            $validator->errors()->add($attribute, 'Invitation code has been used for the maximum possible times');
302
            return false;
303
        }
304
    }
305
306
    /**
307
     * Check whether an invitation is valid with the provided email
308
     * 
309
     * @param string $code
310
     * @param string $email to be checked against
311
     * 
312
     * @return boolean
313
     */
314
315
    public function isValid($code, $email = null)
316
    {
317
        try
318
        {
319
            $this->check($code, $email);
320
321
            return true;
322
        } catch (LaravelInvitesException $e)
323
        {
324
            return false;
325
        }
326
    }
327
328
    /**
329
     * Check the validity of the invitiation code
330
     * 
331
     * @param string $code
332
     * @param string $email
333
     * 
334
     * @return boolean
335
     */
336
    public function check($code, $email = null)
337
    {
338
        $invite = Invite::whereCode($code)->first();
339
340
        if (!$invite) {
341
                    throw new InvalidInvitationCodeException;
342
        }
343
        
344
        if ($invite->valid_from > now()) {
345
                    throw new InvitationNotYetActiveException($invite->valid_from);
346
        }
347
348
        if ($invite->valid_upto && $invite->valid_upto <= now()) {
349
                    throw new InvitationExpiredException($invite->valid_upto);
350
        }
351
352
        if ($invite->used_count > ($invite->allowed_count - 1)) {
0 ignored issues
show
Bug introduced by
The property used_count does not seem to exist on mathewparet\LaravelInvites\Models\Invite. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
353
                    throw new MaximumUseOfCodeException($invite->allowed_count);
354
        }
355
356
        if ($invite->email !== $email && !blank($invite->email)) {
0 ignored issues
show
Bug introduced by
The property email does not seem to exist on mathewparet\LaravelInvites\Models\Invite. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
357
                    throw new InvitationNotValidWithEmailException($email, $invite->email);
358
        }
359
360
        return true;
361
    }
362
363
    /**
364
     * Redeem the invitation code. Make sure the form field is validated before this calls to avoid exceptions
365
     * 
366
     * @param string $code
367
     * @param string $email (optional)
368
     * 
369
     * @return boolean
370
     */
371
372
    public function redeem($code, $email = null)
373
    {
374
        $this->check($code, $email);
375
     
376
        $this->find($code)->redeem();
377
378
        return true;
379
    }
380
381
    /**
382
     * Set a validity start date for the invitation
383
     * 
384
     * @param \Carbon\Carbon $date
385
     * 
386
     * @return \mathewparet\LaravelInvites\Facades\LaravelInvites
387
     */
388
    public function notBefore(Carbon $date)
389
    {
390
        return $this->validFrom($date);
391
    }
392
393
}