Files
2meet-data-optimizer/2meet-data-optimizer.php
T
wpdev fbe41e2130
Anti-EAV Lint + Quality Gate / anti-eav-lint (push) Successful in 9s
Tests / Unit Tests (push) Successful in 10s
Tests / Integration Tests (push) Successful in 33s
Tests / PHP Lint (push) Successful in 8s
Tests / PHPCS (push) Successful in 20s
Tests / PHPStan (push) Failing after 25s
Release / Test Gate (lint + phpcs + phpstan + unit + integration) (push) Failing after 36s
Release / release (push) Has been skipped
release: v1.0.0 — 取代 wp-data-optimizer v3.4.6
版本 0.1.0 → 1.0.0(含 TMDO_VERSION / TWO_MEET_DATA_OPTIMIZER_VERSION /
WP_DATA_OPTIMIZER_VERSION 與 unit bootstrap)。姊妹外掛只在診斷 CLI 顯示
WP_DATA_OPTIMIZER_VERSION、無版本比較,故報 1.0.0 安全。

wp-data-optimizer 退休:兩站台已停用,本機三個目錄改名為 *.retired
(wp-data-optimizer / -v3.1.1 / _audit),git 歷史保留在 gitea。

CHANGELOG 記錄本次 backport 全貌與 4 項 ABI/行為變更。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 09:45:22 +08:00

350 lines
20 KiB
PHP

