core icon indicating copy to clipboard operation
core copied to clipboard

feat(symfony): add `getOperation` Expression Language function on Mercure topics

Open vincentchalamon opened this issue 2 years ago • 1 comments

Q A
Branch? 3.3
Tickets N/A
License MIT
Doc PR TODO

Description

When using Mercure on a resource, it's possible to specify multiple topics using Symfony Expression Language:

#[ApiResource(
    mercure: [
        'topics' => [
            '@=iri(object)',
            '@=iri(object.getOwner()) ~ "/?topic=" ~ escape(iri(object))',
            '@=iri(object, '.UrlGeneratorInterface::ABS_PATH.')', // you can also change the reference type
            'https://example.com/books/1',
        ],
    ],
)]

(source: https://api-platform.com/docs/core/mercure/#dispatching-restrictive-updates-security-mode)

But the iri Expression Language function does not allow to send the second argument of IriConverter::getIriFromResource ($operation), which will just retrieve the first Get operation detected on the resource. While using multiple operations, it should be possible to specify which operation to use to generate the IRI.

Proposition

Considering the following resource with multiple operations:

#[ApiResource(
    operations: [
        new Get(uriTemplate: '/foos/{id}{._format}'),
        new Get(uriTemplate: '/foos/bars/{id}{._format}'),
        new Post(uriTemplate: '/foos{._format}'),
    ]
)]

On POST /foos request, I want to send a Mercure Update to both Get operations identified by their uriTemplate.

Introducing getOperation Expression Language function (currently only) available on Mercure topics feature:

#[ApiResource(
    // ...
    mercure: [
        'topics' => [
            '@=iri(object)',
            '@=iri(object, '.UrlGeneratorInterface::ABS_URL.', getOperation(object, "/foos/bars/{id}{._format}"))'
        ],
    ]
)]

Note: the object variable is required as getOperation first argument to retrieve the resource class. It's also possible to refer to a class name directly (e.g.: using DTO):

'@=iri(object, '.UrlGeneratorInterface::ABS_URL.', getOperation('.OutputDto::class.', "/a/custom/dtos/{id}{._format}"))'

vincentchalamon avatar Sep 28 '23 12:09 vincentchalamon

@soyuka is it ok to merge this one too?

vincentchalamon avatar Feb 02 '24 14:02 vincentchalamon