Skip to content

Commit

Permalink
Merge pull request #4057 from alanpoulain/merge-2.6
Browse files Browse the repository at this point in the history
Merge 2.6
  • Loading branch information
alanpoulain committed Feb 12, 2021
2 parents d4abacb + 7ca48a6 commit 0d784fd
Show file tree
Hide file tree
Showing 40 changed files with 635 additions and 93 deletions.
22 changes: 16 additions & 6 deletions .github/workflows/ci.yml
Expand Up @@ -522,8 +522,8 @@ jobs:
- name: Update project dependencies
run: |
composer update --no-interaction --no-progress --ansi
# - name: Require Symfony Uid
# run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Require Symfony Uid
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -762,6 +762,7 @@ jobs:
matrix:
php:
- '7.4'
- '8.0'
fail-fast: false
env:
APP_ENV: sqlite
Expand All @@ -786,10 +787,14 @@ jobs:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Set Composer platform config
if: (startsWith(matrix.php, '8.0'))
run: |
composer config platform.php 7.4.99
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi --ignore-platform-reqs
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony Uid
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi --ignore-platform-reqs
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install phpunit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand All @@ -805,6 +810,7 @@ jobs:
matrix:
php:
- '7.4'
- '8.0'
fail-fast: false
env:
APP_ENV: sqlite
Expand All @@ -829,10 +835,14 @@ jobs:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Set Composer platform config
if: (startsWith(matrix.php, '8.0'))
run: |
composer config platform.php 7.4.99
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi --ignore-platform-reqs
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony Uid
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi --ignore-platform-reqs
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install phpunit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,21 @@

