merged branch vicb/form/guess/length (PR #3645)
Commits
-------
fc7c7f6
[Form] Fix min/max length guessing for numeric types (fix #3091)
Discussion
----------
[Form] Fix min/max length guessing for numeric types (fix #3091)
Before this PR, the length was guessed from `strlen(min/max)`.
This is obviously false for float: `strlen("1.123") > strlen ("5")` then this guess is now low confidence only and is masked by a `null` medium confidence guess for floats (implemented in both doctrine ORM & validator).
This PR also includes some code reorg in order to improve readability.
I'll update Propel & Mongo if needed once this is merged.
_note: `5.000` did neither work because of `5e3`_
---------------------------------------------------------------------------
by Koc at 2012-03-19T23:42:01Z
Will `strlen` works correctly with multibyte strings?
---------------------------------------------------------------------------
by vicb at 2012-03-19T23:58:33Z
could numeric types be multibyte strings ?
---------------------------------------------------------------------------
by Koc at 2012-03-20T00:07:24Z
I thought it somehow concerns `Symfony\Component\Validator\Constraints\MaxLengthValidator` too.
---------------------------------------------------------------------------
by vicb at 2012-03-20T00:20:33Z
This PR is about numeric types only and the MaxLengthValidator is [multibyte safe:](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Constraints/MaxLengthValidator.php#L45)
This commit is contained in:
commit
9cdc9712b0
@ -60,6 +60,8 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
||||
return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE);
|
||||
case 'date':
|
||||
return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE);
|
||||
case 'time':
|
||||
return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE);
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
@ -71,8 +73,6 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
||||
return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
case 'text':
|
||||
return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
case 'time':
|
||||
return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE);
|
||||
default:
|
||||
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
@ -105,6 +105,10 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
||||
if (isset($mapping['length'])) {
|
||||
return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
|
||||
}
|
||||
|
||||
if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) {
|
||||
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,6 +117,14 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
||||
*/
|
||||
public function guessMinLength($class, $property)
|
||||
{
|
||||
$ret = $this->getMetadata($class);
|
||||
if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) {
|
||||
$mapping = $ret[0]->getFieldMapping($property);
|
||||
|
||||
if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) {
|
||||
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getMetadata($class)
|
||||
|
@ -89,150 +89,68 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
switch ($constraint->type) {
|
||||
case 'boolean':
|
||||
case 'bool':
|
||||
return new TypeGuess(
|
||||
'checkbox',
|
||||
array(),
|
||||
Guess::MEDIUM_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
|
||||
case 'double':
|
||||
case 'float':
|
||||
case 'numeric':
|
||||
case 'real':
|
||||
return new TypeGuess(
|
||||
'number',
|
||||
array(),
|
||||
Guess::MEDIUM_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
|
||||
case 'integer':
|
||||
case 'int':
|
||||
case 'long':
|
||||
return new TypeGuess(
|
||||
'integer',
|
||||
array(),
|
||||
Guess::MEDIUM_CONFIDENCE
|
||||
);
|
||||
case 'string':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
|
||||
case '\DateTime':
|
||||
return new TypeGuess(
|
||||
'date',
|
||||
array(),
|
||||
Guess::MEDIUM_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
|
||||
case 'string':
|
||||
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Country':
|
||||
return new TypeGuess(
|
||||
'country',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Date':
|
||||
return new TypeGuess(
|
||||
'date',
|
||||
array('type' => 'string'),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('date', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\DateTime':
|
||||
return new TypeGuess(
|
||||
'datetime',
|
||||
array('type' => 'string'),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('datetime', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Email':
|
||||
return new TypeGuess(
|
||||
'email',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\File':
|
||||
return new TypeGuess(
|
||||
'file',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Image':
|
||||
return new TypeGuess(
|
||||
'file',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Ip':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::MEDIUM_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Language':
|
||||
return new TypeGuess(
|
||||
'language',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Locale':
|
||||
return new TypeGuess(
|
||||
'locale',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Max':
|
||||
return new TypeGuess(
|
||||
'number',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Min':
|
||||
return new TypeGuess(
|
||||
'number',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\MinLength':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Regex':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Time':
|
||||
return new TypeGuess(
|
||||
'time',
|
||||
array('type' => 'string'),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('time', array('type' => 'string'), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Url':
|
||||
return new TypeGuess(
|
||||
'url',
|
||||
array(),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Size':
|
||||
return new TypeGuess(
|
||||
'number',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Ip':
|
||||
return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
||||
case 'Symfony\Component\Validator\Constraints\MinLength':
|
||||
case 'Symfony\Component\Validator\Constraints\Regex':
|
||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
||||
return new TypeGuess(
|
||||
'text',
|
||||
array(),
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Min':
|
||||
case 'Symfony\Component\Validator\Constraints\Size':
|
||||
case 'Symfony\Component\Validator\Constraints\Max':
|
||||
return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,20 +165,11 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
{
|
||||
switch (get_class($constraint)) {
|
||||
case 'Symfony\Component\Validator\Constraints\NotNull':
|
||||
return new ValueGuess(
|
||||
true,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\NotBlank':
|
||||
return new ValueGuess(
|
||||
true,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
|
||||
|
||||
default:
|
||||
return new ValueGuess(
|
||||
false,
|
||||
Guess::LOW_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess(false, Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,25 +184,21 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
{
|
||||
switch (get_class($constraint)) {
|
||||
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
||||
return new ValueGuess(
|
||||
$constraint->limit,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Max':
|
||||
return new ValueGuess(
|
||||
strlen((string) $constraint->limit),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
||||
return new ValueGuess(
|
||||
$constraint->max,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Type':
|
||||
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
|
||||
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
|
||||
}
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Max':
|
||||
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Size':
|
||||
return new ValueGuess(
|
||||
strlen((string) $constraint->max),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,25 +213,21 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||
{
|
||||
switch (get_class($constraint)) {
|
||||
case 'Symfony\Component\Validator\Constraints\MinLength':
|
||||
return new ValueGuess(
|
||||
$constraint->limit,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
case 'Symfony\Component\Validator\Constraints\Min':
|
||||
return new ValueGuess(
|
||||
strlen((string) $constraint->limit),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
||||
return new ValueGuess(
|
||||
$constraint->min,
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess($constraint->min, Guess::HIGH_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Type':
|
||||
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
|
||||
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
|
||||
}
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Min':
|
||||
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
||||
|
||||
case 'Symfony\Component\Validator\Constraints\Size':
|
||||
return new ValueGuess(
|
||||
strlen((string) $constraint->min),
|
||||
Guess::HIGH_CONFIDENCE
|
||||
);
|
||||
return new ValueGuess(strlen((string) $constraint->min), Guess::LOW_CONFIDENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,16 +349,16 @@ class FormFactory implements FormFactoryInterface
|
||||
|
||||
$type = $typeGuess ? $typeGuess->getType() : 'text';
|
||||
|
||||
if ($maxLengthGuess) {
|
||||
$options = array_merge(array('max_length' => $maxLengthGuess->getValue()), $options);
|
||||
$maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null;
|
||||
$minLength = $minLengthGuess ? $minLengthGuess->getValue() : null;
|
||||
$minLength = $minLength ?: 0;
|
||||
|
||||
if (null !== $maxLength) {
|
||||
$options = array_merge(array('max_length' => $maxLength), $options);
|
||||
}
|
||||
|
||||
if ($minLengthGuess) {
|
||||
if ($maxLengthGuess) {
|
||||
$options = array_merge(array('pattern' => '.{'.$minLengthGuess->getValue().','.$maxLengthGuess->getValue().'}'), $options);
|
||||
} else {
|
||||
$options = array_merge(array('pattern' => '.{'.$minLengthGuess->getValue().',}'), $options);
|
||||
}
|
||||
if ($minLength > 0) {
|
||||
$options = array_merge(array('pattern' => '.{'.$minLength.','.$maxLength.'}'), $options);
|
||||
}
|
||||
|
||||
if ($requiredGuess) {
|
||||
|
Reference in New Issue
Block a user