Passed
Pull Request — master (#35)
by Rafael
04:12
created

Users   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 364
Duplicated Lines 0 %

Test Coverage

Coverage 94.9%

Importance

Changes 0
Metric Value
eloc 160
dl 0
loc 364
ccs 149
cts 157
cp 0.949
rs 10
c 0
b 0
f 0
wmc 26

13 Methods

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