prepare() cannot parameterize table names. $allForms = $wpdb->get_results("SELECT forms.id,forms.entries as fm_entries,forms.form_name,forms.status,forms.views,forms.created_at,COUNT(entries.id) as entries FROM `{$wpdb->prefix}bitforms_form` as forms LEFT JOIN `{$wpdb->prefix}bitforms_form_entries` as entries ON forms.id = entries.form_id GROUP BY forms.id"); if (is_wp_error($allForms)) { return $allForms; } $forms = array_reduce($allForms, function ($carry, $form) { $carry[$form->id] = $form->form_name . ' (' . $form->id . ')'; return $carry; }, []); if (!empty($forms)) { $forms[0] = __('Select a Bitform', 'bit-form'); } return $forms; } /** * Request data formatting. * * Receives raw data from ajax request and formats it into an object. * @param mixed $data * @return object */ public static function formatRequestData(): object { // JSON body from AJAX request; nonce verified upstream by the calling AJAX handler before this method is invoked. // wp_unslash only — sanitize_text_field strips HTML tags and would destroy rich-text content (email template bodies). $data = isset($_POST['data']) ? wp_unslash($_POST['data']) : null; if (null === $data) { throw new \InvalidArgumentException('The "data" parameter is required.'); } if (is_array($data)) { return (object) $data; } $userData = $data; $result = json_decode($userData); if (JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException('Invalid JSON provided in data.'); } if ('object' !== gettype($result)) { $emptyObject = new \stdClass(); Log::debug_log([ 'message'=> 'Invalid JSON provided in data. Returning empty object.', 'data' => $userData, 'result' => $result, 'type' => gettype($result) ]); return $emptyObject; } return $result; // // Normalize to array // if (is_string($userData)) { // $decoded = json_decode($userData, true); // if (JSON_ERROR_NONE !== json_last_error()) { // throw new \InvalidArgumentException('Invalid JSON provided in data.'); // } // $userData = $decoded ?? []; // } elseif (is_object($userData)) { // $userData = (array) $userData; // } // if (!is_array($userData)) { // // You may want to throw here instead of returning empty object // return new \stdClass(); // } // // Recursive sanitizer — always returns objects // $sanitizeRecursive = function ($value) use (&$sanitizeRecursive) { // if (is_array($value)) { // $clean = new \stdClass(); // foreach ($value as $k => $v) { // $clean->$k = $sanitizeRecursive($v); // } // return $clean; // } elseif (is_object($value)) { // $clean = new \stdClass(); // foreach ($value as $k => $v) { // $clean->$k = $sanitizeRecursive($v); // } // return $clean; // } else { // return sanitize_text_field($value); // } // }; // return $sanitizeRecursive($userData); // already an object } public static function requirePostMethod(): void { if (!isset($_SERVER['REQUEST_METHOD']) || 'POST' !== sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD']))) { Log::debug_log('Invalid request method. POST required.'); wp_send_json_error(__('Invalid request method. POST required.', 'bit-form'), 405); return; } } public static function sanitize_files_input(array $files): array { $sanitized = []; foreach ($files as $field_key => $file_data) { $field_key = sanitize_key((string) $field_key); if (!isset($file_data['name'])) { continue; } if (is_array($file_data['name'])) { $sanitized[$field_key] = [ 'name' => array_map(function ($v) { return is_array($v) ? array_map('sanitize_file_name', $v) : sanitize_file_name((string) $v); }, $file_data['name']), 'type' => array_map(function ($v) { return is_array($v) ? array_map('sanitize_mime_type', $v) : sanitize_mime_type((string) $v); }, $file_data['type']), 'tmp_name' => array_map(function ($v) { return is_array($v) ? array_map('sanitize_text_field', $v) : sanitize_text_field((string) $v); }, $file_data['tmp_name']), 'error' => array_map(function ($v) { return is_array($v) ? array_map('absint', $v) : absint($v); }, $file_data['error']), 'size' => array_map(function ($v) { return is_array($v) ? array_map('absint', $v) : absint($v); }, $file_data['size']), ]; if (isset($file_data['full_path'])) { $sanitized[$field_key]['full_path'] = array_map(function ($v) { return is_array($v) ? array_map('sanitize_text_field', $v) : sanitize_text_field((string) $v); }, $file_data['full_path']); } if (isset($file_data['new_name'])) { $sanitized[$field_key]['new_name'] = array_map(function ($v) { return is_array($v) ? array_map('sanitize_file_name', $v) : sanitize_file_name((string) $v); }, $file_data['new_name']); } if (isset($file_data['file_path'])) { $sanitized[$field_key]['file_path'] = array_map(function ($v) { return is_array($v) ? array_map('sanitize_text_field', $v) : sanitize_text_field((string) $v); }, $file_data['file_path']); } } else { $sanitized[$field_key] = [ 'name' => sanitize_file_name($file_data['name']), 'type' => sanitize_mime_type($file_data['type']), 'tmp_name' => sanitize_text_field($file_data['tmp_name']), 'error' => absint($file_data['error']), 'size' => absint($file_data['size']), ]; if (isset($file_data['full_path'])) { $v = $file_data['full_path']; $sanitized[$field_key]['full_path'] = is_array($v) ? array_map('sanitize_text_field', $v) : sanitize_text_field($v); } if (isset($file_data['new_name'])) { $v = $file_data['new_name']; $sanitized[$field_key]['new_name'] = is_array($v) ? array_map('sanitize_file_name', $v) : sanitize_file_name($v); } if (isset($file_data['file_path'])) { $v = $file_data['file_path']; $sanitized[$field_key]['file_path'] = is_array($v) ? array_map('sanitize_text_field', $v) : sanitize_text_field($v); } } } return $sanitized; } }