Skip to content

feat: BackedEnum resources#6309

Merged
soyuka merged 7 commits into
api-platform:3.4from
GwendolenLynch:feat/enum-resources
Jun 18, 2024
Merged

feat: BackedEnum resources#6309
soyuka merged 7 commits into
api-platform:3.4from
GwendolenLynch:feat/enum-resources

Conversation

@GwendolenLynch

@GwendolenLynch GwendolenLynch commented Apr 13, 2024

Copy link
Copy Markdown
Contributor
Q A
Branch? main
Tickets Closes #6298, closes #6317
License MIT
Doc PR api-platform/docs#...

Intended for 3.4, so now it is just for review.

Depends on #6288 as I want to refactor BackedEnumPlainResourceTest test methods into those classes.

  • Add a provider for BackedEnums
  • Identifier is value by default, and implementing function getId(), etc, works too
  • Resource operations will default to only Get & GetCollection unless otherwise configured
#[ApiResource]
enum Status: int
{
    case DRAFT = 0;
    case PUBLISHED = 1;
}

GET /statuses

[
  {
    "name": "DRAFT",
    "value": 0
  },
  {
    "name": "PUBLISHED",
    "value": 1
  }
]

GET /statuses/1

{
  "name": "PUBLISHED",
  "value": 1
}

@soyuka soyuka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would love to see json-ld supported, I need to add my commit to this at some point :)

Comment thread src/State/Provider/BackedEnumProvider.php Outdated
Comment thread src/State/Provider/BackedEnumProvider.php Outdated
Comment thread tests/Functional/BackedEnumPlainResourceTest.php Outdated
@GwendolenLynch GwendolenLynch force-pushed the feat/enum-resources branch 7 times, most recently from 8c96867 to 8acce05 Compare April 14, 2024 12:55
Comment thread src/Metadata/Resource/Factory/LinkFactory.php
@dunglas

dunglas commented Apr 15, 2024

Copy link
Copy Markdown
Member

I would use URIs in GraphQL too, as we do for existing IDs and relations. WDYT?

@GwendolenLynch

Copy link
Copy Markdown
Contributor Author

@dunglas it must be my week for getting confused. 🌞

I'm very happy to make required changes, but could you be so kind as to give a bit more context, please?

@gnito-org

Copy link
Copy Markdown

Please look at how I configure a backed enum as an API resource so that each instance has an IRI just like any other API resource.

https://github.com/gnito-org/problem-replicator-api-platform-enum-example

This is important for machine discovery of APIs and for consistency.

@GwendolenLynch

GwendolenLynch commented Apr 18, 2024

Copy link
Copy Markdown
Contributor Author

Thank you @gnito-org, I can reproduce it here.

@GwendolenLynch GwendolenLynch force-pushed the feat/enum-resources branch 5 times, most recently from 37672db to b088d10 Compare April 24, 2024 07:16
@GwendolenLynch GwendolenLynch force-pushed the feat/enum-resources branch 3 times, most recently from e227f3c to a069f68 Compare May 2, 2024 12:01
@soyuka

soyuka commented May 30, 2024

Copy link
Copy Markdown
Member

@GwendolenLynch I merged #6288 could you rebase I this should fix some of the failing tests right?

@soyuka soyuka changed the base branch from main to 3.4 June 17, 2024 14:58
@soyuka soyuka force-pushed the feat/enum-resources branch from a069f68 to a232425 Compare June 17, 2024 15:01
@soyuka

soyuka commented Jun 17, 2024

Copy link
Copy Markdown
Member

I'll continue working on this tomorrow, hopefully merging it!

@soyuka soyuka force-pushed the feat/enum-resources branch from 84612ab to cc755bf Compare June 18, 2024 08:37
@soyuka soyuka force-pushed the feat/enum-resources branch from cc755bf to f5e7ad2 Compare June 18, 2024 09:03
<service id="api_platform.state_provider.backed_enum" class="ApiPlatform\State\Provider\BackedEnumProvider">
<tag name="api_platform.state_provider" key="ApiPlatform\State\Provider\BackedEnumProvidevr" />
<tag name="api_platform.state_provider" key="api_platform.state_provider.backed_enum" />
</service>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record @GwendolenLynch instead of decorating the provider chain, I choose to declare this as an operation provider instead. This will be called inside the ReadProvider:

try {
$data = $this->provider->provide($operation, $uriVariables, $context);
} catch (ProviderNotFoundException $e) {
$data = null;
}

It's easier for userland to decorate our enum provider (or any item provider) instead of hooking into the main decoration chain.

use ApiPlatform\Metadata\Operation;
use Symfony\Component\Serializer\Attribute\Groups;

trait BackedEnumStringTrait

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For further readers, this was duplicated from the BackedEnumTrait as graphql "guesses" the type from an union:

// guess union/intersect types: check each type until finding a valid one
foreach ($propertyTypes as $propertyType) {
if ($fieldConfiguration = $this->getResourceFieldConfiguration($property, $propertyMetadata->getDescription(), $propertyMetadata->getDeprecationReason(), $propertyType, $resourceClass, $input, $operation, $depth, null !== $propertyMetadata->getSecurity())) {
$fields['id' === $property ? '_id' : $this->normalizePropertyName($property, $resourceClass)] = $fieldConfiguration;
// stop at the first valid type
break;
}
}

I'm not a huge fan, ideally we should provide a fix at some point there, even though when representing resources one should avoid scalar union types in my opinion.

@soyuka soyuka merged commit 63ccfd5 into api-platform:3.4 Jun 18, 2024
@soyuka

soyuka commented Jun 18, 2024

Copy link
Copy Markdown
Member

Thanks @GwendolenLynch!

soyuka added a commit to DartCZ/core that referenced this pull request Jun 27, 2024
* fix(metadata): Only add GET operations for enums when ApiResource doesn't specify operations

* feat(state): backed enum provider

* fix(metadata): enum resource identifier default to value

* fix(metadata): get method metadata for BackedEnums

* test: resource with enum properties schema

* what I would like

* test: backed enums

---------

Co-authored-by: soyuka <soyuka@users.noreply.github.com>
soyuka added a commit to soyuka/core that referenced this pull request Jul 7, 2024
* fix(metadata): Only add GET operations for enums when ApiResource doesn't specify operations

* feat(state): backed enum provider

* fix(metadata): enum resource identifier default to value

* fix(metadata): get method metadata for BackedEnums

* test: resource with enum properties schema

* what I would like

* test: backed enums

---------

Co-authored-by: soyuka <soyuka@users.noreply.github.com>
}

$newGraphQlOperations = [];
foreach ($resourceMetadata->getGraphQlOperations() as $operationName => $operation) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work if there are no GraphQlOperations

@papppeter

papppeter commented Nov 18, 2024

Copy link
Copy Markdown

Hi, @soyuka could you please send me a link to the docs please?
we would like to use this feature, but could not find the proper documentation.

(we tried to use it, but no provider registered message is comming up)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Example documentation is ignored for Enum resources [3.4] Improving handling of BackedEnums with ApiResource class attributes

6 participants