v1.8.1 添加多站点支持

This commit is contained in:
文派备案 2025-05-19 03:26:25 +08:00
parent 31a0254299
commit 88d798a5a5
6 changed files with 2449 additions and 404 deletions

View file

@ -9,6 +9,7 @@ jQuery(document).ready(function($) {
return;
}
// Tab navigation
$('.wpavatar-tab').on('click', function() {
var tab = $(this).data('tab');
if (!tab) return;
@ -21,7 +22,11 @@ jQuery(document).ready(function($) {
if (tab === 'cache' && $('#cache-stats').is(':empty')) {
setTimeout(function() {
$('#check-cache').trigger('click');
if (wpavatar.is_network_admin === '1') {
$('#check-all-cache').trigger('click');
} else {
$('#check-cache').trigger('click');
}
}, 300);
}
@ -32,6 +37,7 @@ jQuery(document).ready(function($) {
}
});
// CDN options management
function updateCdnOptions() {
var selectedType = $('input[name="wpavatar_cdn_type"]:checked').val();
@ -53,23 +59,32 @@ jQuery(document).ready(function($) {
if (value && value.toLowerCase().indexOf('cravatar') !== -1) {
forceMd5HashMethod(true);
} else {
// 非Cravatar服务默认选择SHA256但不强制
var currentHashMethod = $('input[name="wpavatar_hash_method"]:checked').val();
if (!currentHashMethod) {
$('input[name="wpavatar_hash_method"][value="sha256"]').prop('checked', true);
}
forceMd5HashMethod(false);
}
}
function forceMd5HashMethod(force) {
if (force) {
// Save the current user-selected hash method to restore later if needed
var currentMethod = $('input[name="wpavatar_hash_method"]:checked').val();
if (currentMethod) {
$(this).data('previous-hash-method', currentMethod);
}
// Force MD5 and disable SHA256 option
$('input[name="wpavatar_hash_method"][value="md5"]').prop('checked', true);
$('input[name="wpavatar_hash_method"][value="sha256"]').prop('disabled', true);
$('.hash-method-notice').show();
} else {
// Restore disabled state, but don't change selection
$('input[name="wpavatar_hash_method"][value="sha256"]').prop('disabled', false);
$('.hash-method-notice').hide();
// Restore previous selection (if any)
var previousMethod = $(this).data('previous-hash-method');
if (previousMethod && previousMethod === 'sha256') {
$('input[name="wpavatar_hash_method"][value="sha256"]').prop('checked', true);
}
}
}
@ -85,6 +100,7 @@ jQuery(document).ready(function($) {
checkIfCravatarRelated($(this).val());
});
// Cache management for single site
$('#check-cache').on('click', function() {
var $button = $(this);
var $stats = $('#cache-stats');
@ -165,6 +181,111 @@ jQuery(document).ready(function($) {
});
});
// Cache management for network admin
if (wpavatar.is_network_admin === '1') {
$('#check-all-cache').on('click', function() {
var $button = $(this);
var $stats = $('#cache-stats');
$button.prop('disabled', true).text(wpavatar_l10n.checking);
$stats.html('<p>' + wpavatar_l10n.checking_status + '</p>');
$.ajax({
type: 'POST',
url: wpavatar.ajaxurl,
data: {
action: 'wpavatar_check_all_cache',
nonce: wpavatar.nonce
},
success: function(response) {
if (response.success) {
$stats.html(response.data);
} else {
$stats.html('<div class="error"><p>' + (response.data || wpavatar_l10n.check_failed) + '</p></div>');
}
},
error: function() {
$stats.html('<div class="error"><p>' + wpavatar_l10n.request_failed + '</p></div>');
},
complete: function() {
$button.prop('disabled', false).text('查看所有站点缓存');
}
});
});
$('#purge-all-cache').on('click', function() {
var $button = $(this);
var $stats = $('#cache-stats');
var $status = $('#wpavatar-status');
if (!confirm(wpavatar_l10n.confirm_purge)) {
return;
}
$button.prop('disabled', true).text(wpavatar_l10n.purging);
$stats.html('<p>' + wpavatar_l10n.purging_cache + '</p>');
$.ajax({
type: 'POST',
url: wpavatar.ajaxurl,
data: {
action: 'wpavatar_purge_all_cache',
nonce: wpavatar.nonce
},
success: function(response) {
if (response.success) {
$status.removeClass('notice-error')
.addClass('notice-success')
.text(response.data)
.show()
.delay(3000)
.fadeOut();
setTimeout(function() {
$('#check-all-cache').trigger('click');
}, 1000);
} else {
$status.removeClass('notice-success')
.addClass('notice-error')
.text(response.data || wpavatar_l10n.purge_failed)
.show();
}
},
error: function() {
$status.removeClass('notice-success')
.addClass('notice-error')
.text(wpavatar_l10n.request_failed)
.show();
},
complete: function() {
$button.prop('disabled', false).text('清空所有站点缓存');
}
});
});
// Network management controls
if ($('#select-all-options').length) {
$('#select-all-options').on('click', function() {
$('input[name="wpavatar_network_controlled_options[]"]').prop('checked', true);
});
$('#deselect-all-options').on('click', function() {
$('input[name="wpavatar_network_controlled_options[]"]').prop('checked', false);
});
$('#reset-default-options').on('click', function() {
if (confirm(wpavatar_l10n.confirm_reset)) {
var defaultOptions = ['wpavatar_enable_cravatar', 'wpavatar_cdn_type', 'wpavatar_cravatar_route', 'wpavatar_third_party_mirror', 'wpavatar_custom_cdn'];
$('input[name="wpavatar_network_controlled_options[]"]').each(function() {
$(this).prop('checked', defaultOptions.indexOf($(this).val()) !== -1);
});
}
});
}
}
// Form validation
$('#wpavatar-basic-form, #wpavatar-cache-form, #wpavatar-advanced-form, #wpavatar-shortcodes-form').on('submit', function(e) {
var formId = $(this).attr('id');
var $status = $('#wpavatar-status');
@ -202,6 +323,28 @@ jQuery(document).ready(function($) {
return true;
});
// For network import and bulk operations
if ($('#import-site-settings').length) {
$('#import-site-settings').on('click', function(e) {
if (!confirm(wpavatar_l10n.confirm_import)) {
e.preventDefault();
return false;
}
return true;
});
}
if ($('#apply-to-all-sites').length) {
$('#apply-to-all-sites').on('click', function(e) {
if (!confirm('确定要将网络设置应用到所有站点吗?此操作将覆盖每个站点的现有设置。')) {
e.preventDefault();
return false;
}
return true;
});
}
// Settings saved notification
if (window.location.search.indexOf('settings-updated=true') > -1) {
$('#wpavatar-status')
.removeClass('notice-error')
@ -212,6 +355,29 @@ jQuery(document).ready(function($) {
.fadeOut();
}
// Import settings notification
if (window.location.search.indexOf('imported=true') > -1) {
$('#wpavatar-status')
.removeClass('notice-error')
.addClass('notice-success')
.text('站点设置已成功导入到网络设置。')
.show()
.delay(3000)
.fadeOut();
}
// Applied to all sites notification
if (window.location.search.indexOf('applied=true') > -1) {
$('#wpavatar-status')
.removeClass('notice-error')
.addClass('notice-success')
.text('网络设置已成功应用到所有站点。')
.show()
.delay(3000)
.fadeOut();
}
// Set active tab
var currentTab = '';
if (window.location.search.indexOf('tab=') > -1) {

View file

@ -81,9 +81,32 @@ class Settings {
return get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
}
$index_file = $value . 'index.php';
if (!file_exists($index_file)) {
@file_put_contents($index_file, '<?php // Silence is golden.');
// If multisite, ensure the site-specific cache directory exists
if (is_multisite()) {
$blog_id = get_current_blog_id();
$site_cache_dir = trailingslashit($value) . 'site-' . $blog_id;
if (!file_exists($site_cache_dir)) {
if (!wp_mkdir_p($site_cache_dir)) {
add_settings_error(
'wpavatar_cache',
'cache_path_invalid',
__('无法创建站点缓存目录,请检查权限', 'wpavatar'),
'error'
);
return get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
}
}
$index_file = $site_cache_dir . '/index.php';
if (!file_exists($index_file)) {
@file_put_contents($index_file, '<?php // Silence is golden.');
}
} else {
$index_file = $value . 'index.php';
if (!file_exists($index_file)) {
@file_put_contents($index_file, '<?php // Silence is golden.');
}
}
return $value;
@ -112,9 +135,11 @@ class Settings {
wp_localize_script('wpavatar-admin', 'wpavatar', [
'nonce' => wp_create_nonce('wpavatar_admin_nonce'),
'ajaxurl' => admin_url('admin-ajax.php'),
'cache_path' => get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR),
'cache_path' => wpavatar_get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR),
'plugin_url' => WPAVATAR_PLUGIN_URL,
'assets_url' => WPAVATAR_PLUGIN_URL . 'assets/',
'is_network_admin' => '0',
'is_multisite' => is_multisite() ? '1' : '0',
]);
wp_localize_script('wpavatar-admin', 'wpavatar_l10n', [
@ -142,6 +167,17 @@ class Settings {
}
public static function render_settings_page() {
// Check for network control in multisite
if (is_multisite()) {
$network_enabled = get_site_option('wpavatar_network_enabled', 1);
$network_enforce = get_site_option('wpavatar_network_enforce', 0);
$network_controlled_options = get_site_option('wpavatar_network_controlled_options', array());
if (!is_array($network_controlled_options)) {
$network_controlled_options = explode(',', $network_controlled_options);
}
}
$active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'basic';
?>
<div class="wrap wpavatar-settings">
@ -174,24 +210,66 @@ class Settings {
<h2><?php _e('基础设置', 'wpavatar'); ?></h2>
<p class="wpavatar-section-desc"><?php _e('配置头像服务和CDN设置。', 'wpavatar'); ?></p>
<?php if (is_multisite() && $network_enabled): ?>
<div class="wpavatar-network-notice">
<p>
<?php if (in_array('wpavatar_enable_cravatar', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('启用初认头像', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_cdn_type', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('线路选择', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_cravatar_route', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('Cravatar官方源', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_third_party_mirror', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('第三方镜像', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_custom_cdn', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('自定义CDN', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_hash_method', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('头像哈希方法', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_timeout', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('超时设置', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (array_intersect(['wpavatar_enable_cravatar', 'wpavatar_cdn_type', 'wpavatar_cravatar_route', 'wpavatar_third_party_mirror', 'wpavatar_custom_cdn', 'wpavatar_hash_method', 'wpavatar_timeout'], $network_controlled_options)): ?>
<em><?php _e('以上选项由网络管理员控制,您的更改将不会生效。', 'wpavatar'); ?></em>
<?php endif; ?>
</p>
</div>
<?php endif; ?>
<form method="post" action="options.php" id="wpavatar-basic-form">
<?php
settings_fields('wpavatar_basic');
$enable_cravatar = get_option('wpavatar_enable_cravatar', 1);
$cdn_type = get_option('wpavatar_cdn_type', 'cravatar_route');
$cravatar_route = get_option('wpavatar_cravatar_route', 'cravatar.com');
$third_party_mirror = get_option('wpavatar_third_party_mirror', 'weavatar.com');
$custom_cdn = get_option('wpavatar_custom_cdn', '');
$hash_method = get_option('wpavatar_hash_method', 'md5');
$timeout = get_option('wpavatar_timeout', 5);
// Get option values using wpavatar_get_option instead of get_option
$enable_cravatar = wpavatar_get_option('wpavatar_enable_cravatar', 1);
$cdn_type = wpavatar_get_option('wpavatar_cdn_type', 'cravatar_route');
$cravatar_route = wpavatar_get_option('wpavatar_cravatar_route', 'cravatar.com');
$third_party_mirror = wpavatar_get_option('wpavatar_third_party_mirror', 'weavatar.com');
$custom_cdn = wpavatar_get_option('wpavatar_custom_cdn', '');
$hash_method = wpavatar_get_option('wpavatar_hash_method', 'md5');
$timeout = wpavatar_get_option('wpavatar_timeout', 5);
// Determine if fields should be disabled in multisite
$disabled_enable_cravatar = (is_multisite() && $network_enabled && in_array('wpavatar_enable_cravatar', $network_controlled_options)) ? 'disabled' : '';
$disabled_cdn_type = (is_multisite() && $network_enabled && in_array('wpavatar_cdn_type', $network_controlled_options)) ? 'disabled' : '';
$disabled_cravatar_route = (is_multisite() && $network_enabled && in_array('wpavatar_cravatar_route', $network_controlled_options)) ? 'disabled' : '';
$disabled_third_party_mirror = (is_multisite() && $network_enabled && in_array('wpavatar_third_party_mirror', $network_controlled_options)) ? 'disabled' : '';
$disabled_custom_cdn = (is_multisite() && $network_enabled && in_array('wpavatar_custom_cdn', $network_controlled_options)) ? 'disabled' : '';
$disabled_hash_method = (is_multisite() && $network_enabled && in_array('wpavatar_hash_method', $network_controlled_options)) ? 'disabled' : '';
$disabled_timeout = (is_multisite() && $network_enabled && in_array('wpavatar_timeout', $network_controlled_options)) ? 'disabled' : '';
?>
<table class="form-table">
<tr>
<th><?php _e('启用初认头像', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-switch">
<input type="checkbox" name="wpavatar_enable_cravatar" value="1" <?php checked($enable_cravatar); ?>>
<input type="checkbox" name="wpavatar_enable_cravatar" value="1" <?php checked($enable_cravatar); ?> <?php echo $disabled_enable_cravatar; ?>>
<span class="wpavatar-slider"></span>
<span class="wpavatar-switch-label"><?php _e('替换WordPress默认头像为Cravatar', 'wpavatar'); ?></span>
</label>
@ -202,15 +280,15 @@ class Settings {
<th><?php _e('线路选择', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-radio">
<input type="radio" name="wpavatar_cdn_type" value="cravatar_route" <?php checked($cdn_type, 'cravatar_route'); ?>>
<input type="radio" name="wpavatar_cdn_type" value="cravatar_route" <?php checked($cdn_type, 'cravatar_route'); ?> <?php echo $disabled_cdn_type; ?>>
<span class="wpavatar-radio-label"><?php _e('Cravatar自选线路', 'wpavatar'); ?></span>
</label><br>
<label class="wpavatar-radio">
<input type="radio" name="wpavatar_cdn_type" value="third_party" <?php checked($cdn_type, 'third_party'); ?>>
<input type="radio" name="wpavatar_cdn_type" value="third_party" <?php checked($cdn_type, 'third_party'); ?> <?php echo $disabled_cdn_type; ?>>
<span class="wpavatar-radio-label"><?php _e('第三方镜像', 'wpavatar'); ?></span>
</label><br>
<label class="wpavatar-radio">
<input type="radio" name="wpavatar_cdn_type" value="custom" <?php checked($cdn_type, 'custom'); ?>>
<input type="radio" name="wpavatar_cdn_type" value="custom" <?php checked($cdn_type, 'custom'); ?> <?php echo $disabled_cdn_type; ?>>
<span class="wpavatar-radio-label"><?php _e('自定义CDN', 'wpavatar'); ?></span>
</label>
</td>
@ -218,7 +296,7 @@ class Settings {
<tr class="cdn-option cravatar-route-option" <?php echo $cdn_type !== 'cravatar_route' ? 'style="display:none;"' : ''; ?>>
<th><?php _e('Cravatar官方源', 'wpavatar'); ?></th>
<td>
<select name="wpavatar_cravatar_route" class="wpavatar-select">
<select name="wpavatar_cravatar_route" class="wpavatar-select" <?php echo $disabled_cravatar_route; ?>>
<option value="cravatar.cn" <?php selected($cravatar_route, 'cravatar.cn'); ?>><?php _e('默认线路 (cravatar.com)', 'wpavatar'); ?></option>
<option value="cn.cravatar.com" <?php selected($cravatar_route, 'cn.cravatar.com'); ?>><?php _e('中国 (cn.cravatar.com)', 'wpavatar'); ?></option>
<option value="hk.cravatar.com" <?php selected($cravatar_route, 'hk.cravatar.com'); ?>><?php _e('香港 (hk.cravatar.com)', 'wpavatar'); ?></option>
@ -230,7 +308,7 @@ class Settings {
<tr class="cdn-option third-party-option" <?php echo $cdn_type !== 'third_party' ? 'style="display:none;"' : ''; ?>>
<th><?php _e('第三方镜像', 'wpavatar'); ?></th>
<td>
<select name="wpavatar_third_party_mirror" class="wpavatar-select">
<select name="wpavatar_third_party_mirror" class="wpavatar-select" <?php echo $disabled_third_party_mirror; ?>>
<option value="weavatar.com" <?php selected($third_party_mirror, 'weavatar.com'); ?>><?php _e('WeAvatar (weavatar.com)', 'wpavatar'); ?></option>
<option value="libravatar.org" <?php selected($third_party_mirror, 'libravatar.org'); ?>><?php _e('Libravatar (libravatar.org)', 'wpavatar'); ?></option>
<option value="gravatar.loli.net" <?php selected($third_party_mirror, 'gravatar.loli.net'); ?>><?php _e('Loli镜像 (gravatar.loli.net)', 'wpavatar'); ?></option>
@ -244,7 +322,7 @@ class Settings {
<tr class="cdn-option custom-cdn-option" <?php echo $cdn_type !== 'custom' ? 'style="display:none;"' : ''; ?>>
<th><?php _e('自定义CDN', 'wpavatar'); ?></th>
<td>
<input type="text" name="wpavatar_custom_cdn" value="<?php echo esc_attr($custom_cdn); ?>" class="regular-text wpavatar-input">
<input type="text" name="wpavatar_custom_cdn" value="<?php echo esc_attr($custom_cdn); ?>" class="regular-text wpavatar-input" <?php echo $disabled_custom_cdn; ?>>
<p class="description"><?php _e('输入自定义CDN域名例如cdn.example.com', 'wpavatar'); ?></p>
</td>
</tr>
@ -252,21 +330,21 @@ class Settings {
<th><?php _e('头像哈希方法', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-radio">
<input type="radio" name="wpavatar_hash_method" value="md5" <?php checked($hash_method, 'md5'); ?>>
<input type="radio" name="wpavatar_hash_method" value="md5" <?php checked($hash_method, 'md5'); ?> <?php echo $disabled_hash_method; ?>>
<span class="wpavatar-radio-label"><?php _e('MD5 (Cravatar默认)', 'wpavatar'); ?></span>
</label><br>
<label class="wpavatar-radio">
<input type="radio" name="wpavatar_hash_method" value="sha256" <?php checked($hash_method, 'sha256'); ?>>
<input type="radio" name="wpavatar_hash_method" value="sha256" <?php checked($hash_method, 'sha256'); ?> <?php echo $disabled_hash_method; ?>>
<span class="wpavatar-radio-label"><?php _e('SHA256 (Gravatar默认)', 'wpavatar'); ?></span>
</label>
<p class="description"><?php _e('选择头像邮箱的哈希方法Cravatar目前使用MD5一般Gravatar镜像均为SHA256', 'wpavatar'); ?></p>
<p class="description hash-method-notice" style="color: #d63638; <?php echo $cdn_type !== 'cravatar_route' ? 'display:none;' : ''; ?>"><?php _e('注意使用Cravatar服务时哈希方法将仅使用MD5', 'wpavatar'); ?></p>
<p class="description hash-method-notice" style="color: #d63638; <?php echo $cdn_type !== 'cravatar_route' ? 'display:none;' : ''; ?>"><?php _e('注意使用Cravatar服务时哈希方法将仅使用MD5', 'wpavatar'); ?> <a href="https://cravatar.com/docs" target="_blank" rel="noopener noreferrer"><?php _e('进一步了解↗', 'wpavatar'); ?></a></p>
</td>
</tr>
<tr>
<th><?php _e('超时设置', 'wpavatar'); ?></th>
<td>
<input type="number" name="wpavatar_timeout" value="<?php echo esc_attr($timeout); ?>" min="1" max="30" class="small-text wpavatar-input">
<input type="number" name="wpavatar_timeout" value="<?php echo esc_attr($timeout); ?>" min="1" max="30" class="small-text wpavatar-input" <?php echo $disabled_timeout; ?>>
<?php _e('秒', 'wpavatar'); ?>
<p class="description"><?php _e('头像请求的最大等待时间,超过后将使用备用头像', 'wpavatar'); ?></p>
</td>
@ -283,6 +361,26 @@ class Settings {
<h2><?php _e('缓存控制', 'wpavatar'); ?></h2>
<p class="wpavatar-section-desc"><?php _e('管理头像缓存设置和操作。', 'wpavatar'); ?></p>
<?php if (is_multisite() && $network_enabled): ?>
<div class="wpavatar-network-notice">
<p>
<?php if (in_array('wpavatar_enable_cache', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('启用本地缓存', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_cache_path', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('缓存目录', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_cache_expire', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('缓存过期时间', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (array_intersect(['wpavatar_enable_cache', 'wpavatar_cache_path', 'wpavatar_cache_expire'], $network_controlled_options)): ?>
<em><?php _e('以上选项由网络管理员控制,您的更改将不会生效。', 'wpavatar'); ?></em>
<?php endif; ?>
</p>
</div>
<?php endif; ?>
<div class="wpavatar-stats-card">
<h3><?php _e('缓存统计', 'wpavatar'); ?></h3>
<div id="cache-stats" class="cache-stats-wrapper"></div>
@ -296,16 +394,22 @@ class Settings {
<?php
settings_fields('wpavatar_cache');
$enable_cache = get_option('wpavatar_enable_cache', 1);
$cache_path = get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
$cache_expire = get_option('wpavatar_cache_expire', 7);
// Get option values using wpavatar_get_option instead of get_option
$enable_cache = wpavatar_get_option('wpavatar_enable_cache', 1);
$cache_path = wpavatar_get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
$cache_expire = wpavatar_get_option('wpavatar_cache_expire', 7);
// Determine if fields should be disabled in multisite
$disabled_enable_cache = (is_multisite() && $network_enabled && in_array('wpavatar_enable_cache', $network_controlled_options)) ? 'disabled' : '';
$disabled_cache_path = (is_multisite() && $network_enabled && in_array('wpavatar_cache_path', $network_controlled_options)) ? 'disabled' : '';
$disabled_cache_expire = (is_multisite() && $network_enabled && in_array('wpavatar_cache_expire', $network_controlled_options)) ? 'disabled' : '';
?>
<table class="form-table">
<tr>
<th><?php _e('启用本地缓存', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-switch">
<input type="checkbox" name="wpavatar_enable_cache" value="1" <?php checked($enable_cache); ?>>
<input type="checkbox" name="wpavatar_enable_cache" value="1" <?php checked($enable_cache); ?> <?php echo $disabled_enable_cache; ?>>
<span class="wpavatar-slider"></span>
<span class="wpavatar-switch-label"><?php _e('缓存头像到本地服务器', 'wpavatar'); ?></span>
</label>
@ -315,14 +419,18 @@ class Settings {
<tr>
<th><?php _e('缓存目录', 'wpavatar'); ?></th>
<td>
<input type="text" name="wpavatar_cache_path" value="<?php echo esc_attr($cache_path); ?>" class="regular-text wpavatar-input">
<input type="text" name="wpavatar_cache_path" value="<?php echo esc_attr($cache_path); ?>" class="regular-text wpavatar-input" <?php echo $disabled_cache_path; ?>>
<?php if (is_multisite()): ?>
<p class="description"><?php printf(__('确保目录可写,当前站点将创建子目录:%s', 'wpavatar'), trailingslashit($cache_path) . 'site-' . get_current_blog_id()); ?></p>
<?php else: ?>
<p class="description"><?php _e('确保目录可写,建议路径:/wp-content/uploads/cravatar', 'wpavatar'); ?></p>
<?php endif; ?>
</td>
</tr>
<tr>
<th><?php _e('缓存过期时间', 'wpavatar'); ?></th>
<td>
<input type="number" name="wpavatar_cache_expire" value="<?php echo esc_attr($cache_expire); ?>" min="1" max="30" class="small-text wpavatar-input">
<input type="number" name="wpavatar_cache_expire" value="<?php echo esc_attr($cache_expire); ?>" min="1" max="30" class="small-text wpavatar-input" <?php echo $disabled_cache_expire; ?>>
<?php _e('天', 'wpavatar'); ?>
<p class="description"><?php _e('头像缓存的有效期,过期后将重新获取', 'wpavatar'); ?></p>
</td>
@ -339,21 +447,47 @@ class Settings {
<h2><?php _e('高级设置', 'wpavatar'); ?></h2>
<p class="wpavatar-section-desc"><?php _e('配置头像的SEO和备用方案。', 'wpavatar'); ?></p>
<?php if (is_multisite() && $network_enabled): ?>
<div class="wpavatar-network-notice">
<p>
<?php if (in_array('wpavatar_seo_alt', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('SEO替代文本', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_fallback_mode', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('头像加载失败处理', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_fallback_avatar', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('备用头像选择', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (array_intersect(['wpavatar_seo_alt', 'wpavatar_fallback_mode', 'wpavatar_fallback_avatar'], $network_controlled_options)): ?>
<em><?php _e('以上选项由网络管理员控制,您的更改将不会生效。', 'wpavatar'); ?></em>
<?php endif; ?>
</p>
</div>
<?php endif; ?>
<form method="post" action="options.php" id="wpavatar-advanced-form">
<?php
settings_fields('wpavatar_advanced');
$seo_alt = get_option('wpavatar_seo_alt', '%s的头像');
$fallback_mode = get_option('wpavatar_fallback_mode', 1);
$fallback_avatar = get_option('wpavatar_fallback_avatar', 'default');
// Get option values using wpavatar_get_option instead of get_option
$seo_alt = wpavatar_get_option('wpavatar_seo_alt', '%s的头像');
$fallback_mode = wpavatar_get_option('wpavatar_fallback_mode', 1);
$fallback_avatar = wpavatar_get_option('wpavatar_fallback_avatar', 'default');
$local_avatars = \WPAvatar\Cravatar::get_local_avatars();
// Determine if fields should be disabled in multisite
$disabled_seo_alt = (is_multisite() && $network_enabled && in_array('wpavatar_seo_alt', $network_controlled_options)) ? 'disabled' : '';
$disabled_fallback_mode = (is_multisite() && $network_enabled && in_array('wpavatar_fallback_mode', $network_controlled_options)) ? 'disabled' : '';
$disabled_fallback_avatar = (is_multisite() && $network_enabled && in_array('wpavatar_fallback_avatar', $network_controlled_options)) ? 'disabled' : '';
?>
<table class="form-table">
<tr>
<th><?php _e('SEO替代文本', 'wpavatar'); ?></th>
<td>
<input type="text" name="wpavatar_seo_alt" value="<?php echo esc_attr($seo_alt); ?>" class="regular-text wpavatar-input">
<input type="text" name="wpavatar_seo_alt" value="<?php echo esc_attr($seo_alt); ?>" class="regular-text wpavatar-input" <?php echo $disabled_seo_alt; ?>>
<p class="description"><?php _e('头像的ALT文本%s将被替换为用户名', 'wpavatar'); ?></p>
</td>
</tr>
@ -361,7 +495,7 @@ class Settings {
<th><?php _e('头像加载失败处理', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-switch">
<input type="checkbox" name="wpavatar_fallback_mode" value="1" <?php checked($fallback_mode); ?>>
<input type="checkbox" name="wpavatar_fallback_mode" value="1" <?php checked($fallback_mode); ?> <?php echo $disabled_fallback_mode; ?>>
<span class="wpavatar-slider"></span>
<span class="wpavatar-switch-label"><?php _e('启用备用头像', 'wpavatar'); ?></span>
</label>
@ -374,7 +508,7 @@ class Settings {
<div class="default-avatar-options">
<?php foreach ($local_avatars as $key => $avatar) : ?>
<label>
<input type="radio" name="wpavatar_fallback_avatar" value="<?php echo esc_attr($key); ?>" <?php checked($fallback_avatar, $key); ?>>
<input type="radio" name="wpavatar_fallback_avatar" value="<?php echo esc_attr($key); ?>" <?php checked($fallback_avatar, $key); ?> <?php echo $disabled_fallback_avatar; ?>>
<img src="<?php echo esc_url($avatar['url']); ?>" alt="<?php echo esc_attr($avatar['name']); ?>" width="48" height="48">
<span class="avatar-option-name"><?php echo esc_html($avatar['name']); ?></span>
</label>
@ -388,7 +522,7 @@ class Settings {
: 'https://wpcy.com';
printf(
__('选择您喜欢的故障备用头像,如需智能线路切换,请使用%s。', 'wpavatar'),
__('选择您的故障备用头像,如需智能线路切换,请使用%s。', 'wpavatar'),
sprintf(
'<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>',
esc_url($wpcy_link),
@ -397,7 +531,7 @@ class Settings {
);
?>
</p>
</td>
</td>
</tr>
</table>
<div class="wpavatar-submit-wrapper">
@ -407,11 +541,30 @@ class Settings {
</form>
</div>
<div class="wpavatar-section" id="wpavatar-section-shortcodes" style="<?php echo $active_tab !== 'shortcodes' ? 'display: none;' : ''; ?>">
<h2><?php _e('简码设置', 'wpavatar'); ?></h2>
<p class="wpavatar-section-desc"><?php _e('配置头像简码的默认参数和预览效果。', 'wpavatar'); ?></p>
<?php if (is_multisite() && $network_enabled): ?>
<div class="wpavatar-network-notice">
<p>
<?php if (in_array('wpavatar_shortcode_size', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('默认头像大小', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_shortcode_class', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('默认CSS类名', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (in_array('wpavatar_shortcode_shape', $network_controlled_options)): ?>
<span class="dashicons dashicons-lock"></span> <?php _e('默认头像形状', 'wpavatar'); ?><br>
<?php endif; ?>
<?php if (array_intersect(['wpavatar_shortcode_size', 'wpavatar_shortcode_class', 'wpavatar_shortcode_shape'], $network_controlled_options)): ?>
<em><?php _e('以上选项由网络管理员控制,您的更改将不会生效。', 'wpavatar'); ?></em>
<?php endif; ?>
</p>
</div>
<?php endif; ?>
<div class="wpavatar-preview-container">
<h3><?php _e('头像预览', 'wpavatar'); ?></h3>
<div class="wpavatar-preview-wrapper">
@ -447,29 +600,35 @@ class Settings {
<?php
settings_fields('wpavatar_shortcodes');
$shortcode_size = get_option('wpavatar_shortcode_size', 96);
$shortcode_class = get_option('wpavatar_shortcode_class', 'wpavatar');
$shortcode_shape = get_option('wpavatar_shortcode_shape', 'square');
// Get option values using wpavatar_get_option instead of get_option
$shortcode_size = wpavatar_get_option('wpavatar_shortcode_size', 96);
$shortcode_class = wpavatar_get_option('wpavatar_shortcode_class', 'wpavatar');
$shortcode_shape = wpavatar_get_option('wpavatar_shortcode_shape', 'square');
// Determine if fields should be disabled in multisite
$disabled_shortcode_size = (is_multisite() && $network_enabled && in_array('wpavatar_shortcode_size', $network_controlled_options)) ? 'disabled' : '';
$disabled_shortcode_class = (is_multisite() && $network_enabled && in_array('wpavatar_shortcode_class', $network_controlled_options)) ? 'disabled' : '';
$disabled_shortcode_shape = (is_multisite() && $network_enabled && in_array('wpavatar_shortcode_shape', $network_controlled_options)) ? 'disabled' : '';
?>
<table class="form-table">
<tr>
<th><?php _e('默认头像大小', 'wpavatar'); ?></th>
<td>
<input type="number" name="wpavatar_shortcode_size" value="<?php echo esc_attr($shortcode_size); ?>" min="16" max="512" class="small-text wpavatar-input">
<input type="number" name="wpavatar_shortcode_size" value="<?php echo esc_attr($shortcode_size); ?>" min="16" max="512" class="small-text wpavatar-input" <?php echo $disabled_shortcode_size; ?>>
<p class="description"><?php _e('简码默认头像大小(像素)', 'wpavatar'); ?></p>
</td>
</tr>
<tr>
<th><?php _e('默认CSS类名', 'wpavatar'); ?></th>
<td>
<input type="text" name="wpavatar_shortcode_class" value="<?php echo esc_attr($shortcode_class); ?>" class="regular-text wpavatar-input">
<input type="text" name="wpavatar_shortcode_class" value="<?php echo esc_attr($shortcode_class); ?>" class="regular-text wpavatar-input" <?php echo $disabled_shortcode_class; ?>>
<p class="description"><?php _e('简码生成的头像默认CSS类', 'wpavatar'); ?></p>
</td>
</tr>
<tr>
<th><?php _e('默认头像形状', 'wpavatar'); ?></th>
<td>
<select name="wpavatar_shortcode_shape" class="wpavatar-select">
<select name="wpavatar_shortcode_shape" class="wpavatar-select" <?php echo $disabled_shortcode_shape; ?>>
<option value="square" <?php selected($shortcode_shape, 'square'); ?>><?php _e('方形', 'wpavatar'); ?></option>
<option value="rounded" <?php selected($shortcode_shape, 'rounded'); ?>><?php _e('圆角方形', 'wpavatar'); ?></option>
<option value="circle" <?php selected($shortcode_shape, 'circle'); ?>><?php _e('圆形', 'wpavatar'); ?></option>
@ -603,106 +762,23 @@ class Settings {
font-size: 12px;
line-height: 1.3;
}
.wpavatar-network-notice {
margin: 0 0 20px;
padding: 10px 12px;
background: #f0f6fc;
border-left: 4px solid #72aee6;
}
.wpavatar-network-notice .dashicons-lock {
color: #72aee6;
margin-right: 5px;
}
.wpavatar-network-notice em {
display: block;
margin-top: 5px;
color: #666;
}
</style>
<?php
}
}
class Network {
public static function init() {
if (is_network_admin()) {
add_action('network_admin_menu', [__CLASS__, 'add_network_menu']);
add_action('network_admin_edit_wpavatar_network', [__CLASS__, 'save_network_settings']);
}
}
public static function add_network_menu() {
add_submenu_page(
'settings.php',
__('WPAvatar网络设置', 'wpavatar'),
__('WPAvatar', 'wpavatar'),
'manage_network_options',
'wpavatar-network',
[__CLASS__, 'render_network_page']
);
}
public static function render_network_page() {
?>
<div class="wrap wpavatar-settings">
<h1><?php esc_html_e('WPAvatar网络设置', 'wpavatar'); ?></h1>
<div id="wpavatar-network-status" class="notice" style="display:none; margin-top: 10px;"></div>
<div class="wpavatar-card">
<h2><?php _e('网络范围设置', 'wpavatar'); ?></h2>
<p class="wpavatar-section-desc"><?php _e('配置多站点网络的WPAvatar设置。', 'wpavatar'); ?></p>
<form method="post" action="edit.php?action=wpavatar_network" id="wpavatar-network-form">
<?php wp_nonce_field('wpavatar_network_settings'); ?>
<table class="form-table">
<tr>
<th><?php _e('启用网络范围设置', 'wpavatar'); ?></th>
<td>
<label class="wpavatar-switch">
<input type="checkbox" name="wpavatar_network_enabled" value="1" <?php checked(get_site_option('wpavatar_network_enabled', 1)); ?>>
<span class="wpavatar-slider"></span>
<span class="wpavatar-switch-label"><?php _e('在所有站点启用WPAvatar', 'wpavatar'); ?></span>
</label>
<p class="description"><?php _e('启用后WPAvatar将在网络中的所有站点上生效', 'wpavatar'); ?></p>
</td>
</tr>
<tr>
<th><?php _e('默认CDN类型', 'wpavatar'); ?></th>
<td>
<select name="wpavatar_network_cdn_type" class="wpavatar-select">
<option value="cravatar_route" <?php selected(get_site_option('wpavatar_network_cdn_type', 'cravatar_route'), 'cravatar_route'); ?>><?php _e('Cravatar线路', 'wpavatar'); ?></option>
<option value="third_party" <?php selected(get_site_option('wpavatar_network_cdn_type', 'cravatar_route'), 'third_party'); ?>><?php _e('第三方镜像', 'wpavatar'); ?></option>
<option value="custom" <?php selected(get_site_option('wpavatar_network_cdn_type', 'cravatar_route'), 'custom'); ?>><?php _e('自定义CDN', 'wpavatar'); ?></option>
</select>
</td>
</tr>
<tr>
<th><?php _e('默认Cravatar线路', 'wpavatar'); ?></th>
<td>
<select name="wpavatar_network_cravatar_route" class="wpavatar-select">
<option value="cravatar.com" <?php selected(get_site_option('wpavatar_network_cravatar_route', 'cravatar.com'), 'cravatar.com'); ?>><?php _e('默认线路 (cravatar.com)', 'wpavatar'); ?></option>
<option value="cn.cravatar.com" <?php selected(get_site_option('wpavatar_network_cravatar_route', 'cravatar.com'), 'cn.cravatar.com'); ?>><?php _e('中国大陆 (cn.cravatar.com)', 'wpavatar'); ?></option>
<option value="hk.cravatar.com" <?php selected(get_site_option('wpavatar_network_cravatar_route', 'cravatar.com'), 'hk.cravatar.com'); ?>><?php _e('香港 (hk.cravatar.com)', 'wpavatar'); ?></option>
<option value="en.cravatar.com" <?php selected(get_site_option('wpavatar_network_cravatar_route', 'cravatar.com'), 'en.cravatar.com'); ?>><?php _e('国际 (en.cravatar.com)', 'wpavatar'); ?></option>
</select>
</td>
</tr>
<tr>
<th><?php _e('哈希方法', 'wpavatar'); ?></th>
<td>
<p class="description" style="color: #d63638;"><?php _e('注意使用Cravatar服务时哈希方法将强制使用MD5', 'wpavatar'); ?></p>
</td>
</tr>
</table>
<div class="wpavatar-submit-wrapper">
<button type="submit" class="button button-primary"><?php _e('保存设置', 'wpavatar'); ?></button>
</div>
</form>
</div>
</div>
<?php
}
public static function save_network_settings() {
check_admin_referer('wpavatar_network_settings');
update_site_option('wpavatar_network_enabled', isset($_POST['wpavatar_network_enabled']) ? 1 : 0);
if (isset($_POST['wpavatar_network_cdn_type'])) {
update_site_option('wpavatar_network_cdn_type', sanitize_text_field($_POST['wpavatar_network_cdn_type']));
}
if (isset($_POST['wpavatar_network_cravatar_route'])) {
update_site_option('wpavatar_network_cravatar_route', sanitize_text_field($_POST['wpavatar_network_cravatar_route']));
}
wp_redirect(add_query_arg(['page' => 'wpavatar-network', 'updated' => 'true'], network_admin_url('settings.php')));
exit;
}
}

106
includes/compatibility.php Normal file
View file

@ -0,0 +1,106 @@
<?php
/**
* WPAvatar 兼容性修复
*
* 用于处理与 WP-China-Yes 插件的兼容性问题
*/
namespace WPAvatar;
class Compatibility {
/**
* 初始化兼容性修复
*/
public static function init() {
// 在所有插件加载后、主题初始化前运行
add_action('after_setup_theme', [__CLASS__, 'handle_wp_china_yes_compatibility'], 5);
}
/**
* 处理与 WP-China-Yes 插件的兼容性
*/
public static function handle_wp_china_yes_compatibility() {
// 检查 WP-China-Yes 插件是否激活
if (self::is_wp_china_yes_active()) {
// 移除 WP-China-Yes 的头像替换过滤器
self::remove_wp_china_yes_filters();
// 重新初始化 WPAvatar 的 Cravatar 功能,使用更高的优先级
self::reinitialize_wpavatar_filters();
// 可选:添加管理界面通知
if (is_admin()) {
add_action('admin_notices', [__CLASS__, 'admin_compatibility_notice']);
}
}
}
/**
* 检查 WP-China-Yes 插件是否激活
*/
private static function is_wp_china_yes_active() {
return class_exists('WenPai\\ChinaYes\\Service\\Super') ||
defined('CHINA_YES_VERSION') ||
function_exists('WenPai\\ChinaYes\\get_settings');
}
/**
* 移除 WP-China-Yes 的头像替换过滤器
*/
private static function remove_wp_china_yes_filters() {
// 找到可能的 Super 类实例
global $wp_filter;
$filters_to_check = [
'get_avatar_url',
'um_user_avatar_url_filter',
'bp_gravatar_url',
'user_profile_picture_description',
'avatar_defaults'
];
foreach ($filters_to_check as $filter_name) {
if (isset($wp_filter[$filter_name])) {
foreach ($wp_filter[$filter_name]->callbacks as $priority => $callbacks) {
foreach ($callbacks as $callback_key => $callback_data) {
if (is_array($callback_data['function']) &&
is_object($callback_data['function'][0]) &&
get_class($callback_data['function'][0]) === 'WenPai\\ChinaYes\\Service\\Super') {
$method_name = $callback_data['function'][1];
remove_filter($filter_name, [$callback_data['function'][0], $method_name], $priority);
}
}
}
}
}
}
/**
* 重新初始化 WPAvatar Cravatar 过滤器,使用更高的优先级
*/
private static function reinitialize_wpavatar_filters() {
if (wpavatar_get_option('wpavatar_enable_cravatar', true)) {
// 使用高优先级再次添加过滤器
add_filter('um_user_avatar_url_filter', ['\WPAvatar\Cravatar', 'replace_avatar_url'], 9999);
add_filter('bp_gravatar_url', ['\WPAvatar\Cravatar', 'replace_avatar_url'], 9999);
add_filter('user_profile_picture_description', ['\WPAvatar\Cravatar', 'modify_profile_picture_description'], 9999);
// 确保 get_avatar_url 过滤器的优先级高于其他插件
remove_filter('get_avatar_url', ['\WPAvatar\Cravatar', 'get_avatar_url'], 999);
add_filter('get_avatar_url', ['\WPAvatar\Cravatar', 'get_avatar_url'], 9999, 2);
}
}
/**
* 管理界面兼容性通知
*/
public static function admin_compatibility_notice() {
$screen = get_current_screen();
if ($screen && $screen->id === 'settings_page_wpavatar-settings') {
echo '<div class="notice notice-info is-dismissible">';
echo '<p>检测到文派叶子WPCY.COM插件WPAvatar 生态组件兼容性补丁已生效,确保文派头像设置优先。</p>';
echo '</div>';
}
}
}

File diff suppressed because it is too large Load diff

1134
includes/multisite.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,24 @@
<?php
/**
* Plugin Name: WPAvatar
* Version: 1.6.3
* Version: 1.8.1
* Plugin URI: https://wpavatar.com/download
* Description: Replace Gravatar with Cravatar, a perfect replacement of Gravatar in China.
* Author: WPfanyi
* Author URI: https://wpfanyi.com/
* Text Domain: wpavatar
* Domain Path: /languages
* Network: true
*/
defined('ABSPATH') || exit;
define('WPAVATAR_VERSION', '1.6.3');
define('WPAVATAR_VERSION', '1.8.0');
define('WPAVATAR_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WPAVATAR_PLUGIN_URL', plugin_dir_url(__FILE__));
define('WPAVATAR_CACHE_DIR', WP_CONTENT_DIR . '/uploads/cravatar');
// Create necessary plugin directories if they don't exist
if (!file_exists(WPAVATAR_PLUGIN_DIR . 'assets')) {
wp_mkdir_p(WPAVATAR_PLUGIN_DIR . 'assets');
}
@ -55,19 +57,31 @@ if (!file_exists(WPAVATAR_PLUGIN_DIR . 'includes')) {
}
}
// Include core files
require_once WPAVATAR_PLUGIN_DIR . 'includes/core.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/admin.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/multisite.php';
// Register AJAX actions
add_action('wp_ajax_wpavatar_purge_cache', 'wpavatar_purge_cache_ajax');
function wpavatar_purge_cache_ajax() {
check_ajax_referer('wpavatar_admin_nonce', 'nonce');
// Check user capability
if (!current_user_can('manage_options')) {
wp_send_json_error(__('权限不足', 'wpavatar'));
return;
}
$dir = get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
// Get cache directory path
$dir = wpavatar_get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
// Add blog-specific directory if multisite
if (is_multisite()) {
$blog_id = get_current_blog_id();
$dir = trailingslashit($dir) . 'site-' . $blog_id . '/';
}
$dir = rtrim($dir, '/\\') . '/';
if (!file_exists($dir) || !is_dir($dir)) {
@ -91,6 +105,60 @@ function wpavatar_purge_cache_ajax() {
wp_send_json_success(sprintf(__('已清空 %d 个缓存文件', 'wpavatar'), $count));
}
add_action('wp_ajax_wpavatar_purge_all_cache', 'wpavatar_purge_all_cache_ajax');
function wpavatar_purge_all_cache_ajax() {
check_ajax_referer('wpavatar_admin_nonce', 'nonce');
// Check user capability for network admin
if (!current_user_can('manage_network_options')) {
wp_send_json_error(__('权限不足', 'wpavatar'));
return;
}
// Get base cache directory path
$base_dir = wpavatar_get_option('wpavatar_cache_path', WPAVATAR_CACHE_DIR);
$base_dir = rtrim($base_dir, '/\\') . '/';
if (!file_exists($base_dir) || !is_dir($base_dir)) {
wp_send_json_error(__('缓存目录不存在', 'wpavatar'));
return;
}
$count = 0;
// Get all site cache directories
$site_dirs = glob($base_dir . 'site-*', GLOB_ONLYDIR);
if ($site_dirs) {
foreach ($site_dirs as $site_dir) {
$files = glob($site_dir . '/*.jpg');
if ($files) {
foreach ($files as $file) {
if (file_exists($file)) {
if (@unlink($file)) {
$count++;
}
}
}
}
}
}
// Also check legacy non-site specific files
$legacy_files = glob($base_dir . '*.jpg');
if ($legacy_files) {
foreach ($legacy_files as $file) {
if (file_exists($file)) {
if (@unlink($file)) {
$count++;
}
}
}
}
wp_send_json_success(sprintf(__('已清空所有站点的 %d 个缓存文件', 'wpavatar'), $count));
}
add_action('wp_ajax_wpavatar_check_cache', 'wpavatar_check_cache_ajax');
function wpavatar_check_cache_ajax() {
check_ajax_referer('wpavatar_admin_nonce', 'nonce');
@ -104,9 +172,24 @@ function wpavatar_check_cache_ajax() {
wp_send_json_success($result);
}
add_action('wp_ajax_wpavatar_check_all_cache', 'wpavatar_check_all_cache_ajax');
function wpavatar_check_all_cache_ajax() {
check_ajax_referer('wpavatar_admin_nonce', 'nonce');
if (!current_user_can('manage_network_options')) {
wp_send_json_error(__('权限不足', 'wpavatar'));
return;
}
$result = \WPAvatar\Cache::check_all_cache_status();
wp_send_json_success($result);
}
add_action('plugins_loaded', function () {
// Load text domain for translations
load_plugin_textdomain('wpavatar', false, dirname(plugin_basename(__FILE__)) . '/languages');
// Create default avatar if it doesn't exist
$default_avatar = WPAVATAR_PLUGIN_DIR . 'assets/images/default-avatar.png';
if (!file_exists($default_avatar)) {
$placeholder = WPAVATAR_PLUGIN_DIR . 'assets/images/placeholder-avatar.png';
@ -127,6 +210,7 @@ add_action('plugins_loaded', function () {
}
}
// Fetch Cravatar logo if it doesn't exist
$cravatar_logo = WPAVATAR_PLUGIN_DIR . 'assets/images/cravatar-logo.png';
if (!file_exists($cravatar_logo) && function_exists('file_get_contents')) {
$logo_url = 'https://cn.cravatar.com/avatar/00000000000000000000000000000000?d=cravatar_logo';
@ -137,25 +221,49 @@ add_action('plugins_loaded', function () {
}
}
// Initialize multisite network support first
if (is_multisite()) {
\WPAvatar\Network::init();
}
// Initialize core components
\WPAvatar\Core::init();
\WPAvatar\Cravatar::init();
\WPAvatar\Cache::init();
\WPAvatar\Shortcode::init();
// Initialize admin settings (will be conditionally disabled in multisite if network managed)
if (is_admin()) {
\WPAvatar\Settings::init();
// Check if we should initialize settings in site admin
$should_init_settings = true;
if (is_multisite() && get_site_option('wpavatar_network_enforce', 0) && !is_network_admin()) {
$should_init_settings = false;
}
if ($should_init_settings) {
\WPAvatar\Settings::init();
}
}
// Filter text to replace Gravatar references with Cravatar
add_filter('gettext', 'wpavatar_replace_gravatar_text', 20, 3);
add_filter('ngettext', 'wpavatar_replace_gravatar_text_plural', 20, 4);
});
/**
* Replace Gravatar text with Cravatar in translations
*
* @param string $translated_text Translated text
* @param string $text Original text
* @param string $domain Text domain
* @return string Modified translated text
*/
function wpavatar_replace_gravatar_text($translated_text, $text, $domain) {
if (!get_option('wpavatar_enable_cravatar', 1)) {
// Get enable_cravatar setting
$enable_cravatar = wpavatar_get_option('wpavatar_enable_cravatar', 1);
if (!$enable_cravatar) {
return $translated_text;
}
@ -179,8 +287,20 @@ function wpavatar_replace_gravatar_text($translated_text, $text, $domain) {
return $translated_text;
}
/**
* Replace Gravatar text with Cravatar in plural translations
*
* @param string $translated_text Translated text
* @param string $single Singular text
* @param string $plural Plural text
* @param int $number Number for plural form
* @return string Modified translated text
*/
function wpavatar_replace_gravatar_text_plural($translated_text, $single, $plural, $number) {
if (!get_option('wpavatar_enable_cravatar', 1)) {
// Get enable_cravatar setting
$enable_cravatar = wpavatar_get_option('wpavatar_enable_cravatar', 1);
if (!$enable_cravatar) {
return $translated_text;
}
@ -202,7 +322,39 @@ function wpavatar_replace_gravatar_text_plural($translated_text, $single, $plura
return $translated_text;
}
/**
* Helper function to get the correct option based on multisite status
*
* @param string $option_name Option name
* @param mixed $default Default value
* @return mixed Option value
*/
function wpavatar_get_option($option_name, $default = false) {
if (is_multisite()) {
// Check if network settings are enabled
if (get_site_option('wpavatar_network_enabled', 1)) {
// Check if this option is controlled by network
$network_controlled_options = get_site_option('wpavatar_network_controlled_options', array());
// Convert to array if it's a string (for backward compatibility)
if (!is_array($network_controlled_options)) {
$network_controlled_options = explode(',', $network_controlled_options);
}
// If this option is controlled by network or network enforces all settings
if (in_array($option_name, $network_controlled_options) || get_site_option('wpavatar_network_enforce', 0)) {
return get_site_option($option_name, $default);
}
}
}
// Default to site option
return get_option($option_name, $default);
}
// Register activation hook
register_activation_hook(__FILE__, function() {
// Set default options for single site
add_option('wpavatar_enable_cravatar', 1);
add_option('wpavatar_cdn_type', 'cravatar_route');
add_option('wpavatar_cravatar_route', 'cravatar.com');
@ -223,13 +375,16 @@ register_activation_hook(__FILE__, function() {
add_option('wpavatar_shortcode_class', 'wpavatar');
add_option('wpavatar_shortcode_shape', 'square');
// Create cache directory
wp_mkdir_p(WPAVATAR_CACHE_DIR);
// Create index.php to prevent directory listing
$index_file = rtrim(WPAVATAR_CACHE_DIR, '/\\') . '/index.php';
if (!file_exists($index_file)) {
@file_put_contents($index_file, '<?php // Silence is golden.');
}
// Create .htaccess to configure cache
$htaccess_file = rtrim(WPAVATAR_CACHE_DIR, '/\\') . '/.htaccess';
if (!file_exists($htaccess_file)) {
$htaccess_content = "# Prevent directory listing\n";
@ -242,17 +397,127 @@ register_activation_hook(__FILE__, function() {
@file_put_contents($htaccess_file, $htaccess_content);
}
// Set default options for multisite
if (is_multisite()) {
// Network settings
add_site_option('wpavatar_network_enabled', 1);
add_site_option('wpavatar_network_cdn_type', 'cravatar_route');
add_site_option('wpavatar_network_cravatar_route', 'cravatar.com');
add_site_option('wpavatar_network_enforce', 0);
// Define default network controlled options
$default_controlled = array(
'wpavatar_enable_cravatar',
'wpavatar_cdn_type',
'wpavatar_cravatar_route',
'wpavatar_third_party_mirror',
'wpavatar_custom_cdn'
);
add_site_option('wpavatar_network_controlled_options', $default_controlled);
// Copy regular options to network options
foreach ([
'wpavatar_enable_cravatar',
'wpavatar_cdn_type',
'wpavatar_cravatar_route',
'wpavatar_third_party_mirror',
'wpavatar_custom_cdn',
'wpavatar_hash_method',
'wpavatar_timeout',
'wpavatar_enable_cache',
'wpavatar_cache_path',
'wpavatar_cache_expire',
'wpavatar_seo_alt',
'wpavatar_fallback_mode',
'wpavatar_fallback_avatar',
'wpavatar_shortcode_size',
'wpavatar_shortcode_class',
'wpavatar_shortcode_shape'
] as $option_name) {
add_site_option($option_name, get_option($option_name));
}
// If current site is not the main site, create site-specific cache dir
if (!is_main_site()) {
$blog_id = get_current_blog_id();
$cache_dir = trailingslashit(WPAVATAR_CACHE_DIR) . 'site-' . $blog_id;
wp_mkdir_p($cache_dir);
$index_file = $cache_dir . '/index.php';
if (!file_exists($index_file)) {
@file_put_contents($index_file, '<?php // Silence is golden.');
}
}
}
// Schedule daily cache purge
if (!wp_next_scheduled('wpavatar_purge_cache')) {
wp_schedule_event(time(), 'daily', 'wpavatar_purge_cache');
}
});
// Register deactivation hook
register_deactivation_hook(__FILE__, function() {
// Clear scheduled events
wp_clear_scheduled_hook('wpavatar_purge_cache');
});
// 确保 WPAvatar 插件已激活
add_action('plugins_loaded', function() {
if (class_exists('WPAvatar\\Cravatar')) {
// 添加兼容性过滤器,确保 WPAvatar 的优先级高于 WP-China-Yes
add_action('after_setup_theme', function() {
// 检查 WP-China-Yes 插件是否激活
if (class_exists('WenPai\\ChinaYes\\Service\\Super') || defined('CHINA_YES_VERSION')) {
// 移除 WP-China-Yes 的头像相关过滤器
global $wp_filter;
$filters_to_check = [
'get_avatar_url',
'um_user_avatar_url_filter',
'bp_gravatar_url',
'user_profile_picture_description',
'avatar_defaults'
];
foreach ($filters_to_check as $filter_name) {
if (isset($wp_filter[$filter_name])) {
foreach ($wp_filter[$filter_name]->callbacks as $priority => $callbacks) {
foreach ($callbacks as $callback_key => $callback_data) {
if (is_array($callback_data['function']) &&
is_object($callback_data['function'][0]) &&
get_class($callback_data['function'][0]) === 'WenPai\\ChinaYes\\Service\\Super') {
$method_name = $callback_data['function'][1];
remove_filter($filter_name, [$callback_data['function'][0], $method_name], $priority);
}
}
}
}
}
// 重新添加 WPAvatar 的过滤器,使用更高的优先级
if (wpavatar_get_option('wpavatar_enable_cravatar', true)) {
// 移除原有优先级的过滤器
remove_filter('get_avatar_url', ['WPAvatar\\Cravatar', 'get_avatar_url'], 999);
remove_filter('um_user_avatar_url_filter', ['WPAvatar\\Cravatar', 'replace_avatar_url'], 1);
remove_filter('bp_gravatar_url', ['WPAvatar\\Cravatar', 'replace_avatar_url'], 1);
// 使用更高优先级重新添加
add_filter('get_avatar_url', ['WPAvatar\\Cravatar', 'get_avatar_url'], 9999, 2);
add_filter('um_user_avatar_url_filter', ['WPAvatar\\Cravatar', 'replace_avatar_url'], 9999);
add_filter('bp_gravatar_url', ['WPAvatar\\Cravatar', 'replace_avatar_url'], 9999);
add_filter('user_profile_picture_description', ['WPAvatar\\Cravatar', 'modify_profile_picture_description'], 9999);
}
// 添加管理界面通知
add_action('admin_notices', function() {
$screen = get_current_screen();
if ($screen && $screen->id === 'settings_page_wpavatar-settings') {
echo '<div class="notice notice-info is-dismissible">';
echo '<p>检测到文派叶子WPCY.COM插件WPAvatar 生态组件兼容性补丁已生效,确保文派头像设置优先。</p>';
echo '</div>';
}
});
}
}, 5);
}
});