1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 class WhEditableSaver extends CComponent
18 {
19 20 21 22 23
24 public $scenario;
25
26 27 28 29 30
31 public $modelClass;
32
33 34 35 36 37
38 public $primaryKey;
39
40 41 42 43 44
45 public $attribute;
46
47 48 49 50 51
52 public $model;
53
54 55 56
57 public $value;
58
59 60 61
62 public $errorHttpCode = 400;
63
64 65 66 67 68
69 protected $changedAttributes = array();
70
71 72 73 74 75 76
77 public function __construct($modelClass)
78 {
79 if (empty($modelClass)) {
80 throw new CException(Yii::t('EditableSaver.editable', 'You should provide modelClass in constructor of EditableSaver.'));
81 }
82
83 $this->modelClass = $modelClass;
84
85
86
87 if(strpos($this->modelClass, '\\') === false) {
88 $this->modelClass = ucfirst($this->modelClass);
89 }
90 }
91
92 93 94 95
96 public function update()
97 {
98
99 $this->primaryKey = yii::app()->request->getParam('pk');
100 $this->attribute = yii::app()->request->getParam('name');
101 $this->value = yii::app()->request->getParam('value');
102 $this->scenario = yii::app()->request->getParam('scenario');
103
104
105 if (empty($this->attribute)) {
106 throw new CException(Yii::t('EditableSaver.editable','Property "attribute" should be defined.'));
107 }
108
109 $this->model = new $this->modelClass();
110
111 $isFormModel = $this->model instanceOf CFormModel;
112 $isMongo = EditableField::isMongo($this->model);
113
114 if (empty($this->primaryKey) && !$isFormModel) {
115 throw new CException(Yii::t('EditableSaver.editable','Property "primaryKey" should be defined.'));
116 }
117
118
119 if($isMongo) {
120 $this->model = $this->model->findByPk(new MongoID($this->primaryKey));
121 } elseif(!$isFormModel) {
122 $this->model = $this->model->findByPk($this->primaryKey);
123 }
124
125 if (!$this->model) {
126 throw new CException(Yii::t('EditableSaver.editable', 'Model {class} not found by primary key "{pk}"', array(
127 '{class}'=>get_class($this->model), '{pk}' => is_array($this->primaryKey) ? CJSON::encode($this->primaryKey) : $this->primaryKey)));
128 }
129
130
131 $originalModel = $this->model;
132
133
134 if($isMongo) {
135 $resolved = EditableField::resolveModels($this->model, $this->attribute);
136 $this->model = $resolved['model'];
137 $this->attribute = $resolved['attribute'];
138 $staticModel = $resolved['staticModel'];
139 } else {
140 $staticModel = $this->model;
141 }
142
143
144 if($this->scenario) {
145 $originalModel->setScenario($this->scenario);
146 }
147
148
149 if (!$this->model->isAttributeSafe($this->attribute)) {
150 throw new CException(Yii::t('editable', 'Model {class} rules do not allow to update attribute "{attr}"', array(
151 '{class}'=>get_class($this->model), '{attr}'=>$this->attribute)));
152 }
153
154
155 $this->setAttribute($this->attribute, $this->value);
156
157
158 $this->model->validate(array($this->attribute));
159 $this->checkErrors();
160
161
162 $this->beforeUpdate();
163 $this->checkErrors();
164
165
166 if(!$isMongo) {
167 $this->changedAttributes = array_intersect($this->changedAttributes, $originalModel->attributeNames());
168 if(count($this->changedAttributes) == 0) {
169
170 $this->changedAttributes = null;
171 }
172 }
173
174
175 if($isMongo) {
176 $result = $originalModel->save(false, null);
177 } elseif(!$isFormModel) {
178 $result = $originalModel->save(false, $this->changedAttributes);
179 } else {
180 $result = true;
181 }
182 if ($result) {
183 $this->afterUpdate();
184 } else {
185 $this->error(Yii::t('EditableSaver.editable', 'Error while saving record!'));
186 }
187 }
188
189 190 191 192 193
194 public function checkErrors()
195 {
196 if ($this->model->hasErrors()) {
197 $msg = array();
198 foreach($this->model->getErrors() as $attribute => $errors) {
199 $msg = array_merge($msg, $errors);
200 }
201
202
203 $this->error($msg[0]);
204 }
205 }
206
207 208 209 210 211
212 public function error($msg)
213 {
214 throw new CHttpException($this->errorHttpCode, $msg);
215 }
216
217 218 219 220 221 222 223
224 public function setAttribute($name, $value)
225 {
226 $this->model->$name = $value;
227 if(!in_array($name, $this->changedAttributes)) {
228 $this->changedAttributes[] = $name;
229 }
230 }
231
232 233 234 235
236 public function onBeforeUpdate($event)
237 {
238 $this->raiseEvent('onBeforeUpdate', $event);
239 }
240
241 242 243 244
245 public function onAfterUpdate($event)
246 {
247 $this->raiseEvent('onAfterUpdate', $event);
248 }
249
250 251 252 253
254 protected function beforeUpdate()
255 {
256 $this->onBeforeUpdate(new CEvent($this));
257 }
258
259 260 261 262
263 protected function afterUpdate()
264 {
265 $this->onAfterUpdate(new CEvent($this));
266 }
267 }
268