Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #1980 user defined property metadata takes precedence #1997

Merged
merged 1 commit into from
Aug 23, 2018

Conversation

soyuka
Copy link
Member

@soyuka soyuka commented Jun 3, 2018

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #1980
License MIT
Doc PR na

See issue.

@soyuka
Copy link
Member Author

soyuka commented Jun 3, 2018

ping @oxan @bendavies

@oxan
Copy link
Contributor

oxan commented Jun 3, 2018

I don't think this fixes #1994, as the SerializerPropertyMetadataFactory still overwrites information from the annotations. I think a check needs to be added in that factory to avoid overwriting existing information. I'm not sure that won't break anything though, as it also restricts the serializer factory from overwriting data coming from Doctrine and PropertyInfo.

@oxan
Copy link
Contributor

oxan commented Jun 3, 2018

Maybe it's better to leave the serializer factory alone and lower the priority of the annotation & extractor factories so that they run last (well, before the cache). Along with this PR to let them overwrite the present metadata, that should work fine. I checked and none of the existing factories seem to read from the metadata passed to them anyway (except to avoid overwriting), so I don't think it's a problem if they don't get the metadata configured by the user.

(Actually, where I'm talking about the serializer factory, we should really think about all factories that set metadata based on heuristics. It's just that in my case the metadata I defined was overwritten by the serializer factory, but that could happen with others as well).

@soyuka
Copy link
Member Author

soyuka commented Jun 4, 2018

Maybe it's better to leave the serializer factory alone and lower the priority of the annotation & extractor factories so that they run last (well, before the cache).

Yes I think that this is safer :p. I added a commit that does this.

@oxan
Copy link
Contributor

oxan commented Jun 4, 2018

Does Symfony guarantee an order of services with the same priority? Because the ValidatorPropertyMetadataFactory also has priority 20, so if no order is guaranteed the validator can still overwrite user-defined metadata.

