git-it-write/includes/cli.php
Developer 7728f489bd feat: 本地文件模式 + 多仓库自动发现 (v3.0)
替换 Forgejo API 数据源为本地文件系统读取,支持 30+ 仓库自动发现。
新增 WP-Cron 定时同步、WP-CLI 命令、多站点支持、SEO 字段写入。
base_directory 为空时保留原 API 模式向后兼容。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-10 00:37:12 +08:00

176 lines
5.4 KiB
PHP

<?php
if( ! defined( 'ABSPATH' ) ) exit;
class GIW_CLI_Command extends WP_CLI_Command{
/**
* Sync repositories from local file system to WordPress.
*
* ## OPTIONS
*
* [--repo=<name>]
* : Sync only this repository (directory name).
*
* [--force]
* : Force full sync, ignoring SHA comparison.
*
* [--blog-id=<id>]
* : Target blog ID for multisite.
*
* ## EXAMPLES
*
* wp giw sync
* wp giw sync --repo=woocommerce
* wp giw sync --force
* wp giw sync --repo=woocommerce --blog-id=3
*
* @subcommand sync
*/
public function sync( $args, $assoc_args ){
$force = isset( $assoc_args['force'] );
$repo = isset( $assoc_args['repo'] ) ? $assoc_args['repo'] : '';
$blog_id = isset( $assoc_args['blog-id'] ) ? (int) $assoc_args['blog-id'] : 0;
$settings = Git_It_Write::general_settings();
$base_dir = $settings['base_directory'];
if( empty( $base_dir ) ){
WP_CLI::error( 'base_directory is not configured. Set it in Settings > Git it Write.' );
return;
}
// Switch blog if specified.
if( $blog_id > 0 && is_multisite() ){
switch_to_blog( $blog_id );
WP_CLI::log( 'Switched to blog ID: ' . $blog_id );
}elseif( is_multisite() && !empty( $settings['target_blog_id'] ) ){
switch_to_blog( (int) $settings['target_blog_id'] );
WP_CLI::log( 'Switched to configured blog ID: ' . $settings['target_blog_id'] );
}
// Load media functions.
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
if( $force && !defined( 'GIW_PUBLISH_FORCE' ) ){
define( 'GIW_PUBLISH_FORCE', true );
}
if( !empty( $repo ) ){
// Sync single repo.
$repo_data = GIW_Discovery::find( $base_dir, $repo );
if( !$repo_data ){
WP_CLI::error( "Repository '$repo' not found in $base_dir" );
return;
}
WP_CLI::log( "Syncing repository: $repo" . ( $force ? ' (force)' : '' ) );
$result = GIW_Sync::sync_repo( $repo_data, $force );
self::print_result( $repo, $result );
}else{
// Sync all repos.
$repos = GIW_Discovery::discover( $base_dir );
if( empty( $repos ) ){
WP_CLI::warning( 'No repositories discovered in ' . $base_dir );
return;
}
WP_CLI::log( 'Discovered ' . count( $repos ) . ' repositories' . ( $force ? ' (force sync)' : '' ) );
foreach( $repos as $repo_data ){
WP_CLI::log( '' );
WP_CLI::log( "--- Syncing: {$repo_data['name']} ---" );
$result = GIW_Sync::sync_repo( $repo_data, $force );
self::print_result( $repo_data['name'], $result );
}
}
if( is_multisite() ){
restore_current_blog();
}
WP_CLI::success( 'Sync complete.' );
}
/**
* List discovered repositories and their sync status.
*
* ## EXAMPLES
*
* wp giw list
*
* @subcommand list
*/
public function list_repos( $args, $assoc_args ){
$settings = Git_It_Write::general_settings();
$base_dir = $settings['base_directory'];
if( empty( $base_dir ) ){
WP_CLI::error( 'base_directory is not configured.' );
return;
}
$repos = GIW_Discovery::discover( $base_dir );
$timestamps = get_option( 'giw_sync_timestamps', array() );
if( empty( $repos ) ){
WP_CLI::warning( 'No repositories found in ' . $base_dir );
return;
}
$table = array();
foreach( $repos as $repo ){
$name = $repo['name'];
$config = $repo['config'];
$last_ts = isset( $timestamps[ $name ] ) ? $timestamps[ $name ] : 0;
$table[] = array(
'Name' => $name,
'Post Type' => $config['post_type'],
'Folder' => empty( $config['folder'] ) ? '/' : $config['folder'],
'Category' => empty( $config['category'] ) ? '-' : $config['category'],
'Has Config' => is_readable( $repo['path'] . '/.giw.yml' ) ? 'yes' : 'no',
'Last Synced' => $last_ts > 0 ? date( 'Y-m-d H:i:s', $last_ts ) : 'never',
);
}
WP_CLI\Utils\format_items( 'table', $table, array_keys( $table[0] ) );
}
/**
* Print sync result for a single repo.
*/
private static function print_result( $name, $result ){
if( !$result || !is_array( $result ) ){
WP_CLI::warning( "$name: no result returned" );
return;
}
$new = count( $result['stats']['posts']['new'] );
$updated = count( $result['stats']['posts']['updated'] );
$failed = $result['stats']['posts']['failed'];
$images = count( $result['stats']['images']['uploaded'] );
WP_CLI::log( "$name: {$result['message']} (new: $new, updated: $updated, failed: $failed, images: $images)" );
}
}
WP_CLI::add_command( 'giw', 'GIW_CLI_Command' );
?>