Skip to content

Commit 84f063a

Browse files
committed
remove full linkage for post requests
1 parent ca2f85f commit 84f063a

File tree

6 files changed

+54
-59
lines changed

6 files changed

+54
-59
lines changed

src/ResourceInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ public function getResourceAttributes(array $fields = []);
1919

2020
/**
2121
* The "relationships" member of the resource object describing relationships between the resource and other JSON API resources.
22-
* @param null|array $linked specific resource linkage that a client has requested.
22+
* @param array $linked specific resource linkage that a client has requested.
2323
* @return ResourceIdentifierInterface[] represent references from the resource object in which it’s defined to other resource objects.
2424
*/
25-
public function getResourceRelationships(array $linked = null);
25+
public function getResourceRelationships(array $linked = []);
2626

2727
public function setResourceRelationship($name, $relationship);
2828

src/ResourceTrait.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,18 @@ public function getResourceAttributes(array $fields = [])
5151
}
5252

5353
/**
54-
* @param null|array $linked
54+
* @param array $linked
5555
* @return array
5656
*/
57-
public function getResourceRelationships(array $linked = null)
57+
public function getResourceRelationships(array $linked = [])
5858
{
5959
$fields = [];
6060
if ($this instanceof Arrayable) {
6161
$fields = $this->extraFields();
6262
}
6363
$resolvedFields = $this->resolveFields($fields);
6464
$keys = array_keys($resolvedFields);
65-
if ($linked === null) {
66-
$linked = $keys;
67-
}
65+
6866
$relationships = array_fill_keys($keys, null);
6967
$linkedFields = array_intersect($keys, $linked);
7068

src/Serializer.php

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,31 @@ public function serialize($data)
102102
}
103103

