0 ) ? floatval( $config['max_size'] ) : 5; $max_size = $max_size_mb * 1024 * 1024; if ( $file['size'] > $max_size ) { return new WP_Error( 'file_too_large', sprintf( /* translators: %d: maximum file size in megabytes */ __( 'File size exceeds maximum of %dMB.', 'airy-frontend-forms' ), $max_size_mb ) ); } // Validate file type. $allowed_types = isset( $config['allowed_types'] ) ? $config['allowed_types'] : array( 'jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf' ); $file_ext = strtolower( pathinfo( $file['name'], PATHINFO_EXTENSION ) ); if ( ! in_array( $file_ext, $allowed_types, true ) ) { return new WP_Error( 'invalid_file_type', sprintf( /* translators: %s: comma-separated list of allowed file types */ __( 'File type not allowed. Allowed types: %s', 'airy-frontend-forms' ), implode( ', ', $allowed_types ) ) ); } // Verify MIME type matches extension (prevents extension spoofing). $file_type = wp_check_filetype( $file['name'] ); if ( ! $file_type['type'] ) { return new WP_Error( 'invalid_mime_type', __( 'Invalid file type.', 'airy-frontend-forms' ) ); } // Double-check real MIME type of file contents. $real_mime = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'] ); if ( ! empty( $real_mime['proper_filename'] ) ) { // WordPress detected the filename doesn't match the content - use the corrected name. $file['name'] = $real_mime['proper_filename']; } if ( false === $real_mime['ext'] || false === $real_mime['type'] ) { return new WP_Error( 'mime_mismatch', __( 'File content does not match its extension.', 'airy-frontend-forms' ) ); } // Sanitize filename. $file['name'] = sanitize_file_name( $file['name'] ); // Handle the upload. require_once ABSPATH . 'wp-admin/includes/file.php'; $upload_overrides = array( 'test_form' => false, ); $uploaded_file = wp_handle_upload( $file, $upload_overrides ); if ( isset( $uploaded_file['error'] ) ) { return new WP_Error( 'upload_error', $uploaded_file['error'] ); } // Create attachment. $attachment_id = self::create_attachment( $uploaded_file ); return $attachment_id; } /** * Create attachment from uploaded file * * @param array $file Uploaded file data. * @return int Attachment ID. */ private static function create_attachment( $file ) { $file_name = basename( $file['file'] ); $file_type = wp_check_filetype( $file_name ); $attachment = array( 'post_mime_type' => $file_type['type'], 'post_title' => sanitize_file_name( pathinfo( $file_name, PATHINFO_FILENAME ) ), 'post_content' => '', 'post_status' => 'inherit', ); $attachment_id = wp_insert_attachment( $attachment, $file['file'] ); // Generate metadata. require_once ABSPATH . 'wp-admin/includes/image.php'; $attachment_data = wp_generate_attachment_metadata( $attachment_id, $file['file'] ); wp_update_attachment_metadata( $attachment_id, $attachment_data ); return $attachment_id; } /** * Get upload error message * * @param int $error_code PHP upload error code. * @return WP_Error. */ private static function get_upload_error( $error_code ) { $messages = array( UPLOAD_ERR_INI_SIZE => __( 'The file exceeds the maximum upload size.', 'airy-frontend-forms' ), UPLOAD_ERR_FORM_SIZE => __( 'The file exceeds the maximum upload size.', 'airy-frontend-forms' ), UPLOAD_ERR_PARTIAL => __( 'The file was only partially uploaded.', 'airy-frontend-forms' ), UPLOAD_ERR_NO_FILE => __( 'No file was uploaded.', 'airy-frontend-forms' ), UPLOAD_ERR_NO_TMP_DIR => __( 'Missing temporary folder.', 'airy-frontend-forms' ), UPLOAD_ERR_CANT_WRITE => __( 'Failed to write file to disk.', 'airy-frontend-forms' ), UPLOAD_ERR_EXTENSION => __( 'File upload stopped by extension.', 'airy-frontend-forms' ), ); $message = isset( $messages[ $error_code ] ) ? $messages[ $error_code ] : __( 'Unknown upload error.', 'airy-frontend-forms' ); return new WP_Error( 'upload_error', $message ); } /** * Upload multiple files * * @param array $files Files from $_FILES. * @param array $config Upload configuration. * @return array|WP_Error Array of attachment IDs or error. */ public static function upload_multiple( $files, $config = array() ) { $attachment_ids = array(); // Check if max files limit set. $max_files = isset( $config['max_files'] ) ? $config['max_files'] : 0; if ( $max_files > 0 && count( $files['name'] ) > $max_files ) { return new WP_Error( 'too_many_files', sprintf( /* translators: %d: maximum number of files allowed */ __( 'Maximum %d files allowed.', 'airy-frontend-forms' ), $max_files ) ); } // Upload each file. foreach ( $files['name'] as $key => $value ) { if ( $files['name'][ $key ] ) { $file = array( 'name' => $files['name'][ $key ], 'type' => $files['type'][ $key ], 'tmp_name' => $files['tmp_name'][ $key ], 'error' => $files['error'][ $key ], 'size' => $files['size'][ $key ], ); $result = self::upload_file( $file, $config ); if ( is_wp_error( $result ) ) { // Clean up already uploaded files. foreach ( $attachment_ids as $id ) { wp_delete_attachment( $id, true ); } return $result; } $attachment_ids[] = $result; } } return $attachment_ids; } /** * Delete file * * @param int $attachment_id Attachment ID. * @return bool Success. */ public static function delete_file( $attachment_id ) { return wp_delete_attachment( $attachment_id, true ) !== false; } }