* MongoDB: `date_immutable` support (#3940)

## 2.6.3

* Mercure: Do not use data in options when deleting (#4056)

## 2.6.2

* Validation: properties regex pattern is now compliant with ECMA 262 (#4027)
* OpenApi: normalizer is now backward compatible (#4016), fix the name converter issue changing OpenApi properties (#4019)
* Identifiers: Break after transforming the identifier (#3985), use the identifiers context to transform with multiple classes (#4029)
* JsonSchema: Revert `ALLOW_EXTRA_ATTRIBUTE=false` as it is a BC break and will be done in 3.0 instead see #3881 (#4007)
* Subresource: fix ApiSubresource maxDepth option (#3986), recursive issue in the profiler (#4023)
* OpenApi: Allow `requestBody` and `parameters` via the `openapi_context` (#4001), make `openapi_context` work on subresources (#4004), sort paths (#4013)
* Config: Allow disabling OpenAPI and Swagger UI without loosing the schema (#3968 and #4018), fix pagination defaults (#4011)
* DataPersister: context propagation fix (#3983)

## 2.6.1

* Fix defaults when using attributes (#3978)
Expand Down
28 changes: 16 additions & 12 deletions features/hydra/collection.feature
Expand Up @@ -203,9 +203,13 @@ Feature: Collections support
"hydra:next": {"pattern": "^/dummies\\?partial=1&page=8$"},
"hydra:previous": {"pattern": "^/dummies\\?partial=1&page=6$"}
},
"additionalProperties": false
"required": ["@id", "@type", "hydra:next", "hydra:previous"],
"additionalProperties": false,
"maxProperties": 4
}
}
},
"required": ["@context", "@id", "@type", "hydra:member", "hydra:view", "hydra:search"],
"maxProperties": 6
}
"""

Expand Down Expand Up @@ -275,16 +279,16 @@ Feature: Collections support
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 valid according to this schema:
"""
{
"@id":"/dummies?page=3",
"@type":"hydra:PartialCollectionView",
"hydra:first":"/dummies?page=1",
"hydra:last":"/dummies?page=10",
"hydra:previous":"/dummies?page=2",
"hydra:next":"/dummies?page=4"
}
"""
"""
{
"@id":"/dummies?page=3",
"@type":"hydra:PartialCollectionView",
"hydra:first":"/dummies?page=1",
"hydra:last":"/dummies?page=10",
"hydra:previous":"/dummies?page=2",
"hydra:next":"/dummies?page=4"
}
"""
Scenario: Filter with exact match
When I send a "GET" request to "/dummies?id=8"
Then the response status code should be 200
Expand Down
2 changes: 1 addition & 1 deletion features/jsonapi/related-resouces-inclusion.feature
Expand Up @@ -602,7 +602,7 @@ Feature: JSON API Inclusion of Related Resources
Then the response status code should be 200
And the response should be in JSON
And the JSON should be valid according to the JSON API schema
And the JSON should be equal to:
And the JSON should be a superset of:
"""
{
"links": {
Expand Down
8 changes: 1 addition & 7 deletions phpstan.neon.dist
Expand Up @@ -92,7 +92,7 @@ parameters:
# Expected, due to PHP 8 attributes
- '#ReflectionProperty::getAttributes\(\)#'
- '#ReflectionMethod::getAttributes\(\)#'
- '#ReflectionClass<mixed>::getAttributes\(\)#'
- '#ReflectionClass<object>::getAttributes\(\)#'
- '#Constructor of class ApiPlatform\\Core\\Annotation\\ApiResource has an unused parameter#'
- '#Constructor of class ApiPlatform\\Core\\Annotation\\ApiProperty has an unused parameter#'

Expand All @@ -118,9 +118,3 @@ parameters:
-
message: "#Call to function method_exists\\(\\) with ApiPlatform\\\\Core\\\\JsonApi\\\\Serializer\\\\ItemNormalizer and 'setCircularReferenc…' will always evaluate to false\\.#"
path: tests/JsonApi/Serializer/ItemNormalizerTest.php
# Waiting to be fixed by https://github.com/Roave/BetterReflection/issues/663
-
message: '#Call to private method getNestedFieldPath\(\) of class ApiPlatform\\Core\\Bridge\\Elasticsearch\\DataProvider\\Filter\\AbstractFilter\.#'
paths:
- src/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php
- src/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php
4 changes: 2 additions & 2 deletions src/Annotation/ApiResource.php
Expand Up @@ -148,7 +148,7 @@ final class ApiResource
* @param bool|array $mercure https://api-platform.com/docs/core/mercure
* @param bool $messenger https://api-platform.com/docs/core/messenger/#dispatching-a-resource-through-the-message-bus
* @param array $normalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups
* @param array $openapiContext https://api-platform.com/docs/core/swagger/#using-the-openapi-and-swagger-contexts
* @param array $openapiContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts
* @param array $order https://api-platform.com/docs/core/default-order/#overriding-default-order
* @param string|false $output https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation
* @param bool $paginationClientEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource-1
Expand All @@ -167,7 +167,7 @@ final class ApiResource
* @param string $securityPostDenormalizeMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message
* @param bool $stateless
* @param string $sunset https://api-platform.com/docs/core/deprecations/#setting-the-sunset-http-header-to-indicate-when-a-resource-or-an-operation-will-be-removed
* @param array $swaggerContext https://api-platform.com/docs/core/swagger/#using-the-openapi-and-swagger-contexts
* @param array $swaggerContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts
* @param array $validationGroups https://api-platform.com/docs/core/validation/#using-validation-groups
* @param int $urlGenerationStrategy
*
Expand Down
5 changes: 5 additions & 0 deletions src/Annotation/ApiSubresource.php
Expand Up @@ -20,6 +20,9 @@
*
* @Annotation
* @Target({"METHOD", "PROPERTY"})
* @Attributes(
* @Attribute("maxDepth", type="int"),
* )
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)]
final class ApiSubresource
Expand All @@ -36,6 +39,8 @@ public function __construct($maxDepth = null)
{
if (!\is_array($maxDepth)) { // @phpstan-ignore-line
$this->maxDepth = $maxDepth;
} else {
$this->maxDepth = $maxDepth['maxDepth'] ?? null;
}
}
}
Expand Up @@ -213,7 +213,7 @@ private function publishUpdate($object, array $options, string $type): void
// and I'm not a fond of this approach.
$iri = $options['topics'] ?? $object->iri;
/** @var string $data */
$data = $options['data'] ?? json_encode(['@id' => $object->id]);
$data = json_encode(['@id' => $object->id]);
} else {
$resourceClass = $this->getObjectClass($object);
$context = $options['normalization_context'] ?? $this->resourceMetadataFactory->create($resourceClass)->getAttribute('normalization_context', []);
Expand Down
Expand Up @@ -72,15 +72,20 @@ public function collect(Request $request, Response $response, \Throwable $except
++$counters['ignored_filters'];
}

$requestAttributes = RequestAttributesExtractor::extractAttributes($request);
if (isset($requestAttributes['previous_data'])) {
$requestAttributes['previous_data'] = $this->cloneVar($requestAttributes['previous_data']);
}

$this->data = [
'resource_class' => $resourceClass,
'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null,
'acceptable_content_types' => $request->getAcceptableContentTypes(),
'request_attributes' => RequestAttributesExtractor::extractAttributes($request),
'filters' => $filters,
'counters' => $counters,
'dataProviders' => [],
'dataPersisters' => ['responses' => []],
'request_attributes' => $requestAttributes,
];

if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) {
Expand Down
Expand Up @@ -73,7 +73,7 @@ private function tracePersisters($data, array $context = [])
$found = false;
foreach ($this->persisters as $persister) {
if (
($this->persistersResponse[\get_class($persister)] = $found ? false : $persister->supports($data))
($this->persistersResponse[\get_class($persister)] = $found ? false : $persister->supports($data, $context))
&&
!($persister instanceof ResumableDataPersisterInterface && $persister->resumable()) && !$found
) {
Expand Down
Expand Up @@ -185,7 +185,7 @@ private function registerCommonConfiguration(ContainerBuilder $container, array
$container->setParameter('api_platform.collection.exists_parameter_name', $config['collection']['exists_parameter_name']);
$container->setParameter('api_platform.collection.order', $config['defaults']['order'] ?? $config['collection']['order']);
$container->setParameter('api_platform.collection.order_parameter_name', $config['collection']['order_parameter_name']);
$container->setParameter('api_platform.collection.pagination.enabled', $this->isConfigEnabled($container, $config['defaults']['pagination_enabled'] ?? $config['collection']['pagination']));
$container->setParameter('api_platform.collection.pagination.enabled', $config['defaults']['pagination_enabled'] ?? $this->isConfigEnabled($container, $config['collection']['pagination']));
$container->setParameter('api_platform.collection.pagination.partial', $config['defaults']['pagination_partial'] ?? $config['collection']['pagination']['partial']);
$container->setParameter('api_platform.collection.pagination.client_enabled', $config['defaults']['pagination_client_enabled'] ?? $config['collection']['pagination']['client_enabled']);
$container->setParameter('api_platform.collection.pagination.client_items_per_page', $config['defaults']['pagination_client_items_per_page'] ?? $config['collection']['pagination']['client_items_per_page']);
Expand Down Expand Up @@ -397,6 +397,10 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array
$container->setParameter('api_platform.enable_swagger_ui', $config['enable_swagger_ui']);
$container->setParameter('api_platform.enable_re_doc', $config['enable_re_doc']);
$container->setParameter('api_platform.swagger.api_keys', $config['swagger']['api_keys']);

if (true === $config['openapi']['backward_compatibility_layer']) {
$container->getDefinition('api_platform.swagger.normalizer.documentation')->addArgument($container->getDefinition('api_platform.openapi.normalizer'));
}
}

private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void
Expand Down
Expand Up @@ -483,6 +483,7 @@ private function addOpenApiSection(ArrayNodeDefinition $rootNode): void
->scalarNode('email')->defaultNull()->info('The email address of the contact person/organization. MUST be in the format of an email address.')->end()
->end()
->end()
->booleanNode('backward_compatibility_layer')->defaultTrue()->info('Enable this to decorate the "api_platform.swagger.normalizer.documentation" instead of decorating the OpenAPI factory.')->end()
->scalarNode('termsOfService')->defaultNull()->info('A URL to the Terms of Service for the API. MUST be in the format of a URL.')->end()
->arrayNode('license')
->addDefaultsIfNotSet()
Expand Down
4 changes: 2 additions & 2 deletions src/Bridge/Symfony/Bundle/Resources/config/api.xml
Expand Up @@ -275,11 +275,11 @@
</service>

<service id="api_platform.identifier.integer" class="ApiPlatform\Core\Identifier\Normalizer\IntegerDenormalizer" public="false">
<tag name="api_platform.identifier.denormalizer" />
<tag name="api_platform.identifier.denormalizer" priority="-100" />
</service>

<service id="api_platform.identifier.date_normalizer" class="ApiPlatform\Core\Identifier\Normalizer\DateTimeIdentifierDenormalizer" public="false">
<tag name="api_platform.identifier.denormalizer" />
<tag name="api_platform.identifier.denormalizer" priority="-100" />
</service>

<!-- Subresources -->
Expand Down
22 changes: 20 additions & 2 deletions src/Bridge/Symfony/Bundle/Resources/config/openapi.xml
Expand Up @@ -6,8 +6,26 @@

<services>
<service id="api_platform.openapi.normalizer" class="ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer" public="false">
<argument type="service" id="serializer.normalizer.object" />
<tag name="serializer.normalizer" priority="-785" />
<argument type="service">
<service class="Symfony\Component\Serializer\Serializer">
<argument type="collection">
<argument type="service">
<service class="Symfony\Component\Serializer\Normalizer\ObjectNormalizer">
<argument>null</argument>
<argument>null</argument>
<argument type="service" id="api_platform.property_accessor"/>
<argument type="service" id="api_platform.property_info"/>
</service>
</argument>
</argument>
<argument type="collection">
<argument type="service" id="serializer.encoder.json" />
</argument>
</service>
</argument>

<!-- Just after the DocumentationNormalizer see swagger.xml -->
<tag name="serializer.normalizer" priority="-795" />
</service>
<service id="ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer" alias="api_platform.openapi.normalizer" />

Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/ramsey_uuid.xml
Expand Up @@ -6,7 +6,7 @@

<services>
<service id="api_platform.identifier.uuid_normalizer" class="ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer" public="false">
<tag name="api_platform.identifier.denormalizer" />
<tag name="api_platform.identifier.denormalizer" priority="-100" />
</service>

<service id="api_platform.serializer.uuid_denormalizer" class="ApiPlatform\Core\Bridge\RamseyUuid\Serializer\UuidDenormalizer" public="false">
Expand Down
5 changes: 2 additions & 3 deletions src/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php
Expand Up @@ -20,7 +20,6 @@
use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface;
use PHPUnit\Framework\ExpectationFailedException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
Expand Down Expand Up @@ -112,14 +111,14 @@ public static function assertMatchesJsonSchema($jsonSchema, ?int $checkMode = nu

public static function assertMatchesResourceCollectionJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void
{
$schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::COLLECTION, $operationName, null, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]);
$schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::COLLECTION, $operationName, null);

static::assertMatchesJsonSchema($schema->getArrayCopy());
}

public static function assertMatchesResourceItemJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void
{
$schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::ITEM, $operationName, null, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]);
$schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::ITEM, $operationName, null);

static::assertMatchesJsonSchema($schema->getArrayCopy());
}
Expand Down
Expand Up @@ -29,7 +29,7 @@ class PropertySchemaRegexRestriction implements PropertySchemaRestrictionMetadat
*/
public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array
{
return isset($constraint->pattern) ? ['pattern' => $constraint->pattern] : [];
return $constraint instanceof Regex && $constraint->getHtmlPattern() ? ['pattern' => $constraint->getHtmlPattern()] : [];
}

/**
Expand Down

0 comments on commit 0d784fd

Please sign in to comment.