1+ <?php
2+ /**
3+ * @author Anton Tuyakhov <atuyakhov@gmail.com>
4+ */
5+
6+ namespace tuyakhov \jsonapi \actions ;
7+
8+ use Yii ;
9+ use yii \data \ActiveDataProvider ;
10+ use yii \db \ActiveRecordInterface ;
11+ use yii \db \ActiveRelationTrait ;
12+ use yii \db \BaseActiveRecord ;
13+ use yii \helpers \ArrayHelper ;
14+ use yii \web \ForbiddenHttpException ;
15+ use yii \web \NotFoundHttpException ;
16+
17+ /**
18+ * Deletes the specified members from a relationship
19+ * @link http://jsonapi.org/format/#crud-updating-relationships
20+ */
21+ class DeleteRelationshipAction extends Action
22+ {
23+ /**
24+ * Removes the relationships from primary model.
25+ * @var callable
26+ */
27+ public $ unlinkRelationships ;
28+
29+ /**
30+ * @param string $id an ID of the primary resource
31+ * @param string $name a name of the related resource
32+ * @return ActiveDataProvider
33+ * @throws ForbiddenHttpException
34+ * @throws NotFoundHttpException
35+ * @throws \yii\base\InvalidConfigException
36+ */
37+ public function run ($ id , $ name )
38+ {
39+ /** @var BaseActiveRecord $model */
40+ $ model = $ this ->findModel ($ id );
41+
42+ if (!$ related = $ model ->getRelation ($ name , false )) {
43+ throw new NotFoundHttpException ('Relationship does not exist ' );
44+ }
45+
46+ if (!$ related ->multiple ) {
47+ throw new ForbiddenHttpException ('Unsupported request to update relationship ' );
48+ }
49+
50+ if ($ this ->checkAccess ) {
51+ call_user_func ($ this ->checkAccess , $ this ->id , $ model , $ name );
52+ }
53+
54+ $ this ->unlinkRelationships ($ model , [$ name => Yii::$ app ->getRequest ()->getBodyParams ()]);
55+
56+
57+ return new ActiveDataProvider ([
58+ 'query ' => $ related
59+ ]);
60+ }
61+
62+ /**
63+ * Removes the relationships from primary model.
64+ * @param $model ActiveRecordInterface
65+ * @param array $data relationship links
66+ */
67+ protected function unlinkRelationships ($ model , array $ data = [])
68+ {
69+ if ($ this ->unlinkRelationships !== null ) {
70+ call_user_func ($ this ->unlinkRelationships , $ this , $ model , $ data );
71+ return ;
72+ }
73+
74+ foreach ($ data as $ name => $ relationship ) {
75+ /** @var $related ActiveRelationTrait */
76+ if (!$ related = $ model ->getRelation ($ name , false )) {
77+ continue ;
78+ }
79+ /** @var BaseActiveRecord $relatedClass */
80+ $ relatedClass = new $ related ->modelClass ;
81+ $ relationships = ArrayHelper::keyExists ($ relatedClass ->formName (), $ relationship ) ? $ relationship [$ relatedClass ->formName ()] : [];
82+
83+ $ ids = [];
84+ foreach ($ relationships as $ index => $ relObject ) {
85+ if (!isset ($ relObject ['id ' ])) {
86+ continue ;
87+ }
88+ $ ids [] = $ relObject ['id ' ];
89+ }
90+
91+ $ records = $ relatedClass ::find ()->andWhere (['in ' , $ relatedClass ::primaryKey (), $ ids ])->all ();
92+ foreach ($ records as $ record ) {
93+ $ model ->unlink ($ name , $ record );
94+ }
95+ }
96+ }
97+ }
0 commit comments