Skip to content

Conversation

@LuisDeimos
Copy link
Contributor

@LuisDeimos LuisDeimos commented Oct 26, 2016

Q A
Branch? 2.7
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets 20304
License MIT
Doc PR

Fix: When using a form with an Time type with option 'widget' => 'single_text', and 0 is selected in the seconds, we obtain an TransformationFailedException "Unable to reverse value for property path "[time]": Data missing". Check ticket #20304

}

// handle seconds ignored by user's browser when seconds as single_text is 0
if ($this->parseFormat === 'H:i:s|') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also work without the pipe character set.

// handle seconds ignored by user's browser when seconds as single_text is 0
if ($this->parseFormat === 'H:i:s|') {
if (!preg_match('((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9])(?::[0-5][0-9]))', $value) &&
preg_match('((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9]))', $value)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not only the 2nd preg_match call and use ^..$? And should we consider missing hours and/or minutes as well on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the first run, and we should see only seconds, a lack of hours or minutes (without 'with_minutes' => false) itself should make a validation error it indicates an erroneous entry by the user. Here just we managed the browser omission.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here just we managed the browser omission.

So this doesnt count for minutes and hours then? Sorry no real time to test this. But i proposed are more or less generic approach for "adding sensible defaults to the value". Ie.

format="H", value="", new_value="00"
format="H:i", value="", new_value="00:00"
format="H:i", value="12", new_value="12:00"
etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is why the condition $ this-> parseFormat === 'H: i: s |'.

And, ok, these default values would apply then sent the form (within the SUBMIT events) ?, if so, would work.

The ultimate goal of this is to correct the omission of the latter by the browser when the field requires seconds ('with_seconds' => true), and the user enters 0 seconds, in this case the browser sends '02: 05', in instead of '02: 05: 00 'causing a validation error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I fix this with an new DateTimeType implementing:

    # To fix bug in Symfony. On choice 00 seconds in an DateTime with seconds,
    # is checked as invalid, because browser send the request as '01:00' instead of '01:00:00'.
    # we catch the submission data, and, where appropriate, hand add the missing zeros
    $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $e) {
        $data = $e->getData();
        if ($time = $data['time']) {
            if (!preg_match('((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9])(?::[0-5][0-9]))', $time) &&
                preg_match('((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9]))', $time)) {

                $data['time'] = $time . ":00";
                $e->setData($data);
            }
        }

    });`

Copy link
Contributor

@ro0NL ro0NL Oct 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And perhaps at this point even \d{2}:\d{2}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds great, it would be something like:

preg_match('/\d{2}:\d{2}$/', $time)

the above was to eliminate things like '99: 78 'but still has to go through validation.

testing in TimeType...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ^$ is key here ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, error finger, thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, he's looking good, you think?

$this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData());
}

public function testSubmitWithSecondsAndBrowserOmissionSeconds()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add this to TimeTypeTest.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test may be removed now imo.

Copy link
Contributor Author

@LuisDeimos LuisDeimos Oct 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, is covered by Time Type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok unit test only in TimeType ;)

if ($options['with_seconds']) {
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $e) {
if ($data = $e->getData()) {
if (preg_match('/^\d{2}:\d{2}$/', $data)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be a single if()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    if ($options['with_seconds']) {
        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $e) {
            $data = $e->getData();
            if ($data && preg_match('/^\d{2}:\d{2}$/', $data)) {
                $e->setData($data.':00');
            }
        });
    }`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented suggestions, has not simplified the condition 'if ($ options [' with_seconds '])' to avoid adding an not necessary listener

if ('single_text' === $options['widget']) {
$builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format));

// handle seconds ignored by user's browser when with_seconds enabled and seconds is 00
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add a link to some issue(s) here, ie the chromium one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can leave out and seconds is 00 (actually seconds are omitted which you already mentioned).

@LuisDeimos LuisDeimos changed the title [WIP][Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds [Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds Oct 29, 2016
@xabbuh
Copy link
Member

xabbuh commented Nov 12, 2016

👍

Status: Reviewed

@fabpot
Copy link
Member

fabpot commented Nov 12, 2016

Thank you @LuisDeimos.

fabpot added a commit that referenced this pull request Nov 12, 2016
… single_text and zero seconds (LuisDeimos)

This PR was squashed before being merged into the 2.7 branch (closes #20307).

Discussion
----------

[Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds

| Q | A |
| --- | --- |
| Branch? | 2.7 |
| Bug fix? | yes |
| New feature? | no |
| BC breaks? | no |
| Deprecations? | no |
| Tests pass? | yes |
| Fixed tickets | 20304 |
| License | MIT |
| Doc PR |  |

Fix: When using a form with an Time type with option 'widget' => 'single_text', and 0 is selected in the seconds, we obtain an TransformationFailedException "Unable to reverse value for property path "[time]": Data missing". Check ticket #20304

Commits
-------

bcb03e0 [Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds
@fabpot fabpot closed this Nov 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants