55use Yii ;
66use yii \base \Action ;
77use yii \base \InvalidConfigException ;
8+ use yii \base \Model ;
89use yii \web \BadRequestHttpException ;
910
1011/**
@@ -22,7 +23,7 @@ class EditableAction extends Action
2223 /**
2324 * @var string the scenario to be used (optional)
2425 */
25- public $ scenario ;
26+ public $ scenario = Model:: SCENARIO_DEFAULT ;
2627
2728 /**
2829 * @var \Closure a function to be called previous saving model. The anonymous function is preferable to have the
@@ -33,7 +34,7 @@ class EditableAction extends Action
3334 /**
3435 * @var bool whether to create a model if a primary key parameter was not found
3536 */
36- public $ forceCreate = true ;
37+ public $ forceCreate = false ;
3738
3839 /**
3940 * @var string default pk column name
@@ -42,13 +43,11 @@ class EditableAction extends Action
4243
4344 /**
4445 * @inheritdoc
45- *
46- * @throws \yii\base\InvalidConfigException
4746 */
4847 public function init ()
4948 {
5049 if ($ this ->modelClass === null ) {
51- throw new InvalidConfigException ('ModelClass cannot be empty . ' );
50+ throw new InvalidConfigException ('The "modelClass" property must be set . ' );
5251 }
5352 }
5453
@@ -61,50 +60,63 @@ public function init()
6160 */
6261 public function run ()
6362 {
64- $ class = $ this ->modelClass ;
65- $ pk = Yii::$ app ->request ->post ('pk ' );
63+ $ model = $ this ->findModelOrCreate ();
64+ $ attribute = $ this ->getModelAttribute ();
65+
66+ if ($ this ->preProcess && is_callable ($ this ->preProcess , true )) {
67+ call_user_func ($ this ->preProcess , $ model );
68+ }
69+
70+ $ model ->setScenario ($ this ->scenario );
71+ $ model ->$ attribute = Yii::$ app ->request ->post ('value ' );
72+
73+ if ($ model ->validate ([$ attribute ])) {
74+ return $ model ->save (false );
75+ } else {
76+ throw new BadRequestHttpException ($ model ->getFirstError ($ attribute ));
77+ }
78+ }
79+
80+ /**
81+ * @return array|mixed
82+ *
83+ * @throws BadRequestHttpException
84+ */
85+ private function getModelAttribute ()
86+ {
6687 $ attribute = Yii::$ app ->request ->post ('name ' );
67- //For attributes with format - relationName.attributeName
88+
6889 if (strpos ($ attribute , '. ' )) {
6990 $ attributeParts = explode ('. ' , $ attribute );
7091 $ attribute = array_pop ($ attributeParts );
7192 }
72- $ value = Yii::$ app ->request ->post ('value ' );
7393
7494 if ($ attribute === null ) {
7595 throw new BadRequestHttpException ('Attribute cannot be empty. ' );
7696 }
7797
78- if ($ value === null ) {
79- throw new BadRequestHttpException ('Value cannot be empty. ' );
80- }
98+ return $ attribute ;
99+ }
81100
82- /** @var \Yii\db\ActiveRecord $model */
101+ /**
102+ * @return yii\db\ActiveRecord
103+ *
104+ * @throws BadRequestHttpException
105+ */
106+ private function findModelOrCreate ()
107+ {
108+ $ pk = unserialize (base64_decode (Yii::$ app ->request ->post ('pk ' )));
109+ $ class = $ this ->modelClass ;
83110 $ model = $ class ::findOne (is_array ($ pk ) ? $ pk : [$ this ->pkColumn => $ pk ]);
111+
84112 if (!$ model ) {
85- if ($ this ->forceCreate ) { // only useful for models with one editable attribute or no validations
113+ if ($ this ->forceCreate ) {
86114 $ model = new $ class ();
87115 } else {
88116 throw new BadRequestHttpException ('Entity not found by primary key ' . $ pk );
89117 }
90118 }
91119
92- // do we have a preProcess function
93- if ($ this ->preProcess && is_callable ($ this ->preProcess , true )) {
94- call_user_func ($ this ->preProcess , $ model );
95- }
96-
97- if ($ this ->scenario !== null ) {
98- $ model ->setScenario ($ this ->scenario );
99- }
100-
101- $ model ->$ attribute = $ value ;
102-
103- if ($ model ->validate ([$ attribute ])) {
104- // no need to specify which attributes as Yii2 handles that via [[BaseActiveRecord::getDirtyAttributes]]
105- return $ model ->save (false );
106- } else {
107- throw new BadRequestHttpException ($ model ->getFirstError ($ attribute ));
108- }
120+ return $ model ;
109121 }
110122}
0 commit comments