Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c2b6ef4

Browse files
author
Kevin Auvinet
committed
Add the option filenameMaxLength to the File constraint
1 parent c83aadb commit c2b6ef4

File tree

5 files changed

+72
-4
lines changed

5 files changed

+72
-4
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add method `getConstraint()` to `ConstraintViolationInterface`
88
* Add `Uuid::TIME_BASED_VERSIONS` to match that a UUID being validated embeds a timestamp
99
* Add the `pattern` parameter in violations of the `Regex` constraint
10+
* Add the `filenameMaxLength` option to the `File` constraint
1011

1112
6.2
1213
---

src/Symfony/Component/Validator/Constraints/File.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ class File extends Constraint
3333
public const TOO_LARGE_ERROR = 'df8637af-d466-48c6-a59d-e7126250a654';
3434
public const INVALID_MIME_TYPE_ERROR = '744f00bc-4389-4c74-92de-9a43cde55534';
3535
public const INVALID_EXTENSION_ERROR = 'c8c7315c-6186-4719-8b71-5659e16bdcb7';
36+
public const FILENAME_TOO_LONG = 'e5706483-91a8-49d8-9a59-5e81a3c634a8';
3637

3738
protected const ERROR_NAMES = [
3839
self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR',
3940
self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR',
4041
self::EMPTY_ERROR => 'EMPTY_ERROR',
4142
self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR',
4243
self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR',
44+
self::FILENAME_TOO_LONG => 'FILENAME_TOO_LONG',
4345
];
4446

4547
/**
@@ -49,13 +51,15 @@ class File extends Constraint
4951

5052
public $binaryFormat;
5153
public $mimeTypes = [];
54+
public int|null $filenameMaxLength = null;
5255
public array|string|null $extensions = [];
5356
public $notFoundMessage = 'The file could not be found.';
5457
public $notReadableMessage = 'The file is not readable.';
5558
public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.';
5659
public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.';
5760
public string $extensionsMessage = 'The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}.';
5861
public $disallowEmptyMessage = 'An empty file is not allowed.';
62+
public $filenameTooLongMessage = 'The filename is too long. It should have {{ filename_max_length }} character or less.';
5963

6064
public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
6165
public $uploadFormSizeErrorMessage = 'The file is too large.';
@@ -76,11 +80,13 @@ public function __construct(
7680
int|string $maxSize = null,
7781
bool $binaryFormat = null,
7882
array|string $mimeTypes = null,
83+
int $filenameMaxLength = null,
7984
string $notFoundMessage = null,
8085
string $notReadableMessage = null,
8186
string $maxSizeMessage = null,
8287
string $mimeTypesMessage = null,
8388
string $disallowEmptyMessage = null,
89+
string $filenameTooLongMessage= null,
8490

8591
string $uploadIniSizeErrorMessage = null,
8692
string $uploadFormSizeErrorMessage = null,
@@ -101,13 +107,15 @@ public function __construct(
101107
$this->maxSize = $maxSize ?? $this->maxSize;
102108
$this->binaryFormat = $binaryFormat ?? $this->binaryFormat;
103109
$this->mimeTypes = $mimeTypes ?? $this->mimeTypes;
110+
$this->filenameMaxLength = $filenameMaxLength ?? $this->filenameMaxLength;
104111
$this->extensions = $extensions ?? $this->extensions;
105112
$this->notFoundMessage = $notFoundMessage ?? $this->notFoundMessage;
106113
$this->notReadableMessage = $notReadableMessage ?? $this->notReadableMessage;
107114
$this->maxSizeMessage = $maxSizeMessage ?? $this->maxSizeMessage;
108115
$this->mimeTypesMessage = $mimeTypesMessage ?? $this->mimeTypesMessage;
109116
$this->extensionsMessage = $extensionsMessage ?? $this->extensionsMessage;
110117
$this->disallowEmptyMessage = $disallowEmptyMessage ?? $this->disallowEmptyMessage;
118+
$this->filenameTooLongMessage = $filenameTooLongMessage ?? $this->filenameTooLongMessage;
111119
$this->uploadIniSizeErrorMessage = $uploadIniSizeErrorMessage ?? $this->uploadIniSizeErrorMessage;
112120
$this->uploadFormSizeErrorMessage = $uploadFormSizeErrorMessage ?? $this->uploadFormSizeErrorMessage;
113121
$this->uploadPartialErrorMessage = $uploadPartialErrorMessage ?? $this->uploadPartialErrorMessage;

src/Symfony/Component/Validator/Constraints/FileValidator.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,19 @@ public function validate(mixed $value, Constraint $constraint)
143143
$sizeInBytes = filesize($path);
144144
$basename = $value instanceof UploadedFile ? $value->getClientOriginalName() : basename($path);
145145

146+
if ($constraint->filenameMaxLength) {
147+
$filenameLength = strlen($basename);
148+
149+
if ($filenameLength > $constraint->filenameMaxLength) {
150+
$this->context->buildViolation($constraint->filenameTooLongMessage)
151+
->setParameter('{{ filename_max_length }}', $this->formatValue($constraint->filenameMaxLength))
152+
->setCode(File::FILENAME_TOO_LONG)
153+
->addViolation();
154+
155+
return;
156+
}
157+
}
158+
146159
if (0 === $sizeInBytes) {
147160
$this->context->buildViolation($constraint->disallowEmptyMessage)
148161
->setParameter('{{ file }}', $this->formatValue($path))

src/Symfony/Component/Validator/Constraints/Image.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public function __construct(
9898
int|string $maxSize = null,
9999
bool $binaryFormat = null,
100100
array $mimeTypes = null,
101+
int $filenameMaxLength = null,
101102
int $minWidth = null,
102103
int $maxWidth = null,
103104
int $maxHeight = null,
@@ -115,6 +116,7 @@ public function __construct(
115116
string $maxSizeMessage = null,
116117
string $mimeTypesMessage = null,
117118
string $disallowEmptyMessage = null,
119+
string $filenameTooLongMessage= null,
118120
string $uploadIniSizeErrorMessage = null,
119121
string $uploadFormSizeErrorMessage = null,
120122
string $uploadPartialErrorMessage = null,
@@ -144,11 +146,13 @@ public function __construct(
144146
$maxSize,
145147
$binaryFormat,
146148
$mimeTypes,
149+
$filenameMaxLength,
147150
$notFoundMessage,
148151
$notReadableMessage,
149152
$maxSizeMessage,
150153
$mimeTypesMessage,
151154
$disallowEmptyMessage,
155+
$filenameTooLongMessage,
152156
$uploadIniSizeErrorMessage,
153157
$uploadFormSizeErrorMessage,
154158
$uploadPartialErrorMessage,

src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTestCase.php

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ public function testNegativeMaxSize()
531531
}
532532

533533
/**
534-
* @dataProvider validExtensionProvider
534+
* @dataProvider providerValidExtension
535535
*/
536536
public function testExtensionValid(string $name)
537537
{
@@ -551,7 +551,7 @@ public function testExtensionValid(string $name)
551551
$this->assertNoViolation();
552552
}
553553

