Passed
Pull Request — master (#55)
by Rafael
07:07
created

Users   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 433
Duplicated Lines 0 %

Test Coverage

Coverage 84%

Importance

Changes 0
Metric Value
eloc 179
dl 0
loc 433
ccs 147
cts 175
cp 0.84
rs 10
c 0
b 0
f 0
wmc 25

13 Methods

Rating   Name   Duplication   Size   Complexity  
B initialize() 0 96 1
A beforeCreate() 0 14 3
A currentCompanyBranchId() 0 3 1
A getKey() 0 3 1
A currentCompanyId() 0 3 1
A isFirstSignup() 0 3 2
A getAssociatedCompanies() 0 5 1
A validation() 0 38 1
A subscriptions() 0 17 1
B afterCreate() 0 64 8
A startFreeTrial() 0 27 2
A hasRole() 0 3 2
A getSource() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Gewaer\Models;
5
6
use Gewaer\Traits\PermissionsTrait;
7
use Gewaer\Traits\SubscriptionPlanLimitTrait;
8
use Phalcon\Cashier\Billable;
9
use Gewaer\Exception\ServerErrorHttpException;
10
use Exception;
11
use Carbon\Carbon;
12
use Phalcon\Validation;
13
use Phalcon\Validation\Validator\Email;
14
use Phalcon\Validation\Validator\PresenceOf;
15
use Phalcon\Validation\Validator\Regex;
16
use Phalcon\Validation\Validator\Uniqueness;
17
18
/**
19
 * Class Users
20
 *
21
 * @package Gewaer\Models
22
 *
23
 * @property Users $user
24
 * @property Config $config
25
 * @property Apps $app
26
 * @property Companies $defaultCompany
27
 * @property \Phalcon\Di $di
28
 */
29
class Users extends \Baka\Auth\Models\Users
30
{
31
    use PermissionsTrait;
32
    use Billable;
33
    use SubscriptionPlanLimitTrait;
34
35
    /**
36
     * Default Company Branch
37
     *
38
     * @var integer
39
     */
40
    public $default_company_branch;
41
42
    /**
43
     * Roles id
44
     *
45
     * @var integer
46
     */
47
    public $roles_id;
48
49
    /**
50
     * Stripe id
51
     *
52
     * @var string
53
     */
54
    public $stripe_id;
55
56
    /**
57
     * Card last four numbers
58
     *
59
     * @var integer
60
     */
61
    public $card_last_four;
62
63
    /**
64
     * Card Brand
65
     *
66
     * @var integer
67
     */
68
    public $card_brand;
69
70
    /**
71
     * Trial end date
72
     *
73
     * @var string
74
     */
75
    public $trial_ends_at;
76
77
    /**
78
     * Provide the app plan id
79
     * if the user is signing up a new company
80
     *
81
     * @var integer
82
     */
83
    public $appPlanId = null;
84
85
    /**
86
     * Active subscription id.Not an actual table field, used temporarily
87
     * @var string
88
     */
89
    public $active_subscription_id;
90
91
    /**
92
     * Initialize method for model.
93
     */
94 76
    public function initialize()
95
    {
96 76
        $this->setSource('users');
97
98
        //overwrite parent relationships
99 76
        $this->hasOne('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'session']);
100 76
        $this->hasMany('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'sessions']);
101 76
        $this->hasMany('id', 'Baka\Auth\Models\SessionKeys', 'users_id', ['alias' => 'sessionKeys']);
102 76
        $this->hasMany('id', 'Baka\Auth\Models\Banlist', 'users_id', ['alias' => 'bans']);
103 76
        $this->hasMany('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'sessions']);
104 76
        $this->hasMany('id', 'Gewaer\Models\UserConfig', 'users_id', ['alias' => 'config']);
105 76
        $this->hasMany('id', 'Gewaer\Models\UserLinkedSources', 'users_id', ['alias' => 'sources']);
106 76
        $this->hasMany('id', 'Baka\Auth\Models\UsersAssociatedCompany', 'users_id', ['alias' => 'companies']);
107 76
        $this->hasOne('default_company', 'Gewaer\Models\Companies', 'id', ['alias' => 'defaultCompany']);
108 76
        $this->hasOne('default_company', 'Gewaer\Models\Companies', 'id', ['alias' => 'currentCompany']);
109
110 76
        $this->hasOne(
111 76
            'id',
112 76
            'Gewaer\Models\UserRoles',
113 76
            'users_id',
114 76
            ['alias' => 'permission']
115
        );
116
117 76
        $this->hasMany(
118 76
            'id',
119 76
            'Gewaer\Models\UserRoles',
120 76
            'users_id',
121 76
            ['alias' => 'permissions']
122
        );
123
124 76
        $this->hasManyToMany(
125 76
            'id',
126 76
            'Gewaer\Models\UserRoles',
127 76
            'users_id',
128 76
            'roles_id',
129 76
            'Gewaer\Models\Roles',
130 76
            'id',
131
            [
132 76
                'alias' => 'roles',
133
                'params' => [
134 76
                    'limit' => 1,
135 76
                    'conditions' => 'Gewaer\Models\UserRoles.apps_id = ' . $this->di->getConfig()->app->id,
136
                ]
137
            ]
138
        );
139
140 76
        $this->hasMany(
141 76
            'id',
142 76
            'Gewaer\Models\Subscription',
143 76
            'user_id',
144
            [
145 76
                'alias' => 'allSubscriptions',
146
                'params' => [
147 76
                    'conditions' => 'apps_id = ?0',
148 76
                    'bind' => [$this->di->getApp()->getId()],
149 76
                    'order' => 'id DESC'
150
                ]
151
            ]
152
        );
153
154 76
        $this->hasMany(
155 76
            'id',
156 76
            'Gewaer\Models\UsersAssociatedCompanies',
157 76
            'users_id',
158
            [
159 76
                'alias' => 'companies',
160
            ]
161
        );
162
163 76
        $this->hasMany(
164 76
            'id',
165 76
            'Gewaer\Models\UserWebhooks',
166 76
            'users_id',
167 76
            ['alias' => 'userWebhook']
168
        );
169
170 76
        $systemModule = SystemModules::getSystemModuleByModelName(self::class);
171 76
        $this->hasMany(
172 76
            'id',
173 76
            'Gewaer\Models\FileSystem',
174 76
            'entity_id',
175
            [
176 76
                'alias' => 'filesystem',
177 76
                'conditions' => 'system_modules_id = ?0',
178 76
                'bind' => [$systemModule->getId()]
179
            ]
180
        );
181
182 76
        $this->hasOne(
183 76
            'id',
184 76
            'Gewaer\Models\FileSystem',
185 76
            'entity_id',
186
            [
187 76
                'alias' => 'logo',
188 76
                'conditions' => "system_modules_id = ?0 and file_type in ('png','jpg','bmp','jpeg','webp')",
189 76
                'bind' => [$systemModule->getId()]
190
            ]
191
        );
192 76
    }
193
194
    /**
195
     * Validations and business logic
196
     */
197 6
    public function validation()
198
    {
199 6
        $validator = new Validation();
200 6
        $validator->add(
201 6
            'email',
202 6
            new Email([
203 6
                'field' => 'email',
204
                'required' => true,
205
            ])
206
        );
207
208 6
        $validator->add(
209 6
            'displayname',
210 6
            new PresenceOf([
211 6
                'field' => 'displayname',
212
                'required' => true,
213
            ])
214
        );
215
216 6
        $validator->add(
217 6
            'displayname',
218 6
            new Regex([
219 6
                'field' => 'displayname',
220 6
                'message' => _('Please use alphanumerics only.'),
221 6
                'pattern' => '/^[A-Za-z0-9_-]{1,32}$/',
222
            ])
223
        );
224
225
        // Unique values
226 6
        $validator->add(
227 6
            'email',
228 6
            new Uniqueness([
229 6
                'field' => 'email',
230 6
                'message' => _('This email already has an account.'),
231
            ])
232
        );
233
234 6
        return $this->validate($validator);
235
    }
236
237
    /**
238
     * Returns table name mapped in the model.
239
     *
240
     * @return string
241
     */
242 48
    public function getSource() : string
243
    {
244 48
        return 'users';
245
    }
246
247
    /**
248
     * Get the User key for redis
249
     *
250
     * @return string
251
     */
252
    public function getKey() : string
253
    {
254
        return $this->id;
255
    }
256
257
    /**
258
     * A company owner is the first person that register this company
259
     * This only ocurres when signing up the first time, after that all users invites
260
     * come with a default_company id attached
261
     *
262
     * @return boolean
263
     */
264 3
    public function isFirstSignup(): bool
265
    {
266 3
        return empty($this->default_company) ? true : false;
267
    }
268
269
    /**
270
     * Does the user have a role assign to him?
271
     *
272
     * @return boolean
273
     */
274 10
    public function hasRole(): bool
275
    {
276 10
        return !empty($this->roles_id) ? true : false;
277
    }
278
279
    /**
280
     * Get all of the subscriptions for the user.
281
     */
282 7
    public function subscriptions()
283
    {
284 7
        $this->hasMany(
285 7
            'id',
286 7
            'Gewaer\Models\Subscription',
287 7
            'user_id',
288
            [
289 7
                'alias' => 'subscriptions',
290
                'params' => [
291 7
                    'conditions' => 'apps_id = ?0 and companies_id = ?1',
292 7
                    'bind' => [$this->di->getApp()->getId(), $this->default_company],
293 7
                    'order' => 'id DESC'
294
                ]
295
            ]
296
        );
297
298 7
        return $this->getRelated('subscriptions');
299
    }
300
301
    /**
302
     * Strat a free trial
303
     *
304
     * @param Users $user
305
     * @return Subscription
306
     */
307
    public function startFreeTrial() : Subscription
308
    {
309
        $defaultPlan = AppsPlans::getDefaultPlan();
310
        $trialEndsAt = Carbon::now()->addDays($this->di->getApp()->plan->free_trial_dates);
311
312
        $subscription = new Subscription();
313
        $subscription->user_id = $this->getId();
314
        $subscription->companies_id = $this->default_company;
315
        $subscription->apps_id = $this->di->getApp()->getId();
316
        $subscription->apps_plans_id = $this->di->getApp()->default_apps_plan_id;
317
        $subscription->name = $defaultPlan->name;
318
        $subscription->stripe_id = $defaultPlan->stripe_id;
319
        $subscription->stripe_plan = $defaultPlan->stripe_plan;
320
        $subscription->quantity = 1;
321
        $subscription->trial_ends_at = $trialEndsAt->toDateTimeString();
322
        $subscription->trial_ends_days = $trialEndsAt->diffInDays(Carbon::now());
323
        $subscription->is_freetrial = 1;
324
        $subscription->is_active = 1;
325
326
        if (!$subscription->save()) {
327
            throw new ServerErrorHttpException((string)current($this->getMessages()));
328
        }
329
330
        $this->trial_ends_at = $subscription->trial_ends_at;
331
        $this->update();
332
333
        return $subscription;
334
    }
335
336
    /**
337
     * Before create
338
     *
339
     * @return void
340
     */
341 3
    public function beforeCreate()
342
    {
343 3
        parent::beforeCreate();
344
345
        //this is only empty when creating a new user
346 3
        if (!$this->isFirstSignup()) {
347
            //confirm if the app reach its limit
348 2
            $this->isAtLimit();
349
        }
350
351
        //Assign admin role to the system if we dont get a specify role
352 3
        if (!$this->hasRole()) {
353 1
            $role = Roles::findFirstByName('Admins');
354 1
            $this->roles_id = $role->getId();
355
        }
356 3
    }
357
358
    /**
359
     * Get an array of the associates companies Ids
360
     *
361
     * @return array
362
     */
363 6
    public function getAssociatedCompanies(): array
364
    {
365
        return array_map(function ($company) {
366 6
            return $company['companies_id'];
367 6
        }, $this->getCompanies(['columns' => 'companies_id'])->toArray());
368
    }
369
370
    /**
371
     * What the current company the users is logged in with
372
     * in this current session?
373
     *
374
     * @return integer
375
     */
376 38
    public function currentCompanyId(): int
377
    {
378 38
        return (int) $this->default_company;
379
    }
380
381
    /**
382
     * What the current company brach the users is logged in with
383
     * in this current session?
384
     *
385
     * @return integer
386
     */
387 1
    public function currentCompanyBranchId(): int
388
    {
389 1
        return (int) $this->default_company_branch;
390
    }
391
392
    /**
393
     * What to do after the creation of a new users
394
     *  - Assign default role
395
     *
396
     * @return void
397
     */
398 3
    public function afterCreate()
399
    {
400
        //need to run it here, since we overwirte the default_company id and null this function objective
401 3
        $isFirstSignup = $this->isFirstSignup();
402
403
        /**
404
         * User signing up for a new app / plan
405
         * How do we know? well he doesnt have a default_company
406
         */
407 3
        if ($isFirstSignup) {
408 1
            $company = new Companies();
409 1
            $company->name = $this->defaultCompanyName;
410 1
            $company->users_id = $this->getId();
411
412 1
            if (!$company->save()) {
413
                throw new Exception(current($company->getMessages()));
414
            }
415
416 1
            $this->default_company = $company->getId();
417
418 1
            if (!$this->update()) {
419
                throw new ServerErrorHttpException((string) current($this->getMessages()));
420
            }
421
422 1
            $this->stripe_id = $company->getPaymentGatewayCustomerId();
423 1
            $this->default_company_branch = $this->defaultCompany->branch->getId();
424 1
            $this->update();
425
426
            //update default subscription free trial
427
            //$company->app->subscriptions_id = $this->startFreeTrial()->getId();
428
            //$company->update();
429
        } else {
430
            //we have the company id
431 2
            if (empty($this->default_company_branch)) {
432
                $this->default_company_branch = $this->defaultCompany->branch->getId();
433
            }
434
        }
435
436
        //Create new company associated company
437 3
        $newUserAssocCompany = new UsersAssociatedCompanies();
438 3
        $newUserAssocCompany->users_id = $this->id;
439 3
        $newUserAssocCompany->companies_id = $this->default_company;
440 3
        $newUserAssocCompany->identify_id = 1;
441 3
        $newUserAssocCompany->user_active = 1;
442 3
        $newUserAssocCompany->user_role = $this->roles_id;
443
444 3
        if (!$newUserAssocCompany->save()) {
445
            throw new ServerErrorHttpException((string)current($newUserAssocCompany->getMessages()));
446
        }
447
448
        //Insert record into user_roles
449 3
        $userRole = new UserRoles();
450 3
        $userRole->users_id = $this->id;
451 3
        $userRole->roles_id = $this->roles_id;
452 3
        $userRole->apps_id = $this->di->getApp()->getId();
453 3
        $userRole->companies_id = $this->default_company;
454
455 3
        if (!$userRole->save()) {
456
            throw new ServerErrorHttpException((string)current($userRole->getMessages()));
457
        }
458
459
        //update user activity when its not a empty user
460 3
        if (!$isFirstSignup) {
461 2
            $this->updateAppActivityLimit();
462
        }
463 3
    }
464
}
465