vendor/symfony/form/Extension/Validator/ValidatorTypeGuesser.php line 67
<?php/** This file is part of the Symfony package.** (c) Fabien Potencier <fabien@symfony.com>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace Symfony\Component\Form\Extension\Validator;use Symfony\Component\Form\Extension\Core\Type\CheckboxType;use Symfony\Component\Form\Extension\Core\Type\CollectionType;use Symfony\Component\Form\Extension\Core\Type\CountryType;use Symfony\Component\Form\Extension\Core\Type\CurrencyType;use Symfony\Component\Form\Extension\Core\Type\DateTimeType;use Symfony\Component\Form\Extension\Core\Type\DateType;use Symfony\Component\Form\Extension\Core\Type\EmailType;use Symfony\Component\Form\Extension\Core\Type\FileType;use Symfony\Component\Form\Extension\Core\Type\IntegerType;use Symfony\Component\Form\Extension\Core\Type\LanguageType;use Symfony\Component\Form\Extension\Core\Type\LocaleType;use Symfony\Component\Form\Extension\Core\Type\NumberType;use Symfony\Component\Form\Extension\Core\Type\TextType;use Symfony\Component\Form\Extension\Core\Type\TimeType;use Symfony\Component\Form\Extension\Core\Type\UrlType;use Symfony\Component\Form\FormTypeGuesserInterface;use Symfony\Component\Form\Guess\Guess;use Symfony\Component\Form\Guess\TypeGuess;use Symfony\Component\Form\Guess\ValueGuess;use Symfony\Component\Validator\Constraint;use Symfony\Component\Validator\Constraints\Count;use Symfony\Component\Validator\Constraints\Country;use Symfony\Component\Validator\Constraints\Currency;use Symfony\Component\Validator\Constraints\Date;use Symfony\Component\Validator\Constraints\DateTime;use Symfony\Component\Validator\Constraints\Email;use Symfony\Component\Validator\Constraints\File;use Symfony\Component\Validator\Constraints\Image;use Symfony\Component\Validator\Constraints\Ip;use Symfony\Component\Validator\Constraints\IsFalse;use Symfony\Component\Validator\Constraints\IsTrue;use Symfony\Component\Validator\Constraints\Language;use Symfony\Component\Validator\Constraints\Length;use Symfony\Component\Validator\Constraints\Locale;use Symfony\Component\Validator\Constraints\NotBlank;use Symfony\Component\Validator\Constraints\NotNull;use Symfony\Component\Validator\Constraints\Range;use Symfony\Component\Validator\Constraints\Regex;use Symfony\Component\Validator\Constraints\Time;use Symfony\Component\Validator\Constraints\Type;use Symfony\Component\Validator\Constraints\Url;use Symfony\Component\Validator\Mapping\ClassMetadataInterface;use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;class ValidatorTypeGuesser implements FormTypeGuesserInterface{private MetadataFactoryInterface $metadataFactory;public function __construct(MetadataFactoryInterface $metadataFactory){$this->metadataFactory = $metadataFactory;}public function guessType(string $class, string $property): ?TypeGuess{return $this->guess($class, $property, function (Constraint $constraint) {return $this->guessTypeForConstraint($constraint);});}public function guessRequired(string $class, string $property): ?ValueGuess{return $this->guess($class, $property, function (Constraint $constraint) {return $this->guessRequiredForConstraint($constraint);// If we don't find any constraint telling otherwise, we can assume// that a field is not required (with LOW_CONFIDENCE)}, false);}public function guessMaxLength(string $class, string $property): ?ValueGuess{return $this->guess($class, $property, function (Constraint $constraint) {return $this->guessMaxLengthForConstraint($constraint);});}public function guessPattern(string $class, string $property): ?ValueGuess{return $this->guess($class, $property, function (Constraint $constraint) {return $this->guessPatternForConstraint($constraint);});}/*** Guesses a field class name for a given constraint.*/public function guessTypeForConstraint(Constraint $constraint): ?TypeGuess{switch ($constraint::class) {case Type::class:switch ($constraint->type) {case 'array':return new TypeGuess(CollectionType::class, [], Guess::MEDIUM_CONFIDENCE);case 'boolean':case 'bool':return new TypeGuess(CheckboxType::class, [], Guess::MEDIUM_CONFIDENCE);case 'double':case 'float':case 'numeric':case 'real':return new TypeGuess(NumberType::class, [], Guess::MEDIUM_CONFIDENCE);case 'integer':case 'int':case 'long':return new TypeGuess(IntegerType::class, [], Guess::MEDIUM_CONFIDENCE);case \DateTime::class:case '\DateTime':return new TypeGuess(DateType::class, [], Guess::MEDIUM_CONFIDENCE);case 'string':return new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE);}break;case Country::class:return new TypeGuess(CountryType::class, [], Guess::HIGH_CONFIDENCE);case Currency::class:return new TypeGuess(CurrencyType::class, [], Guess::HIGH_CONFIDENCE);case Date::class:return new TypeGuess(DateType::class, ['input' => 'string'], Guess::HIGH_CONFIDENCE);case DateTime::class:return new TypeGuess(DateTimeType::class, ['input' => 'string'], Guess::HIGH_CONFIDENCE);case Email::class:return new TypeGuess(EmailType::class, [], Guess::HIGH_CONFIDENCE);case File::class:case Image::class:$options = [];if ($constraint->mimeTypes) {$options = ['attr' => ['accept' => implode(',', (array) $constraint->mimeTypes)]];}return new TypeGuess(FileType::class, $options, Guess::HIGH_CONFIDENCE);case Language::class:return new TypeGuess(LanguageType::class, [], Guess::HIGH_CONFIDENCE);case Locale::class:return new TypeGuess(LocaleType::class, [], Guess::HIGH_CONFIDENCE);case Time::class:return new TypeGuess(TimeType::class, ['input' => 'string'], Guess::HIGH_CONFIDENCE);case Url::class:return new TypeGuess(UrlType::class, [], Guess::HIGH_CONFIDENCE);case Ip::class:return new TypeGuess(TextType::class, [], Guess::MEDIUM_CONFIDENCE);case Length::class:case Regex::class:return new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE);case Range::class:return new TypeGuess(NumberType::class, [], Guess::LOW_CONFIDENCE);case Count::class:return new TypeGuess(CollectionType::class, [], Guess::LOW_CONFIDENCE);case IsTrue::class:case IsFalse::class:return new TypeGuess(CheckboxType::class, [], Guess::MEDIUM_CONFIDENCE);}return null;}/*** Guesses whether a field is required based on the given constraint.*/public function guessRequiredForConstraint(Constraint $constraint): ?ValueGuess{return match ($constraint::class) {NotNull::class,NotBlank::class,IsTrue::class => new ValueGuess(true, Guess::HIGH_CONFIDENCE),default => null,};}/*** Guesses a field's maximum length based on the given constraint.*/public function guessMaxLengthForConstraint(Constraint $constraint): ?ValueGuess{switch ($constraint::class) {case Length::class:if (is_numeric($constraint->max)) {return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);}break;case Type::class:if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) {return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);}break;case Range::class:if (is_numeric($constraint->max)) {return new ValueGuess(\strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);}break;}return null;}/*** Guesses a field's pattern based on the given constraint.*/public function guessPatternForConstraint(Constraint $constraint): ?ValueGuess{switch ($constraint::class) {case Length::class:if (is_numeric($constraint->min)) {return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE);}break;case Regex::class:$htmlPattern = $constraint->getHtmlPattern();if (null !== $htmlPattern) {return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE);}break;case Range::class:if (is_numeric($constraint->min)) {return new ValueGuess(sprintf('.{%s,}', \strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE);}break;case Type::class:if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) {return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);}break;}return null;}/*** Iterates over the constraints of a property, executes a constraints on* them and returns the best guess.** @param \Closure $closure The closure that returns a guess* for a given constraint* @param mixed $defaultValue The default value assumed if no other value* can be guessed*/protected function guess(string $class, string $property, \Closure $closure, mixed $defaultValue = null): ?Guess{$guesses = [];$classMetadata = $this->metadataFactory->getMetadataFor($class);if ($classMetadata instanceof ClassMetadataInterface && $classMetadata->hasPropertyMetadata($property)) {foreach ($classMetadata->getPropertyMetadata($property) as $memberMetadata) {foreach ($memberMetadata->getConstraints() as $constraint) {if ($guess = $closure($constraint)) {$guesses[] = $guess;}}}}if (null !== $defaultValue) {$guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);}return Guess::getBestGuess($guesses);}}