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:
2026-07-31 05:06:36 +08:00
commit d36bb954d1
206 changed files with 66538 additions and 0 deletions
@@ -0,0 +1,412 @@
<?php
/**
* TMDO_Term_Comment_Misc_Bucket — Catch-all flat storage for unregistered
* term + comment meta keys (v2.12.4 Phase 4).
*
* The "missing piece" that makes wp_termmeta / wp_commentmeta completely
* avoidable. After Phase 03:
*
* - Phase 0 (v2.12.0): cleanup CLI removes historical garbage
* - Phase 1 (v2.12.1): garbage filter blocks new garbage writes
* - Phase 2 (v2.12.2): entity registry routes registered HivePress fields
* to wp_wpdo_term_hp_taxonomy / wp_wpdo_comment_hp_review
* - Phase 3 (v2.12.3): WC term count filter routes product_count_* → wp_options
*
* What's left? **Unregistered keys** — anything written to term/comment meta
* that doesn't match any pattern (e.g., `note_group` on dev10, or any future
* plugin's custom key). Those still land in wp_termmeta / wp_commentmeta.
*
* This class is the catch-all. Filter priority 99 (LAST in the chain) means
* we only handle writes where every other filter has returned null (i.e., no
* match). Two new flat tables provide structurally identical K/V storage
* with explicit ownership.
*
* Filter priority chain (term + comment metadata writes):
*
* priority 9: garbage filter (drop _wxr_ / _demo_ / orphan)
* priority 9: WC term count filter (route product_count_* → wp_options)
* priority 10: Hook Bus / entity (route registered keys → flat tables)
* priority 99: THIS misc bucket (catch-all → wp_wpdo_*_misc)
*
* The chain works because filter callbacks preserve `$check` / `$pre`
* (the accumulator) when they don't match, so we can detect "nobody handled
* this" by checking `$check === null` at our priority.
*
* Storage:
*
* CREATE TABLE wp_wpdo_term_misc (
* term_id BIGINT(20) UNSIGNED NOT NULL,
* meta_key VARCHAR(191) NOT NULL,
* meta_value LONGTEXT,
* updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* PRIMARY KEY (term_id, meta_key),
* KEY meta_key (meta_key)
* );
* -- (and corresponding wp_wpdo_comment_misc with comment_id)
*
* No reverse-EAV optimization (still K/V storage), but achieves the literal
* goal of "wp_termmeta / wp_commentmeta zero writes" — making them DROPpable
* in v3.0.0.
*
* 🔒 Lessons applied (v2.11.7): added to TMDO_Hook_Bus_Bridge::COEXIST_WHITELIST.
*
* @package WP_Data_Optimizer
* @since 2.12.4
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Catch-all storage for unregistered term + comment meta keys.
*/
final class TMDO_Term_Comment_Misc_Bucket {
/** Option toggle key. */
public const OPT_ENABLED = 'wpdo_term_comment_misc_bucket_enabled';
/** Filter priority — runs LAST in the chain (after Hook Bus at 10). */
public const FILTER_PRIORITY = 99;
/**
* Register the four metadata filters on `init` priority 5.
*
* @return void
*/
public static function init(): void {
if ( ! self::is_enabled() ) {
return;
}
// Term metadata.
add_filter( 'get_term_metadata', array( self::class, 'on_term_read' ), self::FILTER_PRIORITY, 4 );
add_filter( 'add_term_metadata', array( self::class, 'on_term_add' ), self::FILTER_PRIORITY, 5 );
add_filter( 'update_term_metadata', array( self::class, 'on_term_update' ), self::FILTER_PRIORITY, 5 );
add_filter( 'delete_term_metadata', array( self::class, 'on_term_delete' ), self::FILTER_PRIORITY, 5 );
// Comment metadata.
add_filter( 'get_comment_metadata', array( self::class, 'on_comment_read' ), self::FILTER_PRIORITY, 4 );
add_filter( 'add_comment_metadata', array( self::class, 'on_comment_add' ), self::FILTER_PRIORITY, 5 );
add_filter( 'update_comment_metadata', array( self::class, 'on_comment_update' ), self::FILTER_PRIORITY, 5 );
add_filter( 'delete_comment_metadata', array( self::class, 'on_comment_delete' ), self::FILTER_PRIORITY, 5 );
}
/**
* Check the admin toggle. Defaults to enabled.
*
* @return bool
*/
public static function is_enabled(): bool {
return (bool) get_option( self::OPT_ENABLED, '1' );
}
/**
* Term-side fully-qualified misc table name.
*
* @return string
*/
public static function term_table(): string {
global $wpdb;
return $wpdb->prefix . 'wpdo_term_misc';
}
/**
* Comment-side fully-qualified misc table name.
*
* @return string
*/
public static function comment_table(): string {
global $wpdb;
return $wpdb->prefix . 'wpdo_comment_misc';
}
// ── Term metadata callbacks ───────────────────────────────────────────────
/**
* Filter callback: get_term_metadata.
*
* @param mixed $pre Filter accumulator.
* @param int $object_id Term ID.
* @param string $meta_key Meta key being read.
* @param bool $single Whether single value was requested.
* @return mixed
*/
public static function on_term_read( $pre, $object_id, $meta_key, $single ) {
unset( $single );
// Only handle when no earlier filter has resolved this read.
if ( null !== $pre ) {
return $pre;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $pre;
}
$value = self::read( self::term_table(), 'term_id', (int) $object_id, $meta_key );
if ( null === $value ) {
return $pre;
}
return array( $value );
}
/**
* Filter callback: add_term_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Term ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value.
* @param bool $unique Unique flag (unused).
* @return mixed
*/
public static function on_term_add( $check, $object_id, $meta_key, $meta_value, $unique ) {
unset( $unique );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::write( self::term_table(), 'term_id', (int) $object_id, $meta_key, $meta_value );
return true;
}
/**
* Filter callback: update_term_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Term ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value.
* @param mixed $prev_value Previous value (unused).
* @return mixed
*/
public static function on_term_update( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
unset( $prev_value );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::write( self::term_table(), 'term_id', (int) $object_id, $meta_key, $meta_value );
return true;
}
/**
* Filter callback: delete_term_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Term ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value-scoped delete (unused).
* @param bool $delete_all Delete-all flag (unused).
* @return mixed
*/
public static function on_term_delete( $check, $object_id, $meta_key, $meta_value, $delete_all ) {
unset( $meta_value, $delete_all );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::delete_row( self::term_table(), 'term_id', (int) $object_id, $meta_key );
return true;
}
// ── Comment metadata callbacks ────────────────────────────────────────────
/**
* Filter callback: get_comment_metadata.
*
* @param mixed $pre Filter accumulator.
* @param int $object_id Comment ID.
* @param string $meta_key Meta key.
* @param bool $single Single flag (unused).
* @return mixed
*/
public static function on_comment_read( $pre, $object_id, $meta_key, $single ) {
unset( $single );
if ( null !== $pre ) {
return $pre;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $pre;
}
$value = self::read( self::comment_table(), 'comment_id', (int) $object_id, $meta_key );
if ( null === $value ) {
return $pre;
}
return array( $value );
}
/**
* Filter callback: add_comment_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Comment ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value.
* @param bool $unique Unique flag (unused).
* @return mixed
*/
public static function on_comment_add( $check, $object_id, $meta_key, $meta_value, $unique ) {
unset( $unique );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::write( self::comment_table(), 'comment_id', (int) $object_id, $meta_key, $meta_value );
return true;
}
/**
* Filter callback: update_comment_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Comment ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value.
* @param mixed $prev_value Previous value (unused).
* @return mixed
*/
public static function on_comment_update( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
unset( $prev_value );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::write( self::comment_table(), 'comment_id', (int) $object_id, $meta_key, $meta_value );
return true;
}
/**
* Filter callback: delete_comment_metadata.
*
* @param mixed $check Filter accumulator.
* @param int $object_id Comment ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value-scoped (unused).
* @param bool $delete_all Delete-all flag (unused).
* @return mixed
*/
public static function on_comment_delete( $check, $object_id, $meta_key, $meta_value, $delete_all ) {
unset( $meta_value, $delete_all );
if ( null !== $check ) {
return $check;
}
if ( ! is_string( $meta_key ) || '' === $meta_key ) {
return $check;
}
self::delete_row( self::comment_table(), 'comment_id', (int) $object_id, $meta_key );
return true;
}
// ── Internal storage helpers ──────────────────────────────────────────────
/**
* Read a value from a misc bucket table.
*
* Returns the raw stored value (string), or null when no row exists.
* Caller must wrap in array for the get_*_metadata filter contract.
*
* @param string $table Fully-qualified table name.
* @param string $id_column 'term_id' or 'comment_id'.
* @param int $object_id Entity ID.
* @param string $meta_key Meta key.
* @return string|null
*/
private static function read( string $table, string $id_column, int $object_id, string $meta_key ): ?string {
global $wpdb;
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$value = $wpdb->get_var(
$wpdb->prepare(
"SELECT meta_value FROM `{$table}` WHERE `{$id_column}` = %d AND meta_key = %s LIMIT 1", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$object_id,
$meta_key
)
);
// phpcs:enable
return ( null === $value ) ? null : (string) $value;
}
/**
* Write (INSERT or UPDATE) a value to a misc bucket table.
*
* Uses ON DUPLICATE KEY UPDATE — the (id, meta_key) primary key
* means each (entity, meta_key) pair has a single canonical row.
*
* @param string $table Fully-qualified table name.
* @param string $id_column 'term_id' or 'comment_id'.
* @param int $object_id Entity ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Value to store. Non-scalar types are serialized.
* @return void
*/
private static function write( string $table, string $id_column, int $object_id, string $meta_key, $meta_value ): void {
global $wpdb;
// Match WP convention: serialize arrays/objects, scalar values stored as-is.
$serialized = is_scalar( $meta_value ) || null === $meta_value
? (string) $meta_value
: maybe_serialize( $meta_value );
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
$wpdb->query(
$wpdb->prepare(
"INSERT INTO `{$table}` (`{$id_column}`, meta_key, meta_value) VALUES (%d, %s, %s)
ON DUPLICATE KEY UPDATE meta_value = VALUES(meta_value)",
$object_id,
$meta_key,
$serialized
)
);
// phpcs:enable
}
/**
* Delete the row matching (object_id, meta_key) from a misc bucket table.
*
* @param string $table Fully-qualified table name.
* @param string $id_column 'term_id' or 'comment_id'.
* @param int $object_id Entity ID.
* @param string $meta_key Meta key.
* @return void
*/
private static function delete_row( string $table, string $id_column, int $object_id, string $meta_key ): void {
global $wpdb;
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
"DELETE FROM `{$table}` WHERE `{$id_column}` = %d AND meta_key = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$object_id,
$meta_key
)
);
// phpcs:enable
}
/**
* Count rows in a misc bucket table (for admin status panel).
*
* @param string $entity_type 'term' or 'comment'.
* @return int
*/
public static function count_rows( string $entity_type ): int {
global $wpdb;
$table = 'comment' === $entity_type ? self::comment_table() : self::term_table();
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$exists = (bool) $wpdb->get_var(
$wpdb->prepare( 'SHOW TABLES LIKE %s', $table )
);
if ( ! $exists ) {
return 0;
}
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$table}`" );
// phpcs:enable
}
}