Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ jobs:
if: matrix.coverage
run: echo "COVERAGE=1" >> $GITHUB_ENV
- name: Remove Doctrine MongoDB ODM
if: (startsWith(matrix.php, '7.1') || startsWith(matrix.php, '8.0'))
if: (startsWith(matrix.php, '7.1'))
run: |
composer remove --dev --no-interaction --no-progress --no-update --ansi \
doctrine/mongodb-odm \
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@

## 2.6.5

* JsonSchema: Update Hydra `@context` property possible types
* Filter validation: Fix issue in Required filter validator with dot notation (#4221)
* OpenAPI: Fix notice/warning for `response` without `content` in the `openapi_context` (#4210)
* OpenAPI: Do not use output for request body (#4213)
* Serializer: Convert internal error to HTTP 400 in Ramsey uuid denormalization from invalid body string (#4200)
* Symfony: Add tests with Symfony Uuid (#4230)
* OpenAPI: Allow to set extensionProperties with YAML schema definition (#4228)
* GraphQL: Fix `FieldsBuilder` not fully unwrapping nested types before deciding if a resolver is needed (#4251)

## 2.6.4

Expand Down
26 changes: 26 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ When you send a PR, just make sure that:
that you did not make in your PR, you're doing it wrong.
* Also don't forget to add a comment when you update a PR with a ping to [the maintainers](https://github.com/orgs/api-platform/people), so he/she will get a notification.

The commit messages must follow the [Conventional Commits specification](https://www.conventionalcommits.org/).
The following types are allowed:

* `fix`: bug fix
* `feat`: new feature
* `docs`: change in the documentation
* `spec`: spec change
* `test`: test-related change
* `perf`: performance optimization
* `ci`: CI-related change
* `chore`: updating dependencies and related changes

Examples:

fix(metadata): resource identifiers from properties

feat(validation): introduce a number constraint

feat(metadata)!: new resource metadata system, BC break

docs(doctrine): search filter on uuids

test(doctrine): mongodb disambiguation

We strongly recommend the use of a scope on API Platform core.

### Tests

On `api-platform/core` there are two kinds of tests: unit (`phpunit` through `simple-phpunit`) and integration tests (`behat`).
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"doctrine/common": "^2.11 || ^3.0",
"doctrine/data-fixtures": "^1.2.2",
"doctrine/doctrine-bundle": "^1.12 || ^2.0",
"doctrine/mongodb-odm": "^2.1",
"doctrine/mongodb-odm": "^2.2",
"doctrine/mongodb-odm-bundle": "^4.0",
"doctrine/orm": "^2.6.4 || ^3.0",
"elasticsearch/elasticsearch": "^6.0 || ^7.0",
Expand Down Expand Up @@ -86,7 +86,7 @@
},
"conflict": {
"doctrine/common": "<2.7",
"doctrine/mongodb-odm": "<2.1",
"doctrine/mongodb-odm": "<2.2",
"doctrine/persistence": "<1.3"
},
"suggest": {
Expand Down
4 changes: 2 additions & 2 deletions features/swagger/docs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ Feature: Documentation support
And the JSON node "paths./api/custom-call/{id}.get" should exist
And the JSON node "paths./api/custom-call/{id}.put" should exist
# Properties
And "id" property exists for the Swagger class "Dummy"
And "name" property is required for Swagger class "Dummy"
And the "id" property exists for the Swagger class "Dummy"
And the "name" property is required for the Swagger class "Dummy"
# Filters
And the JSON node "paths./dummies.get.parameters[0].name" should be equal to "dummyBoolean"
And the JSON node "paths./dummies.get.parameters[0].in" should be equal to "query"
Expand Down
32 changes: 13 additions & 19 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>

<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
bootstrap="tests/Fixtures/app/bootstrap.php"
colors="true"
>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" backupGlobals="false" bootstrap="tests/Fixtures/app/bootstrap.php" colors="true">
<php>
<ini name="error_reporting" value="-1" />
<ini name="memory_limit" value="-1" />
Expand All @@ -25,19 +19,19 @@
</testsuite>
</testsuites>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<coverage processUncoveredFiles="true">
<include>
<directory>.</directory>
<exclude>
<directory>features</directory>
<directory>tests</directory>
<directory>vendor</directory>
<directory>src/Bridge/NelmioApiDoc</directory>
<directory>src/Bridge/FosUser</directory>
<file>src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php</file>
</exclude>
</whitelist>
</filter>
</include>
<exclude>
<directory>features</directory>
<directory>tests</directory>
<directory>vendor</directory>
<directory>src/Bridge/NelmioApiDoc</directory>
<directory>src/Bridge/FosUser</directory>
<file>src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php</file>
</exclude>
</coverage>

<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQl/Type/FieldsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ private function getResourceFieldConfiguration(?string $property, ?string $field
return null;
}

$graphqlWrappedType = $graphqlType instanceof WrappingType ? $graphqlType->getWrappedType() : $graphqlType;
$graphqlWrappedType = $graphqlType instanceof WrappingType ? $graphqlType->getWrappedType(true) : $graphqlType;
$isStandardGraphqlType = \in_array($graphqlWrappedType, GraphQLType::getStandardTypes(), true);
if ($isStandardGraphqlType) {
$resourceClass = '';
Expand Down
22 changes: 21 additions & 1 deletion src/Hydra/JsonSchema/SchemaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Core\Hydra\JsonSchema;

use ApiPlatform\Core\JsonLd\ContextBuilder;
use ApiPlatform\Core\JsonSchema\Schema;
use ApiPlatform\Core\JsonSchema\SchemaFactory as BaseSchemaFactory;
use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface;
Expand All @@ -35,7 +36,26 @@ final class SchemaFactory implements SchemaFactoryInterface
'@type' => self::BASE_PROP,
];
private const BASE_ROOT_PROPS = [
'@context' => self::BASE_PROP,
'@context' => [
'readOnly' => true,
'oneOf' => [
['type' => 'string'],
[
'type' => 'object',
'properties' => [
'@vocab' => [
'type' => 'string',
],
'hydra' => [
'type' => 'string',
'enum' => [ContextBuilder::HYDRA_NS],
],
],
'required' => ['@vocab', 'hydra'],
'additionalProperties' => true,
],
],
],
] + self::BASE_PROPS;

private $schemaFactory;
Expand Down
1 change: 0 additions & 1 deletion src/OpenApi/Factory/OpenApiFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ public function __invoke(array $context = []): OpenApi

foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$resourceShortName = $resourceMetadata->getShortName();

// Items needs to be parsed first to be able to reference the lines from the collection operation
$this->collectPaths($resourceMetadata, $resourceClass, OperationType::ITEM, $context, $paths, $links, $schemas);
Expand Down
6 changes: 5 additions & 1 deletion src/Test/DoctrineMongoDbOdmSetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ public static function createConfiguration(bool $isDevMode = false, string $prox
$cache = self::createCacheConfiguration($isDevMode, $proxyDir, $hydratorDir, $cache);

$config = new Configuration();
$config->setMetadataCacheImpl($cache);
if (method_exists($config, 'setMetadataCache')) {
$config->setMetadataCache($cache);
} else {
$config->setMetadataCacheImpl($cache);
}
$config->setProxyDir($proxyDir);
$config->setHydratorDir($hydratorDir);
$config->setProxyNamespace('DoctrineProxies');
Expand Down
6 changes: 5 additions & 1 deletion src/Test/DoctrineMongoDbOdmTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ public static function createTestDocumentManager($paths = [])
$config->setProxyNamespace('SymfonyTests\Doctrine');
$config->setHydratorNamespace('SymfonyTests\Doctrine');
$config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), $paths));
$config->setMetadataCacheImpl(new ArrayCache());
if (method_exists($config, 'setMetadataCache')) {
$config->setMetadataCache(new ArrayCache());
} else {
$config->setMetadataCacheImpl(new ArrayCache());
}

return DocumentManager::create(null, $config);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Count;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Facet;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch;
use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Skip;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Iterator\Iterator;
Expand Down
2 changes: 1 addition & 1 deletion tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy;
use ApiPlatform\Core\Tests\ProphecyTrait;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch;
use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch;
use Doctrine\ODM\MongoDB\Iterator\Iterator;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
use ApiPlatform\Core\Tests\ProphecyTrait;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup;
use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch;
use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Iterator\Iterator;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
Expand Down
42 changes: 31 additions & 11 deletions tests/Bridge/Symfony/Bundle/Test/ApiTestCaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Model\ResourceInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Tools\SchemaTool;
Expand Down Expand Up @@ -137,6 +138,21 @@ public function testAssertMatchesResourceItemJsonSchema(): void
$this->assertMatchesResourceItemJsonSchema(ResourceInterface::class);
}

public function testAssertMatchesResourceItemJsonSchemaOutput(): void
{
$this->recreateSchema();

/** @var EntityManagerInterface $manager */
$manager = self::$container->get('doctrine')->getManager();
$dummyDtoInputOutput = new DummyDtoInputOutput();
$dummyDtoInputOutput->str = 'lorem';
$dummyDtoInputOutput->num = 54;
$manager->persist($dummyDtoInputOutput);
$manager->flush();
self::createClient()->request('GET', '/dummy_dto_input_outputs/1');
$this->assertMatchesResourceItemJsonSchema(DummyDtoInputOutput::class);
}

// Next tests have been imported from dms/phpunit-arraysubset-asserts, because the original constraint has been deprecated.

public function testAssertArraySubsetPassesStrictConfig(): void
Expand All @@ -160,17 +176,7 @@ public function testAssertArraySubsetDoesNothingForValidScenario(): void

public function testFindIriBy(): void
{
self::bootKernel();
/**
* @var EntityManagerInterface
*/
$manager = self::$container->get('doctrine')->getManager();
/** @var \Doctrine\ORM\Mapping\ClassMetadata[] $classes */
$classes = $manager->getMetadataFactory()->getAllMetadata();
$schemaTool = new SchemaTool($manager);

$schemaTool->dropSchema($classes);
$schemaTool->createSchema($classes);
$this->recreateSchema();

self::createClient()->request('POST', '/dummies', [
'headers' => [
Expand All @@ -185,4 +191,18 @@ public function testFindIriBy(): void
$this->assertMatchesRegularExpression('~^/dummies/\d+~', self::findIriBy($resource, ['name' => 'Kevin']));
$this->assertNull(self::findIriBy($resource, ['name' => 'not-exist']));
}

private function recreateSchema(): void
{
self::bootKernel();

/** @var EntityManagerInterface $manager */
$manager = self::$container->get('doctrine')->getManager();
/** @var \Doctrine\ORM\Mapping\ClassMetadata[] $classes */
$classes = $manager->getMetadataFactory()->getAllMetadata();
$schemaTool = new SchemaTool($manager);

$schemaTool->dropSchema($classes);
$schemaTool->createSchema($classes);
}
}
19 changes: 19 additions & 0 deletions tests/GraphQl/Type/FieldsBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ public function testGetResourceObjectTypeFields(string $resourceClass, ResourceM
$this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), null, $mutationName, null, '', $resourceClass, $propertyName, 1)->willReturn(GraphQLType::string());
$this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), null, null, $subscriptionName, '', $resourceClass, $propertyName, 1)->willReturn(GraphQLType::string());
$this->typeConverterProphecy->convertType(Argument::type(Type::class), true, null, $mutationName, null, 'subresourceClass', $propertyName, 1)->willReturn(GraphQLType::string());
$this->typeConverterProphecy->convertType(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)), Argument::type('bool'), $queryName, null, null, '', $resourceClass, $propertyName, 1)->willReturn(GraphQLType::nonNull(GraphQLType::listOf(GraphQLType::nonNull(GraphQLType::string()))));
}
$this->typesContainerProphecy->has('NotRegisteredType')->willReturn(false);
$this->typesContainerProphecy->all()->willReturn([]);
Expand Down Expand Up @@ -592,6 +593,24 @@ public function resourceObjectTypeFieldsProvider(): array
],
],
],
'query with simple non-null string array property' => ['resourceClass', new ResourceMetadata(),
[
'property' => new PropertyMetadata(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)), null, true, false),
],
false, 'item_query', null, null, null,
[
'id' => [
'type' => GraphQLType::nonNull(GraphQLType::id()),
],
'property' => [
'type' => GraphQLType::nonNull(GraphQLType::listOf(GraphQLType::nonNull(GraphQLType::string()))),
'description' => null,
'args' => [],
'resolve' => null,
'deprecationReason' => null,
],
],
],
'mutation non input' => ['resourceClass', new ResourceMetadata(),
[
'property' => new PropertyMetadata(),
Expand Down
24 changes: 24 additions & 0 deletions tests/Hydra/JsonSchema/SchemaFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Hydra\JsonSchema\SchemaFactory;
use ApiPlatform\Core\JsonLd\ContextBuilder;
use ApiPlatform\Core\JsonSchema\Schema;
use ApiPlatform\Core\JsonSchema\SchemaFactory as BaseSchemaFactory;
use ApiPlatform\Core\JsonSchema\TypeFactoryInterface;
Expand Down Expand Up @@ -79,6 +80,29 @@ public function testHasRootDefinitionKeyBuildSchema(): void
$this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
$properties = $resultSchema['definitions'][$rootDefinitionKey]['properties'];
$this->assertArrayHasKey('@context', $properties);
$this->assertSame(
[
'readOnly' => true,
'oneOf' => [
['type' => 'string'],
[
'type' => 'object',
'properties' => [
'@vocab' => [
'type' => 'string',
],
'hydra' => [
'type' => 'string',
'enum' => [ContextBuilder::HYDRA_NS],
],
],
'required' => ['@vocab', 'hydra'],
'additionalProperties' => true,
],
],
],
$properties['@context']
);
$this->assertArrayHasKey('@type', $properties);
$this->assertArrayHasKey('@id', $properties);
}
Expand Down