wpbridge/includes/Commercial/Vendors/VendorManager.php
feibisi 39b30af242 feat(commercial): add vendor system for third-party GPL plugin sources
- Add VendorInterface, AbstractVendor, VendorManager for vendor abstraction
- Add WooCommerceVendor for WooCommerce API Manager integration
- Add BridgeManager with hybrid mode (official + vendor + custom sources)
- Add GPLValidator for GPL compliance checking
- Add LicenseProxy for license key management
- Add VendorAdmin with AJAX handlers for vendor CRUD operations
- Add vendors.php admin tab with stats, vendor list, custom plugins
- Add vendor management CSS styles and JS module
- Update main.php to include vendors tab

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-02-15 08:39:37 +08:00

374 lines
8.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 供应商管理器
*
* 管理所有第三方 GPL 插件供应商
*
* @package WPBridge
* @since 0.9.7
*/
declare(strict_types=1);
namespace WPBridge\Commercial\Vendors;
use WPBridge\Core\Settings;
use WPBridge\Core\Logger;
// 防止直接访问
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* VendorManager 类
*/
class VendorManager {
/**
* 设置实例
*
* @var Settings
*/
private Settings $settings;
/**
* 已注册的供应商
*
* @var VendorInterface[]
*/
private array $vendors = [];
/**
* 单例实例
*
* @var VendorManager|null
*/
private static ?VendorManager $instance = null;
/**
* 获取单例实例
*
* @param Settings|null $settings 设置实例
* @return VendorManager
*/
public static function get_instance( ?Settings $settings = null ): VendorManager {
if ( self::$instance === null ) {
self::$instance = new self( $settings ?? new Settings() );
}
return self::$instance;
}
/**
* 构造函数
*
* @param Settings $settings 设置实例
*/
public function __construct( Settings $settings ) {
$this->settings = $settings;
$this->load_vendors();
}
/**
* 加载已配置的供应商
*/
private function load_vendors(): void {
$vendor_configs = $this->settings->get( 'vendors', [] );
foreach ( $vendor_configs as $vendor_id => $config ) {
if ( empty( $config['enabled'] ) ) {
continue;
}
$vendor = $this->create_vendor( $vendor_id, $config );
if ( $vendor !== null ) {
$this->vendors[ $vendor_id ] = $vendor;
}
}
// 允许通过 hook 注册额外供应商
do_action( 'wpbridge_register_vendors', $this );
}
/**
* 创建供应商实例
*
* @param string $vendor_id 供应商 ID
* @param array $config 配置
* @return VendorInterface|null
*/
private function create_vendor( string $vendor_id, array $config ): ?VendorInterface {
$type = $config['type'] ?? 'woocommerce';
$name = $config['name'] ?? $vendor_id;
switch ( $type ) {
case 'woocommerce':
case 'wc_am':
return new WooCommerceVendor( $vendor_id, $name, $config );
// 未来可以添加更多类型
// case 'edd':
// return new EDDVendor($vendor_id, $name, $config);
default:
Logger::warning( 'Unknown vendor type', [
'vendor_id' => $vendor_id,
'type' => $type,
] );
return null;
}
}
/**
* 注册供应商
*
* @param VendorInterface $vendor 供应商实例
*/
public function register( VendorInterface $vendor ): void {
$this->vendors[ $vendor->get_id() ] = $vendor;
}
/**
* 获取供应商
*
* @param string $vendor_id 供应商 ID
* @return VendorInterface|null
*/
public function get_vendor( string $vendor_id ): ?VendorInterface {
return $this->vendors[ $vendor_id ] ?? null;
}
/**
* 获取所有供应商
*
* @param bool $only_available 只返回可用的供应商
* @return VendorInterface[]
*/
public function get_vendors( bool $only_available = false ): array {
if ( ! $only_available ) {
return $this->vendors;
}
return array_filter(
$this->vendors,
fn( VendorInterface $vendor ) => $vendor->is_available()
);
}
/**
* 获取所有供应商信息
*
* @return array
*/
public function get_vendors_info(): array {
$info = [];
foreach ( $this->vendors as $vendor ) {
$info[ $vendor->get_id() ] = array_merge(
$vendor->get_info(),
[ 'available' => $vendor->is_available() ]
);
}
return $info;
}
/**
* 从所有供应商搜索插件
*
* @param string $keyword 关键词
* @param string $vendor_id 指定供应商(可选)
* @return array
*/
public function search_plugins( string $keyword, string $vendor_id = '' ): array {
$results = [];
$vendors = ! empty( $vendor_id )
? [ $this->get_vendor( $vendor_id ) ]
: $this->get_vendors( true );
foreach ( $vendors as $vendor ) {
if ( $vendor === null ) {
continue;
}
try {
$vendor_results = $vendor->search_plugins( $keyword );
foreach ( $vendor_results as $plugin ) {
$plugin['vendor_id'] = $vendor->get_id();
$plugin['vendor_name'] = $vendor->get_info()['name'] ?? '';
$results[] = $plugin;
}
} catch ( \Exception $e ) {
Logger::error( 'Vendor search failed', [
'vendor' => $vendor->get_id(),
'error' => $e->getMessage(),
] );
}
}
return $results;
}
/**
* 从所有供应商获取插件
*
* @param string $slug 插件 slug
* @return array|null 包含插件信息和供应商信息
*/
public function get_plugin( string $slug ): ?array {
foreach ( $this->get_vendors( true ) as $vendor ) {
$plugin = $vendor->get_plugin( $slug );
if ( $plugin !== null ) {
$plugin['vendor_id'] = $vendor->get_id();
$plugin['vendor_name'] = $vendor->get_info()['name'] ?? '';
return $plugin;
}
}
return null;
}
/**
* 检查插件更新(从所有供应商)
*
* @param string $slug 插件 slug
* @param string $current_version 当前版本
* @return array|null
*/
public function check_update( string $slug, string $current_version ): ?array {
foreach ( $this->get_vendors( true ) as $vendor ) {
$update = $vendor->check_update( $slug, $current_version );
if ( $update !== null ) {
$update['vendor_id'] = $vendor->get_id();
$update['vendor_name'] = $vendor->get_info()['name'] ?? '';
return $update;
}
}
return null;
}
/**
* 获取下载链接
*
* @param string $slug 插件 slug
* @param string $vendor_id 供应商 ID可选自动查找
* @param string $version 版本号(可选)
* @return string|null
*/
public function get_download_url( string $slug, string $vendor_id = '', string $version = '' ): ?string {
if ( ! empty( $vendor_id ) ) {
$vendor = $this->get_vendor( $vendor_id );
if ( $vendor !== null ) {
return $vendor->get_download_url( $slug, $version );
}
}
// 自动查找
foreach ( $this->get_vendors( true ) as $vendor ) {
$plugin = $vendor->get_plugin( $slug );
if ( $plugin !== null ) {
return $vendor->get_download_url( $slug, $version );
}
}
return null;
}
/**
* 添加供应商配置
*
* @param string $vendor_id 供应商 ID
* @param array $config 配置
* @return bool
*/
public function add_vendor_config( string $vendor_id, array $config ): bool {
$vendors = $this->settings->get( 'vendors', [] );
$vendors[ $vendor_id ] = $config;
$result = $this->settings->set( 'vendors', $vendors );
if ( $result ) {
// 重新加载
$vendor = $this->create_vendor( $vendor_id, $config );
if ( $vendor !== null ) {
$this->vendors[ $vendor_id ] = $vendor;
}
}
return $result;
}
/**
* 移除供应商配置
*
* @param string $vendor_id 供应商 ID
* @return bool
*/
public function remove_vendor_config( string $vendor_id ): bool {
$vendors = $this->settings->get( 'vendors', [] );
if ( ! isset( $vendors[ $vendor_id ] ) ) {
return false;
}
unset( $vendors[ $vendor_id ] );
unset( $this->vendors[ $vendor_id ] );
return $this->settings->set( 'vendors', $vendors );
}
/**
* 测试供应商连接
*
* @param string $vendor_id 供应商 ID
* @return array
*/
public function test_vendor( string $vendor_id ): array {
$vendor = $this->get_vendor( $vendor_id );
if ( $vendor === null ) {
return [
'success' => false,
'message' => __( '供应商不存在', 'wpbridge' ),
];
}
$available = $vendor->is_available();
if ( ! $available ) {
return [
'success' => false,
'message' => __( '供应商连接失败,请检查配置', 'wpbridge' ),
];
}
// 尝试获取插件列表
$plugins = $vendor->get_plugins( 1, 10 );
return [
'success' => true,
'message' => __( '连接成功', 'wpbridge' ),
'plugin_count' => $plugins['total'] ?? count( $plugins['plugins'] ),
];
}
/**
* 获取统计信息
*
* @return array
*/
public function get_stats(): array {
$total_vendors = count( $this->vendors );
$active_vendors = count( $this->get_vendors( true ) );
$total_plugins = 0;
foreach ( $this->get_vendors( true ) as $vendor ) {
$plugins = $vendor->get_plugins( 1, 1 );
$total_plugins += $plugins['total'] ?? 0;
}
return [
'total_vendors' => $total_vendors,
'active_vendors' => $active_vendors,
'total_plugins' => $total_plugins,
];
}
}