Skip to content

Commit 4fe81e4

Browse files
Nightbrabluchet
authored and
abluchet
committed
added maxDepth to ApiSubresource
1 parent 23c66aa commit 4fe81e4

File tree

8 files changed

+78
-6
lines changed

8 files changed

+78
-6
lines changed

src/Annotation/ApiSubresource.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@
2323
*/
2424
final class ApiSubresource
2525
{
26+
/**
27+
* @var int
28+
*/
29+
public $maxDepth;
2630
}

src/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ private function updateMetadata(ApiSubresource $annotation, PropertyMetadata $pr
8282
$type = $propertyMetadata->getType();
8383
$isCollection = $type->isCollection();
8484
$resourceClass = $isCollection ? $type->getCollectionValueType()->getClassName() : $type->getClassName();
85+
$maxDepth = $annotation->maxDepth ? $annotation->maxDepth : null;
8586

86-
return $propertyMetadata->withSubresource(new SubresourceMetadata($resourceClass, $isCollection));
87+
return $propertyMetadata->withSubresource(new SubresourceMetadata($resourceClass, $isCollection, $maxDepth));
8788
}
8889
}

src/Metadata/Property/SubresourceMetadata.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ final class SubresourceMetadata
2222
{
2323
private $resourceClass;
2424
private $collection;
25+
private $maxDepth;
2526

26-
public function __construct(string $resourceClass, bool $collection = false)
27+
public function __construct(string $resourceClass, bool $collection = false, int $maxDepth = null)
2728
{
2829
$this->resourceClass = $resourceClass;
2930
$this->collection = $collection;
31+
$this->maxDepth = $maxDepth;
3032
}
3133

3234
public function getResourceClass(): string
@@ -54,4 +56,12 @@ public function withCollection(bool $collection): self
5456

5557
return $metadata;
5658
}
59+
60+
/**
61+
* @return int
62+
*/
63+
public function getMaxDepth()
64+
{
65+
return $this->maxDepth;
66+
}
5767
}

src/Metadata/schema/metadata.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
<xsd:complexType name="subresource" mixed="true">
8181
<xsd:attribute type="xsd:boolean" name="collection"/>
8282
<xsd:attribute type="xsd:string" name="resourceClass"/>
83+
<xsd:attribute type="xsd:integer" name="maxDepth"/>
8384
</xsd:complexType>
8485

8586
<xsd:complexType name="property">

src/Operation/Factory/SubresourceOperationFactory.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ public function create(string $resourceClass): array
6060
* @param string $rootResourceClass null on the first iteration, it then keeps track of the origin resource class
6161
* @param array $parentOperation the previous call operation
6262
* @param array $visited
63+
* @param int $depth the number of visited
64+
* @param int $maxDepth
6365
*/
64-
private function computeSubresourceOperations(string $resourceClass, array &$tree, string $rootResourceClass = null, array $parentOperation = null, array $visited = [])
66+
private function computeSubresourceOperations(string $resourceClass, array &$tree, string $rootResourceClass = null, array $parentOperation = null, array $visited = [], int $depth = 0, int $maxDepth = null)
6567
{
6668
if (null === $rootResourceClass) {
6769
$rootResourceClass = $resourceClass;
@@ -79,6 +81,15 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
7981
$subresourceMetadata = $this->resourceMetadataFactory->create($subresourceClass);
8082

8183
$visiting = "$resourceClass $property $subresourceClass";
84+
85+
// Handle maxDepth
86+
if ($rootResourceClass === $resourceClass) {
87+
$maxDepth = $subresource->getMaxDepth();
88+
}
89+
90+
if(null !== $maxDepth && $depth >= $maxDepth) {
91+
continue;
92+
}
8293
if (isset($visited[$visiting])) {
8394
continue;
8495
}
@@ -154,7 +165,7 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
154165

155166
$tree[$operation['route_name']] = $operation;
156167

157-
$this->computeSubresourceOperations($subresourceClass, $tree, $rootResourceClass, $operation, $visited + [$visiting => true]);
168+
$this->computeSubresourceOperations($subresourceClass, $tree, $rootResourceClass, $operation, $visited + [$visiting => true], ++$depth, $maxDepth);
158169
}
159170
}
160171
}

tests/Fixtures/FileConfigurations/resources.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
writableLink="false"
5555
required="true"
5656
>
57-
<subresource collection="true" resourceClass="Foo" />
57+
<subresource collection="true" resourceClass="Foo" maxDepth="1" />
5858
<attribute name="foo">
5959
<attribute>Foo</attribute>
6060
</attribute>

tests/Fixtures/FileConfigurations/resources.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ resources:
2828
iri: 'someirischema'
2929
properties:
3030
'foo':
31-
subresource: {collection: true, resourceClass: 'Foo'}
31+
subresource: {collection: true, resourceClass: 'Foo', maxDepth: 1}
3232
description: 'The dummy foo'
3333
readable: true
3434
writable: true

tests/Operation/Factory/SubresourceOperationFactoryTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,49 @@ public function testCreateByOverriding()
259259
] + SubresourceOperationFactory::ROUTE_OPTIONS,
260260
], $subresourceOperationFactory->create(DummyEntity::class));
261261
}
262+
263+
public function testCreateWithMaxDepth()
264+
{
265+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
266+
$resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity'));
267+
$resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity'));
268+
269+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
270+
$propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource']));
271+
$propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource']));
272+
273+
$subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1));
274+
$anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false));
275+
276+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
277+
$propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource')->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth);
278+
$propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar')->shouldBeCalled()->willReturn(new PropertyMetadata());
279+
$propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource')->shouldBeCalled()->willReturn($anotherSubresourceMetadata);
280+
281+
$pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class);
282+
$pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity', true)->shouldBeCalled()->willReturn('dummy_entities');
283+
$pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource');
284+
285+
$subresourceOperationFactory = new SubresourceOperationFactory(
286+
$resourceMetadataFactoryProphecy->reveal(),
287+
$propertyNameCollectionFactoryProphecy->reveal(),
288+
$propertyMetadataFactoryProphecy->reveal(),
289+
$pathSegmentNameGeneratorProphecy->reveal()
290+
);
291+
292+
$this->assertEquals([
293+
'api_dummy_entities_subresource_get_subresource' => [
294+
'property' => 'subresource',
295+
'collection' => false,
296+
'resource_class' => RelatedDummyEntity::class,
297+
'shortNames' => ['relatedDummyEntity', 'dummyEntity'],
298+
'identifiers' => [
299+
['id', DummyEntity::class, true],
300+
],
301+
'route_name' => 'api_dummy_entities_subresource_get_subresource',
302+
'path' => '/dummy_entities/{id}/subresource.{_format}',
303+
'operation_name' => 'subresource_get_subresource',
304+
] + SubresourceOperationFactory::ROUTE_OPTIONS
305+
], $subresourceOperationFactory->create(DummyEntity::class));
306+
}
262307
}

0 commit comments

Comments
 (0)