Skip to content

Commit b244ef4

Browse files
authored
Merge pull request #2586 from soyuka/fix-es-per-operation
Attribute to allow disabling elasticsearch
2 parents 526de3e + c51d911 commit b244ef4

File tree

6 files changed

+79
-8
lines changed

6 files changed

+79
-8
lines changed

src/Annotation/ApiResource.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* @Attribute("denormalizationContext", type="array"),
3232
* @Attribute("deprecationReason", type="string"),
3333
* @Attribute("description", type="string"),
34+
* @Attribute("elasticsearch", type="bool"),
3435
* @Attribute("fetchPartial", type="bool"),
3536
* @Attribute("forceEager", type="bool"),
3637
* @Attribute("formats", type="array"),
@@ -136,6 +137,13 @@ final class ApiResource
136137
*/
137138
private $deprecationReason;
138139

140+
/**
141+
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112
142+
*
143+
* @var bool
144+
*/
145+
private $elasticsearch;
146+
139147
/**
140148
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112
141149
*

src/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
2222
use ApiPlatform\Core\DataProvider\Pagination;
2323
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
24+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
25+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2426
use Elasticsearch\Client;
2527
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
2628

@@ -38,18 +40,20 @@ final class CollectionDataProvider implements ContextAwareCollectionDataProvider
3840
private $identifierExtractor;
3941
private $denormalizer;
4042
private $pagination;
43+
private $resourceMetadataFactory;
4144
private $collectionExtensions;
4245

4346
/**
4447
* @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions
4548
*/
46-
public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer, Pagination $pagination, iterable $collectionExtensions = [])
49+
public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer, Pagination $pagination, ResourceMetadataFactoryInterface $resourceMetadataFactory, iterable $collectionExtensions = [])
4750
{
4851
$this->client = $client;
4952
$this->documentMetadataFactory = $documentMetadataFactory;
5053
$this->identifierExtractor = $identifierExtractor;
5154
$this->denormalizer = $denormalizer;
5255
$this->pagination = $pagination;
56+
$this->resourceMetadataFactory = $resourceMetadataFactory;
5357
$this->collectionExtensions = $collectionExtensions;
5458
}
5559

@@ -58,6 +62,15 @@ public function __construct(Client $client, DocumentMetadataFactoryInterface $do
5862
*/
5963
public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool
6064
{
65+
try {
66+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
67+
if (false === $resourceMetadata->getCollectionOperationAttribute($operationName, 'elasticsearch', true, true)) {
68+
return false;
69+
}
70+
} catch (ResourceClassNotFoundException $e) {
71+
return false;
72+
}
73+
6174
try {
6275
$this->documentMetadataFactory->create($resourceClass);
6376
} catch (IndexNotFoundException $e) {

src/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer;
2121
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
2222
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
23+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
24+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2325
use Elasticsearch\Client;
2426
use Elasticsearch\Common\Exceptions\Missing404Exception;
2527
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
@@ -38,20 +40,31 @@ final class ItemDataProvider implements ItemDataProviderInterface, RestrictedDat
3840
private $documentMetadataFactory;
3941
private $identifierExtractor;
4042
private $denormalizer;
43+
private $resourceMetadataFactory;
4144

42-
public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer)
45+
public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer, ResourceMetadataFactoryInterface $resourceMetadataFactory)
4346
{
4447
$this->client = $client;
4548
$this->documentMetadataFactory = $documentMetadataFactory;
4649
$this->identifierExtractor = $identifierExtractor;
4750
$this->denormalizer = $denormalizer;
51+
$this->resourceMetadataFactory = $resourceMetadataFactory;
4852
}
4953

5054
/**
5155
* {@inheritdoc}
5256
*/
5357
public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool
5458
{
59+
try {
60+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
61+
if (false === $resourceMetadata->getItemOperationAttribute($operationName, 'elasticsearch', true, true)) {
62+
return false;
63+
}
64+
} catch (ResourceClassNotFoundException $e) {
65+
return false;
66+
}
67+
5568
try {
5669
$this->documentMetadataFactory->create($resourceClass);
5770
} catch (IndexNotFoundException $e) {

src/Bridge/Symfony/Bundle/Resources/config/elasticsearch.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
<argument type="service" id="api_platform.elasticsearch.metadata.document.metadata_factory" />
6666
<argument type="service" id="api_platform.elasticsearch.identifier_extractor" />
6767
<argument type="service" id="serializer" />
68+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
6869

6970
<tag name="api_platform.item_data_provider" priority="5" />
7071
</service>
@@ -75,6 +76,7 @@
7576
<argument type="service" id="api_platform.elasticsearch.identifier_extractor" />
7677
<argument type="service" id="serializer" />
7778
<argument type="service" id="api_platform.pagination" />
79+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
7880
<argument type="tagged" tag="api_platform.elasticsearch.request_body_search_extension.collection" />
7981

8082
<tag name="api_platform.collection_data_provider" priority="5" />

tests/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface;
2424
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
2525
use ApiPlatform\Core\DataProvider\Pagination;
26+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
2627
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2728
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
2829
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation;
2930
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
31+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar;
32+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCarColor;
3033
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo;
3134
use Elasticsearch\Client;
3235
use PHPUnit\Framework\TestCase;
@@ -44,7 +47,8 @@ public function testConstruct()
4447
$this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(),
4548
$this->prophesize(IdentifierExtractorInterface::class)->reveal(),
4649
$this->prophesize(DenormalizerInterface::class)->reveal(),
47-
new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal())
50+
new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()),
51+
$this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()
4852
)
4953
);
5054
}
@@ -60,17 +64,27 @@ public function testSupports()
6064
$identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled();
6165
$identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled();
6266

