Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
181 lines
7.1 KiB
PHP
181 lines
7.1 KiB
PHP
<?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_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);
|
|
}
|
|
|
|
$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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
|
$max_size_mb = max(1, min(10, (int) ($settings['avatar_max_size'] ?? 2)));
|
|
$max_size = $max_size_mb * MB_IN_BYTES;
|
|
$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(__('图片大小必须在 1 字节至 %dMB 之间', 'aksrt'), $max_size_mb), 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);
|
|
}
|
|
|
|
$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);
|
|
}
|
|
}
|