b4400a68e5
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
118 lines
3.4 KiB
PHP
118 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* Favorites interceptor for HivePress user favorites.
|
|
*
|
|
* @package WP_Data_Optimizer
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Favorites interceptor — syncs HivePress user favorites to hpct_favorites table.
|
|
*
|
|
* Special: operates on user_meta (hp_favorited_listings), not post_meta.
|
|
*/
|
|
class TMDO_Favorites_Interceptor extends TMDO_Interceptor_Base {
|
|
|
|
/**
|
|
* Module identifier.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $module = 'favorites';
|
|
|
|
/**
|
|
* Registers WordPress hooks for this interceptor.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register_hooks(): void {
|
|
add_filter( 'update_user_metadata', array( $this, 'filter_update_user_meta' ), 10, 5 );
|
|
add_action( 'before_delete_post', array( $this, 'action_delete_post' ), 10, 2 );
|
|
}
|
|
|
|
/**
|
|
* Filters update_user_metadata to sync hp_favorited_listings.
|
|
*
|
|
* @param mixed $check Whether to short-circuit.
|
|
* @param int $user_id User ID.
|
|
* @param string $meta_key Meta key.
|
|
* @param mixed $meta_value Meta value.
|
|
* @param mixed $prev_value Previous meta value.
|
|
* @return mixed Filtered check value.
|
|
*/
|
|
public function filter_update_user_meta( $check, int $user_id, string $meta_key, $meta_value, $prev_value ) {
|
|
if ( 'hp_favorited_listings' !== $meta_key || ! $this->is_active() ) {
|
|
return $check;
|
|
}
|
|
|
|
try {
|
|
$this->sync_favorites( $user_id, $meta_value );
|
|
} catch ( \Throwable $e ) {
|
|
TMDO_Logger::error( $this->module, 'update_user_metadata', $e->getMessage() );
|
|
}
|
|
|
|
return $check;
|
|
}
|
|
|
|
/**
|
|
* Deletes favorites records when a listing post is deleted.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param \WP_Post $post Post object.
|
|
* @return void
|
|
*/
|
|
public function action_delete_post( int $post_id, \WP_Post $post ): void {
|
|
if ( 'hp_listing' !== $post->post_type || ! $this->is_active() ) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
global $wpdb;
|
|
$wpdb->delete( TMDO_DB::table( 'hpct_favorites' ), array( 'listing_id' => $post_id ), array( '%d' ) );
|
|
} catch ( \Throwable $e ) {
|
|
TMDO_Logger::error( $this->module, 'before_delete_post', $e->getMessage() );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Syncs user favorites to the hpct_favorites table.
|
|
*
|
|
* @param int $user_id User ID.
|
|
* @param mixed $meta_value Favorites meta value (array or serialized).
|
|
* @return void
|
|
*/
|
|
private function sync_favorites( int $user_id, $meta_value ): void {
|
|
global $wpdb;
|
|
$table = TMDO_DB::table( 'hpct_favorites' );
|
|
$now = TMDO_DB::now();
|
|
|
|
// v2.13.3: object-injection-safe unserialize (fixes L-DESER-1).
|
|
// Input is user-controlled wp_usermeta value via update_user_meta hook.
|
|
$listing_ids = is_array( $meta_value )
|
|
? $meta_value
|
|
: (array) TMDO_Safe_Unserialize::run( $meta_value );
|
|
$listing_ids = array_filter( array_map( 'absint', $listing_ids ) );
|
|
|
|
// Delete all existing and re-insert.
|
|
$wpdb->delete( $table, array( 'user_id' => $user_id ), array( '%d' ) );
|
|
|
|
$insert_sql = TMDO_IS_SQLITE ? 'INSERT OR IGNORE' : 'INSERT IGNORE';
|
|
|
|
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- insert_sql is 'INSERT IGNORE'/'INSERT OR IGNORE'; table name from TMDO_DB::table().
|
|
foreach ( $listing_ids as $listing_id ) {
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
"{$insert_sql} INTO `{$table}` (user_id, listing_id, created_at) VALUES (%d, %d, %s)",
|
|
$user_id,
|
|
$listing_id,
|
|
$now
|
|
)
|
|
);
|
|
}
|
|
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
}
|
|
}
|