Closed dmamchyts closed 2 months ago
cc @DerManoMann
I'm having the same issue, I'm not sure how to define the context in NelmioApiDocBundle to fix this
For more context for everyone, came from this merge: https://github.com/zircote/swagger-php/pull/1563
@DerManoMann What does one need to change when using https://github.com/nelmio/NelmioApiDocBundle do avoid this deprecation? I mean there must be a reason why you activated that deprecation, it's just very unclear how to not trigger this.
This is related to how the bundle instantiates annotations internally without passing in a context. There has been work to fix that, but obviously not enough. Admittedly, this is a part of swagger-php that is not structured very well.
We're also getting the deprecations in a Symfony project without NelmioApiDocBundle. However, they only occur on controllers where we use attributes instead of annotations to configure OA.
Some Nelmio Testcases just need to add a context - that should be fixable with some effort. However, there remains a special case: When using an attribute with TARGET_PARAMETER in Symfony in a controller, the framework instantiates the attribute. Therefore, theres no context available. The effect can be seen in that test Controller: https://github.com/nelmio/NelmioApiDocBundle/blob/master/tests/Functional/Controller/ApiController81.php#L462
which triggers in turn the Symfony arguments resolver which creates the metadata: https://github.com/symfony/symfony/blob/7.1/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php#L30
Then the attribute instantiation triggers the deprecation because of the missing context.
(at least thats my understanding).
In my opinion, it should be allowed to instantiate an annotation direclty (for such cases), but i am really not sure whats the best way to achieve that. An easy fix would be to set up a context in ParameterTrait if none is set and it doesnt exist in Generator::$context. But i dont know what the goal is with the $context in the future (and don't understand it thoroughly).
Trace:
array(5) {
[0]=>
array(6) {
["file"]=>
string(70) "/app/vendor/zircote/swagger-php/src/Annotations/AbstractAnnotation.php"
["line"]=>
int(103)
["function"]=>
string(6) "detect"
["class"]=>
string(15) "OpenApi\Context"
["type"]=>
string(2) "::"
["args"]=>
array(1) {
[0]=>
int(1)
}
}
[1]=>
array(6) {
["file"]=>
string(65) "/app/vendor/zircote/swagger-php/src/Attributes/ParameterTrait.php"
["line"]=>
int(65)
["function"]=>
string(11) "__construct"
["class"]=>
string(38) "OpenApi\Annotations\AbstractAnnotation"
["type"]=>
string(2) "->"
["args"]=>
array(1) {
[0]=>
array(16) {
["parameter"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["name"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["description"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["in"]=>
string(4) "path"
["required"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["deprecated"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["allowEmptyValue"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["ref"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["example"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["style"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["explode"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["allowReserved"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["spaceDelimited"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["pipeDelimited"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["x"]=>
string(28) "@OA\Generator::UNDEFINED🙈"
["value"]=>
array(0) {
}
}
}
}
[2]=>
array(6) {
["file"]=>
string(52) "/app/tests/Functional/Controller/ApiController81.php"
["line"]=>
int(462)
["function"]=>
string(11) "__construct"
["class"]=>
string(28) "OpenApi\Attributes\Parameter"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
[3]=>
array(6) {
["file"]=>
string(78) "/app/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php"
["line"]=>
int(30)
["function"]=>
string(11) "newInstance"
["class"]=>
string(19) "ReflectionAttribute"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
[4]=>
array(6) {
["file"]=>
string(50) "/app/src/RouteDescriber/RouteArgumentDescriber.php"
["line"]=>
int(42)
["function"]=>
string(22) "createArgumentMetadata"
["class"]=>
string(71) "Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory"
["type"]=>
string(2) "->"
["args"]=>
array(2) {
[0]=>
string(83) "Nelmio\ApiDocBundle\Tests\Functional\Controller\ApiController::inlinePathParameters"
[1]=>
object(ReflectionMethod)#429 (2) {
["name"]=>
string(20) "inlinePathParameters"
["class"]=>
string(63) "Nelmio\ApiDocBundle\Tests\Functional\Controller\ApiController81"
}
}
}
}
it seems that its not symfony itself, but the Routedescriber which just uses the ArgumentMetafactory: so its probably possible to save the generator context there (in NelmioApiDoc), replace it for the describer step and set the context back there.
@lhausammann - thanks for the investigation and summary.
I think you are correct in that it should be possible to instantiate attributes on their own without sideeffects... ~got some ideas~.
We could just use new Context()
here or just not trigger the deprecation. However, the fact is that having a context tree with a shared root context is a fundamental assumption in swagger-php.
So, detecting these cases is perhaps important as it might mean some annotations use the wrong openapi version during serialization or fail to use the correct logger.
Not sure why code would instantiate random attributes, tbh, but I suspect I do not have all the context required.
It would be nice to just use new Context()
and log a warning, but the logger is taken from the context and defaults to the NullLogger
... :/
NelmioApiBundle is probably the wrong place to fix that: I am able to reproduce that on a fresh symfony installation (without Nelmio Api Doc, just swagger-php):
add a controller with one route and one Annotation:
class AppController extends AbstractController
{
#[Get('/', description: 'Simple controller')]
#[Route('/', name: 'number', methods: ['GET'])]
public function number(): Response
{
$number = random_int(0, 100);
return new Response(
'<html><body>Lucky number: ' . $number . '</body></html>'
);
}
}
Its maybe(?) unfortunate that Symfony has to instantiate every attribute in order to make it available for controller methods for further processing(https://github.com/symfony/http-kernel/blob/7.0/Event/ControllerEvent.php#L107).
So it seems to me now that the behaviour should be fixed here in the swagger-php bundle.
Maybe a possible solution could be to create a context on the fly, but "mark" it somehow for further processing (and handle it separately if that is needed)? Im also not sure about the "warning" approach - in a symfony application that would generate and fill logs quickly.
Thanks for the details, some good inspiration in there.
Hi, after updating to zircote/swagger-php 4.9.0 many errors appeared:
We use symfony 7, nelmio/api-doc-bundle, codeception/codeception
Errors appeared in CLI after running command:
debug backtrace:
Example of OpenApi\Attributes usage:![image](https://github.com/zircote/swagger-php/assets/102530135/48cb1cbf-8a94-4a17-8f5c-321d97cc1818)