wenpai.org/wp-content/plugins/plat-wporg-helphub-import/Service/Article.php
2024-07-04 19:26:34 +08:00

228 lines
6.7 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
namespace Platform\Translate\WPOrgHelpHubImport\Service;
use DateTime;
use DateTimeZone;
use DiDom\Document;
use Exception;
use Platform\Logger\Logger;
use WP_CLI;
use WP_Error;
use WP_Http;
use function Platform\Translate\WPOrgHelpHubImport\compress_html;
use function Platform\Translate\WPOrgHelpHubImport\prepare_w_org_string;
defined( 'ABSPATH' ) || exit;
class Article {
private array $cat_map = array();
public function __construct() {
//add_action( 'init', array( $this, 'job' ) );
}
public function job() {
while ( ob_get_level() ) {
ob_end_flush();
}
/**
* 初始化 w.org 上分类 ID 与本地的分类 ID 的对照关系
*/
$this->cat_map = $this->update_category();
$total_pages = 100;
$all_data = [];
for ( $page = 1; $page <= $total_pages; $page ++ ) {
$url = "https://wpmirror.com/documentation/wp-json/wp/v2/articles?per_page=100&page=$page";
$data = $this->remote_get( $url );
if ( is_wp_error( $data ) ) {
Logger::error( Logger::DOCUMENT, $data->get_error_message(), array(
'url' => $url,
) );
return;
}
foreach ( $data as $item ) {
$cat_ids = array_map( function ( $item ) {
return $this->cat_map[ $item ];
}, $item->category );
$r = $this->insert( $item->id, $item->modified_gmt, $item->slug, $item->title?->rendered, $item->menu_order, $item->content?->rendered, $item->excerpt?->rendered, 0, $cat_ids );
if ( is_wp_error( $r ) ) {
Logger::error( Logger::DOCUMENT, '创建文章失败:' . $r->get_error_message() );
}
// 导入后顺便把内容复制一份到 meta方便之后替换翻译用
//update_post_meta( $r, 'original_content', $item->content?->rendered );
// 文档导入后为翻译平台安排一个计划任务来将文档同步过去
switch_to_blog( SITE_ID_TRANSLATE );
wp_schedule_single_event( time() + 1, 'plat_gp_helphub_import', array(
'name' => $item->title?->rendered,
'slug' => $item->slug,
'content' => $item->content?->rendered,
) );
restore_current_blog();
WP_CLI::line( '导入文章:' . $item->title?->rendered );
}
$all_data = array_merge( $all_data, $data );
}
// 删除 ID 不在列表中的文章
$exist_ids = array_map( function ( $item ) {
return $item->id;
}, $all_data );
$exist_ids = implode( ',', $exist_ids );
global $wpdb;
$unexist_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='post' AND ID NOT IN ($exist_ids)" );
foreach ( $unexist_ids as $id ) {
$slug = get_post_field( 'post_name', $id );
WP_CLI::line( '删除不存在的文章:' . $slug );
wp_delete_post( $id, true );
switch_to_blog( SITE_ID_TRANSLATE );
wp_schedule_single_event( time() + 1, 'plat_gp_helphub_delete', array(
'slug' => $slug,
) );
restore_current_blog();
}
}
private function update_category(): array {
$url = "https://wpmirror.com/documentation/wp-json/wp/v2/category?per_page=100";
$data = $this->remote_get( $url );
if ( is_wp_error( $data ) ) {
Logger::error( Logger::DOCUMENT, $data->get_error_message(), array(
'url' => $url,
) );
return array();
}
$cat_map = array();
foreach ( $data as $item ) {
if ( ! function_exists( 'wp_insert_category' ) ) {
require ABSPATH . '/wp-admin/includes/taxonomy.php';
}
// 替换关键字
$item->name = prepare_w_org_string( $item->name );
$item->slug = str_replace( 'wordpress', 'wenpai', $item->slug );
if ( ! get_category_by_slug( $item->slug ) ) {
$args = array(
'taxonomy' => 'category',
'cat_name' => $item->name,
'category_nicename' => $item->slug,
);
wp_insert_category( $args );
}
$r = get_category_by_slug( $item->slug );
$cat_map[ $item->id ] = $r?->term_id;
}
return $cat_map;
}
private function remote_get( string $url ): array|WP_Error {
$args = array(
'timeout' => 600,
);
$r = wp_remote_get( $url, $args );
if ( is_wp_error( $r ) ) {
return new WP_Error( 'docs_import_error', '从 w.org 抓取文档失败:' . $r->get_error_message() );
}
$status_code = wp_remote_retrieve_response_code( $r );
if ( WP_Http::OK !== $status_code ) {
return new WP_Error( 'docs_import_error', '从 w.org 抓取文档失败,接口返回状态码:' . $status_code );
}
$body = wp_remote_retrieve_body( $r );
return json_decode( $body );
}
private function insert( int $id, string $modified_gmt, string $post_name, string $title, int $order, string $content = '', string $excerpt = '', int $post_parent = 0, array $cat_ids = array() ): int|WP_Error {
$is_exist = get_post( $id );
if ( ! $is_exist ) {
$this->insert_empty_post( $id );
}
// 判断时间是否相等,相等就不用更新了
/*if ( $is_exist && $is_exist->post_date_gmt === date( 'Y-m-d H:i:s', strtotime( $modified_gmt ) ) ) {
return $is_exist->ID;
}*/
// 使用平台的全局 DOM 处理库先预处理一遍,因为这个鸟库会转义一些 HTML 实体,如果不预处理的话,将来经过这个库处理的字符串就和原字符串匹配不上了
$dom = new Document();
$dom->loadHtml( $content, LIBXML_HTML_NOIMPLIED | LIBXML_BIGLINES | LIBXML_HTML_NODEFDTD | LIBXML_PARSEHUGE | LIBXML_SCHEMA_CREATE );
$content = $dom->toElement()->html();
// 去除 DOM 处理库自动添加的 Body 标签
/*if ( preg_match( '|^<body>([\s\S]*?)</body>$|', $content, $matches ) ) {
if ( ! empty( $matches[1] ) ) {
$content = $matches[1];
}
}*/
//$content = compress_html( $content );
$content = prepare_w_org_string( $content );
$title = prepare_w_org_string( $title );
$post_name = prepare_w_org_string( $post_name );
// 时间处理成中国
try {
$modified = new DateTime( $modified_gmt, new DateTimeZone( 'UTC' ) );
$modified->setTimezone( new DateTimeZone( 'Asia/Shanghai' ) );
} catch ( Exception $e ) {
return new WP_Error( 'docs_import_error', '时间格式化失败:' . $e->getMessage() );
}
$args = array(
'ID' => $id,
'post_author' => BOT_USER_ID,
'post_content' => $content,
'post_title' => $title,
'post_name' => $post_name,
'post_excerpt' => $excerpt,
'post_status' => 'publish',
'post_type' => 'post',
'post_parent' => $post_parent,
'menu_order' => $order,
'post_category' => $cat_ids,
'post_date' => $modified->format( 'Y-m-d H:i:s' ),
'post_date_gmt' => date( 'Y-m-d H:i:s', strtotime( $modified_gmt ) ),
);
return wp_insert_post( $args );
}
/**
* 创建 ID 为给定值的空文章
*
* @param int $id
*
* @return bool
*/
private function insert_empty_post( int $id ): bool {
global $wpdb;
$wpdb->insert( $wpdb->posts, array(
'ID' => $id,
)
);
return true;
}
}