Skip to content

Commit

Permalink
Merge 09efc75 into 821a077
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreRebeilleau committed Dec 20, 2021
2 parents 821a077 + 09efc75 commit 89b2764
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
92 changes: 92 additions & 0 deletions src/Doctrine/MongoDbOdm/State/CollectionProvider.php
@@ -0,0 +1,92 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\MongoDbOdm\State;

use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\State\LinksHandlerTrait;
use ApiPlatform\Exception\OperationNotFoundException;
use ApiPlatform\Exception\RuntimeException;
use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
use ApiPlatform\State\ProviderInterface;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
use Doctrine\Persistence\ManagerRegistry;

class CollectionProvider implements ProviderInterface
{
use LinksHandlerTrait;

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

public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, iterable $collectionExtensions = [])
{
$this->managerRegistry = $managerRegistry;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->collectionExtensions = $collectionExtensions;
}

/**
* {@inheritdoc}
*/
public function provide(string $resourceClass, array $identifiers = [], ?string $operationName = null, array $context = [])
{
/** @var DocumentManager $manager */
$manager = $this->managerRegistry->getManagerForClass($resourceClass);

$repository = $manager->getRepository($resourceClass);
if (!$repository instanceof DocumentRepository) {
throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class));
}

$aggregationBuilder = $repository->createAggregationBuilder();
foreach ($this->collectionExtensions as $extension) {
$extension->applyToCollection($aggregationBuilder, $resourceClass, $operationName, $context);

if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) {
return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context);
}
}

$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
try {
$operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName);
$attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? [];
} catch (OperationNotFoundException $e) {
$attribute = $resourceMetadata->getOperation(null, true)->getExtraProperties()['doctrine_mongodb'] ?? [];
}
$executeOptions = $attribute['execute_options'] ?? [];

return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions);
}

/**
* {@inheritdoc}
*/
public function supports(string $resourceClass, array $identifiers = [], ?string $operationName = null, array $context = []): bool
{
if (!$this->managerRegistry->getManagerForClass($resourceClass) instanceof DocumentManager) {
return false;
}

$operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation($operationName);

if ($operation instanceof GraphQlOperation) {
return true;
}

return $operation->isCollection() ?? false;
}
}
106 changes: 106 additions & 0 deletions src/Doctrine/MongoDbOdm/State/ItemProvider.php
@@ -0,0 +1,106 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\MongoDbOdm\State;

use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface;
use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface;
use ApiPlatform\Doctrine\Orm\State\LinksHandlerTrait;
use ApiPlatform\Exception\OperationNotFoundException;
use ApiPlatform\Exception\RuntimeException;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\State\ProviderInterface;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;

class ItemProvider implements ProviderInterface
{
use LinksHandlerTrait;

private $resourceMetadataCollectionFactory;
private $managerRegistry;
private $itemExtensions;

/**
* @param AggregationItemExtensionInterface[] $itemExtensions
*/
public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, ManagerRegistry $managerRegistry, iterable $itemExtensions = [])
{
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
$this->managerRegistry = $managerRegistry;
$this->itemExtensions = $itemExtensions;
}

/**
* {@inheritDoc}
*
* @throws \ApiPlatform\Exception\ResourceClassNotFoundException
*/
public function provide(string $resourceClass, array $identifiers = [], ?string $operationName = null, array $context = [])
{
/** @var DocumentManager $manager */
$manager = $this->managerRegistry->getManagerForClass($resourceClass);

$fetchData = $context['fetch_data'] ?? true;
if (!$fetchData) {
return $manager->getReference($resourceClass, $identifiers);
}

$repository = $manager->getRepository($resourceClass);
if (!$repository instanceof DocumentRepository) {
throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class));
}

$aggregationBuilder = $repository->createAggregationBuilder();

foreach ($identifiers as $propertyName => $value) {
$aggregationBuilder->match()->field($propertyName)->equals($value);
}

foreach ($this->itemExtensions as $extension) {
$extension->applyToItem($aggregationBuilder, $resourceClass, $identifiers, $operationName, $context);

if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) {
return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context);
}
}

$resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass);

try {
$operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName);
$attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? [];
} catch (OperationNotFoundException $e) {
$attribute = $resourceMetadata->getOperation(null, true)->getExtraProperties()['doctrine_mongodb'] ?? [];
}
$executeOptions = $attribute['execute_options'] ?? [];

return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions)->current() ?: null;
}

/**
* {@inheritDoc}
*/
public function supports(string $resourceClass, array $identifiers = [], ?string $operationName = null, array $context = []): bool
{
if (!$this->managerRegistry->getManagerForClass($resourceClass) instanceof EntityManagerInterface) {
return false;
}

$operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation($operationName);

return !($operation->isCollection() ?? false);
}
}
6 changes: 6 additions & 0 deletions src/GraphQl/Resolver/Stage/ReadStage.php
Expand Up @@ -102,6 +102,12 @@ public function __invoke(?string $resourceClass, ?string $rootClass, string $ope

$normalizationContext['operation'] = $operation ?? new QueryCollection();

if (!$operation && $resourceClass) {
$operation = (new QueryCollection())->withOperation($this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(null, true));
}

$normalizationContext['operation'] = $operation ?? new QueryCollection();

$source = $context['source'];
/** @var ResolveInfo $info */
$info = $context['info'];
Expand Down

0 comments on commit 89b2764

Please sign in to comment.