1 | <?php |
||
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; |
||
|
|||
100 | } |
||
101 | if (strlen($host) == 16) { |
||
102 | return $this->{$this->createdByAttribute} = Number::guid(false, false, $host); |
||
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() |
||
123 | |||
124 | /** |
||
125 | * |
||
126 | * @param IdentityInterface $user |
||
127 | * @return boolean |
||
128 | */ |
||
129 | public function setUpdater($updater) |
||
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) |
|
167 | } |
||
168 |
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.