Skip to content

Commit 052d53a

Browse files
committed
Merge branch '2.3'
2 parents 4403515 + 067347f commit 052d53a

File tree

17 files changed

+159
-27
lines changed

17 files changed

+159
-27
lines changed

.travis.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
language: node
1+
language: node_js
2+
node_js:
3+
- 'stable'
24

35
cache:
46
yarn: true
@@ -7,6 +9,10 @@ env:
79
global:
810
secure: gjiWHIgNjLXuEFmLiepiOTHOuauHfeKHutrE0sBwFZUQzP9FoGTZzJub1z8/vm+hhygA+TZbB0iclygHyNrXCkZyNdnZXChXl4iPdYqY3OARPOAbQff16+/XSUDsZ/Ok1etdb3kKor1R4rBt/WywBvXmmdggumTA3yT5ExI+dyomdONo4yMUZ7g1la0ehMEzGqyVjt0nUW31PN3l6dI1qgigHCuotSrrpWP6fTXuUh5l6YA7KXb/V1hJxaGENLz1Cdfk0sF66e4KsV/DX6JZSqpvdqVB8OTPU+si511yJtGS8OeuLs4RqmXMLrY/ChCodlYnfCE+NleBFpUnCVqth/RDRh7LvplUJlpsXNcfyoA3mOFmZa0euOMCqJ3qwESz802Y9c5oN63hn2OUF/raFDc3SMMC86FFHxwyYjz5+yzXYupnFNj39NKdQ1v1KBbY8BD8UT8RU3mlu4/3LRz0tSamREHj3pGgBmvgUZfUE1dMngeaZjOmBaIZH8TnKQ75CvfnoT+LJnZo6g9g4uwz6jtaIziSMZ0OW/95nF8yx+xONbHEtt5ex5M09NOFsN2vB2bcUAgIjyGrmmNLQadwJyQv557IGPEE5CyGhJpXh9XZ+WMw2vO45MOw4sQPkARF6OJkMteqFc2NLXMOQJ07EScbgEKR/9VOcyxIk/7a7nc=
911

12+
before_install:
13+
- curl -o- -L https://yarnpkg.com/install.sh | bash
14+
- export PATH="$HOME/.yarn/bin:$PATH"
15+
1016
install:
1117
- pip install --user proselint
1218
- cp .proselintrc ~

client-generator/images/adnew.png

53.7 KB
Loading

client-generator/images/del.png

45.3 KB
Loading

client-generator/images/item.png

52.6 KB
Loading

client-generator/images/list.png

52.9 KB
Loading

client-generator/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
API Platform Client Generator is a generator for scaffolding apps with Create-Retrieve-Update-Delete features for any API exposing a Hydra documentation. Currently the following targets are available:
44

55
* React/Redux
6+
* React Native
67
* Vue.js
78

