ID; } if ($subject instanceof WP_Post) { return (int) $subject->post_author; } if ($subject instanceof WP_Comment) { return (int) $subject->user_id; } if (is_object($subject) && isset($subject->user_id)) { return (int) $subject->user_id; } if (is_numeric($subject)) { return max(0, (int) $subject); } if (is_string($subject) && is_email($subject)) { $user = get_user_by('email', $subject); return $user instanceof WP_User ? (int) $user->ID : 0; } return 0; } } if (!function_exists('aksrt_get_default_avatar_url')) { /** * Return the bundled avatar used when a user has no custom image. */ function aksrt_get_default_avatar_url(): string { return (string) apply_filters( 'aksrt_default_avatar_url', get_theme_file_uri('assets/img/user/default-avatar.svg') ); } } if (!function_exists('aksrt_get_custom_avatar_url')) { /** * Return the locally uploaded avatar URL. */ function aksrt_get_custom_avatar_url(int $user_id, int $size = 96): string { if ($user_id <= 0) { return ''; } $attachment_id = (int) get_user_meta($user_id, 'aksrt_avatar_attachment_id', true); if ($attachment_id <= 0) { return ''; } $attachment = get_post($attachment_id); if (!$attachment instanceof WP_Post || $attachment->post_type !== 'attachment' || (int) $attachment->post_author !== $user_id || !wp_attachment_is_image($attachment_id)) { return ''; } $image = wp_get_attachment_image_url($attachment_id, [$size, $size]); return is_string($image) ? $image : ''; } } if (!function_exists('aksrt_get_avatar_url')) { /** * Resolve the canonical avatar URL used by all AKSRT frontend surfaces. * * @param mixed $subject User subject accepted by get_avatar_url(). * @param array|int $args WordPress avatar args or a numeric size. */ function aksrt_get_avatar_url($subject, $args = []): string { if (is_numeric($args)) { $args = ['size' => (int) $args]; } $args = is_array($args) ? $args : []; $size = max(16, min(512, (int) ($args['size'] ?? 96))); $user_id = aksrt_resolve_avatar_user_id($subject); $custom = aksrt_get_custom_avatar_url($user_id, $size); if ($custom !== '') { return $custom; } return aksrt_get_default_avatar_url(); } } if (!function_exists('aksrt_get_avatar_html')) { /** * Render a canonical avatar image. * * @param mixed $subject User subject. * @param int $size Pixel size. * @param array $attrs Additional safe image attributes. */ function aksrt_get_avatar_html($subject, int $size = 96, array $attrs = []): string { $size = max(16, min(512, $size)); $url = aksrt_get_avatar_url($subject, ['size' => $size]); if ($url === '') { return ''; } $defaults = [ 'class' => 'avatar avatar-' . $size . ' photo', 'alt' => '', 'width' => (string) $size, 'height' => (string) $size, 'loading' => 'lazy', ]; $attrs = array_merge($defaults, $attrs); $html_attrs = ''; foreach ($attrs as $name => $value) { $name = sanitize_key((string) $name); if ($name === '' || $value === false || $value === null) { continue; } $html_attrs .= ' ' . $name . '="' . esc_attr((string) $value) . '"'; } return ''; } } add_filter('get_avatar_data', static function (array $args, $subject): array { $user_id = aksrt_resolve_avatar_user_id($subject); $custom = aksrt_get_custom_avatar_url($user_id, (int) ($args['size'] ?? 96)); $args['url'] = $custom !== '' ? $custom : aksrt_get_default_avatar_url(); $args['found_avatar'] = true; return $args; }, 20, 2); 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"'; }); if (!function_exists('aksrt_is_avatar_upload_enabled')) { /** * Whether local avatar uploads are enabled by attachment policy. */ function aksrt_is_avatar_upload_enabled(): bool { $settings = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_all() : []; return !isset($settings['allow_avatar_upload']) || !empty($settings['allow_avatar_upload']); } } 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; } ?>

$max_size_mb * MB_IN_BYTES) { $errors->add('aksrt_avatar_size', sprintf(__('头像文件无效或超过 %dMB', 'aksrt'), $max_size_mb)); 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; } $settings = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_all() : []; $max_size = max(1, min(10, (int) ($settings['avatar_max_size'] ?? 2))) * MB_IN_BYTES; $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. */ function aksrt_delete_owned_avatar_attachment(int $attachment_id, int $user_id): bool { $attachment = $attachment_id > 0 ? get_post($attachment_id) : null; if (!$attachment instanceof WP_Post || $attachment->post_type !== 'attachment' || (int) $attachment->post_author !== $user_id) { return false; } return (bool) wp_delete_attachment($attachment_id, true); } }