api-platform / core

The server component of API Platform: hypermedia and GraphQL APIs in minutes
https://api-platform.com
MIT License
2.43k stars 868 forks source link

Issues found on 2.7 #4613

Closed vincentchalamon closed 2 years ago

vincentchalamon commented 2 years ago

Write here as comment the errors you may found on api-platform/core:2.7.x-dev installed on your project. Please mention:

vincentchalamon commented 2 years ago

TypeError: App\Core\Api\IriConverter::__construct(): Argument #1 ($decorated) must be of type ApiPlatform\Core\Api\IriConverterInterface, ApiPlatform\Symfony\Routing\IriConverter given


# src/Core/Api/IriConverter.php
use ApiPlatform\Core\Api\IriConverterInterface;

final class IriConverter implements IriConverterInterface { public function __construct(private IriConverterInterface $decorated) { } }

```yaml
App\Core\Api\IriConverter:
    decorates: api_platform.iri_converter

Bug: api_platform.symfony.iri_converter decorates api_platform.iri_converter.legacy which breaks the backward compatibility. Fix: api_platform.symfony.iri_converter should not decorate api_platform.iri_converter.legacy but inject it as an argument.

vincentchalamon commented 2 years ago

Command executed: bin/console debug:event kernel.request -vvv

Fix: replace $deprecatedClasses by $deprecatedInterfaces in deprecation.php line 483

vincentchalamon commented 2 years ago

Cannot retrieve collection operation attribute:

$operationName = $request->attributes->get('_api_collection_operation_name'); // api_broadcast_programmings_get_collection
$resourceMetadata->getCollectionOperationAttribute($operationName, 'filters_expression'); // null

Collection operations:

array:1 [
  "get" => array:9 [
    "repository_method" => "getCollection"
    "filters_expression" => "request.query.get('segment') and (request.query.get('noEmiarte') or (request.query.get('intervalStartAt') and request.query.get('intervalEndAt')))"
    "filters_message" => "Query parameter "segment" is required with "noEmiarte" or "intervalEndAt" and "scenario"."
    "input" => null
    "output" => null
    "method" => "GET"
    "stateless" => null
    "input_formats" => array:4 [
      "jsonld" => array:1 [
        0 => "application/ld+json"
      ]
      "json" => array:1 [
        0 => "application/json"
      ]
      "html" => array:1 [
        0 => "text/html"
      ]
      "csv" => array:1 [
        0 => "text/csv"
      ]
    ]
    "output_formats" => array:4 [
      "jsonld" => array:1 [
        0 => "application/ld+json"
      ]
      "json" => array:1 [
        0 => "application/json"
      ]
      "html" => array:1 [
        0 => "text/html"
      ]
      "csv" => array:1 [
        0 => "text/csv"
      ]
    ]
  ]
]

Bug: invalid collection operation name, got get instead of api_broadcast_programmings_get_collection (or the contrary)

vincentchalamon commented 2 years ago

HTTP 400 invalid filters error message has changed from "detail": "..." to "hydra:description": "..."

vincentchalamon commented 2 years ago

final class PaginationExtension implements CollectionExtensionInterface, ResultCollectionExtensionInterface

```xml
<service id="arte_data.api_platform.extension.pagination" class="Arte\Data\Bridge\ApiPlatform\DataProvider\Extension\PaginationExtension" public="false">
    <argument type="service" id="api_platform.pagination"/>

    <tag name="arte_data.api_platform.collection_extension" priority="-1"/>
</service>
vincentchalamon commented 2 years ago

use ApiPlatform\Core\Api\FilterInterface as ApiFilterInterface;

interface FilterInterface extends ApiFilterInterface

vincentchalamon commented 2 years ago

PHP Fatal error: Cannot declare class ApiPlatform\State\Pagination\Pagination, because the name is already in use in /path/to/vendor/api-platform/core/src/Core/DataProvider/Pagination.php on line 29

vincentchalamon commented 2 years ago

You have requested a non-existent service "api_platform.doctrine.orm.metadata.property.metadata_factory"

Replace ApiPlatformExtension.php:873 by the following:

if ($this->isConfigEnabled($container, $config['doctrine'])) {
    $remapDefinitionClasses['api_platform.doctrine.orm.metadata.property.metadata_factory'] = 'ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory';
}
vincentchalamon commented 2 years ago

You have requested a non-existent service "api_platform.metadata.property.metadata_factory.legacy".

Remove api_platform.metadata.property.metadata_factory.xml from $remapDefinitionClasses in ApiPlatformExtension.php, and add the following before the $remapDefinitionClasses declaration:

$container->getDefinition('api_platform.metadata.property.metadata_factory.xml')->setClass('ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory');
$container->setAlias('api_platform.metadata.property.metadata_factory.legacy', 'api_platform.metadata.property.metadata_factory.xml');
vincentchalamon commented 2 years ago

PHP Fatal error: During class fetch: Uncaught ReflectionException: Class "ApiPlatform\Core\Cache\CachedTrait" not found while loading "ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyMetadataFactory".

