Skip to content

Commit d887fb5

Browse files
Add NotExposed operation (#4881)
* feat: add NotExposed operation * feat: add openapi operation option * feat: add itemUriTemplate GetCollection and Post operations option * fix: use uriTemplate instead of the route name The route name is very Symfony specific, let's use `uriTemplate` instead. The skolem id generation was moved to the IriConverter and will be in another class in a later commit. * feat(iri): move skolem iri to another class Note that we still put this inside the Symfony class as we use the router for the url GenerationStrategy feature which is for now tight to the Symfony router * refactor(itemUriTemplate): index by uri template Co-authored-by: soyuka <[email protected]>
1 parent 6399e3f commit d887fb5

File tree

61 files changed

+2072
-35
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2072
-35
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ jobs:
137137
composer remove --dev --no-interaction --no-progress --no-update --ansi \
138138
doctrine/mongodb-odm \
139139
doctrine/mongodb-odm-bundle
140+
# https://github.com/doctrine/dbal/issues/5570
141+
- name: Fix Doctrine dependencies
142+
if: (startsWith(matrix.php, '7.1') || startsWith(matrix.php, '7.2') || startsWith(matrix.php, '7.3'))
143+
run: composer require "doctrine/orm:<2.13" --dev --no-interaction --no-progress --ansi
140144
- name: Update project dependencies
141145
run: composer update --no-interaction --no-progress --ansi
142146
- name: Require Symfony components
@@ -230,6 +234,10 @@ jobs:
230234
doctrine/mongodb-odm-bundle
231235
- name: Update project dependencies
232236
run: composer update --no-interaction --no-progress --ansi
237+
# https://github.com/doctrine/dbal/issues/5570
238+
- name: Fix Doctrine dependencies
239+
if: (startsWith(matrix.php, '7.1') || startsWith(matrix.php, '7.2') || startsWith(matrix.php, '7.3'))
240+
run: composer require "doctrine/orm:<2.13" --dev --no-interaction --no-progress --ansi
233241
- name: Require Symfony components
234242
if: (!startsWith(matrix.php, '7.1'))
235243
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"justinrainbow/json-schema": "^5.2.1",
4848
"phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.1",
4949
"phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.4",
50+
"phpspec/prophecy": "^1.10",
5051
"phpstan/extension-installer": "^1.1",
5152
"phpstan/phpstan": "^1.1",
5253
"phpstan/phpstan-doctrine": "^1.0",
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
@php8
2+
@v3
3+
Feature: Exposing a collection of objects should use the specified operation to generate the IRI
4+
5+
Scenario: Get a collection of objects without any itemUriTemplate should generate the IRI from the first Get operation
6+
When I add "Accept" header equal to "application/hal+json"
7+
And I send a "GET" request to "/cars"
8+
Then the response status code should be 200
9+
And the response should be in JSON
10+
And the JSON should be valid according to the JSON HAL schema
11+
And the header "Content-Type" should be equal to "application/hal+json; charset=utf-8"
12+
And the JSON should be valid according to this schema:
13+
"""
14+
{
15+
"type": "object",
16+
"additionalProperties": false,
17+
"required": ["_links", "_embedded", "totalItems"],
18+
"properties": {
19+
"_links": {
20+
"type": "object",
21+
"properties": {
22+
"self": {
23+
"type": "object",
24+
"properties": {"href": {"pattern": "^/cars$"}}
25+
},
26+
"item": {
27+
"type": "array",
28+
"minItems": 2,
29+
"maxItems": 2,
30+
"items": {
31+
"type": "object",
32+
"properties": {"href": {"pattern": "^/cars/.+$"}}
33+
}
34+
}
35+
}
36+
},
37+
"totalItems": {"type":"number", "minimum": 2, "maximum": 2},
38+
"_embedded": {
39+
"type": "object",
40+
"properties": {
41+
"item": {
42+
"type": "array",
43+
"minItems": 2,
44+
"maxItems": 2,
45+
"items": {
46+
"type": "object",
47+
"properties": {
48+
"_links": {
49+
"type": "object",
50+
"properties": {
51+
"self": {
52+
"type": "object",
53+
"properties": {"href": {"pattern": "^/cars/.+$"}}
54+
}
55+
}
56+
},
57+
"id": {"type": "string"},
58+
"owner": {"type": "string"}
59+
}
60+
}
61+
}
62+
}
63+
}
64+
}
65+
}
66+
"""
67+
68+
Scenario: Get a collection of objects with an itemUriTemplate should generate the IRI from the correct operation
69+
When I add "Accept" header equal to "application/hal+json"
70+
And I send a "GET" request to "/brands/renault/cars"
71+
Then the response status code should be 200
72+
And the response should be in JSON
73+
And the header "Content-Type" should be equal to "application/hal+json; charset=utf-8"
74+
And the JSON should be valid according to this schema:
75+
"""
76+
{
77+
"type": "object",
78+
"additionalProperties": false,
79+
"required": ["_links", "_embedded", "totalItems"],
80+
"properties": {
81+
"_links": {
82+
"type": "object",
83+
"properties": {
84+
"self": {
85+
"type": "object",
86+
"properties": {"href": {"pattern": "^/brands/renault/cars$"}}
87+
},
88+
"item": {
89+
"type": "array",
90+
"minItems": 2,
91+
"maxItems": 2,
92+
"items": {
93+
"type": "object",
94+
"properties": {"href": {"pattern": "^/brands/renault/cars/.+$"}}
95+
}
96+
}
97+
}
98+
},
99+
"totalItems": {"type":"number", "minimum": 2, "maximum": 2},
100+
"_embedded": {
101+
"type": "object",
102+
"properties": {
103+
"item": {
104+
"type": "array",
105+
"minItems": 2,
106+
"maxItems": 2,
107+
"items": {
108+
"type": "object",
109+
"properties": {
110+
"_links": {
111+
"type": "object",
112+
"properties": {
113+
"self": {
114+
"type": "object",
115+
"properties": {"href": {"pattern": "^/brands/renault/cars/.+$"}}
116+
}
117+
}
118+
},
119+
"id": {"type": "string"},
120+
"owner": {"type": "string"}
121+
}
122+
}
123+
}
124+
}
125+
}
126+
}
127+
}
128+
"""
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
@php8
2+
@v3
3+
Feature: Exposing a collection of objects should use the specified operation to generate the IRI
4+
5+
Scenario: Get a collection of objects without any itemUriTemplate should generate the IRI from the first Get operation
6+
When I send a "GET" request to "/cars"
7+
Then the response status code should be 200
8+
And the response should be in JSON
9+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
10+
And the JSON should be valid according to this schema:
11+
"""
12+
{
13+
"type": "object",
14+
"additionalProperties": false,
15+
"required": ["@context", "@id", "@type", "hydra:member", "hydra:totalItems"],
16+
"properties": {
17+
"@context": {"pattern": "^/contexts/Car$"},
18+
"@id": {"pattern": "^/cars$"},
19+
"@type": {"pattern": "^hydra:Collection$"},
20+
"hydra:member": {
21+
"type": "array",
22+
"minItems": 2,
23+
"maxItems": 2,
24+
"uniqueItems": true,
25+
"items": {
26+
"type": "object",
27+
"additionalProperties": false,
28+
"required": ["@id", "@type", "id", "owner"],
29+
"properties": {
30+
"@id": {"pattern": "^/cars/.+$"},
31+
"@type": {"pattern": "^Car$"},
32+
"id": {"type": "string"},
33+
"owner": {"type": "string"}
34+
}
35+
}
36+
},
37+
"hydra:totalItems": {"type": "integer", "minimum": 2, "maximum": 2}
38+
}
39+
}
40+
"""
41+
42+
Scenario: Get a collection of objects with an itemUriTemplate should generate the IRI from the correct operation
43+
When I send a "GET" request to "/brands/renault/cars"
44+
Then the response status code should be 200
45+
And the response should be in JSON
46+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
47+
And the JSON should be valid according to this schema:
48+
"""
49+
{
50+
"type": "object",
51+
"additionalProperties": false,
52+
"required": ["@context", "@id", "@type", "hydra:member", "hydra:totalItems"],
53+
"properties": {
54+
"@context": {"pattern": "^/contexts/Car$"},
55+
"@id": {"pattern": "^/brands/renault/cars$"},
56+
"@type": {"pattern": "^hydra:Collection$"},
57+
"hydra:member": {
58+
"type": "array",
59+
"minItems": 2,
60+
"maxItems": 2,
61+
"uniqueItems": true,
62+
"items": {
63+
"type": "object",
64+
"additionalProperties": false,
65+
"required": ["@id", "@type", "id", "owner"],
66+
"properties": {
67+
"@id": {"pattern": "^/brands/renault/cars/.+$"},
68+
"@type": {"pattern": "^Car$"},
69+
"id": {"type": "string"},
70+
"owner": {"type": "string"}
71+
}
72+
}
73+
},
74+
"hydra:totalItems": {"type": "integer", "minimum": 2, "maximum": 2}
75+
}
76+
}
77+
"""
78+
79+
Scenario: Create an object without an itemUriTemplate should generate the IRI from the first Get operation
80+
When I add "Content-Type" header equal to "application/json"
81+
And I send a "POST" request to "/cars" with body:
82+
"""
83+
{
84+
"owner": "Vincent"
85+
}
86+
"""
87+
Then the response status code should be 201
88+
And the response should be in JSON
89+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
90+
And the JSON should be valid according to this schema:
91+
"""
92+
{
93+
"type": "object",
94+
"additionalProperties": false,
95+
"required": ["@id", "@type", "id", "owner"],
96+
"properties": {
97+
"@context": {"pattern": "^/contexts/Car$"},
98+
"@id": {"pattern": "^/cars/.+$"},
99+
"@type": {"pattern": "^Car$"},
100+
"id": {"type": "string"},
101+
"owner": {"type": "string"}
102+
}
103+
}
104+
"""
105+
106+
Scenario: Create an object with an itemUriTemplate should generate the IRI from the correct operation
107+
When I add "Content-Type" header equal to "application/json"
108+
And I send a "POST" request to "/brands/renault/cars" with body:
109+
"""
110+
{
111+
"owner": "Vincent"
112+
}
113+
"""
114+
Then the response status code should be 201
115+
And the response should be in JSON
116+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
117+
And the JSON should be valid according to this schema:
118+
"""
119+
{
120+
"type": "object",
121+
"additionalProperties": false,
122+
"required": ["@id", "@type", "id", "owner"],
123+
"properties": {
124+
"@context": {"pattern": "^/contexts/Car$"},
125+
"@id": {"pattern": "^/brands/renault/cars/.+$"},
126+
"@type": {"pattern": "^Car$"},
127+
"id": {"type": "string"},
128+
"owner": {"type": "string"}
129+
}
130+
}
131+
"""

0 commit comments

Comments
 (0)