Code Monkey home page Code Monkey logo

enum's Introduction

Enums

This package holds a simple class that may be used as an ancestor for your enum classes.

Build Status

Installation

composer require greg0ire/enum

Usage

Basic usage

Extend the Greg0ire\Enum\AbstractEnum, define your enum key values as constants, and Bob's your uncle. You can make the class abstract or final, as you see fit.

use Greg0ire\Enum\AbstractEnum;

final class DaysOfWeek extends AbstractEnum {
    const Sunday = 0;
    const Monday = 1;
    const Tuesday = 2;
    const Wednesday = 3;
    const Thursday = 4;
    const Friday = 5;
    const Saturday = 6;
}

Then, you may use the DaysOfWeek class for input validation:

DaysOfWeek::isValidName('Humpday');                  // false
DaysOfWeek::isValidName('Monday');                   // true
DaysOfWeek::isValidName('monday');                   // false
DaysOfWeek::isValidName(0);                          // false

DaysOfWeek::isValidValue(0);                         // true
DaysOfWeek::isValidValue(5);                         // true
DaysOfWeek::isValidValue(7);                         // false
DaysOfWeek::isValidValue('Friday');                  // false

Both methods have an assert* counterpart that will throw a Greg0ire\Enum\Exception\InvalidEnumValue exception:

DaysOfWeek::assertValidName(0);                      // InvalidEnumName
DaysOfWeek::assertValidValue('Friday');              // InvalidEnumValue

Additionally, you may get all the constants in your class as a hash:

DaysOfWeek::getConstants();
DaysOfWeek::getConstants('strtolower'); // Will combine your values with `DaysOfWeek::getKeys($callback)`.
DaysOfWeek::getConstants('strtolower', true); // Values combine with `DaysOfWeek::getClassPrefixedKeys($callback)`.
DaysOfWeek::getConstants('strtolower', true, '.'); // Same with `DaysOfWeek::getClassPrefixedKeys($callback, $separator)`.

You may also get all the keys in your class as an array:

DaysOfWeek::getKeys();
DaysOfWeek::getKeys('strtolower'); // Will call `array_map` with the given callback.

Or the key with the enum class prefix:

DaysOfWeek::getClassPrefixedKeys();
DaysOfWeek::getClassPrefixedKeys('strtolower'); // Will call `array_map` with the given callback.
DaysOfWeek::getClassPrefixedKeys('strtolower', '.'); // Replace the namespace separator ('_' by default).

If you would like to get the keys from a value:

$key = DaysOfWeek::getKeysFromValue(1); // Monday will be assigned to $key

If you have many keys with the same value you will get an array, and a value otherwise.

Advanced usage

If you need to get the constants from a class you cannot modify, or from an interface, or even from several classes / interfaces, you may override AbstractEnum::getEnumTypes().

For example, if you have the following class and interface :

namespace Vendor\Namespace;

class ClassFromAVendor
{
   const SOMETHING      = 'something';
   const SOMETHING_ELSE = 'something_else';
}
namespace My\Namespace;

interface SomeInterface
{
   const ANOTHER_CONST = 'another_const';
}

You can get all three constants by creating this Enum :

use Greg0ire\Enum\AbstractEnum;
use My\Namespace\SomeInterface;
use Vendor\Namespace\ClassFromAVendor;

final class MyEnum extends AbstractEnum
{
    protected static function getEnumTypes()
    {
        return [ClassFromAVendor::class, SomeInterface::class];
    }
}

Alternatively, you can specify a prefix for each type to avoid getting FQCNs in the hash keys.

use Greg0ire\Enum\AbstractEnum;
use My\Namespace\SomeInterface;
use Vendor\Namespace\ClassFromAVendor;

final class MyEnum extends AbstractEnum
{
    protected static function getEnumTypes()
    {
        return [
            'prefix1' => ClassFromAVendor::class,
            'prefix2' => SomeInterface::class,
        ];
    }
}

Get label from a service

If you want to get the constant label behind an enum value, you can instantiate the GetLabel class and invoke it.

use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel;

$label = new GetLabel();
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class);

To enable translation, require the symfony/translation component and pass a Symfony\Contracts\Translation\TranslationInterface instance on the GetLabel constructor

