vendor/overblog/graphql-bundle/src/DependencyInjection/TypesConfiguration.php line 33

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Overblog\GraphQLBundle\DependencyInjection;
  4. use Overblog\GraphQLBundle\Config;
  5. use Overblog\GraphQLBundle\Config\Processor\InheritanceProcessor;
  6. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  7. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  8. use Symfony\Component\Config\Definition\ConfigurationInterface;
  9. use function array_keys;
  10. use function array_map;
  11. use function implode;
  12. use function in_array;
  13. use function is_array;
  14. use function is_string;
  15. use function preg_match;
  16. use function sprintf;
  17. use function str_replace;
  18. class TypesConfiguration implements ConfigurationInterface
  19. {
  20. private static array $types = [
  21. 'object',
  22. 'enum',
  23. 'interface',
  24. 'union',
  25. 'input-object',
  26. 'custom-scalar',
  27. ];
  28. public function getConfigTreeBuilder(): TreeBuilder
  29. {
  30. $treeBuilder = new TreeBuilder('overblog_graphql_types');
  31. /** @var ArrayNodeDefinition $rootNode */
  32. $rootNode = $treeBuilder->getRootNode();
  33. $configTypeKeys = array_map(fn ($type) => $this->normalizedConfigTypeKey($type), self::$types);
  34. $this->addBeforeNormalization($rootNode);
  35. // @phpstan-ignore-next-line
  36. $rootNode
  37. ->useAttributeAsKey('name')
  38. ->prototype('array')
  39. // config is the unique config entry allowed
  40. ->beforeNormalization()
  41. ->ifTrue(function ($v) use ($configTypeKeys) {
  42. if (!empty($v) && is_array($v)) {
  43. $keys = array_keys($v);
  44. foreach ($configTypeKeys as $configTypeKey) {
  45. if (in_array($configTypeKey, $keys)) {
  46. return true;
  47. }
  48. }
  49. }
  50. return false;
  51. })
  52. ->thenInvalid(
  53. sprintf(
  54. 'Don\'t use internal config keys %s, replace it by "config" instead.',
  55. implode(', ', $configTypeKeys)
  56. )
  57. )
  58. ->end()
  59. // config is renamed _{TYPE}_config
  60. ->beforeNormalization()
  61. ->ifTrue(fn ($v) => isset($v['type']) && is_string($v['type']))
  62. ->then(function ($v) {
  63. $key = $this->normalizedConfigTypeKey($v['type']);
  64. if (empty($v[$key])) {
  65. $v[$key] = $v['config'] ?? [];
  66. }
  67. unset($v['config']);
  68. return $v;
  69. })
  70. ->end()
  71. ->cannotBeOverwritten()
  72. ->children()
  73. ->scalarNode('class_name')
  74. ->isRequired()
  75. ->validate()
  76. ->ifTrue(fn ($name) => !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name))
  77. ->thenInvalid('A valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores.')
  78. ->end()
  79. ->end()
  80. ->enumNode('type')->values(self::$types)->isRequired()->end()
  81. ->arrayNode(InheritanceProcessor::INHERITS_KEY)
  82. ->prototype('scalar')->info('Types to inherit of.')->end()
  83. ->end()
  84. ->booleanNode('decorator')->info('Decorator will not be generated.')->defaultFalse()->end()
  85. ->append(Config\ObjectTypeDefinition::create()->getDefinition())
  86. ->append(Config\EnumTypeDefinition::create()->getDefinition())
  87. ->append(Config\InterfaceTypeDefinition::create()->getDefinition())
  88. ->append(Config\UnionTypeDefinition::create()->getDefinition())
  89. ->append(Config\InputObjectTypeDefinition::create()->getDefinition())
  90. ->append(Config\CustomScalarTypeDefinition::create()->getDefinition())
  91. ->variableNode('config')->end()
  92. ->end()
  93. // _{TYPE}_config is renamed config
  94. ->validate()
  95. ->ifTrue(fn ($v) => isset($v[$this->normalizedConfigTypeKey($v['type'])]))
  96. ->then(function ($v) {
  97. $key = $this->normalizedConfigTypeKey($v['type']);
  98. $v['config'] = $v[$key];
  99. unset($v[$key]);
  100. return $v;
  101. })
  102. ->end()
  103. ->end();
  104. return $treeBuilder;
  105. }
  106. private function addBeforeNormalization(ArrayNodeDefinition $node): void
  107. {
  108. $node
  109. // process beforeNormalization (should be execute after relay normalization)
  110. ->beforeNormalization()
  111. ->ifTrue(fn ($types) => is_array($types))
  112. ->then(fn ($types) => Config\Processor::process($types, Config\Processor::BEFORE_NORMALIZATION))
  113. ->end()
  114. ;
  115. }
  116. private function normalizedConfigTypeKey(string $type): string
  117. {
  118. return '_'.str_replace('-', '_', $type).'_config';
  119. }
  120. }