prefix and fixed strings, and every // value goes through $wpdb->prepare() or $wpdb->insert/update/delete. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching class Notes { public static function init() { // AJAX hooks registered in Ajax } public static function save( $user_id, $lesson_id, $content ) { global $wpdb; $table = $wpdb->prefix . 'slms_lesson_notes'; $existing = self::get( $user_id, $lesson_id ); if ( $existing ) { return $wpdb->update( $table, array( 'note_content' => wp_kses_post( $content ) ), array( 'user_id' => $user_id, 'lesson_id' => $lesson_id, ), array( '%s' ), array( '%d', '%d' ) ); } return $wpdb->insert( $table, array( 'user_id' => $user_id, 'lesson_id' => $lesson_id, 'note_content' => wp_kses_post( $content ), 'created_at' => current_time( 'mysql', true ), ), array( '%d', '%d', '%s', '%s' ) ); } public static function get( $user_id, $lesson_id ) { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}slms_lesson_notes WHERE user_id = %d AND lesson_id = %d", $user_id, $lesson_id ) ); } public static function delete( $user_id, $lesson_id ) { global $wpdb; return $wpdb->delete( $wpdb->prefix . 'slms_lesson_notes', array( 'user_id' => $user_id, 'lesson_id' => $lesson_id, ), array( '%d', '%d' ) ); } }