Completed
Push — master ( 769bd7...1d1fd8 )
by vistart
05:06
created

UserTrait   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Test Coverage

Coverage 36.51%

Importance

Changes 0
Metric Value
wmc 27
lcom 2
cbo 3
dl 0
loc 178
ccs 23
cts 63
cp 0.3651
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
B create() 0 15 5
B findOneOrCreate() 0 15 5
A removeSelf() 0 4 1
A rules() 0 12 1
A getSubsidiaryInstanceMax() 0 7 4
B createSubsidiary() 0 19 7
A __call() 0 9 4
1
<?php
2
3
/**
4
 *  _   __ __ _____ _____ ___  ____  _____
5
 * | | / // // ___//_  _//   ||  __||_   _|
6
 * | |/ // /(__  )  / / / /| || |     | |
7
 * |___//_//____/  /_/ /_/ |_||_|     |_|
8
 * @link https://vistart.me/
9
 * @copyright Copyright (c) 2016 vistart
10
 * @license https://vistart.me/license/
11
 */
12
13
namespace rhosocial\base\models\traits;
14
15
/**
16
 * Assemble PasswordTrait, RegistrationTrait and IdentityTrait into UserTrait.
17
 * This trait can only be used in the class extended from [[BaseEntityModel]],
18
 * [[BaseMongoEntityModel]], [[BaseRedisEntityModel]], or any other classes used
19
 * [[EntityTrait]].
20
 * This trait implements two methods `create()` and `findOneOrCreate()`.
21
 * Please read the notes of methods and used traits for further detailed usage.
22
 *
23
 * @version 1.0
24
 * @author vistart <[email protected]>
25
 */
