engine = AI_Explainer_Pro_Detection_Engine::get_instance(); } public function render() { global $wpdb; $this->ensure_history_table(); $this->handle_actions(); $history_table = $wpdb->prefix . 'ai_explainer_scan_history'; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Plugin-owned table name; built from $wpdb->prefix and a hardcoded suffix, no user input. $history = $wpdb->get_results( "SELECT * FROM {$history_table} ORDER BY scan_date DESC LIMIT 10" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregate read on demand; staleness from cache would be misleading after a fresh scan. $total_posts = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_ai_explainer_scanned_date'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $human_posts = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_ai_explainer_human_score' AND CAST(meta_value AS DECIMAL(5,2)) >= %f", 0.7 ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $ai_posts = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_ai_explainer_human_score' AND CAST(meta_value AS DECIMAL(5,2)) < %f", 0.4 ) ); $uncertain = $total_posts - $human_posts - $ai_posts; $never_used = ( 0 === (int) $total_posts ); ?>

0 ) : ?>

render_content_table( 'human' ); ?>

render_content_table( 'ai' ); ?>
🔍
clear_history(); echo '

' . esc_html__( 'Scan history cleared.', 'ai-explainer-pro' ) . '

'; } } private function render_content_table( $type ) { global $wpdb; if ( 'human' === $type ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregate read on postmeta for dashboard table. $results = $wpdb->get_results( $wpdb->prepare( "SELECT p.ID, p.post_title, pm.meta_value as human_score FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_ai_explainer_human_score' WHERE p.post_status = 'publish' ORDER BY CAST(pm.meta_value AS DECIMAL(5,3)) DESC LIMIT %d", 10 ) ); } else { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregate read on postmeta for dashboard table. $results = $wpdb->get_results( $wpdb->prepare( "SELECT p.ID, p.post_title, pm.meta_value as human_score FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_ai_explainer_human_score' WHERE p.post_status = 'publish' ORDER BY CAST(pm.meta_value AS DECIMAL(5,3)) ASC LIMIT %d", 10 ) ); } if ( empty( $results ) ) { echo '

' . esc_html__( 'No data available.', 'ai-explainer-pro' ) . '

'; return; } ?> human_score ); $pct = round( $score * 100 ); if ( $score >= 0.7 ) { $cls = 'high'; $label = __( 'Human', 'ai-explainer-pro' ); } elseif ( $score >= 0.4 ) { $cls = 'medium'; $label = __( 'Uncertain', 'ai-explainer-pro' ); } else { $cls = 'low'; $label = __( 'AI', 'ai-explainer-pro' ); } ?>
post_title ); ?> %
prefix . 'ai_explainer_scan_history'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Plugin-owned table, name built from $wpdb->prefix; user-triggered admin action to truncate plugin history. $wpdb->query( "TRUNCATE TABLE {$table}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk delete of plugin-owned post meta; admin action. $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ('_ai_explainer_scanned_date','_ai_explainer_human_score','_ai_explainer_ai_score','_ai_explainer_detection_data')" ); } private function ensure_history_table() { global $wpdb; $table = $wpdb->prefix . 'ai_explainer_scan_history'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Existence check is one-off per page load. if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table ) ) !== $table ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $charset = $wpdb->get_charset_collate(); dbDelta( "CREATE TABLE {$table} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, scan_date datetime NOT NULL, total_scanned int(11) DEFAULT 0, scan_results longtext, user_id bigint(20) DEFAULT 0, PRIMARY KEY (id), KEY scan_date (scan_date) ) {$charset};" ); } } }