Failed Conditions
Push — release/1.0.0 ( 0a806c...c1e1ac )
by Yo
01:52 queued 10s
created

appendAllConstraintToDoc()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
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)
50
    {
51 7
        return $this->docFromConstraint($constraint);
52
    }
53
54
    /**
55
     * @param Constraint      $constraintOrConstraintList
56
     * @param string|int|null $paramNameOrIndex
57
     *
58
     * @return TypeDoc
59
     */
60 7
    private function docFromConstraint(Constraint $constraint, $paramNameOrIndex = null)
61
    {
62 7
        $constraintList = [$constraint];
63 7
        $constraintDoc = $this->docTypeHelper->guess($constraintList);
64 7
        if (null !== $paramNameOrIndex) {
65 2
            $constraintDoc->setName($paramNameOrIndex);
66
        }
67
68 7
        foreach ($constraintList as $constraint) {
69 7
            $this->appendToDoc($constraintDoc, $constraint);
70
        }
71
72 7
        return $constraintDoc;
73
    }
74
75
    /**
76
     * @param TypeDoc $doc
77
     * @param Constraint   $constraint
78
     */
79 7
    private function appendToDoc(TypeDoc $doc, Constraint $constraint)
80
    {
81 7
        if ($doc instanceof ArrayDoc && $constraint instanceof Assert\All) {
82 1
            $this->appendAllConstraintToDoc($doc, $constraint);
83
        } else {
84 7
            $this->stringDocHelper->append($doc, $constraint);
85 7
            $this->appendCollectionDoc($doc, $constraint);
86
87 7
            $this->minMaxHelper->append($doc, $constraint);
88 7
            $this->appendValidItemListDoc($doc, $constraint);
89
90 7
            if ($constraint instanceof Assert\Existence) {
91 2
                $doc->setRequired($constraint instanceof Assert\Required);
92 2
                foreach ($constraint->constraints as $subConstraint) {
93 2
                    $this->appendToDoc($doc, $subConstraint);
94
                }
95 7
            } elseif ($constraint instanceof Assert\NotNull) {
96 2
                $doc->setNullable(false);
97
            }
98
99
            // /!\ Payload doc will override values even if already defined
100 7
            $this->constraintPayloadDocHelper->appendPayloadDoc($doc, $constraint);
101
        }
102 7
    }
103
104
    /**
105
     * @param TypeDoc $doc
106
     * @param Constraint $constraint
107
     */
108 7
    private function appendCollectionDoc(TypeDoc $doc, Constraint $constraint)
109
    {
110
        // If not a collection => give up
111 7
        if (!$doc instanceof CollectionDoc) {
112 7
            return;
113
        }
114
115 2
        if ($constraint instanceof Assert\Collection) {
116 2
            foreach ($constraint->fields as $fieldName => $constraintOrConstrainList) {
117 2
                $doc->addSibling(
118 2
                    $this->docFromConstraint($constraintOrConstrainList, $fieldName)
119
                );
120
            }
121
122 2
            $doc->setAllowExtraSibling($constraint->allowExtraFields === true);
123 2
            $doc->setAllowMissingSibling($constraint->allowMissingFields === true);
124
        }
125 2
    }
126
127
    /**
128
     * @param TypeDoc $doc
129
     * @param Constraint $constraint
130
     */
131 7
    private function appendValidItemListDoc(TypeDoc $doc, Constraint $constraint)
132
    {
133 7
        if ($constraint instanceof Assert\Choice) {
134 2
            if ($constraint->callback && is_callable($constraint->callback)) {
135 1
                $choiceList = call_user_func($constraint->callback);
136
            } else {
137 1
                $choiceList = $constraint->choices ?? [];
138
            }
139 2
            foreach ($choiceList as $fieldName => $choice) {
140 2
                $doc->addAllowedValue($choice);
141
            }
142
        }
143 7
    }
144
145
    /**
146
     * @param ArrayDoc   $doc
147
     * @param Assert\All $constraint
148
     */
149 1
    private function appendAllConstraintToDoc(ArrayDoc $doc, Assert\All $constraint)
150
    {
151 1
        $itemDoc = $this->docTypeHelper->guess($constraint->constraints);
152 1
        foreach ($constraint->constraints as $subConstraint) {
153 1
            $this->appendToDoc($itemDoc, $subConstraint);
154
        }
155
156 1
        $doc->setItemValidation($itemDoc);
157 1
    }
158
}
159