Failed Conditions
Pull Request — master (#48)
by Rafael
05:06
created

Users::startFreeTrial()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 2.0004

Importance

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