Replace ApiPlatform\Core\Cache\CachedTrait by ApiPlatform\Util\CachedTrait in CachedPropertyMetadataFactory.php.

vincentchalamon commented 2 years ago

Attempted to load class "PropertyInfoPropertyMetadataFactory" from namespace "ApiPlatform\Metadata\Property". Did you forget a "use" statement for "ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory"?

Replace namespace ApiPlatform\Metadata\Property by ApiPlatform\Metadata\Property\Factory in PropertyInfoPropertyMetadataFactory.php.

vincentchalamon commented 2 years ago

ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::__construct(): Argument #1 ($extractor) must be of type ApiPlatform\Core\Metadata\Extractor\ExtractorInterface, ApiPlatform\Core\Metadata\Extractor\XmlExtractor given

Create ExtractorInterface.php as following:

interface ExtractorInterface extends ResourceExtractorInterface

...and implement it in legacy XmlExtractor and YamlExtractor.

vincentchalamon commented 2 years ago

Replace api_platform.property.metadata_factory by api_platform.metadata.property.metadata_factory in ApiPlatformExtension.php

vincentchalamon commented 2 years ago

ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyMetadataFactory::__construct(): Argument #2 ($decorated) must be of type ?ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface, ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory given

Related service: api_platform.metadata.property.identifier_metadata_factory.annotation Replace ApiPlatformExtension.php:852-856 with the following code:

        $remapDefinitionDecorations = [
            'api_platform.metadata.property.identifier_metadata_factory.xml',
            'api_platform.metadata.property.identifier_metadata_factory.yaml',
            'api_platform.metadata.property.identifier_metadata_factory.annotation',
        ];

        foreach ($remapDefinitionDecorations as $definition) {
            $container->getDefinition($definition)->setDecoratedService('api_platform.metadata.property.metadata_factory');
        }
vincentchalamon commented 2 years ago

TypeError: ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyMetadataFactory::withDeprecatedAttributes(): Argument #1 ($propertyMetadata) must be of type ApiPlatform\Metadata\ApiProperty, ApiPlatform\Core\Metadata\Property\PropertyMetadata given, called in /home/les-tilleuls/Sites/api-platform/core/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php on line 160

dgfmdrv commented 2 years ago

php 8.0.12

Hello,

php bin/console debug:event kernel.request -vvv

In DefinitionErrorExceptionPass.php line 54:

  [Symfony\Component\DependencyInjection\Exception\RuntimeException]
  Cannot autowire service "annotated_app_entity_g_e_s_a_c_activo_api_platform_doctrine_orm_filter_search_filter": arg
  ument "$iriConverter" of method "ApiPlatform\Doctrine\Orm\Filter\SearchFilter::__construct()" has no type-hint, you
   should configure its value explicitly.

Exception trace:
  at C:\appbackend\vendor\symfony\dependency-injection\Compiler\DefinitionErrorExceptionPass.php:54
 Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass->processValue() at C:\appbackend\vendor\symfony\dependency-injection\Compiler\AbstractRecursivePass.php:82
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->processValue() at C:\appbackend\vendor\symfony\dependency-injection\Compiler\DefinitionErrorExceptionPass.php:32
 Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass->processValue() at C:\appbackend\vendor\symfony\dependency-injection\Compiler\AbstractRecursivePass.php:47
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->process() at C:\appbackend\vendor\symfony\dependency-injection\Compiler\Compiler.php:91
 Symfony\Component\DependencyInjection\Compiler\Compiler->compile() at C:\appbackend\vendor\symfony\dependency-injection\ContainerBuilder.php:744
 Symfony\Component\DependencyInjection\ContainerBuilder->compile() at C:\appbackend\vendor\symfony\http-kernel\Kernel.php:545
 Symfony\Component\HttpKernel\Kernel->initializeContainer() at C:\appbackend\vendor\symfony\http-kernel\Kernel.php:786
 Symfony\Component\HttpKernel\Kernel->preBoot() at C:\appbackend\vendor\symfony\http-kernel\Kernel.php:125
 Symfony\Component\HttpKernel\Kernel->boot() at C:\appbackend\vendor\symfony\framework-bundle\Console\Application.php:168
 Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands() at C:\appbackend\vendor\symfony\framework-bundle\Console\Application.php:74
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at C:\appbackend\vendor\symfony\console\Application.php:167
 Symfony\Component\Console\Application->run() at C:\appbackend\bin\console:43

C:\appbackend\vendor\api-platform\core\src\Doctrine\Orm\Filter\SearchFilter.php

