fix(user): repair phone binding and profile fields
This commit is contained in:
1 parent
0cf4639d95
commit
f646fa8573
15 files changed
+627
-162
No files matched your search
@@ -267,8 +267,6 @@ if (!function_exists('aksrt_get_avatar_box')) {
|
||||
}
|
||||
}
|
||||
|
||||
add_action('show_user_profile', 'aksrt_render_admin_avatar_field');
|
||||
add_action('edit_user_profile', 'aksrt_render_admin_avatar_field');
|
||||
add_action('user_edit_form_tag', static function (): void {
|
||||
echo ' enctype="multipart/form-data"';
|
||||
});
|
||||
@@ -312,137 +310,6 @@ if (!function_exists('aksrt_get_user_description')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_admin_avatar_field')) {
|
||||
/**
|
||||
* Render local avatar controls on the native WordPress user profile screen.
|
||||
*/
|
||||
function aksrt_render_admin_avatar_field(WP_User $user): void {
|
||||
if (!current_user_can('edit_user', $user->ID) || !aksrt_is_avatar_upload_enabled()) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<h2><?php esc_html_e('AKSRT 头像', 'aksrt'); ?></h2>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e('当前头像', 'aksrt'); ?></th>
|
||||
<td>
|
||||
<?php echo get_avatar($user->ID, 96, '', $user->display_name, ['loading' => 'eager']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<p><input type="file" name="aksrt_avatar_file" accept="image/jpeg,image/png,image/webp,image/gif"></p>
|
||||
<?php if (aksrt_get_custom_avatar_url((int) $user->ID, 96) !== '') : ?>
|
||||
<label><input type="checkbox" name="aksrt_avatar_reset" value="1"> <?php esc_html_e('恢复项目默认头像并删除当前头像文件', 'aksrt'); ?></label>
|
||||
<?php endif; ?>
|
||||
<p class="description"><?php esc_html_e('支持 JPG、PNG、GIF、WebP;大小上限由“权限 → 附件权限”控制。', 'aksrt'); ?></p>
|
||||
<?php wp_nonce_field('aksrt_save_admin_avatar_' . $user->ID, 'aksrt_admin_avatar_nonce'); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
add_filter('user_profile_update_errors', static function (WP_Error $errors, bool $update): void {
|
||||
if (empty($_FILES['aksrt_avatar_file']['name']) || !aksrt_is_avatar_upload_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = $_FILES['aksrt_avatar_file'];
|
||||
// 头像上限并入「前端图片上传限制」统一治理(参考主题同源)。
|
||||
$max_size = class_exists('\AKSRT\Attachment\UploadLimits') ? \AKSRT\Attachment\UploadLimits::limit_bytes('image') : (int) wp_max_upload_size();
|
||||
$actual_size = !empty($file['tmp_name']) && is_readable($file['tmp_name']) ? (int) filesize($file['tmp_name']) : 0;
|
||||
if ((int) ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK || $actual_size <= 0 || $actual_size > $max_size) {
|
||||
$errors->add('aksrt_avatar_size', sprintf(__('头像文件无效或超过 %s', 'aksrt'), size_format($max_size)));
|
||||
return;
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
$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',
|
||||
]);
|
||||
$image_size = wp_getimagesize($file['tmp_name']);
|
||||
if (empty($checked['type']) || empty($checked['ext']) || !wp_match_mime_types('image', $checked['type']) || !$image_size || ((int) $image_size[0] * (int) $image_size[1]) > 40000000) {
|
||||
$errors->add('aksrt_avatar_type', __('头像必须是有效的 JPG、PNG、GIF 或 WebP 图片,且总像素不能超过 4000 万。', 'aksrt'));
|
||||
}
|
||||
}, 10, 2);
|
||||
|
||||
add_action('personal_options_update', 'aksrt_save_admin_avatar_field');
|
||||
add_action('edit_user_profile_update', 'aksrt_save_admin_avatar_field');
|
||||
|
||||
if (!function_exists('aksrt_save_admin_avatar_field')) {
|
||||
/**
|
||||
* Save local avatar changes from the native WordPress profile screen.
|
||||
*/
|
||||
function aksrt_save_admin_avatar_field(int $user_id): void {
|
||||
if (!current_user_can('edit_user', $user_id) || !aksrt_is_avatar_upload_enabled()) {
|
||||
return;
|
||||
}
|
||||
$nonce = isset($_POST['aksrt_admin_avatar_nonce']) ? sanitize_text_field(wp_unslash($_POST['aksrt_admin_avatar_nonce'])) : '';
|
||||
if (!wp_verify_nonce($nonce, 'aksrt_save_admin_avatar_' . $user_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$previous_id = (int) get_user_meta($user_id, 'aksrt_avatar_attachment_id', true);
|
||||
if (!empty($_POST['aksrt_avatar_reset'])) {
|
||||
delete_user_meta($user_id, 'aksrt_avatar_attachment_id');
|
||||
aksrt_delete_owned_avatar_attachment($previous_id, $user_id);
|
||||
do_action('aksrt_user_avatar_changed', $user_id, 0, '');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($_FILES['aksrt_avatar_file']['name'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 头像上限并入「前端图片上传限制」统一治理(参考主题同源)。
|
||||
$max_size = class_exists('\AKSRT\Attachment\UploadLimits') ? \AKSRT\Attachment\UploadLimits::limit_bytes('image') : (int) wp_max_upload_size();
|
||||
$file = $_FILES['aksrt_avatar_file'];
|
||||
$actual_size = !empty($file['tmp_name']) && is_readable($file['tmp_name']) ? (int) filesize($file['tmp_name']) : 0;
|
||||
if ((int) ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK || $actual_size <= 0 || $actual_size > $max_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
$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',
|
||||
]);
|
||||
$image_size = wp_getimagesize($file['tmp_name']);
|
||||
if (empty($checked['type']) || empty($checked['ext']) || !wp_match_mime_types('image', $checked['type']) || !$image_size || ((int) $image_size[0] * (int) $image_size[1]) > 40000000) {
|
||||
return;
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
$attachment_id = media_handle_upload('aksrt_avatar_file', 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) || !wp_attachment_is_image((int) $attachment_id)) {
|
||||
if (!is_wp_error($attachment_id)) {
|
||||
wp_delete_attachment((int) $attachment_id, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$attachment_id = (int) $attachment_id;
|
||||
wp_update_post(['ID' => $attachment_id, 'post_author' => $user_id]);
|
||||
update_post_meta($attachment_id, '_aksrt_profile_media_user_id', $user_id);
|
||||
update_post_meta($attachment_id, '_aksrt_profile_media_type', 'avatar');
|
||||
update_user_meta($user_id, 'aksrt_avatar_attachment_id', $attachment_id);
|
||||
aksrt_delete_owned_avatar_attachment($previous_id, $user_id);
|
||||
do_action('aksrt_user_avatar_changed', $user_id, $attachment_id, (string) wp_get_attachment_image_url($attachment_id, 'thumbnail'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_delete_owned_avatar_attachment')) {
|
||||
/**
|
||||
* Delete an avatar attachment only when it belongs to the target user.
|
||||
|
||||
@@ -12,7 +12,7 @@ if (!function_exists('aksrt_get_user_profile_details')) {
|
||||
* Read the fixed profile details. Social fields are deliberately kept in one
|
||||
* structured meta value so public rendering can filter them server-side.
|
||||
*
|
||||
* @return array{privacy:string,gender:string,website:string,qq:string,wechat:string,github:string}
|
||||
* @return array{privacy:string,gender:string,website:string,qq:string,wechat:string,weibo:string,github:string,address:string}
|
||||
*/
|
||||
function aksrt_get_user_profile_details(int $user_id): array {
|
||||
$raw = get_user_meta($user_id, 'aksrt_profile_details', true);
|
||||
@@ -32,13 +32,15 @@ if (!function_exists('aksrt_get_user_profile_details')) {
|
||||
'website' => esc_url_raw((string) ($raw['website'] ?? '')),
|
||||
'qq' => sanitize_text_field((string) ($raw['qq'] ?? '')),
|
||||
'wechat' => sanitize_text_field((string) ($raw['wechat'] ?? '')),
|
||||
'weibo' => esc_url_raw((string) ($raw['weibo'] ?? '')),
|
||||
'github' => esc_url_raw((string) ($raw['github'] ?? '')),
|
||||
'address' => sanitize_text_field((string) ($raw['address'] ?? '')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_get_visible_user_profile_details')) {
|
||||
/** @return array{gender:string,website:string,qq:string,wechat:string,github:string} */
|
||||
/** @return array{gender:string,website:string,qq:string,wechat:string,weibo:string,github:string,address:string} */
|
||||
function aksrt_get_visible_user_profile_details(int $user_id, int $viewer_id = 0): array {
|
||||
$details = aksrt_get_user_profile_details($user_id);
|
||||
$visible = $viewer_id === $user_id || $details['privacy'] === 'public' || ($details['privacy'] === 'members' && $viewer_id > 0);
|
||||
@@ -47,7 +49,9 @@ if (!function_exists('aksrt_get_visible_user_profile_details')) {
|
||||
'website' => $visible ? $details['website'] : '',
|
||||
'qq' => $visible ? $details['qq'] : '',
|
||||
'wechat' => $visible ? $details['wechat'] : '',
|
||||
'weibo' => $visible ? $details['weibo'] : '',
|
||||
'github' => $visible ? $details['github'] : '',
|
||||
'address' => $visible ? $details['address'] : '',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -86,28 +90,32 @@ if (!function_exists('aksrt_save_user_center_profile')) {
|
||||
}
|
||||
}
|
||||
|
||||
$privacy = isset($input['privacy']) ? sanitize_key(wp_unslash($input['privacy'])) : 'private';
|
||||
$existing_details = aksrt_get_user_profile_details($user_id);
|
||||
$privacy = isset($input['privacy']) ? sanitize_key(wp_unslash($input['privacy'])) : $existing_details['privacy'];
|
||||
if (!in_array($privacy, ['private', 'public', 'members'], true)) {
|
||||
$errors[] = __('无效的隐私设置。', 'aksrt');
|
||||
}
|
||||
$gender = isset($input['gender']) ? sanitize_key(wp_unslash($input['gender'])) : 'secret';
|
||||
$gender = isset($input['gender']) ? sanitize_key(wp_unslash($input['gender'])) : $existing_details['gender'];
|
||||
if (!in_array($gender, ['secret', 'male', 'female'], true)) {
|
||||
$errors[] = __('无效的性别设置。', 'aksrt');
|
||||
}
|
||||
$details = [
|
||||
'privacy' => $privacy,
|
||||
'gender' => $gender,
|
||||
'website' => isset($input['website']) ? esc_url_raw(wp_unslash($input['website'])) : '',
|
||||
'qq' => isset($input['qq']) ? sanitize_text_field(wp_unslash($input['qq'])) : '',
|
||||
'wechat' => isset($input['wechat']) ? sanitize_text_field(wp_unslash($input['wechat'])) : '',
|
||||
'github' => isset($input['github']) ? esc_url_raw(wp_unslash($input['github'])) : '',
|
||||
'website' => isset($input['website']) ? esc_url_raw(wp_unslash($input['website'])) : $existing_details['website'],
|
||||
'qq' => isset($input['qq']) ? sanitize_text_field(wp_unslash($input['qq'])) : $existing_details['qq'],
|
||||
'wechat' => isset($input['wechat']) ? sanitize_text_field(wp_unslash($input['wechat'])) : $existing_details['wechat'],
|
||||
'weibo' => isset($input['weibo']) ? esc_url_raw(wp_unslash($input['weibo'])) : $existing_details['weibo'],
|
||||
'github' => isset($input['github']) ? esc_url_raw(wp_unslash($input['github'])) : $existing_details['github'],
|
||||
'address' => isset($input['address']) ? sanitize_text_field(wp_unslash($input['address'])) : $existing_details['address'],
|
||||
];
|
||||
foreach (['website', 'github'] as $field) {
|
||||
foreach (['website', 'weibo', 'github'] as $field) {
|
||||
if (!empty($input[$field]) && $details[$field] === '') {
|
||||
$errors[] = sprintf(__('无效的%s链接。', 'aksrt'), $field === 'website' ? __('个人网站', 'aksrt') : 'GitHub');
|
||||
$field_label = ['website' => __('个人网站', 'aksrt'), 'weibo' => __('微博', 'aksrt'), 'github' => 'GitHub'][$field];
|
||||
$errors[] = sprintf(__('无效的%s链接。', 'aksrt'), $field_label);
|
||||
}
|
||||
}
|
||||
if (mb_strlen($details['qq']) > 50 || mb_strlen($details['wechat']) > 100) {
|
||||
if (mb_strlen($details['qq']) > 50 || mb_strlen($details['wechat']) > 100 || mb_strlen($details['address']) > 200) {
|
||||
$errors[] = __('社交资料长度超过限制。', 'aksrt');
|
||||
}
|
||||
if ($errors) {
|
||||
|
||||
@@ -66,7 +66,7 @@ function aksrt_get_user_dashboard_view(int $user_id, array $args = []): array {
|
||||
|
||||
$profile_details = function_exists('aksrt_get_visible_user_profile_details')
|
||||
? aksrt_get_visible_user_profile_details($user_id, $viewer_id)
|
||||
: ['gender' => '', 'website' => '', 'qq' => '', 'wechat' => '', 'github' => ''];
|
||||
: ['gender' => '', 'website' => '', 'qq' => '', 'wechat' => '', 'weibo' => '', 'github' => '', 'address' => ''];
|
||||
|
||||
$background_url = function_exists('aksrt_get_user_cover_url') ? aksrt_get_user_cover_url($user_id) : '';
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ $profile_details = isset($profile_details) && is_array($profile_details) ? $prof
|
||||
<label><span><?php esc_html_e('个人网站', 'aksrt'); ?></span><input type="url" name="website" class="profile-input" value="<?php echo esc_attr($profile_details['website']); ?>" placeholder="https://"></label>
|
||||
<label><span>QQ</span><input type="text" name="qq" class="profile-input" maxlength="50" value="<?php echo esc_attr($profile_details['qq']); ?>"></label>
|
||||
<label><span><?php esc_html_e('微信', 'aksrt'); ?></span><input type="text" name="wechat" class="profile-input" maxlength="100" value="<?php echo esc_attr($profile_details['wechat']); ?>"></label>
|
||||
<label><span><?php esc_html_e('微博', 'aksrt'); ?></span><input type="url" name="weibo" class="profile-input" value="<?php echo esc_attr($profile_details['weibo']); ?>" placeholder="https://"></label>
|
||||
<label><span>GitHub</span><input type="url" name="github" class="profile-input" value="<?php echo esc_attr($profile_details['github']); ?>" placeholder="https://github.com/"></label>
|
||||
<label><span><?php esc_html_e('住址', 'aksrt'); ?></span><input type="text" name="address" class="profile-input" maxlength="200" value="<?php echo esc_attr($profile_details['address']); ?>"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ $account_user = isset($target_user) && $target_user instanceof WP_User
|
||||
: wp_get_current_user();
|
||||
$account_user_id = $account_user instanceof WP_User ? (int) $account_user->ID : (int) ($user_id ?? 0);
|
||||
$account_email = $account_user instanceof WP_User ? (string) $account_user->user_email : '';
|
||||
$account_phone = $account_user_id > 0 ? (string) get_user_meta($account_user_id, 'aksrt_phone', true) : '';
|
||||
$account_phone = $account_user_id > 0 ? (string) get_user_meta($account_user_id, 'phone_number', true) : '';
|
||||
$user_settings = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
$sms_settings = class_exists('\\AKSRT\\Sms\\SMS') ? \AKSRT\Sms\SMS::get_instance()->get_provider_config() : [];
|
||||
$phone_available = !empty($user_settings['bind_phone']) && (($sms_settings['sms_sdk'] ?? 'null') !== 'null');
|
||||
|
||||
Reference in new issue
Block a user