Skip to content

Commit f7200e4

Browse files
julien.galenskiruian
authored andcommitted
[Form] added method guessPattern to FormTypeGuesserInterface
rephrase changelog
1 parent b0a6956 commit f7200e4

File tree

9 files changed

+97
-44
lines changed

9 files changed

+97
-44
lines changed

CHANGELOG-2.1.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
277277
* [BC BREAK] renamed "field_*" theme blocks to "form_*" and "field_widget" to
278278
"input"
279279
* ValidatorTypeGuesser now guesses "collection" for array type constraint
280+
* added method `guessPattern` to FormTypeGuesserInterface to guess which pattern to use in the HTML5 attribute "pattern"
280281

281282
### HttpFoundation
282283

src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public function guessMaxLength($class, $property)
115115
/**
116116
* {@inheritDoc}
117117
*/
118-
public function guessMinLength($class, $property)
118+
public function guessPattern($class, $property)
119119
{
120120
$ret = $this->getMetadata($class);
121121
if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) {

src/Symfony/Bridge/Propel1/Form/PropelTypeGuesser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public function guessMaxLength($class, $property)
124124
/**
125125
* {@inheritDoc}
126126
*/
127-
public function guessMinLength($class, $property)
127+
public function guessPattern($class, $property)
128128
{
129129
if ($column = $this->getColumn($class, $property)) {
130130
switch ($column->getType()) {

src/Symfony/Bridge/Propel1/Tests/Form/PropelTypeGuesserTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ public function testGuessMaxLengthWithFloat()
4646

4747
public function testGuessMinLengthWithText()
4848
{
49-
$value = $this->guesser->guessMinLength(self::CLASS_NAME, 'value');
49+
$value = $this->guesser->guessPattern(self::CLASS_NAME, 'value');
5050

5151
$this->assertNull($value);
5252
}
5353

5454
public function testGuessMinLengthWithFloat()
5555
{
56-
$value = $this->guesser->guessMinLength(self::CLASS_NAME, 'price');
56+
$value = $this->guesser->guessPattern(self::CLASS_NAME, 'price');
5757

5858
$this->assertNotNull($value);
5959
$this->assertNull($value->getValue());

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

100644100755
Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ public function guessMaxLength($class, $property)
6868
/**
6969
* {@inheritDoc}
7070
*/
71-
public function guessMinLength($class, $property)
71+
public function guessPattern($class, $property)
7272
{
7373
$guesser = $this;
7474

7575
return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) {
76-
return $guesser->guessMinLengthForConstraint($constraint);
76+
return $guesser->guessPatternForConstraint($constraint);
7777
});
7878
}
7979

@@ -205,32 +205,35 @@ public function guessMaxLengthForConstraint(Constraint $constraint)
205205
}
206206

207207
/**
208-
* Guesses a field's minimum length based on the given constraint
209-
*
208+
* Guesses a field's pattern based on the given constraint
209+
*
210210
* @param Constraint $constraint The constraint to guess for
211211
*
212-
* @return Guess The guess for the minimum length
212+
* @return Guess The guess for the pattern
213213
*/
214-
public function guessMinLengthForConstraint(Constraint $constraint)
214+
public function guessPatternForConstraint(Constraint $constraint)
215215
{
216216
switch (get_class($constraint)) {
217217
case 'Symfony\Component\Validator\Constraints\MinLength':
218-
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
218+
return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE);
219219

220220
case 'Symfony\Component\Validator\Constraints\SizeLength':
221-
return new ValueGuess($constraint->min, Guess::HIGH_CONFIDENCE);
221+
return new ValueGuess(sprintf('.{%s,%s}', (string) $constraint->min, (string) $constraint->max), Guess::LOW_CONFIDENCE);
222+
223+
case 'Symfony\Component\Validator\Constraints\Regex':
224+
return new ValueGuess($constraint->pattern, Guess::HIGH_CONFIDENCE );
225+
226+
case 'Symfony\Component\Validator\Constraints\Min':
227+
return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE);
222228

229+
case 'Symfony\Component\Validator\Constraints\Size':
230+
return new ValueGuess(sprintf('.{%s,%s}', strlen((string) $constraint->min), strlen((string) $constraint->max)), Guess::LOW_CONFIDENCE);
231+
223232
case 'Symfony\Component\Validator\Constraints\Type':
224233
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
225234
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
226235
}
227236
break;
228-
229-
case 'Symfony\Component\Validator\Constraints\Min':
230-
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
231-
232-
case 'Symfony\Component\Validator\Constraints\Size':
233-
return new ValueGuess(strlen((string) $constraint->min), Guess::LOW_CONFIDENCE);
234237
}
235238
}
236239