public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack, $iriConverter, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, IdentifiersExtractorInterface $identifiersExtractor = null, NameConverterInterface $nameConverter = null)
    {

IriConverterInterface $iriConverter

divine commented 2 years ago

Hello,

This issue should probably pinned, anyways here is another "error":

In DecoratorServicePass.php line 80:

The service "api_platform.doctrine_mongodb.odm.metadata.property.identifier_metadata_factory" has a dependency on a non-existent service "api_platform.metadata.property.identifier_metadata_factory".                             

Thanks!

darthf1 commented 2 years ago

Hi!

On composer update with "api-platform/core": "v2.7.0-alpha.1" (same on 2.7.x-dev):

Executing script cache:clear [KO]
 [KO]
Script cache:clear returned with error code 1
!!  
!!  In DefinitionErrorExceptionPass.php line 54:
!!                                                                                 
!!    Cannot autowire service "annotated_user_interface_bank_rest_bank_account_pr  
!!    ojection_api_platform_elasticsearch_filter_order_filter": argument "$proper  
!!    tyMetadataFactory" of method "ApiPlatform\Elasticsearch\Filter\OrderFilter:  
!!    :__construct()" has no type-hint, you should configure its value explicitly  
!!    .                                                                            
!!                                                                                 
!!  
!!  
Script @auto-scripts was called via post-update-cmd

Edit: fixed by https://github.com/api-platform/core/pull/4718. Thanks @soyuka

zakjakub commented 2 years ago

.env

VARNISH_URL='localhost:6082'

api-platform.yaml

    http_cache:
        invalidation:
            enabled: true
            varnish_urls: ['%env(VARNISH_URL)%']
        public: true

    defaults:
        cache_headers:
            max_age: 0
            shared_max_age: 3600
            vary: ['Content-Type', 'Authorization', 'Origin']

On 2.6.* it works without error message.

RobinHoutevelts commented 2 years ago

TypeError : ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\CollectionDataProvider::__construct(): Argument #5 ($pagination) must be of type ApiPlatform\State\Pagination\Pagination, ApiPlatform\Core\DataProvider\Pagination given

The CollectionDataProvider is configured to use ApiPlatform\State\Pagination\Pagination which is the api_platform.pagination service.

However in the legacy/backward_compatibility.xml config the api_platform.pagination service is overwritten and marked an alias for api_platform.pagination.legacy, causing an error when fetching the CollectionDataProvider from the container.

soyuka commented 2 years ago

@dgfmdrv should be fixed since https://github.com/api-platform/core/commit/e21a01aed0c1f8f83a3c6fe9f281c388c1a96276

soyuka commented 2 years ago

@zakjakub I fixed this on main I think it'll be fixed in the next alpha version

Thanks to everyone, I'm working on improving the Elasticsearch support as per comment.

darthf1 commented 2 years ago

A small one. After https://github.com/api-platform/core/pull/4718 no errors after composer install. Running my test suite I get:

Error : Undefined constant ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::FORMAT

If I put this in manually, my test suite passes. I'm on php 8.1, symfony 6.0.x, have 290 functional tests for endpoint testing, using doctrine, elasticsearch and custom search filters.

soyuka commented 2 years ago

Oh my bad I didn't wanted to close this one let's leave it open for upcoming issues.

jonag commented 2 years ago

Hello, I'm testing the new version (2.7.0-alpha.2) on a fairly simple project (for now). The compatibility layer seems to work just fine as everything still work correctly so far after the upgrade.

Now I want to play with the new metadata system so I ran the command api:upgrade-resource and I have two remarks:

Anyway thanks for the good work, this new version looks very promising 👏

dannyvw commented 2 years ago

PHP 8.0 Symfony 5.4 API Platform 2.7.0-alpha.2 (metadata_backward_compatibility_layer: false)

Not an error but some deprecations. Both are logged a few hundred times.

User Deprecated: Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.

User Deprecated: "ApiPlatform\Core\Metadata\Property\PropertyMetadata::ApiPlatform\Core\Metadata\Property\PropertyMetadata::isChildInherited" is deprecated since 2.4 and will be removed in 3.0.

This one is called but there are no subresources configured User Deprecated: Since api-platform/core 2.7: Subresources are deprecated, use alternate URLs instead.

soyuka commented 2 years ago

Thanks so much for the feedbacks.

@jonag

the command changed the code style of all my API resources : I'm not sure it will be possible to do something to prevent that. It will take some time to fix the CS after the command, but that's ok.

Don't you have some kind of php-cs-fixer to help you with that? I've tried my best but indeed php-parser does change the code style :/.

the command correctly upgraded almost all my metadata but completely ignored everything related to subresources: the #[ApiSubresource] attribute stayed in place (but its import has been removed) all the operations defined in subresourceOperations are gone. A line with use ApiPlatform\Metadata\Link; has been added but is not used. Is that intended and I should upgrade these operations manually, or is there an issue with my code or the command?

Are you sure ? It should've built new Operations on the concern Resource. Say you have a subresource that returns Address on Book, check your Address resource, there should be a new #[Get] operation using the old subresource metadata. In API Platform 3, a subresource is just another resource. Links are there to specify links between resources, you can read more on the subject here: https://api-platform.com/docs/main/core/subresources/ (make sure you're on the 2.7 branch).

soyuka commented 2 years ago

