feat(user-center): deepen zibll parity and profile media

This commit is contained in:
2026-07-28 12:22:52 +08:00
parent c13f686cdc
commit e47ee1b029
16 changed files with 479 additions and 65 deletions
+7 -33
View File
@@ -14,6 +14,7 @@ class UserController extends ControllerBase {
use UserControllerAuthPhoneOperations;
use UserControllerRestrictionOperations;
use UserControllerFollowOperations;
use UserControllerProfileMediaOperations;
private static $instance = null;
@@ -44,12 +45,17 @@ class UserController extends ControllerBase {
'permission_callback' => [$this, 'check_permission'],
]);
// User background upload (logged-in users)
// User profile media uploads (logged-in users).
register_rest_route(self::API_NAMESPACE, '/user/background', [
'methods' => 'POST',
'callback' => [$this, 'rest_upload_user_background'],
'permission_callback' => function () { return is_user_logged_in(); },
]);
register_rest_route(self::API_NAMESPACE, '/user/avatar', [
'methods' => 'POST',
'callback' => [$this, 'rest_upload_user_avatar'],
'permission_callback' => function () { return is_user_logged_in(); },
]);
// Comment inline image upload (logged-in users)
register_rest_route(self::API_NAMESPACE, '/comment/upload-image', [
@@ -650,38 +656,6 @@ class UserController extends ControllerBase {
return $this->success(['message' => __('OAuth 代理配置已保存', 'aksrt')]);
}
public function rest_upload_user_background(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
if ($user_id <= 0) {
return $this->error(__('请先登录', 'aksrt'), 401);
}
if (empty($_FILES['background']) && empty($_FILES['file'])) {
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_key = !empty($_FILES['background']) ? 'background' : 'file';
$attachment_id = media_handle_upload($file_key, 0);
if (is_wp_error($attachment_id)) {
return $this->error($attachment_id->get_error_message(), 400);
}
$url = wp_get_attachment_url((int) $attachment_id);
if (!$url) {
return $this->error(__('上传失败', 'aksrt'), 500);
}
update_user_meta($user_id, 'aksrt_background_image', esc_url_raw($url));
update_user_meta($user_id, 'aksrt_background_attachment_id', (int) $attachment_id);
return $this->success([
'message' => __('背景图已更新', 'aksrt'),
'data' => [
'url' => $url,
'attachment_id' => (int) $attachment_id,
],
]);
}
public function rest_upload_comment_image(\WP_REST_Request $request): \WP_REST_Response {
$user_id = get_current_user_id();
if ($user_id <= 0) {
@@ -0,0 +1,112 @@
<?php
/**
* Logged-in user profile media uploads.
*
* @package AKSRT
*/
namespace AKSRT\Admin;
defined('ABSPATH') || exit;
trait UserControllerProfileMediaOperations {
public function rest_upload_user_avatar(\WP_REST_Request $request): \WP_REST_Response {
return $this->upload_profile_image(
['avatar', 'file'],
'aksrt_avatar_attachment_id',
__('头像已更新', 'aksrt'),
true
);
}
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);
}
$center_settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_user_center_settings()
: ['avatar_upload' => true, 'cover_upload' => true];
if ($is_avatar && empty($center_settings['avatar_upload'])) {
return $this->error(__('头像上传功能未开启', 'aksrt'), 403);
}
if (!$is_avatar && (empty($center_settings['cover_upload']) || !aksrt_get_setting('allow_background_upload', false))) {
return $this->error(__('背景图上传功能未开启', '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);
}
$file = $_FILES[$file_key];
if (!empty($file['size']) && (int) $file['size'] > 2 * MB_IN_BYTES) {
return $this->error(__('图片大小不能超过 2MB', 'aksrt'), 413);
}
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$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;
$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) {
$previous = get_post($previous_id);
if ($previous instanceof \WP_Post && (int) $previous->post_author === $user_id) {
wp_delete_attachment($previous_id, true);
}
}
return $this->success([
'message' => $message,
'url' => $url,
'data' => [
'url' => $url,
'attachment_id' => $attachment_id,
],
]);
}
}