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

Users::validation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 1

Importance

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