@dannyvw mhh on a fresh project these don't show up, are you sure you're not using any of the deprecated interfaces? Would it be possible for you to give me stack traces or a way to reproduce? Thanks!

I have one myself about childInherited I'll track this one and check if I can give you a way to remove it.

dannyvw commented 2 years ago

@soyuka I don't use the interface(s) in any custom code. API Platform is added in an existing project with a few new resources and the new metadata system with configuration in XML.

I will try this week to create a stack trace or a reproducer.

darthf1 commented 2 years ago

With v2.7.0-alpha.2 a few errors pop up in my tests. See stacktraces below. Let me know if you need more to continue.

Also: has the ApiPlatform\Core\Validator\ValidatorInterface been removed?


Error : Typed property Application\Engagement\Command\ChangePhaseCommand::$engagementId must not be accessed before initialization
 /home/www/app/src/Application/Engagement/Validation/ChangePhaseEngagementMustHaveThreeRequiredPhasesConstraintValidator.php:50
 /home/www/app/vendor/symfony/validator/Validator/RecursiveContextualValidator.php:758
 /home/www/app/vendor/symfony/validator/Validator/RecursiveContextualValidator.php:603
 /home/www/app/vendor/symfony/validator/Validator/RecursiveContextualValidator.php:517
 /home/www/app/vendor/symfony/validator/Validator/RecursiveContextualValidator.php:314
 /home/www/app/vendor/symfony/validator/Validator/RecursiveContextualValidator.php:139
 /home/www/app/vendor/symfony/validator/Validator/RecursiveValidator.php:97
 /home/www/app/vendor/symfony/validator/Validator/TraceableValidator.php:67
 /home/www/app/vendor/api-platform/core/src/Symfony/Validator/Validator.php:67
 /home/www/app/vendor/api-platform/core/src/Symfony/EventListener/ValidateListener.php:97
 /home/www/app/src/Infrastructure/Shared/ApiPlatform/Listener/ValidateListener.php:41
 /home/www/app/vendor/symfony/event-dispatcher/Debug/WrappedListener.php:111
 /home/www/app/vendor/symfony/event-dispatcher/EventDispatcher.php:230
 /home/www/app/vendor/symfony/event-dispatcher/EventDispatcher.php:59
 /home/www/app/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:152
 /home/www/app/vendor/symfony/http-kernel/HttpKernel.php:157
 /home/www/app/vendor/symfony/http-kernel/HttpKernel.php:74
 /home/www/app/vendor/symfony/http-kernel/Kernel.php:202
 /home/www/app/vendor/symfony/http-kernel/HttpKernelBrowser.php:65
 /home/www/app/vendor/symfony/framework-bundle/KernelBrowser.php:172
 /home/www/app/vendor/symfony/browser-kit/AbstractBrowser.php:370
 /home/www/app/vendor/api-platform/core/src/Symfony/Bundle/Test/Client.php:124
 /home/www/app/tests/Functional/UserInterface/Engagement/Rest/EngagementProjectionTest.php:1251
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestResult.php:726
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:673

Failed asserting that the Response status code is 404.
HTTP/1.1 202 Accepted
Accept-Patch:           application/merge-patch+json
Cache-Control:          no-cache, private
Content-Language:       en
Content-Type:           application/ld+json; charset=utf-8
Date:                   Tue, 26 Apr 2022 13:58:51 GMT
Link:                   <https://localhost/v1/docs?_format=jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
Permissions-Policy:     browsing-topics=()
Vary:                   Accept
Vary:                   Accept-Language
X-Content-Type-Options: nosniff
X-Frame-Options:        deny
X-Robots-Tag:           noindex

 /home/www/app/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:121
 /home/www/app/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
 /home/www/app/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php:142
 /home/www/app/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php:38
 /home/www/app/tests/Functional/UserInterface/Engagement/Rest/EngagementProjectionTest.php:1394
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestResult.php:726
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:673


Failed asserting that the Response is successful.
HTTP/1.1 422 Unprocessable Content
Cache-Control:          no-cache, private
Content-Language:       en
Content-Type:           application/ld+json; charset=utf-8
Date:                   Tue, 26 Apr 2022 14:01:06 GMT
Link:                   <https://localhost/v1/docs?_format=jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
Permissions-Policy:     browsing-topics=()
Vary:                   Accept-Language
X-Content-Type-Options: nosniff
X-Frame-Options:        deny
X-Robots-Tag:           noindex

{"@context":"\/v1\/contexts\/ConstraintViolationList","@type":"ConstraintViolationList","hydra:title":"An error occurred","hydra:description":"memberId: This value should be of type Domain\\Organisation\\MemberId.","violations":[{"propertyPath":"memberId","message":"This value should be of type Domain\\Organisation\\MemberId.","code":null}]}
 /home/www/app/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:121
 /home/www/app/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
 /home/www/app/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php:142
 /home/www/app/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php:33
 /home/www/app/tests/Functional/UserInterface/Organisation/Rest/OrganisationProjectionTest.php:848
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestResult.php:726
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:673

soyuka commented 2 years ago

