Skip to content

Commit 255bf3a

Browse files
committed
Make parsers configurable
1 parent 3d62d90 commit 255bf3a

File tree

2 files changed

+63
-15
lines changed

2 files changed

+63
-15
lines changed

src/DependencyInjection/Compiler/ConfigParserPass.php

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,34 @@
3636

3737
class ConfigParserPass implements CompilerPassInterface
3838
{
39+
public const TYPE_YAML = 'yaml';
40+
public const TYPE_GRAPHQL = 'graphql';
41+
public const TYPE_ANNOTATION = 'annotation';
42+
public const TYPE_ATTRIBUTE = 'attribute';
43+
44+
public const SUPPORTED_TYPES = [
45+
self::TYPE_YAML,
46+
self::TYPE_GRAPHQL,
47+
self::TYPE_ANNOTATION,
48+
self::TYPE_ATTRIBUTE,
49+
];
50+
3951
public const SUPPORTED_TYPES_EXTENSIONS = [
40-
'yaml' => '{yaml,yml}',
41-
'graphql' => '{graphql,graphqls}',
42-
'annotation' => 'php',
43-
'attribute' => 'php',
52+
self::TYPE_YAML => '{yaml,yml}',
53+
self::TYPE_GRAPHQL => '{graphql,graphqls}',
54+
self::TYPE_ANNOTATION => 'php',
55+
self::TYPE_ATTRIBUTE => 'php',
4456
];
4557

4658
/**
59+
* @deprecated They are going to be configurable.
4760
* @var array<string, class-string<ParserInterface|PreParserInterface>>
4861
*/
4962
public const PARSERS = [
50-
'yaml' => YamlParser::class,
51-
'graphql' => GraphQLParser::class,
52-
'annotation' => AnnotationParser::class,
53-
'attribute' => AttributeParser::class,
63+
self::TYPE_YAML => YamlParser::class,
64+
self::TYPE_GRAPHQL => GraphQLParser::class,
65+
self::TYPE_ANNOTATION => AnnotationParser::class,
66+
self::TYPE_ATTRIBUTE => AttributeParser::class,
5467
];
5568

5669
private const DEFAULT_CONFIG = [
@@ -64,6 +77,7 @@ class ConfigParserPass implements CompilerPassInterface
6477
'types' => [],
6578
],
6679
],
80+
'parsers' => self::PARSERS,
6781
];
6882

6983
/**
@@ -93,6 +107,10 @@ private function getConfigs(ContainerBuilder $container): array
93107
$config = $container->getParameterBag()->resolveValue($container->getParameter('overblog_graphql.config'));
94108
$container->getParameterBag()->remove('overblog_graphql.config');
95109
$container->setParameter($this->getAlias().'.classes_map', []);
110+
111+
// use default value if needed
112+
$config = array_replace_recursive(self::DEFAULT_CONFIG, $config);
113+
96114
$typesMappings = $this->mappingConfig($config, $container);
97115
// reset treated files
98116
$this->treatedFiles = [];
@@ -103,7 +121,7 @@ private function getConfigs(ContainerBuilder $container): array
103121
// Pre-parse all files
104122
AnnotationParser::reset($config);
105123
AttributeParser::reset($config);
106-
$typesNeedPreParsing = $this->typesNeedPreParsing();
124+
$typesNeedPreParsing = $this->typesNeedPreParsing($config['parsers']);
107125
foreach ($typesMappings as $params) {
108126
if ($typesNeedPreParsing[$params['type']]) {
109127
$this->parseTypeConfigFiles($params['type'], $params['files'], $container, $config, true);
@@ -122,10 +140,15 @@ private function getConfigs(ContainerBuilder $container): array
122140
return $flattenTypeConfig;
123141
}
124142

125-
private function typesNeedPreParsing(): array
143+
/**
144+
* @param array<string,string> $parsers
145+
*
146+
* @return array<string,bool>
147+
*/
148+
private function typesNeedPreParsing(array $parsers): array
126149
{
127150
$needPreParsing = [];
128-
foreach (self::PARSERS as $type => $className) {
151+
foreach ($parsers as $type => $className) {
129152
$needPreParsing[$type] = is_a($className, PreParserInterface::class, true);
130153
}
131154

@@ -152,7 +175,7 @@ private function parseTypeConfigFiles(string $type, iterable $files, ContainerBu
152175
continue;
153176
}
154177

155-
$parser = [self::PARSERS[$type], $method];
178+
$parser = [$configs['parsers'][$type], $method];
156179
if (is_callable($parser)) {
157180
$config[] = ($parser)($file, $container, $configs);
158181
}
@@ -176,9 +199,6 @@ private function checkTypesDuplication(array $typeConfigs): void
176199

177200
private function mappingConfig(array $config, ContainerBuilder $container): array
178201
{
179-
// use default value if needed
180-
$config = array_replace_recursive(self::DEFAULT_CONFIG, $config);
181-
182202
$mappingConfig = $config['definitions']['mappings'];
183203
$typesMappings = $mappingConfig['types'];
184204

src/DependencyInjection/Configuration.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
88
use GraphQL\Validator\Rules\QueryComplexity;
99
use GraphQL\Validator\Rules\QueryDepth;
10+
use Overblog\GraphQLBundle\Config\Parser\ParserInterface;
1011
use Overblog\GraphQLBundle\Definition\Argument;
1112
use Overblog\GraphQLBundle\DependencyInjection\Compiler\ConfigParserPass;
1213
use Overblog\GraphQLBundle\Error\ErrorHandler;
@@ -57,6 +58,7 @@ public function getConfigTreeBuilder(): TreeBuilder
5758
->append($this->securitySection())
5859
->append($this->doctrineSection())
5960
->append($this->profilerSection())
61+
->append($this->parsersSection())
6062
->end();
6163

6264
return $treeBuilder;
@@ -318,6 +320,32 @@ private function doctrineSection(): ArrayNodeDefinition
318320
return $node;
319321
}
320322

323+
private function parsersSection(): ArrayNodeDefinition
324+
{
325+
/** @var ArrayNodeDefinition $node */
326+
$node = (new TreeBuilder('parsers'))->getRootNode();
327+
$node->useAttributeAsKey('name');
328+
329+
$parserPrototype = $node->scalarPrototype();
330+
$parserPrototype->cannotBeEmpty();
331+
$parserPrototype->validate()
332+
->ifTrue(static function (string $x): bool {
333+
return !is_subclass_of($x, ParserInterface::class, true);
334+
})
335+
->thenInvalid(sprintf('Parser MUST implement "%s', ParserInterface::class));
336+
337+
$node->validate()
338+
->ifTrue(static function (array $x): bool {
339+
return (bool) array_diff(array_keys($x), ConfigParserPass::SUPPORTED_TYPES);
340+
})
341+
->then(static function (array $x) {
342+
$types = implode(', ', array_diff(array_keys($x), ConfigParserPass::SUPPORTED_TYPES));
343+
throw new \InvalidArgumentException(sprintf('Configured parsers for not supported types: %s', $types));
344+
});
345+
346+
return $node;
347+
}
348+
321349
private function profilerSection(): ArrayNodeDefinition
322350
{
323351
$builder = new TreeBuilder('profiler');

0 commit comments

Comments
 (0)