554-
private static function validExtensionProvider(): iterable
554+
public static function providerValidExtension(): iterable
555555
{
556556
yield ['test.gif'];
557557
yield ['test.png.gif'];
@@ -560,7 +560,7 @@ private static function validExtensionProvider(): iterable
560560
}
561561

562562
/**
563-
* @dataProvider invalidExtensionProvider
563+
* @dataProvider provideInvalidExtension
564564
*/
565565
public function testExtensionInvalid(string $name, string $extension)
566566
{
@@ -582,7 +582,7 @@ public function testExtensionInvalid(string $name, string $extension)
582582
->assertRaised();
583583
}
584584

585-
private static function invalidExtensionProvider(): iterable
585+
public static function provideInvalidExtension(): iterable
586586
{
587587
yield ['test.gif', 'gif'];
588588
yield ['test.png.gif', 'gif'];
@@ -658,5 +658,47 @@ public function testUploadedFileExtensions()
658658
$this->assertNoViolation();
659659
}
660660

661+
/**
662+
* @dataProvider provideFilenameMaxLengthIsTooLong
663+
*/
664+
public function testFilenameMaxLengthIsTooLong(File $constraintFile, string $messageViolation)
665+
{
666+
file_put_contents($this->path, '1');
667+
668+
$file = new UploadedFile($this->path, 'myFileWithATooLongOriginalFileName', null, null, true);
669+
$this->validator->validate($file, $constraintFile);
670+
671+
$this->buildViolation($messageViolation)
672+
->setParameters([
673+
'{{ filename_max_length }}' => $constraintFile->filenameMaxLength,
674+
])
675+
->setCode(File::FILENAME_TOO_LONG)
676+
->assertRaised();
677+
}
678+
679+
public static function provideFilenameMaxLengthIsTooLong(): \Generator
680+
{
681+
yield 'Simple case with only the parameter "filenameMaxLength" ' => [
682+
new File(filenameMaxLength: 30),
683+
'The filename is too long. It should have {{ filename_max_length }} character or less.',
684+
];
685+
686+
yield 'Case with the parameter "filenameMaxLength" and a custom error message' => [
687+
new File(filenameMaxLength: 20, filenameTooLongMessage: 'Your filename is too long. Please use at maximum {{ filename_max_length }} characters'),
688+
'Your filename is too long. Please use at maximum {{ filename_max_length }} characters',
689+
];
690+
691+
}
692+
693+
public function testFilenameMaxLength()
694+
{
695+
file_put_contents($this->path, '1');
696+
697+
$file = new UploadedFile($this->path, 'tinyOriginalFileName', null, null, true);
698+
$this->validator->validate($file, new File(filenameMaxLength: 20));
699+
700+
$this->assertNoViolation();
701+
}
702+
661703
abstract protected function getFile($filename);
662704
}

0 commit comments

Comments
 (0)