use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel;
use Symfony\Contracts\Translation\TranslationInterface;

$label = new GetLabel($translator);
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class);

If you're using Symfony, alias the service and simply inject it. If translations are enabled, the TranslatorInterface will be automatically injected.

services:
    # ...
    Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel: "@greg0ire_enum.symfony.translator.get_label"
public function index(GetLabel $label)
{
    $label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
    $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, 'another_domain'); // Change the translation domain
    $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false); // Disable translation. In this case the class prefix wont be added
    $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true); // Disable translation but keep class prefix
    $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true, '.'); // Disable translation but keep class prefix with a custom separator
}

Integration with other libraries

greg0ire/enum integrates with other libraries. The list is available in the suggest section of the Composer dependency manifest.

Symfony validator

This package provides a "ready to use" symfony validator. You have to require the symfony/validator package to get it working.

use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum;
use Symfony\Component\Validator\Validation;
use Your\Namespace\EnumClass;

$validator = Validation::createValidator();

$violations = $validator->validateValue(42, new Enum(EnumClass::class));
// You can also show the constants keys on the error message:
$violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'showKeys' => true]));
// Enum constraint inherits from Choice constraint. You can use inherited options too:
$violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'strict' => true]));

Another example with annotations:

use Doctrine\Common\Annotations\AnnotationRegistry;
use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum as EnumAssert;
use Symfony\Component\Validator\Validation;

class MyClass
{
    /**
     * @EnumAssert("Your\Namespace\EnumClass")
     */
    private $dummy;

    public function __construct($dummy)
    {
        $this->dummy = $dummy
    }
}

AnnotationRegistry::registerLoader('class_exists');
$validator = Validation::createValidatorBuilder()
    ->enableAnnotationMapping()
    ->getValidator();

$object = new MyClass(42);

$violations = $validator->validate($object);

Note: You will have to get doctrine/annotations and doctrine/cache packages to get it working.

Symfony form

This package provides a "ready to use" symfony form type. You have to require the symfony/form package to get it working.

use Greg0ire\Enum\Bridge\Symfony\Form\Type\EnumType;
use Symfony\Component\Form\Forms;
use Your\Namespace\EnumClass;

$formFactory = Forms::createFormFactory();

$view = $this->factory->create(EnumType::class, null, array(
    'class' => EnumClass::class,
))->createView();

Twig extension

This package comes with an EnumExtension Twig class. It contains a filter and some functions. You have to require the twig/twig package to get it working.

Filter

The enum_label filter will try to return the constant label corresponding to the given value.

This filter relies on the Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel service.

It will try to translate it if possible. To enable translation, require the symfony/translation component and pass a Symfony\Contracts\Translation\TranslationInterface instance on the GetLabel constructor. GetLabel instance will be injected on the EnumExtension constructor.

If translation is not available, you will have the default label with class prefixing.

Usage:

