Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

[Form] Refactor guessing of form options and added min and max guessing #9759

Closed
wants to merge 20 commits into
from

Conversation

Projects
None yet
8 participants
Q A
Bug fix? no
New feature? yes
BC breaks? FormTypeGuesserInterface change
Deprecations? max_length and pattern form options
Tests pass? yes
Fixed tickets #6732
License MIT

We worked on issue #6732 and we added automatically min and max attributes to integer type based on Range validator.
It should work also for numeric type, but at the moment it is being rendered as "text" input type. Is there a specific reason beside the comment "type="number" doesn't work with floats"?

We are now working on implementing a guess{Max|Min}Value on Doctrine and Propel guesser.

Credits: @dlondero

@bschussek: It can work also for number type, but at the moment it is being rendered as "text" input type. Is there a specific reason beside the comment "type="number" doesn't work with floats"?

@cordoval cordoval and 1 other commented on an outdated diff Dec 14, 2013

src/Symfony/Component/Form/Tests/FormFactoryTest.php
@@ -504,6 +504,109 @@ public function testCreateBuilderUsesMaxLengthIfFound()
$this->assertEquals('builderInstance', $this->builder);
}
+ public function testCreateBuilderUsesMinAndMaxValueIfFound()
+ {
+ $this->guesser1->expects($this->once())
+ ->method('guessType')
+ ->will($this->returnValue(new TypeGuess(
+ 'integer',
+ array(),
+ Guess::HIGH_CONFIDENCE
+ )));
@cordoval

cordoval Dec 14, 2013

Contributor

thought ubot could detect this wrong indentation

@stefanosala

stefanosala Dec 14, 2013

Let's wait for him to come and check, I'll prepare a fix.

@stefanosala

stefanosala Dec 14, 2013

Apparently he is not so fast, I'll push my fix right now :)

Contributor

webmozart commented Dec 17, 2013

I don't like the original approach that I chose for the type guessers too much anymore. I think instead of adding more methods to that interface, we should try to simplify it:

public function guessType($class, $property);

public function guessOptions($class, $property, $type);

The first method would be basically the same as now, except that it would return only the type, and not the options. (BC should be kept somehow at this point) The second method would then return the options for a class property, given that type $type was selected.

The difference to the current behavior would be that guessOptions() should always be used, even if a type is manually provided.

Do you want to implement this change?

I definitely agree and I can work on it.

I started working on it from the ValidatorTypeGuesser and the max_length option.
@bschussek can you please check if this is the direction you imagined?

@webmozart webmozart commented on an outdated diff Dec 28, 2013

...ent/Form/Extension/Validator/ValidatorTypeGuesser.php
@@ -42,6 +42,24 @@ public function guessType($class, $property)
/**
* {@inheritDoc}
*/
+ public function guessOptions($class, $property, $type)
@webmozart

webmozart Dec 28, 2013

Contributor

You should add the type hint ResolvedFormTypeInterface to the $type argument.

@webmozart webmozart commented on an outdated diff Dec 28, 2013

...ent/Form/Extension/Validator/ValidatorTypeGuesser.php
@@ -42,6 +42,24 @@ public function guessType($class, $property)
/**
* {@inheritDoc}
*/
+ public function guessOptions($class, $property, $type)
+ {
+ $options = array();
+
+ switch ($type) {
@webmozart

webmozart Dec 28, 2013

Contributor

Instead of the switch, you can do:

if ($type->getOptionsResolver()->isKnown('max_length')) {
Contributor

webmozart commented Dec 28, 2013

Yes, looks good! :)

Owner

fabpot commented Dec 31, 2013

@stewe I see that this PR is WIP; will you have time to finish it in the near future?

Yes, I'm working on it. Hope to complete it before the end of the week.

Done. Let's just recap a couple of things:

  • I deprecated the options max_length and pattern and moved them to the attr option;
  • I added the guessing of min and max attributes;

Please review my commits and let me know if I need to adjust or add something and let me know if I need to squash the commits.
Thank you!

Owner

fabpot commented Jan 4, 2014

@bschussek Can you review this one please?

@Tobion Tobion commented on an outdated diff Jan 5, 2014

...mfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php
@@ -122,7 +140,7 @@ public function guessRequired($class, $property)
/**
* {@inheritDoc}
*/
- public function guessMaxLength($class, $property)
+ protected function guessMaxLength($class, $property)
@Tobion

Tobion Jan 5, 2014

Member

why protected? As far as I see, it's not used for inheritance. So it should either be private or public (for BC).
Applies to all of these changes.

@Tobion Tobion commented on an outdated diff Jan 5, 2014

src/Symfony/Component/Form/FormTypeGuesserInterface.php
*
- * @return Guess\ValueGuess|null A guess for the field's maximum length
+ * @return array An array of guesses for the field's attributes
@Tobion

Tobion Jan 5, 2014

Member

Guess\ValueGuess[]

Wait, tests are failing, let me fix them.

@stloyd stloyd commented on an outdated diff Jan 5, 2014

...y/Bridge/Propel1/Tests/Form/PropelTypeGuesserTest.php
- $this->assertNotNull($value);
- $this->assertNull($value->getValue());
+ $this->assertArrayHasKey('maxlength', $attributes);
+ $this->assertEquals(null, $attributes['maxlength']->getValue());
@stloyd

stloyd Jan 5, 2014

Contributor

assertNull() same below.

@stloyd stloyd commented on an outdated diff Jan 5, 2014

...ent/Form/Extension/Validator/ValidatorTypeGuesser.php
@@ -225,6 +301,46 @@ public function guessMaxLengthForConstraint(Constraint $constraint)
}
/**
+ * Guesses a field's maximum value based on the given constraint
+ *
+ * @param Constraint $constraint The constraint to guess for
+ *
+ * @return ValueGuess|null The guess for the maximum value
+ */
+ public function guessMaxValueForConstraint(Constraint $constraint)
+ {
+ switch (get_class($constraint)) {
@stloyd

stloyd Jan 5, 2014

Contributor

Why switch()? And not i.e.:

if ($constraint instanceof Range && is_numeric($constraint->max)) {
    return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
}

@stloyd stloyd commented on an outdated diff Jan 5, 2014

src/Symfony/Component/Form/FormFactory.php
@@ -129,6 +135,20 @@ public function createBuilderForProperty($class, $property, $data = null, array
$options = array_merge($typeGuess->getOptions(), $options);
}
+ $filteredAttributes = array();
+
+ foreach ($guessedAttributes as $key => $value) {
+ if (null !== $value->getValue() && isset($this->supportedAttributes[$type]) && in_array($key, $this->supportedAttributes[$type])) {
+ $filteredAttributes[$key] = $value->getValue();
+ }
+ }
+
+ if (count($filteredAttributes)) {
@stloyd

stloyd Jan 5, 2014

Contributor

!empty($filteredAttributes)? As you just want to know there are some filtered attributes, and not how many of them.

@stloyd stloyd commented on an outdated diff Jan 5, 2014

src/Symfony/Component/Form/FormTypeGuesserChain.php
- /**
- * {@inheritDoc}
- */
- public function guessPattern($class, $property)
- {
- return $this->guess(function ($guesser) use ($class, $property) {
- return $guesser->guessPattern($class, $property);
- });
+ // Cleanup attributes if I get the same attribute from different guessers.
+ foreach ($this->guessers as $guesser) {
+ $guessedAttributes = $guesser->guessAttributes($class, $property);
+
+ if (false === is_array($guessedAttributes)) {
@stloyd

stloyd Jan 5, 2014

Contributor

Just if (!is_array($guessedAttributes)) { is enough.

@stloyd stloyd and 2 others commented on an outdated diff Jan 5, 2014

src/Symfony/Component/Form/FormTypeGuesserInterface.php
*/
- public function guessMaxLength($class, $property);
+ public function guessAttributes($class, $property);
@stloyd

stloyd Jan 5, 2014

Contributor

Removal of guessMaxLength() + guessPattern() from interface is BC break.

@stefanosala

stefanosala Jan 5, 2014

Yes, I know. What do you suggest?

@wouterj

wouterj Jan 5, 2014

Member

afaik, it's not a BC break as it doesn't fail when you have an extra method in the interface (as long as you keep the 2 methods in the core classes as a BC layer).

The BC break is adding guessAttributes and guessRequired to the interface.

@stloyd

stloyd Jan 5, 2014

Contributor

IIRC old methods must be still in interface, but with @deprecated phpdoc with note (for details look around code, there is plenty of examples), adding new ones to interface is as BC break too.

@stefanosala

stefanosala Jan 5, 2014

Is that ok or should I remove the new method too?

@stloyd @Tobion thanks for your review.

@Tobion Tobion and 1 other commented on an outdated diff Jan 5, 2014

...mfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php
@@ -120,7 +138,12 @@ public function guessRequired($class, $property)
}
/**
- * {@inheritDoc}
@Tobion

Tobion Jan 5, 2014

Member

Since you changed to @deprecated you can use @inheritdoc again.

Ping?

Contributor

webmozart commented Jan 7, 2014

Hi @stewe, thank you for the awesome PR! Some feedback:

  • This PR currently contains two different changes: The deprecation of the "max_length" and "pattern" options, and the change of the value guesser. Could you do the option deprecation in a separate PR? This PR will be quite small and quick to review and merge.
  • You added a new method guessAttributes(), but I suggested guessOptions() with a slightly different signature above. Could you change this? guessOptions() should then return an array with the "attr" option set.

Hi @bschussek, thanks for you reply.

  • Yes, I will.
  • I'm sorry, I didn't write you back my consideration.

If guessOptions($class, $property, ResolvedFormTypeInterface $type) is the signature of the method, how can I:

  • get a ResolvedFormTypeInterface in FormFactory?
  • check that the ResolvedFormTypeInterface supports a particular attribute?

fabpot added a commit that referenced this pull request Mar 26, 2014

feature #10001 [Form] Deprecated max_length and pattern options (stef…
…anosala)

This PR was squashed before being merged into the 2.5-dev branch (closes #10001).

Discussion
----------

[Form] Deprecated max_length and pattern options

Split of issue #9759

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | `max_length` and `pattern` in form options
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | symfony/symfony-docs#3461

Commits
-------

52c07c7 Deprecated max_length and pattern options
Owner

fabpot commented Mar 26, 2014

#10001 has been merged now, so this PR should probably be rebased.

Contributor

sstok commented Jul 27, 2014

@sstok I could rebase this, but honestly I have no idea how to go on on this.

I will close this in favour of #7868

@stefanosala stefanosala deleted the stefanosala:issue-6732 branch Sep 25, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment