Passed
Branch master (80e19c)
by Mathew
02:51
created

LaravelInvites   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 296
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 45
eloc 96
dl 0
loc 296
rs 8.8
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A prepare() 0 13 3
A isValid() 0 11 2
A __construct() 0 3 1
A withoutExpiry() 0 5 1
A notBefore() 0 4 1
A for() 0 17 3
A setExpiry() 0 5 1
A initializeData() 0 3 1
A redeem() 0 7 1
A prepareSingle() 0 8 3
B check() 0 20 8
A get() 0 10 2
B validate() 0 34 6
A generateFor() 0 5 1
A allow() 0 5 1
A validFrom() 0 5 2
A generate() 0 22 5
A find() 0 3 1
A getEmailParameter() 0 3 2

How to fix   Complexity   

Complex Class

Complex classes like LaravelInvites often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use LaravelInvites, and based on these observations, apply Extract Interface, too.

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
/**
24
 * Usage
25
 * use mathewparet\LaravelInvites\LaravelInvites;
26
 * 
27
 * $invitation = LaravelInvites::withoutExpiry()->allowUses(10)->generate(100);
28
 */
29
30
class LaravelInvites
31
{
32
    private $number_of_invites = 1;
33
    private $data = [];
34
35
    private function initializeData()
36
    {
37
        $this->data = ['allow_count' => 1];
38
    }
39
40
    public function __construct()
41
    {
42
        $this->initializeData();
43
    }
44
45
    public function get()
46
    {
47
        if(!blank(optional($this->data)['email']))
48
            $result =  Invite::valid()->whereEmail($this->data['email'])->first();
49
        else
50
            $result = Invite::valid()->get();
51
52
        $this->initializeData();
53
54
        return $result;
55
    }
56
57
    public function for($email=null)
58
    {
59
        if(!$email)
60
        {
61
            unset($this->data['email']);
62
            return $this;
63
        }
64
65
        $validator = Validator::make(compact('email'),[
66
            'email'=>'required|email'
67
        ]);
68
        if($validator->fails())
69
            throw new InvalidEmailIdException;
70
71
        $this->data['email'] = $email;
72
73
        return $this;
74
    }
75
76
    private function prepareSingle()
77
    {
78
        $invite = Invite::create($this->data);
79
80
        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...
81
            Mail::to($invite->email)->send(new InvitationMail($invite));
82
83
        return $invite;
84
    }
85
86
    public function validFrom($date = null)
87
    {
88
        $this->data['valid_from'] = $date ? : now();
89
90
        return $this;
91
    }
92
93
    /**
94
     * Generate the requested invitations
95
     * 
96
     * @return \mathewparet\LaravelInvites\Model\Invite::clss $invite
0 ignored issues
show
Bug introduced by
The type mathewparet\LaravelInvites\Model\Invite was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
97
     */
98
    private function prepare()
99
    {
100
        if($this->number_of_invites == 1)
101
            return $this->prepareSingle();
102
103
        $invites = [];
104
105
        for($i = 0; $i < $this->number_of_invites; $i++)
106
        {
107
            $invites[] = $this->prepareSingle();
108
        }
109
110
        return $invites;
111
    }
112
113
    /**
114
     * Generate invitations
115
     * 
116
     * @param intiger $number_of_invites | default = 1
0 ignored issues
show
Bug introduced by
The type mathewparet\LaravelInvites\intiger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
117
     * 
118
     * @return mixed array of invitations generated
119
     */
120
    public function generate($number_of_invites = 1)
121
    {
122
        if(optional($this->data)['email'] && !blank($this->data['email']))
123
        {
124
            if($number_of_invites > 1)
125
                throw new AnEmailCanHaveOnlyOneInvitation;
126
127
            $validator = Validator::make($this->data,[
128
                'email'=>'unique:'.config('laravelinvites.table').',email'
129
            ]);
130
131
            if($validator->fails())
132
                throw new AnEmailCanHaveOnlyOneInvitation;
133
        }
134
135
        $this->number_of_invites = $number_of_invites;
136
137
        $invitations =  $this->prepare();
138
        
139
        $this->initializeData();
140
141
        return $invitations;
142
    }
143
144
    /**
145
     * Set the number of uses allowed for this invite
146
     * 
147
     * @param integer $num_allowed
148
     * 
149
     * @return $this
150
     */
151
    public function allow($num_allowed = 1)
152
    {
153
        $this->data['allowed_count'] = $num_allowed;
154
155
        return $this;
156
    }
157
158
    /**
159
     * Generate a single invitiation to be used only by a specific email
160
     * 
161
     * @param string $email
162
     * 
163
     * @return mixed the invitation record
164
     */
165
    public function generateFor($email)
166
    {
167
        $this->for($email);
168
169
        return $this->generate(1);
0 ignored issues
show
Bug introduced by
1 of type integer is incompatible with the type mathewparet\LaravelInvites\intiger expected by parameter $number_of_invites of mathewparet\LaravelInvit...avelInvites::generate(). ( Ignorable by Annotation )

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

169
        return $this->generate(/** @scrutinizer ignore-type */ 1);
Loading history...
170
    }
171
172
    /**
173
     * Set expiry to never expire
174
     * 
175
     * @return reference to self
0 ignored issues
show
Bug introduced by
The type mathewparet\LaravelInvites\reference was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
176
     */
177
    public function withoutExpiry()
178
    {
179
        $this->data['valid_upto'] = null;
180
181
        return $this;
182
    }
183
184
    /**
185
     * Set an expiry date
186
     * 
187
     * @param \Carbon\Carbon $data
188
     */
189
    public function setExpiry(Carbon $date)
190
    {
191
        $this->data['valid_upto'] = $date;
192
193
        return $this;
194
    }
195
196
    /**
197
     * Find an invitation by code
198
     * 
199
     * @param string $code
200
     *
201
     * @return \mathewparet\LaravelInvites\Model\Invite $invite
202
     */
203
    public function find($code)
204
    {
205
        return Invite::whereCode($code)->firstOrFail();
206
    }
207
208
    private function getEmailParameter($parameters)
209
    {
210
        return $parameters[0] ? : 'email' ;
211
    }
212
    
213
    public function validate($attribute, $value, $parameters, $validator)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

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

213
    public function validate($attribute, /** @scrutinizer ignore-unused */ $value, $parameters, $validator)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

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

213
    public function validate(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters, $validator)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
214
    {
215
        $emailFieldName = $this->getEmailParameter($parameters);
216
217
        try {        
218
            $email = $validator->data[$emailFieldName];
219
220
            $this->check($code, $email);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code seems to be never defined.
Loading history...
221
            return true;
222
        }
223
        catch(InvalidInvitationCodeException $e)
224
        {
225
            $validator->errors()->add($emailFieldName, ':attribute is invalid');
226
            return false;
227
        }
228
        catch(InvitationNotYetActiveException $e)
229
        {
230
            $validator->errors()->add($emailFieldName, ':attribute is not valid yet');
231
            return false;
232
        }
233
        catch(InvitationExpiredException $e)
234
        {
235
            $validator->errors()->add($emailFieldName, ':attribute expired');
236
            return false;
237
        }
238
        catch(InvitationNotValidWithEmailException $e)
239
        {
240
            $validator->errors()->add($emailFieldName, ':attribute is not valid with the provided '.$emailFieldName);
241
            return false;
242
        }
243
        catch(MaximumUseOfCodeException $e)
244
        {
245
            $validator->errors()->add($emailFieldName, ':attribute has been used for the maximum possible times');
246
            return false;
247
        }
248
    }
249
250
    /**
251
     * Check whether an invitation is valid with the provided email
252
     * 
253
     * @param string $code
254
     * @param string $email to be checked against
255
     */
256
257
    public function isValid($code, $email = null)
258
    {
259
        try
260
        {
261
            $this->check($code, $email);
262
263
            return true;
264
        }
265
        catch(LaravelInvitesException $e)
266
        {
267
            return false;
268
        }
269
    }
270
271
    /**
272
     * Check the validity of the invitiation code
273
     * 
274
     * @param string $code
275
     * @param string $email
276
     */
277
    public function check($code, $email=null)
278
    {
279
        $invite = Invite::whereCode($code)->first();
280
281
        if(!$invite)
282
            throw new InvalidInvitationCodeException;
283
        
284
        if($invite->valid_from > now())
285
            throw new InvitationNotYetActiveException($invite->valid_from);
286
287
        if($invite->valid_upto && $invite->valid_upto <= now())
288
            throw new InvitationExpiredException($invite->valid_upto);
289
290
        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...
291
            throw new MaximumUseOfCodeException($invite->allowed_count);
292
293
        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...
294
            throw new InvitationNotValidWithEmailException($email, $invite->email);
295
296
        return true;
297
    }
298
299
    /**
300
     * Redeem the invitation code. Make sure the form field is validated before this calls to avoid exceptions
301
     * 
302
     * @param string $code
303
     * @param string $email (optional)
304
     * 
305
     * @return mixed
306
     */
307
308
    public function redeem($code, $email = null)
309
    {
310
        $this->check($code, $email);
311
     
312
        $this->find($code)->redeem();
313
314
        return true;
315
    }
316
317
    /**
318
     * Set a validity start date for the invitation
319
     * 
320
     * @param \Carbon\Carbon $date
321
     */
322
    public function notBefore(Carbon $date)
323
    {
324
        $this->data['valid_from'] = $date;
325
        return $this;
326
    }
327
328
}