Skip to content

Commit fce9c71

Browse files
Fix #2759
1 parent 9222ded commit fce9c71

File tree

9 files changed

+526
-114
lines changed

9 files changed

+526
-114
lines changed

features/bootstrap/DoctrineContext.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
declare(strict_types=1);
1313

14+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ExternalUser;
1415
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Address as AddressDocument;
1516
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Answer as AnswerDocument;
1617
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeItem as CompositeItemDocument;
@@ -81,6 +82,7 @@
8182
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FooDummy;
8283
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FourthLevel;
8384
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Greeting;
85+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\InternalUser;
8486
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy;
8587
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Node;
8688
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Order;
@@ -95,6 +97,7 @@
9597
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedToDummyFriend;
9698
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelationEmbedder;
9799
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\SecuredDummy;
100+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Site;
98101
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ThirdLevel;
99102
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User;
100103
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UuidIdentifierDummy;
@@ -165,6 +168,52 @@ public function thereAreDummyObjects(int $nb)
165168
$this->manager->flush();
166169
}
167170

171+
/**
172+
* @Given there are :nb sites with internal owner
173+
*/
174+
public function thereAreSitesWithInternalOwner(int $nb)
175+
{
176+
for ($i = 1; $i <= $nb; ++$i) {
177+
$internalUser = new InternalUser();
178+
$internalUser->setFirstname('Internal');
179+
$internalUser->setLastname('User');
180+
$internalUser->setEmail('[email protected]');
181+
$internalUser->setInternalId('INT');
182+
183+
$site = new Site();
184+
$site->setTitle('title');
185+
$site->setDescription('description');
186+
$site->setOwner($internalUser);
187+
188+
$this->manager->persist($site);
189+
}
190+
191+
$this->manager->flush();
192+
}
193+
194+
/**
195+
* @Given there are :nb sites with external owner
196+
*/
197+
public function thereAreSitesWithExternalOwner(int $nb)
198+
{
199+
for ($i = 1; $i <= $nb; ++$i) {
200+
$externalUser = new ExternalUser();
201+
$externalUser->setFirstname('External');
202+
$externalUser->setLastname('User');
203+
$externalUser->setEmail('[email protected]');
204+
$externalUser->setExternalId('EXT');
205+
206+
$site = new Site();
207+
$site->setTitle('title');
208+
$site->setDescription('description');
209+
$site->setOwner($externalUser);
210+
211+
$this->manager->persist($site);
212+
}
213+
214+
$this->manager->flush();
215+
}
216+
168217
/**
169218
* @Given there are :nb foo objects with fake names
170219
*/

features/graphql/non_resource.feature

Lines changed: 0 additions & 92 deletions
This file was deleted.