89
The generator works especially well with APIs built with the [API Platform](https://api-platform.com) framework.

client-generator/react-native.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
React Native generator
2+
======================
3+
4+
Create a React Native application using [React Community's Create React Native App](https://github.com/react-community/create-react-native-app)
5+
6+
```bash
7+
$ yarn add -g expo-cli
8+
$ expo init my-app
9+
$ cd my-app
10+
```
11+
12+
Install: React Native Elements, React Native Router Flux, React Native Vector Icons, Redux, React Redux, Redux Thunk, Redux Form, Prop Types
13+
14+
```bash
15+
$ yarn add redux react-redux redux-thunk redux-form react-native-elements react-native-router-flux
16+
react-native-vector-icons prop-types
17+
```
18+
19+
Install the generator globally:
20+
21+
```bash
22+
$ yarn global add @api-platform/client-generator
23+
```
24+
25+
In the app directory, generate the files for the resource you want:
26+
27+
```
28+
$ generate-api-platform-client https://demo.api-platform.com -g react-native --resource foo
29+
# Replace the URL by the entrypoint of your Hydra-enabled API
30+
# Omit the resource flag to generate files for all resource types exposed by the API
31+
```
32+
Create **Router.js** file to import all routes
33+
34+
```javascript
35+
import React from 'react';
36+
import { Router, Stack } from 'react-native-router-flux';
37+
//replace "book" with the name of resource type
38+
import BookRoutes from './routes/book';
39+
40+
const RouterComponent = () => {
41+
return (
42+
<Router>
43+
<Stack key="root">
44+
{BookRoutes}
45+
</Stack>
46+
</Router>
47+
);
48+
};
49+
50+
export default RouterComponent;
51+
```
52+
Here is an example of **App.js**
53+
54+
```javascript
55+
import React, { Component } from 'react';
56+
import { Provider } from 'react-redux';
57+
import thunk from 'redux-thunk';
58+
import { createStore, applyMiddleware, combineReducers} from 'redux';
59+
import { View } from 'react-native';
60+
import {reducer as form} from 'redux-form';
61+
//replace "book" with the name of resource type
62+
import book from './reducers/book';
63+
import Router from './Router';
64+
65+
export default class App extends Component {
66+
render() {
67+
const store = createStore(combineReducers({
68+
book,
69+
form
70+
}), {}, applyMiddleware(thunk));
71+
return (
72+
<Provider store={store}>
73+
<View style={{flex: 1}}>
74+
<Router/>
75+
</View>
76+
</Provider>
77+
);
78+
}
79+
}
80+
```
81+
82+
The code is ready to be executed!
83+
```bash
84+
$ expo start
85+
```
86+
87+
#### Example of running application on IOS simulator
88+
89+
![List](images/list.png) ![Show](images/item.png)
90+
![Add](images/adnew.png) ![Delete](images/del.png)

client-generator/react.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@ Bootstrap 4 - from release 0.1.16
3838

3939
In the app directory, generate the files for the resource you want:
4040

41-
$ generate-api-platform-client https://demo.api-platform.com src/ --resource foo
42-
# Replace the URL by the entrypoint of your Hydra-enabled API
43-
# Omit the resource flag to generate files for all resource types exposed by the API
41+
```bash
42+
$ generate-api-platform-client https://demo.api-platform.com src/ --resource book
43+
# Replace the URL by the entrypoint of your Hydra-enabled API
44+
# Omit the resource flag to generate files for all resource types exposed by the API
45+
```
4446

4547
The code is ready to be executed! Register the generated reducers and components in the `index.js` file, here is an example:
4648

4749
```javascript
4850
import React from 'react';
49-
import ReactDom from 'react-dom';
50-
import registerServiceWorker from './registerServiceWorker';
51+
import ReactDOM from 'react-dom';
52+
import * as serviceWorker from './serviceWorker';
53+
5154
import { createStore, combineReducers, applyMiddleware } from 'redux';
5255
import { Provider } from 'react-redux';
5356
import thunk from 'redux-thunk';
@@ -56,28 +59,31 @@ import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
5659
import createBrowserHistory from 'history/createBrowserHistory';
5760
import { syncHistoryWithStore, routerReducer as routing } from 'react-router-redux'
5861

59-
// Replace "foo" with the name of the resource type
60-
import foo from './reducers/foo/';
61-
import fooRoutes from './routes/foo';
62+
// Replace "book" with the name of the resource type
63+
import book from './reducers/book/';
64+
import bookRoutes from './routes/book';
6265

6366
const store = createStore(
64-
combineReducers({routing, form, foo}), // Don't forget to register the reducers here
67+
combineReducers({routing, form, book}), // Don't forget to register the reducers here
6568
applyMiddleware(thunk),
6669
);
6770

6871
const history = syncHistoryWithStore(createBrowserHistory(), store);
6972

70-
ReactDom.render(
73+
ReactDOM.render(
7174
<Provider store={store}>
7275
<Router history={history}>
7376
<Switch>
74-
{fooRoutes}
77+
{bookRoutes}
7578
<Route render={() => <h1>Not Found</h1>}/>
7679
</Switch>
7780
</Router>
7881
</Provider>,
7982
document.getElementById('root')
8083
);
8184

82-
registerServiceWorker();
85+
// If you want your app to work offline and load faster, you can change
86+
// unregister() to register() below. Note this comes with some pitfalls.
87+
// Learn more about service workers: http://bit.ly/CRA-PWA
88+
serviceWorker.unregister();
8389
```

core/dto.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ There is two solutions to achieve that:
207207

208208
#### Use Swagger Decorator
209209

210-
By following the doc about [Override the Swagger Documentation](swagger.md##overriding-the-swagger-documentation)
210+
By following the doc about [Override the Swagger Documentation](swagger.md#overriding-the-swagger-documentation)
211211
and adding the ability to retrieve a `_api_swagger_context` in route
212212
parameters, you should be able to display your custom endpoint.
213213

core/file-upload.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ vich_uploader:
3232
3333
## Configuring the Entity Receiving the Uploaded File
3434
35-
In our exemple, we will create a `MediaObject` API resource. We will post files
35+
In our example, we will create a `MediaObject` API resource. We will post files
3636
to this resource endpoint, and then link the newly created resource to another
3737
resource (in our case: Book).
3838

core/filters.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ Case insensitivity may already be enforced at the database level depending on th
136136
used. If you are using MySQL, note that the commonly used `utf8_unicode_ci` collation (and its sibling `utf8mb4_unicode_ci`)
137137
are already case insensitive, as indicated by the `_ci` part in their names.
138138

139+
Note: Search filters with the exact strategy can have multiple values for a same property (in this case the condition will be similar to a SQL IN clause).
140+
141+
Syntax: `?property[]=foo&property[]=bar`
142+
139143
In the following example, we will see how to allow the filtering of a list of e-commerce offers:
140144

141145
```php
@@ -160,6 +164,7 @@ class Offer
160164

161165
`http://localhost:8000/api/offers?price=10` will return all offers with a price being exactly `10`.
162166
`http://localhost:8000/api/offers?name=shirt` will return all offers with a description containing the word "shirt".
167+
`http://localhost:8000/api/offers?name[]=shirt&name[]=sweat` will return all offers with a description containing the word "shirt" or containing the word "sweat".
163168

164169
Filters can be combined together: `http://localhost:8000/api/offers?price=10&name=shirt`
165170

@@ -680,7 +685,7 @@ final class RegexpFilter extends AbstractContextAwareFilter
680685
) {
681686
return;
682687
}
683-
688+
684689
$parameterName = $queryNameGenerator->generateParameterName($property); // Generate a unique parameter name to avoid collisions with other filters
685690
$queryBuilder
686691
->andWhere(sprintf('REGEXP(o.%s, :%s) = 1', $property, $parameterName))
@@ -1074,7 +1079,7 @@ class DummyCar
10741079
* @ApiFilter(SearchFilter::class, properties={"colors.prop": "ipartial"})
10751080
*/
10761081
private $colors;
1077-
1082+
10781083
// ...
10791084
}
10801085

core/identifiers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ final class UuidNormalizer implements DenormalizerInterface
9999
Tag this service as a `api_platform.identifier.normalizer`:
100100

101101
```xml
102-
<service id="App\identifier\UuidNormalizer" class="App\identifier\UuidNormalizer" public="false">
102+
<service id="App\Identifier\UuidNormalizer" class="App\Identifier\UuidNormalizer" public="false">
103103
<tag name="api_platform.identifier.normalizer" />
104104
</service>
105105
```
106106

107107
```yaml
108108
services:
109-
App\identifier\UuidNormalizer:
109+
App\Identifier\UuidNormalizer:
110110
tags:
111111
- { name: api_platform.identifier.normalizer }
112112
```

core/operations.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,29 @@ class Question
462462
}
463463
```
464464

465+
### Access Control of Subresources
466+
467+
The `subresourceOperations` attribute also allows you to add an access control on each path with the attribute `access_control`.
468+
469+
```php
470+
<?php
471+
// api/src/Entity/Question.php
472+
473+
/**
474+
* ...
475+
* @ApiResource(
476+
* subresourceOperations={
477+
* "answer_get_subresource"= {
478+
* "method"="GET",
479+
* "access_control"="has_role('ROLE_AUTHENTICATED')"
480+
* }
481+
* }
482+
* )
483+
class Question
484+
{
485+
}
486+
```
487+
465488
### Control the Depth of Subresources
466489

467490
You can control depth of subresources with the parameter `maxDepth`. For example, if `Answer` entity also have subresource
@@ -663,7 +686,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
663686
class Book
664687
{
665688
//...
666-
689+
667690
/**
668691
* @Groups("special")
669692
*/

core/performance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fresh, because the cache is purged in real time.
2020
The support for most specific cases such as the invalidation of collections when a document is added or removed or for
2121
relationships and inverse relations is built-in.
2222

23-
We also included [Varnish](https://varnish-cache.org/) in the [Docker setup](../deployment/docker.md) provided with the
23+
We also included [Varnish](https://varnish-cache.org/) in the [Docker setup](../distribution/index.md#using-the-official-distribution-recommended) provided with the
2424
distribution of API Platform, so this feature works out of the box.
2525

2626
Integration with Varnish and the Doctrine ORM is shipped with the core library. You can easily implement the support for

core/serialization.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ class Book
308308
}
309309
```
310310

311-
The following rules apply when denormalizating embedded relations:
311+
The following rules apply when denormalizing embedded relations:
312312

313313
* If an `@id` key is present in the embedded resource, then the object corresponding to the given URI will be retrieved through
314314
the data provider. Any changes in the embedded relation will also be applied to that object.
@@ -450,6 +450,7 @@ namespace App\Serializer;
450450
451451
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
452452
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
453+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
453454
use Symfony\Component\Serializer\SerializerAwareInterface;
454455
use Symfony\Component\Serializer\SerializerAwareTrait;
455456
@@ -495,7 +496,7 @@ class BookAttributeNormalizer implements ContextAwareNormalizerInterface, Serial
495496
private function passOn($object, $format = null, array $context = [])
496497
{
497498
if (!$this->serializer instanceof NormalizerInterface) {
498-
throw new LogicException(sprintf('Cannot normalize object "%s" because the injected serializer is not a normalizer', $object));
499+
throw new \LogicException(sprintf('Cannot normalize object "%s" because the injected serializer is not a normalizer', $object));
499500
}
500501
501502
$context[self::BOOK_ATTRIBUTE_NORMALIZER_ALREADY_CALLED] = true;
@@ -606,7 +607,7 @@ final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface,
606607
API Platform is able to guess the entity identifier using [Doctrine metadata](http://doctrine-orm.readthedocs.org/en/latest/reference/basic-mapping.html#identifiers-primary-keys).
607608
It also supports composite identifiers.
608609

609-
If you are not using the Doctrine ORM Provider, you must explictely mark the identifier using the `identifier` attribute of
610+
If you are not using the Doctrine ORM Provider, you must explicitly mark the identifier using the `identifier` attribute of
610611
the `ApiPlatform\Core\Annotation\ApiProperty` annotation. For example:
611612

612613

core/swagger.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class Product // The class name will be used to name exposed resources
103103
public $id;
104104

105105
/**
106-
* @param string $name A name property - this description will be avaliable in the API documentation too.
106+
* @param string $name A name property - this description will be available in the API documentation too.
107107
*
108108
* @ORM\Column
109109
* @Assert\NotBlank

distribution/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,9 @@ ISBN isn't valid...
643643
## Adding GraphQL Support
644644

645645
Isn't API Platform a REST **and** GraphQL framework? That's true! GraphQL support isn't enabled by default, to add it we
646-
need to install the [graphql-php](https://webonyx.github.io/graphql-php/) library. Run the following command:
646+
need to install the [graphql-php](https://webonyx.github.io/graphql-php/) library. Run the following command (the cache needs to be cleared twice):
647647

648-
$ docker-compose exec php composer req webonyx/graphql-php
648+
$ docker-compose exec php composer req webonyx/graphql-php && bin/console cache:clear
649649

650650
You now have a GraphQL API! Open `https://localhost:8443/graphql` to play with it using the nice [GraphiQL](https://github.com/graphql/graphiql)
651651
UI that is shipped with API Platform:

0 commit comments

Comments
 (0)