Passed
Pull Request — feature/fix (#19)
by Yo
01:21
created

getDocFromTypeConstraintOrPayloadDocIfExist()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 13
ccs 7
cts 7
cp 1
crap 3
rs 10
c 0
b 0
f 0
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 25
    public function __construct(ConstraintPayloadDocHelper $constraintPayloadDocHelper, TypeGuesser $typeGuesser)
47
    {
48 25
        $this->constraintPayloadDocHelper = $constraintPayloadDocHelper;
49 25
        $this->typeGuesser = $typeGuesser;
50 25
    }
51
52
    /**
53
     * @param Constraint[] $constraintList
54
     *
55
     * @return TypeDoc
56
     */
57 25
    public function guess(array $constraintList) : TypeDoc
58
    {
59 25
        return $this->getDocFromTypeConstraintOrPayloadDocIfExist($constraintList)
60 3
            ?? $this->typeGuesser->guessTypeFromConstraintList($constraintList)
61 25
            ?? new TypeDoc()
62
        ;
63
    }
64
65
    /**
66
     * @param Constraint[] $constraintList
67
     *
68
     * @return TypeDoc|null
69
     */
70 25
    protected function getDocFromTypeConstraintOrPayloadDocIfExist(array $constraintList) : ?TypeDoc
71
    {
72 25
        $doc = null;
73
        // Check if a Type constraint exist or if a constraint have a type documentation
74 25
        foreach ($constraintList as $constraint) {
75 24
            $doc = $this->createDocFromConstraint($constraint);
76
77 24
            if (null !== $doc) {
78 24
                break;
79
            }
80
        }
81
82 25
        return $doc;
83
    }
84
85
    /**
86
     * @param string $type
87
     *
88
     * @return TypeDoc|null
89
     */
90 23
    private function normalizeType(string $type) : ?TypeDoc
91
    {
92 23
        if (array_key_exists($type, self::MANAGED_TYPE_CLASS_LIST)) {
93 22
            $class = self::MANAGED_TYPE_CLASS_LIST[$type];
94
95 22
            return new $class();
96
        }
97
98 1
        return null;
99
    }
100
101
    /**
102
     * @param Constraint $constraint
103
     *
104
     * @return TypeDoc|null
105
     */
106 24
    private function createDocFromConstraint(Constraint $constraint) : ?TypeDoc
107
    {
108 24
        $doc = null;
109
110 24
        if (null !== ($typeFromPayload = $this->constraintPayloadDocHelper->getTypeIfExist($constraint))) {
111 1
            $doc = $this->normalizeType($typeFromPayload);
112 23
        } elseif ($constraint instanceof Assert\Type) {
113 18
            $doc = $this->normalizeType(strtolower($constraint->type));
114 9
        } elseif ($constraint instanceof Assert\IdenticalTo) {// Strict comparison so value define the type
115 4
            $doc = $this->normalizeType(gettype($constraint->value));
116 5
        } elseif ($constraint instanceof Assert\Existence && count($constraint->constraints) > 0) {
117 2
            $doc = $this->guess($constraint->constraints);
118 3
        } elseif ($constraint instanceof Assert\Callback) {
119 2
            $callbackResult = call_user_func($constraint->callback);
120 2
            $doc = $this->guess(
121 2
                is_array($callbackResult)
122 1
                    ? $callbackResult
123 2
                    : [$callbackResult]
124
            );
125
        }
126
127 24
        return $doc;
128
    }
129
}
130