upload_profile_image( ['avatar', 'file'], 'aksrt_avatar_attachment_id', __('头像已更新', 'aksrt'), true ); } public function rest_delete_user_avatar(\WP_REST_Request $request): \WP_REST_Response { $user_id = get_current_user_id(); if ($user_id <= 0) { return $this->error(__('请先登录', 'aksrt'), 401); } $attachment_id = (int) get_user_meta($user_id, 'aksrt_avatar_attachment_id', true); delete_user_meta($user_id, 'aksrt_avatar_attachment_id'); $this->delete_owned_profile_attachment($attachment_id, $user_id); do_action('aksrt_user_avatar_changed', $user_id, 0, ''); return $this->success([ 'message' => __('已恢复默认头像', 'aksrt'), 'url' => function_exists('aksrt_get_default_avatar_url') ? aksrt_get_default_avatar_url() : '', ]); } public function rest_upload_user_background(\WP_REST_Request $request): \WP_REST_Response { return $this->upload_profile_image( ['background', 'file'], 'aksrt_background_attachment_id', __('背景图已更新', 'aksrt'), false ); } /** * @param string[] $file_keys Accepted multipart field names. */ private function upload_profile_image(array $file_keys, string $meta_key, string $message, bool $is_avatar): \WP_REST_Response { $user_id = get_current_user_id(); if ($user_id <= 0) { return $this->error(__('请先登录', 'aksrt'), 401); } $upload_enabled = $is_avatar ? function_exists('aksrt_is_avatar_upload_enabled') && aksrt_is_avatar_upload_enabled() : function_exists('aksrt_is_user_cover_upload_enabled') && aksrt_is_user_cover_upload_enabled(); if (!$upload_enabled) { return $this->error($is_avatar ? __('当前账号没有上传头像的权限', 'aksrt') : __('当前账号没有上传用户资料卡背景图的权限', 'aksrt'), 403); } $file_key = ''; foreach ($file_keys as $candidate) { if (!empty($_FILES[$candidate])) { $file_key = $candidate; break; } } if ($file_key === '') { return $this->error(__('请选择要上传的图片', 'aksrt'), 400); } require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/media.php'; require_once ABSPATH . 'wp-admin/includes/image.php'; $file = $_FILES[$file_key]; $upload_error = isset($file['error']) ? (int) $file['error'] : UPLOAD_ERR_NO_FILE; if ($upload_error !== UPLOAD_ERR_OK) { return $this->error(__('头像文件上传失败,请重新选择', 'aksrt'), 400); } // 头像与资料卡背景图并入「前端图片上传限制」统一治理(参考主题同源)。 $max_size = class_exists('\AKSRT\Attachment\UploadLimits') ? \AKSRT\Attachment\UploadLimits::limit_bytes('image', $user_id) : (int) wp_max_upload_size(); $actual_size = !empty($file['tmp_name']) && is_readable($file['tmp_name']) ? (int) filesize($file['tmp_name']) : 0; if ($actual_size <= 0 || $actual_size > $max_size) { return $this->error(sprintf(__('图片大小不能超过 %s。', 'aksrt'), size_format($max_size)), 413); } $checked = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], [ 'jpg|jpeg|jpe' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', ]); if (empty($checked['type']) || empty($checked['ext']) || !wp_match_mime_types('image', $checked['type'])) { return $this->error(__('仅支持 JPG、PNG、GIF 或 WebP 图片', 'aksrt'), 415); } $image_size = wp_getimagesize($file['tmp_name']); if (!$image_size || empty($image_size[0]) || empty($image_size[1]) || ((int) $image_size[0] * (int) $image_size[1]) > 40000000) { return $this->error(__('图片无效或尺寸过大', 'aksrt'), 415); } if (!$is_avatar && class_exists('\AKSRT\Extensions\ContentAudit')) { $audit = \AKSRT\Extensions\ContentAudit::get_instance()->audit_image((string) $file['tmp_name']); if (empty($audit['passed'])) { return $this->error(__('图片未通过内容审核', 'aksrt'), 422); } } $attachment_id = media_handle_upload($file_key, 0, [], [ 'test_form' => false, 'mimes' => [ 'jpg|jpeg|jpe' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', ], ]); if (is_wp_error($attachment_id)) { return $this->error($attachment_id->get_error_message(), 400); } $attachment_id = (int) $attachment_id; wp_update_post(['ID' => $attachment_id, 'post_author' => $user_id]); if (!wp_attachment_is_image($attachment_id)) { wp_delete_attachment($attachment_id, true); return $this->error(__('上传文件不是有效图片', 'aksrt'), 415); } update_post_meta($attachment_id, '_aksrt_profile_media_user_id', $user_id); update_post_meta($attachment_id, '_aksrt_profile_media_type', $is_avatar ? 'avatar' : 'background'); $url = wp_get_attachment_image_url($attachment_id, $is_avatar ? 'thumbnail' : 'full'); if (!$url) { wp_delete_attachment($attachment_id, true); return $this->error(__('上传失败', 'aksrt'), 500); } $previous_id = (int) get_user_meta($user_id, $meta_key, true); update_user_meta($user_id, $meta_key, $attachment_id); if (!$is_avatar) { update_user_meta($user_id, 'aksrt_background_image', esc_url_raw($url)); } if ($previous_id > 0 && $previous_id !== $attachment_id) { $this->delete_owned_profile_attachment($previous_id, $user_id); } if ($is_avatar) { do_action('aksrt_user_avatar_changed', $user_id, $attachment_id, $url); } return $this->success([ 'message' => $message, 'url' => $url, 'data' => [ 'url' => $url, 'attachment_id' => $attachment_id, ], ]); } private function delete_owned_profile_attachment(int $attachment_id, int $user_id): bool { if ($attachment_id <= 0) { return false; } $attachment = get_post($attachment_id); if (!$attachment instanceof \WP_Post || $attachment->post_type !== 'attachment' || (int) $attachment->post_author !== $user_id) { return false; } $managed_user_id = (int) get_post_meta($attachment_id, '_aksrt_profile_media_user_id', true); if ($managed_user_id > 0 && $managed_user_id !== $user_id) { return false; } return (bool) wp_delete_attachment($attachment_id, true); } }