Skip to content

Commit d8e624b

Browse files
authored
Possibility to add execute options for MongoDB (#3144)
1 parent e468d98 commit d8e624b

File tree

11 files changed

+427
-98
lines changed

11 files changed

+427
-98
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2.6.0
4+
5+
* MongoDB: Possibility to add execute options (aggregate command fields) for a resource, like `allowDiskUse` (#3144)
6+
37
## 2.5.0
48

59
* Fix BC-break when using short-syntax notation for `access_control`

src/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
1919
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
2020
use ApiPlatform\Core\Exception\RuntimeException;
21+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2122
use Doctrine\Common\Persistence\ManagerRegistry;
2223
use Doctrine\ODM\MongoDB\DocumentManager;
2324
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
@@ -32,14 +33,16 @@
3233
final class CollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
3334
{
3435
private $managerRegistry;
36+
private $resourceMetadataFactory;
3537
private $collectionExtensions;
3638

3739
/**
3840
* @param AggregationCollectionExtensionInterface[] $collectionExtensions
3941
*/
40-
public function __construct(ManagerRegistry $managerRegistry, iterable $collectionExtensions = [])
42+
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, iterable $collectionExtensions = [])
4143
{
4244
$this->managerRegistry = $managerRegistry;
45+
$this->resourceMetadataFactory = $resourceMetadataFactory;
4346
$this->collectionExtensions = $collectionExtensions;
4447
}
4548

@@ -72,6 +75,10 @@ public function getCollection(string $resourceClass, string $operationName = nul
7275
}
7376
}
7477

75-
return $aggregationBuilder->hydrate($resourceClass)->execute();
78+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
79+
$attribute = $resourceMetadata->getCollectionOperationAttribute($operationName, 'doctrine_mongodb', [], true);
80+
$executeOptions = $attribute['execute_options'] ?? [];
81+
82+
return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions);
7683
}
7784
}

src/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator;
1717
use ApiPlatform\Core\DataProvider\Pagination;
1818
use ApiPlatform\Core\Exception\RuntimeException;
19+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
1920
use Doctrine\Common\Persistence\ManagerRegistry;
2021
use Doctrine\ODM\MongoDB\Aggregation\Builder;
2122
use Doctrine\ODM\MongoDB\DocumentManager;
@@ -33,11 +34,13 @@
3334
final class PaginationExtension implements AggregationResultCollectionExtensionInterface
3435
{
3536
private $managerRegistry;
37+
private $resourceMetadataFactory;
3638
private $pagination;
3739

38-
public function __construct(ManagerRegistry $managerRegistry, Pagination $pagination)
40+
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, Pagination $pagination)
3941
{
4042
$this->managerRegistry = $managerRegistry;
43+
$this->resourceMetadataFactory = $resourceMetadataFactory;
4144
$this->pagination = $pagination;
4245
}
4346

@@ -113,7 +116,11 @@ public function getResult(Builder $aggregationBuilder, string $resourceClass, st
113116
throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class));
114117
}
115118

116-
return new Paginator($aggregationBuilder->execute(), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline());
119+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
120+
$attribute = $resourceMetadata->getCollectionOperationAttribute($operationName, 'doctrine_mongodb', [], true);
121+
$executeOptions = $attribute['execute_options'] ?? [];
122+
123+
return new Paginator($aggregationBuilder->execute($executeOptions), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline());
117124
}
118125

119126
private function addCountToContext(Builder $aggregationBuilder, array $context): array

src/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
2323
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2424
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
25+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2526
use Doctrine\Common\Persistence\ManagerRegistry;
2627
use Doctrine\ODM\MongoDB\DocumentManager;
2728
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
@@ -38,14 +39,16 @@ final class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProv
3839
use IdentifierManagerTrait;
3940

4041
private $managerRegistry;
42+
private $resourceMetadataFactory;
4143
private $itemExtensions;
4244

4345
/**
4446
* @param AggregationItemExtensionInterface[] $itemExtensions
4547
*/
46-
public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [])
48+
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [])
4749
{
4850
$this->managerRegistry = $managerRegistry;
51+
$this->resourceMetadataFactory = $resourceMetadataFactory;
4952
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
5053
$this->propertyMetadataFactory = $propertyMetadataFactory;
5154
$this->itemExtensions = $itemExtensions;
@@ -95,6 +98,10 @@ public function getItem(string $resourceClass, $id, string $operationName = null
9598
}
9699
}
97100

98-
return $aggregationBuilder->hydrate($resourceClass)->execute()->current() ?: null;
101+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
102+
$attribute = $resourceMetadata->getItemOperationAttribute($operationName, 'doctrine_mongodb', [], true);
103+
$executeOptions = $attribute['execute_options'] ?? [];
104+
105+
return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions)->current() ?: null;
99106
}
100107
}