src/Symfony/Component/Form/FormFactory.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ public function createNamedBuilder($type, $name, $data = null, array $options =
306306
/**
307307
* Returns a form builder for a property of a class.
308308
*
309-
* If any of the 'max_length', 'required' and type options can be guessed,
309+
* If any of the 'max_length', 'required', 'pattern' and type options can be guessed,
310310
* and are not provided in the options argument, the guessed value is used.
311311
*
312312
* @param string $class The fully qualified class name
@@ -327,27 +327,26 @@ public function createBuilderForProperty($class, $property, $data = null, array
327327

328328
$typeGuess = $this->guesser->guessType($class, $property);
329329
$maxLengthGuess = $this->guesser->guessMaxLength($class, $property);
330-
$minLengthGuess = $this->guesser->guessMinLength($class, $property);
331330
$requiredGuess = $this->guesser->guessRequired($class, $property);
331+
$patternGuess = $this->guesser->guessPattern($class, $property);
332332

333333
$type = $typeGuess ? $typeGuess->getType() : 'text';
334334

335335
$maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null;
336-
$minLength = $minLengthGuess ? $minLengthGuess->getValue() : null;
337-
$minLength = $minLength ?: 0;
336+
$pattern = $patternGuess ? $patternGuess->getValue() : null;
338337

339338
if (null !== $maxLength) {
340339
$options = array_merge(array('max_length' => $maxLength), $options);
341340
}
342341

343-
if ($minLength > 0) {
344-
$options = array_merge(array('pattern' => '.{'.$minLength.','.$maxLength.'}'), $options);
345-
}
346-
347342
if ($requiredGuess) {
348343
$options = array_merge(array('required' => $requiredGuess->getValue()), $options);
349344
}
350345

346+
if (null !== $pattern) {
347+
$options = array_merge(array('pattern' => $pattern), $options);
348+
}
349+
351350
// user options may override guessed options
352351
if ($typeGuess) {
353352
$options = array_merge($typeGuess->getOptions(), $options);

src/Symfony/Component/Form/FormTypeGuesserChain.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,31 +40,43 @@ public function __construct(array $guessers)
4040
}
4141
}
4242

43+
/**
44+
* {@inheritDoc}
45+
*/
4346
public function guessType($class, $property)
4447
{
4548
return $this->guess(function ($guesser) use ($class, $property) {
4649
return $guesser->guessType($class, $property);
4750
});
4851
}
4952

53+
/**
54+
* {@inheritDoc}
55+
*/
5056
public function guessRequired($class, $property)
5157
{
5258
return $this->guess(function ($guesser) use ($class, $property) {
5359
return $guesser->guessRequired($class, $property);
5460
});
5561
}
5662

63+
/**
64+
* {@inheritDoc}
65+
*/
5766
public function guessMaxLength($class, $property)
5867
{
5968
return $this->guess(function ($guesser) use ($class, $property) {
6069
return $guesser->guessMaxLength($class, $property);
6170
});
6271
}
6372

64-
public function guessMinLength($class, $property)
73+
/**
74+
* {@inheritDoc}
75+
*/
76+
public function guessPattern($class, $property)
6577
{
6678
return $this->guess(function ($guesser) use ($class, $property) {
67-
return $guesser->guessMinLength($class, $property);
79+
return $guesser->guessPattern($class, $property);
6880
});
6981
}
7082

src/Symfony/Component/Form/FormTypeGuesserInterface.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,18 @@ function guessRequired($class, $property);
4444
function guessMaxLength($class, $property);
4545

4646
/**
47-
* Returns a guess about the field's minimum length
47+
* Returns a guess about the field's pattern
48+
*
49+
* - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below
50+
* - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess.
51+
* Example:
52+
* You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5)
53+
* @link https://github.com/symfony/symfony/pull/3927
4854
*
4955
* @param string $class The fully qualified class name
5056
* @param string $property The name of the property to guess for
5157
*
52-
* @return Guess A guess for the field's minimum length
58+
* @return Guess A guess for the field's required pattern
5359
*/
54-
function guessMinLength($class, $property);
55-
60+
function guessPattern($class, $property);
5661
}

