Test Failed
Pull Request — master (#46)
by Rafael
06:09
created

Users::beforeCreate()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 4
nop 0
dl 0
loc 14
ccs 6
cts 7
cp 0.8571
crap 3.0261
rs 10
c 0
b 0
f 0
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 integer
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
     * Initialize method for model.
87
     */
88 69
    public function initialize()
89
    {
90 69
        $this->setSource('users');
91
92
        //overwrite parent relationships
93 69
        $this->hasOne('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'session']);
94 69
        $this->hasMany('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'sessions']);
95 69
        $this->hasMany('id', 'Baka\Auth\Models\SessionKeys', 'users_id', ['alias' => 'sessionKeys']);
96 69
        $this->hasMany('id', 'Baka\Auth\Models\Banlist', 'users_id', ['alias' => 'bans']);
97 69
        $this->hasMany('id', 'Baka\Auth\Models\Sessions', 'users_id', ['alias' => 'sessions']);
98 69
        $this->hasMany('id', 'Gewaer\Models\UserConfig', 'users_id', ['alias' => 'config']);
99 69
        $this->hasMany('id', 'Gewaer\Models\UserLinkedSources', 'users_id', ['alias' => 'sources']);
100 69
        $this->hasMany('id', 'Baka\Auth\Models\UsersAssociatedCompany', 'users_id', ['alias' => 'companies']);
101 69
        $this->hasOne('default_company', 'Gewaer\Models\Companies', 'id', ['alias' => 'defaultCompany']);
102 69
        $this->hasOne('default_company', 'Gewaer\Models\Companies', 'id', ['alias' => 'currentCompany']);
103
104 69
        $this->hasOne(
105 69
            'id',
106 69
            'Gewaer\Models\UserRoles',
107 69
            'users_id',
108 69
            ['alias' => 'permission']
109
        );
110
111 69
        $this->hasMany(
112 69
            'id',
113 69
            'Gewaer\Models\UserRoles',
114 69
            'users_id',
115 69
            ['alias' => 'permissions']
116
        );
117
118 69
        $this->hasManyToMany(
119 69
            'id',
120 69
            'Gewaer\Models\UserRoles',
121 69
            'users_id',
122 69
            'roles_id',
123 69
            'Gewaer\Models\Roles',
124 69
            'id',
125
            [
126 69
                'alias' => 'roles',
127
                'params' => [
128 69
                    'limit' => 1,
129 69
                    'conditions' => 'Gewaer\Models\UserRoles.apps_id = ' . $this->di->getConfig()->app->id,
130
                ]
131
            ]
132
        );
133
134 69
        $this->hasMany(
135 69
            'id',
136 69
            'Gewaer\Models\Subscription',
137 69
            'user_id',
138
            [
139 69
                'alias' => 'allSubscriptions',
140
                'params' => [
141 69
                    'conditions' => 'apps_id = ?0',
142 69
                    'bind' => [$this->di->getApp()->getId()],
143 69
                    'order' => 'id DESC'
144
                ]
145
            ]
146
        );
147
148 69
        $this->hasMany(
149 69
            'id',
150 69
            'Gewaer\Models\UsersAssociatedCompany',
151 69
            'users_id',
152
            [
153 69
                'alias' => 'companies',
154
            ]
155
        );
156
157 69
        $this->hasMany(
158 69
            'id',
159 69
            'Gewaer\Models\UserWebhooks',
160 69
            'users_id',
161 69
            ['alias' => 'userWebhook']
162
        );
163
164 69
        $systemModule = SystemModules::getSystemModuleByModelName(self::class);
165 69
        $this->hasMany(
166 69
            'id',
167 69
            'Gewaer\Models\FileSystem',
168 69
            'entity_id',
169
            [
170 69
                'alias' => 'filesystem',
171 69
                'conditions' => 'system_modules_id = ?0',
172 69
                'bind' => [$systemModule->getId()]
173
            ]
174
        );
175 69
    }
176
177
    /**
178
     * Validations and business logic
179
     */
180 1
    public function validation()
181
    {
182 1
        $validator = new Validation();
183 1
        $validator->add(
184 1
            'email',
185 1
            new Email([
186 1
                'field' => 'email',
187
                'required' => true,
188
            ])
189
        );
190
191 1
        $validator->add(
192 1
            'displayname',
193 1
            new PresenceOf([
194 1
                'field' => 'displayname',
195
                'required' => true,
196
            ])
197
        );
198
199 1
        $validator->add(
200 1
            'displayname',
201 1
            new Regex([
202 1
                'field' => 'displayname',
203 1
                'message' => _('Please use alphanumerics only.'),
204 1
                'pattern' => '/^[A-Za-z0-9_-]{1,32}$/',
205
            ])
206
        );
207
208
        // Unique values
209 1
        $validator->add(
210 1
            'email',
211 1
            new Uniqueness([
212 1
                'field' => 'email',
213 1
                'message' => _('This email already has an account.'),
214
            ])
215
        );
216
217 1
        return $this->validate($validator);
218
    }
219
220
    /**
221
     * Returns table name mapped in the model.
222
     *
223
     * @return string
224
     */
225 9
    public function getSource() : string
226
    {
227 9
        return 'users';
228
    }
229
230
    /**
231
     * Get the User key for redis
232
     *
233
     * @return string
234
     */
235
    public function getKey() : string
236
    {
237
        return $this->id;
238
    }
239
240
    /**
241
     * A company owner is the first person that register this company
242
     * This only ocurres when signing up the first time, after that all users invites
243
     * come with a default_company id attached
244
     *
245
     * @return boolean
246
     */
247 1
    public function isFirstSignup(): bool
248
    {
249 1
        return empty($this->default_company) ? true : false;
250
    }
251
252
    /**
253
     * Does the user have a role assign to him?
254
     *
255
     * @return boolean
256
     */
257 1
    public function hasRole(): bool
258
    {
259 1
        return !empty($this->roles_id) ? true : false;
260
    }
261
262
    /**
263
     * Get all of the subscriptions for the user.
264
     */
265
    public function subscriptions()
266
    {
267
        $this->hasMany(
268
            'id',
269
            'Gewaer\Models\Subscription',
270
            'user_id',
271
            [
272
                'alias' => 'subscriptions',
273
                'params' => [
274
                    'conditions' => 'apps_id = ?0 and companies_id = ?1',
275
                    'bind' => [$this->di->getApp()->getId(), $this->default_company],
276
                    'order' => 'id DESC'
277
                ]
278
            ]
279
        );
280
281
        return $this->getRelated('subscriptions');
282
    }
283
284
    /**
285
     * Strat a free trial
286
     *
287
     * @param Users $user
288
     * @return Subscription
289
     */
290
    public function startFreeTrial() : Subscription
291
    {
292
        $defaultPlan = AppsPlans::getDefaultPlan();
293
294
        $subscription = new Subscription();
295
        $subscription->user_id = $this->getId();
296
        $subscription->companies_id = $this->default_company;
297
        $subscription->apps_id = $this->di->getApp()->getId();
298
        $subscription->apps_plans_id = $this->di->getApp()->default_apps_plan_id;
299
        $subscription->name = $defaultPlan->name;
300
        $subscription->stripe_id = $defaultPlan->stripe_id;
301
        $subscription->stripe_plan = $defaultPlan->stripe_plan;
302
        $subscription->quantity = 1;
303
        $subscription->trial_ends_at = Carbon::now()->addDays($this->di->getApp()->plan->free_trial_dates)->toDateTimeString();
304
305
        if (!$subscription->save()) {
306
            throw new ServerErrorHttpException((string)current($this->getMessages()));
307
        }
308
309
        $this->trial_ends_at = $subscription->trial_ends_at;
310
        $this->update();
311
312
        return $subscription;
313
    }
314
315
    /**
316
     * Before create
317
     *
318
     * @return void
319
     */
320 1
    public function beforeCreate()
321
    {
322 1
        parent::beforeCreate();
323
324
        //this is only empty when creating a new user
325 1
        if (!$this->isFirstSignup()) {
326
            //confirm if the app reach its limit
327
            $this->isAtLimit();
328
        }
329
330
        //Assign admin role to the system if we dont get a specify role
331 1
        if (!$this->hasRole()) {
332 1
            $role = Roles::findFirstByName('Admins');
333 1
            $this->roles_id = $role->getId();
334
        }
335 1
    }
336
337
    /**
338
     * Get an array of the associates companies Ids
339
     *
340
     * @return array
341
     */
342
    public function getAssociatedCompanies(): array
343
    {
344
        return array_map(function ($company) {
345
            return $company['companies_id'];
346
        }, $this->getCompanies(['columns' => 'companies_id'])->toArray());
347
    }
348
349
    /**
350
     * What the current company the users is logged in with
351
     * in this current session?
352
     *
353
     * @return integer
354
     */
355
    public function currentCompanyId(): int
356
    {
357
        return (int) $this->default_company;
358
    }
359
360
    /**
361
     * What the current company brach the users is logged in with
362
     * in this current session?
363
     *
364
     * @return integer
365
     */
366
    public function currentCompanyBranchId(): int
367
    {
368
        return (int) $this->default_company_branch;
369
    }
370
371
    /**
372
     * What to do after the creation of a new users
373
     *  - Assign default role
374
     *
375
     * @return void
376
     */
377 1
    public function afterCreate()
378
    {
379
        //need to run it here, since we overwirte the default_company id and null this function objective
380 1
        $isFirstSignup = $this->isFirstSignup();
381
382
        /**
383
         * User signing up for a new app / plan
384
         * How do we know? well he doesnt have a default_company
385
         */
386 1
        if ($isFirstSignup) {
387 1
            $company = new Companies();
388 1
            $company->name = $this->defaultCompanyName;
389 1
            $company->users_id = $this->getId();
390
391 1
            if (!$company->save()) {
392 1
                throw new Exception(current($company->getMessages()));
393
            }
394
395
            $this->default_company = $company->getId();
396
397
            if (!$this->update()) {
398
                throw new ServerErrorHttpException((string) current($this->getMessages()));
399
            }
400
401
            $this->default_company_branch = $this->defaultCompany->branch->getId();
402
            $this->update();
403
404
            //update default subscription free trial
405
            $company->app->subscriptions_id = $this->startFreeTrial()->getId();
406
            $company->update();
407
        } else {
408
            //we have the company id
409
            if (empty($this->default_company_branch)) {
410
                $this->default_company_branch = $this->defaultCompany->branch->getId();
411
            }
412
        }
413
414
        //Create new company associated company
415
        $newUserAssocCompany = new UsersAssociatedCompany();
416
        $newUserAssocCompany->users_id = $this->id;
417
        $newUserAssocCompany->companies_id = $this->default_company;
418
        $newUserAssocCompany->identify_id = 1;
419
        $newUserAssocCompany->user_active = 1;
420
        $newUserAssocCompany->user_role = $this->roles_id == 1 ? 'admins' : 'users';
421
422
        if (!$newUserAssocCompany->save()) {
423
            throw new ServerErrorHttpException((string)current($newUserAssocCompany->getMessages()));
424
        }
425
426
        //Insert record into user_roles
427
        $userRole = new UserRoles();
428
        $userRole->users_id = $this->id;
429
        $userRole->roles_id = $this->roles_id;
430
        $userRole->apps_id = $this->di->getApp()->getId();
431
        $userRole->companies_id = $this->default_company;
432
433
        if (!$userRole->save()) {
434
            throw new ServerErrorHttpException((string)current($userRole->getMessages()));
435
        }
436
437
        //update user activity when its not a empty user
438
        if (!$isFirstSignup) {
439
            $this->updateAppActivityLimit();
440
        }
441
    }
442
}
443