This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 rhosocial\base\helpers\Number; |
||
16 | use rhosocial\base\models\queries\BaseUserQuery; |
||
17 | use yii\base\InvalidParamException; |
||
18 | use yii\base\ModelEvent; |
||
19 | use yii\base\NotSupportedException; |
||
20 | use yii\behaviors\BlameableBehavior; |
||
21 | use yii\caching\TagDependency; |
||
22 | use yii\data\Pagination; |
||
23 | |||
24 | /** |
||
25 | * This trait is used for building blameable model. It contains following features: |
||
26 | * 1.Single-column(field) content; |
||
27 | * 2.Content type; |
||
28 | * 3.Content rules(generated automatically); |
||
29 | * 4.Creator(owner)'s GUID; |
||
30 | * 5.Updater's GUID; |
||
31 | * 6.Confirmation features, provided by [[ConfirmationTrait]]; |
||
32 | * 7.Self referenced features, provided by [[SelfBlameableTrait]]; |
||
33 | * @property-read array $blameableAttributeRules Get all rules associated with |
||
34 | * blameable. |
||
35 | * @property array $blameableRules Get or set all the rules associated with |
||
36 | * creator, updater, content and its ID, as well as all the inherited rules. |
||
37 | * @property array $blameableBehaviors Get or set all the behaviors assoriated |
||
38 | * with creator and updater, as well as all the inherited behaviors. |
||
39 | * @property-read array $descriptionRules Get description property rules. |
||
40 | * @property-read mixed $content Content. |
||
41 | * @property-read boolean $contentCanBeEdited Whether this content could be edited. |
||
42 | * @property-read array $contentRules Get content rules. |
||
43 | * @property BserUserModel $host The owner of this model. |
||
44 | * @property BaseUserModel $user The owner of this model(the same as $host). |
||
45 | * @property BaseUserModel $updater The updater who updated this model latest. |
||
46 | * @version 1.0 |
||
47 | * @author vistart <[email protected]> |
||
48 | */ |
||
49 | trait BlameableTrait |
||
50 | { |
||
51 | use ConfirmationTrait, |
||
52 | SelfBlameableTrait; |
||
53 | |||
54 | private $blameableLocalRules = []; |
||
55 | private $blameableLocalBehaviors = []; |
||
56 | |||
57 | /** |
||
58 | * @var boolean|string|array Specify the attribute(s) name of content(s). If |
||
59 | * there is only one content attribute, you can assign its name. Or there |
||
60 | * is multiple attributes associated with contents, you can assign their |
||
61 | * names in array. If you don't want to use this feature, please assign |
||
62 | * false. |
||
63 | * For example: |
||
64 | * ```php |
||
65 | * public $contentAttribute = 'comment'; // only one field named as 'comment'. |
||
66 | * ``` |
||
67 | * or |
||
68 | * ```php |
||
69 | * public $contentAttribute = ['year', 'month', 'day']; // multiple fields. |
||
70 | * ``` |
||
71 | * or |
||
72 | * ```php |
||
73 | * public $contentAttribute = false; // no need of this feature. |
||
74 | * ``` |
||
75 | * If you don't need this feature, you should add rules corresponding with |
||
76 | * `content` in `rules()` method of your user model by yourself. |
||
77 | */ |
||
78 | public $contentAttribute = 'content'; |
||
79 | |||
80 | /** |
||
81 | * @var array built-in validator name or validatation method name and |
||
82 | * additional parameters. |
||
83 | */ |
||
84 | public $contentAttributeRule = ['string', 'max' => 255]; |
||
85 | |||
86 | /** |
||
87 | * @var boolean|string Specify the field which stores the type of content. |
||
88 | */ |
||
89 | public $contentTypeAttribute = false; |
||
90 | |||
91 | /** |
||
92 | * @var boolean|array Specify the logic type of content, not data type. If |
||
93 | * your content doesn't need this feature. please specify false. If the |
||
94 | * $contentAttribute is specified to false, this attribute will be skipped. |
||
95 | * ```php |
||
96 | * public $contentTypes = [ |
||
97 | * 'public', |
||
98 | * 'private', |
||
99 | * 'friend', |
||
100 | * ]; |
||
101 | * ``` |
||
102 | */ |
||
103 | public $contentTypes = false; |
||
104 | |||
105 | /** |
||
106 | * @var boolean|string This attribute speicfy the name of description |
||
107 | * attribute. If this attribute is assigned to false, this feature will be |
||
108 | * skipped. |
||
109 | */ |
||
110 | public $descriptionAttribute = false; |
||
111 | |||
112 | /** |
||
113 | * @var string |
||
114 | */ |
||
115 | public $initDescription = ''; |
||
116 | |||
117 | /** |
||
118 | * @var string the attribute that will receive current user ID value. This |
||
119 | * attribute must be assigned. |
||
120 | */ |
||
121 | public $createdByAttribute = "user_guid"; |
||
122 | |||
123 | /** |
||
124 | * @var string the attribute that will receive current user ID value. |
||
125 | * Set this property to false if you do not want to record the updater ID. |
||
126 | */ |
||
127 | public $updatedByAttribute = "user_guid"; |
||
128 | |||
129 | /** |
||
130 | * @var boolean Add combinated unique rule if assigned to true. |
||
131 | */ |
||
132 | public $idCreatorCombinatedUnique = true; |
||
133 | |||
134 | /** |
||
135 | * @var boolean|string The name of user class which own the current entity. |
||
136 | * If this attribute is assigned to false, this feature will be skipped, and |
||
137 | * when you use create() method of UserTrait, it will be assigned with |
||
138 | * current user class. |
||
139 | */ |
||
140 | //public $userClass; |
||
141 | |||
142 | /** |
||
143 | * @var boolean|string Host class. |
||
144 | */ |
||
145 | public $hostClass; |
||
146 | public static $cacheKeyBlameableRules = 'blameable_rules'; |
||
147 | public static $cacheTagBlameableRules = 'tag_blameable_rules'; |
||
148 | public static $cacheKeyBlameableBehaviors = 'blameable_behaviors'; |
||
149 | public static $cacheTagBlameableBehaviors = 'tag_blameable_behaviors'; |
||
150 | |||
151 | /** |
||
152 | * @inheritdoc |
||
153 | * ------------ |
||
154 | * The classical rules is like following: |
||
155 | * [ |
||
156 | * ['guid', 'required'], |
||
157 | * ['guid', 'unique'], |
||
158 | * ['guid', 'string', 'max' => 36], |
||
159 | * |
||
160 | * ['id', 'required'], |
||
161 | * ['id', 'unique'], |
||
162 | * ['id', 'string', 'max' => 4], |
||
163 | * |
||
164 | * ['created_at', 'safe'], |
||
165 | * ['updated_at', 'safe'], |
||
166 | * |
||
167 | * ['ip_type', 'in', 'range' => [4, 6]], |
||
168 | * ['ip', 'number', 'integerOnly' => true, 'min' => 0], |
||
169 | * ] |
||
170 | * @return array |
||
171 | */ |
||
172 | 199 | public function rules() |
|
173 | { |
||
174 | 199 | return $this->getBlameableRules(); |
|
175 | } |
||
176 | |||
177 | /** |
||
178 | * @inheritdoc |
||
179 | */ |
||
180 | 209 | public function behaviors() |
|
181 | { |
||
182 | 209 | return $this->getBlameableBehaviors(); |
|
183 | } |
||
184 | |||
185 | /** |
||
186 | * Get total of contents which owned by their owner. |
||
187 | * @return integer |
||
188 | */ |
||
189 | 1 | public function countOfOwner() |
|
190 | { |
||
191 | 1 | $createdByAttribute = $this->createdByAttribute; |
|
192 | 1 | return static::find()->where([$createdByAttribute => $this->$createdByAttribute])->count(); |
|
193 | } |
||
194 | |||
195 | /** |
||
196 | * Get content. |
||
197 | * @return mixed |
||
198 | */ |
||
199 | 7 | public function getContent() |
|
200 | { |
||
201 | 7 | $contentAttribute = $this->contentAttribute; |
|
202 | 7 | if ($contentAttribute === false) { |
|
203 | return null; |
||
204 | } |
||
205 | 7 | if (is_array($contentAttribute)) { |
|
206 | $content = []; |
||
207 | foreach ($contentAttribute as $key => $value) { |
||
208 | $content[$key] = $this->$value; |
||
209 | } |
||
210 | return $content; |
||
211 | } |
||
212 | 7 | return $this->$contentAttribute; |
|
213 | } |
||
214 | |||
215 | /** |
||
216 | * Set content. |
||
217 | * @param mixed $content |
||
218 | */ |
||
219 | 65 | public function setContent($content) |
|
220 | { |
||
221 | 65 | $contentAttribute = $this->contentAttribute; |
|
222 | 65 | if ($contentAttribute === false) { |
|
223 | return; |
||
224 | } |
||
225 | 65 | if (is_array($contentAttribute)) { |
|
226 | foreach ($contentAttribute as $key => $value) { |
||
227 | $this->$value = $content[$key]; |
||
228 | } |
||
229 | return; |
||
230 | } |
||
231 | 65 | $this->$contentAttribute = $content; |
|
232 | 65 | } |
|
233 | |||
234 | /** |
||
235 | * Determines whether content could be edited. Your should implement this |
||
236 | * method by yourself. |
||
237 | * @return boolean |
||
238 | * @throws NotSupportedException |
||
239 | */ |
||
240 | 1 | public function getContentCanBeEdited() |
|
241 | { |
||
242 | 1 | if ($this->contentAttribute === false) { |
|
243 | return false; |
||
244 | } |
||
245 | 1 | throw new NotSupportedException("This method is not implemented."); |
|
246 | } |
||
247 | |||
248 | /** |
||
249 | * Get blameable rules cache key. |
||
250 | * @return string cache key. |
||
251 | */ |
||
252 | 199 | public function getBlameableRulesCacheKey() |
|
253 | { |
||
254 | 199 | return static::class . $this->cachePrefix . static::$cacheKeyBlameableRules; |
|
0 ignored issues
–
show
|
|||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Get blameable rules cache tag. |
||
259 | * @return string cache tag |
||
260 | */ |
||
261 | 199 | public function getBlameableRulesCacheTag() |
|
262 | { |
||
263 | 199 | return static::class . $this->cachePrefix . static::$cacheTagBlameableRules; |
|
264 | } |
||
265 | |||
266 | /** |
||
267 | * Get the rules associated with content to be blamed. |
||
268 | * @return array rules. |
||
269 | */ |
||
270 | 199 | public function getBlameableRules() |
|
271 | { |
||
272 | 199 | $cache = $this->getCache(); |
|
0 ignored issues
–
show
It seems like
getCache() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
273 | 199 | if ($cache) { |
|
274 | 199 | $this->blameableLocalRules = $cache->get($this->getBlameableRulesCacheKey()); |
|
275 | } |
||
276 | // 若当前规则不为空,且是数组,则认为是规则数组,直接返回。 |
||
277 | 199 | if (!empty($this->blameableLocalRules) && is_array($this->blameableLocalRules)) { |
|
278 | 79 | return $this->blameableLocalRules; |
|
279 | } |
||
280 | |||
281 | // 父类规则与确认规则合并。 |
||
282 | 199 | if ($cache) { |
|
283 | 199 | TagDependency::invalidate($cache, [$this->getEntityRulesCacheTag()]); |
|
0 ignored issues
–
show
It seems like
getEntityRulesCacheTag() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
284 | } |
||
285 | 199 | $rules = array_merge( |
|
286 | 199 | parent::rules(), |
|
0 ignored issues
–
show
It seems like you call parent on a different method (
rules() instead of getBlameableRules() ). Are you sure this is correct? If so, you might want to change this to $this->rules() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
287 | 199 | $this->getConfirmationRules(), |
|
288 | 199 | $this->getBlameableAttributeRules(), |
|
289 | 199 | $this->getDescriptionRules(), |
|
290 | 199 | $this->getContentRules(), |
|
291 | 199 | $this->getSelfBlameableRules() |
|
292 | ); |
||
293 | 199 | $this->setBlameableRules($rules); |
|
294 | 199 | return $this->blameableLocalRules; |
|
295 | } |
||
296 | |||
297 | /** |
||
298 | * Get the rules associated with `createdByAttribute`, `updatedByAttribute` |
||
299 | * and `idAttribute`-`createdByAttribute` combination unique. |
||
300 | * @return array rules. |
||
301 | * @throws NotSupportedException throws if `createdByAttribute` not set. |
||
302 | */ |
||
303 | 199 | public function getBlameableAttributeRules() |
|
304 | { |
||
305 | 199 | $rules = []; |
|
306 | // 创建者和上次修改者由 BlameableBehavior 负责,因此标记为安全。 |
||
307 | 199 | if (!is_string($this->createdByAttribute) || empty($this->createdByAttribute)) { |
|
308 | throw new NotSupportedException('You must assign the creator.'); |
||
309 | } |
||
310 | 199 | if ($this->guidAttribute != $this->createdByAttribute) { |
|
0 ignored issues
–
show
The property
guidAttribute 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;
![]() |
|||
311 | 199 | $rules[] = [ |
|
312 | 199 | [$this->createdByAttribute], |
|
313 | 199 | 'safe', |
|
314 | ]; |
||
315 | } |
||
316 | |||
317 | 199 | if (is_string($this->updatedByAttribute) && $this->guidAttribute != $this->updatedByAttribute && !empty($this->updatedByAttribute)) { |
|
318 | 111 | $rules[] = [ |
|
319 | 111 | [$this->updatedByAttribute], |
|
320 | 111 | 'safe', |
|
321 | ]; |
||
322 | } |
||
323 | |||
324 | 199 | if ($this->idCreatorCombinatedUnique && is_string($this->idAttribute)) { |
|
0 ignored issues
–
show
The property
idAttribute does not seem to exist. Did you mean refIdAttribute ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
325 | 197 | $rules ['id'] = [ |
|
326 | 197 | [$this->idAttribute, |
|
0 ignored issues
–
show
The property
idAttribute does not seem to exist. Did you mean refIdAttribute ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
327 | 197 | $this->createdByAttribute], |
|
328 | 197 | 'unique', |
|
329 | 197 | 'targetAttribute' => [$this->idAttribute, |
|
0 ignored issues
–
show
The property
idAttribute does not seem to exist. Did you mean refIdAttribute ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
330 | 197 | $this->createdByAttribute], |
|
331 | ]; |
||
332 | } |
||
333 | 199 | return $rules; |
|
334 | } |
||
335 | |||
336 | 199 | public function getIdRules() |
|
337 | { |
||
338 | 199 | if (is_string($this->idAttribute) && !empty($this->idAttribute) && $this->idCreatorCombinatedUnique && $this->idAttributeType !== static::$idTypeAutoIncrement) { |
|
0 ignored issues
–
show
The property
idAttribute does not seem to exist. Did you mean refIdAttribute ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() The property
idAttributeType 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;
![]() |
|||
339 | return [ |
||
340 | 139 | [[$this->idAttribute], 'required'], |
|
0 ignored issues
–
show
The property
idAttribute does not seem to exist. Did you mean refIdAttribute ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
341 | ]; |
||
342 | } |
||
343 | 106 | return parent::getIdRules(); |
|
344 | } |
||
345 | |||
346 | /** |
||
347 | * Get the rules associated with `description` attribute. |
||
348 | * @return array rules. |
||
349 | */ |
||
350 | 199 | public function getDescriptionRules() |
|
351 | { |
||
352 | 199 | $rules = []; |
|
353 | 199 | if (is_string($this->descriptionAttribute) && !empty($this->descriptionAttribute)) { |
|
354 | 66 | $rules[] = [ |
|
355 | 66 | [$this->descriptionAttribute], |
|
356 | 66 | 'string' |
|
357 | ]; |
||
358 | 66 | $rules[] = [ |
|
359 | 66 | [$this->descriptionAttribute], |
|
360 | 66 | 'default', |
|
361 | 66 | 'value' => $this->initDescription, |
|
362 | ]; |
||
363 | } |
||
364 | 199 | return $rules; |
|
365 | } |
||
366 | |||
367 | /** |
||
368 | * Get the rules associated with `content` and `contentType` attributes. |
||
369 | * @return array rules. |
||
370 | */ |
||
371 | 199 | public function getContentRules() |
|
372 | { |
||
373 | 199 | if (!$this->contentAttribute) { |
|
374 | 46 | return []; |
|
375 | } |
||
376 | 163 | $rules = []; |
|
377 | 163 | $rules[] = [$this->contentAttribute, 'required']; |
|
378 | 163 | if ($this->contentAttributeRule) { |
|
379 | 163 | if (is_string($this->contentAttributeRule)) { |
|
380 | $this->contentAttributeRule = [$this->contentAttributeRule]; |
||
381 | } |
||
382 | 163 | if (is_array($this->contentAttributeRule)) { |
|
383 | 163 | $rules[] = array_merge([$this->contentAttribute], $this->contentAttributeRule); |
|
384 | } |
||
385 | } |
||
386 | |||
387 | 163 | if (!$this->contentTypeAttribute) { |
|
388 | 143 | return $rules; |
|
389 | } |
||
390 | |||
391 | 20 | if (is_array($this->contentTypes) && !empty($this->contentTypes)) { |
|
392 | 20 | $rules[] = [[ |
|
393 | 20 | $this->contentTypeAttribute], |
|
394 | 20 | 'required']; |
|
395 | 20 | $rules[] = [[ |
|
396 | 20 | $this->contentTypeAttribute], |
|
397 | 20 | 'in', |
|
398 | 20 | 'range' => array_keys($this->contentTypes)]; |
|
399 | } |
||
400 | 20 | return $rules; |
|
401 | } |
||
402 | |||
403 | /** |
||
404 | * Set blameable rules. |
||
405 | * @param array $rules |
||
406 | */ |
||
407 | 199 | protected function setBlameableRules($rules = []) |
|
408 | { |
||
409 | 199 | $this->blameableLocalRules = $rules; |
|
410 | 199 | $cache = $this->getCache(); |
|
0 ignored issues
–
show
It seems like
getCache() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
411 | 199 | if ($cache) { |
|
412 | 199 | $tagDependency = new TagDependency(['tags' => [$this->getBlameableRulesCacheTag()]]); |
|
413 | 199 | $cache->set($this->getBlameableRulesCacheKey(), $rules, 0, $tagDependency); |
|
414 | } |
||
415 | 199 | } |
|
416 | |||
417 | /** |
||
418 | * Get blameable behaviors cache key. |
||
419 | * @return string cache key. |
||
420 | */ |
||
421 | 209 | public function getBlameableBehaviorsCacheKey() |
|
422 | { |
||
423 | 209 | return static::class . $this->cachePrefix . static::$cacheKeyBlameableBehaviors; |
|
424 | } |
||
425 | |||
426 | /** |
||
427 | * Get blameable behaviors cache tag. |
||
428 | * @return string cache tag. |
||
429 | */ |
||
430 | 209 | public function getBlameableBehaviorsCacheTag() |
|
431 | { |
||
432 | 209 | return static::class . $this->cachePrefix . static::$cacheTagBlameableBehaviors; |
|
433 | } |
||
434 | |||
435 | /** |
||
436 | * Get blameable behaviors. If current behaviors array is empty, the init |
||
437 | * array will be given. |
||
438 | * @return array |
||
439 | */ |
||
440 | 209 | public function getBlameableBehaviors() |
|
441 | { |
||
442 | 209 | $cache = $this->getCache(); |
|
0 ignored issues
–
show
It seems like
getCache() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
443 | 209 | if ($cache) { |
|
444 | 209 | $this->blameableLocalBehaviors = $cache->get($this->getBlameableBehaviorsCacheKey()); |
|
445 | } |
||
446 | 209 | if (empty($this->blameableLocalBehaviors) || !is_array($this->blameableLocalBehaviors)) { |
|
447 | 209 | if ($cache) { |
|
448 | 209 | TagDependency::invalidate($cache, [$this->getEntityBehaviorsCacheTag()]); |
|
0 ignored issues
–
show
The method
getEntityBehaviorsCacheTag() does not exist on rhosocial\base\models\traits\BlameableTrait . Did you maybe mean behaviors() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
449 | } |
||
450 | 209 | $behaviors = parent::behaviors(); |
|
0 ignored issues
–
show
It seems like you call parent on a different method (
behaviors() instead of getBlameableBehaviors() ). Are you sure this is correct? If so, you might want to change this to $this->behaviors() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
451 | 209 | $behaviors['blameable'] = [ |
|
452 | 209 | 'class' => BlameableBehavior::class, |
|
453 | 209 | 'createdByAttribute' => $this->createdByAttribute, |
|
454 | 209 | 'updatedByAttribute' => $this->updatedByAttribute, |
|
455 | 209 | 'value' => [$this, |
|
456 | 209 | 'onGetCurrentUserGuid'], |
|
457 | ]; |
||
458 | 209 | $this->setBlameableBehaviors($behaviors); |
|
459 | } |
||
460 | 209 | return $this->blameableLocalBehaviors; |
|
461 | } |
||
462 | |||
463 | /** |
||
464 | * Set blameable behaviors. |
||
465 | * @param array $behaviors |
||
466 | */ |
||
467 | 209 | protected function setBlameableBehaviors($behaviors = []) |
|
468 | { |
||
469 | 209 | $this->blameableLocalBehaviors = $behaviors; |
|
470 | 209 | $cache = $this->getCache(); |
|
0 ignored issues
–
show
It seems like
getCache() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
471 | 209 | if ($cache) { |
|
472 | 209 | $tagDependencyConfig = ['tags' => [$this->getBlameableBehaviorsCacheTag()]]; |
|
473 | 209 | $tagDependency = new TagDependency($tagDependencyConfig); |
|
474 | 209 | $cache->set($this->getBlameableBehaviorsCacheKey(), $behaviors, 0, $tagDependency); |
|
475 | } |
||
476 | 209 | } |
|
477 | |||
478 | /** |
||
479 | * Set description. |
||
480 | * @return string description. |
||
481 | */ |
||
482 | 1 | public function getDescription() |
|
483 | { |
||
484 | 1 | $descAttribute = $this->descriptionAttribute; |
|
485 | 1 | return is_string($descAttribute) ? $this->$descAttribute : null; |
|
486 | } |
||
487 | |||
488 | /** |
||
489 | * Get description. |
||
490 | * @param string $desc description. |
||
491 | * @return string|null description if enabled, or null if disabled. |
||
492 | */ |
||
493 | 1 | public function setDescription($desc) |
|
494 | { |
||
495 | 1 | $descAttribute = $this->descriptionAttribute; |
|
496 | 1 | return is_string($descAttribute) ? $this->$descAttribute = $desc : null; |
|
497 | } |
||
498 | |||
499 | /** |
||
500 | * Get blame who owned this blameable model. |
||
501 | * NOTICE! This method will not check whether `$hostClass` exists. You should |
||
502 | * specify it in `init()` method. |
||
503 | * @return BaseUserQuery user. |
||
504 | */ |
||
505 | 18 | public function getUser() |
|
506 | { |
||
507 | 18 | return $this->getHost(); |
|
508 | } |
||
509 | |||
510 | /** |
||
511 | * Declares a `has-one` relation. |
||
512 | * The declaration is returned in terms of a relational [[\yii\db\ActiveQuery]] instance |
||
513 | * through which the related record can be queried and retrieved back. |
||
514 | * |
||
515 | * A `has-one` relation means that there is at most one related record matching |
||
516 | * the criteria set by this relation, e.g., a customer has one country. |
||
517 | * |
||
518 | * For example, to declare the `country` relation for `Customer` class, we can write |
||
519 | * the following code in the `Customer` class: |
||
520 | * |
||
521 | * ```php |
||
522 | * public function getCountry() |
||
523 | * { |
||
524 | * return $this->hasOne(Country::className(), ['id' => 'country_id']); |
||
525 | * } |
||
526 | * ``` |
||
527 | * |
||
528 | * Note that in the above, the 'id' key in the `$link` parameter refers to an attribute name |
||
529 | * in the related class `Country`, while the 'country_id' value refers to an attribute name |
||
530 | * in the current AR class. |
||
531 | * |
||
532 | * Call methods declared in [[\yii\db\ActiveQuery]] to further customize the relation. |
||
533 | * |
||
534 | * This method is provided by [[\yii\db\BaseActiveRecord]]. |
||
535 | * @param string $class the class name of the related record |
||
536 | * @param array $link the primary-foreign key constraint. The keys of the array refer to |
||
537 | * the attributes of the record associated with the `$class` model, while the values of the |
||
538 | * array refer to the corresponding attributes in **this** AR class. |
||
539 | * @return \yii\dbActiveQueryInterface the relational query object. |
||
540 | */ |
||
541 | public abstract function hasOne($class, $link); |
||
542 | |||
543 | /** |
||
544 | * Get host of this model. |
||
545 | * @return BaseUserQuery |
||
546 | */ |
||
547 | 35 | public function getHost() |
|
548 | { |
||
549 | 35 | $hostClass = $this->hostClass; |
|
550 | 35 | $model = $hostClass::buildNoInitModel(); |
|
551 | 35 | return $this->hasOne($hostClass::className(), [$model->guidAttribute => $this->createdByAttribute]); |
|
552 | } |
||
553 | |||
554 | /** |
||
555 | * Set host of this model. |
||
556 | * @param string $host |
||
557 | * @return string|boolean |
||
558 | */ |
||
559 | 150 | public function setHost($host) |
|
560 | { |
||
561 | 150 | if ($host instanceof $this->hostClass || $host instanceof \yii\web\IdentityInterface) { |
|
562 | 111 | return $this->{$this->createdByAttribute} = $host->getGUID(); |
|
563 | } |
||
564 | 50 | if (is_string($host) && preg_match(Number::GUID_REGEX, $host)) { |
|
565 | 1 | return $this->{$this->createdByAttribute} = Number::guid_bin($host); |
|
566 | } |
||
567 | 50 | if (strlen($host) == 16) { |
|
568 | 49 | return $this->{$this->createdByAttribute} = $host; |
|
569 | } |
||
570 | 1 | return false; |
|
571 | } |
||
572 | |||
573 | /** |
||
574 | * |
||
575 | * @param BaseUserModel|string $user |
||
576 | * @return boolean |
||
577 | */ |
||
578 | 4 | public function setUser($user) |
|
579 | { |
||
580 | 4 | return $this->setHost($user); |
|
581 | } |
||
582 | |||
583 | /** |
||
584 | * Get updater who updated this blameable model recently. |
||
585 | * NOTICE! This method will not check whether `$hostClass` exists. You should |
||
586 | * specify it in `init()` method. |
||
587 | * @return BaseUserQuery user. |
||
588 | */ |
||
589 | 6 | public function getUpdater() |
|
590 | { |
||
591 | 6 | if (!is_string($this->updatedByAttribute) || empty($this->updatedByAttribute)) { |
|
592 | 1 | return null; |
|
593 | } |
||
594 | 5 | $hostClass = $this->hostClass; |
|
595 | 5 | $model = $hostClass::buildNoInitModel(); |
|
596 | /* @var $model BaseUserModel */ |
||
597 | 5 | return $this->hasOne($hostClass::className(), [$model->guidAttribute => $this->updatedByAttribute]); |
|
598 | } |
||
599 | |||
600 | /** |
||
601 | * Set updater. |
||
602 | * @param BaseUserModel|string $updater |
||
603 | * @return boolean |
||
604 | */ |
||
605 | 5 | public function setUpdater($updater) |
|
606 | { |
||
607 | 5 | if (!is_string($this->updatedByAttribute) || empty($this->updatedByAttribute)) { |
|
608 | 1 | return false; |
|
609 | } |
||
610 | 4 | if ($updater instanceof $this->hostClass || $updater instanceof \yii\web\IdentityInterface) { |
|
611 | 1 | return $this->{$this->updatedByAttribute} = $updater->getGUID(); |
|
612 | } |
||
613 | 3 | if (is_string($updater) && preg_match(Number::GUID_REGEX, $updater)) { |
|
614 | 1 | return $this->{$this->updatedByAttribute} = Number::guid_bin($updater); |
|
615 | } |
||
616 | 2 | if (strlen($updater) == 16) { |
|
617 | 1 | return $this->{$this->updatedByAttribute} = $updater; |
|
618 | } |
||
619 | 1 | return false; |
|
620 | } |
||
621 | |||
622 | /** |
||
623 | * This event is triggered before the model update. |
||
624 | * This method is ONLY used for being triggered by event. DO NOT call, |
||
625 | * override or modify it directly, unless you know the consequences. |
||
626 | * @param ModelEvent $event |
||
627 | */ |
||
628 | 58 | public function onContentChanged($event) |
|
629 | { |
||
630 | 58 | $sender = $event->sender; |
|
631 | /* @var $sender static */ |
||
632 | 58 | return $sender->resetConfirmation(); |
|
633 | } |
||
634 | |||
635 | /** |
||
636 | * Return the current user's GUID if current model doesn't specify the owner |
||
637 | * yet, or return the owner's GUID if current model has been specified. |
||
638 | * This method is ONLY used for being triggered by event. DO NOT call, |
||
639 | * override or modify it directly, unless you know the consequences. |
||
640 | * @param ModelEvent $event |
||
641 | * @return string the GUID of current user or the owner. |
||
642 | */ |
||
643 | 141 | public function onGetCurrentUserGuid($event) |
|
644 | { |
||
645 | 141 | $sender = $event->sender; |
|
646 | /* @var $sender static */ |
||
647 | 141 | if (isset($sender->attributes[$sender->createdByAttribute])) { |
|
648 | 141 | return $sender->attributes[$sender->createdByAttribute]; |
|
0 ignored issues
–
show
The property
attributes 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;
![]() |
|||
649 | } |
||
650 | $identity = \Yii::$app->user->identity; |
||
651 | /* @var $identity BaseUserModel */ |
||
652 | if ($identity) { |
||
653 | return $identity->getGUID(); |
||
654 | } |
||
655 | } |
||
656 | |||
657 | /** |
||
658 | * Initialize type of content. the first of element[index is 0] of |
||
659 | * $contentTypes will be used. |
||
660 | * @param ModelEvent $event |
||
661 | */ |
||
662 | 26 | public function onInitContentType($event) |
|
663 | { |
||
664 | 26 | $sender = $event->sender; |
|
665 | /* @var $sender static */ |
||
666 | 26 | if (!is_string($sender->contentTypeAttribute) || empty($sender->contentTypeAttribute)) { |
|
667 | return; |
||
668 | } |
||
669 | 26 | $contentTypeAttribute = $sender->contentTypeAttribute; |
|
670 | 26 | if (!isset($sender->$contentTypeAttribute) && |
|
671 | !empty($sender->contentTypes) && |
||
672 | 26 | is_array($sender->contentTypes)) { |
|
673 | 26 | $sender->$contentTypeAttribute = $sender->contentTypes[0]; |
|
674 | } |
||
675 | 26 | } |
|
676 | |||
677 | /** |
||
678 | * Initialize description property with $initDescription. |
||
679 | * @param ModelEvent $event |
||
680 | */ |
||
681 | 75 | public function onInitDescription($event) |
|
682 | { |
||
683 | 75 | $sender = $event->sender; |
|
684 | /* @var $sender static */ |
||
685 | 75 | if (!is_string($sender->descriptionAttribute) || empty($sender->descriptionAttribute)) { |
|
686 | return; |
||
687 | } |
||
688 | 75 | $descriptionAttribute = $sender->descriptionAttribute; |
|
689 | 75 | if (empty($sender->$descriptionAttribute)) { |
|
690 | 75 | $sender->$descriptionAttribute = $sender->initDescription; |
|
691 | } |
||
692 | 75 | } |
|
693 | |||
694 | /** |
||
695 | * Attaches an event handler to an event. |
||
696 | * |
||
697 | * The event handler must be a valid PHP callback. The following are |
||
698 | * some examples: |
||
699 | * |
||
700 | * ``` |
||
701 | * function ($event) { ... } // anonymous function |
||
702 | * [$object, 'handleClick'] // $object->handleClick() |
||
703 | * ['Page', 'handleClick'] // Page::handleClick() |
||
704 | * 'handleClick' // global function handleClick() |
||
705 | * ``` |
||
706 | * |
||
707 | * The event handler must be defined with the following signature, |
||
708 | * |
||
709 | * ``` |
||
710 | * function ($event) |
||
711 | * ``` |
||
712 | * |
||
713 | * where `$event` is an [[Event]] object which includes parameters associated with the event. |
||
714 | * |
||
715 | * This method is provided by [[\yii\base\Component]]. |
||
716 | * @param string $name the event name |
||
717 | * @param callable $handler the event handler |
||
718 | * @param mixed $data the data to be passed to the event handler when the event is triggered. |
||
719 | * When the event handler is invoked, this data can be accessed via [[Event::data]]. |
||
720 | * @param boolean $append whether to append new event handler to the end of the existing |
||
721 | * handler list. If false, the new handler will be inserted at the beginning of the existing |
||
722 | * handler list. |
||
723 | * @see off() |
||
724 | */ |
||
725 | public abstract function on($name, $handler, $data = null, $append = true); |
||
726 | |||
727 | /** |
||
728 | * Detaches an existing event handler from this component. |
||
729 | * This method is the opposite of [[on()]]. |
||
730 | * This method is provided by [[\yii\base\Component]] |
||
731 | * @param string $name event name |
||
732 | * @param callable $handler the event handler to be removed. |
||
733 | * If it is null, all handlers attached to the named event will be removed. |
||
734 | * @return boolean if a handler is found and detached |
||
735 | * @see on() |
||
736 | */ |
||
737 | public abstract function off($name, $handler = null); |
||
738 | |||
739 | /** |
||
740 | * Attach events associated with blameable model. |
||
741 | */ |
||
742 | 209 | public function initBlameableEvents() |
|
743 | { |
||
744 | 209 | $this->on(static::$eventConfirmationChanged, [$this, "onConfirmationChanged"]); |
|
745 | 209 | $this->on(static::$eventNewRecordCreated, [$this, "onInitConfirmation"]); |
|
746 | 209 | $contentTypeAttribute = $this->contentTypeAttribute; |
|
747 | 209 | if (is_string($contentTypeAttribute) && !empty($contentTypeAttribute) && !isset($this->$contentTypeAttribute)) { |
|
748 | 26 | $this->on(static::$eventNewRecordCreated, [$this, "onInitContentType"]); |
|
749 | } |
||
750 | 209 | $descriptionAttribute = $this->descriptionAttribute; |
|
751 | 209 | if (is_string($descriptionAttribute) && !empty($descriptionAttribute) && !isset($this->$descriptionAttribute)) { |
|
752 | 75 | $this->on(static::$eventNewRecordCreated, [$this, 'onInitDescription']); |
|
753 | } |
||
754 | 209 | $this->on(static::EVENT_BEFORE_UPDATE, [$this, "onContentChanged"]); |
|
755 | 209 | $this->initSelfBlameableEvents(); |
|
756 | 209 | } |
|
757 | |||
758 | /** |
||
759 | * @inheritdoc |
||
760 | */ |
||
761 | 86 | public function enabledFields() |
|
762 | { |
||
763 | 86 | $fields = parent::enabledFields(); |
|
764 | 86 | if (is_string($this->createdByAttribute) && !empty($this->createdByAttribute)) { |
|
765 | 86 | $fields[] = $this->createdByAttribute; |
|
766 | } |
||
767 | 86 | if (is_string($this->updatedByAttribute) && !empty($this->updatedByAttribute) && |
|
768 | 65 | $this->createdByAttribute != $this->updatedByAttribute) { |
|
769 | $fields[] = $this->updatedByAttribute; |
||
770 | } |
||
771 | 86 | if (is_string($this->contentAttribute)) { |
|
772 | 86 | $fields[] = $this->contentAttribute; |
|
773 | } |
||
774 | 86 | if (is_array($this->contentAttribute)) { |
|
775 | $fields = array_merge($fields, $this->contentAttribute); |
||
776 | } |
||
777 | 86 | if (is_string($this->descriptionAttribute)) { |
|
778 | 1 | $fields[] = $this->descriptionAttribute; |
|
779 | } |
||
780 | 86 | if (is_string($this->confirmationAttribute)) { |
|
781 | 1 | $fields[] = $this->confirmationAttribute; |
|
782 | } |
||
783 | 86 | if (is_string($this->parentAttribute)) { |
|
784 | 1 | $fields[] = $this->parentAttribute; |
|
785 | } |
||
786 | 86 | return $fields; |
|
787 | } |
||
788 | |||
789 | /** |
||
790 | * Find all follows by specified identity. If `$identity` is null, the logged-in |
||
791 | * identity will be taken. |
||
792 | * @param string|integer $pageSize If it is 'all`, then will find all follows, |
||
793 | * the `$currentPage` parameter will be skipped. If it is integer, it will be |
||
794 | * regarded as sum of models in one page. |
||
795 | * @param integer $currentPage The current page number, begun with 0. |
||
796 | * @param mixed $identity It's type depends on {$this->hostClass}. |
||
797 | * @return static[] If no follows, null will be given, or return follow array. |
||
798 | */ |
||
799 | 1 | public static function findAllByIdentityInBatch($pageSize = 'all', $currentPage = 0, $identity = null) |
|
800 | { |
||
801 | 1 | if ($pageSize === 'all') { |
|
802 | 1 | return static::findByIdentity($identity)->all(); |
|
803 | } |
||
804 | 1 | return static::findByIdentity($identity)->page($pageSize, $currentPage)->all(); |
|
805 | } |
||
806 | |||
807 | /** |
||
808 | * Find one follow by specified identity. If `$identity` is null, the logged-in |
||
809 | * identity will be taken. If $identity doesn't has the follower, null will |
||
810 | * be given. |
||
811 | * @param integer $id user id. |
||
812 | * @param boolean $throwException |
||
813 | * @param mixed $identity It's type depends on {$this->hostClass}. |
||
814 | * @return static |
||
815 | * @throws InvalidParamException |
||
816 | */ |
||
817 | 1 | public static function findOneById($id, $throwException = true, $identity = null) |
|
818 | { |
||
819 | 1 | $query = static::findByIdentity($identity); |
|
820 | 1 | if (!empty($id)) { |
|
821 | 1 | $query = $query->id($id); |
|
822 | } |
||
823 | 1 | $model = $query->one(); |
|
824 | 1 | if (!$model && $throwException) { |
|
825 | 1 | throw new InvalidParamException('Model Not Found.'); |
|
826 | } |
||
827 | 1 | return $model; |
|
828 | } |
||
829 | |||
830 | /** |
||
831 | * Get total of follows of specified identity. |
||
832 | * @param mixed $identity It's type depends on {$this->hostClass}. |
||
833 | * @return integer total. |
||
834 | */ |
||
835 | 3 | public static function countByIdentity($identity = null) |
|
836 | { |
||
837 | 3 | return (int)(static::findByIdentity($identity)->count()); |
|
838 | } |
||
839 | |||
840 | /** |
||
841 | * Get pagination, used for building contents page by page. |
||
842 | * @param integer $limit |
||
843 | * @param mixed $identity It's type depends on {$this->hostClass}. |
||
844 | * @return Pagination |
||
845 | */ |
||
846 | 2 | public static function getPagination($limit = 10, $identity = null) |
|
847 | { |
||
848 | 2 | $limit = (int) $limit; |
|
849 | 2 | $count = static::countByIdentity($identity); |
|
850 | 2 | if ($limit > $count) { |
|
851 | 2 | $limit = $count; |
|
852 | } |
||
853 | 2 | return new Pagination(['totalCount' => $count, 'pageSize' => $limit]); |
|
854 | } |
||
855 | } |
||
856 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: