Skip to content

Commit 3d0b509

Browse files
committed
Fix finding resource when creating polymorphic relationship
Previously the relationship's collection was responsible for finding the resource by ID, but this discarded the provided type information. Now the resource itself is responsible for finding the resource, and the collection merely specifies which resources are allowed in the relationship. Fixes #93
1 parent bf7b14b commit 3d0b509

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

src/Schema/Field/Relationship.php

+10-10
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,18 @@ protected function findResourceForIdentifier(array $identifier, Context $context
7474
throw new BadRequestException('id not specified');
7575
}
7676

77-
$collections = array_map(
78-
fn($collection) => $context->api->getCollection($collection),
79-
$this->collections,
77+
$resources = array_merge(
78+
...array_map(
79+
fn($collection) => $context->api->getCollection($collection)->resources(),
80+
$this->collections,
81+
),
8082
);
8183

82-
foreach ($collections as $collection) {
83-
if (in_array($identifier['type'], $collection->resources())) {
84-
return $this->findResource(
85-
$context->withCollection($collection),
86-
$identifier['id'],
87-
);
88-
}
84+
if (in_array($identifier['type'], $resources)) {
85+
return $this->findResource(
86+
$context->withCollection($context->resource($identifier['type'])),
87+
$identifier['id'],
88+
);
8989
}
9090

9191
throw (new BadRequestException("type [{$identifier['type']}] not allowed"))->setSource([

tests/feature/RelationshipToOneTest.php

+44-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
namespace Tobyz\Tests\JsonApiServer\feature;
44

5-
use stdClass;
65
use Tobyz\JsonApiServer\Endpoint\Create;
76
use Tobyz\JsonApiServer\Endpoint\Show;
87
use Tobyz\JsonApiServer\Exception\BadRequestException;
98
use Tobyz\JsonApiServer\Exception\UnprocessableEntityException;
109
use Tobyz\JsonApiServer\JsonApi;
1110
use Tobyz\JsonApiServer\Schema\Field\ToOne;
1211
use Tobyz\Tests\JsonApiServer\AbstractTestCase;
12+
use Tobyz\Tests\JsonApiServer\MockCollection;
1313
use Tobyz\Tests\JsonApiServer\MockResource;
1414

1515
class RelationshipToOneTest extends AbstractTestCase
@@ -213,16 +213,18 @@ public function test_to_one_create_invalid_type()
213213

214214
public function test_to_one_create_polymorphic()
215215
{
216-
$this->api->resource(new MockResource('animals', models: [(object) ['id' => '1']]));
216+
$this->api->resource(
217+
new MockResource('animals', models: [($friend = (object) ['id' => '1'])]),
218+
);
217219

218220
$this->api->resource(
219-
new MockResource(
221+
$resource = new MockResource(
220222
'users',
221223
models: [(object) ['id' => '1']],
222224
endpoints: [Create::make()],
223225
fields: [
224226
ToOne::make('friend')
225-
->type(['users', stdClass::class => 'animals'])
227+
->type(['users', 'animals'])
226228
->writable(),
227229
],
228230
),
@@ -238,6 +240,44 @@ public function test_to_one_create_polymorphic()
238240
);
239241

240242
$this->assertEquals(201, $response->getStatusCode());
243+
$this->assertSame($friend, $resource->models[1]->friend);
244+
}
245+
246+
public function test_to_one_create_collection()
247+
{
248+
$this->api->collection(
249+
new MockCollection('animals', [
250+
'dogs' => [(object) ['id' => '1']],
251+
'cats' => [($cat = (object) ['id' => '1'])],
252+
]),
253+
);
254+
255+
$this->api->resource(new MockResource('cats', models: [$cat]));
256+
257+
$this->api->resource(
258+
$resource = new MockResource(
259+
'users',
260+
models: [(object) ['id' => '1']],
261+
endpoints: [Create::make()],
262+
fields: [
263+
ToOne::make('pet')
264+
->collection('animals')
265+
->writable(),
266+
],
267+
),
268+
);
269+
270+
$response = $this->api->handle(
271+
$this->buildRequest('POST', '/users')->withParsedBody([
272+
'data' => [
273+
'type' => 'users',
274+
'relationships' => ['pet' => ['data' => ['type' => 'cats', 'id' => '1']]],
275+
],
276+
]),
277+
);
278+
279+
$this->assertEquals(201, $response->getStatusCode());
280+
$this->assertSame($cat, $resource->models[1]->pet);
241281
}
242282

243283
public function test_to_one_create_null_not_nullable()

0 commit comments

Comments
 (0)