PageRenderTime 34ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php

https://github.com/Exercise/symfony
PHP | 273 lines | 163 code | 47 blank | 63 comment | 10 complexity | 251c5be9d9f2e3ff2b47714a49f6ae1f MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\Extension\Validator;
  11. use Symfony\Component\Form\FormTypeGuesserInterface;
  12. use Symfony\Component\Form\Guess\Guess;
  13. use Symfony\Component\Form\Guess\TypeGuess;
  14. use Symfony\Component\Form\Guess\ValueGuess;
  15. use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
  16. use Symfony\Component\Validator\Constraint;
  17. class ValidatorTypeGuesser implements FormTypeGuesserInterface
  18. {
  19. private $metadataFactory;
  20. public function __construct(ClassMetadataFactoryInterface $metadataFactory)
  21. {
  22. $this->metadataFactory = $metadataFactory;
  23. }
  24. /**
  25. * {@inheritDoc}
  26. */
  27. public function guessType($class, $property)
  28. {
  29. $guesser = $this;
  30. return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
  31. return $guesser->guessTypeForConstraint($constraint);
  32. });
  33. }
  34. /**
  35. * {@inheritDoc}
  36. */
  37. public function guessRequired($class, $property)
  38. {
  39. $guesser = $this;
  40. return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
  41. return $guesser->guessRequiredForConstraint($constraint);
  42. // If we don't find any constraint telling otherwise, we can assume
  43. // that a field is not required (with LOW_CONFIDENCE)
  44. }, false);
  45. }
  46. /**
  47. * {@inheritDoc}
  48. */
  49. public function guessMaxLength($class, $property)
  50. {
  51. $guesser = $this;
  52. return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
  53. return $guesser->guessMaxLengthForConstraint($constraint);
  54. });
  55. }
  56. /**
  57. * {@inheritDoc}
  58. */
  59. public function guessMinLength($class, $property)
  60. {
  61. $guesser = $this;
  62. return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
  63. return $guesser->guessMinLengthForConstraint($constraint);
  64. });
  65. }
  66. /**
  67. * Guesses a field class name for a given constraint
  68. *
  69. * @param Constraint $constraint The constraint to guess for
  70. *
  71. * @return TypeGuess The guessed field class and options
  72. */
  73. public function guessTypeForConstraint(Constraint $constraint)
  74. {
  75. switch (get_class($constraint)) {
  76. case 'Symfony\Component\Validator\Constraints\Type':
  77. switch ($constraint->type) {
  78. case 'boolean':
  79. case 'bool':
  80. return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE);
  81. case 'double':
  82. case 'float':
  83. case 'numeric':
  84. case 'real':
  85. return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
  86. case 'integer':
  87. case 'int':
  88. case 'long':
  89. return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
  90. case '\DateTime':
  91. return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE);
  92. case 'string':
  93. return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
  94. }
  95. break;
  96. case 'Symfony\Component\Validator\Constraints\Country':
  97. return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE);
  98. case 'Symfony\Component\Validator\Constraints\Date':
  99. return new TypeGuess('date', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
  100. case 'Symfony\Component\Validator\Constraints\DateTime':
  101. return new TypeGuess('datetime', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
  102. case 'Symfony\Component\Validator\Constraints\Email':
  103. return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE);
  104. case 'Symfony\Component\Validator\Constraints\File':
  105. case 'Symfony\Component\Validator\Constraints\Image':
  106. return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE);
  107. case 'Symfony\Component\Validator\Constraints\Language':
  108. return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE);
  109. case 'Symfony\Component\Validator\Constraints\Locale':
  110. return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE);
  111. case 'Symfony\Component\Validator\Constraints\Time':
  112. return new TypeGuess('time', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
  113. case 'Symfony\Component\Validator\Constraints\Url':
  114. return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE);
  115. case 'Symfony\Component\Validator\Constraints\Ip':
  116. return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
  117. case 'Symfony\Component\Validator\Constraints\MaxLength':
  118. case 'Symfony\Component\Validator\Constraints\MinLength':
  119. case 'Symfony\Component\Validator\Constraints\Regex':
  120. case 'Symfony\Component\Validator\Constraints\SizeLength':
  121. return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
  122. case 'Symfony\Component\Validator\Constraints\Min':
  123. case 'Symfony\Component\Validator\Constraints\Size':
  124. case 'Symfony\Component\Validator\Constraints\Max':
  125. return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);
  126. }
  127. }
  128. /**
  129. * Guesses whether a field is required based on the given constraint
  130. *
  131. * @param Constraint $constraint The constraint to guess for
  132. *
  133. * @return Guess The guess whether the field is required
  134. */
  135. public function guessRequiredForConstraint(Constraint $constraint)
  136. {
  137. switch (get_class($constraint)) {
  138. case 'Symfony\Component\Validator\Constraints\NotNull':
  139. case 'Symfony\Component\Validator\Constraints\NotBlank':
  140. return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
  141. }
  142. }
  143. /**
  144. * Guesses a field's maximum length based on the given constraint
  145. *
  146. * @param Constraint $constraint The constraint to guess for
  147. *
  148. * @return Guess The guess for the maximum length
  149. */
  150. public function guessMaxLengthForConstraint(Constraint $constraint)
  151. {
  152. switch (get_class($constraint)) {
  153. case 'Symfony\Component\Validator\Constraints\MaxLength':
  154. return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
  155. case 'Symfony\Component\Validator\Constraints\SizeLength':
  156. return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
  157. case 'Symfony\Component\Validator\Constraints\Type':
  158. if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
  159. return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
  160. }
  161. break;
  162. case 'Symfony\Component\Validator\Constraints\Max':
  163. return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
  164. case 'Symfony\Component\Validator\Constraints\Size':
  165. return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
  166. }
  167. }
  168. /**
  169. * Guesses a field's minimum length based on the given constraint
  170. *
  171. * @param Constraint $constraint The constraint to guess for
  172. *
  173. * @return Guess The guess for the minimum length
  174. */
  175. public function guessMinLengthForConstraint(Constraint $constraint)
  176. {
  177. switch (get_class($constraint)) {
  178. case 'Symfony\Component\Validator\Constraints\MinLength':
  179. return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
  180. case 'Symfony\Component\Validator\Constraints\SizeLength':
  181. return new ValueGuess($constraint->min, Guess::HIGH_CONFIDENCE);
  182. case 'Symfony\Component\Validator\Constraints\Type':
  183. if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
  184. return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
  185. }
  186. break;
  187. case 'Symfony\Component\Validator\Constraints\Min':
  188. return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
  189. case 'Symfony\Component\Validator\Constraints\Size':
  190. return new ValueGuess(strlen((string) $constraint->min), Guess::LOW_CONFIDENCE);
  191. }
  192. }
  193. /**
  194. * Iterates over the constraints of a property, executes a constraints on
  195. * them and returns the best guess
  196. *
  197. * @param string $class The class to read the constraints from
  198. * @param string $property The property for which to find constraints
  199. * @param \Closure $closure The closure that returns a guess
  200. * for a given constraint
  201. * @param mixed $default The default value assumed if no other value
  202. * can be guessed.
  203. *
  204. * @return Guess The guessed value with the highest confidence
  205. */
  206. protected function guess($class, $property, \Closure $closure, $defaultValue = null)
  207. {
  208. $guesses = array();
  209. $classMetadata = $this->metadataFactory->getClassMetadata($class);
  210. if ($classMetadata->hasMemberMetadatas($property)) {
  211. $memberMetadatas = $classMetadata->getMemberMetadatas($property);
  212. foreach ($memberMetadatas as $memberMetadata) {
  213. $constraints = $memberMetadata->getConstraints();
  214. foreach ($constraints as $constraint) {
  215. if ($guess = $closure($constraint)) {
  216. $guesses[] = $guess;
  217. }
  218. }
  219. }
  220. if (null !== $defaultValue) {
  221. $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);
  222. }
  223. }
  224. return Guess::getBestGuess($guesses);
  225. }
  226. }