wpavatar/wpavatar.php
feibisi b7e0da8079 refactor: WPCS 代码规范修复 (7900+ 问题)
全面的 WordPress Coding Standards 检查和修复:

**已修复 (7900+ 个问题)**:
- 自动修复 7846 个格式问题(缩进、空格、换行等)
- 手动修复 Yoda Conditions(部分)
- 修复严格比较(== 改为 ===)
- 代码无语法错误,可正常运行

**剩余问题 (465 错误 + 82 警告)**:
- EscapeOutput (357个): 输出未转义,需人工审查
- YodaConditions (49个): 部分复杂条件待修复
- StrictInArray (42个): in_array() 缺少 true 参数
- 文档注释 (23个): 缺少 PHPDoc
- 其他 (76个): 文件命名、数据库查询等

**新增文件**:
- phpcs.xml: PHPCS 配置,排除合理警告
- wpavatar-phpcs-report.md: 完整问题报告和修复建议

详见 wpavatar-phpcs-report.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 12:25:48 +08:00

494 lines
15 KiB
PHP
Executable file

<?php
/**
* Plugin Name: WPAvatar
* Version: 1.9.5
* 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.9.5' );
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' );
}
if ( ! file_exists( WPAVATAR_PLUGIN_DIR . 'assets/css' ) ) {
wp_mkdir_p( WPAVATAR_PLUGIN_DIR . 'assets/css' );
$css_file = WPAVATAR_PLUGIN_DIR . 'admin.css';
if ( file_exists( $css_file ) ) {
copy( $css_file, WPAVATAR_PLUGIN_DIR . 'assets/css/admin.css' );
}
}
if ( ! file_exists( WPAVATAR_PLUGIN_DIR . 'assets/js' ) ) {
wp_mkdir_p( WPAVATAR_PLUGIN_DIR . 'assets/js' );
$js_file = WPAVATAR_PLUGIN_DIR . 'admin.js';
if ( file_exists( $js_file ) ) {
copy( $js_file, WPAVATAR_PLUGIN_DIR . 'assets/js/admin.js' );
}
}
if ( ! file_exists( WPAVATAR_PLUGIN_DIR . 'assets/images' ) ) {
wp_mkdir_p( WPAVATAR_PLUGIN_DIR . 'assets/images' );
}
// 检查必要的插件目录是否存在
if ( ! file_exists( WPAVATAR_PLUGIN_DIR . 'includes' ) ) {
wp_mkdir_p( WPAVATAR_PLUGIN_DIR . 'includes' );
if ( file_exists( WPAVATAR_PLUGIN_DIR . 'core.php' ) ) {
copy( WPAVATAR_PLUGIN_DIR . 'core.php', WPAVATAR_PLUGIN_DIR . 'includes/core.php' );
}
if ( file_exists( WPAVATAR_PLUGIN_DIR . 'admin.php' ) ) {
copy( WPAVATAR_PLUGIN_DIR . 'admin.php', WPAVATAR_PLUGIN_DIR . 'includes/admin.php' );
}
// 创建营销组件文件
if ( file_exists( WPAVATAR_PLUGIN_DIR . 'marketing.php' ) ) {
$marketing_content = file_get_contents( WPAVATAR_PLUGIN_DIR . 'marketing.php' );
file_put_contents( WPAVATAR_PLUGIN_DIR . 'includes/marketing.php', $marketing_content );
}
}
// 包含核心文件
require_once WPAVATAR_PLUGIN_DIR . 'includes/core.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/admin.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/multisite.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/marketing.php';
require_once WPAVATAR_PLUGIN_DIR . 'includes/wpcy-compatibility.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;
}
// 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 ) ) {
wp_send_json_error( __( '缓存目录不存在', 'wpavatar' ) );
return;
}
$files = glob( $dir . '*.jpg' );
$count = 0;
if ( $files ) {
foreach ( $files as $file ) {
if ( strpos( $file, $dir ) === 0 && file_exists( $file ) ) {
if ( @unlink( $file ) ) {
++$count;
}
}
}
}
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' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( __( '权限不足', 'wpavatar' ) );
return;
}
$result = \WPAvatar\Cache::check_cache_status();
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';
if ( file_exists( $placeholder ) ) {
copy( $placeholder, $default_avatar );
} else {
$avatar_image = imagecreatetruecolor( 96, 96 );
$bg_color = imagecolorallocate( $avatar_image, 238, 238, 238 );
$text_color = imagecolorallocate( $avatar_image, 68, 68, 68 );
imagefill( $avatar_image, 0, 0, $bg_color );
imagestring( $avatar_image, 5, 30, 40, 'Avatar', $text_color );
wp_mkdir_p( dirname( $default_avatar ) );
imagepng( $avatar_image, $default_avatar );
imagedestroy( $avatar_image );
}
}
// 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';
$logo_data = @file_get_contents( $logo_url );
if ( $logo_data ) {
wp_mkdir_p( dirname( $cravatar_logo ) );
@file_put_contents( $cravatar_logo, $logo_data );
}
}
// Initialize multisite network support first
if ( is_multisite() ) {
\WPAvatar\Network::init();
}
// Initialize compatibility layer
\WPAvatar\Compatibility::init();
// Initialize core components
\WPAvatar\Core::init();
\WPAvatar\Cravatar::init();
\WPAvatar\Cache::init();
\WPAvatar\Shortcode::init();
// Initialize Marketing component
\WPAvatar\Marketing::init();
// Initialize admin settings (will be conditionally disabled in multisite if network managed)
if ( is_admin() ) {
// 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 ) {
// Get enable_cravatar setting
$enable_cravatar = wpavatar_get_option( 'wpavatar_enable_cravatar', 1 );
if ( ! $enable_cravatar ) {
return $translated_text;
}
$current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
$screen_id = $current_screen ? $current_screen->id : '';
$is_discussion_page = ( 'options-discussion' === $screen_id ||
( isset( $_GET['page'] ) && 'discussion' === $_GET['page'] ) );
$is_comments_page = ( 'edit-comments' === $screen_id ||
'comment' === $screen_id );
$is_profile_page = ( 'profile' === $screen_id ||
'user-edit' === $screen_id );
if ( $is_discussion_page || $is_comments_page || $is_profile_page ) {
$translated_text = str_replace( 'Gravatar', 'Cravatar', $translated_text );
$translated_text = str_replace( 'gravatar', 'cravatar', $translated_text );
}
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 ) {
// Get enable_cravatar setting
$enable_cravatar = wpavatar_get_option( 'wpavatar_enable_cravatar', 1 );
if ( ! $enable_cravatar ) {
return $translated_text;
}
$current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
$screen_id = $current_screen ? $current_screen->id : '';
$is_relevant_page = ( 'options-discussion' === $screen_id ||
'edit-comments' === $screen_id ||
'comment' === $screen_id ||
'profile' === $screen_id ||
'user-edit' === $screen_id ||
( isset( $_GET['page'] ) && 'discussion' === $_GET['page'] ) );
if ( $is_relevant_page ) {
$translated_text = str_replace( 'Gravatar', 'Cravatar', $translated_text );
$translated_text = str_replace( 'gravatar', 'cravatar', $translated_text );
}
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' );
add_option( 'wpavatar_third_party_mirror', 'weavatar.com' );
add_option( 'wpavatar_custom_cdn', '' );
add_option( 'wpavatar_timeout', 5 );
add_option( 'wpavatar_enable_cache', 1 );
add_option( 'wpavatar_cache_path', WPAVATAR_CACHE_DIR );
add_option( 'wpavatar_cache_expire', 15 );
add_option( 'wpavatar_seo_alt', '%s的头像' );
add_option( 'wpavatar_fallback_mode', 1 );
add_option( 'wpavatar_fallback_avatar', 'default' );
add_option( 'wpavatar_shortcode_size', 96 );
add_option( 'wpavatar_shortcode_class', 'wpavatar' );
add_option( 'wpavatar_shortcode_shape', 'square' );
// 添加营销组件默认设置
add_option( 'wpavatar_commenters_count', 15 );
add_option( 'wpavatar_commenters_size', 45 );
add_option( 'wpavatar_users_count', 15 );
add_option( 'wpavatar_users_size', 40 );
// 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";
$htaccess_content .= "Options -Indexes\n";
$htaccess_content .= "# Cache images for one week\n";
$htaccess_content .= "<IfModule mod_expires.c>\n";
$htaccess_content .= "ExpiresActive On\n";
$htaccess_content .= "ExpiresByType image/jpeg \"access plus 1 week\"\n";
$htaccess_content .= "</IfModule>\n";
@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_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 ( array(
'wpavatar_enable_cravatar',
'wpavatar_cdn_type',
'wpavatar_cravatar_route',
'wpavatar_third_party_mirror',
'wpavatar_custom_cdn',
'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',
// 营销组件设置
'wpavatar_commenters_count',
'wpavatar_commenters_size',
'wpavatar_users_count',
'wpavatar_users_size',
) 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' );
}
);