<?php
/**
* Plugin Name: 2meet Data Optimizer
* Plugin URI: https://2meet.io/2meet-data-optimizer
* Description: 通用 WordPress 反 EAV 引擎:將 postmeta / usermeta / termmeta / commentmeta 自動分流至四象限扁平表(Hot / Warm / Cold / Archive),大幅提升搜尋與篩選效能。從 wp-data-optimizer v2.16.0 提煉的純核心,整合層交給 11 個 AddOn。
* Version: 1.0.0
* Requires at least: 6.0
* Tested up to: 6.9.4
* Requires PHP: 8.1
* Author: 2meet
* Author URI: https://2meet.io
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: 2meet-data-optimizer
* Domain Path: /languages
*
* TablePrefix: ^wpdo_(hot_|cold_|warm$|archive$|migrations$|errors$|benchmarks$|audit$|shadow_diffs$|site_metrics$|uni_options$|snapshots$|registry_meta$|migration_status$|user_points_ledger$|user_membership$|user_activity$|user_profile$|user_sso$|user_core_profile$|user_social$|user_commerce$|user_hp_user$|user_admin_prefs$|user_hot$|user_cold$|post_wp_core$|post_attachment$|post_nav_menu_item$|term_misc$|comment_misc$|demo_entity_counters$)
*
* @package TMDO
*/
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// ── Constants ──────────────────────────────────────────────────────────────
define( 'TMDO_VERSION', '1.0.0' );
define( 'TMDO_DB_VERSION', '2.1.0' );
define( 'TMDO_PATH', plugin_dir_path( __FILE__ ) );
define( 'TMDO_URL', plugin_dir_url( __FILE__ ) );
define( 'TMDO_FILE', __FILE__ );
define( 'TMDO_MIN_PHP', '8.1' );
define( 'TMDO_MIN_WP', '6.0' );
// 沿用既有 wp_wpdo_* schema(不 rename,與 wp-data-optimizer v2.16.0 共存相容)。
if ( ! defined( 'TMDO_TABLE_PREFIX' ) ) {
define( 'TMDO_TABLE_PREFIX', 'wpdo_' );
}
if ( ! defined( 'TMDO_CACHE_GROUP' ) ) {
define( 'TMDO_CACHE_GROUP', 'wpdo' );
}
/** True when running on the SQLite drop-in. */
define(
'TMDO_IS_SQLITE',
class_exists( 'WP_SQLite_Driver' ) ||
class_exists( 'WP_SQLite_DB' ) ||
class_exists( 'WP_SQLite_Translator' )
);
define( 'TMDO_IS_MYSQL', ! TMDO_IS_SQLITE );
// ── 跨外掛偵測訊號(dual-fire 對外保留 wp-data-optimizer 訊號)────────────
const TWO_MEET_DATA_OPTIMIZER_VERSION = '1.0.0';
const TWO_MEET_DATA_OPTIMIZER_FILE = __FILE__;
const TWO_MEET_DATA_OPTIMIZER_DB_VERSION = '1.2.0';
// 向後相容:對外 sister plugins 仍以 WP_DATA_OPTIMIZER_VERSION 偵測。
if ( ! defined( 'WP_DATA_OPTIMIZER_VERSION' ) ) {
define( 'WP_DATA_OPTIMIZER_VERSION', '1.0.0' );
}
if ( ! defined( 'WP_DATA_OPTIMIZER_FILE' ) ) {
define( 'WP_DATA_OPTIMIZER_FILE', __FILE__ );
}
if ( ! defined( 'WP_DATA_OPTIMIZER_DB_VERSION' ) ) {
define( 'WP_DATA_OPTIMIZER_DB_VERSION', '1.2.0' );
}
// PHP 版本守門。
if ( version_compare( PHP_VERSION, TMDO_MIN_PHP, '<' ) ) {
add_action(
'admin_notices',
static function () {
echo '<div class="notice notice-error"><p>';
printf(
/* translators: 1: required PHP version, 2: current PHP version */
esc_html__( '2meet Data Optimizer 需要 PHP %1$s 或更高版本(目前 %2$s)。', '2meet-data-optimizer' ),
esc_html( TMDO_MIN_PHP ),
esc_html( PHP_VERSION )
);
echo '</p></div>';
}
);
return;
}
// 互斥檢查:偵測既有 wp-data-optimizer v2.x 仍啟用時警告(avoid hook double-fire)。
add_action(
'admin_notices',
static function () {
if ( defined( 'WPDO_VERSION' ) && WPDO_VERSION !== TMDO_VERSION ) {
echo '<div class="notice notice-error"><p>';
esc_html_e( '⚠ 偵測到舊版 wp-data-optimizer 已啟用。請停用舊外掛以避免 hook 雙觸發。', '2meet-data-optimizer' );
echo '</p></div>';
}
}
);
// ── i18n ──────────────────────────────────────────────────────────────────
add_action( 'init', 'tmdo_load_textdomain' );
/**
* Load plugin text domain for translations.
*/
function tmdo_load_textdomain(): void {
load_plugin_textdomain(
'2meet-data-optimizer',
false,
dirname( plugin_basename( TMDO_FILE ) ) . '/languages'
);
}
// ── Core includes ─────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-capability.php';
require_once TMDO_PATH . 'includes/class-tmdo-crypto.php';
require_once TMDO_PATH . 'includes/class-tmdo-safe-unserialize.php';
require_once TMDO_PATH . 'includes/class-tmdo-db.php';
require_once TMDO_PATH . 'includes/class-tmdo-logger.php';
require_once TMDO_PATH . 'includes/class-tmdo-feature-flags.php';
require_once TMDO_PATH . 'includes/class-tmdo-sqlite-compat.php';
require_once TMDO_PATH . 'includes/class-tmdo-installer.php';
require_once TMDO_PATH . 'includes/class-tmdo-schema-registry.php';
require_once TMDO_PATH . 'includes/class-tmdo-custom-table-registry.php';
require_once TMDO_PATH . 'includes/trait-tmdo-anti-eav-aware.php';
require_once TMDO_PATH . 'includes/class-tmdo-hook-bus-bridge.php';
require_once TMDO_PATH . 'includes/class-tmdo-conflict-monitor.php';
require_once TMDO_PATH . 'includes/class-tmdo-compatibility.php';
require_once TMDO_PATH . 'includes/class-tmdo-postmeta-cleaner.php';
require_once TMDO_PATH . 'includes/class-tmdo-termmeta-cleaner.php';
require_once TMDO_PATH . 'includes/class-tmdo-commentmeta-cleaner.php';
require_once TMDO_PATH . 'includes/class-tmdo-term-comment-shadow-verifier.php';
require_once TMDO_PATH . 'includes/class-tmdo-term-comment-backfill.php';
require_once TMDO_PATH . 'includes/class-tmdo-term-stress-tester.php';
require_once TMDO_PATH . 'includes/class-tmdo-comment-stress-tester.php';
// ── Interceptor base + Sync Bridge(核心唯一保留 interceptor)─────────────
require_once TMDO_PATH . 'includes/interceptors/class-tmdo-interceptor-base.php';
require_once TMDO_PATH . 'includes/interceptors/class-tmdo-standard-post-interceptor.php';
require_once TMDO_PATH . 'includes/interceptors/class-tmdo-sync-bridge.php';
// ── Zone handlers ─────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/zones/class-tmdo-zone-router.php';
require_once TMDO_PATH . 'includes/class-tmdo-routing-predicate.php';
require_once TMDO_PATH . 'includes/zones/class-tmdo-zone-hot.php';
require_once TMDO_PATH . 'includes/zones/class-tmdo-zone-warm.php';
require_once TMDO_PATH . 'includes/zones/class-tmdo-zone-cold.php';
require_once TMDO_PATH . 'includes/zones/class-tmdo-zone-archive.php';
// ── Query interceptors(核心通用部分)─────────────────────────────────────
require_once TMDO_PATH . 'includes/query/class-tmdo-query-interceptor-base.php';
require_once TMDO_PATH . 'includes/query/class-tmdo-query-router.php';
require_once TMDO_PATH . 'includes/query/class-tmdo-post-query-router.php';
// ── Migration engine ──────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/migration/class-tmdo-migration-base.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-migration-engine.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-hot-migration.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-warm-migration.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-cold-migration.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-archive-migration.php';
// ── Integrations(核心保留 6 個通用整合,無 HP/WC/LP/2meet 依存)────────
require_once TMDO_PATH . 'includes/integrations/class-tmdo-term-comment-garbage-filter.php';
require_once TMDO_PATH . 'includes/integrations/class-tmdo-term-comment-misc-bucket.php';
require_once TMDO_PATH . 'includes/integrations/class-tmdo-member-fields.php';
require_once TMDO_PATH . 'includes/integrations/class-tmdo-post-fields.php';
require_once TMDO_PATH . 'includes/integrations/class-tmdo-points-manager.php';
require_once TMDO_PATH . 'includes/integrations/class-tmdo-demo-entity-counter.php';
// ── Cache + Classifier ───────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-cache-layer.php';
require_once TMDO_PATH . 'includes/class-tmdo-zone-classifier.php';
// ── Public API facade ─────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-api.php';
// ── v2 Upgrader ───────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-v2-upgrader.php';
// ── Snapshot system ──────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/snapshots/class-tmdo-snapshot-manager.php';
require_once TMDO_PATH . 'includes/snapshots/class-tmdo-snapshot-writer.php';
require_once TMDO_PATH . 'includes/snapshots/class-tmdo-snapshot-reader.php';
require_once TMDO_PATH . 'includes/snapshots/class-tmdo-snapshot-pruner.php';
// ── FSM transition guard ─────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/safety/class-tmdo-fsm-guard.php';
// ── Site Health integration ──────────────────────────────────────────────
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-site-health.php';
add_action( 'init', array( 'TMDO_Site_Health', 'register' ) );
// ── Daily health probe cron ─────────────────────────────────────────────
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-health-cron.php';
// ── Notifiers ─────────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/notifications/abstract-class-tmdo-notifier.php';
require_once TMDO_PATH . 'includes/notifications/class-tmdo-email-notifier.php';
require_once TMDO_PATH . 'includes/notifications/class-tmdo-slack-notifier.php';
require_once TMDO_PATH . 'includes/notifications/class-tmdo-discord-notifier.php';
require_once TMDO_PATH . 'includes/notifications/class-tmdo-telegram-notifier.php';
TMDO_Email_Notifier::register();
TMDO_Slack_Notifier::register();
TMDO_Discord_Notifier::register();
TMDO_Telegram_Notifier::register();
// ── Monthly executive summary ───────────────────────────────────────────
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-monthly-summary.php';
TMDO_Monthly_Summary::register();
// ── Daily site-wide EAV health metrics ──────────────────────────────────
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-site-metrics-collector.php';
// ── FSM advisor ─────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/advisor/class-tmdo-fsm-advisor.php';
require_once TMDO_PATH . 'includes/advisor/class-tmdo-module-rules.php';
require_once TMDO_PATH . 'includes/advisor/class-tmdo-module-detector.php';
require_once TMDO_PATH . 'includes/advisor/class-tmdo-fsm-automator.php';
// ── Report export ──────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/export/class-tmdo-csv-writer.php';
if ( is_admin() ) {
require_once TMDO_PATH . 'admin/class-tmdo-export.php';
TMDO_Export::register();
}
// ── REST API ──────────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-rest-api.php';
// ── v2.0.0 Engine + Adapters + Modules ───────────────────────────────────
require_once TMDO_PATH . 'includes/engine/class-tmdo-type-caster.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-mode-manager.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-audit-logger.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-shadow-diff-logger.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-conflict-detector.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-cache-orchestrator.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-query-compiler.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-schema-manager.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-entity-registry.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-entity-migration-engine.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-entity-health.php';
require_once TMDO_PATH . 'includes/migration/interface-migration-phase.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-migration-phase-base.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-diagnose.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-backup.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-demote.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-install-schema.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-backfill-bulk.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-backfill-unserialize.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-promote-shadow.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-verify-sample.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-promote-aeav.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-cleanup.php';
require_once TMDO_PATH . 'includes/migration/phases/class-tmdo-phase-completed.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-migration-orchestrator.php';
require_once TMDO_PATH . 'includes/migration/class-tmdo-post-migration.php';
add_action( TMDO_Migration_Orchestrator::CRON_HOOK, array( 'TMDO_Migration_Orchestrator', 'cron_tick' ) );
add_action( 'wpdo_bridge_mode_changed', array( 'TMDO_Migration_Orchestrator', 'bust_attention_cache' ) );
add_action( 'tmdo_bridge_mode_changed', array( 'TMDO_Migration_Orchestrator', 'bust_attention_cache' ) );
require_once TMDO_PATH . 'includes/class-tmdo-user-stress-tester.php';
require_once TMDO_PATH . 'includes/class-tmdo-post-stress-tester.php';
require_once TMDO_PATH . 'includes/class-tmdo-post-shadow-verifier.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-auto-promoter.php';
require_once TMDO_PATH . 'includes/engine/class-tmdo-hook-bus.php';
require_once TMDO_PATH . 'includes/adapters/interface-entity-adapter.php';
require_once TMDO_PATH . 'includes/adapters/class-tmdo-adapter-post.php';
require_once TMDO_PATH . 'includes/adapters/class-tmdo-adapter-user.php';
require_once TMDO_PATH . 'includes/adapters/class-tmdo-adapter-term.php';
require_once TMDO_PATH . 'includes/adapters/class-tmdo-adapter-comment.php';
require_once TMDO_PATH . 'modules/options/class-tmdo-options-manager.php';
// ── Main loader ───────────────────────────────────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-core.php';
// ── Admin UI ───────────────────────────────────────────────────────────────
if ( is_admin() ) {
require_once TMDO_PATH . 'admin/class-tmdo-admin.php';
require_once TMDO_PATH . 'admin/class-tmdo-help-tabs.php';
TMDO_Help_Tabs::register();
require_once TMDO_PATH . 'admin/class-tmdo-setup-wizard.php';
TMDO_Setup_Wizard::register();
require_once TMDO_PATH . 'admin/class-tmdo-dashboard-widget.php';
TMDO_Dashboard_Widget::register();
}
// ── WP-CLI ─────────────────────────────────────────────────────────────────
if ( defined( 'WP_CLI' ) && WP_CLI ) {
require_once TMDO_PATH . 'cli/class-tmdo-cli.php';
WP_CLI::add_command( 'tmdo', 'TMDO_CLI' );
// 向後相容:保留 `wp wpdo` 指令命名空間。
WP_CLI::add_command( 'wpdo', 'TMDO_CLI' );
require_once TMDO_PATH . 'cli/class-tmdo-cli-v2.php';
require_once TMDO_PATH . 'cli/class-tmdo-cli-member.php';
require_once TMDO_PATH . 'cli/class-tmdo-cli-post.php';
require_once TMDO_PATH . 'cli/class-tmdo-cli-term-comment.php';
}
// ── 對外向後相容:WPDO_* 類別 / 常數 alias ─────────────────────────────
require_once TMDO_PATH . 'includes/class-tmdo-back-compat.php';
// ── Boot plugin ────────────────────────────────────────────────────────────
/**
* Plugin boot — fires at plugins_loaded:4 (early enough for HPCT-era priority 5).
*/
function tmdo_run(): void {
$core = new TMDO_Core();
$core->run();
add_action(
'rest_api_init',
static function () {
( new TMDO_REST_API() )->register_routes();
}
);
}
add_action( 'plugins_loaded', 'tmdo_run', 4 );
// ── Late-bind safety net ──────────────────────────────────────────────────
// Re-fire registration hooks at priority 30 to catch AddOn / partner plugin
// listeners that bootstrap on plugins_loaded:6+ (after core but before
// init).
add_action(
'plugins_loaded',
static function () {
if ( class_exists( 'TMDO_Custom_Table_Registry' ) ) {
TMDO_Custom_Table_Registry::instance()->fire_registration();
}
// Re-fire entity field registration so AddOns hooked at plugins_loaded:6 catch up.
if ( class_exists( 'TMDO_Entity_Registry' ) ) {
do_action( 'wpdo_register_entity_fields', 'TMDO_Entity_Registry' );
do_action( 'tmdo_register_entity_fields', 'TMDO_Entity_Registry' );
}
if ( class_exists( 'TMDO_Schema_Registry' ) ) {
do_action( 'wpdo_register_fields', TMDO_Schema_Registry::instance() );
do_action( 'tmdo_register_fields', TMDO_Schema_Registry::instance() );
}
},
30
);
// ── Lifecycle hooks ────────────────────────────────────────────────────────
register_activation_hook( __FILE__, array( 'TMDO_Installer', 'activate' ) );
register_deactivation_hook( __FILE__, array( 'TMDO_Installer', 'deactivate' ) );
// Multisite
if ( is_multisite() ) {
add_action( 'wp_initialize_site', array( 'TMDO_Installer', 'on_new_site' ), 999, 1 );
add_action( 'wp_uninitialize_site', array( 'TMDO_Installer', 'on_site_delete' ), 1, 1 );
}