features/main/table_inheritance.feature

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,155 @@ Feature: Table inheritance
350350
}
351351
}
352352
"""
353+
354+
@createSchema
355+
Scenario: Create a table inherited resource
356+
When I add "Content-Type" header equal to "application/ld+json"
357+
And I send a "POST" request to "/dummy_table_inheritance_children" with body:
358+
"""
359+
{"name": "foo", "nickname": "bar"}
360+
"""
361+
Then the response status code should be 201
362+
And the response should be in JSON
363+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
364+
And the JSON should be valid according to this schema:
365+
"""
366+
{
367+
"type": "object",
368+
"properties": {
369+
"@type": {
370+
"type": "string",
371+
"pattern": "^DummyTableInheritanceChild$"
372+
},
373+
"@context": {
374+
"type": "string",
375+
"pattern": "^/contexts/DummyTableInheritanceChild$"
376+
},
377+
"@id": {
378+
"type": "string",
379+
"pattern": "^/dummy_table_inheritance_children/1$"
380+
},
381+
"name": {
382+
"type": "string",
383+
"pattern": "^foo$",
384+
"required": "true"
385+
},
386+
"nickname": {
387+
"type": "string",
388+
"pattern": "^bar$",
389+
"required": "true"
390+
}
391+
}
392+
}
393+
"""
394+
395+
@createSchema
396+
@dropSchema
397+
Scenario: Generate iri from parent resource
398+
Given there are 3 sites with internal owner
399+
When I add "Content-Type" header equal to "application/ld+json"
400+
And I send a "GET" request to "/sites"
401+
Then the response status code should be 200
402+
And the response should be in JSON
403+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
404+
And the JSON should be valid according to this schema:
405+
"""
406+
{
407+
"type": "object",
408+
"properties": {
409+
"hydra:member": {
410+
"type": "array",
411+
"items": {
412+
"type": "object",
413+
"properties": {
414+
"@type": {
415+
"type": "string",
416+
"pattern": "^Site$",
417+
"required": "true"
418+
},
419+
"@id": {
420+
"type": "string",
421+
"pattern": "^/sites/\\d+$",
422+
"required": "true"
423+
},
424+
"id": {
425+
"type": "integer",
426+
"required": "true"
427+
},
428+
"title": {
429+
"type": "string",
430+
"required": "true"
431+
},
432+
"description": {
433+
"type": "string",
434+
"required": "true"
435+
},
436+
"owner": {
437+
"type": "string",
438+
"pattern": "^/users/\\d+$",
439+
"required": "true"
440+
}
441+
}
442+
},
443+
"minItems": 3,
444+
"maxItems": 3,
445+
"required": "true"
446+
}
447+
}
448+
}
449+
"""
450+
451+
@createSchema
452+
Scenario: Generate iri from current resource even if parent class is a resource
453+
Given there are 3 sites with external owner
454+
When I add "Content-Type" header equal to "application/ld+json"
455+
And I send a "GET" request to "/sites"
456+
Then the response status code should be 200
457+
And the response should be in JSON
458+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
459+
And the JSON should be valid according to this schema:
460+
"""
461+
{
462+
"type": "object",
463+
"properties": {
464+
"hydra:member": {
465+
"type": "array",
466+
"items": {
467+
"type": "object",
468+
"properties": {
469+
"@type": {
470+
"type": "string",
471+
"pattern": "^Site$",
472+
"required": "true"
473+
},
474+
"@id": {
475+
"type": "string",
476+
"pattern": "^/sites/\\d+$",
477+
"required": "true"
478+
},
479+
"id": {
480+
"type": "integer",
481+
"required": "true"
482+
},
483+
"title": {
484+
"type": "string",
485+
"required": "true"
486+
},
487+
"description": {
488+
"type": "string",
489+
"required": "true"
490+
},
491+
"owner": {
492+
"type": "string",
493+
"pattern": "^/external_users/\\d+$",
494+
"required": "true"
495+
}
496+
}
497+
},
498+
"minItems": 3,
499+
"maxItems": 3,
500+
"required": "true"
501+
}
502+
}
503+
}
504+
"""

src/Bridge/Symfony/Routing/RouteNameResolver.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function getRouteName(string $resourceClass, $operationType /*, array $co
4545

4646
$operationType = OperationTypeDeprecationHelper::getOperationType($operationType);
4747

48+
// Try with strict class name
4849
foreach ($this->router->getRouteCollection()->all() as $routeName => $route) {
4950
$currentResourceClass = $route->getDefault('_api_resource_class');
5051
$operation = $route->getDefault(sprintf('_api_%s_operation_name', $operationType));
@@ -59,6 +60,21 @@ public function getRouteName(string $resourceClass, $operationType /*, array $co
5960
}
6061
}
6162

63+
// Maybe the parent class is a resource
64+
foreach ($this->router->getRouteCollection()->all() as $routeName => $route) {
65+
$currentResourceClass = $route->getDefault('_api_resource_class');
66+
$operation = $route->getDefault(sprintf('_api_%s_operation_name', $operationType));
67+
$methods = $route->getMethods();
68+
69+
if (null !== $currentResourceClass && is_a($resourceClass, $currentResourceClass, true) && null !== $operation && (empty($methods) || \in_array('GET', $methods, true))) {
70+
if (OperationType::SUBRESOURCE === $operationType && false === $this->isSameSubresource($context, $route->getDefault('_api_subresource_context'))) {
71+
continue;
72+
}
73+
74+
return $routeName;
75+
}
76+
}
77+
6278
throw new InvalidArgumentException(sprintf('No %s route associated with the type "%s".', $operationType, $resourceClass));
6379
}
6480

0 commit comments

Comments
 (0)