src/Symfony/Component/Form/Tests/FormFactoryTest.php

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,39 @@ public function testCreateBuilderUsesRequiredSettingWithHighestConfidence()
491491
$this->assertEquals('builderInstance', $builder);
492492
}
493493

494+
public function testCreateBuilderUsesPatternIfFound()
495+
{
496+
$this->guesser1->expects($this->once())
497+
->method('guessPattern')
498+
->with('Application\Author', 'firstName')
499+
->will($this->returnValue(new ValueGuess(
500+
'/[a-z]/',
501+
Guess::MEDIUM_CONFIDENCE
502+
)));
503+
504+
$this->guesser2->expects($this->once())
505+
->method('guessPattern')
506+
->with('Application\Author', 'firstName')
507+
->will($this->returnValue(new ValueGuess(
508+
'/[a-zA-Z]/',
509+
Guess::HIGH_CONFIDENCE
510+
)));
511+
512+
$factory = $this->createMockFactory(array('createNamedBuilder'));
513+
514+
$factory->expects($this->once())
515+
->method('createNamedBuilder')
516+
->with('text', 'firstName', null, array('pattern' => '/[a-zA-Z]/'))
517+
->will($this->returnValue('builderInstance'));
518+
519+
$builder = $factory->createBuilderForProperty(
520+
'Application\Author',
521+
'firstName'
522+
);
523+
524+
$this->assertEquals('builderInstance', $builder);
525+
}
526+
494527
public function testCreateNamedBuilderFromParentBuilder()
495528
{
496529
$type = new FooType();
@@ -541,18 +574,18 @@ public function testUnknownOption()
541574
$factory->createNamedBuilder($type, "text", "value", array("unknown" => "opt"));
542575
}
543576

544-
public function testFormTypeCreatesDefaultValueForEmptyDataOption()
545-
{
546-
$factory = new FormFactory(array(new \Symfony\Component\Form\Extension\Core\CoreExtension()));
547-
548-
$form = $factory->createNamedBuilder(new AuthorType(), 'author')->getForm();
549-
$form->bind(array('firstName' => 'John', 'lastName' => 'Smith'));
550-
551-
$author = new Author();
552-
$author->firstName = 'John';
553-
$author->setLastName('Smith');
554-
555-
$this->assertEquals($author, $form->getData());
577+
public function testFieldTypeCreatesDefaultValueForEmptyDataOption()
578+
{
579+
$factory = new FormFactory(array(new \Symfony\Component\Form\Extension\Core\CoreExtension()));
580+
581+
$form = $factory->createNamedBuilder(new AuthorType(), 'author')->getForm();
582+
$form->bind(array('firstName' => 'John', 'lastName' => 'Smith'));
583+
584+
$author = new Author();
585+
$author->firstName = 'John';
586+
$author->setLastName('Smith');
587+
588+
$this->assertEquals($author, $form->getData());
556589
}
557590

558591
private function createMockFactory(array $methods = array())

0 commit comments

Comments
 (0)