| 1 |
<?php |
| 2 |
|
| 3 |
namespace FluentBoards\App\Hooks\Handlers; |
| 4 |
|
| 5 |
use DateTimeImmutable; |
| 6 |
use Exception; |
| 7 |
use FluentBoards\App\Services\Libs\FileSystem; |
| 8 |
use FluentBoards\App\Models\Attachment; |
| 9 |
use function Sodium\add; |
| 10 |
|
| 11 |
class FileHandler |
| 12 |
{ |
| 13 |
// private function validateFile($file) |
| 14 |
// { |
| 15 |
// if (!$file) { |
| 16 |
// throw new Exception('File is empty.'); |
| 17 |
// } |
| 18 |
// if (!$this->isFileTypeSupported($file)) { |
| 19 |
// throw new Exception('File type not supported'); |
| 20 |
// } |
| 21 |
// if ($file['size'] > $this->getFileUploadLimit()) { |
| 22 |
// throw new Exception('File size is too large'); |
| 23 |
// } |
| 24 |
// } |
| 25 |
|
| 26 |
private function getFileUploadLimit() { |
| 27 |
// Logic for calculating file upload limit as in your original code |
| 28 |
return min( |
| 29 |
wp_convert_hr_to_bytes(ini_get('upload_max_filesize')), |
| 30 |
wp_convert_hr_to_bytes(ini_get('post_max_size')), |
| 31 |
wp_max_upload_size() |
| 32 |
); |
| 33 |
} |
| 34 |
|
| 35 |
/** |
| 36 |
* Summary of deleteFileByUrl |
| 37 |
* @param mixed $file_url |
| 38 |
* @return bool |
| 39 |
*/ |
| 40 |
public function deleteFileByUrl($file_url) |
| 41 |
{ |
| 42 |
$exists = Attachment::where('full_url', $file_url)->exists(); |
| 43 |
if($exists) { |
| 44 |
return; |
| 45 |
} |
| 46 |
// Convert the URL to the local file path |
| 47 |
$upload_dir = wp_upload_dir(); |
| 48 |
$file_path = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $file_url); |
| 49 |
|
| 50 |
// Check if the file exists |
| 51 |
if (file_exists($file_path)) { |
| 52 |
// Delete the file |
| 53 |
$deleted = wp_delete_file($file_path); |
| 54 |
|
| 55 |
// Optionally, you can also remove the file from the media library |
| 56 |
// Note: This won't delete the file physically, but it will remove it from the media library |
| 57 |
$attachment_id = attachment_url_to_postid($file_url); |
| 58 |
if ($attachment_id) { |
| 59 |
wp_delete_attachment($attachment_id, true); |
| 60 |
} |
| 61 |
|
| 62 |
// Return true if the file was successfully deleted |
| 63 |
return $deleted; |
| 64 |
} |
| 65 |
// Return false if the file does not exist |
| 66 |
return false; |
| 67 |
} |
| 68 |
|
| 69 |
|
| 70 |
/** |
| 71 |
* Summary of isFileTypeSupported checking file type it will allow only file which is readable by browser |
| 72 |
* @param mixed $file |
| 73 |
* TODO: Refactorable: This can be in a Helper class. and we may pass it to frontend via wp_localize_script appvars |
| 74 |
* so that we can check similarly for better experience. |
| 75 |
* @return bool |
| 76 |
*/ |
| 77 |
public function isFileTypeSupported($file) |
| 78 |
{ |
| 79 |
// Define supported file types that are generally allowed by user |
| 80 |
$allowedMimeTypes = get_allowed_mime_types(); |
| 81 |
|
| 82 |
// Check if the file type is supported |
| 83 |
return in_array(strtolower($file['type']), $allowedMimeTypes); |
| 84 |
} |
| 85 |
|
| 86 |
/** |
| 87 |
* @throws Exception |
| 88 |
*/ |
| 89 |
public function handleMediaFileUpload($data) |
| 90 |
{ |
| 91 |
// Check if file was uploaded |
| 92 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer |
| 93 |
if (!isset($_FILES['file']['tmp_name']) || !isset($_FILES['file']['name'])) { |
| 94 |
throw new Exception(esc_html__('No file was uploaded. Please try again.', 'fluent-boards')); |
| 95 |
} |
| 96 |
|
| 97 |
// Sanitize filename from request for validation |
| 98 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer |
| 99 |
$filename = sanitize_file_name(wp_unslash($_FILES['file']['name'])); |
| 100 |
|
| 101 |
// Validate and sanitize tmp_name before use |
| 102 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer |
| 103 |
$tmp_name = sanitize_text_field(wp_unslash($_FILES['file']['tmp_name'])); |
| 104 |
|
| 105 |
if (empty($tmp_name) || !file_exists($tmp_name) || !is_uploaded_file($tmp_name)) { |
| 106 |
throw new Exception(esc_html__('Invalid upload. Please try again.', 'fluent-boards')); |
| 107 |
} |
| 108 |
|
| 109 |
// Check if the uploaded file is an image |
| 110 |
$wp_filetype = wp_check_filetype_and_ext($tmp_name, $filename); |
| 111 |
|
| 112 |
if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { |
| 113 |
throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards')); |
| 114 |
} |
| 115 |
require_once(ABSPATH . 'wp-admin/includes/image.php'); |
| 116 |
require_once( ABSPATH . 'wp-admin/includes/file.php' ); |
| 117 |
require_once( ABSPATH . 'wp-admin/includes/media.php' ); |
| 118 |
$attachment_id = media_handle_upload( 'file', 0, [] ); |
| 119 |
|
| 120 |
$attachment = wp_prepare_attachment_for_js( $attachment_id); |
| 121 |
if(!$attachment) { |
| 122 |
throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards')); |
| 123 |
} else { |
| 124 |
return $attachment; |
| 125 |
} |
| 126 |
} |
| 127 |
|
| 128 |
} |
| 129 |
|