@dannyvw I've tracked some of them and actually managed to reproduce them, I'll let you know when this is fixed. It occurs because we've a backward-compatibility layer in metadata_backward_compatibility_layer: false that reads the old metadata as well. It may trigger some deprecations even though you don't have any legacy code.

@darthf1 weird these didn't threw in alpha.1? I didn't change anything regarding validation, however if you have custom providers or data transformers things have changed and I've documented them at https://api-platform.com/docs/main/core/upgrade-guide/

soyuka commented 2 years ago

Actually I've tagged a bit too quick on the fixed deprecations, this branch should now do the job: https://github.com/api-platform/core/pull/4730 I need to add some tests, expect an alpha.3 soon as the alpha.2 may have a bad parameter injection that breaks implementations.

darthf1 commented 2 years ago

@darthf1 weird these didn't threw in alpha.1? I didn't change anything regarding validation, however if you have custom providers or data transformers things have changed and I've documented them at https://api-platform.com/docs/main/core/upgrade-guide/

I tried again commit per commit to see where the error happened. alpha.1 was not successful for me due to this. So I started testing with 478606e28ce9633f8c4f63b48680fb4a421f5272 and going up a commit and testing again.

From: https://github.com/api-platform/core/commits/main:

I also noticed:

include_once(/home/www/app/vendor/api-platform/core/src/Core/DataTransformer/DataTransformerInterface.php): Failed to open stream: No such file or directory
 /home/www/app/var/cache/test/ContainerHOWZlcL/getApiPlatform_Messenger_DataTransformerService.php:20
 /home/www/app/var/cache/test/ContainerHOWZlcL/getApiPlatform_Messenger_DataTransformerService.php:20
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:803
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:1732
 /home/www/app/vendor/api-platform/core/src/Serializer/AbstractItemNormalizer.php:116
 /home/www/app/vendor/api-platform/core/src/JsonLd/Serializer/ItemNormalizer.php:51
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:1733
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:1721
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:4881
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:1609
 /home/www/app/var/cache/test/ContainerHOWZlcL/Infrastructure_Shared_Symfony_KernelTestDebugContainer.php:1597
 /home/www/app/var/cache/test/ContainerHOWZlcL/IndexManager_33f44ce.php:70
 /home/www/app/var/cache/test/ContainerHOWZlcL/IndexManager_33f44ce.php:70
 /home/www/app/tests/Functional/Fixture/UserTestFixture.php:51
 /home/www/app/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php:119
 /home/www/app/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:74
 /home/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:245
 /home/www/app/var/cache/test/ContainerHOWZlcL/EntityManager_9a5be93.php:66
 /home/www/app/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:76
 /home/www/app/vendor/liip/test-fixtures-bundle/src/Services/DatabaseTools/ORMSqliteDatabaseTool.php:95
 /home/www/app/tests/Functional/FixtureTestCase.php:37
 /home/www/app/tests/Functional/UserInterface/GeneralLedger/Rest/JournalEntryProjectionTest.php:906
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestResult.php:726
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/Framework/TestSuite.php:677
 /home/www/app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:673
soyuka commented 2 years ago

Thanks @darthf1 doesn't the file /home/www/app/vendor/api-platform/core/src/Core/DataTransformer/DataTransformerInterface.php exists? I see it on the main branch I don't understand why it'd throw.

fbourigault commented 2 years ago

It looks like annotations are required while creating a minimal project:

symfony new apip
cd apip
symfony composer req api-platform/core ^2.7@alpha

Produce this error: The service "api_platform.metadata.subresource.metadata_factory.annotation.legacy" has a dependency on a non-existent service "annotation_reader".

PHP 8.1

dannyvw commented 2 years ago

PHP 8.0 Symfony 5.4 API Platform 2.7.0-alpha.2 (metadata_backward_compatibility_layer: false)