26
trait UserTrait
27
{
28
    use PasswordTrait,
29
        RegistrationTrait,
30
        IdentityTrait;
31
32
    /**
33
     * Create new entity model associated with current user. The model to be created
34
     * must be extended from [[BaseBlameableModel]], [[BaseMongoBlameableModel]],
35
     * [[BaseRedisBlameableModel]], or any other classes used [[BlameableTrait]].
36
     * if $config does not specify `userClass` property, self will be assigned to.
37
     * @param string $className Full qualified class name.
38
     * @param array $config name-value pairs that will be used to initialize
39
     * the object properties.
40
     * @param boolean $loadDefault Determines whether loading default values
41
     * after entity model created.
42
     * Notice! The [[\yii\mongodb\ActiveRecord]] and [[\yii\redis\ActiveRecord]]
43
     * does not support loading default value. If you want to assign properties
44
     * with default values, please define the `default` rule(s) for properties in
45
     * `rules()` method and return them by yourself if you don't specified them in config param.
46
     * @param boolean $skipIfSet whether existing value should be preserved.
47
     * This will only set defaults for attributes that are `null`.
48
     * @return [[$className]] new model created with specified configuration.
0 ignored issues
show
Documentation introduced by
The doc-type [[$className]] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
49
     */
50 3
    public function create($className, $config = [], $loadDefault = true, $skipIfSet = true)
51
    {
52 3
        if (!isset($config['userClass'])) {
53 3
            $config['userClass'] = static::class;
54 3
        }
55 3
        if (isset($config['class'])) {
56
            unset($config['class']);
57
        }
58 3
        $entity = new $className($config);
59 3
        $entity->setUser($this);
60 3
        if ($loadDefault && method_exists($entity, 'loadDefaultValues')) {
61 3
            $entity->loadDefaultValues($skipIfSet);
62 3
        }
63 3
        return $entity;
64
    }
65
66
    /**
67
     * Find existed, or create new model.
68
     * If model to be found doesn't exist, and $config is null, the parameter
69
     * `$condition` will be regarded as properties of new model.
70
     * If you want to know whether the returned model is new model, please check
71
     * the return value of `getIsNewRecord()` method.
72
     * @param string $className Full qualified class name.
73
     * @param array $condition Search condition, or properties if not found and
74
     * $config is null.
75
     * @param array $config new model's configuration array. If you specify this
76
     * parameter, the $condition will be skipped when created one.
77
     * @return [[$className]] the existed model, or new model created by specified
0 ignored issues
show
Documentation introduced by
The doc-type [[$className]] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
78
     * condition or configuration.
79
     */
80
    public function findOneOrCreate($className, $condition = [], $config = null)
81
    {
82
        $entity = new $className(['skipInit' => true]);
83
        if (!isset($condition[$entity->createdByAttribute])) {
84
            $condition[$entity->createdByAttribute] = $this->guid;
0 ignored issues
show
Bug introduced by
The property guid does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
85
        }
86
        $model = $className::findOne($condition);
87
        if (!$model) {
88
            if ($config === null || !is_array($config)) {
89
                $config = $condition;
90
            }
91
            $model = $this->create($className, $config);
92
        }
93
        return $model;
94
    }
95
    
96
    /**
97
     * This method is only used for overriding [[removeSelf()]] in [[TimestampTrait]].
98
     * @see deregister()
99
     * @return boolean
100
     */
101 3
    public function removeSelf()
102
    {
103 3
        return $this->deregister();
104
    }
105
106
    /**
107
     * Get all rules with current user properties.
108
     * @return array all rules.
109
     */
110 82
    public function rules()
111
    {
112 82
        return array_merge(
113 82
            parent::rules(),
114 82
            $this->getPasswordHashRules(),
115 82
            $this->getPasswordResetTokenRules(),
116 82
            $this->getSourceRules(),
117 82
            $this->getStatusRules(),
118 82
            $this->getAuthKeyRules(),
119 82
            $this->getAccessTokenRules()
120 82
        );
121
    }
122
    
123
    /**
124
     * @var string[] Subsidiary map.
125
     * Array key represents class alias,
126
     * array value represents the full qualified class name corresponds to the alias.
127
     *
128
     * For example:
129
     * ```php
130
     * public $subsidiaryMap = [
131
     *     'Profile' => 'app\models\user\Profile',
132
     * ];
133
     * ```
134
     * or:
135
     * ```php
136
     * public $subsidiaryMap = [
137
     *     'Profile' => [
138
     *         'class' => 'app\models\user\Profile',
139
     *         'max' => 1,
140
     *     ]
141
     * ];
142
     *
143
     * If you want to create subsidiary model and the class is not found, the array elements will be taken.
144
     * @see normalizeSubsidiaryClass
145
     */
146
    public $subsidiaryMap = [];
147
    
148
    /**
149
     *
150
     * @param string $class
151
     * @return integer|null
152
     */
153
    public function getSubsidiaryInstanceMax($class)
154
    {
155
        if (array_key_exists($class, $this->subsidiaryMap) && class_exists($this->subsidiaryMap[$class]['class'])) {
156
            return array_key_exists('max', $this->subsidiaryMap[$class]) ? $this->subsidiaryMap[$class]['max'] : null;
157
        }
158
        return null;
159
    }
160
    
161
    /**
162
     *
163
     * @param type $class
164
     * @param type $config
165
     * @return type
166
     * @todo 区分字符串和类的实例两种情况。
167
     */
168
    public function createSubsidiary($class, $config = [])
169
    {
170
        if (!is_string($class) || empty($class)) {
171
            return null;
172
        }
173
        $className = '';
174
        if (class_exists($class)) {
175
            $className = $class;
176
        } elseif (array_key_exists($class, $this->subsidiaryMap)) {
177
            if (class_exists($this->subsidiaryMap[$class])) {
178
                $className = $this->subsidiaryMap[$class];
179
            } elseif (class_exists($this->subsidiaryMap[$class]['class'])) {
180
                $className = $this->subsidiaryMap[$class]['class'];
181
            }
182
        } else {
183
            return null;
184
        }
185
        return $this->create($className, $config);
186
    }
187
    
188
    /**
189
     *
190
     * @param string $name
191
     * @param array $params
192
     * @return type
193
     */
194
    public function __call($name, $params)
195
    {
196
        if (strpos(strtolower($name), "create") === 0) {
197
            $class = substr($name, 6);
198
            $config = (isset($params) && isset($params[0])) ? $params[0] : [];
199
            return $this->createSubsidiary($class, $config);
0 ignored issues
show
Documentation introduced by
$class is of type string, but the function expects a object<rhosocial\base\models\traits\type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
200
        }
201
        return parent::__call($name, $params);
202
    }
203
}
204