-
-
Notifications
You must be signed in to change notification settings - Fork 906
Add JSON API basic support (continuation) #1175
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
Add JSON API basic support (continuation) #1175
Conversation
61d1023
to
fbcbcde
Compare
// If order query parameter is not defined or is already an array, never mind | ||
$orderParameter = $request->query->get($this->orderParameterName); | ||
if (null === $orderParameter || is_array($orderParameter) | ||
) { |
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.
strange cs?
Wow! For this you deserve much ❤️! To bad that authors history was lost though. Really nice if this can finally come to an end :D. Thanks @meyerbaptiste! |
fbcbcde
to
a91b570
Compare
@soyuka Yep, anyway the author are in the files and we could Thanks @meyerbaptiste for finishing this ! |
a91b570
to
ec82832
Compare
* | ||
* @author Héctor Hurtarte <hectorh30@gmail.com> | ||
*/ | ||
final class TransformSortingParametersListener |
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 feels like those parametersListener
have a lot of code duplication. I don't know if it's okay like this or if we should base those on an abstract class. WDYT?
$returnDataArray = []; | ||
if (isset($context['api_sub_level'])) { | ||
foreach ($data as $index => $obj) { | ||
$returnDataArray['data'][][$index] = $this->normalizer->normalize($obj, $format, $context); |
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.
Shouldn't the $returnDataArray
be like $returnDataArray = ['data' => []]
on initialization for this to work? I don't get how ['data' => [[]]]
is self-initializing.
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.
The magic of PHP: https://3v4l.org/GXaOT
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.
Wow okay, I feel dumb right now, thanks @meyerbaptiste!
$lastPage = $data->getLastPage(); | ||
$itemsPerPage = $data->getItemsPerPage(); | ||
|
||
$paginated = 1. !== $lastPage; |
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.
1.
? Because of float comparison? Saw that below too.
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.
Yes, I think. $lastPage
is a float.
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.
https://github.com/api-platform/core/pull/1175/files#diff-5b154fa3efaf5776695baccd0a52daf4R66 initialized as integer? IMO pagination stuff should be integer-only because it doesn't make sense to have a float ^^ (maybe jsonapi specifies float though I haven't looked at it).
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 think they wanted to keep a consistency with the PaginatorInterface
interface which returns floats.
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.
Indeed. We use float because of large numbers.
|
||
$typeShortName = ''; | ||
|
||
if ($className && $this->resourceClassResolver->isResourceClass($className)) { |
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.
Because isResourceClass
is quite heavy (#1068) I'd prefer if we could use a variable to store it above instead of calling it a least twice.
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 refactored this part.
* | ||
* @return bool|string | ||
*/ | ||
private function getJsonApiCacheKey(string $format = null, array $context) |
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.
method typing :bool
?
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 method returns a string or false.
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.
wow, my bad missed that.
@@ -183,6 +183,8 @@ private function getPathOperation(string $operationName, array $operation, strin | |||
return $this->updateGetOperation($pathOperation, $mimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); | |||
case 'POST': | |||
return $this->updatePostOperation($pathOperation, $mimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); | |||
case 'PATCH': | |||
$pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Updates the %s resource.', $resourceShortName); |
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.
interesting hack 😛 we could break
after this IMO so that it gets to the return statement directly.
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.
Why adding a break
here? I have to return in the PUT
case.
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.
Oh okay then thought it returned as default.
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.
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 like you did here indeed.
|
||
$normalizer = new ItemNormalizer($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $contextBuilderProphecy->reveal()); | ||
|
||
$this->assertFalse($normalizer->supportsDenormalization('foo', ItemNormalizer::FORMAT)); | ||
$normalizer->denormalize(['foo'], Dummy::class, 'jsonld', ['jsonld_has_context' => true, 'jsonld_sub_level' => true, 'resource_class' => Dummy::class]); |
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.
why did you drop this test?
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.
Huum, I think it was because the test is about denormalization support and not denormalization.
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.
Yeah it's weird indeed, test is testDontSupportDenormalization
. Then we still do the denormalization with no assertions ?!
Still, denormalize
isn't tested anymore in this class, maybe we could move it in a new test with an assertion then?
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.
Yep, you're right.
Then we still do the denormalization with no assertions
It's wrong, because shouldBeCalled()
is an assertion 😛
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.
haha yeah I meant no assertion on the denormalization
call like we do on normalization
below.
|
||
$this->listener->onKernelRequest($eventProphecy->reveal()); | ||
|
||
$expectedRequest = new Request(['page.size' => 5, 'page.number' => 3]); |
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.
we could also test negative page parameters values to avoid a recent issue we had.
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.
Okay. But at this level, positive or negative, it has no impact.
ec82832
to
86c1e58
Compare
@meyerbaptiste could you push it a little bit further by adding that 0.6% coverage missing ? |
8e34350
to
257522c
Compare
$returnDataArray = []; | ||
if (isset($context['api_sub_level'])) { | ||
foreach ($data as $index => $obj) { | ||
$returnDataArray['data'][][$index] = $this->normalizer->normalize($obj, $format, $context); |
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 really not confident with this piece of code. I don't think it works properly but at the same time, I don't know what is the correct result. I am not familiar with sub-resources...
Anyone can help me here?
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.
Looks correct according to what are the other normalizer's doing in case of a api_sub_level
flag.
if (isset($context['api_sub_level'])) { |
if (isset($context['api_sub_level'])) { |
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 more about the array structure. What type of values can be the index and the normalized object here? According to JSON API spec, data
must be primary data or represent resource linkage, we can not put what we want in it! 😕
2bcdfcc
to
481636c
Compare
I got +0.1% @Simperfit! I don't want to write tests for at least 1 month... |
it's good for me ;) |
Awesome! Thanks so much for going on with this. I also went out of time to complete this, but I'm glad to see it moving forward. |
1203621
to
938c0e0
Compare
938c0e0
to
4c37880
Compare
Thanks @Simperfit & @hectorh30, 4 Oct 2016 -> 13 Oct 2017, 1 year of collaborative work! |
Thank you for finishing it ! |
It's MERGGEEEEDDDD ❤️ ❤️ ❤️ |
@mario-digitalstate |
* GraphQL Query support (api-platform#1358) * Fix missing service when no Varnish URL is defined * [PropertyFilter] Fix whitelist comparison (api-platform#1379) * Remove wrong doc * Swagger subcollection documentation issue (api-platform#1395) * Make the requirements configurable Closes api-platform#1401 * Provide a better exception message and type Getting "Not found" on a route where you are getting an object can get really confusing. * Bump branch alias to 2.2.x-dev 2.1.x-dev is already taken by the 2.1 branch, and this should represent the next minor version anyway. * Fix tests * Reuse PriorityTaggedServiceTrait from symfony * Improve payload support and remove duplicate code in ConstraintViolationListNormalizer (api-platform#1416) * Filter Annotation implementation Parent class filters (needs test) Support for nested properties Tests Fix some comments and remove id=>id in compiler pass * Throw on abstract data providers / filters * Remove an unused var * Remove useless badges * Enable the coverage * Fix some quality issues * Add job to test upstream libs deprecations If api-platform uses upstream libs in a deprecated way, we should be aware of it. * Add job to test upstream libs deprecations If api-platform uses upstream libs in a deprecated way, we should be aware of it. * Fix missing cache tag on empty collections * Allow plain IDs with `allow_plain_identifiers` * Fix indentation for GraphQL features. * Add JSON API basic support (api-platform#785, api-platform#1036, api-platform#1175) * Clean Behat tests * Fix tags addition with an empty value * Document swagger-specific description options … and where to find them should there be newer ones. * Fix PHPUnit tests * Fix missing return statement * Support & compatibility for PHP7.2 * Add feature to update swagger context for properties * Generator compat improvements (api-platform#1429) * Add support for resource names without namespace * [SF 4.0] Make actions explicitly public * Allow phpdocumentor/reflection-docblock 4 * fix hydra documentation normalizer with subresources * Create a base collection normalizer * Fix request auto-runner * Update the changelog * Update changelog
Well done to everyone that helped out with this. Looks really great, been testing it out since it was merged in and great to see it has made it into a release. Is there any plans on getting include working http://jsonapi.org/format/#fetching-includes ... If not I'd be interested in contributing as it is one of my favorite parts of JSON API. |
This looks really similar to what our Property and Group filters are doing. See https://github.com/api-platform/docs/blob/master/core/filters.md#serializer-filters |
@soyuka I could be wrong but it seems like the current implementation of JSON API will only provide me with the relationships property in the response if I add a related entity with a Group annotation for GET for example
So a second API request need to be made. With the functionality that has yet to be implemented of the "include" query string to allow you to return:
|
Indeed, it's just very similar and the implementation of |
@soyuka Ah yeah I get you, sorry been a long day ... thought you were saying I could use them already to get the included functionality. I'll take a look at those now though, thanks. |
Just a note on the includes. They make caching really difficult. A change in an A better option is to adopt HTTP/2 for faster connections with less latency and cache at the individual entity level (aggregate in DDD).
Making the JSON-API support feature-complete compared to the spec is a good thing, but I thought I'd bring some attention to the issues associated with using this feature. My opinion is based on using includes in a project, and having some big issues. |
@cjunge-work I think it's a common issue with embedded relations (i.e using serialization group), irrespective of the format used. And IMO the best way to deal with it is to be mindful on what to embed for each responses to prevent overcomplicating cache management logic. I personally hope this functionality would be available to provide consistency when used with content negotiation. |
Hey thanks for the feature! How to enable this json api support?. |
@jonday-simitive did you start working on this? I am in a situation where I need a subresource to be included with data. |
@Ronnie-J We ended up using multiple API requests or the SubResources Api Platform functionality. I've been trying to find the time to implement it but been unable to so far :( |
Continuation (and conclusion?) of PRs #785 and #1036.
First, I rebase the branch against the master branch (:cold_sweat:).
Then (see the second commit):
GTK:
Did I forget something?
Cc: @hectorh30, @Simperfit