Skip to content

Commit

Permalink
feature: add allowedMimeType validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Waldstein committed Jul 31, 2023
1 parent de947e6 commit 9964d06
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 21 deletions.
52 changes: 46 additions & 6 deletions src/Framework/FieldsAPI/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
use Give\Framework\ValidationRules\Rules\AllowedTypes;
use Give\Framework\ValidationRules\Rules\File as FileRule;

use function get_allowed_mime_types;
use function wp_max_upload_size;

/**
* A file upload field.
*
Expand All @@ -32,11 +29,11 @@ public function maxSize(int $maxSize): File
if ($this->hasRule(FileRule::id())) {
/** @var FileRule $rule */
$rule = $this->getRule(FileRule::id());
$rule->size($maxSize);
$rule->maxSize($maxSize);
}

// TODO: add support for file:maxSize
$this->rules((new FileRule())->size($maxSize));
$this->rules((new FileRule())->maxSize($maxSize));

return $this;
}
Expand All @@ -53,12 +50,53 @@ public function getMaxSize(): int
/** @var FileRule $rule */
$rule = $this->getRule(FileRule::id());

return $rule->getSize();
return $rule->getMaxSize();
}

/**
* Set the allowed file types.
*
* @unreleased
*
* @param string[] $allowedMimeTypes
*/
public function allowedMimeTypes(array $allowedMimeTypes): File
{
if ($this->hasRule(FileRule::id())) {
/** @var FileRule $rule */
$rule = $this->getRule(FileRule::id());
// TODO: add support for file:allowedMimeTypes
$rule->allowedMimeTypes($allowedMimeTypes);
} else {
$this->rules((new FileRule())->allowedMimeTypes($allowedMimeTypes));
}


return $this;
}

/**
* Access the allowed file mime types.
*
* @return string[]
*/
public function getAllowedMimeTypes(): array
{
if (!$this->hasRule(FileRule::id())) {
return get_allowed_mime_types();
}

/** @var FileRule $rule */
$rule = $this->getRule(FileRule::id());

return $rule->getAllowedMimeTypes();
}

/**
* Set the allowed file types.
*
* @deprecated use allowedMimeTypes() instead
*
* @param string[] $allowedTypes
*/
public function allowedTypes(array $allowedTypes): File
Expand All @@ -77,6 +115,8 @@ public function allowedTypes(array $allowedTypes): File
/**
* Access the allowed file types.
*
* @deprecated use getAllowedMimeTypes() instead
*
* @return string[]
*/
public function getAllowedTypes(): array
Expand Down
48 changes: 42 additions & 6 deletions src/Framework/Http/Types/FileType.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@ class FileType {
*
* @var string
*/
public $name;
protected $name;
/**
* The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted
*
* @var string
*/
public $type;
protected $browserMimeType;
/**
* The temporary filename of the file in which the uploaded file was stored on the server.
*
* @var string
*/
public $tmpName;
protected $tmpName;
/**
* The error code associated with this file upload.
*
* @see https://www.php.net/manual/en/features.file-upload.errors.php
* @var int
*/
public $error;
protected $error;
/**
* The size, in bytes, of the uploaded file
*
* @var int
*/
public $size;
protected $size;

/**
* @unreleased
Expand All @@ -50,11 +50,47 @@ public static function fromArray(array $fileArray): FileType
$file = new self();

$file->name = (string)$fileArray['name'];
$file->type = (string)$fileArray['type'];
$file->browserMimeType = (string)$fileArray['type'];
$file->tmpName = (string)$fileArray['tmp_name'];
$file->error = (int)$fileArray['error'];
$file->size = (int)$fileArray['size'];

return $file;
}

/**
* @unreleased
*
* @see https://www.php.net/manual/en/function.is-uploaded-file.php
*/
public function isUploadedFile(): bool
{
return is_uploaded_file($this->tmpName);
}

/**
* @unreleased
*
* @see https://www.php.net/manual/en/function.mime-content-type.php
*/
public function getMimeType(): string
{
return mime_content_type($this->tmpName);
}

/**
* @unreleased
*/
public function getSize(): int
{
return $this->size;
}

/**
* @unreleased
*/
public function getError(): int
{
return $this->error;
}
}
54 changes: 45 additions & 9 deletions src/Framework/ValidationRules/Rules/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ class File implements ValidationRule
*
* @var int
*/
protected $size;
protected $maxSize;

/**
* @var string[]
*/
protected $allowedMimeTypes;

/**
* @unreleased
Expand All @@ -27,24 +32,45 @@ public static function id(): string
return 'file';
}


/**
* @unreleased
*/
public function maxSize(int $maxSize): ValidationRule
{
$this->maxSize = $maxSize;

return $this;
}

/**
* @unreleased
*/
public function getSize(): int
public function getMaxSize(): int
{
return $this->size;
return $this->maxSize;
}

/**
* @unreleased
*/
public function size(int $size): ValidationRule
public function allowedMimeTypes(array $allowedMimeTypes): ValidationRule
{
$this->size = $size;
$this->allowedMimeTypes = $allowedMimeTypes;

return $this;
}

/**
* @unreleased
*
* @return string[]
*/
public function getAllowedMimeTypes(): array
{
return $this->allowedMimeTypes ?? [];
}

/**
* @unreleased
**/
Expand All @@ -53,12 +79,22 @@ public function __invoke($value, Closure $fail, string $key, array $values)
try {
$fileType = FileType::fromArray($value);

if ($fileType->size > $this->getSize()) {
$fail(sprintf(__('%s must be less than or equal to %d bytes', 'give'), '{field}', $this->getSize()));
if (!$fileType->isUploadedFile()) {
$fail(sprintf(__('%s must be a valid file.', 'give'), '{field}'));
}

if (!in_array($fileType->getMimeType(), $this->getAllowedMimeTypes(), true)) {
$fail(sprintf(__('%s must be a valid file type.', 'give'), '{field}'));
}

if ($fileType->getSize() > $this->getMaxSize()) {
$fail(
sprintf(__('%s must be less than or equal to %d bytes.', 'give'), '{field}', $this->getMaxSize())
);
}

if ($fileType->error !== UPLOAD_ERR_OK) {
$fail(sprintf(__('%s must be a valid file', 'give'), '{field}'));
if ($fileType->getError() !== UPLOAD_ERR_OK) {
$fail(sprintf(__('%s must be a valid file.', 'give'), '{field}'));
}
} catch (\Throwable $e) {
$fail($e->getMessage());
Expand Down

0 comments on commit 9964d06

Please sign in to comment.