Test Failed
Pull Request — master (#54)
by Rafael
05:26
created

Users::beforeCreate()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 4
nop 0
dl 0
loc 14
ccs 7
cts 7
cp 1
crap 3
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 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\UsersAssociatedCompany',
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 76
    }
182
183
    /**
184
     * Validations and business logic
185
     */
186 6
    public function validation()
187
    {
188 6
        $validator = new Validation();
189 6
        $validator->add(
190 6
            'email',
191 6
            new Email([
192 6
                'field' => 'email',
193
                'required' => true,
194
            ])
195
        );
196
197 6
        $validator->add(
198 6
            'displayname',
199 6
            new PresenceOf([
200 6
                'field' => 'displayname',
201
                'required' => true,
202
            ])
203
        );
204
205 6
        $validator->add(
206 6
            'displayname',
207 6
            new Regex([
208 6
                'field' => 'displayname',
209 6
                'message' => _('Please use alphanumerics only.'),
210 6
                'pattern' => '/^[A-Za-z0-9_-]{1,32}$/',
211
            ])
212
        );
213
214
        // Unique values
215 6
        $validator->add(
216 6
            'email',
217 6
            new Uniqueness([
218 6
                'field' => 'email',
219 6
                'message' => _('This email already has an account.'),
220
            ])
221
        );
222
223 6
        return $this->validate($validator);
224
    }
225
226
    /**
227
     * Returns table name mapped in the model.
228
     *
229
     * @return string
230
     */
231 48
    public function getSource() : string
232
    {
233 48
        return 'users';
234
    }
235
236
    /**
237
     * Get the User key for redis
238
     *
239
     * @return string
240
     */
241
    public function getKey() : string
242
    {
243
        return $this->id;
244
    }
245
246
    /**
247
     * A company owner is the first person that register this company
248
     * This only ocurres when signing up the first time, after that all users invites
249
     * come with a default_company id attached
250
     *
251
     * @return boolean
252
     */
253 3
    public function isFirstSignup(): bool
254
    {
255 3
        return empty($this->default_company) ? true : false;
256
    }
257
258
    /**
259
     * Does the user have a role assign to him?
260
     *
261
     * @return boolean
262
     */
263 10
    public function hasRole(): bool
264
    {
265 10
        return !empty($this->roles_id) ? true : false;
266
    }
267
268
    /**
269
     * Get all of the subscriptions for the user.
270
     */
271 7
    public function subscriptions()
272
    {
273 7
        $this->hasMany(
274 7
            'id',
275 7
            'Gewaer\Models\Subscription',
276 7
            'user_id',
277
            [
278 7
                'alias' => 'subscriptions',
279
                'params' => [
280 7
                    'conditions' => 'apps_id = ?0 and companies_id = ?1',
281 7
                    'bind' => [$this->di->getApp()->getId(), $this->default_company],
282 7
                    'order' => 'id DESC'
283
                ]
284
            ]
285
        );
286
287 7
        return $this->getRelated('subscriptions');
288
    }
289
290
    /**
291
     * Strat a free trial
292
     *
293
     * @param Users $user
294
     * @return Subscription
295
     */
296
    public function startFreeTrial() : Subscription
297
    {
298
        $defaultPlan = AppsPlans::getDefaultPlan();
299
        $trialEndsAt = Carbon::now()->addDays($this->di->getApp()->plan->free_trial_dates);
300
301
        $subscription = new Subscription();
302
        $subscription->user_id = $this->getId();
303
        $subscription->companies_id = $this->default_company;
304
        $subscription->apps_id = $this->di->getApp()->getId();
305
        $subscription->apps_plans_id = $this->di->getApp()->default_apps_plan_id;
306
        $subscription->name = $defaultPlan->name;
307
        $subscription->stripe_id = $defaultPlan->stripe_id;
308
        $subscription->stripe_plan = $defaultPlan->stripe_plan;
309
        $subscription->quantity = 1;
310
        $subscription->trial_ends_at = $trialEndsAt->toDateTimeString();
311
        $subscription->trial_ends_days = $trialEndsAt->diffInDays(Carbon::now());
312
        $subscription->is_freetrial = 1;
313
        $subscription->is_active = 1;
314
315
        if (!$subscription->save()) {
316
            throw new ServerErrorHttpException((string)current($this->getMessages()));
317
        }
318
319
        $this->trial_ends_at = $subscription->trial_ends_at;
320
        $this->update();
321
322
        return $subscription;
323
    }
324
325
    /**
326
     * Before create
327
     *
328
     * @return void
329
     */
330 3
    public function beforeCreate()
331
    {
332 3
        parent::beforeCreate();
333
334
        //this is only empty when creating a new user
335 3
        if (!$this->isFirstSignup()) {
336
            //confirm if the app reach its limit
337 2
            $this->isAtLimit();
338
        }
339
340
        //Assign admin role to the system if we dont get a specify role
341 3
        if (!$this->hasRole()) {
342 1
            $role = Roles::findFirstByName('Admins');
343 1
            $this->roles_id = $role->getId();
344
        }
345 3
    }
346
347
    /**
348
     * Get an array of the associates companies Ids
349
     *
350
     * @return array
351
     */
352 6
    public function getAssociatedCompanies(): array
353
    {
354
        return array_map(function ($company) {
355 6
            return $company['companies_id'];
356 6
        }, $this->getCompanies(['columns' => 'companies_id'])->toArray());
357
    }
358
359
    /**
360
     * What the current company the users is logged in with
361
     * in this current session?
362
     *
363
     * @return integer
364
     */
365 36
    public function currentCompanyId(): int
366
    {
367 36
        return (int) $this->default_company;
368
    }
369
370
    /**
371
     * What the current company brach the users is logged in with
372
     * in this current session?
373
     *
374
     * @return integer
375
     */
376 1
    public function currentCompanyBranchId(): int
377
    {
378 1
        return (int) $this->default_company_branch;
379
    }
380
381
    /**
382
     * What to do after the creation of a new users
383
     *  - Assign default role
384
     *
385
     * @return void
386
     */
387 3
    public function afterCreate()
388
    {
389
        //need to run it here, since we overwirte the default_company id and null this function objective
390 3
        $isFirstSignup = $this->isFirstSignup();
391
392
        /**
393
         * User signing up for a new app / plan
394
         * How do we know? well he doesnt have a default_company
395
         */
396 3
        if ($isFirstSignup) {
397 1
            $company = new Companies();
398 1
            $company->name = $this->defaultCompanyName;
399 1
            $company->users_id = $this->getId();
400
401 1
            if (!$company->save()) {
402
                throw new Exception(current($company->getMessages()));
403
            }
404
405 1
            $this->default_company = $company->getId();
406
407 1
            if (!$this->update()) {
408
                throw new ServerErrorHttpException((string) current($this->getMessages()));
409
            }
410
411 1
            $this->stripe_id = $company->getPaymentGatewayCustomerId();
412 1
            $this->default_company_branch = $this->defaultCompany->branch->getId();
413 1
            $this->update();
414
415
        //update default subscription free trial
416
            //$company->app->subscriptions_id = $this->startFreeTrial()->getId();
417
            //$company->update();
418
        } else {
419
            //we have the company id
420 2
            if (empty($this->default_company_branch)) {
421
                $this->default_company_branch = $this->defaultCompany->branch->getId();
422
            }
423
        }
424
425
        //Create new company associated company
426 3
        $newUserAssocCompany = new UsersAssociatedCompany();
427 3
        $newUserAssocCompany->users_id = $this->id;
428 3
        $newUserAssocCompany->companies_id = $this->default_company;
429 3
        $newUserAssocCompany->identify_id = 1;
430 3
        $newUserAssocCompany->user_active = 1;
431 3
        $newUserAssocCompany->user_role = $this->roles_id;
432
433 3
        if (!$newUserAssocCompany->save()) {
434
            throw new ServerErrorHttpException((string)current($newUserAssocCompany->getMessages()));
435
        }
436
437
        //Insert record into user_roles
438 3
        $userRole = new UserRoles();
439 3
        $userRole->users_id = $this->id;
440 3
        $userRole->roles_id = $this->roles_id;
441 3
        $userRole->apps_id = $this->di->getApp()->getId();
442 3
        $userRole->companies_id = $this->default_company;
443
444 3
        if (!$userRole->save()) {
445
            throw new ServerErrorHttpException((string)current($userRole->getMessages()));
446
        }
447
448
        //update user activity when its not a empty user
449 3
        if (!$isFirstSignup) {
450 2
            $this->updateAppActivityLimit();
451
        }
452 3
    }
453
}
454