Skip to content

Commit

Permalink
Possibility to add execute options for MongoDB (#3144)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain committed Oct 7, 2019
1 parent e468d98 commit d8e624b
Show file tree
Hide file tree
Showing 11 changed files with 427 additions and 98 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2.6.0

* MongoDB: Possibility to add execute options (aggregate command fields) for a resource, like `allowDiskUse` (#3144)

## 2.5.0

* Fix BC-break when using short-syntax notation for `access_control`
Expand Down
11 changes: 9 additions & 2 deletions src/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use ApiPlatform\Core\Exception\RuntimeException;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
Expand All @@ -32,14 +33,16 @@
final class CollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{
private $managerRegistry;
private $resourceMetadataFactory;
private $collectionExtensions;

/**
* @param AggregationCollectionExtensionInterface[] $collectionExtensions
*/
public function __construct(ManagerRegistry $managerRegistry, iterable $collectionExtensions = [])
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, iterable $collectionExtensions = [])
{
$this->managerRegistry = $managerRegistry;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->collectionExtensions = $collectionExtensions;
}

Expand Down Expand Up @@ -72,6 +75,10 @@ public function getCollection(string $resourceClass, string $operationName = nul
}
}

return $aggregationBuilder->hydrate($resourceClass)->execute();
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$attribute = $resourceMetadata->getCollectionOperationAttribute($operationName, 'doctrine_mongodb', [], true);
$executeOptions = $attribute['execute_options'] ?? [];

return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions);
}
}
11 changes: 9 additions & 2 deletions src/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator;
use ApiPlatform\Core\DataProvider\Pagination;
use ApiPlatform\Core\Exception\RuntimeException;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Doctrine\ODM\MongoDB\DocumentManager;
Expand All @@ -33,11 +34,13 @@
final class PaginationExtension implements AggregationResultCollectionExtensionInterface
{
private $managerRegistry;
private $resourceMetadataFactory;
private $pagination;

public function __construct(ManagerRegistry $managerRegistry, Pagination $pagination)
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, Pagination $pagination)
{
$this->managerRegistry = $managerRegistry;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->pagination = $pagination;
}

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

return new Paginator($aggregationBuilder->execute(), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline());
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$attribute = $resourceMetadata->getCollectionOperationAttribute($operationName, 'doctrine_mongodb', [], true);
$executeOptions = $attribute['execute_options'] ?? [];

return new Paginator($aggregationBuilder->execute($executeOptions), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline());
}

private function addCountToContext(Builder $aggregationBuilder, array $context): array
Expand Down
11 changes: 9 additions & 2 deletions src/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
Expand All @@ -38,14 +39,16 @@ final class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProv
use IdentifierManagerTrait;

private $managerRegistry;
private $resourceMetadataFactory;
private $itemExtensions;

/**
* @param AggregationItemExtensionInterface[] $itemExtensions
*/
public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [])
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [])
{
$this->managerRegistry = $managerRegistry;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
$this->propertyMetadataFactory = $propertyMetadataFactory;
$this->itemExtensions = $itemExtensions;
Expand Down Expand Up @@ -95,6 +98,10 @@ public function getItem(string $resourceClass, $id, string $operationName = null
}
}

return $aggregationBuilder->hydrate($resourceClass)->execute()->current() ?: null;
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$attribute = $resourceMetadata->getItemOperationAttribute($operationName, 'doctrine_mongodb', [], true);
$executeOptions = $attribute['execute_options'] ?? [];

return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions)->current() ?: null;
}
}
19 changes: 13 additions & 6 deletions src/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Doctrine\ODM\MongoDB\DocumentManager;
Expand All @@ -43,16 +44,18 @@ final class SubresourceDataProvider implements SubresourceDataProviderInterface
use IdentifierManagerTrait;

private $managerRegistry;
private $resourceMetadataFactory;
private $collectionExtensions;
private $itemExtensions;

/**
* @param AggregationCollectionExtensionInterface[] $collectionExtensions
* @param AggregationItemExtensionInterface[] $itemExtensions
*/
public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = [])
public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = [])
{
$this->managerRegistry = $managerRegistry;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
$this->propertyMetadataFactory = $propertyMetadataFactory;
$this->collectionExtensions = $collectionExtensions;
Expand Down Expand Up @@ -80,7 +83,11 @@ public function getSubresource(string $resourceClass, array $identifiers, array
throw new ResourceClassNotSupportedException('The given resource class is not a subresource.');
}

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

$aggregationBuilder = $this->buildAggregation($identifiers, $context, $executeOptions, $repository->createAggregationBuilder(), \count($context['identifiers']));

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

$iterator = $aggregationBuilder->hydrate($resourceClass)->execute();
$iterator = $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions);

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

/**
* @throws RuntimeException
*/
private function buildAggregation(array $identifiers, array $context, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder
private function buildAggregation(array $identifiers, array $context, array $executeOptions, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder
{
if ($remainingIdentifiers <= 0) {
return $previousAggregationBuilder;
Expand Down Expand Up @@ -154,9 +161,9 @@ private function buildAggregation(array $identifiers, array $context, Builder $p
}

// Recurse aggregations
$aggregation = $this->buildAggregation($identifiers, $context, $aggregation, --$remainingIdentifiers, $topAggregationBuilder);
$aggregation = $this->buildAggregation($identifiers, $context, $executeOptions, $aggregation, --$remainingIdentifiers, $topAggregationBuilder);

$results = $aggregation->execute()->toArray();
$results = $aggregation->execute($executeOptions)->toArray();
$in = array_reduce($results, function ($in, $result) use ($previousAssociationProperty) {
return $in + array_map(function ($result) {
return $result['_id'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@

<service id="api_platform.doctrine_mongodb.odm.collection_data_provider" public="false" abstract="true">
<argument type="service" id="doctrine_mongodb"/>
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.collection" />
</service>

<service id="api_platform.doctrine_mongodb.odm.item_data_provider" public="false" abstract="true">
<argument type="service" id="doctrine_mongodb"/>
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument type="service" id="api_platform.metadata.property.name_collection_factory"/>
<argument type="service" id="api_platform.metadata.property.metadata_factory"/>
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.item" />
</service>

<service id="api_platform.doctrine_mongodb.odm.subresource_data_provider" public="false" abstract="true">
<argument type="service" id="doctrine_mongodb" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument type="service" id="api_platform.metadata.property.name_collection_factory" />
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
<argument type="tagged" tag="api_platform.doctrine_mongodb.odm.aggregation_extension.collection" />
Expand All @@ -46,7 +49,6 @@
parent="api_platform.doctrine_mongodb.odm.collection_data_provider"
class="ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider">
<tag name="api_platform.collection_data_provider"/>

</service>
<service id="api_platform.doctrine_mongodb.odm.default.item_data_provider"
parent="api_platform.doctrine_mongodb.odm.item_data_provider"
Expand Down Expand Up @@ -138,6 +140,7 @@
<service id="api_platform.doctrine_mongodb.odm.aggregation_extension.pagination"
class="ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension" public="false">
<argument type="service" id="doctrine_mongodb"/>
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument type="service" id="api_platform.pagination" />

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

0 comments on commit d8e624b

Please sign in to comment.