Files
2meet-data-optimizer/includes/interceptors/class-tmdo-standard-post-interceptor.php
T
wpdev 76c01e44df refactor: 全部 128 個生產檔加入 declare(strict_types=1)(PR-H)
對齊 A v3.2.0。型別強制會把隱式轉換變成 TypeError,所以一次全檔加入
並跑完整測試(unit 451 / integration 398 全綠,無迴歸)。

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

152 lines
5.0 KiB
PHP

<?php
/**
* Abstract base for standard post→custom-table interceptors.
*
* Consolidates the identical action_delete_post / filter_update_meta /
* action_insert_post pattern shared by Reviews, Messages, Memberships,
* and Requests interceptors. Subclasses supply the three varying pieces:
* - post_type string
* - table key (passed to TMDO_DB::table())
* - INSERT columns via build_insert_data()
*
* Subclasses MUST also define:
* public const FIELD_MAP = [ 'meta_key' => 'column', ... ];
*
* @package TMDO
* @since 3.0.1
*/
declare(strict_types=1);
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from TMDO_DB::table(); column validated by subclass FIELD_MAP constant.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Abstract base for standard post→custom-table interceptors.
*
* @since 3.0.1
*/
abstract class TMDO_Standard_Post_Interceptor extends TMDO_Interceptor_Base {
// ── Subclass contracts ────────────────────────────────────────────────────
/** WordPress post_type slug this interceptor handles. */
abstract protected function get_post_type(): string;
/** Key passed to TMDO_DB::table() to resolve the custom table name. */
abstract protected function get_table_key(): string;
/**
* Build the INSERT row for a newly created post.
*
* @param int $post_id Post ID.
* @param \WP_Post $post Post object.
* @param string $now Formatted datetime string from TMDO_DB::now().
* @return array{values: array, formats: array}
* 'values' — associative array of column => value.
* 'formats' — ordered format string array (%d/%s) for $wpdb->insert.
*/
abstract protected function build_insert_data( int $post_id, \WP_Post $post, string $now ): array;
// ── Shared implementation ─────────────────────────────────────────────────
/**
* Register the three standard hooks. Subclasses that need additional
* hooks (e.g. get_post_metadata) should call parent::register_hooks()
* first and then add their own.
*/
public function register_hooks(): void {
add_filter( 'update_post_metadata', array( $this, 'filter_update_meta' ), 10, 5 );
add_action( 'wp_insert_post', array( $this, 'action_insert_post' ), 10, 3 );
add_action( 'before_delete_post', array( $this, 'action_delete_post' ), 10, 2 );
}
/**
* Deletes the custom-table record when the post is deleted.
*
* @param int $post_id Post ID.
* @param \WP_Post $post Post object.
* @return void
*/
final public function action_delete_post( int $post_id, \WP_Post $post ): void {
if ( $this->get_post_type() !== $post->post_type || ! $this->is_active() ) {
return;
}
try {
global $wpdb;
$wpdb->delete( TMDO_DB::table( $this->get_table_key() ), array( 'post_id' => $post_id ), array( '%d' ) );
} catch ( \Throwable $e ) {
TMDO_Logger::error( $this->module, 'before_delete_post', $e->getMessage() );
}
}
/**
* Syncs a meta update to the custom table column.
*
* @param mixed $check Short-circuit flag.
* @param int $post_id Post ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
* @param mixed $prev_value Previous value (unused).
* @return mixed Unmodified $check.
*/
final public function filter_update_meta( $check, int $post_id, string $meta_key, $meta_value, $prev_value ) {
$field_map = static::FIELD_MAP; // late static binding — picks up subclass const.
if ( $this->get_post_type() !== get_post_type( $post_id ) || ! isset( $field_map[ $meta_key ] ) ) {
return $check;
}
if ( ! $this->is_active() ) {
return $check;
}
try {
global $wpdb;
$col = $field_map[ $meta_key ];
$table = TMDO_DB::table( $this->get_table_key() );
$wpdb->query(
$wpdb->prepare(
"UPDATE `{$table}` SET `{$col}` = %s, updated_at = %s WHERE post_id = %d",
$meta_value,
TMDO_DB::now(),
$post_id
)
);
} catch ( \Throwable $e ) {
TMDO_Logger::error( $this->module, 'update_post_metadata', $e->getMessage() );
}
return $check;
}
/**
* Inserts the custom-table record when a new post is created.
*
* @param int $post_id Post ID.
* @param \WP_Post $post Post object.
* @param bool $update Whether this is an update (not a new post).
* @return void
*/
final public function action_insert_post( int $post_id, \WP_Post $post, bool $update ): void {
if ( $update || $this->get_post_type() !== $post->post_type || ! $this->is_active() ) {
return;
}
try {
$data = $this->build_insert_data( $post_id, $post, TMDO_DB::now() );
global $wpdb;
$wpdb->insert(
TMDO_DB::table( $this->get_table_key() ),
$data['values'],
$data['formats']
);
} catch ( \Throwable $e ) {
TMDO_Logger::error( $this->module, 'wp_insert_post', $e->getMessage() );
}
}
}