Skip to content

Commit

Permalink
Merge branch '4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas committed Sep 19, 2024
2 parents e11fdfe + e6b2569 commit a05b89a
Show file tree
Hide file tree
Showing 58 changed files with 1,959 additions and 138 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the website
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: api-platform/website
ref: main
Expand All @@ -20,7 +20,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> "$GITHUB_OUTPUT"

- uses: actions/cache@v3
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
Expand All @@ -32,7 +32,7 @@ jobs:
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.119.0'
hugo-version: '0.134.2'
extended: true

- name: Install php
Expand Down
15 changes: 12 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,34 @@ on:
push:
pull_request:

permissions: {}

jobs:
build:
name: Lint
runs-on: ubuntu-latest

permissions:
contents: read
packages: read
statuses: write

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Lint
uses: github/super-linter/slim@v4
env:
VALIDATE_ALL_CODEBASE: false
VALIDATE_EDITORCONFIG: false
VALIDATE_JSCPD: false
DEFAULT_BRANCH: main
DEFAULT_BRANCH: "4.0"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
Expand Down
4 changes: 2 additions & 2 deletions core/bootstrap.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Bootstraping the core library

You may want to run a minimal version of API Platform. This one file runs API Platform (without GraphQL, Doctrine and MongoDB).
It requires the following composer packages:
You may want to run a minimal version of API Platform. This one file runs API Platform (without GraphQL, Eloquent, Doctrine MongoDB...).
It requires the following Composer packages:

```console
composer require \
Expand Down
3 changes: 3 additions & 0 deletions core/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ api_platform:
# Enable the data collector and the WebProfilerBundle integration.
enable_profiler: true

# Keep doctrine/inflector instead of symfony/string to generate plurals for routes.
keep_legacy_inflector: true

collection:
# The name of the query parameter to filter nullable results (with the ExistsFilter).
exists_parameter_name: 'exists'
Expand Down
4 changes: 2 additions & 2 deletions core/content-negotiation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

The API system has built-in [content negotiation](https://en.wikipedia.org/wiki/Content_negotiation) capabilities.

By default, only the [JSON-LD](https://json-ld.org) and JSON formats are enabled. However API Platform supports many more formats and can be extended.
By default, only the [JSON-LD](https://json-ld.org) format is enabled. However API Platform supports many more formats and can be extended.

The framework natively supports JSON-LD (and Hydra), GraphQL, JSON:API, HAL, YAML, CSV, HTML (API docs), raw JSON and raw XML.
Using the raw JSON or raw XML formats is discouraged, prefer using JSON-LD instead, which provides more feature and is as easy to use.

API Platform also supports [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) the JSON:API [`PATCH`](https://tools.ietf.org/html/rfc5789) formats, as well as [Problem Details (RFC 7807)](https://tools.ietf.org/html/rfc7807), Hydra and JSON:API error formats.
API Platform also supports [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) the JSON:API [`PATCH`](https://jsonapi.org/format/#crud-updating) formats, as well as [Problem Details (RFC 7807)](https://tools.ietf.org/html/rfc7807), [Hydra](https://www.hydra-cg.com/spec/latest/core/#description-of-http-status-codes-and-errors) and [JSON:API](https://jsonapi.org/format/#errors) error formats.

<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/formats?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Formats screencast"><br>Watch the Formats screencast</a></p>

Expand Down
2 changes: 1 addition & 1 deletion core/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ properties:

## Setting the `Sunset` HTTP Header to Indicate When a Resource or an Operation Will Be Removed

[The `Sunset` HTTP response header](https://tools.ietf.org/html/draft-wilde-sunset-header) indicates that a URI is likely to become unresponsive at a specified point in the future.
[The `Sunset` HTTP response header (RFC 8594)](https://www.rfc-editor.org/rfc/rfc8594) indicates that a URI is likely to become unresponsive at a specified point in the future.
It is especially useful to indicate when a deprecated URL will not be available anymore.

Thanks to the `sunset` attribute, API Platform makes it easy to set this header for all URLs related to a resource class:
Expand Down
2 changes: 1 addition & 1 deletion core/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ api_platform:
# The 4 following handlers are registered by default, keep those lines to prevent unexpected side effects
Symfony\Component\Serializer\Exception\ExceptionInterface: 400 # Use a raw status code (recommended)
ApiPlatform\Exception\InvalidArgumentException: !php/const Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST
ApiPlatform\Exception\FilterValidationException: 400
ApiPlatform\ParameterValidator\Exception\ValidationExceptionInterface: 400
Doctrine\ORM\OptimisticLockException: 409
# Validation exception
Expand Down
2 changes: 2 additions & 0 deletions core/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ final readonly class CurrentUserExtension implements QueryCollectionExtensionInt

```

Note that the default `rootAlias` is "o" in the bundled `ItemProvider` and `CollectionProvider`, so you should use different aliases for your custom joins in your extension.

