55use Symfony \Component \Validator \Constraints as Assert ;
66use Yoanm \JsonRpcServerDoc \Domain \Model \Type \ArrayDoc ;
77use Yoanm \JsonRpcServerDoc \Domain \Model \Type \BooleanDoc ;
8- use Yoanm \JsonRpcServerDoc \Domain \Model \Type \CollectionDoc ;
98use Yoanm \JsonRpcServerDoc \Domain \Model \Type \FloatDoc ;
109use Yoanm \JsonRpcServerDoc \Domain \Model \Type \IntegerDoc ;
11- use Yoanm \JsonRpcServerDoc \Domain \Model \Type \NumberDoc ;
1210use Yoanm \JsonRpcServerDoc \Domain \Model \Type \ObjectDoc ;
1311use Yoanm \JsonRpcServerDoc \Domain \Model \Type \ScalarDoc ;
1412use Yoanm \JsonRpcServerDoc \Domain \Model \Type \StringDoc ;
@@ -21,13 +19,16 @@ class DocTypeHelper
2119{
2220 /** @var ConstraintPayloadDocHelper */
2321 private $ constraintPayloadDocHelper ;
22+ /** @var TypeGuesser */
23+ private $ typeGuesser ;
2424
2525 /**
2626 * @param ConstraintPayloadDocHelper $constraintPayloadDocHelper
2727 */
28- public function __construct (ConstraintPayloadDocHelper $ constraintPayloadDocHelper )
28+ public function __construct (ConstraintPayloadDocHelper $ constraintPayloadDocHelper, TypeGuesser $ typeGuesser )
2929 {
3030 $ this ->constraintPayloadDocHelper = $ constraintPayloadDocHelper ;
31+ $ this ->typeGuesser = $ typeGuesser ;
3132 }
3233
3334 /**
@@ -38,24 +39,25 @@ public function __construct(ConstraintPayloadDocHelper $constraintPayloadDocHelp
3839 public function guess (array $ constraintList ) : TypeDoc
3940 {
4041 return $ this ->getDocFromTypeConstraintOrPayloadDocIfExist ($ constraintList )
41- ?? $ this ->guessTypeFromConstraintList ($ constraintList )
42- ?? new TypeDoc ();
42+ ?? $ this ->typeGuesser ->guessTypeFromConstraintList ($ constraintList )
43+ ?? new TypeDoc ()
44+ ;
4345 }
4446
4547 /**
4648 * @param Constraint[] $constraintList
4749 *
4850 * @return TypeDoc|null
4951 */
50- private function getDocFromTypeConstraintOrPayloadDocIfExist (array $ constraintList )
52+ protected function getDocFromTypeConstraintOrPayloadDocIfExist (array $ constraintList )
5153 {
5254 $ doc = null ;
5355 // Check if a Type constraint exist or if a constraint have a type documentation
5456 foreach ($ constraintList as $ constraint ) {
5557 if (null !== ($ typeFromPayload = $ this ->constraintPayloadDocHelper ->getTypeIfExist ($ constraint ))) {
56- $ doc = $ this ->getDocFromType ($ typeFromPayload );
58+ $ doc = $ this ->normalizeType ($ typeFromPayload );
5759 } elseif ($ constraint instanceof Assert \Type) {
58- $ doc = $ this ->getDocFromType (strtolower ($ constraint ->type ));
60+ $ doc = $ this ->normalizeType (strtolower ($ constraint ->type ));
5961 }
6062
6163 if (null !== $ doc ) {
@@ -66,121 +68,12 @@ private function getDocFromTypeConstraintOrPayloadDocIfExist(array $constraintLi
6668 return $ doc ;
6769 }
6870
69- /**
70- * @param array $constraintList
71- *
72- * @return TypeDoc|null
73- */
74- private function guessTypeFromConstraintList (array $ constraintList )
75- {
76- $ doc = $ abstractTypeFound = null ;
77- foreach ($ constraintList as $ constraint ) {
78- $ doc = $ this ->guessTypeFromConstraint ($ constraint );
79- if (null !== $ doc ) {
80- if ($ this ->isAbstractType ($ doc )) {
81- // Abstract type => continue to see if better type can be found
82- $ abstractTypeFound = $ doc ;
83- $ doc = null ;
84- } else {
85- break ;
86- }
87- }
88- }
89- // Try to fallback on abstractType if found
90- if (null === $ doc && null !== $ abstractTypeFound ) {
91- $ doc = $ abstractTypeFound ;
92- }
93-
94- return $ doc ;
95- }
96-
97- /**
98- * @param Constraint $constraint
99- *
100- * @return TypeDoc|null
101- */
102- private function guessTypeFromConstraint (Constraint $ constraint )
103- {
104- static $ stringConstraintClassList = [
105- Assert \Length::class, // << Applied on string only
106- Assert \Date::class, // << validator expect a string with specific format
107- Assert \Time::class, // << validator expect a string with specific format
108- Assert \Bic::class,
109- Assert \CardScheme::class,
110- Assert \Country::class,
111- Assert \Currency::class,
112- Assert \Email::class,
113- Assert \File::class,
114- Assert \Iban::class,
115- Assert \Ip::class,
116- Assert \Isbn::class,
117- Assert \Issn::class,
118- Assert \Language::class,
119- Assert \Locale::class,
120- Assert \Luhn::class,
121- Assert \Regex::class,
122- Assert \Url::class,
123- Assert \Uuid::class,
124- ];
125- static $ booleanConstraintClassList = [
126- Assert \IsTrue::class,
127- Assert \IsFalse::class,
128- ];
129- $ constraintClass = get_class ($ constraint );
130-
131- // Try to guess primary types
132- if (in_array ($ constraintClass , $ stringConstraintClassList )) {
133- return new StringDoc ();
134- } elseif (in_array ($ constraintClass , $ booleanConstraintClassList )) {
135- return new BooleanDoc ();
136- } elseif ($ constraint instanceof Assert \DateTime) {
137- if ('U ' === $ constraint ->format ) {
138- return new ScalarDoc ();// Don't know if value will be an number as string or as integer
139- }
140-
141- return new StringDoc ();
142- } elseif ($ constraint instanceof Assert \Collection) {
143- // If only integer => array, else object
144- $ integerKeyList = array_filter (array_keys ($ constraint ->fields ), 'is_int ' );
145- if (count ($ constraint ->fields ) === count ($ integerKeyList )) {
146- return new ArrayDoc ();
147- }
148-
149- return new ObjectDoc ();
150- } elseif (Assert \All::class === $ constraintClass // << Applied only on array
151- || ($ constraint instanceof Assert \Choice
152- && true === $ constraint ->multiple // << expect an array multiple choices
153- )
154- ) {
155- return new ArrayDoc ();
156- }
157-
158- // If primary type is still not defined
159- static $ numberOrFloatConstraintClassList = [
160- Assert \GreaterThan::class,
161- Assert \GreaterThanOrEqual::class,
162- Assert \LessThan::class,
163- Assert \LessThanOrEqual::class,
164- ];
165- if ($ constraint instanceof Assert \Range) {
166- return $ this ->floatOrNumber ([$ constraint ->min , $ constraint ->max ]);
167- } elseif (in_array ($ constraintClass , $ numberOrFloatConstraintClassList )) {
168- return $ this ->floatOrNumber ([$ constraint ->value ]);
169- } elseif (Assert \Count::class == $ constraintClass ) {
170- return new CollectionDoc ();
171- } elseif ($ constraint instanceof Assert \Existence) {
172- return $ this ->guess ($ constraint ->constraints );
173- }
174-
175- return null ;
176- }
177-
17871 /**
17972 * @param string $type
18073 *
18174 * @return TypeDoc|null
18275 */
183- private function getDocFromType (string $ type )
76+ private function normalizeType (string $ type )
18477 {
18578 if ('scalar ' === $ type ) {
18679 return new ScalarDoc ();
@@ -200,36 +93,4 @@ private function getDocFromType(string $type)
20093
20194 return null ;
20295 }
203-
204- /**
205- * @param TypeDoc $doc
206- *
207- * @return bool
208- */
209- private function isAbstractType (TypeDoc $ doc ) : bool
210- {
211- // use get_class to avoid inheritance issue
212- $ class = get_class ($ doc );
213-
214- return CollectionDoc::class === $ class
215- || NumberDoc::class === $ class
216- || ScalarDoc::class === $ class
217- ;
218- }
219-
220- /**
221- * @param array $basedOnList
222- *
223- * @return FloatDoc|NumberDoc
224- */
225- private function floatOrNumber (array $ basedOnList )
226- {
227- foreach ($ basedOnList as $ value ) {
228- if (null !== $ value && is_float ($ value )) {
229- return new FloatDoc ();
230- }
231- }
232-
233- return new NumberDoc ();
234- }
23596}
0 commit comments