67+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
68+
$resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
69+
$resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false]));
70+
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
71+
$resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
72+
$resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException());
73+
6374
$collectionDataProvider = new CollectionDataProvider(
6475
$this->prophesize(Client::class)->reveal(),
6576
$documentMetadataFactoryProphecy->reveal(),
6677
$identifierExtractorProphecy->reveal(),
6778
$this->prophesize(DenormalizerInterface::class)->reveal(),
68-
new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal())
79+
new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()),
80+
$resourceMetadataFactoryProphecy->reveal()
6981
);
7082

7183
self::assertTrue($collectionDataProvider->supports(Foo::class));
7284
self::assertFalse($collectionDataProvider->supports(Dummy::class));
7385
self::assertFalse($collectionDataProvider->supports(CompositeRelation::class));
86+
self::assertFalse($collectionDataProvider->supports(DummyCar::class));
87+
self::assertFalse($collectionDataProvider->supports(DummyCarColor::class));
7488
}
7589

7690
public function testGetCollection()
@@ -150,6 +164,7 @@ public function testGetCollection()
150164
$this->prophesize(IdentifierExtractorInterface::class)->reveal(),
151165
$denormalizer = $this->prophesize(DenormalizerInterface::class)->reveal(),
152166
new Pagination($resourceMetadataFactoryProphecy->reveal(), ['items_per_page' => 2]),
167+
$resourceMetadataFactoryProphecy->reveal(),
153168
[$requestBodySearchCollectionExtensionProphecy->reveal()]
154169
);
155170

tests/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@
2121
use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface;
2222
use ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer;
2323
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
24+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
25+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
26+
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
2427
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation;
2528
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
29+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar;
30+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCarColor;
2631
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Foo;
2732
use Elasticsearch\Client;
2833
use Elasticsearch\Common\Exceptions\Missing404Exception;
@@ -40,7 +45,8 @@ public function testConstruct()
4045
$this->prophesize(Client::class)->reveal(),
4146
$this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(),
4247
$this->prophesize(IdentifierExtractorInterface::class)->reveal(),
43-
$this->prophesize(DenormalizerInterface::class)->reveal()
48+
$this->prophesize(DenormalizerInterface::class)->reveal(),
49+
$this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()
4450
)
4551
);
4652
}
@@ -56,16 +62,26 @@ public function testSupports()
5662
$identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled();
5763
$identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled();
5864

65+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
66+
$resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
67+
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
68+
$resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata());
69+
$resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false]));
70+
$resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException());
71+
5972
$itemDataProvider = new ItemDataProvider(
6073
$this->prophesize(Client::class)->reveal(),
6174
$documentMetadataFactoryProphecy->reveal(),
6275
$identifierExtractorProphecy->reveal(),
63-
$this->prophesize(DenormalizerInterface::class)->reveal()
76+
$this->prophesize(DenormalizerInterface::class)->reveal(),
77+
$resourceMetadataFactoryProphecy->reveal()
6478
);
6579

6680
self::assertTrue($itemDataProvider->supports(Foo::class));
6781
self::assertFalse($itemDataProvider->supports(Dummy::class));
6882
self::assertFalse($itemDataProvider->supports(CompositeRelation::class));
83+
self::assertFalse($itemDataProvider->supports(DummyCar::class));
84+
self::assertFalse($itemDataProvider->supports(DummyCarColor::class));
6985
}
7086

7187
public function testGetItem()
@@ -99,7 +115,9 @@ public function testGetItem()
99115
$denormalizerProphecy = $this->prophesize(DenormalizerInterface::class);
100116
$denormalizerProphecy->denormalize($document, Foo::class, ItemNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true])->willReturn($foo)->shouldBeCalled();
101117

102-
$itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $denormalizerProphecy->reveal());
118+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
119+
120+
$itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $denormalizerProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal());
103121

104122
self::assertSame($foo, $itemDataProvider->getItem(Foo::class, ['id' => 1]));
105123
}
@@ -115,7 +133,9 @@ public function testGetItemWithMissing404Exception()
115133
$clientProphecy = $this->prophesize(Client::class);
116134
$clientProphecy->get(['index' => 'foo', 'type' => DocumentMetadata::DEFAULT_TYPE, 'id' => '404'])->willThrow(new Missing404Exception())->shouldBeCalled();
117135

118-
$itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $this->prophesize(DenormalizerInterface::class)->reveal());
136+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
137+
138+
$itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $this->prophesize(DenormalizerInterface::class)->reveal(), $resourceMetadataFactoryProphecy->reveal());
119139

120140
self::assertNull($itemDataProvider->getItem(Foo::class, ['id' => 404]));
121141
}

0 commit comments

Comments
 (0)