diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..95457d6
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,39 @@
+name: Continuous Integration
+
+on:
+ pull_request:
+ push:
+ branches:
+ - "master"
+
+jobs:
+ tests:
+ name: "Tests"
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ include:
+ - php-version: 7.1
+ symfony-version: 4.4.*
+ - php-version: 7.4
+ symfony-version: 4.4.*
+ - php-version: 7.2
+ symfony-version: 5.1.*
+ - php-version: 7.4
+ symfony-version: 5.1.*
+
+ steps:
+ - name: "Checkout"
+ uses: actions/checkout@v2.0.0
+
+ - name: "Install dependencies with composer"
+ run: |
+ composer require --no-update --dev symfony/symfony:${{ matrix.symfony-version }}
+ composer update --no-interaction --no-progress --no-suggest
+
+ - name: "Run checkstyle with squizlabs/php_codesniffer"
+ run: vendor/bin/phpcs
+
+ - name: "Run tests with phpunit/phpunit"
+ run: vendor/bin/phpunit --coverage-text
diff --git a/.gitignore b/.gitignore
index 6b44be9..09a9d69 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
-/phpunit.xml
-composer.lock
+/.idea/
/vendor/
-/build/
-.idea/
-docker-compose.yml
+/.phpcs-cache
+/composer.lock
+/docker-compose.yml
+/phpunit.xml
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
deleted file mode 100644
index 39dd4c9..0000000
--- a/.scrutinizer.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-filter:
- excluded_paths: [vendor/*, Tests/*]
-
-before_commands:
- - 'composer install --dev --prefer-source'
-
-tools:
- external_code_coverage: true
- php_mess_detector: true
- php_code_sniffer: true
- sensiolabs_security_checker: true
- php_code_coverage: true
- php_pdepend: true
- php_loc:
- enabled: true
- excluded_dirs: [vendor, Tests]
- php_cpd:
- enabled: true
- excluded_dirs: [vendor, Tests]
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index be44bc1..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-language: php
-
-php:
- - 5.6
- - 7.0
- - 7.1
- - 7.2
-
-env:
- - SYMFONY_VERSION="2.7.*"
- - SYMFONY_VERSION="2.8.*"
- - SYMFONY_VERSION="3.4.*"
- - SYMFONY_VERSION="4.0.*"
-
-matrix:
- exclude:
- - php: 5.6
- env: SYMFONY_VERSION="4.0.*" # Symfony >= 4.0 PHP requirement is ^7.1.3
- - php: 7.0
- env: SYMFONY_VERSION="4.0.*" # Symfony >= 4.0 PHP requirement is ^7.1.3
-
-sudo: false
-
-cache:
- directories:
- - $HOME/.composer/cache
-
-before_install:
- - composer selfupdate
- - if [ "$SYMFONY_VERSION" != "" ]; then composer require "symfony/symfony:${SYMFONY_VERSION}" --no-update; fi;
-
-install: composer update --prefer-dist --no-interaction $COMPOSER_FLAGS
-
-script:
- - vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover=coverage.clover
-
-after_script:
- - wget https://scrutinizer-ci.com/ocular.phar
- - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
-
-notifications:
- email: eugone.yann@gmail.com
diff --git a/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPass.php b/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPass.php
deleted file mode 100644
index ca6df01..0000000
--- a/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPass.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- *
- * @deprecated
- */
-class ConventionedEnumCollectorCompilerPass implements CompilerPassInterface
-{
- /**
- * @inheritdoc
- */
- public function process(ContainerBuilder $container)
- {
- $bundles = $container->getParameter('enum.register_bundles');
-
- if (!$bundles) {
- return;
- }
-
- @trigger_error(
- '"' . __CLASS__ . '" is deprecated since v2.2. Please use Symfony\'s PSR4 Service discovery instead.',
- E_USER_DEPRECATED
- );
-
- if (true === $bundles) {
- $bundles = $container->getParameter('kernel.bundles');
- } else {
- $bundles = (array) $bundles;
- }
-
- foreach ($bundles as $bundleClass) {
- $declarativePass = new DeclarativeEnumCollectorCompilerPass($bundleClass);
- $declarativePass->process($container);
- }
- }
-}
diff --git a/DependencyInjection/CompilerPass/DeclarativeEnumCollectorCompilerPass.php b/DependencyInjection/CompilerPass/DeclarativeEnumCollectorCompilerPass.php
deleted file mode 100644
index 56f4a07..0000000
--- a/DependencyInjection/CompilerPass/DeclarativeEnumCollectorCompilerPass.php
+++ /dev/null
@@ -1,211 +0,0 @@
-
- *
- * @deprecated
- */
-class DeclarativeEnumCollectorCompilerPass implements CompilerPassInterface
-{
- /**
- * @var string
- */
- private $bundleDir;
-
- /**
- * @var string
- */
- private $bundleNamespace;
-
- /**
- * @var string
- */
- private $bundleName;
-
- /**
- * @var string
- */
- private $transDomain;
-
- /**
- * @param string $bundle
- * @param string|null $transDomain
- */
- public function __construct($bundle, $transDomain = null)
- {
- $reflection = new ReflectionClass($bundle);
- $this->bundleDir = dirname($reflection->getFileName());
- $this->bundleNamespace = $reflection->getNamespaceName();
- $this->bundleName = $reflection->getShortName();
-
- $this->transDomain = $transDomain;
- }
-
- /**
- * @inheritdoc
- */
- public function process(ContainerBuilder $container)
- {
- @trigger_error(
- '"' . __CLASS__ . '" is deprecated since v2.2. Please use Symfony\'s PSR4 Service discovery instead.',
- E_USER_DEPRECATED
- );
-
- if (!class_exists('Symfony\Component\Finder\Finder')) {
- throw new RuntimeException('You need the symfony/finder component to register enums.');
- }
-
- $enumDir = $this->bundleDir . '/Enum';
-
- if (!is_dir($enumDir)) {
- return;
- }
-
- $finder = new Finder();
- $finder->files()->name('*Enum.php')->in($enumDir);
-
- foreach ($finder as $file) {
- /** @var SplFileInfo $file */
- $enumNamespace = $this->bundleNamespace . '\\Enum';
- if ($relativePath = $file->getRelativePath()) {
- $enumNamespace .= '\\' . strtr($relativePath, '/', '\\');
- }
-
- $enumClass = $enumNamespace . '\\' . $file->getBasename('.php');
- $enumReflection = new ReflectionClass($enumClass);
-
- if (!$enumReflection->isSubclassOf(EnumInterface::class) || $enumReflection->isAbstract()) {
- continue; //Not an enum or abstract enum
- }
-
- $definition = null;
- $requiredParameters = 0;
- if ($enumReflection->getConstructor()) {
- $requiredParameters = $enumReflection->getConstructor()->getNumberOfRequiredParameters();
- }
-
- if ($requiredParameters === 0) {
- $definition = new Definition($enumClass);
- } elseif ($requiredParameters === 2 && $enumReflection->isSubclassOf(AbstractTranslatedEnum::class)) {
- if (class_exists('Symfony\Component\DependencyInjection\ChildDefinition')) {
- // ChildDefinition was introduced as Symfony 3.3
- $definition = new ChildDefinition('enum.abstract_translated');
- } else {
- // DefinitionDecorator was deprecated as Symfony 3.3
- $definition = new DefinitionDecorator('enum.abstract_translated');
- }
- $definition->setClass($enumClass);
- $definition->addArgument(
- $this->getTransPattern($enumClass)
- );
-
- if ($this->transDomain) {
- $definition->addMethodCall(
- 'setTransDomain',
- [
- $this->transDomain
- ]
- );
- }
- }
-
- if (!$definition) {
- continue; //Could not determine how to create definition for the enum
- }
-
- $definition->addTag('enum');
-
- $container->setDefinition(
- $this->getServiceId($enumClass),
- $definition
- );
- }
- }
-
- /**
- * @param string $enumClass
- *
- * @return string
- */
- private function getServiceId($enumClass)
- {
- $enumNamespace = $this->bundleNamespace.'\\Enum\\';
-
- return sprintf('%s.enum.%s',
- Container::underscore(
- substr($this->bundleName, 0, -6)
- ),
- Container::underscore(
- str_replace(
- '\\',
- '',
- str_replace(
- $enumNamespace,
- '',
- substr($enumClass, 0, -4)
- )
- )
- )
- );
- }
-
- /**
- * @param string $enumClass
- *
- * @return string
- */
- private function getTransPattern($enumClass)
- {
- $parts = array_filter(
- array_map(
- [$this, 'underscore'],
- explode(
- '\\',
- str_replace(
- $this->bundleNamespace . '\\',
- '',
- $enumClass
- )
- )
- )
- );
-
- $enum = array_pop($parts);
-
- return implode('_', $parts) . '.' . $enum . '.label_%s';
- }
-
- /**
- * @param string $input
- *
- * @return string
- */
- private function underscore($input)
- {
- return strtolower(
- preg_replace(
- '~(?<=\\w)([A-Z])~', '_$1',
- preg_replace(
- '~(Enum|Bundle)~',
- '',
- $input
- )
- )
- );
- }
-}
diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
deleted file mode 100644
index 6ceb101..0000000
--- a/DependencyInjection/Configuration.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
- */
-class Configuration implements ConfigurationInterface
-{
- /**
- * @inheritdoc
- */
- public function getConfigTreeBuilder()
- {
- $treeBuilder = new TreeBuilder();
- $rootNode = $treeBuilder->root('yokai_enum');
-
- $rootNode
- ->children()
- ->variableNode('register_bundles')
- ->info('[DEPRECATED] bundles for which to auto-register enums.')
- ->defaultFalse()
- ->end()
- ->booleanNode('enum_autoconfiguration')
- ->info('If set to true, all services that implements EnumInterface, will obtain the "enum" tag automatically.')
- ->defaultTrue()
- ->end()
- ->booleanNode('enum_registry_autoconfigurable')
- ->info('If set to true, add an alias for the enum registry so your service can ask for it via autoconfiguration.')
- ->defaultTrue()
- ->end()
- ->end()
- ;
-
- return $treeBuilder;
- }
-}
diff --git a/DependencyInjection/EnumExtension.php b/DependencyInjection/EnumExtension.php
deleted file mode 100644
index 889aa39..0000000
--- a/DependencyInjection/EnumExtension.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- */
-class EnumExtension extends Extension
-{
- /**
- * @inheritdoc
- */
- public function load(array $configs, ContainerBuilder $container)
- {
- $configuration = new Configuration();
- $config = $this->processConfiguration($configuration, $configs);
-
- $container->setParameter('enum.register_bundles', $config['register_bundles']);
-
- $xmlLoader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
- $xmlLoader->load('services.xml');
- $xmlLoader->load('forms.xml');
- $xmlLoader->load('validators.xml');
- $xmlLoader->load('twig.xml');
-
- if ($config['enum_autoconfiguration'] && method_exists($container, 'registerForAutoconfiguration')) {
- $container->registerForAutoconfiguration(EnumInterface::class)
- ->addTag('enum');
- }
-
- if ($config['enum_registry_autoconfigurable']) {
- $container->setAlias(EnumRegistryInterface::class, 'enum.registry');
- }
- }
-}
diff --git a/README.md b/README.md
index d11ed37..746cb77 100644
--- a/README.md
+++ b/README.md
@@ -11,13 +11,16 @@ YokaiEnumBundle
[](https://scrutinizer-ci.com/g/yokai-php/enum-bundle/?branch=master)
[](https://insight.sensiolabs.com/projects/596d2076-90ee-49d9-a8b2-e3bcbd390874)
-This repository aims to provide simple enumeration implementation to Symfony :
+This library aims to provide simple enumeration implementation for PHP projects.
+
+First created as a Symfony bundle only, the doc is focused on integration with it.
+But if you love this library, feel free to propose a bridge for you framework.
Installation
------------
-### Add the bundle as dependency with Composer
+### Add the library as a dependency with Composer
``` bash
$ composer require yokai/enum-bundle
@@ -48,17 +51,17 @@ We first need to create the classes that will handle our enums :
```php
'Male', 'f' => 'Female'];
}
@@ -74,9 +77,10 @@ Adding validation to your model :
```php
= 2.8
use Yokai\EnumBundle\Form\Type\EnumType;
class MemberType extends AbstractType
@@ -111,11 +114,8 @@ class MemberType extends AbstractType
// Let the bundle guess the form type for you (requires that you configured the validation)
->add('gender')
- // Manual form type binding for Symfony >= 2.8
+ // Manual form type binding
->add('gender', EnumType::class, ['enum' => GenderEnum::class])
-
- // Manual form type binding for Symfony 2.7
- ->add('gender', 'enum', ['enum' => GenderEnum::class])
;
}
}
@@ -131,8 +131,8 @@ Displaying the label for an enum value within a template :
Recipes
-------
-- Usage in [SonataAdminBundle](https://github.com/sonata-project/SonataAdminBundle) : see [doc](Resources/doc/sonata-admin.md)
-- All the ways to declare [enums](Resources/doc/declaring-enum.md) or [translated enums](Resources/doc/declaring-translated-enum.md)
+- Usage in [SonataAdminBundle](https://github.com/sonata-project/SonataAdminBundle) : see [doc](doc/sonata-admin.md)
+- All the ways to declare [enums](doc/declaring-enum.md) or [translated enums](doc/declaring-translated-enum.md)
MIT License
diff --git a/Registry/EnumRegistryInterface.php b/Registry/EnumRegistryInterface.php
deleted file mode 100644
index 270621f..0000000
--- a/Registry/EnumRegistryInterface.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
- */
-interface EnumRegistryInterface
-{
- /**
- * @param EnumInterface $enum
- *
- * @throws DuplicatedEnumException
- */
- public function add(EnumInterface $enum);
-
- /**
- * @param string $name
- *
- * @return EnumInterface
- * @throws InvalidEnumException
- */
- public function get($name);
-
- /**
- * @param string $name
- *
- * @return bool
- */
- public function has($name);
-
- /**
- * @return EnumInterface[]
- */
- public function all();
-}
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
deleted file mode 100644
index 76f17cc..0000000
--- a/Resources/config/services.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Tests/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPassTest.php b/Tests/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPassTest.php
deleted file mode 100644
index 901566c..0000000
--- a/Tests/DependencyInjection/CompilerPass/ConventionedEnumCollectorCompilerPassTest.php
+++ /dev/null
@@ -1,89 +0,0 @@
-
- */
-class ConventionedEnumCollectorCompilerPassTest extends \PHPUnit_Framework_TestCase
-{
- /**
- * @dataProvider getBundles
- */
- public function testCollectThroughBundles($bundle, $prefix)
- {
- $container = $this->prophesize('Symfony\Component\DependencyInjection\ContainerBuilder');
-
- $namespace = (new \ReflectionClass($bundle))->getNamespaceName();
-
- $container->getParameter('enum.register_bundles')
- ->shouldBeCalled()
- ->willReturn([$bundle]);
-
- $container
- ->setDefinition(
- $prefix.'.enum.dummy',
- Argument::allOf(
- Argument::type('Symfony\Component\DependencyInjection\Definition'),
- Argument::which('getTags', ['enum' => [[]]]),
- Argument::which('getClass', $namespace.'\Enum\DummyEnum')
- )
- )
- ->shouldBeCalled();
- $container
- ->setDefinition(
- $prefix.'.enum.customer_gender',
- Argument::allOf(
- Argument::type('Symfony\Component\DependencyInjection\Definition'),
- Argument::which('getTags', ['enum' => [[]]]),
- Argument::which('getClass', $namespace.'\Enum\Customer\GenderEnum')
- )
- )
- ->shouldBeCalled();
- $class = 'Symfony\Component\DependencyInjection\DefinitionDecorator';
- if (class_exists('Symfony\Component\DependencyInjection\ChildDefinition')) {
- $class = 'Symfony\Component\DependencyInjection\ChildDefinition';
- }
- $container
- ->setDefinition(
- $prefix.'.enum.customer_state',
- Argument::allOf(
- Argument::type($class),
- Argument::which('getTags', ['enum' => [[]]]),
- Argument::which('getClass', $namespace.'\Enum\Customer\StateEnum'),
- Argument::which(
- 'getArguments',
- [
- 'customer.state.label_%s'
- ]
- ),
- Argument::which('getParent', 'enum.abstract_translated')
- )
- )
- ->shouldBeCalled();
-
- $compiler = new ConventionedEnumCollectorCompilerPass();
- $compiler->process($container->reveal());
- }
-
- public function getBundles()
- {
- return [
- ['AppBundle\AppBundle', 'app'],
- ['Acme\AppBundle\AcmeAppBundle', 'acme_app'],
- ['Acme\Bundle\AppBundle\AcmeAppBundle', 'acme_app'],
- ];
- }
-}
diff --git a/Tests/DependencyInjection/EnumExtensionTest.php b/Tests/DependencyInjection/EnumExtensionTest.php
deleted file mode 100644
index 2e14b23..0000000
--- a/Tests/DependencyInjection/EnumExtensionTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-
- */
-class EnumExtensionTest extends \PHPUnit_Framework_TestCase
-{
- /**
- * @return EnumExtension
- */
- public function extension()
- {
- return new EnumExtension();
- }
-
- /**
- * @test
- */
- public function it_register_enum_for_autoconfiguration_by_default()
- {
- $container = new ContainerBuilder();
- $this->extension()->load([[]], $container);
-
- if (method_exists($container, 'getAutoconfiguredInstanceof')) {
- $autoconfigure = $container->getAutoconfiguredInstanceof();
- $this->assertArrayHasKey(EnumInterface::class, $autoconfigure);
- $this->assertEquals(['enum' => [[]]], $autoconfigure[EnumInterface::class]->getTags());
- } else {
- $this->assertTrue(true); // not in this version
- }
- }
-
- /**
- * @test
- */
- public function it_do_not_register_enum_for_autoconfiguration_if_asked_to()
- {
- $container = new ContainerBuilder();
- $this->extension()->load([['enum_autoconfiguration' => false]], $container);
-
- if (method_exists($container, 'getAutoconfiguredInstanceof')) {
- $autoconfigure = $container->getAutoconfiguredInstanceof();
- $this->assertArrayNotHasKey(EnumInterface::class, $autoconfigure);
- } else {
- $this->assertTrue(true); // not in this version
- }
- }
-
- /**
- * @test
- */
- public function it_register_enum_registry_alias_for_autowire_by_default()
- {
- $container = new ContainerBuilder();
- $this->extension()->load([[]], $container);
- $this->assertTrue($container->hasAlias(EnumRegistryInterface::class));
- }
-
- /**
- * @test
- */
- public function it_do_not_register_enum_registry_alias_for_autowire_if_asked_to()
- {
- $container = new ContainerBuilder();
- $this->extension()->load([['enum_registry_autoconfigurable' => false]], $container);
- $this->assertFalse($container->hasAlias(EnumRegistryInterface::class));
- }
-}
diff --git a/Tests/Enum/ConfigurableEnumTest.php b/Tests/Enum/ConfigurableEnumTest.php
deleted file mode 100644
index a5ab0db..0000000
--- a/Tests/Enum/ConfigurableEnumTest.php
+++ /dev/null
@@ -1,15 +0,0 @@
- 'FOO', 'bar' => 'BAR']);
- $this->assertSame('foo', $fooEnum->getName());
- $this->assertSame(['foo' => 'FOO', 'bar' => 'BAR'], $fooEnum->getChoices());
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/AppBundle/AcmeAppBundle.php b/Tests/Fixtures/Bundles/Acme/AppBundle/AcmeAppBundle.php
deleted file mode 100644
index 8a2a29f..0000000
--- a/Tests/Fixtures/Bundles/Acme/AppBundle/AcmeAppBundle.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
- */
-class AcmeAppBundle extends Bundle
-{
-}
diff --git a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/GenderEnum.php b/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/GenderEnum.php
deleted file mode 100644
index 052e963..0000000
--- a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/GenderEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class GenderEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['male' => 'Male', 'female' => 'Female'];
- }
-
- public function getName()
- {
- return 'gender';
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/StateEnum.php b/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/StateEnum.php
deleted file mode 100644
index 87f313f..0000000
--- a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/Customer/StateEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class StateEnum extends AbstractTranslatedEnum
-{
- protected function getValues()
- {
- return ['new', 'validated', 'disabled'];
- }
-
- public function getName()
- {
- return 'state';
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/DummyEnum.php b/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/DummyEnum.php
deleted file mode 100644
index fded8fb..0000000
--- a/Tests/Fixtures/Bundles/Acme/AppBundle/Enum/DummyEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class DummyEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['foo' => 'Foo', 'bar' => 'Bar'];
- }
-
- public function getName()
- {
- return 'dummy';
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/AcmeAppBundle.php b/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/AcmeAppBundle.php
deleted file mode 100644
index f6c6259..0000000
--- a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/AcmeAppBundle.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
- */
-class AcmeAppBundle extends Bundle
-{
-}
diff --git a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/GenderEnum.php b/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/GenderEnum.php
deleted file mode 100644
index 073110d..0000000
--- a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/GenderEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class GenderEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['male' => 'Male', 'female' => 'Female'];
- }
-
- public function getName()
- {
- return 'gender';
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/StateEnum.php b/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/StateEnum.php
deleted file mode 100644
index cd2f134..0000000
--- a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/Customer/StateEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class StateEnum extends AbstractTranslatedEnum
-{
- protected function getValues()
- {
- return ['new', 'validated', 'disabled'];
- }
-
- public function getName()
- {
- return 'state';
- }
-}
diff --git a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/DummyEnum.php b/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/DummyEnum.php
deleted file mode 100644
index c1ef2e4..0000000
--- a/Tests/Fixtures/Bundles/Acme/Bundle/AppBundle/Enum/DummyEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class DummyEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['foo' => 'Foo', 'bar' => 'Bar'];
- }
-
- public function getName()
- {
- return 'dummy';
- }
-}
diff --git a/Tests/Fixtures/Bundles/AppBundle/AppBundle.php b/Tests/Fixtures/Bundles/AppBundle/AppBundle.php
deleted file mode 100644
index c38ab20..0000000
--- a/Tests/Fixtures/Bundles/AppBundle/AppBundle.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
- */
-class AppBundle extends Bundle
-{
-}
diff --git a/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/GenderEnum.php b/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/GenderEnum.php
deleted file mode 100644
index 5d8eef2..0000000
--- a/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/GenderEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class GenderEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['male' => 'Male', 'female' => 'Female'];
- }
-
- public function getName()
- {
- return 'gender';
- }
-}
diff --git a/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/StateEnum.php b/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/StateEnum.php
deleted file mode 100644
index 8c3c519..0000000
--- a/Tests/Fixtures/Bundles/AppBundle/Enum/Customer/StateEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class StateEnum extends AbstractTranslatedEnum
-{
- protected function getValues()
- {
- return ['new', 'validated', 'disabled'];
- }
-
- public function getName()
- {
- return 'state';
- }
-}
diff --git a/Tests/Fixtures/Bundles/AppBundle/Enum/DummyEnum.php b/Tests/Fixtures/Bundles/AppBundle/Enum/DummyEnum.php
deleted file mode 100644
index 24fafc0..0000000
--- a/Tests/Fixtures/Bundles/AppBundle/Enum/DummyEnum.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- */
-class DummyEnum implements EnumInterface
-{
- public function getChoices()
- {
- return ['foo' => 'Foo', 'bar' => 'Bar'];
- }
-
- public function getName()
- {
- return 'dummy';
- }
-}
diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php
deleted file mode 100644
index 8bf2add..0000000
--- a/Tests/bootstrap.php
+++ /dev/null
@@ -1,19 +0,0 @@
-= 4.0 support
-if (class_exists('Symfony\Component\Validator\Test\ConstraintValidatorTestCase')) {
- class_alias(
- 'Symfony\Component\Validator\Test\ConstraintValidatorTestCase',
- 'Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest'
- );
-}
diff --git a/Twig/Extension/EnumExtension.php b/Twig/Extension/EnumExtension.php
deleted file mode 100644
index 60d8972..0000000
--- a/Twig/Extension/EnumExtension.php
+++ /dev/null
@@ -1,83 +0,0 @@
-
- */
-class EnumExtension extends Twig_Extension
-{
- /**
- * @var EnumRegistryInterface
- */
- private $registry;
-
- /**
- * @param EnumRegistryInterface $registry
- */
- public function __construct(EnumRegistryInterface $registry)
- {
- $this->registry = $registry;
- }
-
- /**
- * @inheritdoc
- */
- public function getFunctions()
- {
- return [
- new Twig_SimpleFunction('enum_label', [$this, 'getLabel']),
- new Twig_SimpleFunction('enum_choices', [$this, 'getChoices']),
- ];
- }
-
- /**
- * @inheritdoc
- */
- public function getFilters()
- {
- return [
- new Twig_SimpleFilter('enum_label', [$this, 'getLabel']),
- ];
- }
-
- /**
- * @param string $value
- * @param string $enum
- *
- * @return string
- */
- public function getLabel($value, $enum)
- {
- $choices = $this->getChoices($enum);
-
- if (isset($choices[$value])) {
- return $choices[$value];
- }
-
- return $value;
- }
-
- /**
- * @param string $enum
- *
- * @return array
- */
- public function getChoices($enum)
- {
- return $this->registry->get($enum)->getChoices();
- }
-
- /**
- * @inheritdoc
- */
- public function getName()
- {
- return 'enum';
- }
-}
diff --git a/composer.json b/composer.json
index 7bdcbe7..b89a2f7 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "yokai/enum-bundle",
- "description": "Bring simple enumeration implementation to Symfony",
+ "description": "Simple enumeration system with Symfony integration",
"type": "symfony-bundle",
"license": "MIT",
"authors": [
@@ -10,23 +10,36 @@
}
],
"require": {
- "php": ">=5.6",
- "symfony/framework-bundle": "~2.7|~3.0|~4.0",
- "symfony/form": "~2.7|~3.0|~4.0",
- "symfony/validator": "~2.7|~3.0|~4.0",
- "twig/twig": "~1.20|~2.0"
+ "php": "^7.1.3",
+ "symfony/framework-bundle": "^4.4|^5.0"
},
"require-dev": {
- "doctrine/annotations": "~1.3",
- "phpunit/phpunit": "~5.0"
+ "doctrine/annotations": "^1.3",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.0",
+ "squizlabs/php_codesniffer": "^3.5",
+ "symfony/form": "^4.4|^5.0",
+ "symfony/framework-bundle": "^4.4|^5.0",
+ "symfony/twig-bundle": "^4.4|^5.0",
+ "symfony/validator": "^4.4|^5.0",
+ "twig/twig": "^2.0|^3.0"
+ },
+ "suggest": {
+ "symfony/framework-bundle": "Integrate with Symfony Framework",
+ "symfony/form": "Add enum form type",
+ "symfony/validator": "Add enum validation",
+ "twig/twig": "Add enum util functions"
},
"autoload": {
- "psr-4": { "Yokai\\EnumBundle\\": "" }
+ "psr-4": { "Yokai\\EnumBundle\\": "src" }
+ },
+ "autoload-dev": {
+ "psr-4": { "Yokai\\EnumBundle\\Tests\\": "tests" }
},
"minimum-stability": "stable",
"extra": {
"branch-alias": {
- "dev-master": "2.x-dev"
+ "dev-master": "3.x-dev"
}
}
}
diff --git a/Resources/doc/declaring-enum.md b/doc/declaring-enum.md
similarity index 66%
rename from Resources/doc/declaring-enum.md
rename to doc/declaring-enum.md
index 14e7fe8..d1bd3f4 100644
--- a/Resources/doc/declaring-enum.md
+++ b/doc/declaring-enum.md
@@ -19,16 +19,16 @@ Create a new class, implement both `getName` & `getChoices` methods.
namespace App\Enum;
-use Yokai\EnumBundle\Enum\EnumInterface;
+use Yokai\EnumBundle\EnumInterface;
class GenderEnum implements EnumInterface
{
- public function getName()
+ public function getName(): string
{
return 'gender';
}
- public function getChoices()
+ public function getChoices(): array
{
return ['m' => 'Male', 'f' => 'Female'];
}
@@ -56,14 +56,14 @@ Create a new class, use `EnumWithClassAsNameTrait` trait and implement `getChoic
namespace App\Enum;
-use Yokai\EnumBundle\Enum\EnumInterface;
-use Yokai\EnumBundle\Enum\EnumWithClassAsNameTrait;
+use Yokai\EnumBundle\EnumInterface;
+use Yokai\EnumBundle\EnumWithClassAsNameTrait;
class GenderEnum implements EnumInterface
{
use EnumWithClassAsNameTrait;
- public function getChoices()
+ public function getChoices(): array
{
return ['m' => 'Male', 'f' => 'Female'];
}
@@ -89,7 +89,7 @@ No need for a class, just use the `ConfigurableEnum` class and define a new enum
```yaml
services:
enum.member.gender:
- class: 'Yokai\EnumBundle\Enum\ConfigurableEnum'
+ class: 'Yokai\EnumBundle\ConfigurableEnum'
public: false
tags: ['enum']
arguments:
@@ -97,3 +97,22 @@ services:
- m: 'Male'
f: 'Female'
```
+
+
+The configurable way extracting constant list
+--------------------
+
+Let say that you already have a list of constant that for the gender.
+No need for a class, just use the `ConstantListEnum` class and define a new enum service.
+
+```yaml
+services:
+ enum.member.gender:
+ class: 'Yokai\EnumBundle\ConstantListEnum'
+ public: false
+ tags: ['enum']
+ arguments:
+ - '@enum.constant_extractor'
+ - 'App\\Model\\Person::GENDER_*'
+ - "gender"
+```
diff --git a/Resources/doc/declaring-translated-enum.md b/doc/declaring-translated-enum.md
similarity index 65%
rename from Resources/doc/declaring-translated-enum.md
rename to doc/declaring-translated-enum.md
index 700ff70..8b5cab7 100644
--- a/Resources/doc/declaring-translated-enum.md
+++ b/doc/declaring-translated-enum.md
@@ -6,7 +6,7 @@ If you wish to use Symfony's Translator for your enum labels, this bundle provid
There is a lot of way to create and declare such classes.
> **Note :** It is pretty much like [declaring classic enums](declaring-enum.md),
-> but with a `extends` instead of an `implements`.
+> but with a dependency to `symfony/translator`.
The classic way
@@ -19,8 +19,8 @@ Create a new class, implement both `getName` & `getValues` methods and specify t
namespace App\Enum;
-use Symfony\Component\Translation\TranslatorInterface;
-use Yokai\EnumBundle\Enum\AbstractTranslatedEnum;
+use Symfony\Contracts\Translation\TranslatorInterface;
+use Yokai\EnumBundle\AbstractTranslatedEnum;
class GenderEnum extends AbstractTranslatedEnum
{
@@ -29,12 +29,12 @@ class GenderEnum extends AbstractTranslatedEnum
parent::__construct($translator, 'enum.gender.%s');
}
- public function getName()
+ public function getName(): string
{
return 'gender';
}
- public function getValues()
+ public function getValues(): array
{
return ['m', 'f'];
}
@@ -64,9 +64,9 @@ Create a new class, use `EnumWithClassAsNameTrait` trait, implement `getValues`
namespace App\Enum;
-use Symfony\Component\Translation\TranslatorInterface;
-use Yokai\EnumBundle\Enum\AbstractTranslatedEnum;
-use Yokai\EnumBundle\Enum\EnumWithClassAsNameTrait;
+use Symfony\Contracts\Translation\TranslatorInterface;
+use Yokai\EnumBundle\AbstractTranslatedEnum;
+use Yokai\EnumBundle\EnumWithClassAsNameTrait;
class GenderEnum extends AbstractTranslatedEnum
{
@@ -77,7 +77,7 @@ class GenderEnum extends AbstractTranslatedEnum
parent::__construct($translator, 'enum.gender.%s');
}
- public function getValues()
+ public function getValues(): array
{
return ['m', 'f'];
}
@@ -105,7 +105,7 @@ No need for a class, just use the `ConfigurableTranslatedEnum` class and define
```yaml
services:
enum.member.gender:
- class: 'Yokai\EnumBundle\Enum\ConfigurableTranslatedEnum'
+ class: 'Yokai\EnumBundle\ConfigurableTranslatedEnum'
public: false
tags: ['enum']
arguments:
@@ -114,3 +114,23 @@ services:
- "gender"
- ['m', 'f']
```
+
+The configurable way extracting constant list
+--------------------
+
+Let say that you already have a list of constant that for the gender.
+No need for a class, just use the `ConstantListTranslatedEnum` class and define a new enum service.
+
+```yaml
+services:
+ enum.member.gender:
+ class: 'Yokai\EnumBundle\ConstantListTranslatedEnum'
+ public: false
+ tags: ['enum']
+ arguments:
+ - '@yokai_enum.constant_extractor'
+ - 'App\\Model\\Person::GENDER_*'
+ - "@translator"
+ - "enum.gender.%s"
+ - "gender"
+```
diff --git a/Resources/doc/sonata-admin.md b/doc/sonata-admin.md
similarity index 89%
rename from Resources/doc/sonata-admin.md
rename to doc/sonata-admin.md
index e07e106..9f259d1 100644
--- a/Resources/doc/sonata-admin.md
+++ b/doc/sonata-admin.md
@@ -20,7 +20,7 @@ use Yokai\EnumBundle\Form\Type\EnumType;
class MemberAdmin extends AbstractAdmin
{
- protected function configureListFields(ListMapper $list)
+ protected function configureListFields(ListMapper $list): void
{
$list
->add('gender', null, [
@@ -30,7 +30,7 @@ class MemberAdmin extends AbstractAdmin
;
}
- protected function configureDatagridFilters(DatagridMapper $filter)
+ protected function configureDatagridFilters(DatagridMapper $filter): void
{
$filter
->add('gender', 'doctrine_orm_choice', [
@@ -43,7 +43,7 @@ class MemberAdmin extends AbstractAdmin
;
}
- protected function configureFormFields(FormMapper $form)
+ protected function configureFormFields(FormMapper $form): void
{
$form
// Let the bundle guess the form type for you (requires that you configured the validation)
@@ -52,7 +52,7 @@ class MemberAdmin extends AbstractAdmin
;
}
- protected function configureShowFields(ShowMapper $form)
+ protected function configureShowFields(ShowMapper $form): void
{
$form
->add('gender', null, [
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..3d26c56
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+ src/
+
+
+
+
+
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 74ed0e5..dd1c914 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -7,24 +7,19 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
- syntaxCheck="false"
colors="true"
- bootstrap="Tests/bootstrap.php"
+ bootstrap="vendor/autoload.php"
>
- ./Tests
+ ./tests
- ./
-
- ./Tests
- ./vendor
-
+ ./src
diff --git a/Enum/AbstractTranslatedEnum.php b/src/AbstractTranslatedEnum.php
similarity index 80%
rename from Enum/AbstractTranslatedEnum.php
rename to src/AbstractTranslatedEnum.php
index 4d629e8..7e9a0f3 100644
--- a/Enum/AbstractTranslatedEnum.php
+++ b/src/AbstractTranslatedEnum.php
@@ -1,8 +1,10 @@
getValues(),
array_map(
- function ($value) {
+ function (string $value): string {
return $this->translator->trans(
sprintf($this->transPattern, $value),
[],
@@ -62,7 +64,7 @@ function ($value) {
/**
* @param string $transDomain
*/
- public function setTransDomain($transDomain)
+ public function setTransDomain(string $transDomain): void
{
$this->transDomain = $transDomain;
}
@@ -70,5 +72,5 @@ public function setTransDomain($transDomain)
/**
* @return array
*/
- abstract protected function getValues();
+ abstract protected function getValues(): array;
}
diff --git a/Enum/ConfigurableEnum.php b/src/ConfigurableEnum.php
similarity index 73%
rename from Enum/ConfigurableEnum.php
rename to src/ConfigurableEnum.php
index 1683071..73aee05 100644
--- a/Enum/ConfigurableEnum.php
+++ b/src/ConfigurableEnum.php
@@ -1,6 +1,8 @@
@@ -21,7 +23,7 @@ class ConfigurableEnum implements EnumInterface
* @param string $name
* @param array $choices
*/
- public function __construct($name, array $choices)
+ public function __construct(string $name, array $choices)
{
$this->name = $name;
$this->choices = $choices;
@@ -30,7 +32,7 @@ public function __construct($name, array $choices)
/**
* @inheritdoc
*/
- public function getName()
+ public function getName(): string
{
return $this->name;
}
@@ -38,7 +40,7 @@ public function getName()
/**
* @inheritdoc
*/
- public function getChoices()
+ public function getChoices(): array
{
return $this->choices;
}
diff --git a/Enum/ConfigurableTranslatedEnum.php b/src/ConfigurableTranslatedEnum.php
similarity index 76%
rename from Enum/ConfigurableTranslatedEnum.php
rename to src/ConfigurableTranslatedEnum.php
index 1b3b752..6056987 100644
--- a/Enum/ConfigurableTranslatedEnum.php
+++ b/src/ConfigurableTranslatedEnum.php
@@ -1,8 +1,10 @@
@@ -25,7 +27,7 @@ class ConfigurableTranslatedEnum extends AbstractTranslatedEnum
* @param string $name
* @param array $values
*/
- public function __construct(TranslatorInterface $translator, $transPattern, $name, array $values)
+ public function __construct(TranslatorInterface $translator, string $transPattern, string $name, array $values)
{
parent::__construct($translator, $transPattern);
@@ -36,7 +38,7 @@ public function __construct(TranslatorInterface $translator, $transPattern, $nam
/**
* @inheritdoc
*/
- public function getName()
+ public function getName(): string
{
return $this->name;
}
@@ -44,7 +46,7 @@ public function getName()
/**
* @inheritdoc
*/
- public function getValues()
+ protected function getValues(): array
{
return $this->values;
}
diff --git a/src/ConstantExtractor.php b/src/ConstantExtractor.php
new file mode 100644
index 0000000..cda8924
--- /dev/null
+++ b/src/ConstantExtractor.php
@@ -0,0 +1,83 @@
+
+ */
+class ConstantExtractor
+{
+ public function extract(string $pattern): array
+ {
+ [$class, $patternRegex] = $this->explode($pattern);
+
+ return $this->filter(
+ $this->publicConstants($class),
+ $patternRegex,
+ $pattern
+ );
+ }
+
+ private function filter(array $constants, string $regexp, string $pattern): array
+ {
+ $matchingNames = preg_grep($regexp, array_keys($constants));
+
+ if (count($matchingNames) === 0) {
+ throw CannotExtractConstantsException::noConstantMatchingPattern($pattern);
+ }
+
+ return array_values(array_intersect_key($constants, array_flip($matchingNames)));
+ }
+
+ private function publicConstants(string $class): array
+ {
+ try {
+ $constants = (new ReflectionClass($class))->getReflectionConstants();
+ } catch (ReflectionException $exception) {
+ throw CannotExtractConstantsException::classDoNotExists($class);
+ }
+
+ $list = [];
+ foreach ($constants as $constant) {
+ if (!$constant->isPublic()) {
+ continue;
+ }
+
+ $list[$constant->getName()] = $constant->getValue();
+ }
+
+ if (count($list) === 0) {
+ throw CannotExtractConstantsException::classHasNoPublicConstant($class);
+ }
+
+ return $list;
+ }
+
+ private function explode(string $pattern): array
+ {
+ if (substr_count($pattern, '::') !== 1) {
+ throw CannotExtractConstantsException::invalidPattern($pattern);
+ }
+
+ [$class, $constantsNamePattern] = explode('::', $pattern);
+
+ if (substr_count($constantsNamePattern, '*') === 0) {
+ throw CannotExtractConstantsException::invalidPattern($pattern);
+ }
+
+ $constantsNameRegexp = sprintf(
+ '#^%s$#',
+ str_replace('*', '[0-9a-zA-Z_]+', $constantsNamePattern)
+ );
+
+ return [$class, $constantsNameRegexp];
+ }
+}
diff --git a/src/ConstantListEnum.php b/src/ConstantListEnum.php
new file mode 100644
index 0000000..f676d92
--- /dev/null
+++ b/src/ConstantListEnum.php
@@ -0,0 +1,20 @@
+
+ */
+class ConstantListEnum extends ConfigurableEnum
+{
+ /**
+ * @inheritDoc
+ */
+ public function __construct(ConstantExtractor $extractor, string $constantsPattern, string $name)
+ {
+ $values = $extractor->extract($constantsPattern);
+ parent::__construct($name, array_combine($values, $values));
+ }
+}
diff --git a/src/ConstantListTranslatedEnum.php b/src/ConstantListTranslatedEnum.php
new file mode 100644
index 0000000..aec3509
--- /dev/null
+++ b/src/ConstantListTranslatedEnum.php
@@ -0,0 +1,26 @@
+
+ */
+class ConstantListTranslatedEnum extends ConfigurableTranslatedEnum
+{
+ /**
+ * @inheritDoc
+ */
+ public function __construct(
+ ConstantExtractor $extractor,
+ string $constantsPattern,
+ TranslatorInterface $translator,
+ string $transPattern,
+ string $name
+ ) {
+ parent::__construct($translator, $transPattern, $name, $extractor->extract($constantsPattern));
+ }
+}
diff --git a/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php b/src/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php
similarity index 89%
rename from DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php
rename to src/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php
index 63863c7..11e6ce8 100644
--- a/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php
+++ b/src/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPass.php
@@ -1,5 +1,7 @@
hasDefinition('enum.registry')) {
return;
diff --git a/src/DependencyInjection/EnumExtension.php b/src/DependencyInjection/EnumExtension.php
new file mode 100644
index 0000000..081d7d6
--- /dev/null
+++ b/src/DependencyInjection/EnumExtension.php
@@ -0,0 +1,49 @@
+
+ */
+class EnumExtension extends Extension
+{
+ /**
+ * @inheritdoc
+ */
+ public function load(array $configs, ContainerBuilder $container): void
+ {
+ $xmlLoader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
+ $xmlLoader->load('enum.xml');
+
+ $requiresForm = interface_exists(FormInterface::class);
+ $requiresValidator = interface_exists(ValidatorInterface::class);
+ $requiresTwig = class_exists(TwigBundle::class);
+
+ if ($requiresForm) {
+ $xmlLoader->load('form.xml');
+ if (!$requiresValidator) {
+ $container->removeDefinition('form_extention.type_guesser.enum');
+ }
+ }
+ if ($requiresValidator) {
+ $xmlLoader->load('validator.xml');
+ }
+ if ($requiresTwig) {
+ $xmlLoader->load('twig.xml');
+ }
+
+ $container->registerForAutoconfiguration(EnumInterface::class)
+ ->addTag('enum');
+ }
+}
diff --git a/Enum/EnumInterface.php b/src/EnumInterface.php
similarity index 55%
rename from Enum/EnumInterface.php
rename to src/EnumInterface.php
index 01e212e..3bb2b56 100644
--- a/Enum/EnumInterface.php
+++ b/src/EnumInterface.php
@@ -1,6 +1,8 @@
@@ -10,10 +12,10 @@ interface EnumInterface
/**
* @return array
*/
- public function getChoices();
+ public function getChoices(): array;
/**
* @return string
*/
- public function getName();
+ public function getName(): string;
}
diff --git a/Registry/EnumRegistry.php b/src/EnumRegistry.php
similarity index 59%
rename from Registry/EnumRegistry.php
rename to src/EnumRegistry.php
index a80afb2..762b224 100644
--- a/Registry/EnumRegistry.php
+++ b/src/EnumRegistry.php
@@ -1,15 +1,16 @@
*/
-class EnumRegistry implements EnumRegistryInterface
+class EnumRegistry
{
/**
* @var EnumInterface[]
@@ -17,9 +18,11 @@ class EnumRegistry implements EnumRegistryInterface
private $enums;
/**
- * @inheritdoc
+ * @param EnumInterface $enum
+ *
+ * @throws DuplicatedEnumException
*/
- public function add(EnumInterface $enum)
+ public function add(EnumInterface $enum): void
{
if ($this->has($enum->getName())) {
throw DuplicatedEnumException::alreadyRegistered($enum->getName());
@@ -29,9 +32,12 @@ public function add(EnumInterface $enum)
}
/**
- * @inheritdoc
+ * @param string $name
+ *
+ * @return EnumInterface
+ * @throws InvalidEnumException
*/
- public function get($name)
+ public function get(string $name): EnumInterface
{
if (!$this->has($name)) {
throw InvalidEnumException::nonexistent($name);
@@ -41,17 +47,19 @@ public function get($name)
}
/**
- * @inheritdoc
+ * @param string $name
+ *
+ * @return bool
*/
- public function has($name)
+ public function has(string $name): bool
{
return isset($this->enums[$name]);
}
/**
- * @inheritDoc
+ * @return EnumInterface[]
*/
- public function all()
+ public function all(): array
{
return $this->enums;
}
diff --git a/Enum/EnumWithClassAsNameTrait.php b/src/EnumWithClassAsNameTrait.php
similarity index 66%
rename from Enum/EnumWithClassAsNameTrait.php
rename to src/EnumWithClassAsNameTrait.php
index 2e8898f..04e3879 100644
--- a/Enum/EnumWithClassAsNameTrait.php
+++ b/src/EnumWithClassAsNameTrait.php
@@ -1,6 +1,8 @@
@@ -10,7 +12,7 @@ trait EnumWithClassAsNameTrait
/**
* @return string
*/
- public function getName()
+ public function getName(): string
{
return static::class;
}
diff --git a/src/Exception/CannotExtractConstantsException.php b/src/Exception/CannotExtractConstantsException.php
new file mode 100644
index 0000000..5b5bc72
--- /dev/null
+++ b/src/Exception/CannotExtractConstantsException.php
@@ -0,0 +1,35 @@
+
+ */
+class CannotExtractConstantsException extends InvalidArgumentException
+{
+ public static function invalidPattern(string $pattern): self
+ {
+ return new self(
+ "Constant extraction pattern must look like Fully\\Qualified\\ClassName::CONSTANT_*. Got $pattern."
+ );
+ }
+
+ public static function classDoNotExists(string $class): self
+ {
+ return new self("Class $class do not exists.");
+ }
+
+ public static function classHasNoPublicConstant(string $class): self
+ {
+ return new self("Class $class has no public constant.");
+ }
+
+ public static function noConstantMatchingPattern(string $pattern): self
+ {
+ return new self("Pattern $pattern matches no constant.");
+ }
+}
diff --git a/Exception/DuplicatedEnumException.php b/src/Exception/DuplicatedEnumException.php
similarity index 80%
rename from Exception/DuplicatedEnumException.php
rename to src/Exception/DuplicatedEnumException.php
index 9a87a83..39eff58 100644
--- a/Exception/DuplicatedEnumException.php
+++ b/src/Exception/DuplicatedEnumException.php
@@ -1,5 +1,7 @@
enumRegistry = $enumRegistry;
-
- if (method_exists(AbstractType::class, 'getBlockPrefix')) {
- $this->enumFormType = EnumType::class; //Symfony 3.x support
- } else {
- $this->enumFormType = 'enum'; //Symfony 2.x support
- }
}
/**
* @inheritdoc
*/
- public function guessTypeForConstraint(Constraint $constraint)
+ public function guessTypeForConstraint(Constraint $constraint): ?TypeGuess
{
if (!$constraint instanceof Enum) {
return null;
}
return new TypeGuess(
- $this->enumFormType,
+ EnumType::class,
[
'enum' => $constraint->enum,
'multiple' => $constraint->multiple,
@@ -66,7 +57,7 @@ public function guessTypeForConstraint(Constraint $constraint)
/**
* @inheritDoc
*/
- public function guessRequired($class, $property)
+ public function guessRequired($class, $property): ?ValueGuess
{
return null; //override parent : not able to guess
}
@@ -74,7 +65,7 @@ public function guessRequired($class, $property)
/**
* @inheritDoc
*/
- public function guessMaxLength($class, $property)
+ public function guessMaxLength($class, $property): ?ValueGuess
{
return null; //override parent : not able to guess
}
@@ -82,7 +73,7 @@ public function guessMaxLength($class, $property)
/**
* @inheritDoc
*/
- public function guessPattern($class, $property)
+ public function guessPattern($class, $property): ?ValueGuess
{
return null; //override parent : not able to guess
}
diff --git a/Form/Type/EnumType.php b/src/Form/Type/EnumType.php
similarity index 59%
rename from Form/Type/EnumType.php
rename to src/Form/Type/EnumType.php
index 4262897..fd9c075 100644
--- a/Form/Type/EnumType.php
+++ b/src/Form/Type/EnumType.php
@@ -1,12 +1,14 @@
@@ -14,14 +16,14 @@
class EnumType extends AbstractType
{
/**
- * @var EnumRegistryInterface
+ * @var EnumRegistry
*/
private $enumRegistry;
/**
- * @param EnumRegistryInterface $enumRegistry
+ * @param EnumRegistry $enumRegistry
*/
- public function __construct(EnumRegistryInterface $enumRegistry)
+ public function __construct(EnumRegistry $enumRegistry)
{
$this->enumRegistry = $enumRegistry;
}
@@ -29,20 +31,19 @@ public function __construct(EnumRegistryInterface $enumRegistry)
/**
* @inheritdoc
*/
- public function configureOptions(OptionsResolver $resolver)
+ public function configureOptions(OptionsResolver $resolver): void
{
$resolver
->setRequired('enum')
- ->setDefault('choices_as_values', true)
->setAllowedValues(
'enum',
- function ($name) {
+ function (string $name): bool {
return $this->enumRegistry->has($name);
}
)
->setDefault(
'choices',
- function (Options $options) {
+ function (Options $options): array {
return array_flip($this->enumRegistry->get($options['enum'])->getChoices());
}
)
@@ -52,28 +53,16 @@ function (Options $options) {
/**
* @inheritdoc
*/
- public function getParent()
+ public function getParent(): string
{
- if (!method_exists(AbstractType::class, 'getBlockPrefix')) {
- return 'choice'; //Symfony 2.x support
- }
-
return ChoiceType::class;
}
/**
* @inheritdoc
*/
- public function getBlockPrefix()
+ public function getBlockPrefix(): string
{
return 'enum';
}
-
- /**
- * @inheritdoc
- */
- public function getName()
- {
- return $this->getBlockPrefix();
- }
}
diff --git a/src/Resources/config/enum.xml b/src/Resources/config/enum.xml
new file mode 100644
index 0000000..2a9775d
--- /dev/null
+++ b/src/Resources/config/enum.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Resources/config/forms.xml b/src/Resources/config/form.xml
similarity index 58%
rename from Resources/config/forms.xml
rename to src/Resources/config/form.xml
index 0c88ac9..78bcd1f 100644
--- a/Resources/config/forms.xml
+++ b/src/Resources/config/form.xml
@@ -5,20 +5,16 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
-
-
-
+
+
-
-
+
-
-
+
-
diff --git a/Resources/config/twig.xml b/src/Resources/config/twig.xml
similarity index 67%
rename from Resources/config/twig.xml
rename to src/Resources/config/twig.xml
index f4e282c..47bd009 100644
--- a/Resources/config/twig.xml
+++ b/src/Resources/config/twig.xml
@@ -5,13 +5,10 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
-
-
-
+
+
-
diff --git a/Resources/config/validators.xml b/src/Resources/config/validator.xml
similarity index 67%
rename from Resources/config/validators.xml
rename to src/Resources/config/validator.xml
index 42f99bf..8c5e36d 100644
--- a/Resources/config/validators.xml
+++ b/src/Resources/config/validator.xml
@@ -5,13 +5,10 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
-
-
-
+
+
-
diff --git a/src/Twig/Extension/EnumExtension.php b/src/Twig/Extension/EnumExtension.php
new file mode 100644
index 0000000..ba7f157
--- /dev/null
+++ b/src/Twig/Extension/EnumExtension.php
@@ -0,0 +1,71 @@
+
+ */
+class EnumExtension extends AbstractExtension
+{
+ /**
+ * @var EnumRegistry
+ */
+ private $registry;
+
+ /**
+ * @param EnumRegistry $registry
+ */
+ public function __construct(EnumRegistry $registry)
+ {
+ $this->registry = $registry;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getFunctions(): array
+ {
+ return [
+ new TwigFunction('enum_label', [$this, 'getLabel']),
+ new TwigFunction('enum_choices', [$this, 'getChoices']),
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getFilters(): array
+ {
+ return [
+ new TwigFilter('enum_label', [$this, 'getLabel']),
+ ];
+ }
+
+ /**
+ * @param string $value
+ * @param string $enum
+ *
+ * @return string
+ */
+ public function getLabel(string $value, string $enum): string
+ {
+ return $this->getChoices($enum)[$value] ?? $value;
+ }
+
+ /**
+ * @param string $enum
+ *
+ * @return array
+ */
+ public function getChoices(string $enum): array
+ {
+ return $this->registry->get($enum)->getChoices();
+ }
+}
diff --git a/Validator/Constraints/Enum.php b/src/Validator/Constraints/Enum.php
similarity index 73%
rename from Validator/Constraints/Enum.php
rename to src/Validator/Constraints/Enum.php
index 4373196..91bfbcc 100644
--- a/Validator/Constraints/Enum.php
+++ b/src/Validator/Constraints/Enum.php
@@ -1,5 +1,7 @@
@@ -14,14 +16,14 @@
class EnumValidator extends ChoiceValidator
{
/**
- * @var EnumRegistryInterface
+ * @var EnumRegistry
*/
private $enumRegistry;
/**
- * @param EnumRegistryInterface $enumRegistry
+ * @param EnumRegistry $enumRegistry
*/
- public function __construct(EnumRegistryInterface $enumRegistry)
+ public function __construct(EnumRegistry $enumRegistry)
{
$this->enumRegistry = $enumRegistry;
}
@@ -29,10 +31,10 @@ public function __construct(EnumRegistryInterface $enumRegistry)
/**
* @inheritdoc
*/
- public function validate($value, Constraint $constraint)
+ public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof Enum) {
- throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Enum');
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\Enum');
}
$constraint->choices = null;
diff --git a/YokaiEnumBundle.php b/src/YokaiEnumBundle.php
similarity index 65%
rename from YokaiEnumBundle.php
rename to src/YokaiEnumBundle.php
index a010f52..e798e6b 100644
--- a/YokaiEnumBundle.php
+++ b/src/YokaiEnumBundle.php
@@ -1,10 +1,11 @@
addCompilerPass(new ConventionedEnumCollectorCompilerPass())
- ->addCompilerPass(new TaggedEnumCollectorCompilerPass)
+ ->addCompilerPass(new TaggedEnumCollectorCompilerPass())
;
}
/**
* @inheritdoc
*/
- public function getContainerExtension()
+ public function getContainerExtension(): EnumExtension
{
- return new EnumExtension;
+ return new EnumExtension();
}
}
diff --git a/tests/ConfigurableEnumTest.php b/tests/ConfigurableEnumTest.php
new file mode 100644
index 0000000..fcd6702
--- /dev/null
+++ b/tests/ConfigurableEnumTest.php
@@ -0,0 +1,18 @@
+
+ */
+class ConfigurableEnumTest extends TestCase
+{
+ public function testConfigurability(): void
+ {
+ $fooEnum = new ConfigurableEnum('foo', ['foo' => 'FOO', 'bar' => 'BAR']);
+ $this->assertSame('foo', $fooEnum->getName());
+ $this->assertSame(['foo' => 'FOO', 'bar' => 'BAR'], $fooEnum->getChoices());
+ }
+}
diff --git a/Tests/Enum/ConfigurableTranslatedEnumTest.php b/tests/ConfigurableTranslatedEnumTest.php
similarity index 69%
rename from Tests/Enum/ConfigurableTranslatedEnumTest.php
rename to tests/ConfigurableTranslatedEnumTest.php
index bef5223..3c2abdd 100644
--- a/Tests/Enum/ConfigurableTranslatedEnumTest.php
+++ b/tests/ConfigurableTranslatedEnumTest.php
@@ -1,27 +1,28 @@
-
*/
-class ConfigurableTranslatedEnumTest extends \PHPUnit_Framework_TestCase
+class ConfigurableTranslatedEnumTest extends TestCase
{
- public function testConstructedWithInvalidPattern()
+ public function testConstructedWithInvalidPattern(): void
{
- $this->expectException('Yokai\EnumBundle\Exception\InvalidTranslatePatternException');
- $translator = $this->prophesize('Symfony\Component\Translation\TranslatorInterface');
+ $this->expectException(InvalidTranslatePatternException::class);
+ $translator = $this->prophesize(TranslatorInterface::class);
new ConfigurableTranslatedEnum($translator->reveal(), 'invalid.pattern', 'invalid', ['foo', 'bar']);
}
- public function testTranslatedChoices()
+ public function testTranslatedChoices(): void
{
/** @var ObjectProphecy|TranslatorInterface $translator */
- $translator = $this->prophesize('Symfony\Component\Translation\TranslatorInterface');
+ $translator = $this->prophesize(TranslatorInterface::class);
$translator->trans('choice.something.foo', [], 'messages', null)->shouldBeCalled()->willReturn('FOO translated');
$translator->trans('choice.something.bar', [], 'messages', null)->shouldBeCalled()->willReturn('BAR translated');
$type = new ConfigurableTranslatedEnum($translator->reveal(), 'choice.something.%s', 'something', ['foo', 'bar']);
@@ -33,10 +34,10 @@ public function testTranslatedChoices()
$this->assertEquals($expectedChoices, $type->getChoices());
}
- public function testTranslatedWithDomainChoices()
+ public function testTranslatedWithDomainChoices(): void
{
/** @var ObjectProphecy|TranslatorInterface $translator */
- $translator = $this->prophesize('Symfony\Component\Translation\TranslatorInterface');
+ $translator = $this->prophesize(TranslatorInterface::class);
$translator->trans('choice.something.foo', [], 'messages', null)->shouldNotBeCalled();
$translator->trans('choice.something.bar', [], 'messages', null)->shouldNotBeCalled();
$translator->trans('something.foo', [], 'choices', null)->shouldBeCalled()->willReturn('FOO translated');
diff --git a/tests/ConstantExtractorTest.php b/tests/ConstantExtractorTest.php
new file mode 100644
index 0000000..0c39755
--- /dev/null
+++ b/tests/ConstantExtractorTest.php
@@ -0,0 +1,123 @@
+
+ */
+class ConstantExtractorTest extends TestCase
+{
+ public function getExtractor(): ConstantExtractor
+ {
+ return new ConstantExtractor();
+ }
+
+ /**
+ * @dataProvider malformed
+ */
+ public function testExtractMalformedPattern(string $pattern, string $exceptionMessage): void
+ {
+ $this->expectException(CannotExtractConstantsException::class);
+ $this->expectExceptionMessageMatches($exceptionMessage);
+
+ $this->getExtractor()->extract($pattern);
+ }
+
+ /**
+ * @dataProvider empty
+ */
+ public function testExtractEmpty(string $pattern, string $exceptionMessage): void
+ {
+ $this->expectException(CannotExtractConstantsException::class);
+ $this->expectExceptionMessageMatches($exceptionMessage);
+
+ $this->getExtractor()->extract($pattern);
+ }
+
+ /**
+ * @dataProvider successful
+ */
+ public function testExtractSuccessful(string $pattern, array $expectedList): void
+ {
+ self::assertEquals($expectedList, $this->getExtractor()->extract($pattern));
+ }
+
+ public function empty(): Generator
+ {
+ yield 'class without constant' => [
+ ClassWithoutConstant::class.'::*',
+ '/Class .+ has no public constant/',
+ ];
+ yield 'class without public constant' => [
+ ClassWithNoPublicConstant::class.'::*',
+ '/Class .+ has no public constant/',
+ ];
+ yield 'class with constant but no match' => [
+ ClassWithConstant::class.'::NO_MATCH*',
+ '/Pattern .+ matches no constant/',
+ ];
+ }
+
+ public function malformed(): Generator
+ {
+ $invalidPatternRegexp = '/Constant extraction pattern must look like Fully\\\\Qualified\\\\ClassName::CONSTANT_\*\..+/';
+ yield 'no class no constant pattern' => [
+ 'not a pattern',
+ $invalidPatternRegexp,
+ ];
+ yield 'class that do not exists' => [
+ 'SomeClassThatDoNotExists::STATUS_*',
+ '/Class SomeClassThatDoNotExists do not exists\./',
+ ];
+ yield 'missing constant pattern and separator' => [
+ ClassWithConstant::class,
+ $invalidPatternRegexp,
+ ];
+ yield 'missing constant pattern' => [
+ ClassWithConstant::class.'::',
+ $invalidPatternRegexp,
+ ];
+ yield 'two separator' => [
+ ClassWithConstant::class.'::STATUS_*::',
+ $invalidPatternRegexp,
+ ];
+ yield 'no * in pattern' => [
+ ClassWithConstant::class.'::STATUS_ONLINE',
+ $invalidPatternRegexp,
+ ];
+ }
+
+ public function successful(): Generator
+ {
+ yield 'starting with status' => [
+ ClassWithConstant::class.'::STATUS_*',
+ [ClassWithConstant::STATUS_ONLINE, ClassWithConstant::STATUS_DRAFT],
+ ];
+ yield 'ending with online' => [
+ ClassWithConstant::class.'::*_ONLINE',
+ [ClassWithConstant::STATUS_ONLINE],
+ ];
+ }
+}
+
+class ClassWithoutConstant
+{
+}
+
+class ClassWithNoPublicConstant
+{
+ private const PROTECTED_CONST = 'protected';
+ private const PRIVATE_CONST = 'private';
+}
+
+class ClassWithConstant
+{
+ public const STATUS_ONLINE = 'online';
+ public const STATUS_DRAFT = 'draft';
+ protected const STATUS_PROTECTED = 'protected';
+ private const STATUS_PRIVATE = 'private';
+}
diff --git a/tests/ConstantListEnumTest.php b/tests/ConstantListEnumTest.php
new file mode 100644
index 0000000..e9d68d7
--- /dev/null
+++ b/tests/ConstantListEnumTest.php
@@ -0,0 +1,42 @@
+
+ */
+class ConstantListEnumTest extends TestCase
+{
+ public function getEnum(string $pattern, string $name): ConstantListEnum
+ {
+ return new ConstantListEnum(new ConstantExtractor(), $pattern, $name);
+ }
+
+ public function testVehicleEnums(): void
+ {
+ $type = $this->getEnum(Vehicle::class.'::TYPE_*', 'vehicle.type');
+ self::assertSame('vehicle.type', $type->getName());
+ self::assertSame(
+ ['bike' => 'bike', 'car' => 'car', 'bus' => 'bus'],
+ $type->getChoices()
+ );
+
+ $engine = $this->getEnum(Vehicle::class.'::ENGINE_*', 'vehicle.engine');
+ self::assertSame('vehicle.engine', $engine->getName());
+ self::assertSame(
+ ['electic' => 'electic', 'combustion' => 'combustion'],
+ $engine->getChoices()
+ );
+
+ $brand = $this->getEnum(Vehicle::class.'::BRAND_*', 'vehicle.brand');
+ self::assertSame('vehicle.brand', $brand->getName());
+ self::assertSame(
+ ['renault' => 'renault', 'volkswagen' => 'volkswagen', 'toyota' => 'toyota'],
+ $brand->getChoices()
+ );
+ }
+}
diff --git a/tests/ConstantListTranslatedEnumTest.php b/tests/ConstantListTranslatedEnumTest.php
new file mode 100644
index 0000000..9588996
--- /dev/null
+++ b/tests/ConstantListTranslatedEnumTest.php
@@ -0,0 +1,68 @@
+
+ */
+class ConstantListTranslatedEnumTest extends TestCase
+{
+ /**
+ * @var TranslatorInterface|ObjectProphecy
+ */
+ private $translator;
+
+ protected function setUp(): void
+ {
+ $this->translator = $this->prophesize(TranslatorInterface::class);
+ }
+
+ public function getEnum(string $pattern, string $name): ConstantListTranslatedEnum
+ {
+ return new ConstantListTranslatedEnum(
+ new ConstantExtractor(),
+ $pattern,
+ $this->translator->reveal(),
+ $name.'.%s',
+ $name
+ );
+ }
+
+ public function testVehicleEnums(): void
+ {
+ $type = $this->getEnum(Vehicle::class.'::TYPE_*', 'vehicle.type');
+ $this->translator->trans('vehicle.type.bike', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Moto');
+ $this->translator->trans('vehicle.type.car', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Voiture');
+ $this->translator->trans('vehicle.type.bus', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Bus');
+ self::assertSame('vehicle.type', $type->getName());
+ self::assertSame(
+ ['bike' => 'Moto', 'car' => 'Voiture', 'bus' => 'Bus'],
+ $type->getChoices()
+ );
+
+ $engine = $this->getEnum(Vehicle::class.'::ENGINE_*', 'vehicle.engine');
+ $this->translator->trans('vehicle.engine.electic', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Electrique');
+ $this->translator->trans('vehicle.engine.combustion', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Combustion');
+ self::assertSame('vehicle.engine', $engine->getName());
+ self::assertSame(
+ ['electic' => 'Electrique', 'combustion' => 'Combustion'],
+ $engine->getChoices()
+ );
+
+ $brand = $this->getEnum(Vehicle::class.'::BRAND_*', 'vehicle.brand');
+ $this->translator->trans('vehicle.brand.renault', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Renault');
+ $this->translator->trans('vehicle.brand.volkswagen', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Volkswagen');
+ $this->translator->trans('vehicle.brand.toyota', [], 'messages')->shouldBeCalledTimes(1)->willReturn('Toyota');
+ self::assertSame('vehicle.brand', $brand->getName());
+ self::assertSame(
+ ['renault' => 'Renault', 'volkswagen' => 'Volkswagen', 'toyota' => 'Toyota'],
+ $brand->getChoices()
+ );
+ }
+}
diff --git a/Tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php b/tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php
similarity index 58%
rename from Tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php
rename to tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php
index 7496a2f..8e6e31d 100644
--- a/Tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php
+++ b/tests/DependencyInjection/CompilerPass/TaggedEnumCollectorCompilerPassTest.php
@@ -1,50 +1,48 @@
-
*/
-class TaggedEnumCollectorCompilerPassTest extends \PHPUnit_Framework_TestCase
+class TaggedEnumCollectorCompilerPassTest extends TestCase
{
/**
* @var TaggedEnumCollectorCompilerPass
*/
private $compiler;
- protected function setUp()
+ protected function setUp(): void
{
$this->compiler = new TaggedEnumCollectorCompilerPass;
}
- protected function tearDown()
+ public function testCollectWhenServiceNotAvailable(): void
{
- unset($this->compiler);
- }
-
- public function testCollectWhenServiceNotAvailable()
- {
- $compiler = $this->prophesize('Symfony\Component\DependencyInjection\ContainerBuilder');
+ $compiler = $this->prophesize(ContainerBuilder::class);
$compiler->hasDefinition('enum.registry')->shouldBeCalled()->willReturn(false);
$this->compiler->process($compiler->reveal());
}
- public function testCollectEnums()
+ public function testCollectEnums(): void
{
- $registry = $this->prophesize('Symfony\Component\DependencyInjection\Definition');
+ $registry = $this->prophesize(Definition::class);
$registry->addMethodCall('add', [new Reference('enum.gender')])->shouldBeCalled();
$registry->addMethodCall('add', [new Reference('enum.type')])->shouldBeCalled();
- $compiler = $this->prophesize('Symfony\Component\DependencyInjection\ContainerBuilder');
+ $compiler = $this->prophesize(ContainerBuilder::class);
$compiler->hasDefinition('enum.registry')->shouldBeCalled()->willReturn(true);
$compiler->getDefinition('enum.registry')->shouldBeCalled()->willReturn($registry);
$compiler->findTaggedServiceIds('enum')->shouldBeCalled()->willReturn([
- 'enum.gender' => $this->prophesize('Symfony\Component\DependencyInjection\Definition')->reveal(),
- 'enum.type' => $this->prophesize('Symfony\Component\DependencyInjection\Definition')->reveal(),
+ 'enum.gender' => $this->prophesize(Definition::class)->reveal(),
+ 'enum.type' => $this->prophesize(Definition::class)->reveal(),
]);
$this->compiler->process($compiler->reveal());
diff --git a/tests/DependencyInjection/EnumExtensionTest.php b/tests/DependencyInjection/EnumExtensionTest.php
new file mode 100644
index 0000000..92f7270
--- /dev/null
+++ b/tests/DependencyInjection/EnumExtensionTest.php
@@ -0,0 +1,45 @@
+
+ */
+class EnumExtensionTest extends TestCase
+{
+ public function extension(): EnumExtension
+ {
+ return new EnumExtension();
+ }
+
+ /**
+ * @test
+ */
+ public function it_register_services(): void
+ {
+ $container = new ContainerBuilder();
+ $this->extension()->load([[]], $container);
+
+ $services = [
+ 'yokai_enum.form_type.enum_type',
+ 'yokai_enum.form_extension.enum_type_guesser',
+ 'yokai_enum.validator_constraints.enum_validator',
+ 'yokai_enum.twig_extension.enum_extension',
+ ];
+ foreach ($services as $service) {
+ self::assertTrue($container->has($service), sprintf('Service "%s" is registered', $service));
+ }
+
+ $autoconfigure = $container->getAutoconfiguredInstanceof();
+ $this->assertArrayHasKey(EnumInterface::class, $autoconfigure);
+ $this->assertEquals(['enum' => [[]]], $autoconfigure[EnumInterface::class]->getTags());
+
+ $this->assertTrue($container->hasAlias(EnumRegistry::class));
+ }
+}
diff --git a/Tests/Registry/EnumRegistryTest.php b/tests/EnumRegistryTest.php
similarity index 67%
rename from Tests/Registry/EnumRegistryTest.php
rename to tests/EnumRegistryTest.php
index 3a0192c..98b11f5 100644
--- a/Tests/Registry/EnumRegistryTest.php
+++ b/tests/EnumRegistryTest.php
@@ -1,8 +1,12 @@
-
*/
-class EnumRegistryTest extends \PHPUnit_Framework_TestCase
+class EnumRegistryTest extends TestCase
{
/**
* @var EnumRegistry
*/
private $registry;
- protected function setUp()
+ protected function setUp(): void
{
$this->registry = new EnumRegistry;
}
- protected function tearDown()
+ public function testAddDuplicatedException(): void
{
- unset($this->registry);
- }
-
- public function testAddDuplicatedException()
- {
- $this->expectException('Yokai\EnumBundle\Exception\DuplicatedEnumException');
+ $this->expectException(DuplicatedEnumException::class);
$this->registry->add(new GenderEnum);
$this->registry->add(new GenderEnum);
}
- public function testGetInvalidException()
+ public function testGetInvalidException(): void
{
- $this->expectException('Yokai\EnumBundle\Exception\InvalidEnumException');
+ $this->expectException(InvalidEnumException::class);
$this->registry->add(new GenderEnum);
$this->registry->get('type');
}
- public function testAddNominal()
+ public function testAddNominal(): void
{
- $translator = $this->prophesize('Symfony\Component\Translation\TranslatorInterface')->reveal();
+ /** @var TranslatorInterface|ObjectProphecy $translator */
+ $translator = $this->prophesize(TranslatorInterface::class)->reveal();
$gender = new GenderEnum;
$state = new StateEnum($translator);
$subscription = new SubscriptionEnum($translator);
diff --git a/Tests/Fixtures/GenderEnum.php b/tests/Fixtures/GenderEnum.php
similarity index 62%
rename from Tests/Fixtures/GenderEnum.php
rename to tests/Fixtures/GenderEnum.php
index d56042a..ab787f1 100644
--- a/Tests/Fixtures/GenderEnum.php
+++ b/tests/Fixtures/GenderEnum.php
@@ -1,9 +1,9 @@
-
@@ -12,7 +12,7 @@ class GenderEnum implements EnumInterface
{
use EnumWithClassAsNameTrait;
- public function getChoices()
+ public function getChoices(): array
{
return ['male' => 'Male', 'female' => 'Female'];
}
diff --git a/Tests/Fixtures/StateEnum.php b/tests/Fixtures/StateEnum.php
similarity index 66%
rename from Tests/Fixtures/StateEnum.php
rename to tests/Fixtures/StateEnum.php
index 465fe19..93cec36 100644
--- a/Tests/Fixtures/StateEnum.php
+++ b/tests/Fixtures/StateEnum.php
@@ -1,9 +1,9 @@
-
@@ -18,12 +18,12 @@ public function __construct(TranslatorInterface $translator)
parent::__construct($translator, 'choice.state.%s');
}
- protected function getValues()
+ protected function getValues(): array
{
return ['new', 'validated', 'disabled'];
}
- public function getName()
+ public function getName(): string
{
return 'state';
}
diff --git a/Tests/Fixtures/SubscriptionEnum.php b/tests/Fixtures/SubscriptionEnum.php
similarity index 77%
rename from Tests/Fixtures/SubscriptionEnum.php
rename to tests/Fixtures/SubscriptionEnum.php
index d42128b..26f18ca 100644
--- a/Tests/Fixtures/SubscriptionEnum.php
+++ b/tests/Fixtures/SubscriptionEnum.php
@@ -1,9 +1,9 @@
-
diff --git a/Tests/Fixtures/TypeEnum.php b/tests/Fixtures/TypeEnum.php
similarity index 80%
rename from Tests/Fixtures/TypeEnum.php
rename to tests/Fixtures/TypeEnum.php
index 426a14c..de4bf65 100644
--- a/Tests/Fixtures/TypeEnum.php
+++ b/tests/Fixtures/TypeEnum.php
@@ -1,8 +1,8 @@
-
diff --git a/tests/Fixtures/Vehicle.php b/tests/Fixtures/Vehicle.php
new file mode 100644
index 0000000..a8e27e5
--- /dev/null
+++ b/tests/Fixtures/Vehicle.php
@@ -0,0 +1,17 @@
+enumRegistry = $this->prophesize('Yokai\EnumBundle\Registry\EnumRegistryInterface');
+ $this->enumRegistry = $this->prophesize(EnumRegistry::class);
$this->enumRegistry->has('state')->willReturn(false);
$this->enumRegistry->has(GenderEnum::class)->willReturn(true);
$this->enumRegistry->get(GenderEnum::class)->willReturn(new GenderEnum);
$this->metadata = new ClassMetadata(self::TEST_CLASS);
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, new Enum(['enum' => GenderEnum::class]));
- $this->metadataFactory = $this->prophesize('Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface');
+ $this->metadataFactory = $this->prophesize(MetadataFactoryInterface::class);
$this->metadataFactory->getMetadataFor(self::TEST_CLASS)
->willReturn($this->metadata);
@@ -64,10 +66,10 @@ protected function setUp()
parent::setUp();
}
- public function testGuessType()
+ public function testGuessType(): void
{
$guess = new TypeGuess(
- $this->getEnumType(),
+ EnumType::class,
[
'enum' => GenderEnum::class,
'multiple' => false,
@@ -78,53 +80,34 @@ public function testGuessType()
$this->assertEquals($guess, $this->guesser->guessType(self::TEST_CLASS, self::TEST_PROPERTY));
}
- public function testGuessRequired()
+ public function testGuessRequired(): void
{
$this->assertNull($this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
}
- public function testGuessMaxLength()
+ public function testGuessMaxLength(): void
{
$this->assertNull($this->guesser->guessMaxLength(self::TEST_CLASS, self::TEST_PROPERTY));
}
- public function testGuessPattern()
+ public function testGuessPattern(): void
{
$this->assertNull($this->guesser->guessPattern(self::TEST_CLASS, self::TEST_PROPERTY));
}
- public function testCreateForm()
+ public function testCreateForm(): void
{
$class = self::TEST_CLASS;
- $form = $this->factory->create($this->getFormType(), new $class, ['data_class' => $class])
+ $form = $this->factory->create(FormType::class, new $class, ['data_class' => $class])
->add(self::TEST_PROPERTY);
- $this->assertEquals(['Male' => 'male', 'Female' => 'female'], $form->get(self::TEST_PROPERTY)->getConfig()->getOption('choices'));
- }
-
- protected function getFormType()
- {
- if (method_exists(AbstractType::class, 'getBlockPrefix')) {
- $name = FormType::class; //Symfony 3.x support
- } else {
- $name = 'form'; //Symfony 2.x support
- }
-
- return $name;
- }
-
- protected function getEnumType()
- {
- if (method_exists(AbstractType::class, 'getBlockPrefix')) {
- $name = EnumType::class; //Symfony 3.x support
- } else {
- $name = 'enum'; //Symfony 2.x support
- }
-
- return $name;
+ $this->assertEquals(
+ ['Male' => 'male', 'Female' => 'female'],
+ $form->get(self::TEST_PROPERTY)->getConfig()->getOption('choices')
+ );
}
- protected function getExtensions()
+ protected function getExtensions(): array
{
return [
new TestExtension($this->enumRegistry->reveal(), $this->metadataFactory->reveal()),
diff --git a/Tests/Form/TestExtension.php b/tests/Form/TestExtension.php
similarity index 73%
rename from Tests/Form/TestExtension.php
rename to tests/Form/TestExtension.php
index 4b49be8..3b1d8ce 100644
--- a/Tests/Form/TestExtension.php
+++ b/tests/Form/TestExtension.php
@@ -1,12 +1,12 @@
-
@@ -14,7 +14,7 @@
class TestExtension extends AbstractExtension
{
/**
- * @var EnumRegistryInterface
+ * @var EnumRegistry
*/
private $enumRegistry;
@@ -24,10 +24,10 @@ class TestExtension extends AbstractExtension
private $metadataFactory;
/**
- * @param EnumRegistryInterface $enumRegistry
+ * @param EnumRegistry $enumRegistry
* @param MetadataFactoryInterface|null $metadataFactory
*/
- public function __construct(EnumRegistryInterface $enumRegistry, MetadataFactoryInterface $metadataFactory = null)
+ public function __construct(EnumRegistry $enumRegistry, MetadataFactoryInterface $metadataFactory = null)
{
$this->enumRegistry = $enumRegistry;
$this->metadataFactory = $metadataFactory;
@@ -36,7 +36,7 @@ public function __construct(EnumRegistryInterface $enumRegistry, MetadataFactory
/**
* @inheritdoc
*/
- protected function loadTypes()
+ protected function loadTypes(): array
{
return [
new EnumType($this->enumRegistry),
@@ -46,7 +46,7 @@ protected function loadTypes()
/**
* @inheritdoc
*/
- protected function loadTypeGuesser()
+ protected function loadTypeGuesser(): ?EnumTypeGuesser
{
if ($this->metadataFactory === null) {
return null;
diff --git a/Tests/Form/Type/EnumTypeTest.php b/tests/Form/Type/EnumTypeTest.php
similarity index 55%
rename from Tests/Form/Type/EnumTypeTest.php
rename to tests/Form/Type/EnumTypeTest.php
index c6a0399..acade77 100644
--- a/Tests/Form/Type/EnumTypeTest.php
+++ b/tests/Form/Type/EnumTypeTest.php
@@ -1,9 +1,13 @@
-enumRegistry = $this->prophesize('Yokai\EnumBundle\Registry\EnumRegistryInterface');
+ $this->enumRegistry = $this->prophesize(EnumRegistry::class);
$this->enumRegistry->has('state')->willReturn(false);
$this->enumRegistry->has(GenderEnum::class)->willReturn(true);
$this->enumRegistry->get(GenderEnum::class)->willReturn(new GenderEnum);
@@ -25,45 +31,39 @@ protected function setUp()
parent::setUp();
}
- public function testEnumOptionIsRequired()
+ public function testEnumOptionIsRequired(): void
{
- $this->expectException('Symfony\Component\OptionsResolver\Exception\MissingOptionsException');
+ $this->expectException(MissingOptionsException::class);
$this->createForm();
}
- public function testEnumOptionIsInvalid()
+ public function testEnumOptionIsInvalid(): void
{
- $this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
+ $this->expectException(InvalidOptionsException::class);
$this->createForm('state');
}
- public function testEnumOptionValid()
+ public function testEnumOptionValid(): void
{
$form = $this->createForm(GenderEnum::class);
$this->assertEquals(['Male' => 'male', 'Female' => 'female'], $form->getConfig()->getOption('choices'));
}
- protected function getExtensions()
+ protected function getExtensions(): array
{
return [
new TestExtension($this->enumRegistry->reveal())
];
}
- private function createForm($enum = null)
+ private function createForm($enum = null): FormInterface
{
$options = [];
if ($enum) {
$options['enum'] = $enum;
}
- if (method_exists(AbstractType::class, 'getBlockPrefix')) {
- $name = EnumType::class; //Symfony 3.x support
- } else {
- $name = 'enum'; //Symfony 2.x support
- }
-
- return $this->factory->create($name, null, $options);
+ return $this->factory->create(EnumType::class, null, $options);
}
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..2a4f28c
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,14 @@
+
+ */
+abstract class TestCase extends PHPUnitTestCase
+{
+ use ProphecyTrait;
+}
diff --git a/Tests/Twig/Extension/EnumExtensionTest.php b/tests/Twig/Extension/EnumExtensionTest.php
similarity index 64%
rename from Tests/Twig/Extension/EnumExtensionTest.php
rename to tests/Twig/Extension/EnumExtensionTest.php
index fdb50b7..a46809e 100644
--- a/Tests/Twig/Extension/EnumExtensionTest.php
+++ b/tests/Twig/Extension/EnumExtensionTest.php
@@ -1,35 +1,33 @@
-
*/
-class EnumExtensionTest extends \PHPUnit_Framework_TestCase
+class EnumExtensionTest extends TestCase
{
/**
- * @var EnumRegistryInterface|\Prophecy\Prophecy\ObjectProphecy
+ * @var EnumRegistry|ObjectProphecy
*/
private $registry;
- protected function setUp()
+ protected function setUp(): void
{
- $this->registry = $this->prophesize('Yokai\EnumBundle\Registry\EnumRegistryInterface');
+ $this->registry = $this->prophesize(EnumRegistry::class);
}
- protected function tearDown()
+ public function testEnumLabel(): void
{
- unset(
- $this->registry
- );
- }
-
- public function testEnumLabel()
- {
- $enum = $this->prophesize('Yokai\EnumBundle\Enum\EnumInterface');
+ $enum = $this->prophesize(EnumInterface::class);
$enum->getChoices()
->willReturn(['foo' => 'FOO', 'bar' => 'BAR']);
@@ -57,9 +55,9 @@ public function testEnumLabel()
);
}
- public function testEnumChoices()
+ public function testEnumChoices(): void
{
- $enum = $this->prophesize('Yokai\EnumBundle\Enum\EnumInterface');
+ $enum = $this->prophesize(EnumInterface::class);
$enum->getChoices()
->willReturn(['foo' => 'FOO', 'bar' => 'BAR']);
@@ -75,12 +73,12 @@ public function testEnumChoices()
}
/**
- * @return \Twig_Environment
+ * @return Environment
*/
- protected function createEnvironment()
+ protected function createEnvironment(): Environment
{
- $loader = new \Twig_Loader_Array([]);
- $twig = new \Twig_Environment($loader, ['debug' => true, 'cache' => false, 'autoescape' => false]);
+ $loader = new ArrayLoader([]);
+ $twig = new Environment($loader, ['debug' => true, 'cache' => false, 'autoescape' => false]);
$twig->addExtension($this->createExtension());
return $twig;
@@ -89,7 +87,7 @@ protected function createEnvironment()
/**
* @return EnumExtension
*/
- private function createExtension()
+ private function createExtension(): EnumExtension
{
return new EnumExtension($this->registry->reveal());
}
diff --git a/Tests/Validator/Constraints/EnumValidatorTest.php b/tests/Validator/Constraints/EnumValidatorTest.php
similarity index 60%
rename from Tests/Validator/Constraints/EnumValidatorTest.php
rename to tests/Validator/Constraints/EnumValidatorTest.php
index 3f660c8..451a05c 100644
--- a/Tests/Validator/Constraints/EnumValidatorTest.php
+++ b/tests/Validator/Constraints/EnumValidatorTest.php
@@ -1,9 +1,14 @@
-
*/
-class EnumValidatorTest extends AbstractConstraintValidatorTest
+class EnumValidatorTest extends ConstraintValidatorTestCase
{
+ use ProphecyTrait;
- protected function createValidator()
+ protected function createValidator(): EnumValidator
{
- $registry = $this->prophesize('Yokai\EnumBundle\Registry\EnumRegistryInterface');
+ /** @var EnumRegistry|ObjectProphecy $registry */
+ $registry = $this->prophesize(EnumRegistry::class);
$registry->has('state')->willReturn(false);
$registry->has(GenderEnum::class)->willReturn(true);
$registry->has('type')->willReturn(true);
@@ -26,39 +33,39 @@ protected function createValidator()
return new EnumValidator($registry->reveal());
}
- public function testAcceptOnlyEnum()
+ public function testAcceptOnlyEnum(): void
{
- $this->expectException('Symfony\Component\Validator\Exception\UnexpectedTypeException');
+ $this->expectException(UnexpectedTypeException::class);
$this->validator->validate(null, new Choice);
}
- public function testEnumIsRequired()
+ public function testEnumIsRequired(): void
{
- $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+ $this->expectException(ConstraintDefinitionException::class);
$this->validator->validate('foo', new Enum);
}
- public function testValidEnumIsRequired()
+ public function testValidEnumIsRequired(): void
{
- $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+ $this->expectException(ConstraintDefinitionException::class);
$this->validator->validate('foo', new Enum('state'));
}
- public function testNullIsValid()
+ public function testNullIsValid(): void
{
$this->validator->validate(null, new Enum('type'));
$this->assertNoViolation();
}
- public function testValidSingleEnum()
+ public function testValidSingleEnum(): void
{
$this->validator->validate('customer', new Enum('type'));
$this->assertNoViolation();
}
- public function testInvalidSingleEnum()
+ public function testInvalidSingleEnum(): void
{
$constraint = new Enum(['enum' => 'type', 'message' => 'myMessage']);
@@ -67,10 +74,11 @@ public function testInvalidSingleEnum()
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"foo"')
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->setParameter('{{ choices }}', '"customer", "prospect"')
->assertRaised();
}
- public function testValidMultipleEnum()
+ public function testValidMultipleEnum(): void
{
$constraint = new Enum(['enum' => 'type', 'multiple' => true]);
@@ -79,7 +87,7 @@ public function testValidMultipleEnum()
$this->assertNoViolation();
}
- public function testInvalidMultipleEnum()
+ public function testInvalidMultipleEnum(): void
{
$constraint = new Enum(['enum' => 'type', 'multiple' => true, 'multipleMessage' => 'myMessage']);
@@ -89,7 +97,7 @@ public function testInvalidMultipleEnum()
->setParameter('{{ value }}', '"foo"')
->setInvalidValue('foo')
->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->setParameter('{{ choices }}', '"customer", "prospect"')
->assertRaised();
}
-
}