prevent duplicated error message for file upload limits

This commit is contained in:
Christian Flothmann 2020-11-19 19:56:09 +01:00
parent b60bb6e2d6
commit fe6a2dd64f
4 changed files with 132 additions and 2 deletions

View File

@ -12,8 +12,8 @@
namespace Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FileUploadError;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
@ -171,7 +171,7 @@ class FileType extends AbstractType
$message = strtr($messageTemplate, $messageParameters);
}
return new FormError($message, $messageTemplate, $messageParameters);
return new FileUploadError($message, $messageTemplate, $messageParameters);
}
/**

View File

@ -11,12 +11,14 @@
namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;
use Symfony\Component\Form\FileUploadError;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Util\InheritDataAwareIterator;
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
use Symfony\Component\PropertyAccess\PropertyPathIterator;
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\ConstraintViolation;
/**
@ -124,6 +126,23 @@ class ViolationMapper implements ViolationMapperInterface
// Only add the error if the form is synchronized
if ($this->acceptsErrors($scope)) {
if ($violation->getConstraint() instanceof File && (string) \UPLOAD_ERR_INI_SIZE === $violation->getCode()) {
$errorsTarget = $scope;
while (null !== $errorsTarget->getParent() && $errorsTarget->getConfig()->getErrorBubbling()) {
$errorsTarget = $errorsTarget->getParent();
}
$errors = $errorsTarget->getErrors();
$errorsTarget->clearErrors();
foreach ($errors as $error) {
if (!$error instanceof FileUploadError) {
$errorsTarget->addError($error);
}
}
}
$scope->addError(new FormError(
$violation->getMessage(),
$violation->getMessageTemplate(),

View File

@ -0,0 +1,19 @@
<?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;
/**
* @internal
*/
class FileUploadError extends FormError
{
}

View File

@ -18,12 +18,14 @@ use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
use Symfony\Component\Form\FileUploadError;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormConfigBuilder;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper\Fixtures\Issue;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationInterface;
@ -81,6 +83,7 @@ class ViolationMapperTest extends TestCase
$config->setPropertyPath($propertyPath);
$config->setCompound(true);
$config->setDataMapper(new PropertyPathMapper());
$config->setErrorBubbling($options['error_bubbling'] ?? false);
if (!$synchronized) {
$config->addViewTransformer(new CallbackTransformer(
@ -1590,4 +1593,93 @@ class ViolationMapperTest extends TestCase
$this->assertEquals([$this->getFormError($violation2, $grandChild2)], iterator_to_array($grandChild2->getErrors()), $grandChild2->getName().' should have an error, but has none');
$this->assertEquals([$this->getFormError($violation3, $grandChild3)], iterator_to_array($grandChild3->getErrors()), $grandChild3->getName().' should have an error, but has none');
}
public function testFileUploadErrorIsNotRemovedIfNoFileSizeConstraintViolationWasRaised()
{
$form = $this->getForm('form');
$form->addError(new FileUploadError(
'The file is too large. Allowed maximum size is 2 MB.',
'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.',
[
'{{ limit }}' => '2',
'{{ suffix }}' => 'MB',
]
));
$this->mapper->mapViolation($this->getConstraintViolation('data'), $form);
$this->assertCount(2, $form->getErrors());
}
public function testFileUploadErrorIsRemovedIfFileSizeConstraintViolationWasRaised()
{
$form = $this->getForm('form');
$form->addError(new FileUploadError(
'The file is too large. Allowed maximum size is 2 MB.',
'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.',
[
'{{ limit }}' => '2',
'{{ suffix }}' => 'MB',
]
));
$violation = new ConstraintViolation(
'The file is too large (3 MB). Allowed maximum size is 2 MB.',
'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.',
[
'{{ limit }}' => '2',
'{{ size }}' => '3',
'{{ suffix }}' => 'MB',
],
'',
'data',
null,
null,
(string) \UPLOAD_ERR_INI_SIZE,
new File()
);
$this->mapper->mapViolation($this->getConstraintViolation('data'), $form);
$this->mapper->mapViolation($violation, $form);
$this->assertCount(2, $form->getErrors());
}
public function testFileUploadErrorIsRemovedIfFileSizeConstraintViolationWasRaisedOnFieldWithErrorBubbling()
{
$parent = $this->getForm('parent');
$child = $this->getForm('child', 'file', null, [], false, true, [
'error_bubbling' => true,
]);
$parent->add($child);
$child->addError(new FileUploadError(
'The file is too large. Allowed maximum size is 2 MB.',
'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.',
[
'{{ limit }}' => '2',
'{{ suffix }}' => 'MB',
]
));
$violation = new ConstraintViolation(
'The file is too large (3 MB). Allowed maximum size is 2 MB.',
'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.',
[
'{{ limit }}' => '2',
'{{ size }}' => '3',
'{{ suffix }}' => 'MB',
],
null,
'data.file',
null,
null,
(string) \UPLOAD_ERR_INI_SIZE,
new File()
);
$this->mapper->mapViolation($this->getConstraintViolation('data'), $parent);
$this->mapper->mapViolation($this->getConstraintViolation('data.file'), $parent);
$this->mapper->mapViolation($violation, $parent);
$this->assertCount(3, $parent->getErrors());
$this->assertCount(0, $child->getErrors());
}
}