-
-
Notifications
You must be signed in to change notification settings - Fork 895
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
Support union/intersect types #5470
Conversation
vincentchalamon
commented
Mar 17, 2023
Q | A |
---|---|
Branch? | main |
Tickets | #5452 |
License | MIT |
Doc PR | N/A |
eeba480
to
6659839
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start!
To resume my thoughts I think that we should compute most of the type-inflected schema inside a JsonSchema\Metadata\TypePropertyMetadataFactory
to reduce the work inside the SchemaFactory. Also move the ReflectionType
checks there.
Specifications like JSON-LD, HAL and JSON:API support mutliple types but we stop at the first one.
Deprecating XML, CSV support from our normalizer is another task but reading these parts of the code reminded me of that so don't bother here.
I want to suggest that our codebase should not handle types that are scalars and objects but we probably need to discuss this with more @api-platform/core-team members.
return $noop; | ||
} | ||
|
||
$hasAssociation = $totalProperties === $index && $isResourceClass; | ||
} | ||
|
||
return [$type, $hasAssociation, $currentResourceClass, $currentProperty]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling that having a property that is a scalar and a resource class is such a bad practice that we should just not support it.
foreach ($types as $type) { | ||
if (null !== $type->getClassName()) { | ||
return "data/relationships/$fieldName"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's harder to find informations about json-api but it looks like it supports polymorphism inside collections, not sure how to handle this case.
|
||
$components['relationships'][] = $relation; | ||
// if all types are not relationships, declare it as an attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a huge fan, this means that the type is something like scalar|object
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better something like Foo|Bar|Baz
where only Baz
is a resource
src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php
Outdated
Show resolved
Hide resolved
src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php
Outdated
Show resolved
Hide resolved
src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php
Outdated
Show resolved
Hide resolved
/* From @see AbstractObjectNormalizer::validateAndDenormalize() */ | ||
// Fix a collection that contains the only one element | ||
// This is special to xml format only | ||
if ('xml' === $format && null !== $collectionValueType && (!\is_array($value) || !\is_int(key($value)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dunglas should we really support this? We discussed XML is not supporte-able by our normalizers at the symfony live. Maybe that deprecating the support of XML (w/ JSON by default) for 3.2 should be our target?
// In XML and CSV all basic datatypes are represented as strings, it is e.g. not possible to determine, | ||
// if a value is meant to be a string, float, int or a boolean value from the serialized representation. | ||
// That's why we have to transform the values, if one of these non-string basic datatypes is expected. | ||
if (\is_string($value) && (XmlEncoder::FORMAT === $format || CsvEncoder::FORMAT === $format)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same for this, wondering if it's not the time to get rid of that and use symfony's normalizers without ours for these.
421046d
to
efb4a00
Compare
foreach ($propertyTypes as $propertyType) { | ||
if ($fieldConfiguration = $this->getResourceFieldConfiguration($property, $propertyMetadata->getDescription(), $propertyMetadata->getDeprecationReason(), $propertyType, $resourceClass, $input, $operation, $depth, null !== $propertyMetadata->getSecurity())) { | ||
$fields['id' === $property ? '_id' : $this->normalizePropertyName($property, $resourceClass)] = $fieldConfiguration; | ||
// stop at the first valid type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alanpoulain doesn't graphql support multiple types ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently, it seems possible, but it requires a special trick:
https://stackoverflow.com/questions/49897319/graphql-union-scalar-type
https://graphql.org/learn/schema/#union-types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not an input type, yes. Otherwise no (see graphql/graphql-spec#825).
src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php
Outdated
Show resolved
Hide resolved
src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php
Outdated
Show resolved
Hide resolved
src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice job on the metadata and schema factory part! few things left on the hydra support and I haven't read the part about validators / elasticsearch yet. We need to find out what to do about graphql thoug.
7e066c3
to
576dda7
Compare
576dda7
to
2c5fc99
Compare
17b27a3
to
e8d09a6
Compare
src/JsonSchema/SchemaFactory.php
Outdated
@@ -42,7 +41,7 @@ final class SchemaFactory implements SchemaFactoryInterface | |||
public const FORCE_SUBSCHEMA = '_api_subschema_force_readable_link'; | |||
public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name'; | |||
|
|||
public function __construct(private readonly TypeFactoryInterface $typeFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ?NameConverterInterface $nameConverter = null, ResourceClassResolverInterface $resourceClassResolver = null) | |||
public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ?NameConverterInterface $nameConverter = null, ResourceClassResolverInterface $resourceClassResolver = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really good improvement imo but we still need to cover BC on that constructor. can we trigger a deprecation on using it and we'll remove it in 4.x
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one last thing awesome work!
{ | ||
if ($typeFactory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want to remove this parameter from the signature at some point e.g. in 4.0?
This looks like a silent BC break. The layer in place does not allow calling code to adapt before the actual removal happens, given there is no way to make such code ready for the 4.0 constructor (unless using named arguments, not a majority)