-
-
Notifications
You must be signed in to change notification settings - Fork 934
[WIP] feat: fix #539 hal support #608
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
Closed
Simperfit
wants to merge
14
commits into
api-platform:master
from
Simperfit:feature/adding-hal-support
Closed
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
14ca87b
feat: fix #539 hal support
c91b5a0
feat: Add PartialCollectionTest
fc86f78
feat: Add CollectionNormalizerTest
9a2c768
Factorize the JSON encoder
dunglas 63e37f5
Merge pull request #2 from dunglas/Simperfit-feature/adding-hal-support
Simperfit 3bcf108
feat: Add CollectionNormalizerTest
b52e750
apply styleci
50c746f
feat: start itemNormalizerTest
afd8b66
Extrat common serialization logic in AbstractItemNormalizer
dunglas f9c0e97
Use AbstractItemNormalizer in Hal\ItemNormalizer
dunglas a245c3f
Merge pull request #3 from dunglas/Simperfit-feature/adding-hal-support
Simperfit 9d033b1
feat: start itemNormalizerTest
96d6753
Merge branch 'feature/adding-hal-support' of github.com:Simperfit/cor…
3f39333
fixcs
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,326 @@ | ||
| Feature: Create-Retrieve-Update-Delete | ||
| In order to use an hypermedia API | ||
| As a client software developer | ||
| I need to be able to retrieve, create, update and delete JSON-LD encoded resources. | ||
|
|
||
| @createSchema | ||
| Scenario: Create a resource | ||
| When I add "Accept" header equal to "application/hal+json" | ||
| And I send a "POST" request to "/dummies" with body: | ||
| """ | ||
| { | ||
| "name": "My Dummy", | ||
| "dummyDate": "2015-03-01T10:00:00+00:00", | ||
| "jsonData": { | ||
| "key": [ | ||
| "value1", | ||
| "value2" | ||
| ] | ||
| } | ||
| } | ||
| """ | ||
| Then the response status code should be 201 | ||
| And the response should be in JSON | ||
| And the header "Content-Type" should be equal to "application/hal+json" | ||
| And the JSON should be equal to: | ||
| """ | ||
| { | ||
| "_links": { | ||
| "self": { | ||
| "href": "\/dummies\/1" | ||
| } | ||
| }, | ||
| "description": null, | ||
| "dummy": null, | ||
| "dummyBoolean": null, | ||
| "dummyDate": "2015-03-01T10:00:00+00:00", | ||
| "dummyPrice": null, | ||
| "relatedDummy": null, | ||
| "relatedDummies": [], | ||
| "jsonData": { | ||
| "key": [ | ||
| "value1", | ||
| "value2" | ||
| ] | ||
| }, | ||
| "name_converted": null, | ||
| "name": "My Dummy", | ||
| "alias": null | ||
| } | ||
| """ | ||
|
|
||
| Scenario: Get a resource | ||
| When I add "Accept" header equal to "application/hal+json" | ||
| And I send a "GET" request to "/dummies/1" | ||
| Then the response status code should be 200 | ||
| And the response should be in JSON | ||
| And the header "Content-Type" should be equal to "application/hal+json" | ||
| And the JSON should be equal to: | ||
| """ | ||
| { | ||
| "_links": { | ||
| "self": { | ||
| "href": "\/dummies\/1" | ||
| } | ||
| }, | ||
| "description": null, | ||
| "dummy": null, | ||
| "dummyBoolean": null, | ||
| "dummyDate": "2015-03-01T10:00:00+00:00", | ||
| "dummyPrice": null, | ||
| "relatedDummy": null, | ||
| "relatedDummies": [], | ||
| "jsonData": { | ||
| "key": [ | ||
| "value1", | ||
| "value2" | ||
| ] | ||
| }, | ||
| "name_converted": null, | ||
| "name": "My Dummy", | ||
| "alias": null | ||
| } | ||
| """ | ||
|
|
||
| Scenario: Get a not found exception | ||
| When I send a "GET" request to "/dummies/42" | ||
| Then the response status code should be 404 | ||
|
|
||
| Scenario: Get a collection | ||
| When I send a "GET" request to "/dummies" | ||
| Then the response status code should be 200 | ||
| And the response should be in JSON | ||
| And the header "Content-Type" should be equal to "application/ld+json" | ||
| And the JSON should be equal to: | ||
| """ | ||
| { | ||
| "@context": "/contexts/Dummy", | ||
| "@id": "/dummies", | ||
| "@type": "hydra:Collection", | ||
| "hydra:member": [ | ||
| { | ||
| "@id": "/dummies/1", | ||
| "@type": "Dummy", | ||
| "description": null, | ||
| "dummy": null, | ||
| "dummyBoolean": null, | ||
| "dummyDate": "2015-03-01T10:00:00+00:00", | ||
| "dummyPrice": null, | ||
| "relatedDummy": null, | ||
| "relatedDummies": [], | ||
| "jsonData": { | ||
| "key": [ | ||
| "value1", | ||
| "value2" | ||
| ] | ||
| }, | ||
| "name_converted": null, | ||
| "name": "My Dummy", | ||
| "alias": null | ||
| } | ||
| ], | ||
| "hydra:totalItems": 1, | ||
| "hydra:search": { | ||
| "@type": "hydra:IriTemplate", | ||
| "hydra:template": "/dummies{?id,id[],name,alias,description,relatedDummy.name,relatedDummy.name[],relatedDummies,relatedDummies[],dummy,order[id],order[name],order[relatedDummy.symfony],dummyDate[before],dummyDate[after],relatedDummy.dummyDate[before],relatedDummy.dummyDate[after],dummyPrice[between],dummyPrice[gt],dummyPrice[gte],dummyPrice[lt],dummyPrice[lte],dummyBoolean,dummyPrice}", | ||
| "hydra:variableRepresentation": "BasicRepresentation", | ||
| "hydra:mapping": [ | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "id", | ||
| "property": "id", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "id[]", | ||
| "property": "id", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "name", | ||
| "property": "name", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "alias", | ||
| "property": "alias", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "description", | ||
| "property": "description", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummy.name", | ||
| "property": "relatedDummy.name", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummy.name[]", | ||
| "property": "relatedDummy.name", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummies", | ||
| "property": "relatedDummies", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummies[]", | ||
| "property": "relatedDummies", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummy", | ||
| "property": "dummy", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "order[id]", | ||
| "property": "id", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "order[name]", | ||
| "property": "name", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "order[relatedDummy.symfony]", | ||
| "property": "relatedDummy.symfony", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyDate[before]", | ||
| "property": "dummyDate", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyDate[after]", | ||
| "property": "dummyDate", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummy.dummyDate[before]", | ||
| "property": "relatedDummy.dummyDate", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "relatedDummy.dummyDate[after]", | ||
| "property": "relatedDummy.dummyDate", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice[between]", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice[gt]", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice[gte]", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice[lt]", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice[lte]", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyBoolean", | ||
| "property": "dummyBoolean", | ||
| "required": false | ||
| }, | ||
| { | ||
| "@type": "IriTemplateMapping", | ||
| "variable": "dummyPrice", | ||
| "property": "dummyPrice", | ||
| "required": false | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| """ | ||
|
|
||
| Scenario: Update a resource | ||
| When I send a "PUT" request to "/dummies/1" with body: | ||
| """ | ||
| { | ||
| "@id": "/dummies/1", | ||
| "name": "A nice dummy", | ||
| "jsonData": [{ | ||
| "key": "value1" | ||
| }, | ||
| { | ||
| "key": "value2" | ||
| } | ||
| ] | ||
| } | ||
| """ | ||
| Then the response status code should be 200 | ||
| And the response should be in JSON | ||
| And the header "Content-Type" should be equal to "application/ld+json" | ||
| And the JSON should be equal to: | ||
| """ | ||
| { | ||
| "@context": "/contexts/Dummy", | ||
| "@id": "/dummies/1", | ||
| "@type": "Dummy", | ||
| "description": null, | ||
| "dummy": null, | ||
| "dummyBoolean": null, | ||
| "dummyDate": "2015-03-01T10:00:00+00:00", | ||
| "dummyPrice": null, | ||
| "relatedDummy": null, | ||
| "relatedDummies": [], | ||
| "jsonData": [ | ||
| { | ||
| "key": "value1" | ||
| }, | ||
| { | ||
| "key": "value2" | ||
| } | ||
| ], | ||
| "name_converted": null, | ||
| "name": "A nice dummy", | ||
| "alias": null | ||
| } | ||
| """ | ||
|
|
||
| @dropSchema | ||
| Scenario: Delete a resource | ||
| When I send a "DELETE" request to "/dummies/1" | ||
| Then the response status code should be 204 | ||
| And the response should be empty |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,12 +9,12 @@ | |
| * file that was distributed with this source code. | ||
| */ | ||
|
|
||
| namespace ApiPlatform\Core\Hydra\Action; | ||
| namespace ApiPlatform\Core\Action; | ||
|
|
||
| use ApiPlatform\Core\JsonLd\EntrypointBuilderInterface; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the namespace here be changed to |
||
|
|
||
| /** | ||
| * Generates the JSON-LD API entrypoint. | ||
| * Generates the API entrypoint. | ||
| * | ||
| * @author Kévin Dunglas <dunglas@gmail.com> | ||
| */ | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Perhaps
ApiPlatform\Core\Hypermedia\Action?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.
IMO we can get rid of the
Hypermedianamespace. The entrypoint can be useful even in a non-hypermedia context (i.e raw JSON or XML).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.
Not sure what an "entrypoint" is supposed to be (outside of the Hydra context), actually. It's a Hydra thing. Perhaps we shouldn't try to shoehorn things...
Uh oh!
There was an error while loading. Please reload this page.
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.
HAL has a similar concept. And it's a common use case to list all resources collection exposed by the API.
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.
Schema.org itself contains this concept: https://schema.org/EntryPoint
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.
No. That's a different thing, if you look carefully. Their naming is just confusing sometimes... 😆
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 catch. But HAL has it: http://haltalk.herokuapp.com/explorer/browser.html#/
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 understand as is, an entrypoint is the /, the base of the app. The first thing you will see (even if there is authentification, you will be redirect or not allowed).