Skip to content

Commit

Permalink
Add rule mimes
Browse files Browse the repository at this point in the history
  • Loading branch information
emsifa committed Nov 24, 2018
1 parent 12d06ff commit 3924708
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 2 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ Below is list of all available validation rules
* [required_without](#rule-required_without)
* [required_with_all](#rule-required_with_all)
* [required_without_all](#rule-required_without_all)
* [uploaded_file](#rule-uploaded_file)
* [uploaded_file](#rule-uploaded_file) (uploaded file)
* [mimes](#rule-mimes) (uploaded file)
* [default/defaults](#rule-default)
* [email](#rule-email)
* [uppercase](#rule-uppercase)
Expand Down Expand Up @@ -355,7 +356,7 @@ The field under validation must be present and not empty only if all of the othe
The field under validation must be present and not empty only when all of the other specified fields are not present.

<a id="rule-uploaded_file"></a>
#### uploaded_file:min_size,max_size,file_type_a,file_type_b,...
#### uploaded_file:min_size,max_size,extension_a,extension_b,...

This rule will validate `$_FILES` data, but not for multiple uploaded files.
Field under this rule must be following rules below to be valid:
Expand All @@ -372,6 +373,12 @@ Here are some example definitions and explanations:
* `uploaded_file:0,1M`: uploaded file size must be between 0 - 1 MB, but uploaded file is optional.
* `required|uploaded_file:0,1M,png,jpeg`: uploaded file size must be between 0 - 1MB and mime types must be `image/jpeg` or `image/png`.


<a id="rule-default"></a>
#### mimes:extension_a,extension_b,...

The `$_FILES` item under validation must have a MIME type corresponding to one of the listed extensions.

<a id="rule-default"></a>
#### default/defaults

Expand Down
89 changes: 89 additions & 0 deletions src/Rules/Mimes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Rakit\Validation\Rules;

use Rakit\Validation\Rule;
use Rakit\Validation\MimeTypeGuesser;

class Mimes extends Rule
{
use FileTrait;

/** @var string */
protected $message = "The :attribute file type is not allowed";

/** @var string|int */
protected $maxSize = null;

/** @var string|int */
protected $minSize = null;

/** @var array */
protected $allowedTypes = [];

/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params): Rule
{
$this->allowTypes($params);
return $this;
}

/**
* Given $types and assign $this->params
*
* @param mixed $types
* @return self
*/
public function allowTypes($types): Rule
{
if (is_string($types)) {
$types = explode('|', $types);
}

$this->params['allowed_types'] = $types;

return $this;
}

/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value): bool
{
$allowedTypes = $this->parameter('allowed_types');

// below is Required rule job
if (!$this->isValueFromUploadedFiles($value) or $value['error'] == UPLOAD_ERR_NO_FILE) {
return true;
}

if (!$this->isUploadedFile($value)) {
return false;
}

// just make sure there is no error
if ($value['error']) {
return false;
}

if (!empty($allowedTypes)) {
$guesser = new MimeTypeGuesser;
$ext = $guesser->getExtension($value['type']);
unset($guesser);

if (!in_array($ext, $allowedTypes)) {
return false;
}
}

return true;
}
}
1 change: 1 addition & 0 deletions src/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ protected function registerBaseValidators()
'present' => new Rules\Present,
'different' => new Rules\Different,
'uploaded_file' => new Rules\UploadedFile,
'mimes' => new Rules\Mimes,
'callback' => new Rules\Callback,
'before' => new Rules\Before,
'after' => new Rules\After,
Expand Down
151 changes: 151 additions & 0 deletions tests/Rules/MimesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace Rakit\Validation\Tests;

use Rakit\Validation\Rules\Mimes;
use PHPUnit\Framework\TestCase;

class MimesTest extends TestCase
{

public function setUp()
{
$this->rule = new Mimes();
}

public function testValidMimes()
{
$file = [
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'text/plain',
'size' => filesize(__FILE__),
'tmp_name' => __FILE__,
'error' => UPLOAD_ERR_OK
];

$uploadedFileRule = $this->getMockBuilder(Mimes::class)
->setMethods(['isUploadedFile'])
->getMock();

$uploadedFileRule->expects($this->once())
->method('isUploadedFile')
->willReturn(true);

$this->assertTrue($uploadedFileRule->check($file));
}

/**
* Make sure we can't just passing array like valid $_FILES['key']
*/
public function testValidateWithoutMockShouldBeInvalid()
{
$this->assertFalse($this->rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'text/plain',
'size' => filesize(__FILE__),
'tmp_name' => __FILE__,
'error' => UPLOAD_ERR_OK
]));
}

/**
* Missing UPLOAD_ERR_NO_FILE should be valid because it is job for required rule
*/
public function testEmptyMimesShouldBeValid()
{
$this->assertTrue($this->rule->check([
'name' => '',
'type' => '',
'size' => '',
'tmp_name' => '',
'error' => UPLOAD_ERR_NO_FILE
]));
}

public function testUploadError()
{
$this->assertFalse($this->rule->check([
'name' => '',
'type' => '',
'size' => '',
'tmp_name' => '',
'error' => 5
]));
}

public function testFileTypes()
{

$rule = $this->getMockBuilder(Mimes::class)
->setMethods(['isUploadedFile'])
->getMock();

$rule->expects($this->exactly(3))
->method('isUploadedFile')
->willReturn(true);

$rule->allowTypes('png|jpeg');

$this->assertFalse($rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'text/plain',
'size' => 1024, // 1K
'tmp_name' => __FILE__,
'error' => 0
]));

$this->assertTrue($rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'image/png',
'size' => 10 * 1024,
'tmp_name' => __FILE__,
'error' => 0
]));

$this->assertTrue($rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'image/jpeg',
'size' => 10 * 1024,
'tmp_name' => __FILE__,
'error' => 0
]));
}

/**
* Missing array key(s) should be valid because it is job for required rule
*/
public function testMissingAKeyShouldBeValid()
{
// missing name
$this->assertTrue($this->rule->check([
'type' => 'text/plain',
'size' => filesize(__FILE__),
'tmp_name' => __FILE__,
'error' => 0
]));

// missing type
$this->assertTrue($this->rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'size' => filesize(__FILE__),
'tmp_name' => __FILE__,
'error' => 0
]));

// missing size
$this->assertTrue($this->rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'text/plain',
'tmp_name' => __FILE__,
'error' => 0
]));

// missing tmp_name
$this->assertTrue($this->rule->check([
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
'type' => 'text/plain',
'size' => filesize(__FILE__),
'error' => 0
]));
}
}

0 comments on commit 3924708

Please sign in to comment.