zircote/swagger-php

Accessing non-OA property attributes in processor

Closed this issue · 6 comments

I'm using swagger-php with a versioned symfony API, and am using JMS\Serializer attributes to handle the serialization itself.

I'm converting the docblock annotations over to attributes, but have encountered an issue that I'm not sure how to resolve.

Previously, I could have a property such as this:

/**
 * @OA\Property(
 *     description="Some property as an example",
 * ),
 * @JMS\Expose(),
 * @JMS\Since("1.2"),
 * @JMS\Until("1.3")
 */
protected $someProperty;

which I could run through a custom processor, grab the JMS annotations from the property _context->annotations, and then remove the properties that don't match the target spec version.

However since converting to attributes, it seems as though the AttributeAnnotationFactory will ignore any attributes that don't extend OA\AbstractAnnotation, leaving the processor unable to see any non-OA attributes. Before, _context->annotations contained both OA and non-OA annotations.

Do you have any recommendation on how to support this without duplicating the versioning information in something like attachables, or would you be open to somehow exposing a properties attributes in _context?

Thanks in advance!

Context might be an option. It's a bit outside of scope but I can see that it would be helpful for some.

Do you have an idea how you might implement that? I'm happy to contribute if that would be helpful (or even just fork, if it's not functionality you're wanting to merge in)

@brettgoss Created a PR that collects unrelated annotations/attributes in Context::other.

The change is implemented for both docblocks and attributes, so your current setup will now break on this.

Let me know if this works for you.

@DerManoMann pulled those changes down and it works great and completely solves what I'm trying to do! Thank you so much!

The only thing I noticed which I'll note here for anyone trying to do something similarly, is that I found I had to explicitly load the external annotations and pass them in to the generator as one of the sources. Otherwise the DocParser wouldn't detect the classes as existing.

Interestingly, that was only an issue for the first file being processed, and every subsequent file would have the additional external annotations.

But that's easy enough to work around by doing something like this (which will explicitly preload the JMS\Serializer annotations that I'm using in the processor):

$openApi = (new \OpenApi\Generator())
	->generate([
		\Symfony\Component\Finder\Finder::create()->files()
			->name('*.php')
			->in('vendor/jms/serializer/src/Annotation'),
		$otherFinders
	]);

Very strange - didn't you say you'd get annotations all loaded before?
For docblock all I changed was put them in a different place!
Smells like a autoloading issue to me.

Ah yeah, unrelated to the change - just noticed it while I was testing it out.

Anyway, thanks for the assistance! This is a super helpful improvement for our workflow!