Skip to content

Commit 83eac62

Browse files
authored
Merge pull request #9 from siggi-k/callback-scenario
callable scenarios for actions: create, update, delete
2 parents 134701e + 8ee5446 commit 83eac62

File tree

3 files changed

+81
-18
lines changed

3 files changed

+81
-18
lines changed

src/actions/CreateAction.php

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use yii\base\Model;
1717
use yii\db\ActiveRecordInterface;
1818
use yii\helpers\Url;
19+
use yii\base\InvalidConfigException;
1920
use yii\web\ServerErrorHttpException;
2021
use function array_keys;
2122
use function call_user_func;
@@ -29,27 +30,40 @@ class CreateAction extends JsonApiAction
2930
{
3031
use HasResourceTransformer;
3132
use HasParentAttributes;
33+
3234
/**
3335
* @var array
34-
* * Configuration for attaching relationships
36+
* Configuration for attaching relationships
3537
* Should contains key - relation name and array with
3638
* idType - php type of resource ids for validation
3739
* validator = callback for custom id validation
3840
* Keep it empty for disable this ability
3941
* @see https://jsonapi.org/format/#crud-creating
4042
* @example
41-
* 'allowedRelations' => [
42-
* 'author' => ['idType' => 'integer'],
43-
* 'photos' => ['idType' => 'integer', 'validator' => function($model, array $ids) {
44-
* $relatedModels = Relation::find()->where(['id' => $ids])->andWhere([additional conditions])->all();
45-
* if(count($relatedModels) < $ids) {
46-
* throw new HttpException(422, 'Invalid photos ids');
47-
* }],
48-
* ]
49-
**/
43+
* 'allowedRelations' => [
44+
* 'author' => ['idType' => 'integer'],
45+
* 'photos' => ['idType' => 'integer', 'validator' => function($model, array $ids) {
46+
* $relatedModels = Relation::find()->where(['id' => $ids])->andWhere([additional conditions])->all();
47+
* if (count($relatedModels) < $ids) {
48+
* throw new HttpException(422, 'Invalid photos ids');
49+
* }
50+
* },
51+
* ]
52+
*/
53+
5054
public $allowedRelations = [];
55+
5156
/**
52-
* @var string the scenario to be assigned to the new model before it is validated and saved.
57+
* @var string|callable
58+
* string - the scenario to be assigned to the model before it is validated and saved.
59+
* callable - a PHP callable that will be executed during the action.
60+
* It must return a string representing the scenario to be assigned to the model before it is validated and saved.
61+
* The signature of the callable should be as follows,
62+
* ```php
63+
* function ($action, $model) {
64+
* // $model is the requested model instance.
65+
* }
66+
* ```
5367
*/
5468
public $scenario = Model::SCENARIO_DEFAULT;
5569

@@ -97,9 +111,17 @@ public function run()
97111
}
98112

99113
/* @var $model \yii\db\ActiveRecord */
100-
$model = new $this->modelClass([
101-
'scenario' => $this->scenario,
102-
]);
114+
$model = new $this->modelClass();
115+
116+
if (is_string($this->scenario)) {
117+
$scenario = $this->scenario;
118+
} elseif (is_callable($this->scenario)) {
119+
$scenario = call_user_func($this->scenario, $this->id, $model);
120+
} else {
121+
throw new InvalidConfigException('The "scenario" property must be defined either as a string or as a callable.');
122+
}
123+
$model->setScenario($scenario);
124+
103125
RelationshipManager::validateRelationships($model, $this->getResourceRelationships(), $this->allowedRelations);
104126
$model->load($this->getResourceAttributes(), '');
105127
if ($this->isParentRestrictionRequired()) {

src/actions/DeleteAction.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Closure;
1111
use Yii;
1212
use yii\base\Model;
13+
use yii\base\InvalidConfigException;
1314
use yii\web\ForbiddenHttpException;
1415
use yii\web\ServerErrorHttpException;
1516

@@ -23,7 +24,16 @@ class DeleteAction extends JsonApiAction
2324
use HasParentAttributes;
2425

2526
/**
26-
* @var string the scenario to be assigned to the new model before it is validated and saved.
27+
* @var string|callable
28+
* string - the scenario to be assigned to the model before it is validated and saved.
29+
* callable - a PHP callable that will be executed during the action.
30+
* It must return a string representing the scenario to be assigned to the model before it is validated and saved.
31+
* The signature of the callable should be as follows,
32+
* ```php
33+
* function ($action, $model) {
34+
* // $model is the requested model instance.
35+
* }
36+
* ```
2737
*/
2838
public $scenario = Model::SCENARIO_DEFAULT;
2939

@@ -56,10 +66,20 @@ public function run($id):void
5666
throw new ForbiddenHttpException('Update with relationships not supported yet');
5767
}
5868
$model = $this->isParentRestrictionRequired() ? $this->findModelForParent($id) : $this->findModel($id);
59-
$model->setScenario($this->scenario);
69+
70+
if (is_string($this->scenario)) {
71+
$scenario = $this->scenario;
72+
} elseif (is_callable($this->scenario)) {
73+
$scenario = call_user_func($this->scenario, $this->id, $model);
74+
} else {
75+
throw new InvalidConfigException('The "scenario" property must be defined either as a string or as a callable.');
76+
}
77+
$model->setScenario($scenario);
78+
6079
if ($this->checkAccess) {
6180
call_user_func($this->checkAccess, $this->id, $model);
6281
}
82+
6383
if ($model->delete() === false) {
6484
throw new ServerErrorHttpException('Failed to delete the object for unknown reason.');
6585
}

src/actions/UpdateAction.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Yii;
1616
use yii\base\Model;
1717
use yii\db\ActiveRecord;
18+
use yii\base\InvalidConfigException;
1819
use yii\web\ServerErrorHttpException;
1920

2021
/**
@@ -51,8 +52,18 @@ class UpdateAction extends JsonApiAction
5152
* ]
5253
**/
5354
public $allowedRelations = [];
55+
5456
/**
55-
* @var string the scenario to be assigned to the model before it is validated and updated.
57+
* @var string|callable
58+
* string - the scenario to be assigned to the model before it is validated and updated.
59+
* callable - a PHP callable that will be executed during the action.
60+
* It must return a string representing the scenario to be assigned to the model before it is validated and updated.
61+
* The signature of the callable should be as follows,
62+
* ```php
63+
* function ($action, $model) {
64+
* // $model is the requested model instance.
65+
* }
66+
* ```
5667
*/
5768
public $scenario = Model::SCENARIO_DEFAULT;
5869
/**
@@ -88,10 +99,20 @@ public function run($id):Item
8899
{
89100
/* @var $model ActiveRecord */
90101
$model = $this->isParentRestrictionRequired() ? $this->findModelForParent($id) : $this->findModel($id);
91-
$model->scenario = $this->scenario;
102+
103+
if (is_string($this->scenario)) {
104+
$scenario = $this->scenario;
105+
} elseif (is_callable($this->scenario)) {
106+
$scenario = call_user_func($this->scenario, $this->id, $model);
107+
} else {
108+
throw new InvalidConfigException('The "scenario" property must be defined either as a string or as a callable.');
109+
}
110+
$model->setScenario($scenario);
111+
92112
if ($this->checkAccess) {
93113
call_user_func($this->checkAccess, $this->id, $model);
94114
}
115+
95116
$originalModel = clone $model;
96117
RelationshipManager::validateRelationships($model, $this->getResourceRelationships(), $this->allowedRelations);
97118
if (empty($this->getResourceAttributes()) && $this->hasResourceRelationships()) {

0 commit comments

Comments
 (0)