TypeMappingException::wrapWithParamInfo()   B
last analyzed

Complexity

Conditions 8
Paths 6

Size

Total Lines 41
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 41
rs 8.1315
c 0
b 0
f 0
cc 8
nc 6
nop 2
1
<?php
2
3
4
namespace TheCodingMachine\GraphQL\Controllers;
5
6
7
use Iterator;
8
use IteratorAggregate;
9
use phpDocumentor\Reflection\Type;
10
use phpDocumentor\Reflection\Types\Array_;
11
use phpDocumentor\Reflection\Types\Iterable_;
12
use phpDocumentor\Reflection\Types\Mixed_;
13
use phpDocumentor\Reflection\Types\Object_;
14
use ReflectionClass;
15
use \ReflectionMethod;
16
17
class TypeMappingException extends GraphQLException
18
{
19
    private $type;
20
21
    public static function createFromType(Type $type): self
22
    {
23
        $e = new self("Don't know how to handle type ".(string) $type);
24
        $e->type = $type;
25
        return $e;
26
    }
27
28
    public static function wrapWithParamInfo(TypeMappingException $previous, \ReflectionParameter $parameter): TypeMappingException
29
    {
30
        if ($previous->type instanceof Array_ || $previous->type instanceof Iterable_) {
31
            $typeStr = $previous->type instanceof Array_ ? 'array' : 'iterable';
32
            $message = sprintf('Parameter $%s in %s::%s is type-hinted to %s. Please provide an additional @param in the PHPDoc block to further specify the type of the %s. For instance: @param string[] $%s.',
33
                $parameter->getName(),
34
                $parameter->getDeclaringClass()->getName(),
35
                $parameter->getDeclaringFunction()->getName(),
36
                $typeStr,
37
                $typeStr,
38
                $parameter->getName());
39
        } elseif ($previous->type instanceof Mixed_) {
40
            $message = sprintf('Parameter $%s in %s::%s is missing a type-hint (or type-hinted to "mixed"). Please provide a better type-hint. For instance: "string $%s".',
41
                $parameter->getName(),
42
                $parameter->getDeclaringClass()->getName(),
43
                $parameter->getDeclaringFunction()->getName(),
44
                $parameter->getName());
45
        } else {
46
            if ($previous->type instanceof Object_) {
47
                $fqcn = (string) $previous->type->getFqsen();
48
                $refClass = new ReflectionClass($fqcn);
49
                // Note : $refClass->isIterable() is only accessible in PHP 7.2
50
                if ($refClass->implementsInterface(Iterator::class) || $refClass->implementsInterface(IteratorAggregate::class)) {
51
                    $message = sprintf('Parameter $%s in %s::%s is type-hinted to "%s", which is iterable. Please provide an additional @param in the PHPDoc block to further specify the type. For instance: @param %s|User[] $%s.',
52
                        $parameter->getName(),
53
                        $parameter->getDeclaringClass()->getName(),
54
                        $parameter->getDeclaringFunction()->getName(),
55
                        $fqcn,
56
                        $fqcn,
57
                        $parameter->getName());
58
                } else {
59
                    throw new GraphQLException("Unexpected type in TypeMappingException. Got a non iterable '".$fqcn.'"');
60
                }
61
            } else {
62
                throw new GraphQLException("Unexpected type in TypeMappingException. Got '".get_class($previous->type).'"');
63
            }
64
        }
65
66
        $e = new self($message, 0, $previous);
67
        $e->type = $previous->type;
68
        return $e;
69
    }
70
71
    public static function wrapWithReturnInfo(TypeMappingException $previous, ReflectionMethod $method): TypeMappingException
72
    {
73
        if ($previous->type instanceof Array_ || $previous->type instanceof Iterable_) {
74
            $typeStr = $previous->type instanceof Array_ ? 'array' : 'iterable';
75
            $message = sprintf('Return type in %s::%s is type-hinted to %s. Please provide an additional @return in the PHPDoc block to further specify the type of the array. For instance: @return string[]',
76
                $method->getDeclaringClass()->getName(),
77
                $method->getName(),
78
                $typeStr);
79
        } elseif ($previous->type instanceof Mixed_) {
80
            $message = sprintf('Return type in %s::%s is missing a type-hint (or type-hinted to "mixed"). Please provide a better type-hint.',
81
                $method->getDeclaringClass()->getName(),
82
                $method->getName());
83
        } else {
84
            if ($previous->type instanceof Object_) {
85
                $fqcn = (string) $previous->type->getFqsen();
86
                $refClass = new ReflectionClass($fqcn);
87
                // Note : $refClass->isIterable() is only accessible in PHP 7.2
88
                if ($refClass->implementsInterface(Iterator::class) || $refClass->implementsInterface(IteratorAggregate::class)) {
89
                    $message = sprintf('Return type in %s::%s is type-hinted to "%s", which is iterable. Please provide an additional @param in the PHPDoc block to further specify the type. For instance: @return %s|User[]',
90
                        $method->getDeclaringClass()->getName(),
91
                        $method->getName(),
92
                        $fqcn,
93
                        $fqcn);
94
                } else {
95
                    throw new GraphQLException("Unexpected type in TypeMappingException. Got a non iterable '".$fqcn.'"');
96
                }
97
            } else {
98
                throw new GraphQLException("Unexpected type in TypeMappingException. Got '".get_class($previous->type).'"');
99
            }
100
        }
101
102
        $e = new self($message, 0, $previous);
103
        $e->type = $previous->type;
104
        return $e;
105
    }
106
}
107