HCE Project DC service web UI  0.2
Hierarchical Cluster Engine DC service web UI
 All Classes Namespaces Files Functions Variables Pages
TbEditableSaver.php
Go to the documentation of this file.
1 <?php
16 class TbEditableSaver extends CComponent
17 {
23  public $scenario = 'editable';
24 
30  public $modelClass;
36  public $primaryKey;
42  public $attribute;
48  public $model;
49 
53  public $value;
54 
58  public $errorHttpCode = 400;
59 
65  protected $changedAttributes = array();
66 
78  public function __construct($modelClass)
79  {
80  if (empty($modelClass)) {
81  throw new CException(Yii::t(
82  'TbEditableSaver.editable',
83  'You should provide modelClass in constructor of EditableSaver.'
84  ));
85  }
86 
87  $this->modelClass = $modelClass;
88 
89  //for non-namespaced models do ucfirst (for backwards compability)
90  //see https://github.com/vitalets/x-editable-yii/issues/9
91  if (strpos($this->modelClass, '\\') === false) {
92  $this->modelClass = ucfirst($this->modelClass);
93  }
94  }
95 
102  public function update()
103  {
104  //get params from request
105  $this->primaryKey = yii::app()->request->getParam('pk');
106  $this->attribute = yii::app()->request->getParam('name');
107  $this->value = yii::app()->request->getParam('value');
108 
109  //checking params
110  if (empty($this->attribute)) {
111  throw new CException(Yii::t('TbEditableSaver.editable', 'Property "attribute" should be defined.'));
112  }
113  if (empty($this->primaryKey)) {
114  throw new CException(Yii::t('TbEditableSaver.editable', 'Property "primaryKey" should be defined.'));
115  }
116 
117  //loading model
118  $this->model = CActiveRecord::model($this->modelClass)->findByPk($this->primaryKey);
119  if (!$this->model) {
120  throw new CException(Yii::t(
121  'TbEditableSaver.editable',
122  'Model {class} not found by primary key "{pk}"',
123  array(
124  '{class}' => get_class($this->model),
125  '{pk}' => is_array($this->primaryKey) ? CJSON::encode($this->primaryKey) : $this->primaryKey
126  )
127  ));
128  }
129 
130  //set scenario
131  $this->model->setScenario($this->scenario);
132 
133  //commented to be able to work with virtual attributes
134  //see https://github.com/vitalets/yii-bootstrap-editable/issues/15
135  /*
136  //is attribute exists
137  if (!$this->model->hasAttribute($this->attribute)) {
138  throw new CException(Yii::t('EditableSaver.editable', 'Model {class} does not have attribute "{attr}"', array(
139  '{class}'=>get_class($this->model), '{attr}'=>$this->attribute)));
140  }
141  */
142 
143  //is attribute safe
144  if (!$this->model->isAttributeSafe($this->attribute)) {
145  throw new CException(Yii::t(
146  'editable',
147  'Model {class} rules do not allow to update attribute "{attr}"',
148  array(
149  '{class}' => get_class($this->model),
150  '{attr}' => $this->attribute
151  )
152  ));
153  }
154 
155  //setting new value
156  $this->setAttribute($this->attribute, $this->value);
157 
158  //validate attribute
159  $this->model->validate(array($this->attribute));
160  $this->checkErrors();
161 
162  //trigger beforeUpdate event
163  $this->beforeUpdate();
164  $this->checkErrors();
165 
166  //saving (no validation, only changed attributes)
167  if ($this->model->save(false, $this->changedAttributes)) {
168  //trigger afterUpdate event
169  $this->afterUpdate();
170  } else {
171  $this->error(Yii::t('TbEditableSaver.editable', 'Error while saving record!'));
172  }
173  }
174 
182  public function checkErrors()
183  {
184  if ($this->model->hasErrors()) {
185  $msg = array();
186  foreach ($this->model->getErrors() as $attribute => $errors) {
187  // TODO: make use of $attribute elements
188  $msg = array_merge($msg, $errors);
189  }
190  // TODO: show several messages. should be checked in x-editable js
191  //$this->error(join("\n", $msg));
192  $this->error($msg[0]);
193  }
194  }
195 
205  public function error($msg)
206  {
207  throw new CHttpException($this->errorHttpCode, $msg);
208  }
209 
219  public function setAttribute($name, $value)
220  {
221  $this->model->$name = $value;
222  if (!in_array($name, $this->changedAttributes)) {
223  $this->changedAttributes[] = $name;
224  }
225  }
226 
234  public function onBeforeUpdate($event)
235  {
236  $this->raiseEvent('onBeforeUpdate', $event);
237  }
238 
246  public function onAfterUpdate($event)
247  {
248  $this->raiseEvent('onAfterUpdate', $event);
249  }
250 
257  protected function beforeUpdate()
258  {
259  $this->onBeforeUpdate(new CModelEvent($this));
260  }
261 
268  protected function afterUpdate()
269  {
270  $this->onAfterUpdate(new CModelEvent($this));
271  }
272 }