@@ -134,10 +134,6 @@ private function createMetadata(ApiProperty $annotation, PropertyMetadata $paren
private function createWith(PropertyMetadata $propertyMetadata, array $property, $value): PropertyMetadata
{
$getter = $property[0].ucfirst($property[1]);
if (null !== $propertyMetadata->$getter()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be dropped. It's a BC break.

@@ -117,7 +117,7 @@ private function update(PropertyMetadata $propertyMetadata, array $metadata): Pr
];

foreach ($metadataAccessors as $metadataKey => $accessorPrefix) {
if (null === $metadata[$metadataKey] || null !== $propertyMetadata->{$accessorPrefix.ucfirst($metadataKey)}()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@bendavies
Copy link
Contributor

So I'd the factory can not be changed, the only possible fix is to alter the priority?

@dunglas
Copy link
Member

dunglas commented Jun 4, 2018

Yes. It's cleaner anyway. And it allows anybody to customize the order (by changing priorities).

@bendavies
Copy link
Contributor

But the factories are still weird in that some will overwrite, but some won't. Guess this can't be changed until 3.0?

@dunglas
Copy link
Member

dunglas commented Jun 4, 2018

None should...

@bendavies
Copy link
Contributor

bendavies commented Jun 4, 2018

I'll check tomorrow but I was under the impression that that wasn't the case.

@soyuka soyuka force-pushed the fix-metadata branch 3 times, most recently from f5c0fca to f230bc4 Compare June 5, 2018 07:37
@soyuka
Copy link
Member Author

soyuka commented Jun 5, 2018

I'm really unsure that changing priorities will be enough to fix this...

@oxan
Copy link
Contributor

oxan commented Jun 5, 2018

Yeah, at least the SerializerPropertyMetadataFactory currently does overwrite existing data. Since the annotation factory doesn't, only changing the priority doesn't fix this.

@teohhanhui
Copy link
Contributor

teohhanhui commented Jun 5, 2018

@oxan

Does Symfony guarantee an order of services with the same priority?

It should be in the reverse order of service registration:

https://github.com/symfony/symfony/blob/v4.1.0/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php#L28

https://github.com/symfony/symfony/blob/v4.1.0/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php#L35

@soyuka
Copy link
Member Author

soyuka commented Jun 5, 2018

So I should change SerializerPropertyMetadataFactory so that they don't overwrite? But will it not be a BC break?

@bendavies
Copy link
Contributor

that seems like it would be a BC break yes. seems like a catch 22 situation here to me.

@bendavies
Copy link
Contributor

copying @Nek- nice image which shows the current state of things:

@Nek-
Copy link
Contributor

Nek- commented Jun 5, 2018

Btw I can update it on demand.

@soyuka
Copy link
Member Author

soyuka commented Jun 5, 2018

Anyway, if you guys need a resolution to this issue, you can always add your own PropertyMetadataFactory that overrides everything (with the lowest priority before cache)!

To me this whole issue looks like a wontfix because I don't see any viable solution that doesn't break the current state of things...

@teohhanhui
Copy link
Contributor

@bendavies There is no "ambiguous order" :)

@bendavies
Copy link
Contributor

@teohhanhui it's not my image, but anyway, it's more a "non obvious" order.

@oxan
Copy link
Contributor

oxan commented Jun 5, 2018

Is there any actual situation where autogenerated metadata overwiriting user-defined metadata is actually desired? Yes, preventing that is a BC break, but every bugfix is a BC break in a way. I can't think of any real-world situations where the current situation would be relied upon. The behaviour would only change in places where people purposefully have manually declared wrong metadata (in fact, @ApiProperty is barely documented, so I doubt it has much usage at all).

@oxan
Copy link
Contributor

oxan commented Jun 5, 2018

@soyuka Yes, I'm currently using a custom metadata factory to be able to override the readableLink and writableLink properties, but it's ugly and it'd be nice to have an easier solution (for future reference, code is here: https://gist.github.com/oxan/5a9ba44e72bbeae5fa1aee7d0be0b337)

@bendavies
Copy link
Contributor

agree with @oxan really.

@Nek-
Copy link
Contributor

Nek- commented Jun 5, 2018

I think a failing test case is needed to show how obviously wrong is "state of things". I'll do it next week if nobody is faster than me.

But indeed the best solution is to drop the behavior of voting on null only for some of theses "voters".

@soyuka
Copy link
Member Author

soyuka commented Jun 6, 2018

In the mean time we could always introduce a new annotation that overrides metadata (like the one from @oxan), feels dirty but at least it's non-breaking.

@soyuka soyuka changed the base branch from 2.2 to 2.3 July 10, 2018 07:34
@soyuka soyuka force-pushed the fix-metadata branch 4 times, most recently from 22535af to deb3e07 Compare July 10, 2018 10:11
@@ -117,7 +114,7 @@ private function transformLinkStatus(PropertyMetadata $propertyMetadata, array $
$relatedClass = $type->isCollection() && ($collectionValueType = $type->getCollectionValueType()) ? $collectionValueType->getClassName() : $type->getClassName();

if (null === $relatedClass) {
return $propertyMetadata;
return $propertyMetadata->withReadableLink(true)->withWritableLink(true);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda prevents the break, to me these should stay nullable but it leads to bugs (essentially regarding docs and context - should I fix those there instead?).

Copy link
Contributor

@teohhanhui teohhanhui Jul 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't think this is correct, as this class is only supposed to fill in the metadata based on the Symfony Serializer mapping.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally 👍 to remove this but this has some impacts down the road.
Should we default these to true or should we test for null || true in the normalizers?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... Now I see we were already doing this from before. 😱 I guess let's keep it then. Haha...

@soyuka
Copy link
Member Author

soyuka commented Jul 10, 2018

ping @oxan @Nek- @bendavies

Could you guys give a shot at the latest version of this patch?

Thanks!

@soyuka soyuka force-pushed the fix-metadata branch 2 times, most recently from 5114c1b to 2f30e44 Compare July 10, 2018 12:52
@soyuka
Copy link
Member Author

soyuka commented Jul 25, 2018

@dunglas wdyt?

@bendavies
Copy link
Contributor

🚢

@dunglas
Copy link
Member

dunglas commented Aug 22, 2018

Should be merged in master, not in 2.3 because the priority change may break some apps.

Change priority of user-defined metadata services to 20
User-defined metadata always overrides previous metadata
@soyuka soyuka changed the base branch from 2.3 to master August 23, 2018 07:11
@soyuka soyuka merged commit 3fdb58c into api-platform:master Aug 23, 2018
@soyuka soyuka deleted the fix-metadata branch August 23, 2018 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants