Skip to content

Commit

Permalink
[10.x] Support human-friendly text for file size (#47846)
Browse files Browse the repository at this point in the history
* Support human-friendly text for file size

* Fix formatting issues

* Remove a single space

* formatting

* add min test

* update doc block

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
jxxe and taylorotwell authored Jul 26, 2023
1 parent e49896e commit a56efdb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 15 deletions.
54 changes: 39 additions & 15 deletions src/Illuminate/Validation/Rules/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
Expand Down Expand Up @@ -131,58 +132,81 @@ public static function types($mimetypes)
/**
* Indicate that the uploaded file should be exactly a certain size in kilobytes.
*
* @param int $kilobytes
* @param string|int $size
* @return $this
*/
public function size($kilobytes)
public function size($size)
{
$this->minimumFileSize = $kilobytes;
$this->maximumFileSize = $kilobytes;
$this->minimumFileSize = $this->toKilobytes($size);
$this->maximumFileSize = $this->minimumFileSize;

return $this;
}

/**
* Indicate that the uploaded file should be between a minimum and maximum size in kilobytes.
*
* @param int $minKilobytes
* @param int $maxKilobytes
* @param string|int $minSize
* @param string|int $maxSize
* @return $this
*/
public function between($minKilobytes, $maxKilobytes)
public function between($minSize, $maxSize)
{
$this->minimumFileSize = $minKilobytes;
$this->maximumFileSize = $maxKilobytes;
$this->minimumFileSize = $this->toKilobytes($minSize);
$this->maximumFileSize = $this->toKilobytes($maxSize);

return $this;
}

/**
* Indicate that the uploaded file should be no less than the given number of kilobytes.
*
* @param int $kilobytes
* @param string|int $size
* @return $this
*/
public function min($kilobytes)
public function min($size)
{
$this->minimumFileSize = $kilobytes;
$this->minimumFileSize = $this->toKilobytes($size);

return $this;
}

/**
* Indicate that the uploaded file should be no more than the given number of kilobytes.
*
* @param int $kilobytes
* @param string|int $size
* @return $this
*/
public function max($kilobytes)
public function max($size)
{
$this->maximumFileSize = $kilobytes;
$this->maximumFileSize = $this->toKilobytes($size);

return $this;
}

/**
* Convert a potentially human-friendly file size to kilobytes.
*
* @param string|int $size
* @return mixed
*/
protected function toKilobytes($size)
{
if (! is_string($size)) {
return $size;
}

$value = floatval($size);

return round(match (true) {
Str::endsWith($size, 'kb') => $value * 1,
Str::endsWith($size, 'mb') => $value * 1000,
Str::endsWith($size, 'gb') => $value * 1000000,
Str::endsWith($size, 'tb') => $value * 1000000000,
default => throw new InvalidArgumentException("Invalid file size suffix."),
});
}

/**
* Specify additional validation rules that should be merged with the default rules during validation.
*
Expand Down
54 changes: 54 additions & 0 deletions tests/Validation/ValidationFileRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,24 @@ public function testMin()
);
}

public function testMinWithHumanReadableSize()
{
$this->fails(
File::default()->min('1024kb'),
UploadedFile::fake()->create('foo.txt', 1023),
['validation.min.file']
);

$this->passes(
File::default()->min('1024kb'),
[
UploadedFile::fake()->create('foo.txt', 1024),
UploadedFile::fake()->create('foo.txt', 1025),
UploadedFile::fake()->create('foo.txt', 2048),
]
);
}

public function testMax()
{
$this->fails(
Expand All @@ -223,6 +241,42 @@ public function testMax()
);
}

public function testMaxWithHumanReadableSize()
{
$this->fails(
File::default()->max('1024kb'),
UploadedFile::fake()->create('foo.txt', 1025),
['validation.max.file']
);

$this->passes(
File::default()->max('1024kb'),
[
UploadedFile::fake()->create('foo.txt', 1024),
UploadedFile::fake()->create('foo.txt', 1023),
UploadedFile::fake()->create('foo.txt', 512),
]
);
}

public function testMaxWithHumanReadableSizeAndMultipleValue()
{
$this->fails(
File::default()->max('1mb'),
UploadedFile::fake()->create('foo.txt', 1025),
['validation.max.file']
);

$this->passes(
File::default()->max('1mb'),
[
UploadedFile::fake()->create('foo.txt', 1000),
UploadedFile::fake()->create('foo.txt', 999),
UploadedFile::fake()->create('foo.txt', 512),
]
);
}

public function testMacro()
{
File::macro('toDocument', function () {
Expand Down

0 comments on commit a56efdb

Please sign in to comment.