vendor/elao/enum/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php line 57

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the "elao/enum" package.
  4.  *
  5.  * Copyright (C) Elao
  6.  *
  7.  * @author Elao <contact@elao.com>
  8.  */
  9. namespace Elao\Enum\Bridge\Symfony\Bundle\DependencyInjection;
  10. use Elao\Enum\Bridge\Doctrine\DBAL\Types\TypesDumper;
  11. use Elao\Enum\EnumInterface;
  12. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  13. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  14. use Symfony\Component\Config\Definition\ConfigurationInterface;
  15. use Symfony\Component\Serializer\SerializerInterface;
  16. class Configuration implements ConfigurationInterface
  17. {
  18.     public function getConfigTreeBuilder()
  19.     {
  20.         $treeBuilder = new TreeBuilder('elao_enum');
  21.         $rootNode method_exists(TreeBuilder::class, 'getRootNode') ? $treeBuilder->getRootNode() : $treeBuilder->root('elao_enum');
  22.         $rootNode->children()
  23.             ->arrayNode('argument_value_resolver')->canBeDisabled()->end()
  24.             ->arrayNode('serializer')
  25.                 ->{interface_exists(SerializerInterface::class) ? 'canBeDisabled' 'canBeEnabled'}()
  26.             ->end()
  27.         ->end();
  28.         $this->addDoctrineSection($rootNode);
  29.         $this->addTranslationExtractorSection($rootNode);
  30.         $this->addJsEnumsSection($rootNode);
  31.         return $treeBuilder;
  32.     }
  33.     private function addDoctrineSection(ArrayNodeDefinition $rootNode)
  34.     {
  35.         $rootNode->children()
  36.             ->arrayNode('doctrine')
  37.             ->addDefaultsIfNotSet()
  38.             ->fixXmlConfig('type')
  39.             ->children()
  40.                 ->booleanNode('enum_sql_declaration')
  41.                     ->defaultValue(false)
  42.                     ->info('If true, by default for string enumerations, generate DBAL types with an ENUM SQL declaration with enum values instead of a VARCHAR (Your platform must support it)')
  43.                 ->end()
  44.                 ->arrayNode('types')
  45.                     ->beforeNormalization()
  46.                         ->always(function (array $values): array {
  47.                             // BC: detect legacy format with enum classes as keys
  48.                             if (is_a(array_key_first($values), EnumInterface::class, true)) {
  49.                                 @trigger_error('Using enum FQCN as keys at path "elao_enum.doctrine.types" is deprecated. Provide the name as keys and add the "class" option for each entry instead.'E_USER_DEPRECATED);
  50.                                 // Convert to new format:
  51.                                 $legacyFormat $values;
  52.                                 $values = [];
  53.                                 foreach ($legacyFormat as $name => $value) {
  54.                                     if (\is_string($value)) {
  55.                                         $values[$value] = $name;
  56.                                         continue;
  57.                                     }
  58.                                     $values[$value['name']] = $value + ['class' => $name];
  59.                                 }
  60.                             }
  61.                             return $values;
  62.                         })
  63.                     ->end()
  64.                     ->useAttributeAsKey('name')
  65.                     ->arrayPrototype()
  66.                     ->beforeNormalization()
  67.                         ->ifString()->then(static function (string $v): array { return ['class' => $v]; })
  68.                     ->end()
  69.                     ->children()
  70.                         ->scalarNode('class')
  71.                             ->cannotBeEmpty()
  72.                             ->validate()
  73.                                 ->ifTrue(static function (string $class): bool {return !is_a($classEnumInterface::class, true); })
  74.                                 ->thenInvalid(sprintf('Invalid class. Expected instance of "%s"'EnumInterface::class) . '. Got %s.')
  75.                             ->end()
  76.                         ->end()
  77.                         ->enumNode('type')
  78.                             ->values(TypesDumper::TYPES)
  79.                             ->info(<<<TXT
  80. Which column definition to use and the way the enumeration values are stored in the database:
  81. - string: VARCHAR
  82. - enum: ENUM(...values) (Your platform must support it)
  83. - int: INT
  84. - json_collection: JSON
  85. - csv_collection: CSV (Doctrine simple_array type)
  86. Default is either "string" or "enum", controlled by the `elao_enum.doctrine.enum_sql_declaration` option.
  87. Default for flagged enums is "int".
  88. TXT
  89.                             )
  90.                             ->cannotBeEmpty()
  91.                             ->defaultValue(null)
  92.                         ->end()
  93.                     ->end()
  94.                 ->end()
  95.             ->end()
  96.         ->end();
  97.     }
  98.     private function addTranslationExtractorSection(ArrayNodeDefinition $rootNode)
  99.     {
  100.         $rootNode->children()
  101.             ->arrayNode('translation_extractor')
  102.             ->canBeEnabled()
  103.             ->fixXmlConfig('path')
  104.             ->children()
  105.                 ->arrayNode('paths')
  106.                     ->example(['App\Enum' => '%kernel.project_dir%/src/Enum'])
  107.                     ->useAttributeAsKey('namespace')
  108.                     ->scalarPrototype()
  109.                     ->end()
  110.                 ->end()
  111.                 ->scalarNode('domain')
  112.                     ->defaultValue('messages')
  113.                     ->cannotBeEmpty()
  114.                 ->end()
  115.                 ->scalarNode('filename_pattern')
  116.                     ->example('*Enum.php')
  117.                     ->defaultValue('*.php')
  118.                     ->cannotBeEmpty()
  119.                 ->end()
  120.                 ->arrayNode('ignore')
  121.                     ->example(['%kernel.project_dir%/src/Enum/Other/*'])
  122.                     ->scalarPrototype()->cannotBeEmpty()->end()
  123.                 ->end()
  124.             ->end()
  125.         ->end();
  126.     }
  127.     private function addJsEnumsSection(ArrayNodeDefinition $rootNode)
  128.     {
  129.         $rootNode->children()
  130.             ->arrayNode('js')
  131.                 ->addDefaultsIfNotSet()
  132.                 ->fixXmlConfig('path')
  133.                 ->children()
  134.                     ->scalarNode('base_dir')
  135.                         ->info('A prefixed dir used for relative paths supplied for each of the generated enums and library path')
  136.                         ->example('%kernel.project_dir%/assets/js/modules')
  137.                         ->defaultNull()
  138.                     ->end()
  139.                     ->scalarNode('lib_path')
  140.                         ->info('The path of the file were to place the javascript library sources used by the dumped enums.')
  141.                         ->example('%kernel.project_dir%/assets/js/lib/enum.js')
  142.                         ->defaultNull()
  143.                     ->end()
  144.                     ->arrayNode('paths')
  145.                         ->defaultValue([])
  146.                         ->info('Path where to generate the javascript enums per enum class')
  147.                         ->example(['App\Enum\SimpleEnum' => '"common/SimpleEnum.js"'])
  148.                         ->useAttributeAsKey('class')
  149.                         ->validate()
  150.                             ->ifTrue(static function (array $v): bool {return self::hasNonEnumKeys($v); })
  151.                             ->then(static function (array $v) { self::throwsNonEnumKeysException($v); })
  152.                         ->end()
  153.                         ->scalarPrototype()->end()
  154.                     ->end()
  155.                 ->end()
  156.             ->end()
  157.         ->end();
  158.     }
  159.     private static function hasNonEnumKeys(array $values): bool
  160.     {
  161.         $classes array_column($values'class');
  162.         foreach ($classes as $class) {
  163.             if (!is_a($classEnumInterface::class, true)) {
  164.                 return true;
  165.             }
  166.         }
  167.         return false;
  168.     }
  169.     private static function throwsNonEnumKeysException(array $values)
  170.     {
  171.         $classes array_column($values'class');
  172.         $invalids = [];
  173.         foreach ($classes as $class) {
  174.             if (!is_a($classEnumInterface::class, true)) {
  175.                 $invalids[] = $class;
  176.             }
  177.         }
  178.         throw new \InvalidArgumentException(sprintf(
  179.             'Invalid classes %s. Expected instances of "%s"',
  180.             json_encode($invalids),
  181.             EnumInterface::class
  182.         ));
  183.     }
  184. }