Force iri relations (https://api-platform.com/docs/main/core/serialization/#force-iri-with-relations-of-the-same-type-parentchilds-relations) with XML configuration does not work.

XML Configuration

<?xml version="1.0" ?>
<properties xmlns="https://api-platform.com/schema/metadata/properties-3.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="https://api-platform.com/schema/metadata/properties-3.0
           https://api-platform.com/schema/metadata/properties.xsd">
    <property resource="App\Entity\Person" name="parent" writableLink="false" readableLink="false" />
</properties>

But when adding the attribute to the var parent it works.

class Person
{
   #[ApiProperty(readableLink: false, writableLink: false)]
   public Person $parent;
}
darthf1 commented 2 years ago

Thanks @darthf1 doesn't the file /home/www/app/vendor/api-platform/core/src/Core/DataTransformer/DataTransformerInterface.php exists? I see it on the main branch I don't understand why it'd throw.

@soyuka I'm not sure what happened but I just checked out a84b6d447b16215554739f08bce9d32b8aebbfb1 and everything is green again. :D

I do have some phpstan errors popping up (not necessarily because of this commit, i just haven't checked earlier), I'm not sure if you want to cover all of these too:

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   src/Infrastructure/Shared/ApiPlatform/Bridge/Elasticsearch/DocumentMetadataFactory.php                                                                                                                           
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  106    Property Infrastructure\Shared\ApiPlatform\Bridge\Elasticsearch\DocumentMetadataFactory::$cachedIndexedNames (array<string, ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata>) does not  
         accept array<string, ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata>.                                                                                                                              
  108    Method Infrastructure\Shared\ApiPlatform\Bridge\Elasticsearch\DocumentMetadataFactory::create() should return ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata but returns               
         ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata.                                                                                                                                                    
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   src/Infrastructure/Shared/ApiPlatform/OpenApi/OpenApiFactory.php                                                                                                     
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  50     Method Infrastructure\Shared\ApiPlatform\OpenApi\OpenApiFactory::__invoke() should return ApiPlatform\Core\OpenApi\OpenApi but returns ApiPlatform\OpenApi\OpenApi.  
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   tests/Functional/FunctionalTestCase.php                                                                                                                                          
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  36     Method Tests\Functional\FunctionalTestCase::createClient() should return ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client but returns ApiPlatform\Symfony\Bundle\Test\Client.  
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   tests/Functional/Infrastructure/Shared/ApiPlatform/DataProvider/Extension/CompositeAggregationExtensionTest.php                                                                                          
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  35     Parameter #2 $propertyNameCollectionFactory of class Infrastructure\Shared\ApiPlatform\DataProvider\Extension\CompositeAggregationExtension constructor expects                                          
         ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface, ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory given.                                           
  37     Parameter #4 $resourceClassResolver of class Infrastructure\Shared\ApiPlatform\DataProvider\Extension\CompositeAggregationExtension constructor expects ApiPlatform\Api\ResourceClassResolverInterface,  
         ApiPlatform\Api\ResourceClassResolver given.                                                                                                                                                             
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
darthf1 commented 2 years ago

When I run php bin/console api:upgrade-resource on a84b6d447b16215554739f08bce9d32b8aebbfb1, it messes with my white spaces inside the resource class, not directly related to the upgraded attributes:

image image image

I think these can be fixed with php-cs-fixer, but I'm not sure this is intended or can be prevented.

soyuka commented 2 years ago

@darthf1 Hi, yes the changed lines not related are a side effect of the PHPParser library... I think it should be fixed upstream but anyways php-cs-fixer should fix these. As this script is a short-living one I don't think we should put much effort in it though. About the new phpstan issues you have, you should implement the interfaces in ApiPlatform\OpenApi not ApiPlatform\Core\OpenApi and it should fix the issue.

I tagged a 2.7-alpha.3, let me know if there are still backward compatibility issues.

darthf1 commented 2 years ago

@darthf1 Hi, yes the changed lines not related are a side effect of the PHPParser library... I think it should be fixed upstream but anyways php-cs-fixer should fix these. As this script is a short-living one I don't think we should put much effort in it though. About the new phpstan issues you have, you should implement the interfaces in ApiPlatform\OpenApi not ApiPlatform\Core\OpenApi and it should fix the issue.

I tagged a 2.7-alpha.3, let me know if there are still backward compatibility issues.

Ok! Yeah I was only wondering whether or not you'd consider the phpstan issues as breaking issues as well. I'm fine either way.

I'm away this week, I'll test alpha 3 next week and let you know if any issues arise.

soyuka commented 2 years ago

Its more a bug with phpstan, these classes are aliased and are the same (https://github.com/api-platform/core/blob/main/src/OpenApi/OpenApi.php#L178) :/

jonag commented 2 years ago

Are you sure ? It should've built new Operations on the concern Resource. Say you have a subresource that returns Address on Book, check your Address resource, there should be a new #[Get] operation using the old subresource metadata. In API Platform 3, a subresource is just another resource. Links are there to specify links between resources, you can read more on the subject here: https://api-platform.com/docs/main/core/subresources/ (make sure you're on the 2.7 branch).

I tried again with the latest alpha (2.7.0-alpha.3) and here is the result :

Metadata before the command

<?php

#[ApiResource(
    collectionOperations: [
        'get' => [
            'security' => 'is_granted(\'GET_COLLECTION\', object)',
            'normalization_context' => ['groups' => ['rapport:getAll']],
        ],
        'post' => [
            'security_post_denormalize' => 'is_granted(\'POST_COLLECTION\', object)',
            'denormalization_context' => ['groups' => ['rapport:create']],
            'normalization_context' => ['groups' => ['rapport:created']],
            'validation_groups' => ['Default', 'rapport:create'],
        ],
    ],
    itemOperations: [
        'get' => [
            'security' => 'is_granted(\'GET_ITEM\', object)',
            'normalization_context' => ['groups' => ['rapport:get']],
        ],
        'put' => [
            'security' => 'is_granted(\'PUT_ITEM\', object)',
            'denormalization_context' => ['groups' => ['rapport:update']],
            'normalization_context' => ['groups' => ['rapport:updated']],
        ],
    ],
    subresourceOperations: [
        'rapport_modalite_accompagnements_get_subresource' => [
            'path' => '/rapports/{id}/modalite_accompagnements',
        ],
        'rapport_changement_statuts_get_subresource' => [
            'path' => '/rapports/{id}/historique',
        ],
    ],
    order: ['periode' => 'ASC']
)]
#[ApiFilter(SearchFilter::class, properties: [
    'entite' => 'exact',
    'entite.directionActivite' => 'exact',
    'periode' => 'start',
    'statut' => 'exact',
    'agrement' => 'exact',
])]
#[ApiFilter(OrderFilter::class, properties: [
    'entite.nom',
    'agrement.nom',
    'periode',
    'statut',
])]
class Rapport
{
    // ...

