Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions src/Illuminate/Validation/Rules/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,46 @@

class File implements Rule, DataAwareRule, ValidatorAwareRule
{
use Conditionable, Macroable;
use Conditionable, Macroable {
Macroable::__call as macroCall;
Macroable::__callStatic as macroCallStatic;
}

/**
* Handle dynamic calls to the object.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
if ($method === 'types') {
return $this->setTypes(...$parameters);
}

return $this->macroCall($method, $parameters);
}

/**
* Handle dynamic, static calls to the object.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public static function __callStatic($method, $parameters)
{
if ($method === 'types') {
return (new static())->setTypes(...$parameters);
}

return static::macroCallStatic($method, $parameters);
}

/**
* The MIME types that the given file should match. This array may also contain file extensions.
Expand Down Expand Up @@ -137,12 +176,18 @@ public static function image($allowSvg = false)
/**
* Limit the uploaded file to the given MIME types or file extensions.
*
* This method can be called both statically (as a factory) and on an instance.
* When called statically, a new File instance is created.
* When called on an instance, the current instance is modified and returned.
*
* @param string|array<int, string> $mimetypes
* @return static
* @return $this
*/
public static function types($mimetypes)
public function setTypes($mimetypes)
{
return tap(new static(), fn ($file) => $file->allowedMimetypes = (array) $mimetypes);
$this->allowedMimetypes = (array) $mimetypes;

return $this;
}

/**
Expand Down
25 changes: 25 additions & 0 deletions tests/Validation/ValidationFileRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,31 @@ public function testMixOfMimetypesAndMimes()
);
}

public function testTypesPreservesChainConfiguration()
{
// When types() is called on an existing instance, it should preserve
// prior configuration like max() instead of creating a new instance.
$this->fails(
File::image()->max(1)->types(['jpg', 'jpeg']),
UploadedFile::fake()->image('photo.jpg', 800, 600),
['validation.max.file'],
);

// When types() is called statically, it should still work as a factory.
$this->fails(
File::types('text/plain'),
UploadedFile::fake()->createWithContent('foo.png', file_get_contents(__DIR__.'/fixtures/image.png')),
['validation.mimetypes'],
);

// When types() is called before max(), the max constraint should also work.
$this->fails(
File::default()->types(['jpg', 'jpeg'])->max(1),
UploadedFile::fake()->image('photo.jpg', 800, 600),
['validation.max.file'],
);
}

public function testSingleExtension()
{
$this->fails(
Expand Down
Loading