Skip to content

Commit

Permalink
feature #36302 [Form] Add the html5 option to ColorType to validate t…
Browse files Browse the repository at this point in the history
…he input (fancyweb)

This PR was merged into the 5.1-dev branch.

Discussion
----------

[Form] Add the html5 option to ColorType to validate the input

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | no
| License       | MIT
| Doc PR        | TODO

Continuation of #35626.

I'm resubmitting the initial implementation, this time in the Form component.

This `Color` constraint is dedicated to the HTML5 input type="color".

Commits
-------

454b6ff [Form] Add the html5 option to ColorType to validate the input
  • Loading branch information
fabpot committed May 5, 2020
2 parents b494beb + 454b6ff commit 341ea45
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
Expand Up @@ -74,6 +74,10 @@
<tag name="form.type" />
<argument type="service" id="translator" on-invalid="ignore" />
</service>
<service id="form.type.color" class="Symfony\Component\Form\Extension\Core\Type\ColorType">
<tag name="form.type" />
<argument type="service" id="translator" on-invalid="ignore" />
</service>

<service id="form.type_extension.form.transformation_failure_handling" class="Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension">
<tag name="form.type_extension" extended-type="Symfony\Component\Form\Extension\Core\Type\FormType" />
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Expand Up @@ -19,6 +19,7 @@ CHANGELOG
is deprecated. The method will be added to the interface in 6.0.
* Added a `rounding_mode` option for the PercentType and correctly round the value when submitted
* Deprecated `Symfony\Component\Form\Extension\Validator\Util\ServerParams` in favor of its parent class `Symfony\Component\Form\Util\ServerParams`
* Added the `html5` option to the `ColorType` to validate the input

5.0.0
-----
Expand Down
Expand Up @@ -75,7 +75,7 @@ protected function loadTypes()
new Type\ResetType(),
new Type\CurrencyType(),
new Type\TelType(),
new Type\ColorType(),
new Type\ColorType($this->translator),
new Type\WeekType(),
];
}
Expand Down
59 changes: 59 additions & 0 deletions src/Symfony/Component/Form/Extension/Core/Type/ColorType.php
Expand Up @@ -12,9 +12,68 @@
namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;

class ColorType extends AbstractType
{
/**
* @see https://www.w3.org/TR/html52/sec-forms.html#color-state-typecolor
*/
private const HTML5_PATTERN = '/^#[0-9a-f]{6}$/i';

private $translator;

public function __construct(TranslatorInterface $translator = null)
{
$this->translator = $translator;
}

/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (!$options['html5']) {
return;
}

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event): void {
$value = $event->getData();
if (null === $value || '' === $value) {
return;
}

if (\is_string($value) && preg_match(self::HTML5_PATTERN, $value)) {
return;
}

$messageTemplate = 'This value is not a valid HTML5 color.';
$messageParameters = [
'{{ value }}' => is_scalar($value) ? (string) $value : \gettype($value),
];
$message = $this->translator ? $this->translator->trans($messageTemplate, $messageParameters, 'validators') : $messageTemplate;

$event->getForm()->addError(new FormError($message, $messageTemplate, $messageParameters));
});
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'html5' => false,
]);

$resolver->setAllowedTypes('html5', 'bool');
}

/**
* {@inheritdoc}
*/
Expand Down
Expand Up @@ -14,6 +14,10 @@
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
<target>The CSRF token is invalid. Please try to resubmit the form.</target>
</trans-unit>
<trans-unit id="99">
<source>This value is not a valid HTML5 color.</source>
<target>This value is not a valid HTML5 color.</target>
</trans-unit>
</body>
</file>
</xliff>
Expand Up @@ -14,6 +14,10 @@
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
<target>Le jeton CSRF est invalide. Veuillez renvoyer le formulaire.</target>
</trans-unit>
<trans-unit id="99">
<source>This value is not a valid HTML5 color.</source>
<target>Cette valeur n'est pas une couleur HTML5 valide.</target>
</trans-unit>
</body>
</file>
</xliff>
@@ -0,0 +1,89 @@
<?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\Tests\Extension\Core\Type;

use Symfony\Component\Form\Extension\Core\Type\ColorType;
use Symfony\Component\Form\FormError;

final class ColorTypeTest extends BaseTypeTest
{
const TESTED_TYPE = ColorType::class;

/**
* @dataProvider validationShouldPassProvider
*/
public function testValidationShouldPass(bool $html5, ?string $submittedValue)
{
$form = $this->factory->create(static::TESTED_TYPE, null, [
'html5' => $html5,
'trim' => true,
]);

$form->submit($submittedValue);

$this->assertEmpty($form->getErrors());
}

public function validationShouldPassProvider()
{
return [
[false, 'foo'],
[false, null],
[false, ''],
[false, ' '],
[true, '#000000'],
[true, '#abcabc'],
[true, '#BbBbBb'],
[true, '#1Ee54d'],
[true, ' #1Ee54d '],
[true, null],
[true, ''],
[true, ' '],
];
}

/**
* @dataProvider validationShouldFailProvider
*/
public function testValidationShouldFail(string $expectedValueParameterValue, ?string $submittedValue, bool $trim = true)
{
$form = $this->factory->create(static::TESTED_TYPE, null, [
'html5' => true,
'trim' => $trim,
]);

$form->submit($submittedValue);

$expectedFormError = new FormError('This value is not a valid HTML5 color.', 'This value is not a valid HTML5 color.', [
'{{ value }}' => $expectedValueParameterValue,
]);
$expectedFormError->setOrigin($form);

$this->assertEquals([$expectedFormError], iterator_to_array($form->getErrors()));
}

public function validationShouldFailProvider()
{
return [
['foo', 'foo'],
['000000', '000000'],
['#abcabg', '#abcabg'],
['#12345', '#12345'],
[' #ffffff ', ' #ffffff ', false],
];
}

public function testSubmitNull($expected = null, $norm = null, $view = null)
{
parent::testSubmitNull($expected, $norm, '');
}
}

0 comments on commit 341ea45

Please sign in to comment.