    /**
     * @var Collection<int, \App\Entity\IndicateurValeur>
     */
    #[ORM\OneToMany(mappedBy: 'rapport', targetEntity: IndicateurValeur::class)]
    #[ApiSubresource()]
    #[Groups([
        'rapport:update',
    ])]
    #[Assert\Valid]
    private Collection $valeurs;

    // ...
}
#[ApiResource(
    collectionOperations: [
        'get' => [
            'controller' => NotFoundAction::class,
            'read' => false,
            'output' => false,
        ],
    ],
    itemOperations: [
        'get' => [
            'controller' => NotFoundAction::class,
            'read' => false,
            'output' => false,
        ],
    ],
    subresourceOperations: [
        'api_rapports_valeurs_get_subresource' => [
            'security' => 'is_granted(\'GET_COLLECTION\', object)',
            'normalization_context' => ['groups' => ['indicateurValeur:getAll']],
        ],
    ],
    paginationEnabled: false,
)]
class IndicateurValeur
{
    // ...
}

Metadata after the command

<?php

#[ApiResource(
    operations: [
        new Get(
            security: 'is_granted(\'GET_ITEM\', object)',
            normalizationContext: ['groups' => ['rapport:get']]
        ),
        new Put(
            security: 'is_granted(\'PUT_ITEM\', object)',
            denormalizationContext: ['groups' => ['rapport:update']],
            normalizationContext: ['groups' => ['rapport:updated']]
        ),
        new GetCollection(
            security: 'is_granted(\'GET_COLLECTION\', object)',
            normalizationContext: ['groups' => ['rapport:getAll']]
        ),
        new Post(
            securityPostDenormalize: 'is_granted(\'POST_COLLECTION\', object)',
            denormalizationContext: ['groups' => ['rapport:create']],
            normalizationContext: ['groups' => ['rapport:created']],
            validationContext: ['groups' => ['Default', 'rapport:create']]
        )
    ],
    order: ['periode' => 'ASC']
)]
#[ApiFilter(SearchFilter::class, properties: [
    'entite' => 'exact',
    'entite.directionActivite' => 'exact',
    'periode' => 'start',
    'statut' => 'exact',
    'agrement' => 'exact'
])]
#[ApiFilter(OrderFilter::class, properties: [
    'entite.nom', 
    'agrement.nom', 
    'periode', 
    'statut']
)]
class Rapport
{
    // ...

    #[ORM\OneToMany(mappedBy: 'rapport', targetEntity: IndicateurValeur::class)]
    #[ApiSubresource]
    #[Groups(['rapport:update'])]
    #[Assert\Valid]
    private Collection $valeurs;

    // ...
}
#[ApiResource(
    operations: [
        new Get(controller: NotFoundAction::class, read: false, output: false),
        new GetCollection(controller: NotFoundAction::class, read: false, output: false)
    ],
    paginationEnabled: false
)]
#[ORM\Entity(repositoryClass: IndicateurValeurRepository::class)]
#[ORM\UniqueConstraint(fields: ['indicateur', 'rapport', 'modaliteAccompagnement'])]
class IndicateurValeur
{
    // ...
}

The old operations on my resource IndicateurValeur have been converted but:

Maybe there is something wrong with my initial metadata (even if it's working) ?

dannyvw commented 2 years ago

API Platform v2.7.0-alpha.4

Decorating the OpenApiFactory which is described here https://api-platform.com/docs/main/core/openapi/#overriding-the-openapi-specification does not work because the service "api_platform.openapi.factory.next" is used in https://github.com/api-platform/core/blob/main/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml#L12 I think this should be api_platform.openapi.factory?

I am currently using this which works

    App\OpenApi\OpenApiFactory:
        decorates: 'api_platform.openapi.factory.next'
soyuka commented 2 years ago

@dannyvw I don't understand the service is declared and aliased:

20220506_10h08m24s_grim 20220506_10h08m46s_grim

@jonag thanks investing...

dannyvw commented 2 years ago

@soyuka Yes.. but the custom factory is not loaded. Only if I change https://github.com/api-platform/core/blob/main/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml#L12 to api_platform.openapi.factory or when using decorates: 'api_platform.openapi.factory.next'

soyuka commented 2 years ago

@dannyvw gotcha https://github.com/api-platform/core/pull/4748 should fix this thanks!

soyuka commented 2 years ago

@jonag https://github.com/api-platform/core/pull/4747 should fix yours also

soyuka commented 2 years ago

tagged both in 2.7.0-alpha.5

jonag commented 2 years ago

Thank you very much for your work 🤩

Here is the result of the command with the new alpha :

#[ApiResource(
    operations: [
        new Get(controller: NotFoundAction::class, read: false, output: false),
        new GetCollection(controller: NotFoundAction::class, read: false, output: false)
    ],
    paginationEnabled: false
)]
#[ApiResource(
    uriTemplate: '/rapports/{id}/valeurs.{_format}', 
    uriVariables: [
        'id' => new Link(fromClass: \App\Entity\Rapport::class, identifiers: ['id'])
    ], 
    status: 200, 
    operations: [new GetCollection()]
)]
#[ORM\Entity(repositoryClass: IndicateurValeurRepository::class)]
#[ORM\UniqueConstraint(fields: ['indicateur', 'rapport', 'modaliteAccompagnement'])]
class IndicateurValeur
{
    // ...
}

The subresource is now migrated, however :

Moreover, I don't know if this is connected with this last update but I can't access to the swagger UI anymore. A warning is trigerred :

Warning: Undefined array key "$ref" ErrorException: Warning: Undefined array key "$ref" at vendor/api-platform/core/src/JsonSchema/TypeFactory.php:153 at ApiPlatform\JsonSchema\TypeFactory->getClassType('App\\Entity\\RapportModaliteAccompagnement', 'jsonld', true, array('groups' => array('rapport:update')), object(Schema)) (vendor/api-platform/core/src/JsonSchema/TypeFactory.php:84) at ApiPlatform\JsonSchema\TypeFactory->makeBasicType(object(Type), 'jsonld', true, array('groups' => array('rapport:update')), object(Schema)) (vendor/api-platform/core/src/JsonSchema/TypeFactory.php:71) at ApiPlatform\JsonSchema\TypeFactory->getType(object(Type), 'jsonld', true, array('groups' => array('rapport:update')), object(Schema)) (vendor/api-platform/core/src/JsonSchema/TypeFactory.php:67) at ApiPlatform\JsonSchema\TypeFactory->getType(object(Type), 'jsonld', true, array('groups' => array('rapport:update')), object(Schema)) (vendor/api-platform/core/src/JsonSchema/SchemaFactory.php:269) at ApiPlatform\JsonSchema\SchemaFactory->buildPropertySchema(object(Schema), 'Rapport.jsonld-rapport.update', 'rapportModaliteAccompagnements', object(ApiProperty), array('groups' => array('rapport:update')), 'jsonld') (vendor/api-platform/core/src/JsonSchema/SchemaFactory.php:180) at ApiPlatform\JsonSchema\SchemaFactory->buildSchema('App\\Entity\\Rapport', 'jsonld', 'input', null, '_api_/rapports/{id}.{_format}_put', object(Schema), array('groups' => array('rapport:update')), false) (vendor/api-platform/core/src/Hydra/JsonSchema/SchemaFactory.php:75) at ApiPlatform\Hydra\JsonSchema\SchemaFactory->buildSchema('App\\Entity\\Rapport', 'jsonld', 'input', null, '_api_/rapports/{id}.{_format}_put', object(Schema), null, false) (vendor/api-platform/core/src/OpenApi/Factory/OpenApiFactory.php:262) at ApiPlatform\OpenApi\Factory\OpenApiFactory->collectPaths(object(ApiResource), object(ResourceMetadataCollection), object(Paths), object(ArrayObject)) (vendor/api-platform/core/src/OpenApi/Factory/OpenApiFactory.php:104) at ApiPlatform\OpenApi\Factory\OpenApiFactory->__invoke(array('base_url' => '/')) (vendor/api-platform/core/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php:66) at ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction->__invoke(object(Request)) (vendor/api-platform/core/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php:136) at ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction->__invoke(object(Request)) (vendor/symfony/http-kernel/HttpKernel.php:152) at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1) (vendor/symfony/http-kernel/HttpKernel.php:74) at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true) (vendor/symfony/http-kernel/Kernel.php:202) at Symfony\Component\HttpKernel\Kernel->handle(object(Request)) (vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:35) at Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() (vendor/autoload_runtime.php:29) at require_once('/srv/php/vendor/autoload_runtime.php') (public/index.php:5)

Unfortunately I won't be available next week to give you more insights, I hope it will be enough 🙏

soyuka commented 2 years ago

The ApiResource attribute is duplicated : is it intended ? Can I safely remove the first ? (If I'm not wrong it's mandatory to have a GET item operation with API Platform v2.6)

Yes :) you should read https://api-platform.com/docs/main/core/subresources/ (and let me know if it's not clear enough, thanks!)

The rest are things I should be able to fix, thanks for the feedbacks.