forked from consultnn/yii2-mongodb-embedded
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAbstractEmbeddedBehavior.php
189 lines (167 loc) · 4.67 KB
/
AbstractEmbeddedBehavior.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<?php
namespace consultnn\embedded;
use Yii;
use yii\base\Behavior;
use yii\db\ActiveRecord;
use yii\validators\Validator;
/**
* Class AbstractEmbeddedBehavior
* @property string $fakeAttribute {@link getFakeAttribute()}
* @property \yii\mongodb\ActiveRecord $owner
* @property mixed $storage
* @package consultnn\embedded
*/
abstract class AbstractEmbeddedBehavior extends Behavior
{
/**
* Attribute for store embedded document
* @var string
*/
public $attribute;
/**
* Embedded document class name
* @var string
*/
public $embedded;
/**
* If true, Embedded model formName look like this: Company['address']
* @var bool
*/
public $setFormName = true;
/**
* Save empty embedded models to db. Emptyness is checked via EmbeddedDocument::isEmpty method.
*
* Сохранять ли пустые вложенные объекты в бд. Проверка на пустоту делается в методе EmbeddedDocument::isEmpty.
* @see EmbeddedDocument::isEmpty
* @var bool
*/
public $saveEmpty = true;
/**
* Default event handlers
* @var array
*/
public $events = [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'validate',
ActiveRecord::EVENT_BEFORE_INSERT => 'proxy',
ActiveRecord::EVENT_BEFORE_UPDATE => 'proxy'
];
/**
* @var mixed
*/
protected $_storage;
/**
* set $_storage property and return it
* @return mixed
*/
abstract public function getStorage();
/**
* Set attributes to storage
* @param array $attributes
* @param bool $safeOnly
*/
abstract protected function setAttributes($attributes, $safeOnly = true);
/**
* Return storage attributes.
*
* Возвращает данные для сохранения в бд.
* @return mixed
*/
abstract protected function getAttributes();
public function events()
{
return $this->events;
}
/**
* @inheritdoc
*/
public function __get($name)
{
if ($this->checkName($name)) {
return $this->storage;
} else {
return parent::__get($name);
}
}
public function __set($name, $value)
{
if ($this->checkName($name)) {
$this->setAttributes($value);
} else {
parent::__set($name, $value);
}
}
/**
* @return string {@link $fakeAttribute}
*/
public function getFakeAttribute()
{
return substr($this->attribute, 1);
}
/**
* Trigger owner event in storage
* @param \yii\base\Event $event
*/
public function proxy($event)
{
$this->storage->setScenario($this->owner->scenario);
$this->storage->trigger($event->name, $event);
$this->owner->{$this->attribute} = $this->getAttributes();
}
/**
* Validate storage
*/
public function validate()
{
if ($this->owner->isAttributeSafe($this->fakeAttribute)) {
$this->storage->setScenario($this->owner->scenario);
if (!$this->storage->validate()) {
$this->owner->addError(
$this->fakeAttribute,
Yii::t('yii', '{attribute} is invalid.', ['attribute' => $this->owner->getAttributeLabel($this->fakeAttribute)])
);
foreach ($this->storage->errors as $attribute => $error) {
foreach ($error as $oneError) {
$this->owner->addError($attribute, $oneError);
}
};
}
}
}
/**
* @inheritdoc
*/
public function canSetProperty($name, $checkVars = true)
{
return $this->checkName($name) || parent::canSetProperty($name, $checkVars);
}
/**
* @inheritdoc
*/
public function canGetProperty($name, $checkVars = true)
{
return $this->checkName($name) || parent::canGetProperty($name, $checkVars);
}
/**
* Check attribute name for getter
* @param $name
* @return bool
*/
protected function checkName($name)
{
return $this->getFakeAttribute() == $name;
}
protected function createEmbedded($attributes, $safeOnly = true, $config = [])
{
if (is_array($this->embedded)) {
$embeddedConfig = $this->embedded;
} else {
$embeddedConfig = ['class' => $this->embedded];
}
$embeddedConfig = array_merge($embeddedConfig, $config);
/** @var EmbeddedDocument $model */
$model = \Yii::createObject($embeddedConfig);
$model->scenario = $this->owner->scenario;
$model->setAttributes($attributes, $safeOnly);
return $model;
}
}