fa356a63b1
Anti-EAV Lint + Quality Gate / anti-eav-lint (push) Successful in 8s
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) Successful in 22s
Release / Test Gate (lint + phpcs + phpstan + unit + integration) (push) Successful in 1m2s
Release / release (push) Successful in 11s
WPDO_VERSION 由 class-tmdo-back-compat.php 自行 define 為 TMDO_VERSION, 兩者永遠相等,admin notice 從未觸發;PHPStan L6 認出 notIdentical.alwaysFalse 並卡掉 main run #8 與 v1.0.0 tag 的 Test Gate。改查 active_plugins basename, 與 HP AddOn detector 的偵測方式一致。
354 lines
20 KiB
PHP
354 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 () {
|
|
// Deliberately not a WPDO_VERSION comparison: this plugin defines that
|
|
// constant itself (includes/class-tmdo-back-compat.php), so the two
|
|
// would always match and the notice could never fire.
|
|
$tmdo_legacy = 'wp-data-optimizer/wp-data-optimizer.php';
|
|
if ( in_array( $tmdo_legacy, (array) get_option( 'active_plugins', array() ), true ) ) {
|
|
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 );
|
|
}
|