mirror of
https://ghfast.top/https://github.com/bradvin/wp-git-sync.git
synced 2026-05-10 14:12:29 +08:00
182 lines
4.6 KiB
PHP
182 lines
4.6 KiB
PHP
<?php
|
|
/**
|
|
* Diff/check helpers.
|
|
*
|
|
* @package WPGitSync
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Helpers for comparing a local post to its remote representation in GitHub.
|
|
*/
|
|
final class WPGS_Diff {
|
|
/**
|
|
* Compute the deterministic repo-relative paths for a post.
|
|
*
|
|
* @param WP_Post $post Post.
|
|
* @return array{content_path:string,post_path:string,meta_path:string}
|
|
*/
|
|
public static function paths_for_post( WP_Post $post ): array {
|
|
return [
|
|
'content_path' => WPGS_Paths::content_relpath( (string) $post->post_type, (int) $post->ID ),
|
|
'post_path' => WPGS_Paths::post_data_relpath( (string) $post->post_type, (int) $post->ID ),
|
|
'meta_path' => WPGS_Paths::meta_relpath( (string) $post->post_type, (int) $post->ID ),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Build the local export content, post-data JSON, and meta JSON for a post.
|
|
*
|
|
* @param WP_Post $post Post.
|
|
* @return array{content:string,post_json:string,meta_json:string,post_data:array<string,mixed>,meta:array<string,mixed>}
|
|
*/
|
|
public static function build_local_payload( WP_Post $post ): array {
|
|
$content = (string) $post->post_content;
|
|
$post_data = get_post( $post->ID, ARRAY_A );
|
|
if ( ! is_array( $post_data ) ) {
|
|
$post_data = [];
|
|
}
|
|
unset( $post_data['post_content'] );
|
|
|
|
$all_meta = get_post_meta( $post->ID );
|
|
if ( ! is_array( $all_meta ) ) {
|
|
$all_meta = [];
|
|
}
|
|
|
|
// Avoid exporting our own internal meta.
|
|
foreach ( WPGS_Sync_Meta::internal_keys() as $k ) {
|
|
unset( $all_meta[ $k ] );
|
|
}
|
|
|
|
$meta_blacklist = self::meta_blacklist();
|
|
foreach ( array_keys( $all_meta ) as $meta_key ) {
|
|
$meta_key = (string) $meta_key;
|
|
if ( self::meta_key_matches_blacklist( $meta_key, $meta_blacklist ) ) {
|
|
unset( $all_meta[ $meta_key ] );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter exported post meta.
|
|
*
|
|
* @param array<string,mixed> $all_meta All meta.
|
|
* @param int $post_id Post ID.
|
|
*/
|
|
$all_meta = apply_filters( 'wpgs_export_postmeta', $all_meta, (int) $post->ID );
|
|
|
|
$post_json = self::stable_json( $post_data ) . "\n";
|
|
$meta_json = self::stable_json( $all_meta ) . "\n";
|
|
|
|
return [
|
|
'content' => $content,
|
|
'post_json' => $post_json,
|
|
'meta_json' => $meta_json,
|
|
'post_data' => $post_data,
|
|
'meta' => $all_meta,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Post-meta keys excluded from export by default.
|
|
*
|
|
* @return string[]
|
|
*/
|
|
public static function meta_blacklist(): array {
|
|
$blacklist = array_merge(
|
|
[ '_edit_lock' ],
|
|
WPGS_Settings::excluded_post_meta_keys()
|
|
);
|
|
|
|
/**
|
|
* Filter post-meta keys excluded from export.
|
|
*
|
|
* @param string[] $blacklist Meta keys to exclude.
|
|
*/
|
|
$blacklist = apply_filters( 'wpgs_export_postmeta_blacklist', $blacklist );
|
|
if ( ! is_array( $blacklist ) ) {
|
|
return [ '_edit_lock' ];
|
|
}
|
|
|
|
return array_values( array_unique( array_map( 'strval', $blacklist ) ) );
|
|
}
|
|
|
|
/**
|
|
* Determine whether a meta key matches any blacklist rule.
|
|
*
|
|
* Supports exact-key rules and simple wildcard patterns using `*`.
|
|
* Example: `_elementor*` matches `_elementor_data`.
|
|
*
|
|
* @param string $meta_key Meta key being evaluated.
|
|
* @param string[] $blacklist Blacklist rules.
|
|
* @return bool
|
|
*/
|
|
public static function meta_key_matches_blacklist( string $meta_key, array $blacklist ): bool {
|
|
$meta_key = (string) $meta_key;
|
|
if ( '' === $meta_key ) {
|
|
return false;
|
|
}
|
|
|
|
foreach ( $blacklist as $rule ) {
|
|
$rule = trim( (string) $rule );
|
|
if ( '' === $rule ) {
|
|
continue;
|
|
}
|
|
if ( false === strpos( $rule, '*' ) ) {
|
|
if ( $meta_key === $rule ) {
|
|
return true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$regex = '/^' . str_replace( '\*', '.*', preg_quote( $rule, '/' ) ) . '$/';
|
|
if ( 1 === preg_match( $regex, $meta_key ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Normalize line endings to improve diff stability.
|
|
*
|
|
* @param string $text Text.
|
|
* @return string
|
|
*/
|
|
public static function normalize_newlines( string $text ): string {
|
|
return str_replace( "\r\n", "\n", $text );
|
|
}
|
|
|
|
/**
|
|
* Generate a stable JSON string with recursive key sorting.
|
|
*
|
|
* @param mixed $data Data.
|
|
* @return string
|
|
*/
|
|
public static function stable_json( $data ): string {
|
|
$data = self::ksort_recursive( $data );
|
|
return (string) wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
|
|
}
|
|
|
|
/**
|
|
* Recursively sort associative arrays by key.
|
|
*
|
|
* @param mixed $value Value.
|
|
* @return mixed
|
|
*/
|
|
private static function ksort_recursive( $value ) {
|
|
if ( is_array( $value ) ) {
|
|
$is_assoc = array_keys( $value ) !== range( 0, count( $value ) - 1 );
|
|
if ( $is_assoc ) {
|
|
ksort( $value );
|
|
}
|
|
foreach ( $value as $k => $v ) {
|
|
$value[ $k ] = self::ksort_recursive( $v );
|
|
}
|
|
}
|
|
return $value;
|
|
}
|
|
}
|