minor #10951 Made use of "kB" vs. "KiB" consistent (Yannick, webmozart)
This PR was merged into the 2.5-dev branch. Discussion ---------- Made use of "kB" vs. "KiB" consistent | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Continuation of #10661. This PR makes the usage of "kB" and "KiB" consistent across the project. The notations equal the internationally recognized ones: Short form | Long form | Value in Bytes --- | --- | --- B | bytes | 1 kB | kilobytes | 1000 KiB | kibibytes | 1024 MB | megabytes | 1000000 MiB | mebibytes | 1048576 GB | gigabytes | 1000000000 GiB | gibibytes | 1073741824 The reason for differentiating between the two is that several users got confused with the current mix (see #10648, #10917, #10661). FileValidator, UploadedFile and the ProgressBar helper were changed accordingly. Follow-up feature request: #10962 Commits -------e4c6da5
[Validator] Improved to-string conversion of the file size/size limitbbe1045
[Validator][Console][HttpFoundation] Use "KiB" everywhere (instead of "kB")
This commit is contained in:
commit
3c9d8837cf
@ -92,15 +92,15 @@ abstract class Helper implements HelperInterface
|
||||
public static function formatMemory($memory)
|
||||
{
|
||||
if ($memory >= 1024 * 1024 * 1024) {
|
||||
return sprintf('%.1f GB', $memory / 1024 / 1024 / 1024);
|
||||
return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
|
||||
}
|
||||
|
||||
if ($memory >= 1024 * 1024) {
|
||||
return sprintf('%.1f MB', $memory / 1024 / 1024);
|
||||
return sprintf('%.1f MiB', $memory / 1024 / 1024);
|
||||
}
|
||||
|
||||
if ($memory >= 1024) {
|
||||
return sprintf('%d kB', $memory / 1024);
|
||||
return sprintf('%d KiB', $memory / 1024);
|
||||
}
|
||||
|
||||
return sprintf('%d B', $memory);
|
||||
|
@ -367,17 +367,17 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
||||
$this->generateOutput(
|
||||
" \033[44;37m Starting the demo... fingers crossed \033[0m\n".
|
||||
" 0/15 ".$progress.str_repeat($empty, 26)." 0%\n".
|
||||
" 🏁 1 sec \033[44;37m 0 B \033[0m"
|
||||
" \xf0\x9f\x8f\x81 1 sec \033[44;37m 0 B \033[0m"
|
||||
).
|
||||
$this->generateOutput(
|
||||
" \033[44;37m Looks good to me... \033[0m\n".
|
||||
" 4/15 ".str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n".
|
||||
" 🏁 1 sec \033[41;37m 97 kB \033[0m"
|
||||
" \xf0\x9f\x8f\x81 1 sec \033[41;37m 97 KiB \033[0m"
|
||||
).
|
||||
$this->generateOutput(
|
||||
" \033[44;37m Thanks, bye \033[0m\n".
|
||||
" 15/15 ".str_repeat($done, 28)." 100%\n".
|
||||
" 🏁 1 sec \033[41;37m 195 kB \033[0m"
|
||||
" \xf0\x9f\x8f\x81 1 sec \033[41;37m 195 KiB \033[0m"
|
||||
),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
|
@ -291,7 +291,7 @@ class UploadedFile extends File
|
||||
public function getErrorMessage()
|
||||
{
|
||||
static $errors = array(
|
||||
UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d kb).',
|
||||
UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
|
||||
UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
|
||||
UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
|
||||
UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
|
||||
|
@ -25,6 +25,16 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
*/
|
||||
class FileValidator extends ConstraintValidator
|
||||
{
|
||||
const KB_BYTES = 1000;
|
||||
|
||||
const MB_BYTES = 1000000;
|
||||
|
||||
private static $suffices = array(
|
||||
1 => 'bytes',
|
||||
self::KB_BYTES => 'kB',
|
||||
self::MB_BYTES => 'MB',
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -43,21 +53,21 @@ class FileValidator extends ConstraintValidator
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
if ($constraint->maxSize) {
|
||||
if (ctype_digit((string) $constraint->maxSize)) {
|
||||
$maxSize = (int) $constraint->maxSize;
|
||||
$limitInBytes = (int) $constraint->maxSize;
|
||||
} elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
|
||||
$maxSize = $constraint->maxSize * 1024;
|
||||
$limitInBytes = $constraint->maxSize * self::KB_BYTES;
|
||||
} elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
|
||||
$maxSize = $constraint->maxSize * 1048576;
|
||||
$limitInBytes = $constraint->maxSize * self::MB_BYTES;
|
||||
} else {
|
||||
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
|
||||
}
|
||||
$maxSize = min(UploadedFile::getMaxFilesize(), $maxSize);
|
||||
$limitInBytes = min(UploadedFile::getMaxFilesize(), $limitInBytes);
|
||||
} else {
|
||||
$maxSize = UploadedFile::getMaxFilesize();
|
||||
$limitInBytes = UploadedFile::getMaxFilesize();
|
||||
}
|
||||
|
||||
$this->context->addViolation($constraint->uploadIniSizeErrorMessage, array(
|
||||
'{{ limit }}' => $maxSize,
|
||||
'{{ limit }}' => $limitInBytes,
|
||||
'{{ suffix }}' => 'bytes',
|
||||
));
|
||||
|
||||
@ -112,27 +122,45 @@ class FileValidator extends ConstraintValidator
|
||||
}
|
||||
|
||||
if ($constraint->maxSize) {
|
||||
if (ctype_digit((string) $constraint->maxSize)) {
|
||||
$size = filesize($path);
|
||||
$limit = (int) $constraint->maxSize;
|
||||
$suffix = 'bytes';
|
||||
} elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
|
||||
$size = round(filesize($path) / 1000, 2);
|
||||
$limit = (int) $constraint->maxSize;
|
||||
$suffix = 'kB';
|
||||
$sizeInBytes = filesize($path);
|
||||
$limitInBytes = (int) $constraint->maxSize;
|
||||
|
||||
if (preg_match('/^\d++k$/', $constraint->maxSize)) {
|
||||
$limitInBytes *= self::KB_BYTES;
|
||||
} elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
|
||||
$size = round(filesize($path) / 1000000, 2);
|
||||
$limit = (int) $constraint->maxSize;
|
||||
$suffix = 'MB';
|
||||
} else {
|
||||
$limitInBytes *= self::MB_BYTES;
|
||||
} elseif (!ctype_digit((string) $constraint->maxSize)) {
|
||||
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
|
||||
}
|
||||
|
||||
if ($size > $limit) {
|
||||
if ($sizeInBytes > $limitInBytes) {
|
||||
// Convert the limit to the smallest possible number
|
||||
// (i.e. try "MB", then "kB", then "bytes")
|
||||
$coef = self::MB_BYTES;
|
||||
$limitAsString = (string) ($limitInBytes / $coef);
|
||||
|
||||
// Restrict the limit to 2 decimals (without rounding! we
|
||||
// need the precise value)
|
||||
while (self::moreDecimalsThan($limitAsString, 2)) {
|
||||
$coef /= 1000;
|
||||
$limitAsString = (string) ($limitInBytes / $coef);
|
||||
}
|
||||
|
||||
// Convert size to the same measure, but round to 2 decimals
|
||||
$sizeAsString = (string) round($sizeInBytes / $coef, 2);
|
||||
|
||||
// If the size and limit produce the same string output
|
||||
// (due to rounding), reduce the coefficient
|
||||
while ($sizeAsString === $limitAsString) {
|
||||
$coef /= 1000;
|
||||
$limitAsString = (string) ($limitInBytes / $coef);
|
||||
$sizeAsString = (string) round($sizeInBytes / $coef, 2);
|
||||
}
|
||||
|
||||
$this->context->addViolation($constraint->maxSizeMessage, array(
|
||||
'{{ size }}' => $size,
|
||||
'{{ limit }}' => $limit,
|
||||
'{{ suffix }}' => $suffix,
|
||||
'{{ size }}' => $sizeAsString,
|
||||
'{{ limit }}' => $limitAsString,
|
||||
'{{ suffix }}' => static::$suffices[$coef],
|
||||
'{{ file }}' => $path,
|
||||
));
|
||||
|
||||
@ -172,4 +200,9 @@ class FileValidator extends ConstraintValidator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function moreDecimalsThan($double, $numberOfDecimals)
|
||||
{
|
||||
return strlen((string) $double) > strlen(round($double, $numberOfDecimals));
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,13 @@ abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
fclose($this->file);
|
||||
if (is_resource($this->file)) {
|
||||
fclose($this->file);
|
||||
}
|
||||
|
||||
if (file_exists($this->path)) {
|
||||
unlink($this->path);
|
||||
}
|
||||
|
||||
$this->context = null;
|
||||
$this->validator = null;
|
||||
@ -82,65 +88,97 @@ abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->validator->validate($file, new File());
|
||||
}
|
||||
|
||||
public function testTooLargeBytes()
|
||||
public function provideMaxSizeExceededTests()
|
||||
{
|
||||
fwrite($this->file, str_repeat('0', 11));
|
||||
return array(
|
||||
array(11, 10, '11', '10', 'bytes'),
|
||||
|
||||
array(ceil(1.005*1000), ceil(1.005*1000) - 1, '1005', '1004', 'bytes'),
|
||||
array(ceil(1.005*1000*1000), ceil(1.005*1000*1000) - 1, '1005000', '1004999', 'bytes'),
|
||||
|
||||
// round(size) == 1.01kB, limit == 1kB
|
||||
array(ceil(1.005*1000), 1000, '1.01', '1', 'kB'),
|
||||
array(ceil(1.005*1000), '1k', '1.01', '1', 'kB'),
|
||||
|
||||
// round(size) == 1kB, limit == 1kB -> use bytes
|
||||
array(ceil(1.004*1000), 1000, '1004', '1000', 'bytes'),
|
||||
array(ceil(1.004*1000), '1k', '1004', '1000', 'bytes'),
|
||||
|
||||
array(1000 + 1, 1000, '1001', '1000', 'bytes'),
|
||||
array(1000 + 1, '1k', '1001', '1000', 'bytes'),
|
||||
|
||||
// round(size) == 1.01MB, limit == 1MB
|
||||
array(ceil(1.005*1000*1000), 1000*1000, '1.01', '1', 'MB'),
|
||||
array(ceil(1.005*1000*1000), '1000k', '1.01', '1', 'MB'),
|
||||
array(ceil(1.005*1000*1000), '1M', '1.01', '1', 'MB'),
|
||||
|
||||
// round(size) == 1MB, limit == 1MB -> use kB
|
||||
array(ceil(1.004*1000*1000), 1000*1000, '1004', '1000', 'kB'),
|
||||
array(ceil(1.004*1000*1000), '1000k', '1004', '1000', 'kB'),
|
||||
array(ceil(1.004*1000*1000), '1M', '1004', '1000', 'kB'),
|
||||
|
||||
array(1000*1000 + 1, 1000*1000, '1000001', '1000000', 'bytes'),
|
||||
array(1000*1000 + 1, '1000k', '1000001', '1000000', 'bytes'),
|
||||
array(1000*1000 + 1, '1M', '1000001', '1000000', 'bytes'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMaxSizeExceededTests
|
||||
*/
|
||||
public function testMaxSizeExceeded($bytesWritten, $limit, $sizeAsString, $limitAsString, $suffix)
|
||||
{
|
||||
fseek($this->file, $bytesWritten-1, SEEK_SET);
|
||||
fwrite($this->file, '0');
|
||||
fclose($this->file);
|
||||
|
||||
$constraint = new File(array(
|
||||
'maxSize' => 10,
|
||||
'maxSize' => $limit,
|
||||
'maxSizeMessage' => 'myMessage',
|
||||
));
|
||||
|
||||
$this->context->expects($this->once())
|
||||
->method('addViolation')
|
||||
->with('myMessage', array(
|
||||
'{{ limit }}' => '10',
|
||||
'{{ size }}' => '11',
|
||||
'{{ suffix }}' => 'bytes',
|
||||
'{{ limit }}' => $limitAsString,
|
||||
'{{ size }}' => $sizeAsString,
|
||||
'{{ suffix }}' => $suffix,
|
||||
'{{ file }}' => $this->path,
|
||||
));
|
||||
|
||||
$this->validator->validate($this->getFile($this->path), $constraint);
|
||||
}
|
||||
|
||||
public function testTooLargeKiloBytes()
|
||||
public function provideMaxSizeNotExceededTests()
|
||||
{
|
||||
fwrite($this->file, str_repeat('0', 1400));
|
||||
return array(
|
||||
array(10, 10),
|
||||
array(9, 10),
|
||||
|
||||
$constraint = new File(array(
|
||||
'maxSize' => '1k',
|
||||
'maxSizeMessage' => 'myMessage',
|
||||
));
|
||||
array(1000, '1k'),
|
||||
array(1000 - 1, '1k'),
|
||||
|
||||
$this->context->expects($this->once())
|
||||
->method('addViolation')
|
||||
->with('myMessage', array(
|
||||
'{{ limit }}' => '1',
|
||||
'{{ size }}' => '1.4',
|
||||
'{{ suffix }}' => 'kB',
|
||||
'{{ file }}' => $this->path,
|
||||
));
|
||||
|
||||
$this->validator->validate($this->getFile($this->path), $constraint);
|
||||
array(1000*1000, '1M'),
|
||||
array(1000*1000 - 1, '1M'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testTooLargeMegaBytes()
|
||||
/**
|
||||
* @dataProvider provideMaxSizeNotExceededTests
|
||||
*/
|
||||
public function testMaxSizeNotExceeded($bytesWritten, $limit)
|
||||
{
|
||||
fwrite($this->file, str_repeat('0', 1400000));
|
||||
fseek($this->file, $bytesWritten-1, SEEK_SET);
|
||||
fwrite($this->file, '0');
|
||||
fclose($this->file);
|
||||
|
||||
$constraint = new File(array(
|
||||
'maxSize' => '1M',
|
||||
'maxSize' => $limit,
|
||||
'maxSizeMessage' => 'myMessage',
|
||||
));
|
||||
|
||||
$this->context->expects($this->once())
|
||||
->method('addViolation')
|
||||
->with('myMessage', array(
|
||||
'{{ limit }}' => '1',
|
||||
'{{ size }}' => '1.4',
|
||||
'{{ suffix }}' => 'MB',
|
||||
'{{ file }}' => $this->path,
|
||||
));
|
||||
$this->context->expects($this->never())
|
||||
->method('addViolation');
|
||||
|
||||
$this->validator->validate($this->getFile($this->path), $constraint);
|
||||
}
|
||||
|
Reference in New Issue
Block a user