$object_type, 'object_id' => absint( $object_id ), 'user_id' => absint( $user_id ), 'type' => $type, ); $has = self::has( $object_type, $object_id, $user_id, $type ); if ( $on && ! $has ) { $wpdb->insert( $table, array_merge( $where, array( 'created_at' => Time::now() ) ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table. /** * Fires after a member likes or bookmarks something. * * @since 1.0.0 * * @param string $object_type "post" or "comment". * @param int $object_id Object ID. * @param int $user_id User ID. * @param string $type "like" or "bookmark". */ do_action( 'spacebay_reaction_added', $object_type, absint( $object_id ), absint( $user_id ), $type ); } elseif ( ! $on && $has ) { $wpdb->delete( $table, $where ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table. /** * Fires after a member takes back a like or a bookmark. * * @since 1.0.0 * * @param string $object_type "post" or "comment". * @param int $object_id Object ID. * @param int $user_id User ID. * @param string $type "like" or "bookmark". */ do_action( 'spacebay_reaction_removed', $object_type, absint( $object_id ), absint( $user_id ), $type ); } if ( 'like' === $type ) { self::recount( $object_type, $object_id ); } return $on; } /** * Whether a user reacted. * * @param string $object_type Object type. * @param int $object_id Object ID. * @param int $user_id User ID. * @param string $type Reaction type. * @return bool */ public static function has( $object_type, $object_id, $user_id, $type ) { global $wpdb; return (bool) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Fresh read before writing. $wpdb->prepare( 'SELECT id FROM %i WHERE object_type = %s AND object_id = %d AND user_id = %d AND type = %s', Tables::name( 'reactions' ), $object_type, absint( $object_id ), absint( $user_id ), $type ) ); } /** * IDs among the given objects that a user reacted to. * * @param string $object_type Object type. * @param int[] $object_ids Object IDs. * @param int $user_id User ID. * @param string $type Reaction type. * @return int[] */ public static function of_user( $object_type, array $object_ids, $user_id, $type ) { global $wpdb; $object_ids = array_values( array_filter( array_map( 'absint', $object_ids ) ) ); if ( ! $object_ids || ! $user_id ) { return array(); } $placeholders = implode( ',', array_fill( 0, count( $object_ids ), '%d' ) ); $ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table, one query per feed page. $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber -- The IN() list has one %d per ID. "SELECT object_id FROM %i WHERE object_type = %s AND user_id = %d AND type = %s AND object_id IN ($placeholders)", // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Placeholders are built from %d only. array_merge( array( Tables::name( 'reactions' ), $object_type, absint( $user_id ), $type ), $object_ids ) ) ); return array_map( 'intval', (array) $ids ); } /** * Removes every reaction on objects. * * @param string $object_type Object type. * @param int[] $object_ids Object IDs. * @return void */ public static function delete_for( $object_type, array $object_ids ) { global $wpdb; foreach ( array_map( 'absint', $object_ids ) as $object_id ) { $wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table. Tables::name( 'reactions' ), array( 'object_type' => $object_type, 'object_id' => $object_id, ) ); } } /** * Stores the like count on the post or comment row. * * @param string $object_type Object type. * @param int $object_id Object ID. * @return void */ private static function recount( $object_type, $object_id ) { global $wpdb; $count = (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Counter refresh after a write. $wpdb->prepare( 'SELECT COUNT(id) FROM %i WHERE object_type = %s AND object_id = %d AND type = %s', Tables::name( 'reactions' ), $object_type, absint( $object_id ), 'like' ) ); $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table. Tables::name( 'post' === $object_type ? 'posts' : 'comments' ), array( 'reactions_count' => $count ), array( 'id' => absint( $object_id ) ) ); } }