Test Failed
Push — master ( 5196a6...aaaa1a )
by vistart
08:44
created

traits/RegistrationTrait.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 *  _   __ __ _____ _____ ___  ____  _____
5
 * | | / // // ___//_  _//   ||  __||_   _|
6
 * | |/ // /(__  )  / / / /| || |     | |
7
 * |___//_//____/  /_/ /_/ |_||_|     |_|
8
 * @link https://vistart.me/
9
 * @copyright Copyright (c) 2016 - 2017 vistart
10
 * @license https://vistart.me/license/
11
 */
12
13
namespace rhosocial\base\models\traits;
14
15
use Yii;
16
use yii\base\ModelEvent;
17
use yii\db\IntegrityException;
18
use yii\rbac\ManagerInterface;
19
use yii\rbac\Role;
20
21
/**
22
 * User features concerning registration.
23
 *
24
 * @property-read mixed $authManager
25
 * @property mixed $source
26
 * @property array $sourceRules rules associated with source attribute.
27
 * @version 1.0
28
 * @author vistart <[email protected]>
29
 */
30
trait RegistrationTrait
31
{
32
33
    /**
34
     * @event Event an event that is triggered after user is registered successfully.
35
     */
36
    public static $eventAfterRegister = "afterRegister";
37
38
    /**
39
     * @event Event an event that is triggered before registration.
40
     */
41
    public static $eventBeforeRegister = "beforeRegister";
42
43
    /**
44
     * @event Event an event that is triggered when registration failed.
45
     */
46
    public static $eventRegisterFailed = "registerFailed";
47
48
    /**
49
     * @event Event an event that is triggered after user is deregistered successfully.
50
     */
51
    public static $eventAfterDeregister = "afterDeregister";
52
53
    /**
54
     * @event Event an event that is triggered before deregistration.
55
     */
56
    public static $eventBeforeDeregister = "beforeDeregister";
57
58
    /**
59
     * @event Event an event that is triggered when deregistration failed.
60
     */
61
    public static $eventDeregisterFailed = "deregisterFailed";
62
63
    /**
64
     * @var string name of attribute which store the source. if you don't want to
65
     * record source, please assign false.
66
     */
67
    public $sourceAttribute = 'source';
68
    private $_sourceRules = [];
69
    public static $sourceSelf = '0';
70
71
    /**
72
     * @var string auth manager component id.
73
     */
74
    public $authManagerId = 'authManager';
75
76
    /**
77
     * Get auth manager. If auth manager not configured, Yii::$app->authManager
78
     * will be given.
79
     * @return ManagerInterface
80
     */
81 277
    public function getAuthManager()
82
    {
83 277
        $authManagerId = $this->authManagerId;
84 277
        return empty($authManagerId) ? Yii::$app->authManager : Yii::$app->$authManagerId;
85
    }
86
87
    /**
88
     * Register new user.
89
     * It is equivalent to store the current user and its associated models into
90
     * database synchronously. The registration will be terminated immediately
91
     * if any errors occur in the process, and all the earlier steps succeeded
92
     * are rolled back.
93
     * If auth manager configured, and auth role(s) provided, it(they) will be
94
     * assigned to user after registration.
95
     * If current user is not a new one(isNewRecord = false), the registration
96
     * will be skipped and return false.
97
     * The $eventBeforeRegister will be triggered before registration starts.
98
     * If registration finished, the $eventAfterRegister will be triggered. or
99
     * $eventRegisterFailed will be triggered when any errors occured.
100
     * @param array $associatedModels The models associated with user to be stored synchronously.
101
     * @param string|array $authRoles auth name, auth instance, auth name array or auth instance array.
102
     * @return boolean Whether the registration succeeds or not.
103
     * @throws IntegrityException when inserting user and associated models failed.
104
     */
105 278
    public function register($associatedModels = [], $authRoles = [])
106
    {
107 278
        if (!$this->getIsNewRecord()) {
108 3
            return false;
109
        }
110 278
        $this->trigger(static::$eventBeforeRegister);
111 278
        $transaction = $this->getDb()->beginTransaction();
112
        try {
113 278
            if (!$this->save()) {
114 1
                throw new IntegrityException('Registration Error(s) Occured: User Save Failed.', $this->getErrors());
115
            }
116 277
            if ($authManager = $this->getAuthManager() && !empty($authRoles)) {
117
                if (is_string($authRoles) || $authRoles instanceof Role || !is_array($authRoles)) {
118
                    $authRoles = [$authRoles];
119
                }
120
                foreach ($authRoles as $role) {
121
                    if (is_string($role)) {
122
                        $role = $authManager->getRole($role);
0 ignored issues
show
The method getRole cannot be called on $authManager (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
123
                    }
124
                    if ($role instanceof Role) {
125
                        $authManager->assign($role, $this->getGUID());
0 ignored issues
show
The method assign cannot be called on $authManager (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
126
                    }
127
                }
128
            }
129 277
            if (!empty($associatedModels) && is_array($associatedModels)) {
130 131
                foreach ($associatedModels as $model) {
131 131
                    if (!$model->save()) {
132
                        throw new IntegrityException
133 131
                        ('Registration Error(s) Occured: Associated Models Save Failed.', $model->getErrors());
134
                    }
135
                }
136
            }
137 277
            $transaction->commit();
138 1
        } catch (\Exception $ex) {
139 1
            $transaction->rollBack();
140 1
            $this->trigger(static::$eventRegisterFailed);
141 1
            if (YII_DEBUG || YII_ENV !== YII_ENV_PROD) {
142 1
                Yii::error($ex->getMessage(), static::class . '\register');
143 1
                return $ex;
144
            }
145
            Yii::warning($ex->getMessage(), static::class . '\register');
146
            return false;
147
        }
148 277
        $this->trigger(static::$eventAfterRegister);
149 277
        return true;
150
    }
151
152
    /**
153
     * Deregister current user itself.
154
     * It is equivalent to delete current user and its associated models. BUT it
155
     * deletes current user ONLY, the associated models will not be deleted
156
     * forwardly. So you should set the foreign key of associated models' table
157
     * referenced from primary key of user table, and their association mode is
158
     * 'on update cascade' and 'on delete cascade'.
159
     * the $eventBeforeDeregister will be triggered before deregistration starts.
160
     * if deregistration finished, the $eventAfterDeregister will be triggered. or
161
     * $eventDeregisterFailed will be triggered when any errors occured.
162
     * @return boolean Whether deregistration succeeds or not.
163
     * @throws IntegrityException when deleting user failed.
164
     */
165 300
    public function deregister()
166
    {
167 300
        if ($this->getIsNewRecord()) {
168 253
            return false;
169
        }
170 278
        $this->trigger(static::$eventBeforeDeregister);
171 278
        $transaction = $this->getDb()->beginTransaction();
172
        try {
173 278
            $result = $this->delete();
174 278
            if ($result == 0) {
175
                throw new IntegrityException('User has not existed.');
176
            }
177 278
            if ($result != 1) {
178
                throw new IntegrityException('Deregistration Error(s) Occured.', $this->getErrors());
179
            }
180 278
            $transaction->commit();
181
        } catch (\Exception $ex) {
182
            $transaction->rollBack();
183
            $this->trigger(static::$eventDeregisterFailed);
184
            if (YII_DEBUG || YII_ENV !== YII_ENV_PROD) {
185
                Yii::error($ex->getMessage(), static::class . '\deregister');
186
                return $ex;
187
            }
188
            Yii::warning($ex->getMessage(), static::class . '\deregister');
189
            return false;
190
        }
191 278
        $this->trigger(static::$eventAfterDeregister);
192 278
        return $result == 1;
193
    }
194
195
    /**
196
     * Get source.
197
     * @return string
198
     */
199 1
    public function getSource()
200
    {
201 1
        $sourceAttribute = $this->sourceAttribute;
202 1
        return is_string($sourceAttribute) ? $this->$sourceAttribute : null;
203
    }
204
205
    /**
206
     * Set source.
207
     * @param string $source
208
     */
209 2
    public function setSource($source)
210
    {
211 2
        $sourceAttribute = $this->sourceAttribute;
212 2
        return is_string($sourceAttribute) ? $this->$sourceAttribute = $source : null;
213
    }
214
215
    /**
216
     * Get the rules associated with source attribute.
217
     * @return array rules.
218
     */
219 288
    public function getSourceRules()
220
    {
221 288
        if (empty($this->_sourceRules)) {
222 287
            $this->_sourceRules = [
223 287
                [[$this->sourceAttribute], 'required'],
224 287
                [[$this->sourceAttribute], 'string'],
225
            ];
226
        }
227 288
        return $this->_sourceRules;
228
    }
229
230
    /**
231
     * Set the rules associated with source attribute.
232
     * @param array $rules
233
     */
234 1
    public function setSourceRules($rules)
235
    {
236 1
        if (!empty($rules) && is_array($rules)) {
237 1
            $this->_sourceRules = $rules;
238
        }
239 1
    }
240
241
    /**
242
     * Initialize the source attribute with $sourceSelf.
243
     * This method is ONLY used for being triggered by event. DO NOT call,
244
     * override or modify it directly, unless you know the consequences.
245
     * @param ModelEvent $event
246
     */
247 300
    public function onInitSourceAttribute($event)
248
    {
249 300
        $sender = $event->sender;
250 300
        $sourceAttribute = $sender->sourceAttribute;
251 300
        $sender->$sourceAttribute = static::$sourceSelf;
252 300
    }
253
}
254