{{ value|enum_label('Your\\Enum\\Class') }}
{{ value|enum_label('Your\\Enum\\Class', 'another_domain') }} {# Change the translation domain #}
{{ value|enum_label('Your\\Enum\\Class', false) }} {# Disable translation. In this case the class prefix wont be added #}
{{ value|enum_label('Your\\Enum\\Class', false, true) }} {# Disable translation but keep class prefix #}
{{ value|enum_label('Your\\Enum\\Class', false, true, '.') }} {# Disable translation but keep class prefix with a custom separator #}
Functions

The 3 available twig functions are ports of some AbstractEnum methods that can be useful in a twig template:

  • enum_get_constants => AbstractEnum::getConstants
  • enum_get_keys => AbstractEnum::getKeys
  • enum_get_class_prefixed_keys => AbstractEnum::getClassPrefixedKeys

The arguments are exactly the same except you have to specify the targeted class first (as enum_label filter).

Here is a concrete example with enum_get_constants function:

{% for enum_key, enum_value in enum_get_constants('Your\\Enum\\Class') %}
    {{ enum_key }} -> {{ enum_value }}
{% endfor %}
Twig extension as a service

On Symfony projects, the extension can be autoloaded. First, you have to require the symfony/framework-bundle and symfony/twig-bundle packages, or use Symfony fullstack.

Then, register the bundle in the kernel of your application:

// app/AppKernel.php

public function registerBundles()
{
    $bundles = [
        // ...
        new Greg0ire\Enum\Bridge\Symfony\Bundle\Greg0ireEnumBundle(),
    ];

    // ...

    return $bundles
}

That's all. You can now directly use the filter.

Contributing

see CONTRIBUTING.md

Credits

This is a shameless rip-off of this Stack Overflow answer, with one modification: the getConstants method has been made public so that it is available for building choice widgets, for instance. If you want to give credit to someone for this, give it to Brian Cline

enum's People

Contributors

binotaliu avatar cyb3rd4d avatar greg0ire avatar laurent-bientz avatar roukmoute avatar soullivaneuh avatar stylecibot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

enum's Issues

Symfony configuration for default behavior

Add the possibility to have a bundle configuration for some options:

  • Default translation_domain for twig and forms
  • Default prefix_label_with_class for form types

Currently, we have to define the option on the code. This is redundant when you use this library multiple times.

Get key from value

Is it possible to add a new method to return the key according to a value ?

conflict with symfony version 3.2.x-dev

Hi ,
I think that there is a problem of compatibility with the new version of symfony -> version 3.2.x-dev and the enum -> v3.1.0 version

  Problem 1
    - Installation request for symfony/symfony 3.2.x-dev -> satisfiable by symfony/symfony[3.2.x-dev].
    - greg0ire/enum v3.1.0 conflicts with symfony/symfony[3.2.x-dev].
    - Installation request for greg0ire/enum ^3.1 -> satisfiable by greg0ire/enum[v3.1.0].

Use ::class

Internal note.

Since we will drop old PHP versions support on unstable branch, we can use ::class syntax.

To be done when all stable branch PR will be merged and backported to unstable.

Relocate Twig label() method in a service?

Hello @greg0ire

Why not relocate the code of Twig label() method (enum_label filter) in a service and simply inject the service in your Twig Extension?

It could be useful if we want to display the "human" value (stored in the translations) in other services/controllers that are not using Twig rendering (e.g. flash messages).

What do you think?

Thanks for this great bundle!
Cheers

Bump doctrine/inflector?

Hey @greg0ire,

I got this deprecation notice with a fresh install:

User Deprecated: The "Doctrine\Common\Inflector\Inflector::tableize" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.

According to composer.json, Inflector targets "^1.0", could we upgrade to "^1.4 || ^2.0"?

Thanks in advance!

Use short array

Internal note.

Since we will drop old PHP versions support on unstable branch, we can use short array syntax.

To be done when all stable branch PR will be merged and backported to unstable.

Add keyword self for EnumAssert

What do you think about a new keyword self for annotation EnumAssert?

It permits to guess automatically correct namespace when you have in the same class constants and assertion.

Here it is an example:

class MyClass extends AbstractEnum
{
    const MY_CONST = 42;
    const MY_OTHER_CONST = 'whatever';

    /**
     * @EnumAssert(self)
     */
    private $dummy;

    public function __construct($dummy)
    {
        $this->dummy = $dummy
    }
}

translator.default detection issue

The fix for #91 wasn't great, because sometimes, this service will not be available at loading time. Proposed solution:

  1. Introduce a new use_translator configuration entry, defaulting to false
  2. Prepend a configuration that enables it the translation is enabled in the configuration under framework
  3. Make sure the configuration in 1. has priority over it.

Dependency injection fail when the translator is disabled

On a classic symfony project with the following configuration:

framework:
  translator:
    enabled: false

You will get the following error:

(1/1) ServiceNotFoundExceptionThe
service "greg0ire_enum.twig.extension.enum" has a dependency on a non-existent service "translator.default".

This part must be changed:

if (class_exists(Translator::class)) {
$container->getDefinition('greg0ire_enum.twig.extension.enum')
->addArgument(new Reference('translator.default'));
}

Checking if the translator class is not reliable, we have to check if the definition exists and/or is enabled.

Enum mapping aware service

It would be great to have a service that knows which field of which class uses which enum. This could be used by a twig extension that would then retrieve the right label for a value stored in such a field, and translate it (optionally, if translation is enabled), using the class name to build the catalog name by default.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.