-
Notifications
You must be signed in to change notification settings - Fork 2
feat: add file upload validation rules with WordPress integration #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
9116bb1
f5730b5
bc3bf7f
43f6594
c211750
07f421c
676467d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| <?php | ||
| namespace BitApps\WPValidator\Rules; | ||
|
|
||
| use BitApps\WPValidator\Helpers; | ||
| use BitApps\WPValidator\Rule; | ||
|
|
||
| class EncodingRule extends Rule | ||
| { | ||
| use Helpers; | ||
|
|
||
| protected $message = "The :attribute must be encoded as one of: :encoding"; | ||
|
|
||
| protected $requireParameters = ['encoding']; | ||
|
|
||
| public function validate($value) | ||
| { | ||
| $this->checkRequiredParameter($this->requireParameters); | ||
|
|
||
| if ($this->isEmpty($value)) { | ||
| return false; | ||
| } | ||
|
|
||
| $allowedEncodings = array_map('trim', explode(',', $this->getParameter('encoding'))); | ||
|
|
||
| $filePath = $this->getFilePath($value); | ||
| if (! $filePath) { | ||
| return false; | ||
| } | ||
|
|
||
| $contents = file_get_contents($filePath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loading the entire file content into memory using $contents = file_get_contents($filePath, false, null, 0, 32768); |
||
| if ($contents === false) { | ||
| return false; | ||
| } | ||
|
|
||
| return mb_detect_encoding($contents, $allowedEncodings, true) !== false; | ||
| } | ||
|
|
||
| private function getFilePath($value) | ||
| { | ||
| if (is_numeric($value)) { | ||
| $filePath = get_attached_file((int) $value); | ||
| return (! empty($filePath) && file_exists($filePath)) ? $filePath : null; | ||
| } | ||
|
|
||
| if (is_array($value) && isset($value['tmp_name']) && is_uploaded_file($value['tmp_name'])) { | ||
| return $value['tmp_name']; | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| public function getParamKeys() | ||
| { | ||
| return $this->requireParameters; | ||
| } | ||
|
|
||
| public function message() | ||
| { | ||
| return $this->message; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| <?php | ||
| namespace BitApps\WPValidator\Rules; | ||
|
|
||
| use BitApps\WPValidator\Helpers; | ||
| use BitApps\WPValidator\Rule; | ||
|
|
||
| class ExtensionsRule extends Rule | ||
| { | ||
| use Helpers; | ||
|
|
||
| protected $message = "The :attribute must have one of the following extensions: :extensions"; | ||
|
|
||
| protected $requireParameters = ['extensions']; | ||
|
|
||
| public function validate($value) | ||
| { | ||
| $this->checkRequiredParameter($this->requireParameters); | ||
|
|
||
| if ($this->isEmpty($value)) { | ||
| return false; | ||
| } | ||
|
|
||
| $allowedExtensions = array_map(function ($e) { | ||
| return strtolower(trim($e)); | ||
| }, explode(',', $this->getParameter('extensions'))); | ||
|
|
||
| $fileName = $this->getFileName($value); | ||
| if (! $fileName) { | ||
| return false; | ||
| } | ||
|
|
||
| $wpFileType = wp_check_filetype($fileName); | ||
| $extension = strtolower($wpFileType['ext'] ?? ''); | ||
|
|
||
| return ! empty($extension) && in_array($extension, $allowedExtensions, true); | ||
| } | ||
|
|
||
| private function getFileName($value) | ||
| { | ||
| if (is_numeric($value)) { | ||
| $filePath = get_attached_file((int) $value); | ||
| return (! empty($filePath) && file_exists($filePath)) ? basename($filePath) : null; | ||
| } | ||
|
|
||
| if (is_array($value) && isset($value['name'])) { | ||
| return $value['name']; | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| public function getParamKeys() | ||
| { | ||
| return $this->requireParameters; | ||
| } | ||
|
|
||
| public function message() | ||
| { | ||
| return $this->message; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| <?php | ||
| namespace BitApps\WPValidator\Rules; | ||
|
|
||
| use BitApps\WPValidator\Helpers; | ||
| use BitApps\WPValidator\Rule; | ||
|
|
||
| class FileRule extends Rule | ||
| { | ||
| use Helpers; | ||
|
|
||
| protected $message = "The :attribute must be a valid file upload"; | ||
|
|
||
| public function validate($value) | ||
| { | ||
| if ($this->isEmpty($value)) { | ||
| return false; | ||
| } | ||
|
|
||
| if (is_numeric($value)) { | ||
| $attachmentId = (int) $value; | ||
| $filePath = get_attached_file($attachmentId); | ||
| return ! empty($filePath) && file_exists($filePath); | ||
| } | ||
|
|
||
| if (is_array($value)) { | ||
| $requiredKeys = array_flip(['name', 'type', 'tmp_name', 'error', 'size']); | ||
| if (array_diff_key($requiredKeys, $value)) { | ||
| return false; | ||
| } | ||
|
|
||
| if ($value['error'] !== UPLOAD_ERR_OK) { | ||
| return false; | ||
| } | ||
|
|
||
| if (empty($value['tmp_name']) || ! is_uploaded_file($value['tmp_name'])) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| public function message() | ||
| { | ||
| return $this->message; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| <?php | ||
| namespace BitApps\WPValidator\Rules; | ||
|
|
||
| use BitApps\WPValidator\Helpers; | ||
| use BitApps\WPValidator\Rule; | ||
|
|
||
| class ImageDimensionsRule extends Rule | ||
| { | ||
| use Helpers; | ||
|
|
||
| protected $message = "The :attribute must not be larger than :width x :height pixels"; | ||
|
|
||
| protected $requireParameters = ['width', 'height']; | ||
|
|
||
| public function validate($value) | ||
| { | ||
| $this->checkRequiredParameter($this->requireParameters); | ||
|
|
||
| if ($this->isEmpty($value)) { | ||
| return false; | ||
| } | ||
|
|
||
| $maxWidth = (int) $this->getParameter('width'); | ||
| $maxHeight = (int) $this->getParameter('height'); | ||
|
|
||
| $dimensions = $this->getImageDimensions($value); | ||
| if (! $dimensions) { | ||
| return false; | ||
| } | ||
|
|
||
| $width = $dimensions['width']; | ||
| $height = $dimensions['height']; | ||
|
|
||
| return $width <= $maxWidth && $height <= $maxHeight; | ||
| } | ||
|
|
||
| private function getImageDimensions($value) | ||
| { | ||
| $filePath = null; | ||
|
|
||
| if (is_numeric($value)) { | ||
| $attachmentId = (int) $value; | ||
| $filePath = get_attached_file($attachmentId); | ||
| if (empty($filePath) || ! file_exists($filePath)) { | ||
| return null; | ||
| } | ||
|
|
||
| $metadata = wp_get_attachment_metadata($attachmentId); | ||
| if ($metadata && isset($metadata['width']) && isset($metadata['height'])) { | ||
| return [ | ||
| 'width' => (int) $metadata['width'], | ||
| 'height' => (int) $metadata['height'], | ||
| ]; | ||
| } | ||
| } | ||
|
|
||
| if (is_array($value) && isset($value['tmp_name'])) { | ||
| if (empty($value['tmp_name']) || ! is_uploaded_file($value['tmp_name'])) { | ||
| return null; | ||
| } | ||
| $filePath = $value['tmp_name']; | ||
| } | ||
|
|
||
| if ($filePath && file_exists($filePath)) { | ||
| $imageSize = @getimagesize($filePath); | ||
| if ($imageSize && isset($imageSize[0]) && isset($imageSize[1])) { | ||
| return [ | ||
| 'width' => (int) $imageSize[0], | ||
| 'height' => (int) $imageSize[1], | ||
| ]; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| public function getParamKeys() | ||
| { | ||
| return $this->requireParameters; | ||
| } | ||
|
|
||
| public function message() | ||
| { | ||
| return $this->message; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
(int)cast here is applied only to$value['size']before the division, which is redundant as the size is already an integer. If the intention was to truncate the result of the division to an integer (KB), parentheses are missing. However, using floats for range comparison is generally more accurate. Also, note the inconsistency withSizeRulewhich usesround().