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

Support union/intersect types #5470

Merged
merged 14 commits into from
Jul 6, 2023

Conversation

vincentchalamon
Copy link
Contributor

Q A
Branch? main
Tickets #5452
License MIT
Doc PR N/A

@vincentchalamon vincentchalamon self-assigned this Mar 17, 2023
@vincentchalamon vincentchalamon force-pushed the fix/issues/5452 branch 9 times, most recently from eeba480 to 6659839 Compare March 20, 2023 12:21
@vincentchalamon vincentchalamon marked this pull request as ready for review March 20, 2023 12:40
Copy link
Member

@soyuka soyuka left a 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];
Copy link
Member

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.

src/Hydra/Serializer/DocumentationNormalizer.php Outdated Show resolved Hide resolved
foreach ($types as $type) {
if (null !== $type->getClassName()) {
return "data/relationships/$fieldName";
}
Copy link
Member

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
Copy link
Member

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?

Copy link
Contributor Author

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

/* 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)))) {
Copy link
Member

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)) {
Copy link
Member

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.

@vincentchalamon vincentchalamon force-pushed the fix/issues/5452 branch 6 times, most recently from 421046d to efb4a00 Compare April 6, 2023 14:13
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
Copy link
Member

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 ?

Copy link
Contributor Author

@vincentchalamon vincentchalamon Apr 11, 2023

Choose a reason for hiding this comment

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

Copy link
Member

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).

Copy link
Member

@soyuka soyuka left a 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.

@vincentchalamon vincentchalamon force-pushed the fix/issues/5452 branch 2 times, most recently from 7e066c3 to 576dda7 Compare April 11, 2023 08:29
@vincentchalamon vincentchalamon marked this pull request as draft June 6, 2023 07:16
@vincentchalamon vincentchalamon requested a review from soyuka June 27, 2023 11:05
@vincentchalamon vincentchalamon marked this pull request as ready for review June 27, 2023 11:05
@@ -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)
Copy link
Member

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

Copy link
Member

@soyuka soyuka left a 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!

@soyuka soyuka merged commit d793ffb into api-platform:main Jul 6, 2023
@vincentchalamon vincentchalamon deleted the fix/issues/5452 branch July 6, 2023 08:40
{
if ($typeFactory) {
Copy link
Contributor

@chalasr chalasr Aug 6, 2023

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)

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.

4 participants