-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathEditableAction.php
138 lines (113 loc) · 3.29 KB
/
EditableAction.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
<?php
namespace yii2mod\editable;
use Yii;
use yii\base\Action;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\web\BadRequestHttpException;
/**
* Class EditableAction
*
* @package yii2mod\editable
*/
class EditableAction extends Action
{
/**
* @var string the class name to handle
*/
public $modelClass;
/**
* @var string the scenario to be used (optional)
*/
public $scenario = Model::SCENARIO_DEFAULT;
/**
* @var \Closure a function to be called previous saving model. The anonymous function is preferable to have the
* model passed by reference. This is useful when we need to set model with extra data previous update
*/
public $preProcess;
/**
* @var bool whether to create a model if a primary key parameter was not found
*/
public $forceCreate = false;
/**
* @var string default pk column name
*/
public $pkColumn = 'id';
/**
* @inheritdoc
*/
public function init()
{
if ($this->modelClass === null) {
throw new InvalidConfigException('The "modelClass" property must be set.');
}
}
/**
* Runs the action
*
* @return bool
*
* @throws BadRequestHttpException
*/
public function run()
{
$model = $this->findModelOrCreate();
$attribute = $this->getModelAttribute();
$value = Yii::$app->request->post('value');
if ($this->preProcess && is_callable($this->preProcess, true)) {
call_user_func($this->preProcess, $model);
}
$model->setScenario($this->scenario);
$model->$attribute = $value;
if ($model->validate([$attribute])) {
return $model->save(false);
} else {
throw new BadRequestHttpException($model->getFirstError($attribute));
}
}
/**
* @return array|mixed
*
* @throws BadRequestHttpException
*/
private function getModelAttribute()
{
$attribute = Yii::$app->request->post('name');
if ($attribute === null) {
throw new BadRequestHttpException('Attribute cannot be empty.');
}
if (strpos($attribute, '.')) {
$attributePath = explode('.', $attribute);
return array_pop($attributePath);
}
return $attribute;
}
/**
* @return yii\db\ActiveRecord
*
* @throws BadRequestHttpException
*/
private function findModelOrCreate()
{
$pk = unserialize(base64_decode(Yii::$app->request->post('pk')));
$class = $this->modelClass;
$model = $class::findOne(is_array($pk) ? $pk : [$this->pkColumn => $pk]);
if (!$model) {
if ($this->forceCreate) {
$model = new $class();
} else {
throw new BadRequestHttpException('Entity not found by primary key ' . $pk);
}
}
$attribute = Yii::$app->request->post('name');
if (strpos($attribute, '.')) {
$attributePath = explode('.', $attribute);
$related = $model[array_shift($attributePath)];
while ((count($attributePath) > 1)) {
$related = $model[array_shift($attributePath)];
}
return $related;
}
return $model;
}
}