prefix . 'arwp_sessions'; $table_messages = $wpdb->prefix . 'arwp_messages'; $wpdb->delete( $table_messages, array( 'session_id' => $session_id ), array( '%d' ) ); $wpdb->delete( $table_sessions, array( 'id' => $session_id ), array( '%d' ) ); } $redirect = admin_url( 'edit.php?post_type=arwp_agent&page=arwp-conversations' ); if ( ! empty( $_GET['agent_id'] ) ) { $redirect = add_query_arg( 'agent_id', intval( $_GET['agent_id'] ), $redirect ); } wp_safe_redirect( $redirect ); exit; } /** * Render list or single-session view. */ public function render_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } // Read-only admin screen navigation (which session to view / which page); intval()-cast, no data is written. $session_id = isset( $_GET['session_id'] ) ? intval( $_GET['session_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( $session_id ) { $this->render_session_view( $session_id ); return; } $this->render_list_view(); } /** * Paginated session list. */ private function render_list_view() { global $wpdb; $table_sessions = $wpdb->prefix . 'arwp_sessions'; $table_messages = $wpdb->prefix . 'arwp_messages'; $per_page = 20; // Read-only pagination/filter params, intval()-cast, no data is written. $paged = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $offset = ( $paged - 1 ) * $per_page; $agent_filter = isset( $_GET['agent_id'] ) ? intval( $_GET['agent_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $where = '1=1'; $params = array(); if ( $agent_filter ) { $where .= ' AND s.agent_id = %d'; $params[] = $agent_filter; } // $where only ever concatenates the static ' AND s.agent_id = %d' fragment above; the value itself is always bound through prepare() via $count_params, never interpolated raw. $count_sql = "SELECT COUNT(*) FROM %i s WHERE $where"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $count_params = array_merge( array( $table_sessions ), $params ); $total = (int) $wpdb->get_var( $wpdb->prepare( $count_sql, $count_params ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_pages = max( 1, (int) ceil( $total / $per_page ) ); // Same $where fragment as above -- safe, values bound via $list_params, never interpolated raw. $list_sql = "SELECT s.*, (SELECT COUNT(*) FROM %i m WHERE m.session_id = s.id AND m.role != 'system') AS message_count, (SELECT COALESCE(SUM(tokens_used),0) FROM %i m WHERE m.session_id = s.id) AS tokens_used FROM %i s WHERE $where ORDER BY s.created_at DESC LIMIT %d OFFSET %d"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $list_params = array_merge( array( $table_messages, $table_messages, $table_sessions ), $params ); $list_params[] = $per_page; $list_params[] = $offset; $sessions = $wpdb->get_results( $wpdb->prepare( $list_sql, $list_params ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter $agents = get_posts( array( 'post_type' => 'arwp_agent', 'posts_per_page' => -1, 'post_status' => 'any', ) ); ?>
← |
| agent_id ) ); ?> | |
| user_id ) > 0 ? $this->user_label( $session->user_id ) : __( 'Guest', 'arwp-agents' ) ); ?> | |
| created_at ); ?> |
role ) ); ?> · created_at ); ?> tokens_used ) ) : ?> · tokens_used ) ) ); ?>