66namespace tuyakhov \jsonapi ;
77
88use yii \helpers \ArrayHelper ;
9+ use yii \web \BadRequestHttpException ;
910use \yii \web \JsonParser ;
1011
1112class JsonApiParser extends JsonParser
@@ -33,37 +34,27 @@ class JsonApiParser extends JsonParser
3334 public function parse ($ rawBody , $ contentType )
3435 {
3536 $ array = parent ::parse ($ rawBody , $ contentType );
36- if ($ type = ArrayHelper::getValue ($ array , 'data.type ' )) {
37- $ formName = $ this ->typeToFormName ($ type );
38- if ($ attributes = ArrayHelper::getValue ($ array , 'data.attributes ' )) {
39- $ result [$ formName ] = array_combine ($ this ->parseMemberNames (array_keys ($ attributes )), array_values ($ attributes ));
40- } elseif ($ id = ArrayHelper::getValue ($ array , 'data.id ' )) {
41- $ result [$ formName ] = ['id ' => $ id , 'type ' => $ type ];
42- }
43- if ($ relationships = ArrayHelper::getValue ($ array , 'data.relationships ' )) {
44- foreach ($ relationships as $ name => $ relationship ) {
45- if (isset ($ relationship [0 ])) {
46- foreach ($ relationship as $ item ) {
47- if (isset ($ item ['type ' ]) && isset ($ item ['id ' ])) {
48- $ formName = $ this ->typeToFormName ($ item ['type ' ]);
49- $ result [$ name ][$ formName ][] = $ item ;
50- }
51- }
52- } elseif (isset ($ relationship ['type ' ]) && isset ($ relationship ['id ' ])) {
53- $ formName = $ this ->typeToFormName ($ relationship ['type ' ]);
54- $ result [$ name ][$ formName ] = $ relationship ;
55- }
56- }
37+ $ data = ArrayHelper::getValue ($ array , 'data ' , []);
38+ if (empty ($ data )) {
39+ if ($ this ->throwException ) {
40+ throw new BadRequestHttpException ('The request MUST include a single resource object as primary data. ' );
5741 }
42+ return [];
43+ }
44+ if (ArrayHelper::isAssociative ($ data )) {
45+ $ result = $ this ->parseResource ($ data );
46+
47+ $ relObjects = ArrayHelper::getValue ($ data , 'relationships ' , []);
48+ $ result ['relationships ' ] = $ this ->parseRelationships ($ relObjects );
5849 } else {
59- $ data = ArrayHelper::getValue ($ array , 'data ' , []);
60- foreach ($ data as $ relationLink ) {
61- if (isset ($ relationLink ['type ' ]) && isset ($ relationLink ['id ' ])) {
62- $ formName = $ this ->typeToFormName ($ relationLink ['type ' ]);
63- $ result [$ formName ][] = $ relationLink ;
50+ foreach ($ data as $ object ) {
51+ $ resource = $ this ->parseResource ($ object );
52+ foreach (array_keys ($ resource ) as $ key ) {
53+ $ result [$ key ][] = $ resource [$ key ];
6454 }
6555 }
6656 }
57+
6758 return isset ($ result ) ? $ result : $ array ;
6859 }
6960
@@ -84,4 +75,53 @@ protected function parseMemberNames(array $memberNames = [])
8475 {
8576 return array_map ($ this ->memberNameCallback , $ memberNames );
8677 }
78+
79+ /**
80+ * @param $item
81+ * @return array
82+ * @throws BadRequestHttpException
83+ */
84+ protected function parseResource ($ item )
85+ {
86+ if (!$ type = ArrayHelper::getValue ($ item , 'type ' )) {
87+ if ($ this ->throwException ) {
88+ throw new BadRequestHttpException ('The resource object MUST contain at least a type member ' );
89+ }
90+ return [];
91+ }
92+ $ formName = $ this ->typeToFormName ($ type );
93+
94+ $ attributes = ArrayHelper::getValue ($ item , 'attributes ' , []);
95+ $ attributes = array_combine ($ this ->parseMemberNames (array_keys ($ attributes )), array_values ($ attributes ));
96+
97+ if ($ id = ArrayHelper::getValue ($ item , 'id ' )) {
98+ $ attributes ['id ' ] = $ id ;
99+ }
100+
101+ return [$ formName => $ attributes ];
102+ }
103+
104+ /**
105+ * @param array $relObjects
106+ * @return array
107+ */
108+ protected function parseRelationships (array $ relObjects = [])
109+ {
110+ $ relationships = [];
111+ foreach ($ relObjects as $ name => $ relationship ) {
112+ if (!$ relData = ArrayHelper::getValue ($ relationship , 'data ' )) {
113+ continue ;
114+ }
115+ if (!ArrayHelper::isIndexed ($ relData )) {
116+ $ relData = [$ relData ];
117+ }
118+ foreach ($ relData as $ identifier ) {
119+ if (isset ($ identifier ['type ' ]) && isset ($ identifier ['id ' ])) {
120+ $ formName = $ this ->typeToFormName ($ identifier ['type ' ]);
121+ $ relationships [$ name ][$ formName ][] = ['id ' => $ identifier ['id ' ]];
122+ }
123+ }
124+ }
125+ return $ relationships ;
126+ }
87127}
0 commit comments