Finally, if you're not using the autoconfiguration, you have to register the custom extension with either of those tags:

```yaml
Expand Down
68 changes: 22 additions & 46 deletions core/file-upload.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ before proceeding. It will help you get a grasp on how the bundle works, and why
**Note**: Uploading files won't work in `PUT` or `PATCH` requests, you must use `POST` method to upload files.
See [the related issue on Symfony](https://github.com/symfony/symfony/issues/9226) and [the related bug in PHP](https://bugs.php.net/bug.php?id=55815) talking about this behavior.

Enable the multipart format globally in order to use it as the input format of your resource:

```yaml
api_platform:
formats:
multipart: ['multipart/form-data']
jsonld: ['application/ld+json']
```
## Installing VichUploaderBundle
Install the bundle with the help of Composer:
Expand Down Expand Up @@ -44,9 +53,6 @@ In this example, we will create a `MediaObject` API resource. We will post files
to this resource endpoint, and then link the newly created resource to another
resource (in our case: `Book`).

This example will use a custom controller to receive the file.
The second example will use a custom `multipart/form-data` decoder to deserialize the resource instead.

### Configuring the Resource Receiving the Uploaded File

The `MediaObject` resource is implemented like this:
Expand All @@ -63,7 +69,7 @@ use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\Model;
use App\Controller\CreateMediaObjectAction;
use App\State\SaveMediaObject;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Serializer\Annotation\Groups;
Expand All @@ -75,13 +81,12 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[ApiResource(
normalizationContext: ['groups' => ['media_object:read']],
types: ['https://schema.org/MediaObject'],
outputFormats: ['jsonld' => ['application/ld+json']],
operations: [
new Get(),
new GetCollection(),
new Post(
controller: CreateMediaObjectAction::class,
deserialize: false,
validationContext: ['groups' => ['Default', 'media_object_create']],
inputFormats: ['multipart' => ['multipart/form-data']],
openapi: new Model\Operation(
requestBody: new Model\RequestBody(
content: new \ArrayObject([
Expand All @@ -107,14 +112,15 @@ class MediaObject
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private ?int $id = null;
#[ApiProperty(types: ['https://schema.org/contentUrl'])]
#[ApiProperty(types: ['https://schema.org/contentUrl'], writable: false)]
#[Groups(['media_object:read'])]
public ?string $contentUrl = null;
#[Vich\UploadableField(mapping: 'media_object', fileNameProperty: 'filePath')]
#[Assert\NotNull(groups: ['media_object_create'])]
#[Assert\NotNull]
public ?File $file = null;
#[ApiProperty(writable: false)]
#[ORM\Column(nullable: true)]
public ?string $filePath = null;
Expand All @@ -124,41 +130,7 @@ class MediaObject
}
}
```

### Creating the Controller

At this point, the entity is configured, but we still need to write the action
that handles the file upload.

```php
<?php
// api/src/Controller/CreateMediaObjectAction.php
namespace App\Controller;
use App\Entity\MediaObject;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
#[AsController]
final class CreateMediaObjectAction extends AbstractController
{
public function __invoke(Request $request): MediaObject
{
$uploadedFile = $request->files->get('file');
if (!$uploadedFile) {
throw new BadRequestHttpException('"file" is required');
}
$mediaObject = new MediaObject();
$mediaObject->file = $uploadedFile;
return $mediaObject;
}
}
```
Note: From V3.3 onwards, `'multipart/form-data'` must either be including in the global API-Platform config, either in `formats` or `defaults->inputFormats`, or defined as an `inputFormats` parameter on an operation by operation basis.

### Resolving the File URL

Expand All @@ -169,6 +141,7 @@ A [normalizer](serialization.md#normalization) could be used to set the `content

```php
<?php
// api/src/Serializer/MediaObjectNormalizer.php
namespace App\Serializer;
Expand All @@ -183,7 +156,7 @@ class MediaObjectNormalizer implements NormalizerInterface
private const ALREADY_CALLED = 'MEDIA_OBJECT_NORMALIZER_ALREADY_CALLED';
public function __construct(
#[Autowire(service: 'serializer.normalizer.object')]
#[Autowire(service: 'api_platform.jsonld.normalizer.item')]
private readonly NormalizerInterface $normalizer,
private readonly StorageInterface $storage
) {
Expand Down Expand Up @@ -383,7 +356,10 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich;
types: ['https://schema.org/Book'],
operations: [
new GetCollection(),
new Post(inputFormats: ['multipart' => ['multipart/form-data']])
new Post(
outputFormats: ['jsonld' => ['application/ld+json']],
inputFormats: ['multipart' => ['multipart/form-data']]
)
]
)]
class Book
Expand Down
Loading

0 comments on commit a05b89a

Please sign in to comment.