chore: initial snapshot of 2meet-data-optimizer v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* TMDO_Adapter_Comment - Comment 實體適配器
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
|
||||
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
final class TMDO_Adapter_Comment implements TMDO_Entity_Adapter_Interface {
|
||||
|
||||
public function get_entity_type(): string {
|
||||
return 'comment';
|
||||
}
|
||||
|
||||
public function get_native_meta_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->commentmeta;
|
||||
}
|
||||
|
||||
public function get_entity_id_column(): string {
|
||||
return 'comment_id';
|
||||
}
|
||||
|
||||
public function get_primary_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->comments;
|
||||
}
|
||||
|
||||
public function get_primary_id_column(): string {
|
||||
return 'comment_ID';
|
||||
}
|
||||
|
||||
public function get_cache_group(): string {
|
||||
return 'wpdo_comment_profile';
|
||||
}
|
||||
|
||||
public function get_delete_hook(): string {
|
||||
return 'delete_comment';
|
||||
}
|
||||
|
||||
public function extend_native_query( $query_object ): void {
|
||||
if ( ! ( $query_object instanceof WP_Comment_Query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpdo_query = $query_object->query_vars['wpdo_meta_query'] ?? null;
|
||||
if ( empty( $wpdo_query ) || ! is_array( $wpdo_query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WP_Comment_Query 使用 comments_clauses filter
|
||||
add_filter(
|
||||
'comments_clauses',
|
||||
function ( $clauses ) use ( $wpdo_query ) {
|
||||
$compiled = TMDO_Query_Compiler::compile( 'comment', $wpdo_query );
|
||||
|
||||
if ( ! empty( $compiled['joins'] ) ) {
|
||||
$clauses['join'] .= ' ' . implode( ' ', $compiled['joins'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $compiled['where'] ) ) {
|
||||
$clauses['where'] .= ' AND (' . implode( ' AND ', $compiled['where'] ) . ')';
|
||||
}
|
||||
|
||||
return $clauses;
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
public function get_entity_ids_after( int $after_id, int $limit ): array {
|
||||
global $wpdb;
|
||||
|
||||
return array_map(
|
||||
'intval',
|
||||
$wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT comment_ID FROM `{$wpdb->comments}` WHERE comment_ID > %d ORDER BY comment_ID ASC LIMIT %d",
|
||||
$after_id,
|
||||
$limit
|
||||
)
|
||||
) ?: array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 註冊 pre_get_comments hook(unit test 下 add_action 未載入時跳過)
|
||||
if ( function_exists( 'add_action' ) ) {
|
||||
add_action(
|
||||
'pre_get_comments',
|
||||
function ( $query ) {
|
||||
$adapter = TMDO_Entity_Registry::get_adapter( 'comment' );
|
||||
if ( $adapter ) {
|
||||
$adapter->extend_native_query( $query );
|
||||
}
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* TMDO_Adapter_Post - Post 實體適配器
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
|
||||
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
final class TMDO_Adapter_Post implements TMDO_Entity_Adapter_Interface {
|
||||
|
||||
public function get_entity_type(): string {
|
||||
return 'post';
|
||||
}
|
||||
|
||||
public function get_native_meta_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->postmeta;
|
||||
}
|
||||
|
||||
public function get_entity_id_column(): string {
|
||||
return 'post_id';
|
||||
}
|
||||
|
||||
public function get_primary_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->posts;
|
||||
}
|
||||
|
||||
public function get_primary_id_column(): string {
|
||||
return 'ID';
|
||||
}
|
||||
|
||||
public function get_cache_group(): string {
|
||||
return 'wpdo_post_profile';
|
||||
}
|
||||
|
||||
public function get_delete_hook(): string {
|
||||
return 'before_delete_post';
|
||||
}
|
||||
|
||||
/**
|
||||
* 擴充 WP_Query 支援 wpdo_meta_query / wpdo_orderby
|
||||
*/
|
||||
public function extend_native_query( $query_object ): void {
|
||||
if ( ! ( $query_object instanceof WP_Query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpdo_query = $query_object->get( 'wpdo_meta_query' );
|
||||
if ( empty( $wpdo_query ) || ! is_array( $wpdo_query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
TMDO_Query_Compiler::inject_into_wp_query( $query_object, $wpdo_query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor-based 取得 post IDs
|
||||
*/
|
||||
public function get_entity_ids_after( int $after_id, int $limit ): array {
|
||||
global $wpdb;
|
||||
|
||||
return array_map(
|
||||
'intval',
|
||||
$wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM `{$wpdb->posts}` WHERE ID > %d ORDER BY ID ASC LIMIT %d",
|
||||
$after_id,
|
||||
$limit
|
||||
)
|
||||
) ?: array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 註冊 pre_get_posts 以啟用 wpdo_meta_query(unit test 下 add_action 未載入時跳過)
|
||||
if ( function_exists( 'add_action' ) ) {
|
||||
add_action(
|
||||
'pre_get_posts',
|
||||
function ( $query ) {
|
||||
$adapter = TMDO_Entity_Registry::get_adapter( 'post' );
|
||||
if ( $adapter ) {
|
||||
$adapter->extend_native_query( $query );
|
||||
}
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* TMDO_Adapter_Term - Term 實體適配器
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
|
||||
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
final class TMDO_Adapter_Term implements TMDO_Entity_Adapter_Interface {
|
||||
|
||||
public function get_entity_type(): string {
|
||||
return 'term';
|
||||
}
|
||||
|
||||
public function get_native_meta_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->termmeta;
|
||||
}
|
||||
|
||||
public function get_entity_id_column(): string {
|
||||
return 'term_id';
|
||||
}
|
||||
|
||||
public function get_primary_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->terms;
|
||||
}
|
||||
|
||||
public function get_primary_id_column(): string {
|
||||
return 'term_id';
|
||||
}
|
||||
|
||||
public function get_cache_group(): string {
|
||||
return 'wpdo_term_profile';
|
||||
}
|
||||
|
||||
public function get_delete_hook(): string {
|
||||
return 'delete_term';
|
||||
}
|
||||
|
||||
public function extend_native_query( $query_object ): void {
|
||||
// Term 查詢使用 terms_clauses filter,不使用 $query_object
|
||||
}
|
||||
|
||||
/**
|
||||
* Term 特有:透過 terms_clauses filter 注入
|
||||
*/
|
||||
public function extend_term_clauses( array $clauses, array $taxonomies, array $args ): array {
|
||||
if ( empty( $args['wpdo_meta_query'] ) || ! is_array( $args['wpdo_meta_query'] ) ) {
|
||||
return $clauses;
|
||||
}
|
||||
return TMDO_Query_Compiler::inject_into_terms_clauses( $clauses, $args['wpdo_meta_query'] );
|
||||
}
|
||||
|
||||
public function get_entity_ids_after( int $after_id, int $limit ): array {
|
||||
global $wpdb;
|
||||
|
||||
return array_map(
|
||||
'intval',
|
||||
$wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT term_id FROM `{$wpdb->terms}` WHERE term_id > %d ORDER BY term_id ASC LIMIT %d",
|
||||
$after_id,
|
||||
$limit
|
||||
)
|
||||
) ?: array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 註冊 terms_clauses filter(unit test 下 add_filter 未載入時跳過)
|
||||
if ( function_exists( 'add_filter' ) ) {
|
||||
add_filter(
|
||||
'terms_clauses',
|
||||
function ( $clauses, $taxonomies, $args ) {
|
||||
$adapter = TMDO_Entity_Registry::get_adapter( 'term' );
|
||||
if ( $adapter instanceof TMDO_Adapter_Term ) {
|
||||
return $adapter->extend_term_clauses( $clauses, $taxonomies, $args );
|
||||
}
|
||||
return $clauses;
|
||||
},
|
||||
10,
|
||||
3
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* TMDO_Adapter_User - User 實體適配器
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
|
||||
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
final class TMDO_Adapter_User implements TMDO_Entity_Adapter_Interface {
|
||||
|
||||
public function get_entity_type(): string {
|
||||
return 'user';
|
||||
}
|
||||
|
||||
public function get_native_meta_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->usermeta;
|
||||
}
|
||||
|
||||
public function get_entity_id_column(): string {
|
||||
return 'user_id';
|
||||
}
|
||||
|
||||
public function get_primary_table(): string {
|
||||
global $wpdb;
|
||||
return $wpdb->users;
|
||||
}
|
||||
|
||||
public function get_primary_id_column(): string {
|
||||
return 'ID';
|
||||
}
|
||||
|
||||
public function get_cache_group(): string {
|
||||
return 'wpdo_user_profile';
|
||||
}
|
||||
|
||||
public function get_delete_hook(): string {
|
||||
return 'delete_user';
|
||||
}
|
||||
|
||||
public function extend_native_query( $query_object ): void {
|
||||
if ( ! ( $query_object instanceof WP_User_Query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpdo_query = $query_object->get( 'wpdo_meta_query' );
|
||||
if ( empty( $wpdo_query ) || ! is_array( $wpdo_query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
TMDO_Query_Compiler::inject_into_user_query( $query_object, $wpdo_query );
|
||||
}
|
||||
|
||||
public function get_entity_ids_after( int $after_id, int $limit ): array {
|
||||
global $wpdb;
|
||||
|
||||
return array_map(
|
||||
'intval',
|
||||
$wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM `{$wpdb->users}` WHERE ID > %d ORDER BY ID ASC LIMIT %d",
|
||||
$after_id,
|
||||
$limit
|
||||
)
|
||||
) ?: array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 註冊 pre_user_query(unit test 下 add_action 未載入時跳過)
|
||||
if ( function_exists( 'add_action' ) ) {
|
||||
add_action(
|
||||
'pre_user_query',
|
||||
function ( $query ) {
|
||||
$adapter = TMDO_Entity_Registry::get_adapter( 'user' );
|
||||
if ( $adapter ) {
|
||||
$adapter->extend_native_query( $query );
|
||||
}
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* Entity Adapter 合約介面
|
||||
*
|
||||
* 所有實體適配器(Post/User/Term/Comment)必須實作此介面
|
||||
* 將不同實體的行為標準化,供 Hook Bus 統一呼叫
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
|
||||
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Back-compat: define WPDO_ marker first so TMDO_ can extend it.
|
||||
// PHP class_alias() doesn't work on interfaces; extending is the only option.
|
||||
// Any class implementing TMDO_Entity_Adapter_Interface automatically satisfies
|
||||
// `instanceof WPDO_Entity_Adapter_Interface` via interface inheritance.
|
||||
if ( ! interface_exists( 'WPDO_Entity_Adapter_Interface', false ) ) {
|
||||
interface WPDO_Entity_Adapter_Interface {}
|
||||
}
|
||||
|
||||
interface TMDO_Entity_Adapter_Interface extends WPDO_Entity_Adapter_Interface {
|
||||
|
||||
/**
|
||||
* 實體類型識別子
|
||||
* 必須回傳 WordPress metadata type 之一:post|user|term|comment
|
||||
*/
|
||||
public function get_entity_type(): string;
|
||||
|
||||
/**
|
||||
* 原生 meta 表完整名稱(含 wp_ 前綴)
|
||||
* 例:wp_postmeta / wp_usermeta
|
||||
*/
|
||||
public function get_native_meta_table(): string;
|
||||
|
||||
/**
|
||||
* 原生 meta 表中指向實體的欄位名稱
|
||||
* 例:post_id / user_id / term_id / comment_id
|
||||
*/
|
||||
public function get_entity_id_column(): string;
|
||||
|
||||
/**
|
||||
* 對應的主實體表(用於 JOIN)
|
||||
* 例:wp_posts / wp_users / wp_terms / wp_comments
|
||||
*/
|
||||
public function get_primary_table(): string;
|
||||
|
||||
/**
|
||||
* 主實體表的主鍵欄位
|
||||
* 例:ID (post/user) / term_id / comment_ID
|
||||
*/
|
||||
public function get_primary_id_column(): string;
|
||||
|
||||
/**
|
||||
* 快取群組名稱(供 wp_cache_* 使用)
|
||||
*/
|
||||
public function get_cache_group(): string;
|
||||
|
||||
/**
|
||||
* 實體刪除時會觸發的 WordPress hook
|
||||
* 用於自動清理 UAE 資料表中對應列
|
||||
*/
|
||||
public function get_delete_hook(): string;
|
||||
|
||||
/**
|
||||
* 擴充原生查詢物件以支援 UAE meta_query
|
||||
*
|
||||
* @param mixed $query_object WP_Query / WP_User_Query / WP_Comment_Query 等
|
||||
*/
|
||||
public function extend_native_query( $query_object ): void;
|
||||
|
||||
/**
|
||||
* 取得所有已知的 ID(用於遷移時的迭代)
|
||||
* 採用 cursor-based 分頁
|
||||
*
|
||||
* @param int $after_id 取大於此 ID 的筆
|
||||
* @param int $limit 取多少筆
|
||||
* @return array<int>
|
||||
*/
|
||||
public function get_entity_ids_after( int $after_id, int $limit ): array;
|
||||
}
|
||||
Reference in New Issue
Block a user