We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
Complex classes like AnnotationParser often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AnnotationParser, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | class AnnotationParser implements PreParserInterface |
||
| 15 | { |
||
| 16 | public const CLASSESMAP_CONTAINER_PARAMETER = 'overblog_graphql_types.classes_map'; |
||
| 17 | |||
| 18 | private static $annotationReader = null; |
||
| 19 | private static $classesMap = []; |
||
| 20 | private static $providers = []; |
||
| 21 | private static $doctrineMapping = []; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * {@inheritdoc} |
||
| 25 | * |
||
| 26 | * @throws \ReflectionException |
||
| 27 | * @throws InvalidArgumentException |
||
| 28 | */ |
||
| 29 | 14 | public static function preParse(\SplFileInfo $file, ContainerBuilder $container, array $configs = []): void |
|
| 33 | |||
| 34 | /** |
||
| 35 | * {@inheritdoc} |
||
| 36 | * |
||
| 37 | * @throws \ReflectionException |
||
| 38 | * @throws InvalidArgumentException |
||
| 39 | */ |
||
| 40 | 14 | public static function parse(\SplFileInfo $file, ContainerBuilder $container, array $configs = []): array |
|
| 44 | |||
| 45 | /** |
||
| 46 | * Clear the Annotation parser. |
||
| 47 | */ |
||
| 48 | 14 | public static function clear(): void |
|
| 54 | |||
| 55 | /** |
||
| 56 | * Process a file. |
||
| 57 | * |
||
| 58 | * @param \SplFileInfo $file |
||
| 59 | * @param ContainerBuilder $container |
||
| 60 | * @param bool $resolveClassMap |
||
| 61 | * |
||
| 62 | * @throws \ReflectionException |
||
| 63 | * @throws InvalidArgumentException |
||
| 64 | */ |
||
| 65 | 14 | public static function proccessFile(\SplFileInfo $file, ContainerBuilder $container, array $configs, bool $resolveClassMap = false): array |
|
| 66 | { |
||
| 67 | 14 | self::$doctrineMapping = $configs['doctrine']['types_mapping']; |
|
| 68 | |||
| 69 | 14 | $rootQueryType = $configs['definitions']['schema']['default']['query'] ?? false; |
|
| 70 | 14 | $rootMutationType = $configs['definitions']['schema']['default']['mutation'] ?? false; |
|
| 71 | |||
| 72 | 14 | $container->addResource(new FileResource($file->getRealPath())); |
|
| 73 | |||
| 74 | 14 | if (!$resolveClassMap) { |
|
| 75 | 14 | $container->setParameter(self::CLASSESMAP_CONTAINER_PARAMETER, self::$classesMap); |
|
| 76 | } |
||
| 77 | |||
| 78 | try { |
||
| 79 | 14 | $fileContent = \file_get_contents($file->getRealPath()); |
|
| 80 | |||
| 81 | 14 | $shortClassName = \substr($file->getFilename(), 0, -4); |
|
| 82 | 14 | if (\preg_match('#namespace (.+);#', $fileContent, $namespace)) { |
|
| 83 | 14 | $className = $namespace[1].'\\'.$shortClassName; |
|
| 84 | 14 | $namespace = $namespace[1]; |
|
| 85 | } else { |
||
| 86 | $className = $shortClassName; |
||
| 87 | } |
||
| 88 | |||
| 89 | 14 | $reflexionEntity = new \ReflectionClass($className); |
|
| 90 | |||
| 91 | 14 | $classAnnotations = self::getAnnotationReader()->getClassAnnotations($reflexionEntity); |
|
| 92 | |||
| 93 | 14 | $properties = []; |
|
| 94 | 14 | foreach ($reflexionEntity->getProperties() as $property) { |
|
| 95 | 14 | $properties[$property->getName()] = ['property' => $property, 'annotations' => self::getAnnotationReader()->getPropertyAnnotations($property)]; |
|
| 96 | } |
||
| 97 | |||
| 98 | 14 | $methods = []; |
|
| 99 | 14 | foreach ($reflexionEntity->getMethods() as $method) { |
|
| 100 | 14 | $methods[$method->getName()] = ['method' => $method, 'annotations' => self::getAnnotationReader()->getMethodAnnotations($method)]; |
|
|
|
|||
| 101 | } |
||
| 102 | |||
| 103 | 14 | $gqlTypes = []; |
|
| 104 | |||
| 105 | 14 | foreach ($classAnnotations as $classAnnotation) { |
|
| 106 | 14 | $gqlConfiguration = $gqlType = $gqlName = false; |
|
| 107 | |||
| 108 | switch (true) { |
||
| 109 | 14 | case $classAnnotation instanceof GQL\Type: |
|
| 110 | 14 | $gqlType = 'type'; |
|
| 111 | 14 | $gqlName = $classAnnotation->name ?: $shortClassName; |
|
| 112 | 14 | if (!$resolveClassMap) { |
|
| 113 | 14 | $isRootQuery = ($rootQueryType && $gqlName === $rootQueryType); |
|
| 114 | 14 | $isRootMutation = ($rootMutationType && $gqlName === $rootMutationType); |
|
| 115 | 14 | $currentValue = ($isRootQuery || $isRootMutation) ? \sprintf("service('%s')", self::formatNamespaceForExpression($className)) : 'value'; |
|
| 116 | |||
| 117 | 14 | $gqlConfiguration = self::getGraphqlType($classAnnotation, $classAnnotations, $properties, $methods, $namespace, $currentValue); |
|
| 118 | 14 | $providerFields = self::getGraphqlFieldsFromProviders($namespace, $className, $isRootMutation ? 'Mutation' : 'Query', $gqlName, ($isRootQuery || $isRootMutation)); |
|
| 119 | 14 | $gqlConfiguration['config']['fields'] = $providerFields + $gqlConfiguration['config']['fields']; |
|
| 120 | } |
||
| 121 | 14 | break; |
|
| 122 | 14 | case $classAnnotation instanceof GQL\Input: |
|
| 123 | 14 | $gqlType = 'input'; |
|
| 124 | 14 | $gqlName = $classAnnotation->name ?: self::suffixName($shortClassName, 'Input'); |
|
| 125 | 14 | if (!$resolveClassMap) { |
|
| 126 | 14 | $gqlConfiguration = self::getGraphqlInput($classAnnotation, $classAnnotations, $properties, $namespace); |
|
| 127 | } |
||
| 128 | 14 | break; |
|
| 129 | 14 | case $classAnnotation instanceof GQL\Scalar: |
|
| 130 | 14 | $gqlType = 'scalar'; |
|
| 131 | 14 | if (!$resolveClassMap) { |
|
| 132 | 14 | $gqlConfiguration = self::getGraphqlScalar($className, $classAnnotation, $classAnnotations); |
|
| 133 | } |
||
| 134 | 14 | break; |
|
| 135 | 14 | case $classAnnotation instanceof GQL\Enum: |
|
| 136 | 14 | $gqlType = 'enum'; |
|
| 137 | 14 | if (!$resolveClassMap) { |
|
| 138 | 14 | $gqlConfiguration = self::getGraphqlEnum($classAnnotation, $classAnnotations, $reflexionEntity->getConstants()); |
|
| 139 | } |
||
| 140 | 14 | break; |
|
| 141 | 14 | case $classAnnotation instanceof GQL\Union: |
|
| 142 | 14 | $gqlType = 'union'; |
|
| 143 | 14 | if (!$resolveClassMap) { |
|
| 144 | 14 | $gqlConfiguration = self::getGraphqlUnion($className, $classAnnotation, $classAnnotations, $methods); |
|
| 145 | } |
||
| 146 | 14 | break; |
|
| 147 | 14 | case $classAnnotation instanceof GQL\TypeInterface: |
|
| 148 | 14 | $gqlType = 'interface'; |
|
| 149 | 14 | if (!$resolveClassMap) { |
|
| 150 | 14 | $gqlConfiguration = self::getGraphqlInterface($classAnnotation, $classAnnotations, $properties, $methods, $namespace); |
|
| 151 | } |
||
| 152 | 14 | break; |
|
| 153 | 14 | case $classAnnotation instanceof GQL\Provider: |
|
| 154 | 14 | if ($resolveClassMap) { |
|
| 155 | 14 | self::$providers[$className] = ['annotation' => $classAnnotation, 'methods' => $methods]; |
|
| 156 | } |
||
| 157 | 14 | break; |
|
| 158 | default: |
||
| 159 | 14 | continue 2; |
|
| 160 | } |
||
| 161 | |||
| 162 | 14 | if ($gqlType) { |
|
| 163 | 14 | if (!$gqlName) { |
|
| 164 | 14 | $gqlName = $classAnnotation->name ?: $shortClassName; |
|
| 165 | } |
||
| 166 | |||
| 167 | 14 | if ($resolveClassMap) { |
|
| 168 | 14 | if (isset(self::$classesMap[$gqlName])) { |
|
| 169 | 1 | throw new InvalidArgumentException(\sprintf('The GraphQL type "%s" has already been registered in class "%s"', $gqlName, self::$classesMap[$gqlName]['class'])); |
|
| 170 | } |
||
| 171 | 14 | self::$classesMap[$gqlName] = ['type' => $gqlType, 'class' => $className]; |
|
| 172 | } else { |
||
| 173 | 14 | $gqlTypes = [$gqlName => $gqlConfiguration] + $gqlTypes; |
|
| 174 | } |
||
| 175 | } |
||
| 176 | } |
||
| 177 | |||
| 178 | 14 | return $resolveClassMap ? self::$classesMap : $gqlTypes; |
|
| 179 | 5 | } catch (\InvalidArgumentException $e) { |
|
| 180 | 5 | throw new InvalidArgumentException(\sprintf('Failed to parse GraphQL annotations from file "%s".', $file), $e->getCode(), $e); |
|
| 181 | } |
||
| 182 | } |
||
| 183 | |||
| 184 | /** |
||
| 185 | * Retrieve annotation reader. |
||
| 186 | * |
||
| 187 | * @return AnnotationReader |
||
| 188 | */ |
||
| 189 | 14 | private static function getAnnotationReader() |
|
| 203 | |||
| 204 | /** |
||
| 205 | * Create a GraphQL Type configuration from annotations on class, properties and methods. |
||
| 206 | * |
||
| 207 | * @param GQL\Type $typeAnnotation |
||
| 208 | * @param array $classAnnotations |
||
| 209 | * @param array $properties |
||
| 210 | * @param array $methods |
||
| 211 | * @param string $namespace |
||
| 212 | * @param string $currentValue |
||
| 213 | * |
||
| 214 | * @return array |
||
| 215 | */ |
||
| 216 | 14 | private static function getGraphqlType(GQL\Type $typeAnnotation, array $classAnnotations, array $properties, array $methods, string $namespace, string $currentValue) |
|
| 246 | |||
| 247 | /** |
||
| 248 | * Create a GraphQL Interface type configuration from annotations on properties. |
||
| 249 | * |
||
| 250 | * @param string $shortClassName |
||
| 251 | * @param GQL\Interface $interfaceAnnotation |
||
| 252 | * @param array $properties |
||
| 253 | * @param array $methods |
||
| 254 | * @param string $namespace |
||
| 255 | * |
||
| 256 | * @return array |
||
| 257 | */ |
||
| 258 | 14 | private static function getGraphqlInterface(GQL\TypeInterface $interfaceAnnotation, array $classAnnotations, array $properties, array $methods, string $namespace) |
|
| 272 | |||
| 273 | /** |
||
| 274 | * Create a GraphQL Input type configuration from annotations on properties. |
||
| 275 | * |
||
| 276 | * @param string $shortClassName |
||
| 277 | * @param GQL\Input $inputAnnotation |
||
| 278 | * @param array $properties |
||
| 279 | * @param string $namespace |
||
| 280 | * |
||
| 281 | * @return array |
||
| 282 | */ |
||
| 283 | 14 | private static function getGraphqlInput(GQL\Input $inputAnnotation, array $classAnnotations, array $properties, string $namespace) |
|
| 293 | |||
| 294 | /** |
||
| 295 | * Get a Graphql scalar configuration from given scalar annotation. |
||
| 296 | * |
||
| 297 | * @param string $shortClassName |
||
| 298 | * @param string $className |
||
| 299 | * @param GQL\Scalar $scalarAnnotation |
||
| 300 | * @param array $classAnnotations |
||
| 301 | * |
||
| 302 | * @return array |
||
| 303 | */ |
||
| 304 | 14 | private static function getGraphqlScalar(string $className, GQL\Scalar $scalarAnnotation, array $classAnnotations) |
|
| 322 | |||
| 323 | /** |
||
| 324 | * Get a Graphql Enum configuration from given enum annotation. |
||
| 325 | * |
||
| 326 | * @param string $shortClassName |
||
| 327 | * @param GQL\Enum $enumAnnotation |
||
| 328 | * @param array $classAnnotations |
||
| 329 | * @param array $constants |
||
| 330 | * |
||
| 331 | * @return array |
||
| 332 | */ |
||
| 333 | 14 | private static function getGraphqlEnum(GQL\Enum $enumAnnotation, array $classAnnotations, array $constants) |
|
| 362 | |||
| 363 | /** |
||
| 364 | * Get a Graphql Union configuration from given union annotation. |
||
| 365 | * |
||
| 366 | * @param string $className |
||
| 367 | * @param GQL\Union $unionAnnotation |
||
| 368 | * @param array $classAnnotations |
||
| 369 | * @param array $methods |
||
| 370 | * |
||
| 371 | * @return array |
||
| 372 | */ |
||
| 373 | 14 | private static function getGraphqlUnion(string $className, GQL\Union $unionAnnotation, array $classAnnotations, array $methods): array |
|
| 395 | |||
| 396 | /** |
||
| 397 | * Create Graphql fields configuration based on annotations. |
||
| 398 | * |
||
| 399 | * @param string $namespace |
||
| 400 | * @param array $propertiesOrMethods |
||
| 401 | * @param bool $isInput |
||
| 402 | * @param bool $isMethod |
||
| 403 | * @param string $currentValue |
||
| 404 | * |
||
| 405 | * @return array |
||
| 406 | */ |
||
| 407 | 14 | private static function getGraphqlFieldsFromAnnotations(string $namespace, array $propertiesOrMethods, bool $isInput = false, bool $isMethod = false, string $currentValue = 'value', string $fieldAnnotationName = 'Field'): array |
|
| 408 | { |
||
| 409 | 14 | $fields = []; |
|
| 410 | 14 | foreach ($propertiesOrMethods as $target => $config) { |
|
| 411 | 14 | $annotations = $config['annotations']; |
|
| 412 | 14 | $method = $isMethod ? $config['method'] : false; |
|
| 413 | 14 | $property = $isMethod ? false : $config['property']; |
|
| 414 | |||
| 415 | 14 | $fieldAnnotation = self::getFirstAnnotationMatching($annotations, \sprintf('Overblog\GraphQLBundle\Annotation\%s', $fieldAnnotationName)); |
|
| 416 | 14 | $accessAnnotation = self::getFirstAnnotationMatching($annotations, 'Overblog\GraphQLBundle\Annotation\Access'); |
|
| 417 | 14 | $publicAnnotation = self::getFirstAnnotationMatching($annotations, 'Overblog\GraphQLBundle\Annotation\IsPublic'); |
|
| 418 | |||
| 419 | 14 | if (!$fieldAnnotation) { |
|
| 420 | if ($accessAnnotation || $publicAnnotation) { |
||
| 421 | throw new InvalidArgumentException(\sprintf('The annotations "@Access" and/or "@Visible" defined on "%s" are only usable in addition of annotation "@Field"', $target)); |
||
| 422 | } |
||
| 423 | continue; |
||
| 424 | } |
||
| 425 | |||
| 426 | 14 | if ($isMethod && !$method->isPublic()) { |
|
| 427 | throw new InvalidArgumentException(\sprintf('The Annotation "@Field" can only be applied to public method. The method "%s" is not public.', $target)); |
||
| 428 | } |
||
| 429 | |||
| 430 | // Ignore field with resolver when the type is an Input |
||
| 431 | 14 | if ($fieldAnnotation->resolve && $isInput) { |
|
| 432 | continue; |
||
| 433 | } |
||
| 434 | |||
| 435 | 14 | $fieldName = $target; |
|
| 436 | 14 | $fieldType = $fieldAnnotation->type; |
|
| 437 | 14 | $fieldConfiguration = []; |
|
| 438 | 14 | if ($fieldType) { |
|
| 439 | 14 | $resolvedType = self::resolveClassFromType($fieldType); |
|
| 440 | 14 | if ($resolvedType) { |
|
| 441 | 14 | if ($isInput && !\in_array($resolvedType['type'], ['input', 'scalar', 'enum'])) { |
|
| 442 | throw new InvalidArgumentException(\sprintf('The type "%s" on "%s" is a "%s" not valid on an Input @Field. Only Input, Scalar and Enum are allowed.', $fieldType, $target, $resolvedType['type'])); |
||
| 443 | } |
||
| 444 | } |
||
| 445 | |||
| 446 | 14 | $fieldConfiguration['type'] = $fieldType; |
|
| 447 | } |
||
| 448 | |||
| 449 | 14 | $fieldConfiguration = self::getDescriptionConfiguration($annotations, true) + $fieldConfiguration; |
|
| 450 | |||
| 451 | 14 | if (!$isInput) { |
|
| 452 | 14 | $args = []; |
|
| 453 | 14 | $args = self::getArgs($fieldAnnotation->args, $isMethod && !$fieldAnnotation->argsBuilder ? $method : null); |
|
| 454 | |||
| 455 | 14 | if (!empty($args)) { |
|
| 456 | 14 | $fieldConfiguration['args'] = $args; |
|
| 457 | } |
||
| 458 | |||
| 459 | 14 | $fieldName = $fieldAnnotation->name ?: $fieldName; |
|
| 460 | |||
| 461 | 14 | if ($fieldAnnotation->resolve) { |
|
| 462 | 14 | $fieldConfiguration['resolve'] = self::formatExpression($fieldAnnotation->resolve); |
|
| 463 | } else { |
||
| 464 | 14 | if ($isMethod) { |
|
| 465 | 14 | $fieldConfiguration['resolve'] = self::formatExpression(\sprintf('call(%s.%s, %s)', $currentValue, $target, self::formatArgsForExpression($args))); |
|
| 466 | } else { |
||
| 467 | 14 | if ($fieldName !== $target || 'value' !== $currentValue) { |
|
| 468 | $fieldConfiguration['resolve'] = self::formatExpression(\sprintf('%s.%s', $currentValue, $target)); |
||
| 469 | } |
||
| 470 | } |
||
| 471 | } |
||
| 472 | |||
| 473 | 14 | if ($fieldAnnotation->argsBuilder) { |
|
| 474 | 14 | if (\is_string($fieldAnnotation->argsBuilder)) { |
|
| 475 | $fieldConfiguration['argsBuilder'] = $fieldAnnotation->argsBuilder; |
||
| 476 | 14 | } elseif (\is_array($fieldAnnotation->argsBuilder)) { |
|
| 477 | 14 | list($builder, $builderConfig) = $fieldAnnotation->argsBuilder; |
|
| 478 | 14 | $fieldConfiguration['argsBuilder'] = ['builder' => $builder, 'config' => $builderConfig]; |
|
| 479 | } else { |
||
| 480 | throw new InvalidArgumentException(\sprintf('The attribute "argsBuilder" on GraphQL annotation "@%s" defined on "%s" must be a string or an array where first index is the builder name and the second is the config.', $fieldAnnotationName, $target)); |
||
| 481 | } |
||
| 482 | } |
||
| 483 | |||
| 484 | 14 | if ($fieldAnnotation->fieldBuilder) { |
|
| 485 | 14 | if (\is_string($fieldAnnotation->fieldBuilder)) { |
|
| 486 | $fieldConfiguration['builder'] = $fieldAnnotation->fieldBuilder; |
||
| 487 | 14 | } elseif (\is_array($fieldAnnotation->fieldBuilder)) { |
|
| 488 | 14 | list($builder, $builderConfig) = $fieldAnnotation->fieldBuilder; |
|
| 489 | 14 | $fieldConfiguration['builder'] = $builder; |
|
| 490 | 14 | $fieldConfiguration['builderConfig'] = $builderConfig ?: []; |
|
| 491 | } else { |
||
| 492 | 14 | throw new InvalidArgumentException(\sprintf('The attribute "argsBuilder" on GraphQL annotation "@%s" defined on "%s" must be a string or an array where first index is the builder name and the second is the config.', $fieldAnnotationName, $target)); |
|
| 493 | } |
||
| 494 | } else { |
||
| 495 | 14 | if (!$fieldType) { |
|
| 496 | 14 | if ($isMethod) { |
|
| 497 | 14 | if ($method->hasReturnType()) { |
|
| 498 | try { |
||
| 499 | 14 | $fieldConfiguration['type'] = self::resolveGraphqlTypeFromReflectionType($method->getReturnType(), 'type'); |
|
| 500 | } catch (\Exception $e) { |
||
| 501 | 14 | throw new InvalidArgumentException(\sprintf('The attribute "type" on GraphQL annotation "@%s" is missing on method "%s" and cannot be auto-guessed from type hint "%s"', $fieldAnnotationName, $target, (string) $method->getReturnType())); |
|
| 502 | } |
||
| 503 | } else { |
||
| 504 | 14 | throw new InvalidArgumentException(\sprintf('The attribute "type" on GraphQL annotation "@%s" is missing on method "%s" and cannot be auto-guessed as there is not return type hint.', $fieldAnnotationName, $target)); |
|
| 505 | } |
||
| 506 | } else { |
||
| 507 | try { |
||
| 508 | 14 | $fieldConfiguration['type'] = self::guessType($namespace, $annotations); |
|
| 509 | 2 | } catch (\Exception $e) { |
|
| 510 | 2 | throw new InvalidArgumentException(\sprintf('The attribute "type" on "@%s" defined on "%s" is required and cannot be auto-guessed : %s.', $fieldAnnotationName, $target, $e->getMessage())); |
|
| 511 | } |
||
| 512 | } |
||
| 513 | } |
||
| 514 | } |
||
| 515 | |||
| 516 | 14 | if ($accessAnnotation) { |
|
| 517 | 14 | $fieldConfiguration['access'] = self::formatExpression($accessAnnotation->value); |
|
| 518 | } |
||
| 519 | |||
| 520 | 14 | if ($publicAnnotation) { |
|
| 521 | 14 | $fieldConfiguration['public'] = self::formatExpression($publicAnnotation->value); |
|
| 522 | } |
||
| 523 | |||
| 524 | 14 | if ($fieldAnnotation->complexity) { |
|
| 525 | 14 | $fieldConfiguration['complexity'] = self::formatExpression($fieldAnnotation->complexity); |
|
| 526 | } |
||
| 527 | } |
||
| 528 | |||
| 529 | 14 | $fields[$fieldName] = $fieldConfiguration; |
|
| 530 | } |
||
| 531 | |||
| 532 | 14 | return $fields; |
|
| 533 | } |
||
| 534 | |||
| 535 | /** |
||
| 536 | * Return fields config from Provider methods. |
||
| 537 | * |
||
| 538 | * @param string $className |
||
| 539 | * @param array $methods |
||
| 540 | * @param bool $isMutation |
||
| 541 | * |
||
| 542 | * @return array |
||
| 543 | */ |
||
| 544 | 14 | private static function getGraphqlFieldsFromProviders(string $namespace, string $className, string $annotationName, string $targetType, bool $isRoot = false) |
|
| 584 | |||
| 585 | /** |
||
| 586 | * Get the config for description & deprecation reason. |
||
| 587 | * |
||
| 588 | * @param array $annotations |
||
| 589 | * @param bool $withDeprecation |
||
| 590 | * |
||
| 591 | * @return array |
||
| 592 | */ |
||
| 593 | 14 | private static function getDescriptionConfiguration(array $annotations, bool $withDeprecation = false) |
|
| 594 | { |
||
| 595 | 14 | $config = []; |
|
| 596 | 14 | $descriptionAnnotation = self::getFirstAnnotationMatching($annotations, 'Overblog\GraphQLBundle\Annotation\Description'); |
|
| 597 | 14 | if ($descriptionAnnotation) { |
|
| 598 | 14 | $config['description'] = $descriptionAnnotation->value; |
|
| 599 | } |
||
| 600 | |||
| 601 | 14 | if ($withDeprecation) { |
|
| 602 | 14 | $deprecatedAnnotation = self::getFirstAnnotationMatching($annotations, 'Overblog\GraphQLBundle\Annotation\Deprecated'); |
|
| 603 | 14 | if ($deprecatedAnnotation) { |
|
| 604 | 14 | $config['deprecationReason'] = $deprecatedAnnotation->value; |
|
| 605 | } |
||
| 606 | } |
||
| 607 | |||
| 608 | 14 | return $config; |
|
| 609 | } |
||
| 610 | |||
| 611 | /** |
||
| 612 | * Get args config from an array of @Arg annotation or by auto-guessing if a method is provided. |
||
| 613 | * |
||
| 614 | * @param array $args |
||
| 615 | * @param \ReflectionMethod $method |
||
| 616 | * |
||
| 617 | * @return array |
||
| 618 | */ |
||
| 619 | 14 | private static function getArgs(array $args = null, \ReflectionMethod $method = null) |
|
| 632 | |||
| 633 | /** |
||
| 634 | * Format an array of args to a list of arguments in an expression. |
||
| 635 | * |
||
| 636 | * @param array $args |
||
| 637 | * |
||
| 638 | * @return string |
||
| 639 | */ |
||
| 640 | 14 | private static function formatArgsForExpression(array $args) |
|
| 649 | |||
| 650 | /** |
||
| 651 | * Format a namespace to be used in an expression (double escape). |
||
| 652 | * |
||
| 653 | * @param string $namespace |
||
| 654 | * |
||
| 655 | * @return string |
||
| 656 | */ |
||
| 657 | 14 | private static function formatNamespaceForExpression(string $namespace) |
|
| 661 | |||
| 662 | /** |
||
| 663 | * Get the first annotation matching given class. |
||
| 664 | * |
||
| 665 | * @param array $annotations |
||
| 666 | * @param string|array $annotationClass |
||
| 667 | * |
||
| 668 | * @return mixed |
||
| 669 | */ |
||
| 670 | 14 | private static function getFirstAnnotationMatching(array $annotations, $annotationClass) |
|
| 686 | |||
| 687 | /** |
||
| 688 | * Format an expression (ie. add "@=" if not set). |
||
| 689 | * |
||
| 690 | * @param string $expression |
||
| 691 | * |
||
| 692 | * @return string |
||
| 693 | */ |
||
| 694 | 14 | private static function formatExpression(string $expression) |
|
| 698 | |||
| 699 | /** |
||
| 700 | * Suffix a name if it is not already. |
||
| 701 | * |
||
| 702 | * @param string $name |
||
| 703 | * @param string $suffix |
||
| 704 | * |
||
| 705 | * @return string |
||
| 706 | */ |
||
| 707 | 14 | private static function suffixName(string $name, string $suffix) |
|
| 711 | |||
| 712 | /** |
||
| 713 | * Try to guess a field type base on is annotations. |
||
| 714 | * |
||
| 715 | * @param string $namespace |
||
| 716 | * @param array $annotations |
||
| 717 | * |
||
| 718 | * @return string|false |
||
| 719 | */ |
||
| 720 | 14 | private static function guessType(string $namespace, array $annotations) |
|
| 765 | |||
| 766 | /** |
||
| 767 | * Resolve a FQN from classname and namespace. |
||
| 768 | * |
||
| 769 | * @param string $className |
||
| 770 | * @param string $namespace |
||
| 771 | * |
||
| 772 | * @return string |
||
| 773 | */ |
||
| 774 | 14 | public static function fullyQualifiedClassName(string $className, string $namespace) |
|
| 782 | |||
| 783 | /** |
||
| 784 | * Resolve a GraphqlType from a doctrine type. |
||
| 785 | * |
||
| 786 | * @param string $doctrineType |
||
| 787 | * |
||
| 788 | * @return string|false |
||
| 789 | */ |
||
| 790 | 14 | private static function resolveTypeFromDoctrineType(string $doctrineType) |
|
| 818 | |||
| 819 | /** |
||
| 820 | * Transform a method arguments from reflection to a list of GraphQL argument. |
||
| 821 | * |
||
| 822 | * @param \ReflectionMethod $method |
||
| 823 | * |
||
| 824 | * @return array |
||
| 825 | */ |
||
| 826 | 14 | private static function guessArgs(\ReflectionMethod $method) |
|
| 852 | |||
| 853 | /** |
||
| 854 | * Try to guess a GraphQL type from a Reflected Type. |
||
| 855 | * |
||
| 856 | * @param \ReflectionType $type |
||
| 857 | * |
||
| 858 | * @return string |
||
| 859 | */ |
||
| 860 | 14 | private static function resolveGraphqlTypeFromReflectionType(\ReflectionType $type, string $filterGraphqlType = null, bool $isOptionnal = false) |
|
| 877 | |||
| 878 | /** |
||
| 879 | * Resolve a GraphQL Type from a class name. |
||
| 880 | * |
||
| 881 | * @param string $className |
||
| 882 | * @param string $wantedType |
||
| 883 | * |
||
| 884 | * @return string|false |
||
| 885 | */ |
||
| 886 | 14 | private static function resolveTypeFromClass(string $className, string $wantedType = null) |
|
| 898 | |||
| 899 | /** |
||
| 900 | * Resolve a PHP class from a GraphQL type. |
||
| 901 | * |
||
| 902 | * @param string $type |
||
| 903 | * |
||
| 904 | * @return string|false |
||
| 905 | */ |
||
| 906 | 14 | private static function resolveClassFromType(string $type) |
|
| 910 | |||
| 911 | /** |
||
| 912 | * Convert a PHP Builtin type to a GraphQL type. |
||
| 913 | * |
||
| 914 | * @param string $phpType |
||
| 915 | * |
||
| 916 | * @return string |
||
| 917 | */ |
||
| 918 | 14 | private static function resolveTypeFromPhpType(string $phpType) |
|
| 936 | } |
||
| 937 |