Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3366849
Update branch alias
dunglas Sep 23, 2019
81d276c
Merge branch '2.5'
dunglas Sep 23, 2019
59fa1e2
Merge branch '2.5'
dunglas Sep 25, 2019
9ff7a23
Merge branch '2.5'
dunglas Sep 26, 2019
9799193
Merge branch '2.5'
dunglas Sep 26, 2019
854bcc9
Add entrypoints sorting
mRoca Sep 27, 2019
8e28a58
Merge pull request #3114 from mRoca/entrypoints-sorting
soyuka Sep 30, 2019
e468d98
Merge branch '2.5'
dunglas Oct 1, 2019
d8e624b
Possibility to add execute options for MongoDB (#3144)
alanpoulain Oct 7, 2019
4d4ee37
Feat: remove template pull request
toofff Oct 2, 2019
a4c8af6
Merge pull request #3137 from toofff/feat-remove-template-pull-request
dunglas Oct 14, 2019
1931f16
Context stamp (#3157)
Oct 14, 2019
dfc1771
Merge branch '2.5'
dunglas Oct 14, 2019
74ee7ef
Global resource defaults implementation (#3151)
bpolaszek Oct 14, 2019
f3312a7
Merge branch '2.5' into merge-2.5
teohhanhui Oct 15, 2019
3c371aa
Merge pull request #3179 from teohhanhui/merge-2.5
teohhanhui Oct 15, 2019
1e7d7ed
Merge remote-tracking branch 'upstream/2.5' into merge-25
soyuka Oct 23, 2019
480c077
Merge pull request #3202 from soyuka/merge-25
soyuka Oct 23, 2019
8e21ef2
Make the base exception extend throwable
BackEndTea Oct 28, 2019
21bbe95
Use https instead of http
BackEndTea Oct 28, 2019
59a1702
Merge pull request #3219 from BackEndTea/patch-3
dunglas Oct 28, 2019
449842a
Merge pull request #3217 from BackEndTea/patch-1
dunglas Oct 28, 2019
b125b66
Merge branch '2.5'
dunglas Oct 29, 2019
b4297d2
Use human-readable names instead of a hash
Oct 29, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/PULL_REQUEST_TEMPLATE.md

This file was deleted.

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
7 changes: 1 addition & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ Then, if it appears that it's a real bug, you may report it using GitHub by foll

> _NOTE:_ Don't hesitate giving as much information as you can (OS, PHP version extensions...)

### Security Issues

If you find a security issue, send a mail to Kévin Dunglas <dunglas@gmail.com>. **Please do not report security problems
publicly**. We will disclose details of the issue and credit you after having released a new version including a fix.

## Pull Requests

### Writing a Pull Request
Expand All @@ -33,7 +28,7 @@ See [the dedicated documentation entry](https://api-platform.com/docs/extra/rele
### Matching Coding Standards

The API Platform project follows [Symfony coding standards](https://symfony.com/doc/current/contributing/code/standards.html).
But don't worry, you can fix CS issues automatically using the [PHP CS Fixer](http://cs.sensiolabs.org/) tool:
But don't worry, you can fix CS issues automatically using the [PHP CS Fixer](https://cs.sensiolabs.org/) tool:

```shell
php-cs-fixer.phar fix
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.5.x-dev"
"dev-master": "2.6.x-dev"
}
}
}
20 changes: 20 additions & 0 deletions features/bootstrap/JsonApiContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@ public function theJsonNodeShouldNotBeAnEmptyString($node)
}
}

/**
* @Then the JSON node :node should be sorted
* @Then the JSON should be sorted
*/
public function theJsonNodeShouldBeSorted($node = '')
{
$actual = (array) $this->getValueOfNode($node);

if (!is_array($actual)) {
throw new \Exception(sprintf('The "%s" node value is not an array', $node));
}

$expected = $actual;
ksort($expected);

if ($actual !== $expected) {
throw new ExpectationFailedException(sprintf('The json node "%s" is not sorted by keys', $node));
}
}

/**
* @Given there is a RelatedDummy
*/
Expand Down
1 change: 1 addition & 0 deletions features/hydra/entrypoint.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Feature: Entrypoint support
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
And the JSON should be sorted
And the JSON node "@context" should be equal to "/contexts/Entrypoint"
And the JSON node "@id" should be equal to "/"
And the JSON node "@type" should be equal to "Entrypoint"
Expand Down
49 changes: 49 additions & 0 deletions src/Annotation/ApiResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,55 @@ final class ApiResource
{
use AttributesHydratorTrait;

/**
* @internal
*
* @see \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Configuration::addDefaultsSection
*/
public const CONFIGURABLE_DEFAULTS = [
'accessControl',
'accessControlMessage',
'security',
'securityMessage',
'securityPostDenormalize',
'securityPostDenormalizeMessage',
'cacheHeaders',
'collectionOperations',
'denormalizationContext',
'deprecationReason',
'description',
'elasticsearch',
'fetchPartial',
'forceEager',
'formats',
'filters',
'graphql',
'hydraContext',
'input',
'iri',
'itemOperations',
'mercure',
'messenger',
'normalizationContext',
'openapiContext',
'order',
'output',
'paginationClientEnabled',
'paginationClientItemsPerPage',
'paginationClientPartial',
'paginationEnabled',
'paginationFetchJoinCollection',
'paginationItemsPerPage',
'maximumItemsPerPage',
'paginationMaximumItemsPerPage',
'paginationPartial',
'paginationViaCursor',
'routePrefix',
'sunset',
'swaggerContext',
'validationGroups',
];

/**
* @see https://api-platform.com/docs/core/operations
*
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 @@ -191,6 +191,29 @@ private function registerCommonConfiguration(ContainerBuilder $container, array
if ($config['name_converter']) {
$container->setAlias('api_platform.name_converter', $config['name_converter']);
}
$container->setParameter('api_platform.defaults', $this->normalizeDefaults($config['defaults'] ?? []));
}

private function normalizeDefaults(array $defaults): array
{
$normalizedDefaults = ['attributes' => []];
$rootLevelOptions = [
'description',
'iri',
'item_operations',
'collection_operations',
'graphql',
];

foreach ($defaults as $option => $value) {
if (\in_array($option, $rootLevelOptions, true)) {
$normalizedDefaults[$option] = $value;
} else {
$normalizedDefaults['attributes'][$option] = $value;
}
}

return $normalizedDefaults;
}

private function registerMetadataConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
Expand Down
Loading