- phpcbf 自动修复 3893 处格式问题 - 添加 phpcs.xml 排除不适用的规则 - 安全相关规则降级为 warning 保持可见 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
151 lines
4.3 KiB
PHP
151 lines
4.3 KiB
PHP
<?php
|
||
/**
|
||
* WenPaiEPay 自动更新器
|
||
*
|
||
* 通过文派云桥 (WenPai Bridge) 检查插件更新。
|
||
* 利用 WordPress 5.8+ 的 Update URI 机制,注册
|
||
* update_plugins_updates.wenpai.net filter。
|
||
*
|
||
* @package WenPaiEPay
|
||
*/
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
class WenPaiEPay_Updater {
|
||
|
||
/** @var string 云桥 API 地址 */
|
||
private $api_url = 'https://updates.wenpai.net/api/v1';
|
||
|
||
/** @var string 插件主文件 basename */
|
||
private $plugin_file;
|
||
|
||
/** @var string 插件 slug */
|
||
private $slug;
|
||
|
||
/** @var string 当前版本 */
|
||
private $version;
|
||
|
||
/**
|
||
* @param string $plugin_file 插件主文件路径(plugin_basename 格式)
|
||
* @param string $version 当前插件版本
|
||
*/
|
||
public function __construct( string $plugin_file, string $version ) {
|
||
$this->plugin_file = $plugin_file;
|
||
$this->slug = dirname( $plugin_file );
|
||
$this->version = $version;
|
||
|
||
$this->register_hooks();
|
||
}
|
||
|
||
private function register_hooks(): void {
|
||
add_filter( 'update_plugins_updates.wenpai.net', array( $this, 'check_update' ), 10, 4 );
|
||
add_filter( 'plugins_api', array( $this, 'plugin_info' ), 20, 3 );
|
||
}
|
||
|
||
public function check_update( $update, array $plugin_data, string $plugin_file, array $locales ) {
|
||
if ( $plugin_file !== $this->plugin_file ) {
|
||
return $update;
|
||
}
|
||
|
||
$response = $this->api_request(
|
||
'update-check',
|
||
array(
|
||
'plugins' => array(
|
||
$this->plugin_file => array(
|
||
'Version' => $this->version,
|
||
),
|
||
),
|
||
)
|
||
);
|
||
|
||
if ( is_wp_error( $response ) || empty( $response['plugins'][ $this->plugin_file ] ) ) {
|
||
return $update;
|
||
}
|
||
|
||
$data = $response['plugins'][ $this->plugin_file ];
|
||
|
||
return (object) array(
|
||
'slug' => $data['slug'] ?? $this->slug,
|
||
'plugin' => $this->plugin_file,
|
||
'version' => $data['version'] ?? '',
|
||
'new_version' => $data['version'] ?? '',
|
||
'url' => $data['url'] ?? '',
|
||
'package' => $data['package'] ?? '',
|
||
'icons' => $data['icons'] ?? array(),
|
||
'banners' => $data['banners'] ?? array(),
|
||
'requires' => $data['requires'] ?? '',
|
||
'tested' => $data['tested'] ?? '',
|
||
'requires_php' => $data['requires_php'] ?? '',
|
||
);
|
||
}
|
||
|
||
public function plugin_info( $result, string $action, object $args ) {
|
||
if ( $action !== 'plugin_information' ) {
|
||
return $result;
|
||
}
|
||
|
||
if ( ! isset( $args->slug ) || $args->slug !== $this->slug ) {
|
||
return $result;
|
||
}
|
||
|
||
$response = $this->api_request( 'plugins/' . $this->slug . '/info' );
|
||
|
||
if ( is_wp_error( $response ) ) {
|
||
return $result;
|
||
}
|
||
|
||
$info = new stdClass();
|
||
$info->name = $response['name'] ?? '';
|
||
$info->slug = $response['slug'] ?? $this->slug;
|
||
$info->version = $response['version'] ?? '';
|
||
$info->author = $response['author'] ?? '';
|
||
$info->homepage = $response['homepage'] ?? '';
|
||
$info->download_link = $response['download_link'] ?? '';
|
||
$info->requires = $response['requires'] ?? '';
|
||
$info->tested = $response['tested'] ?? '';
|
||
$info->requires_php = $response['requires_php'] ?? '';
|
||
$info->last_updated = $response['last_updated'] ?? '';
|
||
$info->icons = $response['icons'] ?? array();
|
||
$info->banners = $response['banners'] ?? array();
|
||
$info->sections = $response['sections'] ?? array();
|
||
|
||
return $info;
|
||
}
|
||
|
||
private function api_request( string $endpoint, ?array $body = null ) {
|
||
$url = rtrim( $this->api_url, '/' ) . '/' . ltrim( $endpoint, '/' );
|
||
|
||
$args = array(
|
||
'timeout' => 15,
|
||
'headers' => array(
|
||
'Accept' => 'application/json',
|
||
),
|
||
);
|
||
|
||
if ( $body !== null ) {
|
||
$args['headers']['Content-Type'] = 'application/json';
|
||
$args['body'] = wp_json_encode( $body );
|
||
$response = wp_remote_post( $url, $args );
|
||
} else {
|
||
$response = wp_remote_get( $url, $args );
|
||
}
|
||
|
||
if ( is_wp_error( $response ) ) {
|
||
return $response;
|
||
}
|
||
|
||
$code = wp_remote_retrieve_response_code( $response );
|
||
if ( $code !== 200 ) {
|
||
return new WP_Error( 'wenpai_bridge_error', sprintf( 'WenPai Bridge API returned %d', $code ) );
|
||
}
|
||
|
||
$data = json_decode( wp_remote_retrieve_body( $response ), true );
|
||
if ( ! is_array( $data ) ) {
|
||
return new WP_Error( 'wenpai_bridge_parse_error', 'Invalid JSON response from WenPai Bridge' );
|
||
}
|
||
|
||
return $data;
|
||
}
|
||
}
|