src/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
2525
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2626
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
27+
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2728
use Doctrine\Common\Persistence\ManagerRegistry;
2829
use Doctrine\ODM\MongoDB\Aggregation\Builder;
2930
use Doctrine\ODM\MongoDB\DocumentManager;
@@ -43,16 +44,18 @@ final class SubresourceDataProvider implements SubresourceDataProviderInterface
4344
use IdentifierManagerTrait;
4445

4546
private $managerRegistry;
47+
private $resourceMetadataFactory;
4648
private $collectionExtensions;
4749
private $itemExtensions;
4850

4951
/**
5052
* @param AggregationCollectionExtensionInterface[] $collectionExtensions
5153
* @param AggregationItemExtensionInterface[] $itemExtensions
5254
*/
53-
public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = [])
55+
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = [])
5456
{
5557
$this->managerRegistry = $managerRegistry;
58+
$this->resourceMetadataFactory = $resourceMetadataFactory;
5659
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
5760
$this->propertyMetadataFactory = $propertyMetadataFactory;
5861
$this->collectionExtensions = $collectionExtensions;
@@ -80,7 +83,11 @@ public function getSubresource(string $resourceClass, array $identifiers, array
8083
throw new ResourceClassNotSupportedException('The given resource class is not a subresource.');
8184
}
8285

83-
$aggregationBuilder = $this->buildAggregation($identifiers, $context, $repository->createAggregationBuilder(), \count($context['identifiers']));
86+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
87+
$attribute = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'doctrine_mongodb', [], true);
88+
$executeOptions = $attribute['execute_options'] ?? [];
89+
90+
$aggregationBuilder = $this->buildAggregation($identifiers, $context, $executeOptions, $repository->createAggregationBuilder(), \count($context['identifiers']));
8491

8592
if (true === $context['collection']) {
8693
foreach ($this->collectionExtensions as $extension) {
@@ -98,15 +105,15 @@ public function getSubresource(string $resourceClass, array $identifiers, array
98105
}
99106
}
100107

101-
$iterator = $aggregationBuilder->hydrate($resourceClass)->execute();
108+
$iterator = $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions);
102109

103110
return $context['collection'] ? $iterator->toArray() : ($iterator->current() ?: null);
104111
}
105112

106113
/**
107114
* @throws RuntimeException
108115
*/
109-
private function buildAggregation(array $identifiers, array $context, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder
116+
private function buildAggregation(array $identifiers, array $context, array $executeOptions, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder
110117
{
111118
if ($remainingIdentifiers <= 0) {
112119
return $previousAggregationBuilder;
@@ -154,9 +161,9 @@ private function buildAggregation(array $identifiers, array $context, Builder $p
154161
}
155162

156163
// Recurse aggregations
157-
$aggregation = $this->buildAggregation($identifiers, $context, $aggregation, --$remainingIdentifiers, $topAggregationBuilder);
164+
$aggregation = $this->buildAggregation($identifiers, $context, $executeOptions, $aggregation, --$remainingIdentifiers, $topAggregationBuilder);
158165

159-
$results = $aggregation->execute()->toArray();
166+
$results = $aggregation->execute($executeOptions)->toArray();
160167
$in = array_reduce($results, function ($in, $result) use ($previousAssociationProperty) {
161168
return $in + array_map(function ($result) {
162169
return $result['_id'];

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@
2424

2525
<service id="api_platform.doctrine_mongodb.odm.collection_data_provider" public="false" abstract="true">
2626
<argument type="service" id="doctrine_mongodb"/>
27+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
2728
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.collection" />
2829
</service>
2930

3031
<service id="api_platform.doctrine_mongodb.odm.item_data_provider" public="false" abstract="true">
3132
<argument type="service" id="doctrine_mongodb"/>
33+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
3234
<argument type="service" id="api_platform.metadata.property.name_collection_factory"/>
3335
<argument type="service" id="api_platform.metadata.property.metadata_factory"/>
3436
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.item" />
3537
</service>
3638

3739
<service id="api_platform.doctrine_mongodb.odm.subresource_data_provider" public="false" abstract="true">
3840
<argument type="service" id="doctrine_mongodb" />
41+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
3942
<argument type="service" id="api_platform.metadata.property.name_collection_factory" />
4043
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
4144
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.collection" />
@@ -46,7 +49,6 @@
4649
parent="api_platform.doctrine_mongodb.odm.collection_data_provider"
4750
class="ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider">
4851
<tag name="api_platform.collection_data_provider"/>
49-
5052
</service>
5153
<service id="api_platform.doctrine_mongodb.odm.default.item_data_provider"
5254
parent="api_platform.doctrine_mongodb.odm.item_data_provider"
@@ -138,6 +140,7 @@
138140
<service id="api_platform.doctrine_mongodb.odm.aggregation_extension.pagination"
139141
class="ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension" public="false">
140142
<argument type="service" id="doctrine_mongodb"/>
143+
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
141144
<argument type="service" id="api_platform.pagination" />
142145

143146
<tag name="api_platform.doctrine_mongodb.odm.aggregation_extension.collection"/>

0 commit comments

Comments
 (0)