prefix's resolution by creating tables under the // itest prefix and shadowing term_table()/comment_table() via $wpdb->prefix. // $wpdb->prefix is 'wp_itest_' in tests so wpdo_term_misc resolves to wp_itest_wpdo_term_misc. $wpdb->query( 'DROP TABLE IF EXISTS `' . self::TERM_MISC . '`' ); $wpdb->query( 'CREATE TABLE `' . self::TERM_MISC . '` ( term_id bigint(20) unsigned NOT NULL, meta_key varchar(191) NOT NULL, meta_value longtext, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (term_id, meta_key), KEY meta_key (meta_key) ) DEFAULT CHARACTER SET utf8mb4' ); $wpdb->query( 'DROP TABLE IF EXISTS `' . self::COMMENT_MISC . '`' ); $wpdb->query( 'CREATE TABLE `' . self::COMMENT_MISC . '` ( comment_id bigint(20) unsigned NOT NULL, meta_key varchar(191) NOT NULL, meta_value longtext, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (comment_id, meta_key), KEY meta_key (meta_key) ) DEFAULT CHARACTER SET utf8mb4' ); } public static function tearDownAfterClass(): void { global $wpdb; $wpdb->query( 'DROP TABLE IF EXISTS `' . self::TERM_MISC . '`' ); $wpdb->query( 'DROP TABLE IF EXISTS `' . self::COMMENT_MISC . '`' ); } protected function setUp(): void { global $wpdb; $wpdb->query( 'TRUNCATE TABLE `' . self::TERM_MISC . '`' ); $wpdb->query( 'TRUNCATE TABLE `' . self::COMMENT_MISC . '`' ); } // ── $pre preservation contract (priority chain integrity) ──────────────── public function test_on_term_read_preserves_non_null_pre(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_read( array( 'managed_value' ), 1, 'any_key', true ); $this->assertSame( array( 'managed_value' ), $result ); } public function test_on_term_add_preserves_non_null_check(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_add( true, 1, 'any_key', 'value', false ); $this->assertTrue( $result, 'Must preserve $check=true (someone else handled write)' ); } public function test_on_term_update_preserves_non_null_check(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_update( true, 1, 'any_key', 'value', '' ); $this->assertTrue( $result ); } public function test_on_term_delete_preserves_non_null_check(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_delete( true, 1, 'any_key', '', false ); $this->assertTrue( $result ); } public function test_comment_callbacks_preserve_non_null_check(): void { $this->assertTrue( WPDO_Term_Comment_Misc_Bucket::on_comment_add( true, 1, 'any', 'v', false ) ); $this->assertTrue( WPDO_Term_Comment_Misc_Bucket::on_comment_update( true, 1, 'any', 'v', '' ) ); $this->assertTrue( WPDO_Term_Comment_Misc_Bucket::on_comment_delete( true, 1, 'any', '', false ) ); $this->assertSame( array( 'v' ), WPDO_Term_Comment_Misc_Bucket::on_comment_read( array( 'v' ), 1, 'any', true ) ); } // ── Catch-all behavior when $check === null ───────────────────────────── public function test_on_term_add_writes_to_misc_table_when_unhandled(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_add( null, 5, 'note_group', 'foo', false ); $this->assertTrue( $result, 'Must short-circuit (return true) after writing' ); global $wpdb; $value = $wpdb->get_var( $wpdb->prepare( 'SELECT meta_value FROM `' . self::TERM_MISC . '` WHERE term_id = %d AND meta_key = %s', 5, 'note_group' ) ); $this->assertSame( 'foo', $value ); } public function test_on_term_read_returns_value_from_misc_table_when_unhandled(): void { WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 7, 'unknown_key', 'bar', '' ); $result = WPDO_Term_Comment_Misc_Bucket::on_term_read( null, 7, 'unknown_key', true ); $this->assertSame( array( 'bar' ), $result ); } public function test_on_term_read_returns_pre_on_cache_miss(): void { // No prior write — read should fall through (return $pre = null, letting WP query DB). $result = WPDO_Term_Comment_Misc_Bucket::on_term_read( null, 999, 'never_written', true ); $this->assertNull( $result ); } public function test_upsert_replaces_existing_value(): void { WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 5, 'k', 'first', '' ); WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 5, 'k', 'second', '' ); $result = WPDO_Term_Comment_Misc_Bucket::on_term_read( null, 5, 'k', true ); $this->assertSame( array( 'second' ), $result ); // Ensure exactly one row (composite PK enforces this). global $wpdb; $count = (int) $wpdb->get_var( 'SELECT COUNT(*) FROM `' . self::TERM_MISC . "` WHERE term_id = 5 AND meta_key = 'k'" ); $this->assertSame( 1, $count ); } public function test_on_term_delete_removes_row(): void { WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 5, 'k', 'v', '' ); $this->assertSame( array( 'v' ), WPDO_Term_Comment_Misc_Bucket::on_term_read( null, 5, 'k', true ) ); WPDO_Term_Comment_Misc_Bucket::on_term_delete( null, 5, 'k', '', false ); $this->assertNull( WPDO_Term_Comment_Misc_Bucket::on_term_read( null, 5, 'k', true ) ); } // ── Comment side ───────────────────────────────────────────────────────── public function test_on_comment_add_writes_to_misc_table(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_comment_add( null, 8, 'note_group', 'baz', false ); $this->assertTrue( $result ); global $wpdb; $value = $wpdb->get_var( $wpdb->prepare( 'SELECT meta_value FROM `' . self::COMMENT_MISC . '` WHERE comment_id = %d AND meta_key = %s', 8, 'note_group' ) ); $this->assertSame( 'baz', $value ); } public function test_term_writes_do_not_pollute_comment_table(): void { WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 5, 'k', 'term_val', '' ); global $wpdb; $count = (int) $wpdb->get_var( 'SELECT COUNT(*) FROM `' . self::COMMENT_MISC . '`' ); $this->assertSame( 0, $count, 'Term writes must not appear in comment misc table' ); } // ── Empty meta_key guard ──────────────────────────────────────────────── public function test_empty_meta_key_returns_check_unchanged(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_add( null, 5, '', 'value', false ); $this->assertNull( $result, 'Empty meta_key must not be written' ); } public function test_non_string_meta_key_returns_check_unchanged(): void { $result = WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 5, 123, 'value', '' ); $this->assertNull( $result ); } // ── is_enabled toggle ─────────────────────────────────────────────────── public function test_is_enabled_defaults_true(): void { delete_option( WPDO_Term_Comment_Misc_Bucket::OPT_ENABLED ); $this->assertTrue( WPDO_Term_Comment_Misc_Bucket::is_enabled() ); } public function test_is_enabled_respects_zero_value(): void { update_option( WPDO_Term_Comment_Misc_Bucket::OPT_ENABLED, '0' ); $this->assertFalse( WPDO_Term_Comment_Misc_Bucket::is_enabled() ); delete_option( WPDO_Term_Comment_Misc_Bucket::OPT_ENABLED ); } public function test_count_rows_returns_actual_count(): void { WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 1, 'a', 'x', '' ); WPDO_Term_Comment_Misc_Bucket::on_term_update( null, 2, 'b', 'y', '' ); WPDO_Term_Comment_Misc_Bucket::on_comment_update( null, 5, 'c', 'z', '' ); $this->assertSame( 2, WPDO_Term_Comment_Misc_Bucket::count_rows( 'term' ) ); $this->assertSame( 1, WPDO_Term_Comment_Misc_Bucket::count_rows( 'comment' ) ); } }