diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 92479f1e2d9..52be4952be1 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -2,7 +2,7 @@
If your pull request fixes a BUG, use the last stable branch that contains the bug.
-If your pull request documents a NEW FEATURE, use the `master` branch.
+If your pull request documents a NEW FEATURE, use the `main` branch.
Versions and branches are described there: https://api-platform.com/docs/extra/releases/
diff --git a/.textlintrc b/.textlintrc
new file mode 100644
index 00000000000..9a594e1278c
--- /dev/null
+++ b/.textlintrc
@@ -0,0 +1,10 @@
+{
+ "rules": {
+ "terminology": {
+ "exclude": [
+ "Node(?:js)?",
+ "web[- ]?site(s)?"
+ ]
+ }
+ }
+}
diff --git a/.travis.yml b/.travis.yml
index bbdd684f63b..4f32632a8f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -37,4 +37,4 @@ deploy:
fqdn: api-platform.com
on:
all_branches: true
- condition: $TRAVIS_BRANCH =~ ^(master|2.5|2.4|2.3|2.2|2.1)$
+ condition: $TRAVIS_BRANCH =~ ^(main|2.6|2.5|2.4|2.3|2.2|2.1)$
diff --git a/client-generator/nextjs.md b/client-generator/nextjs.md
index 776e8e1c19c..0fc2c05658b 100644
--- a/client-generator/nextjs.md
+++ b/client-generator/nextjs.md
@@ -8,7 +8,7 @@ The Next.js Client Generator generates components for Server Side Rendered appli
### Next + Express Server
-Create a [Next.js application with express server](https://github.com/zeit/next.js/tree/canary/examples/custom-server-express). The easiest way is to execute:
+Create a [Next.js application with express server](https://github.com/zeit/next.js/tree/canary/examples/custom-server-express). The easiest way is to execute:
$ npx create-next-app your-app-name
# or
@@ -33,13 +33,13 @@ Install required dependencies:
## Starting the Project
-You can launch the server with
+You can launch the server with
$ yarn dev
-Go to `https://localhost:3000/books/` to start using your app.
+Go to `http://localhost:3000/books/` to start using your app.
## Screenshots
-
+

diff --git a/client-generator/nuxtjs.md b/client-generator/nuxtjs.md
index 50752b20397..971c4ca8514 100644
--- a/client-generator/nuxtjs.md
+++ b/client-generator/nuxtjs.md
@@ -30,8 +30,24 @@ Deployment target: Static (Static/JAMStack hosting)
Install required dependencies:
- $ yarn add moment lodash vue-i18n vuelidate vuex-map-fields
+ $ yarn add moment lodash vue-i18n vuelidate vuex-map-fields nuxt-i18n
+ # yarn add --dev @nuxtjs/vuetify @nuxtjs/fontawesome
+## Updating nuxtjs config
+
+Update your `nuxt.config.js` with following:
+
+```javascript
+ buildModules: [
+ // ...
+ '@nuxtjs/vuetify',
+ '@nuxtjs/fontawesome',
+ 'nuxt-i18n'
+ ],
+ // ...
+ // to avoid name conflicts in generators
+ components: false,
+```
## Generating Routes
$ npx @api-platform/client-generator https://demo.api-platform.com . --generator nuxt
@@ -95,7 +111,7 @@ Update your `layouts/default.vue` with following:
```
diff --git a/core/content-negotiation.md b/core/content-negotiation.md
index 818dbcb7dae..6cc20e76e25 100644
--- a/core/content-negotiation.md
+++ b/core/content-negotiation.md
@@ -33,7 +33,7 @@ Format | Format name |
If the client's requested format is not specified, the response format will be the first format defined in the `formats` configuration key (see below).
If the request format is not supported, an [Unsupported Media Type](https://developer.mozilla.org/fr/docs/Web/HTTP/Status/415) error will be returned.
-Examples showcasing how to use the different mechanisms are available [in the API Platform test suite](https://github.com/api-platform/core/blob/master/features/main/content_negotiation.feature).
+Examples showcasing how to use the different mechanisms are available [in the API Platform test suite](https://github.com/api-platform/core/blob/main/features/main/content_negotiation.feature).
## Configuring Formats Globally
@@ -121,7 +121,7 @@ this configuration might disable the `json` or the `html` on this resource for e
You can specify different accepted formats at operation level too, it's especially convenient for to configure formats available for the `PATCH` method:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
## Supporting Custom Formats
diff --git a/core/controllers.md b/core/controllers.md
index ae5cb0d3c06..14bec50df88 100644
--- a/core/controllers.md
+++ b/core/controllers.md
@@ -79,7 +79,7 @@ the client.
The routing has not been configured yet because we will add it at the resource configuration level:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
It is mandatory to set the `method`, `path` and `controller` attributes. They allow API Platform to configure the routing path and
the associated controller respectively.
@@ -143,7 +143,7 @@ the associated controller respectively.
You may want different serialization groups for your custom operations. Just configure the proper `normalization_context` and/or `denormalization_context` in your operation:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
## Retrieving the Entity
If you want to bypass the automatic retrieval of the entity in your custom operation, you can set `"read"=false` in the
operation attribute:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
This way, it will skip the `ReadListener`. You can do the same for some other built-in listeners. See [Built-in Event Listeners](events.md#built-in-event-listeners)
for more information.
@@ -296,7 +296,7 @@ for `book_post_discontinuation` when neither `method` nor `route_name` attribute
First, let's create your resource configuration:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
API Platform will automatically map this `post_publication` operation to the route `book_post_publication`. Let's create a custom action
and its related route using annotations:
diff --git a/core/data-persisters.md b/core/data-persisters.md
index a4398757232..89ecb496b80 100644
--- a/core/data-persisters.md
+++ b/core/data-persisters.md
@@ -22,7 +22,7 @@ persist data for a given resource will be used.
## Creating a Custom Data Persister
-To create a data persister, you have to implement the [`ContextAwareDataPersisterInterface`](https://github.com/api-platform/core/blob/master/src/DataPersister/ContextAwareDataPersisterInterface.php).
+To create a data persister, you have to implement the [`ContextAwareDataPersisterInterface`](https://github.com/api-platform/core/blob/main/src/DataPersister/ContextAwareDataPersisterInterface.php).
This interface defines only 3 methods:
* `persist`: to create or update the given data
@@ -71,7 +71,7 @@ services:
#tags: [ 'api_platform.data_persister' ]
```
-Note that if you don't need any `$context` in your data persister's methods, you can implement the [`DataPersisterInterface`](https://github.com/api-platform/core/blob/master/src/DataPersister/DataPersisterInterface.php) instead.
+Note that if you don't need any `$context` in your data persister's methods, you can implement the [`DataPersisterInterface`](https://github.com/api-platform/core/blob/main/src/DataPersister/DataPersisterInterface.php) instead.
## Decorating the Built-In Data Persisters
@@ -79,6 +79,8 @@ Note that if you don't need any `$context` in your data persister's methods, you
If you want to execute custom business logic before or after persistence, this can be achieved by [decorating](https://symfony.com/doc/current/service_container/service_decoration.html) the built-in data persisters.
+The next example uses [Symfony Mailer](https://symfony.com/doc/current/mailer.html). Read its documentation if you want to use it.
+
Here is an implementation example which sends new users a welcome email after a REST `POST` or GraphQL `create` operation, in a project using the native Doctrine ORM data persister:
```php
diff --git a/core/data-providers.md b/core/data-providers.md
index 018d0824eb3..b5947520708 100644
--- a/core/data-providers.md
+++ b/core/data-providers.md
@@ -13,13 +13,13 @@ retrieve data for a given resource will be used.
For a given resource, you can implement two kinds of interface:
-* the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/DataProvider/CollectionDataProviderInterface.php)
+* the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/CollectionDataProviderInterface.php)
is used when fetching a collection.
-* the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/DataProvider/ItemDataProviderInterface.php)
+* the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/ItemDataProviderInterface.php)
is used when fetching items.
Both implementations can also implement a third, optional, interface called
-['RestrictedDataProviderInterface'](https://github.com/api-platform/core/blob/master/src/DataProvider/RestrictedDataProviderInterface.php)
+['RestrictedDataProviderInterface'](https://github.com/api-platform/core/blob/main/src/DataProvider/RestrictedDataProviderInterface.php)
if you want to limit their effects to a single resource or operation.
In the following examples we will create custom data providers for an entity class called `App\Entity\BlogPost`.
@@ -27,9 +27,9 @@ Note, that if your entity is not Doctrine-related, you need to flag the identifi
## Custom Collection Data Provider
-First, your `BlogPostCollectionDataProvider` has to implement the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/DataProvider/CollectionDataProviderInterface.php):
+First, your `BlogPostCollectionDataProvider` has to implement the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/CollectionDataProviderInterface.php):
-The `getCollection` method must return an `array`, a `Traversable` or a [`ApiPlatform\Core\DataProvider\PaginatorInterface`](https://github.com/api-platform/core/blob/master/src/DataProvider/PaginatorInterface.php) instance.
+The `getCollection` method must return an `array`, a `Traversable` or a [`ApiPlatform\Core\DataProvider\PaginatorInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/PaginatorInterface.php) instance.
If no data is available, you should return an empty array.
```php
@@ -40,7 +40,6 @@ namespace App\DataProvider;
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
-use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Entity\BlogPost;
final class BlogPostCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
@@ -74,14 +73,13 @@ services:
Tagging the service with the tag `api_platform.collection_data_provider` will enable API Platform Core to automatically
register and use this data provider. The optional attribute `priority` allows you to define the order in which the
-data providers are called. The first data provider not throwing a `ApiPlatform\Core\Exception\ResourceClassNotSupportedException`
-will be used.
+data providers are called. Implementing the `ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface` let you restrict the data provider use. Alternatively, you can also throw a `ApiPlatform\Core\Exception\ResourceClassNotSupportedException`. Without the `RestrictedDataProviderInterface`, the first data provider not throwing this exception will be used.
-You can find a full working example in the [API Platform's demo application](https://github.com/api-platform/demo/blob/master/api/src/DataProvider/TopBookCollectionDataProvider.php).
+You can find a full working example in the [API Platform's demo application](https://github.com/api-platform/demo/blob/main/api/src/DataProvider/TopBookCollectionDataProvider.php).
## Custom Item Data Provider
-The process is similar for item data providers. Create a `BlogPostItemDataProvider` implementing the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/DataProvider/ItemDataProviderInterface.php)
+The process is similar for item data providers. Create a `BlogPostItemDataProvider` implementing the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/ItemDataProviderInterface.php)
interface:
The `getItem` method can return `null` if no result has been found.
@@ -94,7 +92,6 @@ namespace App\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
-use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Entity\BlogPost;
final class BlogPostItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
@@ -127,7 +124,7 @@ services:
#tags: [ 'api_platform.item_data_provider' ]
```
-You can find a full working example in the [API Platform's demo application](https://github.com/api-platform/demo/blob/master/api/src/DataProvider/TopBookItemDataProvider.php).
+You can find a full working example in the [API Platform's demo application](https://github.com/api-platform/demo/blob/main/api/src/DataProvider/TopBookItemDataProvider.php).
## Injecting the Serializer in an `ItemDataProvider`
@@ -145,7 +142,6 @@ namespace App\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface;
use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderTrait;
-use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Entity\BlogPost;
final class BlogPostItemDataProvider implements ItemDataProviderInterface, SerializerAwareDataProviderInterface
@@ -174,7 +170,7 @@ API Platform provides a few extensions that you can reuse in your custom DataPro
Note that there are a few kinds of extensions which are detailed in [their own chapter of the documentation](extensions.md).
Because extensions are tagged services, you can use the [injection of tagged services](https://symfony.com/blog/new-in-symfony-3-4-simpler-injection-of-tagged-services):
-[codeSelector]
+
```yaml
services:
'App\DataProvider\BlogPostItemDataProvider':
@@ -189,7 +185,7 @@ services:
```
-[/codeSelector]
+
Your data provider will now have access to the core extensions, here is an example on how to use them:
@@ -203,7 +199,6 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInter
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
-use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Entity\BlogPost;
use Doctrine\Persistence\ManagerRegistry;
diff --git a/core/dto.md b/core/dto.md
index 6aad15c1088..f2fd694ae8d 100644
--- a/core/dto.md
+++ b/core/dto.md
@@ -9,7 +9,7 @@ However, it's sometimes useful to use a specific class to represent the input or
For a given resource class, you may want to have a different representation of this class as input (write) or output (read).
To do so, a resource can take an input and/or an output class:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
The `input` attribute is used during [the deserialization process](serialization.md), when transforming the user-provided data to a resource instance.
Similarly, the `output` attribute is used during [the serialization process](serialization.md). This class represents how the `Book` resource will be represented in the `Response`.
@@ -278,7 +278,7 @@ will be skipped. If `output` is `false`, the serialization process will be skipp
`input` and `output` attributes can be set on a per operation basis:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
## Input/Output Metadata
diff --git a/core/elasticsearch.md b/core/elasticsearch.md
index 93e412d013f..cdacad7f752 100644
--- a/core/elasticsearch.md
+++ b/core/elasticsearch.md
@@ -41,9 +41,9 @@ api_platform:
API Platform follows the best practices of Elasticsearch:
* a single index per resource should be used because Elasticsearch is going to [drop support for index types and will allow only a single type per
index](https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html);
-* index name should be the short resource name in lower case;
+* index name should be the short resource name in lower snake case;
* the default `_doc` type should be used;
-* all fields should be lower case and should use snake case for combining words.
+* all fields should be lower case and should use camel case for combining words.
This involves having mappings and models which absolutely match each other.
@@ -222,7 +222,7 @@ class Tweet
}
```
-API Platform will automatically disable write operations and snake case document fields will automatically be converted to
+API Platform will automatically disable write operations and camel case document fields will automatically be converted to
camel case object properties during serialization.
Keep in mind that it is your responsibility to populate your Elasticsearch index. To do so, you can use [Logstash](https://www.elastic.co/products/logstash),
diff --git a/core/events.md b/core/events.md
index 60424637614..b7f80f9728c 100644
--- a/core/events.md
+++ b/core/events.md
@@ -59,7 +59,7 @@ Attribute | Type | Default | Description
Registering your own event listeners to add extra logic is convenient.
-The [`ApiPlatform\Core\EventListener\EventPriorities`](https://github.com/api-platform/core/blob/master/src/EventListener/EventPriorities.php) class comes with a convenient set of class constants corresponding to commonly used priorities:
+The [`ApiPlatform\Core\EventListener\EventPriorities`](https://github.com/api-platform/core/blob/main/src/EventListener/EventPriorities.php) class comes with a convenient set of class constants corresponding to commonly used priorities:
Constant | Event | Priority |
-------------------|-------------------|----------|
diff --git a/core/extending-jsonld-context.md b/core/extending-jsonld-context.md
index 80547eeb028..3b553f9e861 100644
--- a/core/extending-jsonld-context.md
+++ b/core/extending-jsonld-context.md
@@ -2,7 +2,7 @@
## JSON-LD
-

Watch the JSON-LD screencast
+

Watch the JSON-LD screencast
API Platform Core provides the possibility to extend the JSON-LD context of properties. This allows you to describe JSON-LD-typed
values, inverse properties using the `@reverse` keyword and you can even overwrite the `@id` property this way. Everything you define
@@ -75,7 +75,7 @@ Note that you do not have to provide the `@id` attribute. If you do not provide
It's also possible to replace the Hydra context used by the documentation generator:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
diff --git a/core/filters.md b/core/filters.md
index 407e14c4add..f75da7ccf3f 100644
--- a/core/filters.md
+++ b/core/filters.md
@@ -12,7 +12,7 @@ By default, all filters are disabled. They must be enabled explicitly.
When a filter is enabled, it automatically appears in the [OpenAPI](swagger.md) and [GraphQL](graphql.md) documentations.
It is also automatically documented as a `hydra:search` property for JSON-LD responses.
-
Watch the Filtering & Searching screencast
+

Watch the Filtering & Searching screencast
## Doctrine ORM and MongoDB ODM Filters
@@ -42,7 +42,7 @@ services:
We're linking the filter `offer.date_filter` with the resource like this:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
2. By using the `@ApiFilter` annotation.
diff --git a/core/getting-started.md b/core/getting-started.md
index 68220118305..1473dfe593c 100644
--- a/core/getting-started.md
+++ b/core/getting-started.md
@@ -178,7 +178,7 @@ It is also possible to override the naming convention using [operation path nami
As an alternative to annotations, you can map entity classes using YAML or XML:
-[codeSelector]
+
```yaml
# api/config/api_platform/resources.yaml
resources:
@@ -208,7 +208,7 @@ resources:
/>
```
-[/codeSelector]
+
If you prefer to use YAML or XML files instead of annotations, you must configure API Platform to load the appropriate files:
@@ -230,4 +230,4 @@ Run the Symfony app with the [Symfony Local Web Server](https://symfony.com/doc/
Interact with the API using a REST client (we recommend [Postman](https://www.getpostman.com/)) or an Hydra-aware application
(you should give [Hydra Console](https://github.com/lanthaler/HydraConsole) a try). Take
-a look at the usage examples in [the `features` directory](https://github.com/api-platform/core/tree/master/features).
+a look at the usage examples in [the `features` directory](https://github.com/api-platform/core/tree/main/features).
diff --git a/core/identifiers.md b/core/identifiers.md
index 0e2e5fc4aed..3d04e30baa2 100644
--- a/core/identifiers.md
+++ b/core/identifiers.md
@@ -9,6 +9,7 @@ To help with your development experience, we introduced an identifier normalizat
Let's say you have the following class, which is identified by a `UUID` type. In this example, `UUID` is not a simple string but an object with many attributes.
+
```php
+
+
+
+
+```
+
+
Once registered as an `ApiResource`, having an existing person, it will be accessible through the following URL: `/people/110e8400-e29b-11d4-a716-446655440000`.
Note that the property identifying our resource is named `code`.
@@ -105,7 +115,7 @@ final class UuidNormalizer implements DenormalizerInterface
Tag this service as an `api_platform.identifier.denormalizer`:
-[codeSelector]
+
```yaml
services:
App\Identifier\UuidNormalizer:
@@ -118,7 +128,7 @@ services:
```
-[/codeSelector]
+
Your `PersonDataProvider` will now work as expected!
@@ -167,5 +177,5 @@ final class Person
API Platform supports the following identifier types:
- `scalar` (string, integer)
- - `\DateTime` (uses the symfony `DateTimeNormalizer` internally, see [DateTimeIdentifierNormalizer](https://github.com/api-platform/core/blob/master/src/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php))
- - `\Ramsey\Uuid\Uuid` (see [UuidNormalizer](https://github.com/api-platform/core/blob/master/src/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php))
+ - `\DateTime` (uses the symfony `DateTimeNormalizer` internally, see [DateTimeIdentifierNormalizer](https://github.com/api-platform/core/blob/main/src/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php))
+ - `\Ramsey\Uuid\Uuid` (see [UuidNormalizer](https://github.com/api-platform/core/blob/main/src/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php))
diff --git a/core/index.md b/core/index.md
index 54f250e5aff..260a3facb0b 100644
--- a/core/index.md
+++ b/core/index.md
@@ -38,7 +38,7 @@ Here is the fully featured REST API you'll get in minutes:
Everything is fully customizable through a powerful [event system](events.md) and strong OOP.
-This bundle is extensively tested (unit and functional). The [`Fixtures/` directory](https://github.com/api-platform/core/tree/master/tests/Fixtures) contains a working app covering all features of the library.
+This bundle is extensively tested (unit and functional). The [`Fixtures/` directory](https://github.com/api-platform/core/tree/main/tests/Fixtures) contains a working app covering all features of the library.
## Screencasts
diff --git a/core/jwt.md b/core/jwt.md
index 7ac6b355e7c..787215373b3 100644
--- a/core/jwt.md
+++ b/core/jwt.md
@@ -12,10 +12,13 @@ API Platform allows to easily add a JWT-based authentication to your API using [
We begin by installing the bundle:
+```
$ docker-compose exec php composer require jwt-auth
+```
Then we need to generate the public and private keys used for signing JWT tokens. If you're using the [API Platform distribution](../distribution/index.md), you may run this from the project's root directory:
+```
$ docker-compose exec php sh -c '
set -e
apk add openssl
@@ -26,6 +29,7 @@ Then we need to generate the public and private keys used for signing JWT tokens
setfacl -R -m u:www-data:rX -m u:"$(whoami)":rwX config/jwt
setfacl -dR -m u:www-data:rX -m u:"$(whoami)":rwX config/jwt
'
+```
Note that the `setfacl` command relies on the `acl` package. This is installed by default when using the API Platform docker distribution but may need be installed in your working environment in order to execute the `setfacl` command.
@@ -298,69 +302,60 @@ services:
autoconfigure: false
```
-## Testing with Behat
+## Testing
-Let's configure Behat to automatically send an `Authorization` HTTP header containing a valid JWT token when a scenario is marked with a `@login` annotation. Edit `features/bootstrap/FeatureContext.php` and add the following methods:
+To test your authentication with `ApiTestCase`, you can write a method as below:
```php
setUsername('admin');
- $user->setPassword('ATestPassword');
- $user->setEmail('test@test.com');
+ $client = self::createClient();
- $this->manager->persist($user);
- $this->manager->flush();
+ $user = new User();
+ $user->setEmail('test@example.com');
+ $user->setPassword(
+ self::$container->get('security.password_encoder')->encodePassword($user, '$3CR3T')
+ );
+
+ $manager = self::$container->get('doctrine')->getManager();
+ $manager->persist($user);
+ $manager->flush();
+
+ // retrieve a token
+ $response = $client->request('POST', '/authentication_token', [
+ 'headers' => ['Content-Type' => 'application/json'],
+ 'json' => [
+ 'email' => 'test@example.com',
+ 'password' => '$3CR3T',
+ ],
+ ]);
- $token = $this->jwtManager->create($user);
+ $json = $response->toArray();
+ $this->assertResponseIsSuccessful();
+ $this->assertArrayHasKey('token', $json);
- $this->restContext = $scope->getEnvironment()->getContext(RestContext::class);
- $this->restContext->iAddHeaderEqualTo('Authorization', "Bearer $token");
- }
+ // test not authorized
+ $client->request('GET', '/greetings');
+ $this->assertResponseStatusCodeSame(401);
- /**
- * @AfterScenario
- * @logout
- */
- public function logout() {
- $this->restContext->iAddHeaderEqualTo('Authorization', '');
+ // test authorized
+ $client->request('GET', '/greetings', ['auth_bearer' => $json['token']]);
+ $this->assertResponseIsSuccessful();
}
}
```
-Then, update `behat.yml` to inject the `lexik_jwt_authentication.jwt_manager`:
-
-```yaml
-# behat.yml
-default:
- # ...
- suites:
- default:
- contexts:
- - FeatureContext: { doctrine: '@doctrine', 'jwtManager': '@lexik_jwt_authentication.jwt_manager' }
- - Behat\MinkExtension\Context\MinkContext
- - Behatch\Context\RestContext
- - Behatch\Context\JsonContext
- # ...
-```
-
-Finally, mark your scenarios with the `@login` annotation to automatically add a valid `Authorization` header, and with `@logout` to be sure to destroy the token after this scenario.
+Refer to [Testing the API](../distribution/testing.md) for more information about testing API Platform.
diff --git a/core/mercure.md b/core/mercure.md
index 5b175472e2b..72bfba73b3c 100644
--- a/core/mercure.md
+++ b/core/mercure.md
@@ -27,7 +27,7 @@ Finally, 3 environment variables [must be set](https://symfony.com/doc/current/c
* `MERCURE_PUBLISH_URL`: the URL that must be used by API Platform to publish updates to your Mercure hub (can be an internal or a public URL)
* `MERCURE_SUBSCRIBE_URL`: the **public** URL of the Mercure hub that clients will use to subscribe to updates
-* `MERCURE_JWT_SECRET`: a valid Mercure [JSON Web Token (JWT)](https://jwt.io/) allowing API Platform to publish updates to the hub
+* `MERCURE_JWT_TOKEN`: a valid Mercure [JSON Web Token (JWT)](https://jwt.io/) allowing API Platform to publish updates to the hub
The JWT **must** contain a `mercure.publish` property containing an array of topic selectors.
This array can be empty to allow publishing anonymous updates only. It can also be `["*"]` to allow publishing on every topics.
diff --git a/core/messenger.md b/core/messenger.md
index 9c0addbedde..a78f6d924af 100644
--- a/core/messenger.md
+++ b/core/messenger.md
@@ -17,7 +17,7 @@ To enable the support of Messenger, install the library:
Set the `messenger` attribute to `true`, and API Platform will automatically dispatch the API Resource instance as a message using the message bus provided by the Messenger Component:
-[codeSelector]
+
```php
Because the `messenger` attribute is `true`, when a `POST` is handled by API Platform, the corresponding instance of the `ResetPasswordRequest` will be dispatched.
diff --git a/core/mongodb.md b/core/mongodb.md
index b6a35e32c51..8ba0476e8ee 100644
--- a/core/mongodb.md
+++ b/core/mongodb.md
@@ -111,7 +111,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class Product
{
/**
- * @ODM\Id(strategy="INCREMENT", type="integer")
+ * @ODM\Id(strategy="INCREMENT", type="int")
*/
private $id;
@@ -170,7 +170,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class Offer
{
/**
- * @ODM\Id(strategy="INCREMENT", type="integer")
+ * @ODM\Id(strategy="INCREMENT", type="int")
*/
private $id;
diff --git a/core/operation-path-naming.md b/core/operation-path-naming.md
index d6261d456b7..db36814fe20 100644
--- a/core/operation-path-naming.md
+++ b/core/operation-path-naming.md
@@ -27,7 +27,7 @@ Let's assume we need URLs without separators (e.g. `api.tld/myresources`)
### Defining the Operation Segment Name Generator
-Make sure the custom segment generator implements [`ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface`](https://github.com/api-platform/core/blob/master/src/Operation/PathSegmentNameGeneratorInterface.php):
+Make sure the custom segment generator implements [`ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface`](https://github.com/api-platform/core/blob/main/src/Operation/PathSegmentNameGeneratorInterface.php):
```php
```php
```
-[/codeSelector]
+
The previous example can also be written with an explicit method definition:
+
```php
+
+
+
+
+
+
+
+
+
+ GET
+
+
+
+
+```
+
+
+You can also disable all operations for an item or a collection. This example disables every item-related routes (PUT, GET, DELETE):
+
+
+```php
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
API Platform Core is smart enough to automatically register the applicable Symfony route referencing a built-in CRUD action
just by specifying the method name as key, or by checking the explicitly configured HTTP method.
If you do not want to allow access to the resource item (i.e. you don't want a `GET` item operation), instead of omitting it altogether, you should instead declare a `GET` item operation which returns HTTP 404 (Not Found), so that the resource item can still be identified by an IRI. For example:
+
```php
+
+
+
+
+
+
+
+
+
+ App\Controller\NotFoundAction
+ false
+ false
+
+
+
+
+```
+
+
## Configuring Operations
The URL, the method and the default status code (among other options) can be configured per operation.
@@ -175,7 +296,7 @@ The URL, the method and the default status code (among other options) can be con
In the next example, both `GET` and `POST` operations are registered with custom URLs. Those will override the URLs generated by default.
In addition to that, we require the `id` parameter in the URL of the `GET` operation to be an integer, and we configure the status code generated after successful `POST` request to be `301`:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
In all these examples, the `method` attribute is omitted because it matches the operation name.
@@ -275,7 +396,7 @@ Sometimes it's also useful to put a whole resource into its own "namespace" rega
put everything that's related to a `Book` into the `library` so that URIs become `library/book/{id}`. In that case
you don't need to override all the operations to set the path but configure the `route_prefix` attribute for the whole entity instead:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
Alternatively, the more verbose attribute syntax can be used: `@ApiResource(attributes={"route_prefix"="/library"})`.
diff --git a/core/pagination.md b/core/pagination.md
index ff37005701c..cf3a484b4e2 100644
--- a/core/pagination.md
+++ b/core/pagination.md
@@ -359,7 +359,7 @@ To know more about cursor-based pagination take a look at [this blog post on med
## Controlling the behavior of the Doctrine ORM Paginator
-The [PaginationExtension](https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/Extension/PaginationExtension.php) of API Platform performs some checks on the `QueryBuilder` to guess, in most common cases, the correct values to use when configuring the Doctrine ORM Paginator:
+The [PaginationExtension](https://github.com/api-platform/core/blob/main/src/Bridge/Doctrine/Orm/Extension/PaginationExtension.php) of API Platform performs some checks on the `QueryBuilder` to guess, in most common cases, the correct values to use when configuring the Doctrine ORM Paginator:
- `$fetchJoinCollection` argument: Whether there is a join to a collection-valued association. When set to `true`, the Doctrine ORM Paginator will perform an additional query, in order to get the correct number of results.
diff --git a/core/security.md b/core/security.md
index c543fa62334..74c6333c63d 100644
--- a/core/security.md
+++ b/core/security.md
@@ -4,9 +4,9 @@ The API Platform security layer is built on top of the [Symfony Security compone
All its features, including [global access control directives](http://symfony.com/doc/current/book/security.html#securing-url-patterns-access-control) are supported.
API Platform also provides convenient [access control expressions](https://symfony.com/doc/current/expressions.html#security-complex-access-controls-with-expressions) which you can apply at resource and operation level.
-
Watch the Security screencast
+

Watch the Security screencast
-[codeSelector]
+
```php
In this example:
@@ -93,7 +93,7 @@ It means than for `PUT` requests, `object` doesn't contain the value submitted b
In some cases, it might be useful to execute a security after the denormalization step.
To do so, use the `security_post_denormalize` attribute:
-[codeSelector]
+
```php
This time, the `object` variable contains data that have been extracted from the HTTP request body during the denormalization process.
However, the object is not persisted yet.
@@ -240,7 +240,7 @@ You can change it by configuring the `security_message` attribute or the `securi
For example:
-[codeSelector]
+
```php
## Filtering Collection According to the Current User Permissions
diff --git a/core/serialization.md b/core/serialization.md
index 52adbab0c93..c4f467aaeda 100644
--- a/core/serialization.md
+++ b/core/serialization.md
@@ -74,7 +74,7 @@ It is simple to specify what groups to use in the API system:
1. Add the normalization context and denormalization context attributes to the resource, and specify which groups to use. Here you see that we add `read` and `write`, respectively. You can use any group names you wish.
2. Apply the groups to properties in the object.
-[codeSelector]
+
```php
Alternatively, you can use the more verbose syntax:
@@ -703,9 +703,18 @@ services:
arguments: [ '@App\Serializer\ApiNormalizer.inner' ]
```
+Note: this normalizer will work only for JSON-LD format, if you want to process JSON data too, you have to decorate another service:
+
+```yaml
+ app.serializer.app_normalizer.json:
+ class: App\Serializer\ApiNormalizer
+ decorates: 'api_platform.serializer.normalizer.item'
+ arguments: [ '@app.serializer.app_normalizer.json.inner' ]
+```
+
```php
```php
Note that all we had to do is to set up `@ApiSubresource` on the `Question::answer` relation. Because the `answer` is a to-one relation, we know that this subresource is an item. Therefore the response will look like this:
@@ -127,7 +127,7 @@ Note: only for `GET` operations are supported at the moment
You may want custom groups on subresources, you can set `normalization_context` or `denormalization_context` on that operation. To do so, add a `subresourceOperations` node. For example:
-[codeSelector]
+
```php
```
-[/codeSelector]
+
In the previous examples, the `method` attribute is mandatory, because the operation name doesn't match a supported HTTP
method.
diff --git a/core/swagger.md b/core/swagger.md
index e506b5bf3e3..99426752394 100644
--- a/core/swagger.md
+++ b/core/swagger.md
@@ -105,7 +105,7 @@ final class SwaggerDecorator implements NormalizerInterface
Sometimes you may want to change the information included in your OpenAPI documentation.
The following configuration will give you total control over your OpenAPI definitions:
-[codeSelector]
+
```php
-
+
type
one
@@ -200,7 +200,7 @@ resources:
-
+
string
date-time
@@ -208,7 +208,7 @@ resources:
```
-[/codeSelector]
+
This will produce the following Swagger documentation:
```json
@@ -292,7 +292,7 @@ class User
You also have full control over both built-in and custom operations documentation.
-[codeSelector]
+
```yaml
resources:
App\Entity\Rabbit:
@@ -301,8 +301,8 @@ resources:
method: get
path: '/rabbit/rand'
controller: App\Controller\RandomRabbit
- # if you are using OpenApi V3 use 'openapi_context' instead of 'swagger_context'
- swagger_context:
+ # if you are using OpenApi V2 instead of V3 use 'swagger_context' instead of 'openapi_context'
+ openapi_context:
summary: Random rabbit picture
description: >
# Pop a great rabbit picture by color!
@@ -334,8 +334,8 @@ resources:
get
/rabbit/rand
App\Controller\RandomRabbit
-
-
+
+
Random rabbit picture
# Pop a great rabbit picture by color!
@@ -368,7 +368,7 @@ resources:
```
-[/codeSelector]
+

@@ -412,7 +412,7 @@ As described [in the Symfony documentation](https://symfony.com/doc/current/temp