Passed
Pull Request — release/1.0.0 (#6)
by Yo
01:27
created

docFromConstraint()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 2
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Yoanm\JsonRpcParamsSymfonyConstraintDoc\Infra\Transformer;
3
4
use Symfony\Component\Validator\Constraint;
5
use Symfony\Component\Validator\Constraints as Assert;
6
use Yoanm\JsonRpcParamsSymfonyConstraintDoc\App\Helper\ConstraintPayloadDocHelper;
7
use Yoanm\JsonRpcParamsSymfonyConstraintDoc\App\Helper\DocTypeHelper;
8
use Yoanm\JsonRpcParamsSymfonyConstraintDoc\App\Helper\MinMaxHelper;
9
use Yoanm\JsonRpcParamsSymfonyConstraintDoc\App\Helper\StringDocHelper;
10
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc;
11
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\CollectionDoc;
12
use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc;
13
14
/**
15
 * Class ConstraintToParamsDocTransformer
16
 */
17
class ConstraintToParamsDocTransformer
18
{
19
    /** @var DocTypeHelper */
20
    private $docTypeHelper;
21
    /** @var StringDocHelper */
22
    private $stringDocHelper;
23
    /** @var MinMaxHelper */
24
    private $minMaxHelper;
25
    /** @var ConstraintPayloadDocHelper */
26
    private $constraintPayloadDocHelper;
27
28
    /**
29
     * @param DocTypeHelper              $docTypeHelper
30
     * @param ConstraintPayloadDocHelper $constraintPayloadDocHelper
31
     */
32 7
    public function __construct(
33
        DocTypeHelper $docTypeHelper,
34
        StringDocHelper $stringDocHelper,
35
        MinMaxHelper $minMaxHelper,
36
        ConstraintPayloadDocHelper $constraintPayloadDocHelper
37
    ) {
38 7
        $this->docTypeHelper = $docTypeHelper;
39 7
        $this->minMaxHelper = $minMaxHelper;
40 7
        $this->stringDocHelper = $stringDocHelper;
41 7
        $this->constraintPayloadDocHelper = $constraintPayloadDocHelper;
42 7
    }
43
44
    /**
45
     * @param Constraint $constraint
46
     *
47
     * @return TypeDoc
48
     */
49 7
    public function transform(Constraint $constraint) : TypeDoc
50
    {
51 7
        $constraintList = [$constraint];
52 7
        $constraintDoc = $this->docTypeHelper->guess($constraintList);
53
54 7
        foreach ($constraintList as $constraint) {
55 7
            $this->appendToDoc($constraintDoc, $constraint);
56
        }
57
58 7
        return $constraintDoc;
59
    }
60
61
    /**
62
     * @param TypeDoc $doc
63
     * @param Constraint   $constraint
64
     */
65 7
    private function appendToDoc(TypeDoc $doc, Constraint $constraint) : void
66
    {
67 7
        if ($doc instanceof ArrayDoc && $constraint instanceof Assert\All) {
68 1
            $this->appendAllConstraintToDoc($doc, $constraint);
69
        } else {
70 7
            $this->stringDocHelper->append($doc, $constraint);
71 7
            $this->appendCollectionDoc($doc, $constraint);
72
73 7
            $this->minMaxHelper->append($doc, $constraint);
74 7
            $this->appendValidItemListDoc($doc, $constraint);
75
76 7
            if ($constraint instanceof Assert\Existence) {
77 2
                $doc->setRequired($constraint instanceof Assert\Required);
78 2
                foreach ($constraint->constraints as $subConstraint) {
79 2
                    $this->appendToDoc($doc, $subConstraint);
80
                }
81 7
            } elseif ($constraint instanceof Assert\NotNull) {
82 2
                $doc->setNullable(false);
83
            }
84
85
            // /!\ Payload doc will override values even if already defined
86 7
            $this->constraintPayloadDocHelper->appendPayloadDoc($doc, $constraint);
87
        }
88 7
    }
89
90
    /**
91
     * @param TypeDoc $doc
92
     * @param Constraint $constraint
93
     */
94 7
    private function appendCollectionDoc(TypeDoc $doc, Constraint $constraint) : void
95
    {
96
        // If not a collection => give up
97 7
        if (!$doc instanceof CollectionDoc) {
98 7
            return;
99
        }
100
101 2
        if ($constraint instanceof Assert\Collection) {
102 2
            foreach ($constraint->fields as $fieldName => $constraintOrConstrainList) {
103 2
                $doc->addSibling(
104 2
                    $this->transform($constraintOrConstrainList)
105 2
                        ->setName($fieldName)
106
                );
107
            }
108
109 2
            $doc->setAllowExtraSibling($constraint->allowExtraFields === true);
110 2
            $doc->setAllowMissingSibling($constraint->allowMissingFields === true);
111
        }
112 2
    }
113
114
    /**
115
     * @param TypeDoc $doc
116
     * @param Constraint $constraint
117
     */
118 7
    private function appendValidItemListDoc(TypeDoc $doc, Constraint $constraint) : void
119
    {
120 7
        if ($constraint instanceof Assert\Choice) {
121 2
            if ($constraint->callback && is_callable($constraint->callback)) {
122 1
                $choiceList = call_user_func($constraint->callback);
123
            } else {
124 1
                $choiceList = $constraint->choices ?? [];
125
            }
126 2
            foreach ($choiceList as $fieldName => $choice) {
127 2
                $doc->addAllowedValue($choice);
128
            }
129
        }
130 7
    }
131
132
    /**
133
     * @param ArrayDoc   $doc
134
     * @param Assert\All $constraint
135
     */
136 1
    private function appendAllConstraintToDoc(ArrayDoc $doc, Assert\All $constraint) : void
137
    {
138 1
        $itemDoc = $this->docTypeHelper->guess($constraint->constraints);
139 1
        foreach ($constraint->constraints as $subConstraint) {
140 1
            $this->appendToDoc($itemDoc, $subConstraint);
141
        }
142
143 1
        $doc->setItemValidation($itemDoc);
144 1
    }
145
}
146