104104
/**
105+
* @param array $included
105106
* @param ResourceInterface $model
106107
* @return array
107108
*/
108-
protected function serializeModel(ResourceInterface $model, array $included = null)
109+
protected function serializeModel(ResourceInterface $model, array $included = [])
109110
{
110111
$fields = $this->getRequestedFields();
111112
$type = $this->pluralize ? Inflector::pluralize($model->getType()) : $model->getType();
112113
$fields = isset($fields[$type]) ? $fields[$type] : [];
113114

115+
$topLevel = array_map(function($item) {
116+
if (($pos = strrpos($item, '.')) !== false) {
117+
return substr($item, 0, $pos);
118+
}
119+
return $item;
120+
}, $included);
121+
114122
$attributes = $model->getResourceAttributes($fields);
115123
$attributes = array_combine($this->prepareMemberNames(array_keys($attributes)), array_values($attributes));
116124

117125
$data = array_merge($this->serializeIdentifier($model), [
118126
'attributes' => $attributes,
119127
]);
120128

121-
$relationships = $model->getResourceRelationships($included);
129+
$relationships = $model->getResourceRelationships($topLevel);
122130
if (!empty($relationships)) {
123131
foreach ($relationships as $name => $items) {
124132
$relationship = [];
@@ -161,19 +169,9 @@ protected function serializeResource(ResourceInterface $resource)
161169
if ($this->request->getIsHead()) {
162170
return null;
163171
} else {
164-
$included = $topLevel = $this->getIncluded();
165-
166-
if ($included !== null) {
167-
$topLevel = array_map(function($item) {
168-
if (($pos = strrpos($item, '.')) !== false) {
169-
return substr($item, 0, $pos);
170-
}
171-
return $item;
172-
}, $included);
173-
}
174-
172+
$included = $this->getIncluded();
175173
$data = [
176-
'data' => $this->serializeModel($resource, $topLevel)
174+
'data' => $this->serializeModel($resource, $included)
177175
];
178176

179177
$relatedResources = $this->serializeIncluded($resource, $included);
@@ -210,37 +208,31 @@ protected function serializeIdentifier(ResourceIdentifierInterface $identifier)
210208

211209
/**
212210
* @param ResourceInterface|array $resources
213-
* @param null|array $included
211+
* @param array $included
212+
* @param true $assoc
214213
* @return array
215214
*/
216-
protected function serializeIncluded($resources, array $included = null)
215+
protected function serializeIncluded($resources, array $included = [], $assoc = false)
217216
{
218217
$resources = is_array($resources) ? $resources : [$resources];
219218
$data = [];
220219

221-
if ($included === null) {
222-
return [];
223-
}
224-
225220
$inclusion = [];
226-
$linked = [];
227221
foreach ($included as $path) {
228222
if (($pos = strrpos($path, '.')) === false) {
229-
$linked[] = $path;
230223
$inclusion[$path] = [];
231224
continue;
232225
}
233226
$name = substr($path, $pos + 1);
234227
$key = substr($path, 0, $pos);
235228
$inclusion[$key][] = $name;
236-
$linked[] = $key;
237229
}
238230

239231
foreach ($resources as $resource) {
240232
if (!$resource instanceof ResourceInterface) {
241233
continue;
242234
}
243-
$relationships = $resource->getResourceRelationships($linked);
235+
$relationships = $resource->getResourceRelationships(array_keys($inclusion));
244236
foreach ($relationships as $name => $relationship) {
245237
if ($relationship === null) {
246238
continue;
@@ -249,18 +241,21 @@ protected function serializeIncluded($resources, array $included = null)
249241
$relationship = [$relationship];
250242
}
251243
foreach ($relationship as $model) {
252-
if ($model instanceof ResourceInterface) {
253-
$uniqueKey = $model->getType() . '/' . $model->getId();
244+
if (!$model instanceof ResourceInterface) {
245+
continue;
246+
}
247+
$uniqueKey = $model->getType() . '/' . $model->getId();
248+
if (!isset($data[$uniqueKey])) {
254249
$data[$uniqueKey] = $this->serializeModel($model, $inclusion[$name]);
255-
if (!empty($inclusion[$name])) {
256-
$data = array_merge($data, $this->serializeIncluded($model, $inclusion[$name]));
257-
}
250+
}
251+
if (!empty($inclusion[$name])) {
252+
$data = array_merge($data, $this->serializeIncluded($model, $inclusion[$name], true));
258253
}
259254
}
260255
}
261256
}
262257

263-
return array_values($data);
258+
return $assoc ? $data : array_values($data);
264259
}
265260

266261
/**
@@ -359,9 +354,6 @@ protected function getRequestedFields()
359354
protected function getIncluded()
360355
{
361356
$include = $this->request->get($this->expandParam);
362-
if (!$this->request->isGet) {
363-
return null;
364-
}
365357
return is_string($include) ? array_map($this->formatMemberName, preg_split('/\s*,\s*/', $include, -1, PREG_SPLIT_NO_EMPTY)) : [];
366358
}
367359

tests/SerializerTest.php

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,28 @@ public function testSerializeModelData()
8181
'related' => ['href' => 'http://example.com/resource/123/extra-field1'],
8282
]
8383
];
84-
$expected = [
85-
'data' => [
86-
'id' => '123',
87-
'type' => 'resource-models',
88-
'attributes' => [
89-
'first-name' => 'Bob',
90-
],
91-
'relationships' => [
92-
'extra-field1' => [
93-
'links' => $relationship['links']
94-
]
95-
],
96-
'links' => [
97-
'self' => ['href' => 'http://example.com/resource/123']
84+
$resource = [
85+
'id' => '123',
86+
'type' => 'resource-models',
87+
'attributes' => [
88+
'first-name' => 'Bob',
89+
],
90+
'relationships' => [
91+
'extra-field1' => [
92+
'links' => $relationship['links']
9893
]
94+
],
95+
'links' => [
96+
'self' => ['href' => 'http://example.com/resource/123']
9997
]
10098
];
99+
$expected = [
100+
'data' => $resource
101+
];
101102
$this->assertSame($expected, $serializer->serialize($model));
102103
$_POST[$serializer->request->methodParam] = 'POST';
104+
\Yii::$app->request->setQueryParams(['include' => 'extra-field1']);
105+
$expected['included'][] = $resource;
103106
$expected['data']['relationships']['extra-field1'] = $relationship;
104107
$this->assertSame($expected, $serializer->serialize($model));
105108
}
@@ -264,10 +267,12 @@ public function testIncludedDuplicates()
264267
$model = new ResourceModel();
265268
ResourceModel::$fields = ['field1', 'field2'];
266269
ResourceModel::$extraFields = ['extraField1', 'extraField2'];
270+
$relationship = new ResourceModel();
271+
$relationship->extraField1 = new ResourceModel();
272+
$model->extraField2 = $relationship;
267273
$model->extraField1 = new ResourceModel();
268-
$model->extraField2 = new ResourceModel();
269274

270-
\Yii::$app->request->setQueryParams(['include' => 'extra-field1,extra-field2']);
275+
\Yii::$app->request->setQueryParams(['include' => 'extra-field1,extra-field2.extra-field1']);
271276
$this->assertSame([
272277
'data' => $compoundModel,
273278
'included' => [
@@ -280,7 +285,7 @@ public function testIncludedDuplicates()
280285
$includedModel
281286
],
282287
'links' => [
283-
'self' => ['href' => '/index.php?r=&include=extra-field1%2Cextra-field2&page=1']
288+
'self' => ['href' => '/index.php?r=&include=extra-field1%2Cextra-field2.extra-field1&page=1']
284289
],
285290
'meta' => [
286291
'total-count' => 1,

tests/actions/CreateActionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function testSuccess()
4444

4545
$this->assertInstanceOf(ResourceModel::className(), $model = $action->run());
4646
$this->assertFalse($model->hasErrors());
47-
$relationships = $model->getResourceRelationships();
47+
$relationships = $model->getResourceRelationships(['extra_field1']);
4848
$this->assertArrayHasKey('extra_field1', $relationships);
4949
$this->assertInstanceOf(ResourceModel::className(), $relationships['extra_field1']);
5050
$this->assertEquals(124, $relationships['extra_field1']->id);

tests/actions/UpdateActionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function testSuccess()
4949
$this->assertInstanceOf(ResourceModel::className(), $model = $action->run(1));
5050
$this->assertFalse($model->hasErrors());
5151
$this->assertEquals('test', $model->field1);
52-
$relationships = $model->getResourceRelationships();
52+
$relationships = $model->getResourceRelationships(['extra_field1']);
5353
$this->assertArrayHasKey('extra_field1', $relationships);
5454
$this->assertInstanceOf(ResourceModel::className(), $relationships['extra_field1']);
5555
$this->assertEquals(124, $relationships['extra_field1']->id);

0 commit comments

Comments
 (0)