DocTypeHelper   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 135
ccs 46
cts 46
cp 1
rs 10
wmc 18

7 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeType() 0 9 2
A getStringType() 0 12 4
A createDocFromConstraint() 0 13 5
A __construct() 0 4 1
A guess() 0 5 1
A getDocFromTypeConstraintOrPayloadDocIfExist() 0 13 3
A getTypeFromCallbackConstraint() 0 9 2
1
<?php
2
namespace Yoanm\JsonRpcParamsSymfonyConstraintDoc\App\Helper;
3
4
use Symfony\Component\Validator\Constraint;
5
use Symfony\Component\Validator\Constraints as Assert;
6
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc;
7
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\BooleanDoc;
8
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\FloatDoc;
9
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\IntegerDoc;
10
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\NumberDoc;
11
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ObjectDoc;
12
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ScalarDoc;
13
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\StringDoc;
14
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc;
15
16
/**
17
 * Class DocTypeHelper
18
 */
19
class DocTypeHelper
20
{
21
    /** @var ConstraintPayloadDocHelper */
22
    private $constraintPayloadDocHelper;
23
    /** @var TypeGuesser */
24
    private $typeGuesser;
25
26
    const MANAGED_TYPE_CLASS_LIST = [
27
        'scalar' => ScalarDoc::class,
28
        'string' => StringDoc::class,
29
        'bool' => BooleanDoc::class,
30
        'boolean' => BooleanDoc::class,
31
        'int' => IntegerDoc::class,
32
        'integer' => IntegerDoc::class,
33
        'float' => FloatDoc::class,
34
        'long' => FloatDoc::class,
35
        'double' => FloatDoc::class,
36
        'real' => FloatDoc::class,
37
        'numeric' => NumberDoc::class,
38
        'array' => ArrayDoc::class,
39
        'object' => ObjectDoc::class,
40
    ];
41
42
    /**
43
     * @param ConstraintPayloadDocHelper $constraintPayloadDocHelper
44
     * @param TypeGuesser                $typeGuesser
45
     */
46 178
    public function __construct(ConstraintPayloadDocHelper $constraintPayloadDocHelper, TypeGuesser $typeGuesser)
47
    {
48 178
        $this->constraintPayloadDocHelper = $constraintPayloadDocHelper;
49 178
        $this->typeGuesser = $typeGuesser;
50
    }
51
52
    /**
53
     * @param Constraint[] $constraintList
54
     *
55
     * @return TypeDoc
56
     */
57 178
    public function guess(array $constraintList) : TypeDoc
58
    {
59 178
        return $this->getDocFromTypeConstraintOrPayloadDocIfExist($constraintList)
60 178
            ?? $this->typeGuesser->guessTypeFromConstraintList($constraintList)
61 178
            ?? new TypeDoc()
62 178
        ;
63
    }
64
65
    /**
66
     * @param Constraint[] $constraintList
67
     *
68
     * @return TypeDoc|null
69
     */
70 178
    protected function getDocFromTypeConstraintOrPayloadDocIfExist(array $constraintList) : ?TypeDoc
71
    {
72 178
        $doc = null;
73
        // Check if a Type constraint exist or if a constraint have a type documentation
74 178
        foreach ($constraintList as $constraint) {
75 177
            $doc = $this->createDocFromConstraint($constraint);
76
77 177
            if (null !== $doc) {
78 105
                break;
79
            }
80
        }
81
82 178
        return $doc;
83
    }
84
85
    /**
86
     * @param string $type
87
     *
88
     * @return TypeDoc|null
89
     */
90 106
    private function normalizeType(string $type) : ?TypeDoc
91
    {
92 106
        if (array_key_exists($type, self::MANAGED_TYPE_CLASS_LIST)) {
93 105
            $class = self::MANAGED_TYPE_CLASS_LIST[$type];
94
95 105
            return new $class();
96
        }
97
98 1
        return null;
99
    }
100
101
    /**
102
     * @param Constraint $constraint
103
     *
104
     * @return TypeDoc|null
105
     */
106 177
    private function createDocFromConstraint(Constraint $constraint) : ?TypeDoc
107
    {
108 177
        $doc = null;
109
110 177
        if (null !== ($stringType = $this->getStringType($constraint))) {
111 106
            $doc = $this->normalizeType($stringType);
112 84
        } elseif ($constraint instanceof Assert\Callback) {
113 4
            $doc = $this->getTypeFromCallbackConstraint($constraint);
114 82
        } elseif ($constraint instanceof Assert\Existence && count($constraint->constraints) > 0) {
115 8
            $doc = $this->guess($constraint->constraints);
116
        }
117
118 177
        return $doc;
119
    }
120
121
    /**
122
     * @param Assert\Callback $constraint
123
     *
124
     * @return TypeDoc
125
     */
126 4
    private function getTypeFromCallbackConstraint(Assert\Callback $constraint): TypeDoc
127
    {
128 4
        $callbackResult = call_user_func($constraint->callback);
129 4
        $doc = $this->guess(
130 4
            is_array($callbackResult)
131 1
                ? $callbackResult
132 4
                : [$callbackResult]
133 4
        );
134 4
        return $doc;
135
    }
136
137
    /**
138
     * @param Constraint $constraint
139
     *
140
     * @return string|null
141
     */
142 177
    private function getStringType(Constraint $constraint) : ?string
143
    {
144 177
        $stringType = null;
145 177
        if (null !== ($typeFromPayload = $this->constraintPayloadDocHelper->getTypeIfExist($constraint))) {
146 49
            $stringType = $typeFromPayload;
147 128
        } elseif ($constraint instanceof Assert\Type) {
148 45
            $stringType = strtolower($constraint->type);
149 96
        } elseif ($constraint instanceof Assert\IdenticalTo) {// Strict comparison so value define the type
150 12
            $stringType = gettype($constraint->value);
151
        }
152
153 177
        return $stringType;
154
    }
155
}
156