@@ -391,6 +391,120 @@ public function testCreateWithMaxDepthMultipleSubresources()
391
391
], $ subresourceOperationFactory ->create (DummyEntity::class));
392
392
}
393
393
394
+ /**
395
+ * Test for issue: https://github.com/api-platform/core/issues/2103.
396
+ */
397
+ public function testCreateWithMaxDepthMultipleSubresourcesSameMaxDepth ()
398
+ {
399
+ /**
400
+ * DummyEntity -subresource (maxDepth=1)-> RelatedDummyEntity -anotherSubresource-> DummyEntity
401
+ * DummyEntity -secondSubresource (maxDepth=1)-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity.
402
+ */
403
+ $ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
404
+ $ resourceMetadataFactoryProphecy ->create (DummyEntity::class)->shouldBeCalled ()->willReturn (new ResourceMetadata ('dummyEntity ' ));
405
+ $ resourceMetadataFactoryProphecy ->create (RelatedDummyEntity::class)->shouldBeCalled ()->willReturn (new ResourceMetadata ('relatedDummyEntity ' ));
406
+ $ resourceMetadataFactoryProphecy ->create (DummyValidatedEntity::class)->shouldBeCalled ()->willReturn (new ResourceMetadata ('dummyValidatedEntity ' ));
407
+
408
+ $ propertyNameCollectionFactoryProphecy = $ this ->prophesize (PropertyNameCollectionFactoryInterface::class);
409
+ $ propertyNameCollectionFactoryProphecy ->create (DummyEntity::class)->shouldBeCalled ()->willReturn (new PropertyNameCollection (['subresource ' , 'secondSubresource ' ]));
410
+ $ propertyNameCollectionFactoryProphecy ->create (RelatedDummyEntity::class)->shouldBeCalled ()->willReturn (new PropertyNameCollection (['bar ' , 'anotherSubresource ' ]));
411
+ $ propertyNameCollectionFactoryProphecy ->create (DummyValidatedEntity::class)->shouldBeCalled ()->willReturn (new PropertyNameCollection (['moreSubresource ' ]));
412
+
413
+ $ subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata ())->withSubresource (new SubresourceMetadata (RelatedDummyEntity::class, false , 1 ));
414
+ $ secondSubresourceMetadata = (new PropertyMetadata ())->withSubresource (new SubresourceMetadata (DummyValidatedEntity::class, false , 1 ));
415
+ $ anotherSubresourceMetadata = (new PropertyMetadata ())->withSubresource (new SubresourceMetadata (DummyEntity::class, false ));
416
+ $ moreSubresourceMetadata = (new PropertyMetadata ())->withSubresource (new SubresourceMetadata (RelatedDummyEntity::class, false ));
417
+
418
+ $ propertyMetadataFactoryProphecy = $ this ->prophesize (PropertyMetadataFactoryInterface::class);
419
+ $ propertyMetadataFactoryProphecy ->create (DummyEntity::class, 'subresource ' )->shouldBeCalled ()->willReturn ($ subresourceMetadataCollectionWithMaxDepth );
420
+ $ propertyMetadataFactoryProphecy ->create (DummyEntity::class, 'secondSubresource ' )->shouldBeCalled ()->willReturn ($ secondSubresourceMetadata );
421
+ $ propertyMetadataFactoryProphecy ->create (RelatedDummyEntity::class, 'bar ' )->shouldBeCalled ()->willReturn (new PropertyMetadata ());
422
+ $ propertyMetadataFactoryProphecy ->create (RelatedDummyEntity::class, 'anotherSubresource ' )->shouldBeCalled ()->willReturn ($ anotherSubresourceMetadata );
423
+ $ propertyMetadataFactoryProphecy ->create (DummyValidatedEntity::class, 'moreSubresource ' )->shouldBeCalled ()->willReturn ($ moreSubresourceMetadata );
424
+
425
+ $ pathSegmentNameGeneratorProphecy = $ this ->prophesize (PathSegmentNameGeneratorInterface::class);
426
+ $ pathSegmentNameGeneratorProphecy ->getSegmentName ('dummyEntity ' , true )->shouldBeCalled ()->willReturn ('dummy_entities ' );
427
+ $ pathSegmentNameGeneratorProphecy ->getSegmentName ('subresource ' , false )->shouldBeCalled ()->willReturn ('subresources ' );
428
+ $ pathSegmentNameGeneratorProphecy ->getSegmentName ('secondSubresource ' , false )->shouldBeCalled ()->willReturn ('second_subresources ' );
429
+
430
+ $ subresourceOperationFactory = new SubresourceOperationFactory (
431
+ $ resourceMetadataFactoryProphecy ->reveal (),
432
+ $ propertyNameCollectionFactoryProphecy ->reveal (),
433
+ $ propertyMetadataFactoryProphecy ->reveal (),
434
+ $ pathSegmentNameGeneratorProphecy ->reveal ()
435
+ );
436
+
437
+ $ this ->assertEquals ([
438
+ 'api_dummy_entities_subresource_get_subresource ' => [
439
+ 'property ' => 'subresource ' ,
440
+ 'collection ' => false ,
441
+ 'resource_class ' => RelatedDummyEntity::class,
442
+ 'shortNames ' => ['relatedDummyEntity ' , 'dummyEntity ' ],
443
+ 'identifiers ' => [
444
+ ['id ' , DummyEntity::class, true ],
445
+ ],
446
+ 'route_name ' => 'api_dummy_entities_subresource_get_subresource ' ,
447
+ 'path ' => '/dummy_entities/{id}/subresources.{_format} ' ,
448
+ 'operation_name ' => 'subresource_get_subresource ' ,
449
+ ] + SubresourceOperationFactory::ROUTE_OPTIONS ,
450
+ 'api_dummy_entities_second_subresource_get_subresource ' => [
451
+ 'property ' => 'secondSubresource ' ,
452
+ 'collection ' => false ,
453
+ 'resource_class ' => DummyValidatedEntity::class,
454
+ 'shortNames ' => ['dummyValidatedEntity ' , 'dummyEntity ' ],
455
+ 'identifiers ' => [
456
+ ['id ' , DummyEntity::class, true ],
457
+ ],
458
+ 'route_name ' => 'api_dummy_entities_second_subresource_get_subresource ' ,
459
+ 'path ' => '/dummy_entities/{id}/second_subresources.{_format} ' ,
460
+ 'operation_name ' => 'second_subresource_get_subresource ' ,
461
+ ] + SubresourceOperationFactory::ROUTE_OPTIONS ,
462
+ ], $ subresourceOperationFactory ->create (DummyEntity::class));
463
+ }
464
+
465
+ public function testCreateSelfReferencingSubresources ()
466
+ {
467
+ /**
468
+ * DummyEntity -subresource-> DummyEntity -subresource-> DummyEntity ...
469
+ */
470
+ $ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
471
+ $ resourceMetadataFactoryProphecy ->create (DummyEntity::class)->shouldBeCalled ()->willReturn (new ResourceMetadata ('dummyEntity ' ));
472
+
473
+ $ propertyNameCollectionFactoryProphecy = $ this ->prophesize (PropertyNameCollectionFactoryInterface::class);
474
+ $ propertyNameCollectionFactoryProphecy ->create (DummyEntity::class)->shouldBeCalled ()->willReturn (new PropertyNameCollection (['subresource ' ]));
475
+
476
+ $ subresource = (new PropertyMetadata ())->withSubresource (new SubresourceMetadata (DummyEntity::class, false ));
477
+
478
+ $ propertyMetadataFactoryProphecy = $ this ->prophesize (PropertyMetadataFactoryInterface::class);
479
+ $ propertyMetadataFactoryProphecy ->create (DummyEntity::class, 'subresource ' )->shouldBeCalled ()->willReturn ($ subresource );
480
+
481
+ $ pathSegmentNameGeneratorProphecy = $ this ->prophesize (PathSegmentNameGeneratorInterface::class);
482
+ $ pathSegmentNameGeneratorProphecy ->getSegmentName ('dummyEntity ' , true )->shouldBeCalled ()->willReturn ('dummy_entities ' );
483
+ $ pathSegmentNameGeneratorProphecy ->getSegmentName ('subresource ' , false )->shouldBeCalled ()->willReturn ('subresources ' );
484
+
485
+ $ subresourceOperationFactory = new SubresourceOperationFactory (
486
+ $ resourceMetadataFactoryProphecy ->reveal (),
487
+ $ propertyNameCollectionFactoryProphecy ->reveal (),
488
+ $ propertyMetadataFactoryProphecy ->reveal (),
489
+ $ pathSegmentNameGeneratorProphecy ->reveal ()
490
+ );
491
+
492
+ $ this ->assertEquals ([
493
+ 'api_dummy_entities_subresource_get_subresource ' => [
494
+ 'property ' => 'subresource ' ,
495
+ 'collection ' => false ,
496
+ 'resource_class ' => DummyEntity::class,
497
+ 'shortNames ' => ['dummyEntity ' ],
498
+ 'identifiers ' => [
499
+ ['id ' , DummyEntity::class, true ],
500
+ ],
501
+ 'route_name ' => 'api_dummy_entities_subresource_get_subresource ' ,
502
+ 'path ' => '/dummy_entities/{id}/subresources.{_format} ' ,
503
+ 'operation_name ' => 'subresource_get_subresource ' ,
504
+ ] + SubresourceOperationFactory::ROUTE_OPTIONS ,
505
+ ], $ subresourceOperationFactory ->create (DummyEntity::class));
506
+ }
507
+
394
508
public function testCreateWithEnd ()
395
509
{
396
510
$ resourceMetadataFactoryProphecy = $ this ->prophesize (ResourceMetadataFactoryInterface::class);
0 commit comments