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

🚧 V2: Rewrite for PHP 8.1 Enum #124

Open
14 of 24 tasks
ogizanagi opened this issue Feb 18, 2021 · 6 comments
Open
14 of 24 tasks

🚧 V2: Rewrite for PHP 8.1 Enum #124

ogizanagi opened this issue Feb 18, 2021 · 6 comments
Assignees
Milestone

Comments

@ogizanagi
Copy link
Member

ogizanagi commented Feb 18, 2021

First step was made in #165 to rewrite the lib with the new native enum types & adding some integrations based on it and our specificities (readables, flags, …).

📚 See current V2 documentation here

🚧 More work to come. Help welcome to integrate what could be useful, from 1.x features or whole new ones.

Will probable create a 2.0.0-alpha1 tag in the next weeks.


V2 Features

Core features

From V1, core features extending the PHP 8.1 native enum capabilities

New features

Whole new features or integration, leveraging new enum capabilities

(Pending) official integrations

From V1, likely to be dropped in the future, or already having an official integration

Extra integrations

From V1, might still be relevant/adapted

Extra tasks

  • Write an UPGRADE-2.x.md guide, with most basic hints for upgrading your application code from 1.x to 2.x
@ogizanagi

This comment has been minimized.

@ogizanagi ogizanagi self-assigned this Jul 20, 2021
@ogizanagi ogizanagi pinned this issue Dec 9, 2021
ogizanagi added a commit that referenced this issue Dec 14, 2021
This PR was squashed before being merged into the 2.x branch.

Discussion
----------

V2: Rewrite with PHP 8.1 enums

WIP POC to observe what could be relevant to keep from this lib and its integrations while moving to PHP 8.1 native enums…

Relates to #124

---

#### random thoughts

- [x] [WeakMap/SplObjStorage](https://wiki.php.net/rfc/enumerations#splobjectstorage_and_weakmaps) for readables?
- [x] For now, no requirements for a FlaggedEnumInterface, no specific methods. But it requires an int backed enum. Drop the interface and replace by backed type reflection checks?

#### notes

- Enum may not include __toString (from PHP)
- Cannot implement FlaggedEnum as before, since we can only define cases for each bit, but cannot hold a $value and have a FlaggedEnum instance with multiple bits. Instead, we might need a FlagBag. Will impact forms, dbal types, js generation, …
- readables for Flagged enum combination might be difficult to write using the same interfaces. Dedicated system for a FlagBag?
- FlagBag controller arg resolver?

Commits
-------

e21a5bf Update CI branches
8019e3d Update cs-fixer
5135227 Remove FlagEnumInterface & add docs
2d1c212 Complete README.md
7e1d3e4 Add Symfony Bundle & configuration for generating BDAL types
e4905fb Basic doctrine dbal types dumper
2117f82 Basic Doctrine types
7db6f59 Clean the deps & CI
69f3a71 Add Symfony Form type with readable enums supports
ae2bcc6 Use enum cases as keys in readables
b7fa48b Base readable implem uses annotations
1633fae V2: Rewrite with PHP 8.1 enums
@ogizanagi ogizanagi changed the title Prepare for PHP 8.1 Enum RFC changes V2: Rewrite for PHP 8.1 Enum Dec 14, 2021
@ogizanagi ogizanagi added this to the 2.x milestone Dec 15, 2021
@jensstalder
Copy link

Tried my hands with porting the ApiPlatform bridge over. Maybe it helps?

<?php

/*
 * This file is part of the "elao/enum" package.
 *
 * Copyright (C) Elao
 *
 * @author Elao <[email protected]>
 */

namespace App\ApiPlatform\Core\JsonSchema\Type;

use ApiPlatform\Core\JsonSchema\Schema;
use ApiPlatform\Core\JsonSchema\TypeFactoryInterface;
use Elao\Enum\ReadableEnumInterface;
use Symfony\Component\PropertyInfo\Type;

final class ElaoEnumType implements TypeFactoryInterface
{
    /** @var TypeFactoryInterface */
    private $decorated;

    public function __construct(TypeFactoryInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    /**
     * {@inheritdoc}
     */
    public function getType(Type $type, string $format = 'json', ?bool $readableLink = null, ?array $serializerContext = null, Schema $schema = null): array
    {
        if (!is_a($enum = $type->getClassName(), ReadableEnumInterface::class, true)) {
            return $this->decorated->getType($type, $format, $readableLink, $serializerContext, $schema);
        }

        $ref = new \ReflectionEnum($type->getClassName());
        $docType = '';
        switch ($ref->getBackingType()) {
            case 'string': $docType = 'string'; break;
            case 'int': $docType = 'integer'; break;
            case null:
            default:
                $docType = 'string';
                break;
        }
        $schema = [];
        $cases = $enum::cases();
        if ($type->isNullable() && !$type->isCollection()) {
            $cases[] = null;
        }
        $readableCases = [];
        foreach ($cases as $case) {
            //$readableCases[$case->value] = $case->getReadable();
            $readableCases[$case->value] = $case->value . '=' . $case->name;
        }
        $enumSchema = [
            'type' => $docType,
            'enum' => $readableCases,
            'example' => $cases[0]->value,
        ];

        if ($type->isCollection()) {
            $schema['type'] = 'array';
            $schema['items'] = $enumSchema;
        } else {
            $schema = $enumSchema;
        }

        if ($type->isNullable()) {
            $schema['nullable'] = true;
        }

        return $schema;
    }
}

@ogizanagi
Copy link
Member Author

ogizanagi commented Dec 18, 2021

Hi @jensstalder . Thank you very much for looking at this.

Could you please explain me a bit more what would be the purpose of such a bridge now with native PHP enum?
I see the $readableCases used as $enumSchema.enum in your sample, but is that correct?
An API would rely on the backed value (as in the previous version of this library), not the readable one. But is there some places where the readable label could be relevant?

You might have more clues than me on what could be relevant to provide in such a bridge regarding the features that are specific to this lib v2 extending native enums capabilities. So, your help is appreciated :)

@ogizanagi ogizanagi changed the title V2: Rewrite for PHP 8.1 Enum 🚧 V2: Rewrite for PHP 8.1 Enum Dec 18, 2021
@jensstalder
Copy link

@ogizanagi Good question. The only benefit I see in relation to JsonSchema is that it shows up in the open API docs. My original goal was to extend the graphql implementation so that the types also get interpreted as enum. I have not found a solution for that yet. But thinking about it, it's true that API platform core should instead simply handle native enums better for both cases (JsonSchema and GraphQL), and it might not be necessary to do this within this package. But this might be a bit to opinionated from the view of the platform? As far as I can tell though, API platform currently only considers the backing type as if it were a simple string or int field? And Graphql endpoint hides the enum typed field completely (but that could be another issue).

@michnovka
Copy link
Contributor

michnovka commented Apr 9, 2022

For Doctrine there is one issue affecting this lib

Please add it on the list

EDIT: merged

@michnovka
Copy link
Contributor

@ogizanagi the doctrine/orm#9629 has been merged in doctrine/orm 2.12.x , so you can remove the known issue from the list

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

No branches or pull requests

3 participants