Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: BackedEnum resources #6309

Merged
merged 7 commits into from
Jun 18, 2024
Merged

Conversation

GwendolenLynch
Copy link
Contributor

@GwendolenLynch GwendolenLynch commented Apr 13, 2024

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
}

Copy link
Member

@soyuka soyuka left a comment

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 :)

src/State/Provider/BackedEnumProvider.php Outdated Show resolved Hide resolved
src/State/Provider/BackedEnumProvider.php Outdated Show resolved Hide resolved
tests/Functional/BackedEnumPlainResourceTest.php Outdated Show resolved Hide resolved
@GwendolenLynch GwendolenLynch force-pushed the feat/enum-resources branch 7 times, most recently from 8c96867 to 8acce05 Compare April 14, 2024 12:55
@dunglas
Copy link
Member

dunglas commented Apr 15, 2024

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

@GwendolenLynch
Copy link
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

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
Copy link
Contributor Author

GwendolenLynch commented Apr 18, 2024

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
Copy link
Member

soyuka commented May 30, 2024

@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
Copy link
Member

soyuka commented Jun 17, 2024

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

<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
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
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
75 of 77 checks passed
@soyuka
Copy link
Member

soyuka commented Jun 18, 2024

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) {

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants