Completed
Push — master ( fa3ca9...034150 )
by vistart
05:25
created

BaseMongoBlameableModel   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 39.58%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 5
dl 0
loc 141
ccs 19
cts 48
cp 0.3958
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getUpdater() 0 10 3
B setUpdater() 0 16 8
A init() 0 11 4
A findByIdentity() 0 4 1
A attributes() 0 4 1
A onGetCurrentUserGuid() 0 13 3
A getHost() 0 7 1
B setHost() 0 13 6
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\models;
14
15
use rhosocial\base\helpers\Number;
16
use rhosocial\base\models\models\BaseUserModel;
17
use rhosocial\base\models\queries\BaseMongoBlameableQuery;
18
use rhosocial\base\models\traits\BlameableTrait;
19
use yii\web\IdentityInterface;
20
21
/**
22
 * Description of BaseMongoBlameableModel
23
 *
24
 * @version 1.0
25
 * @author vistart <[email protected]>
26
 */
27
abstract class BaseMongoBlameableModel extends BaseMongoEntityModel
28
{
29
    use BlameableTrait;
30
31
    /**
32
     * Initialize the blameable model.
33
     * If query class is not specified, [[BaseMongoBlameableQuery]] will be taken.
34
     */
35 12
    public function init()
36
    {
37 12
        if (!is_string($this->queryClass) || empty($this->queryClass)) {
38 12
            $this->queryClass = BaseMongoBlameableQuery::class;
39
        }
40 12
        if ($this->skipInit) {
41 12
            return;
42
        }
43 12
        $this->initBlameableEvents();
44 12
        parent::init();
45 12
    }
46
47
    /**
48
     * Get the query class with specified identity.
49
     * @param BaseUserModel $identity
50
     * @return BaseMongoBlameableQuery
51
     */
52 3
    public static function findByIdentity($identity = null)
53
    {
54 3
        return static::find()->byIdentity($identity);
55
    }
56
57
    /**
58
     * Because every document has a `MongoId" class, this class no longer needs GUID feature.
59
     * @var boolean determines whether enable the GUID features.
60
     */
61
    public $guidAttribute = false;
62
    public $idAttribute = '_id';
63
64
    /**
65
     * @inheritdoc
66
     * You can override this method if enabled fields cannot meet your requirements.
67
     * @return array
68
     */
69 12
    public function attributes()
70
    {
71 12
        return $this->enabledFields();
72
    }
73
74
    /**
75
     * Get blame who owned this blameable model.
76
     * NOTICE! This method will not check whether `$userClass` exists. You should
77
     * specify it in `init()` method.
78
     * @return BaseUserQuery user.
79
     */
80
    public function getHost()
81
    {
82
        $hostClass = $this->hostClass;
83
        $user = $hostClass::buildNoInitModel();
84
        /* @var BaseUserModel $user */
85
        return $this->hasOne($hostClass::className(), [$user->guidAttribute => $this->createdByAttribute]);
86
    }
87
    
88
    /**
89
     * 
90
     * @param IdentityInterface $host
91
     * @return boolean
92
     */
93 12
    public function setHost($host)
94
    {
95 12
        if ($host instanceof $this->hostClass || $host instanceof IdentityInterface) {
96 12
            return $this->{$this->createdByAttribute} = $host->getReadableGUID();
97
        }
98
        if (is_string($host) && preg_match(Number::GUID_REGEX, $host)) {
99
            return $this->{$this->createdByAttribute} = $host;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->{$this->cr...edByAttribute} = $host; (string) is incompatible with the return type documented by rhosocial\base\models\mo...BlameableModel::setHost of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
100
        }
101
        if (strlen($host) == 16) {
102
            return $this->{$this->createdByAttribute} = Number::guid(false, false, $host);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->{$this->cr...d(false, false, $host); (string) is incompatible with the return type documented by rhosocial\base\models\mo...BlameableModel::setHost of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
103
        }
104
        return false;
105
    }
106
107
    /**
108
     * Get updater who updated this blameable model recently.
109
     * NOTICE! This method will not check whether `$userClass` exists. You should
110
     * specify it in `init()` method.
111
     * @return BaseUserQuery user.
112
     */
113
    public function getUpdater()
114
    {
115
        if (!is_string($this->updatedByAttribute) || empty($this->updatedByAttribute)) {
116
            return null;
117
        }
118
        $hostClass = $this->hostClass;
119
        $host = $hostClass::buildNoInitModel();
120
        /* @var $user BaseUserModel */
121
        return $this->hasOne($hostClass::className(), [$host->guidAttribute => $this->updatedByAttribute]);
122
    }
123
    
124
    /**
125
     * 
126
     * @param IdentityInterface $user
0 ignored issues
show
Bug introduced by
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
127
     * @return boolean
128
     */
129
    public function setUpdater($updater)
130
    {
131
        if (!is_string($this->updatedByAttribute) || empty($this->updatedByAttribute)) {
132
            return false;
133
        }
134
        if ($updater instanceof $this->hostClass || $updater instanceof IdentityInterface) {
135
            return $this->{$this->updatedByAttribute} = $updater->getReadableGUID();
136
        }
137
        if (is_string($updater) && preg_match(Number::GUID_REGEX, $updater)) {
138
            return $this->{$this->updatedByAttribute} = $updater;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->{$this->up...yAttribute} = $updater; (string) is incompatible with the return type documented by rhosocial\base\models\mo...meableModel::setUpdater of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
139
        }
140
        if (strlen($updater) == 16) {
141
            return $this->{$this->updatedByAttribute} = Number::guid(false, false, $updater);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->{$this->up...alse, false, $updater); (string) is incompatible with the return type documented by rhosocial\base\models\mo...meableModel::setUpdater of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
142
        }
143
        return false;
144
    }
145
146
    /**
147
     * Return the current user's GUID if current model doesn't specify the owner
148
     * yet, or return the owner's GUID if current model has been specified.
149
     * This method is ONLY used for being triggered by event. DO NOT call,
150
     * override or modify it directly, unless you know the consequences.
151
     * @param ModelEvent $event
152
     * @return string the GUID of current user or the owner.
153
     */
154 12
    public function onGetCurrentUserGuid($event)
155
    {
156 12
        $sender = $event->sender;
157
        /* @var $sender static */
158 12
        if (isset($sender->attributes[$sender->createdByAttribute])) {
159 12
            return $sender->attributes[$sender->createdByAttribute];
160
        }
161
        $identity = \Yii::$app->user->identity;
162
        /* @var BaseUserModel $identity */
163
        if ($identity) {
164
            return $identity->getReadableGUID();
165
        }
166
    }
167
}
168