|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace Ruudk\GraphQLCodeGenerator\Executor; |
| 6 | + |
| 7 | +use JsonException; |
| 8 | +use LogicException; |
| 9 | +use Ruudk\GraphQLCodeGenerator\Config; |
| 10 | +use Ruudk\GraphQLCodeGenerator\Generator\DataClassGenerator; |
| 11 | +use Ruudk\GraphQLCodeGenerator\Generator\EnumTypeGenerator; |
| 12 | +use Ruudk\GraphQLCodeGenerator\Generator\ErrorClassGenerator; |
| 13 | +use Ruudk\GraphQLCodeGenerator\Generator\ExceptionClassGenerator; |
| 14 | +use Ruudk\GraphQLCodeGenerator\Generator\InputTypeGenerator; |
| 15 | +use Ruudk\GraphQLCodeGenerator\Generator\NodeNotFoundExceptionGenerator; |
| 16 | +use Ruudk\GraphQLCodeGenerator\Generator\OperationClassGenerator; |
| 17 | +use Ruudk\GraphQLCodeGenerator\Planner\OperationPlan; |
| 18 | +use Ruudk\GraphQLCodeGenerator\Planner\Plan\DataClassPlan; |
| 19 | +use Ruudk\GraphQLCodeGenerator\Planner\Plan\EnumClassPlan; |
| 20 | +use Ruudk\GraphQLCodeGenerator\Planner\Plan\InputClassPlan; |
| 21 | +use Ruudk\GraphQLCodeGenerator\Planner\Plan\NodeNotFoundExceptionPlan; |
| 22 | +use Ruudk\GraphQLCodeGenerator\Planner\PlannerResult; |
| 23 | +use Ruudk\GraphQLCodeGenerator\TypeInitializer\BackedEnumTypeInitializer; |
| 24 | +use Ruudk\GraphQLCodeGenerator\TypeInitializer\CollectionTypeInitializer; |
| 25 | +use Ruudk\GraphQLCodeGenerator\TypeInitializer\DelegatingTypeInitializer; |
| 26 | +use Ruudk\GraphQLCodeGenerator\TypeInitializer\NullableTypeInitializer; |
| 27 | +use Ruudk\GraphQLCodeGenerator\TypeInitializer\ObjectTypeInitializer; |
| 28 | +use Ruudk\GraphQLCodeGenerator\TypeMapper; |
| 29 | +use Symfony\Component\TypeInfo\Type as SymfonyType; |
| 30 | + |
| 31 | +final class PlanExecutor |
| 32 | +{ |
| 33 | + private readonly DataClassGenerator $dataClassGenerator; |
| 34 | + private readonly EnumTypeGenerator $enumTypeGenerator; |
| 35 | + private readonly OperationClassGenerator $operationClassGenerator; |
| 36 | + private readonly ErrorClassGenerator $errorClassGenerator; |
| 37 | + private readonly ExceptionClassGenerator $exceptionClassGenerator; |
| 38 | + private readonly InputTypeGenerator $inputTypeGenerator; |
| 39 | + private readonly NodeNotFoundExceptionGenerator $nodeNotFoundExceptionGenerator; |
| 40 | + |
| 41 | + public function __construct( |
| 42 | + Config $config, |
| 43 | + ) { |
| 44 | + // Initialize type initializer |
| 45 | + $typeInitializer = new DelegatingTypeInitializer( |
| 46 | + new NullableTypeInitializer(), |
| 47 | + new CollectionTypeInitializer(), |
| 48 | + new BackedEnumTypeInitializer($config->addUnknownCaseToEnums, $config->namespace), |
| 49 | + new ObjectTypeInitializer(), |
| 50 | + ...$config->typeInitializers, |
| 51 | + ); |
| 52 | + |
| 53 | + // Initialize scalars |
| 54 | + $scalars = [ |
| 55 | + 'ID' => SymfonyType::string(), |
| 56 | + 'String' => SymfonyType::string(), |
| 57 | + 'Int' => SymfonyType::int(), |
| 58 | + 'Float' => SymfonyType::float(), |
| 59 | + 'Boolean' => SymfonyType::bool(), |
| 60 | + ...$config->scalars, |
| 61 | + ]; |
| 62 | + |
| 63 | + // Initialize enum types |
| 64 | + $enumTypes = $config->enumTypes; |
| 65 | + |
| 66 | + // Initialize input object types |
| 67 | + $inputObjectTypes = $config->inputObjectTypes; |
| 68 | + |
| 69 | + // Initialize object types |
| 70 | + $objectTypes = $config->objectTypes; |
| 71 | + |
| 72 | + // Create TypeMapper |
| 73 | + $typeMapper = new TypeMapper( |
| 74 | + $scalars, |
| 75 | + $enumTypes, |
| 76 | + $inputObjectTypes, |
| 77 | + $objectTypes, |
| 78 | + ); |
| 79 | + |
| 80 | + // Initialize all generators |
| 81 | + $this->dataClassGenerator = new DataClassGenerator($config, $typeInitializer); |
| 82 | + $this->enumTypeGenerator = new EnumTypeGenerator($config); |
| 83 | + $this->operationClassGenerator = new OperationClassGenerator($config); |
| 84 | + $this->errorClassGenerator = new ErrorClassGenerator($config); |
| 85 | + $this->exceptionClassGenerator = new ExceptionClassGenerator($config); |
| 86 | + $this->inputTypeGenerator = new InputTypeGenerator($config, $typeMapper); |
| 87 | + $this->nodeNotFoundExceptionGenerator = new NodeNotFoundExceptionGenerator($config); |
| 88 | + } |
| 89 | + |
| 90 | + /** |
| 91 | + * @throws LogicException |
| 92 | + * @throws JsonException |
| 93 | + * @return array<string, string> |
| 94 | + */ |
| 95 | + public function execute(PlannerResult $plan) : array |
| 96 | + { |
| 97 | + $files = []; |
| 98 | + |
| 99 | + foreach ($plan->classes as $relativePath => $class) { |
| 100 | + $files[$relativePath] = $this->generateClass($class); |
| 101 | + } |
| 102 | + |
| 103 | + foreach ($plan->operations as $operation) { |
| 104 | + $files = array_merge($files, $this->generateOperation($operation)); |
| 105 | + } |
| 106 | + |
| 107 | + return $files; |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * @throws LogicException |
| 112 | + */ |
| 113 | + private function generateClass(object $class) : string |
| 114 | + { |
| 115 | + return match ($class::class) { |
| 116 | + DataClassPlan::class => $this->dataClassGenerator->generate($class), |
| 117 | + |
| 118 | + EnumClassPlan::class => $this->enumTypeGenerator->generate($class), |
| 119 | + |
| 120 | + InputClassPlan::class => $this->inputTypeGenerator->generate($class), |
| 121 | + |
| 122 | + NodeNotFoundExceptionPlan::class => $this->nodeNotFoundExceptionGenerator->generate(), |
| 123 | + |
| 124 | + default => throw new LogicException('Unknown class type: ' . $class::class), |
| 125 | + }; |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * @throws JsonException |
| 130 | + * @return array<string, string> |
| 131 | + */ |
| 132 | + private function generateOperation(OperationPlan $operation) : array |
| 133 | + { |
| 134 | + $files = []; |
| 135 | + |
| 136 | + // Generate operation class |
| 137 | + $files[$operation->operationClass->relativePath] = $this->operationClassGenerator->generate( |
| 138 | + $operation->operationClass, |
| 139 | + ); |
| 140 | + |
| 141 | + // Generate error class |
| 142 | + $files[$operation->errorClass->relativePath] = $this->errorClassGenerator->generate( |
| 143 | + $operation->errorClass, |
| 144 | + ); |
| 145 | + |
| 146 | + // Generate exception class |
| 147 | + $files[$operation->exceptionClass->relativePath] = $this->exceptionClassGenerator->generate( |
| 148 | + $operation->exceptionClass, |
| 149 | + ); |
| 150 | + |
| 151 | + return $files; |
| 152 | + } |
| 153 | +} |
0 commit comments