Changeset 3791852
- Timestamp:
- 11/09/2026 05:34:27 AM (less than one hour ago)
- Location:
- edgeshaping-lite/trunk
- Files:
-
- 13 edited
-
admin/class-admin.php (modified) (5 diffs)
-
edgeshaping.php (modified) (4 diffs)
-
includes/class-aggregator.php (modified) (27 diffs)
-
includes/class-ahqg.php (modified) (2 diffs)
-
includes/class-ahtg.php (modified) (2 diffs)
-
includes/class-bot-dictionary.php (modified) (2 diffs)
-
includes/class-bot-ipranges.php (modified) (23 diffs)
-
includes/class-cache-bypass.php (modified) (1 diff)
-
includes/class-cdn-edges.php (modified) (2 diffs)
-
includes/class-gsc.php (modified) (5 diffs)
-
includes/class-matrix.php (modified) (3 diffs)
-
includes/class-tracker.php (modified) (18 diffs)
-
readme.txt (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
edgeshaping-lite/trunk/admin/class-admin.php
r3735949 r3791852 7 7 add_menu_page( 'EdgeShaping Lite', 'EdgeShaping Lite', 'manage_options', 'edgeshaping-lite', [ __CLASS__, 'render_dashboard' ], 'dashicons-visibility', 80 ); 8 8 add_submenu_page( 'edgeshaping-lite', esc_html__( 'Dashboard', 'edgeshaping-lite' ), esc_html__( 'Dashboard', 'edgeshaping-lite' ), 'manage_options', 'edgeshaping-lite', [ __CLASS__, 'render_dashboard' ] ); 9 add_submenu_page( 'edgeshaping-lite', esc_html__( 'AI Ready', 'edgeshaping-lite' ), esc_html__( 'AI Ready', 'edgeshaping-lite' ), 'manage_options', 'edgeshaping-ai-ready', [ __CLASS__, 'render_ai_ready' ] ); 9 10 add_submenu_page( 'edgeshaping-lite', esc_html__( 'Access Log', 'edgeshaping-lite' ), esc_html__( 'Access Log', 'edgeshaping-lite' ), 'manage_options', 'edgeshaping-log', [ __CLASS__, 'render_log' ] ); 10 11 add_submenu_page( 'edgeshaping-lite', esc_html__( 'AHTG Matrix', 'edgeshaping-lite' ), esc_html__( 'AHTG Matrix', 'edgeshaping-lite' ), 'manage_options', 'edgeshaping-ahtg', [ __CLASS__, 'render_ahtg' ] ); … … 127 128 } 128 129 129 private static function render_date_filter( array $range, string $page ): void {130 private static function render_date_filter( array $range, string $page, array $presets = [] ): void { 130 131 $base = admin_url( 'admin.php?page=' . $page ); 131 $presets = [ '7days' => esc_html__( 'Last 7 days', 'edgeshaping-lite' ), '30days' => esc_html__( 'Last 30 days', 'edgeshaping-lite' ), 'this_month' => esc_html__( 'This month', 'edgeshaping-lite' ), 'last_month' => esc_html__( 'Last month', 'edgeshaping-lite' ), 'custom' => esc_html__( 'Custom range', 'edgeshaping-lite' ) ]; 132 if ( empty( $presets ) ) { 133 $presets = [ '7days' => esc_html__( 'Last 7 days', 'edgeshaping-lite' ), '30days' => esc_html__( 'Last 30 days', 'edgeshaping-lite' ), 'this_month' => esc_html__( 'This month', 'edgeshaping-lite' ), 'last_month' => esc_html__( 'Last month', 'edgeshaping-lite' ), 'custom' => esc_html__( 'Custom range', 'edgeshaping-lite' ) ]; 134 } 132 135 echo '<div class="es-date-filter">'; 133 136 echo '<div class="es-preset-buttons">'; … … 206 209 } 207 210 echo '</div></div></div>'; 211 } 212 213 214 private static function get_ai_ready_date_range(): array { 215 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 216 $preset = isset( $_GET['preset'] ) ? sanitize_text_field( wp_unslash( $_GET['preset'] ) ) : 'today'; 217 $today = current_time( 'Y-m-d' ); 218 switch ( $preset ) { 219 case '7days': 220 $from = gmdate( 'Y-m-d', strtotime( '-6 days', strtotime( $today ) ) ); 221 $to = $today; 222 break; 223 case 'custom': 224 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 225 $from = isset( $_GET['from'] ) ? sanitize_text_field( wp_unslash( $_GET['from'] ) ) : $today; 226 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 227 $to = isset( $_GET['to'] ) ? sanitize_text_field( wp_unslash( $_GET['to'] ) ) : $today; 228 $earliest = gmdate( 'Y-m-d', strtotime( '-29 days', strtotime( $today ) ) ); 229 if ( $to > $today ) $to = $today; 230 if ( $from < $earliest ) $from = $earliest; 231 if ( $from > $to ) $from = $to; 232 break; 233 default: 234 $preset = 'today'; 235 $from = $today; 236 $to = $today; 237 break; 238 } 239 return compact( 'preset', 'from', 'to' ); 240 } 241 242 public static function render_ai_ready(): void { 243 $range = self::get_ai_ready_date_range(); 244 $names = EdgeShaping_Tracker::get_bot_names( $range['from'], $range['to'] ); 245 246 echo '<div class="wrap edgeshaping-wrap">'; 247 echo '<h1>EdgeShaping Lite — ' . esc_html__( 'AI Ready', 'edgeshaping-lite' ) . '</h1>'; 248 echo '<p class="es-description">' . esc_html__( 'AI bots that reached this site in this period (including today, up to 30 days).', 'edgeshaping-lite' ) . '</p>'; 249 250 self::render_date_filter( $range, 'edgeshaping-ai-ready', [ 251 'today' => esc_html__( 'Today', 'edgeshaping-lite' ), 252 '7days' => esc_html__( 'Last 7 days', 'edgeshaping-lite' ), 253 'custom' => esc_html__( 'Custom range', 'edgeshaping-lite' ), 254 ] ); 255 256 if ( empty( $names ) ) { 257 echo '<p class="es-empty">' . esc_html__( 'No data available.', 'edgeshaping-lite' ) . '</p>'; 258 } else { 259 echo '<table class="es-table"><thead><tr><th>' . esc_html__( 'Bot Name', 'edgeshaping-lite' ) . '</th></tr></thead><tbody>'; 260 foreach ( $names as $name ) { 261 echo '<tr><td><strong>' . esc_html( $name ) . '</strong></td></tr>'; 262 } 263 echo '</tbody></table>'; 264 } 265 echo '</div>'; 208 266 } 209 267 … … 354 412 echo '<div class="es-panel es-ahqg-extra" style="margin-top:20px;">'; 355 413 echo '<h2>Inferred Path <span class="es-ahqg-quad-count">' . absint( count( $inferred ) ) . ' ' . esc_html__( 'pages', 'edgeshaping-lite' ) . '</span></h2>'; 356 echo '<p class="es-ahqg-extra-desc">'. esc_html__( 'URLs visited by AI but not in sitemap', 'edgeshaping-lite' ) .'('. esc_html__( 'spam/scan paths excluded', 'edgeshaping-lite' ) .')</p>';414 echo '<p class="es-ahqg-extra-desc">'. esc_html__( 'URLs visited by AI that are not published pages', 'edgeshaping-lite' ) .'('. esc_html__( 'spam/scan paths excluded', 'edgeshaping-lite' ) .')</p>'; 357 415 if ( empty( $inferred ) ) { 358 416 echo '<p class="es-empty">'. esc_html__( 'None', 'edgeshaping-lite' ) .'</p>'; … … 465 523 echo '<div class="es-panel es-ahqg-extra" style="margin-top:20px;">'; 466 524 echo '<h2>Inferred Path <span class="es-ahqg-quad-count">' . absint( count( $inferred ) ) . ' ' . esc_html__( 'pages', 'edgeshaping-lite' ) . '</span></h2>'; 467 echo '<p class="es-ahqg-extra-desc">' . esc_html__( 'URLs visited by AI but not in sitemap', 'edgeshaping-lite' ) . '(' . esc_html__( 'spam/scan paths excluded', 'edgeshaping-lite' ) . ')</p>';525 echo '<p class="es-ahqg-extra-desc">' . esc_html__( 'URLs visited by AI that are not published pages', 'edgeshaping-lite' ) . '(' . esc_html__( 'spam/scan paths excluded', 'edgeshaping-lite' ) . ')</p>'; 468 526 if ( empty( $inferred ) ) { 469 527 echo '<p class="es-empty">' . esc_html__( 'None', 'edgeshaping-lite' ) . '</p>'; -
edgeshaping-lite/trunk/edgeshaping.php
r3735949 r3791852 4 4 * Plugin URI: https://edgeshap.ing 5 5 * Description: Observe which AI bots visit which pages and when. WordPress implementation of the EdgeShaping framework by mare interno. 6 * Version: 2026.1 0.06 * Version: 2026.11.0 7 7 * Author: mare interno 8 8 * Author URI: https://mareinterno.com 9 9 * License: GPL-2.0+ 10 10 * Text Domain: edgeshaping-lite 11 * Requires at least: 6. 012 * Requires PHP: 7.411 * Requires at least: 6.9 12 * Requires PHP: 8.2 13 13 */ 14 14 15 15 if ( ! defined( 'ABSPATH' ) ) exit; 16 16 17 define( 'EDGESHAPING_VERSION', '2026.1 0.0' );17 define( 'EDGESHAPING_VERSION', '2026.11.0' ); 18 18 define( 'EDGESHAPING_DIR', plugin_dir_path( __FILE__ ) ); 19 19 define( 'EDGESHAPING_URL', plugin_dir_url( __FILE__ ) ); … … 48 48 49 49 add_action( 'init', [ 'EdgeShaping_Aggregator', 'maybe_migrate_categories' ], 1 ); 50 add_action( 'init', [ 'EdgeShaping_Aggregator', 'maybe_add_is_page_column' ], 1 ); 50 51 add_action( 'init', [ 'EdgeShaping_Tracker', 'observe' ] ); 51 52 add_action( 'rest_api_init', [ 'EdgeShaping_Tracker', 'register_beacon_route' ] ); … … 84 85 } 85 86 } 87 88 89 EdgeShaping_Aggregator::maybe_prepare_path_hash(); 90 91 92 EdgeShaping_Aggregator::maybe_restore_unique_key(); 93 94 EdgeShaping_Aggregator::maybe_migrate_is_page(); 86 95 } ); 87 96 … … 101 110 header( 'Pragma: no-cache' ); 102 111 103 // phpcs:disable WordPress.WP.AlternativeFunctions -- php://output requires direct file functions 112 113 // phpcs:disable WordPress.WP.AlternativeFunctions 104 114 $out = fopen( 'php://output', 'w' ); 105 115 -
edgeshaping-lite/trunk/includes/class-aggregator.php
r3735949 r3791852 18 18 path_hash CHAR(32) NOT NULL, 19 19 verified TINYINT(1) NOT NULL DEFAULT 0, 20 is_page TINYINT(1) NULL DEFAULT NULL, 20 21 cnt INT UNSIGNED NOT NULL DEFAULT 0, 21 22 PRIMARY KEY (id), 22 23 UNIQUE KEY idx_unique (agg_date, bot_name, path_hash, verified), 23 24 INDEX idx_agg_date (agg_date), 25 INDEX idx_path_hash (path_hash), 24 26 INDEX idx_bot_category (bot_category) 25 27 ) {$charset};"; … … 28 30 29 31 30 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter32 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 31 33 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 32 34 return $exists === $table; … … 46 48 47 49 48 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter50 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 49 51 $has_column = $wpdb->get_var( $wpdb->prepare( 50 52 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', … … 52 54 ) ); 53 55 if ( ! $has_column ) { 54 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter55 $wpdb->query( "ALTER TABLE {$table} ADD COLUMN verified TINYINT(1) NOT NULL DEFAULT 0 AFTER path_hash");56 } 57 58 59 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter60 $wpdb->query( "ALTER TABLE {$table} DROP INDEX idx_unique");61 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter62 $wpdb->query( "ALTER TABLE {$table} ADD UNIQUE KEY idx_unique (agg_date, bot_name, path_hash, verified)");56 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 57 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD COLUMN verified TINYINT(1) NOT NULL DEFAULT 0 AFTER path_hash', $table ) ); 58 } 59 60 61 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 62 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i DROP INDEX idx_unique', $table ) ); 63 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 64 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD UNIQUE KEY idx_unique (agg_date, bot_name, path_hash, verified)', $table ) ); 63 65 64 66 65 67 if ( $boundary ) { 66 $sql = $wpdb->prepare( "UPDATE {$table} SET verified = 1 WHERE agg_date <= %s", $boundary ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter 67 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 68 $wpdb->query( $sql ); 68 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 69 $wpdb->query( $wpdb->prepare( 'UPDATE %i SET verified = 1 WHERE agg_date <= %s', $table, $boundary ) ); 69 70 } 70 71 … … 77 78 $table = $wpdb->prefix . self::TABLE; 78 79 79 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter80 $bot_names = $wpdb->get_col( "SELECT DISTINCT bot_name FROM {$table} WHERE bot_category = ''");80 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 81 $bot_names = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT bot_name FROM %i WHERE bot_category = ''", $table ) ); 81 82 if ( empty( $bot_names ) ) return; 82 83 … … 84 85 $category = EdgeShaping_Bot_Dictionary::get_category( $bot_name ); 85 86 if ( '' === $category ) continue; 86 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared87 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 87 88 $wpdb->query( $wpdb->prepare( 88 "UPDATE {$table} SET bot_category = %s WHERE bot_name = %s AND bot_category = ''", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared89 $ category, $bot_name89 "UPDATE %i SET bot_category = %s WHERE bot_name = %s AND bot_category = ''", 90 $table, $category, $bot_name 90 91 ) ); 91 92 } … … 102 103 103 104 104 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter105 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 105 106 $log_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $log_table ) ); 106 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter107 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 107 108 $agg_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $agg_table ) ); 108 109 if ( $log_exists !== $log_table || $agg_exists !== $agg_table ) return; … … 110 111 EdgeShaping_Tracker::maybe_add_category_column(); 111 112 112 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter113 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 113 114 $agg_has = $wpdb->get_var( $wpdb->prepare( 114 115 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', … … 116 117 ) ); 117 118 if ( ! $agg_has ) { 118 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter119 $wpdb->query( "ALTER TABLE {$agg_table} ADD COLUMN bot_category VARCHAR(50) NOT NULL DEFAULT '' AFTER bot_name");120 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter121 $wpdb->query( "ALTER TABLE {$agg_table} ADD INDEX idx_bot_category (bot_category)");119 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 120 $wpdb->query( $wpdb->prepare( "ALTER TABLE %i ADD COLUMN bot_category VARCHAR(50) NOT NULL DEFAULT '' AFTER bot_name", $agg_table ) ); 121 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 122 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD INDEX idx_bot_category (bot_category)', $agg_table ) ); 122 123 } 123 124 … … 127 128 128 129 foreach ( [ $log_table, $agg_table ] as $check_table ) { 129 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter130 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 130 131 $has = $wpdb->get_var( $wpdb->prepare( 131 132 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', … … 137 138 138 139 foreach ( [ $log_table, $agg_table ] as $check_table ) { 139 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter140 $remaining = $wpdb->get_col( "SELECT DISTINCT bot_name FROM {$check_table} WHERE bot_category = ''");140 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 141 $remaining = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT bot_name FROM %i WHERE bot_category = ''", $check_table ) ); 141 142 if ( ! is_array( $remaining ) ) return; 142 143 foreach ( $remaining as $bot_name ) { … … 149 150 150 151 152 public static function maybe_add_is_page_column(): void { 153 global $wpdb; 154 155 if ( get_option( 'edgeshaping_is_page_column_added' ) ) return; 156 157 $table = $wpdb->prefix . self::TABLE; 158 159 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 160 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 161 if ( $exists !== $table ) return; 162 163 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 164 $has = $wpdb->get_var( $wpdb->prepare( 165 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', 166 DB_NAME, $table, 'is_page' 167 ) ); 168 if ( ! $has ) { 169 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 170 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD COLUMN is_page TINYINT(1) NULL DEFAULT NULL AFTER verified', $table ) ); 171 } 172 173 174 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 175 $has = $wpdb->get_var( $wpdb->prepare( 176 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', 177 DB_NAME, $table, 'is_page' 178 ) ); 179 if ( $has ) { 180 update_option( 'edgeshaping_is_page_column_added', 1 ); 181 } 182 } 183 184 185 public static function is_published_page( string $path ): bool { 186 static $memo = []; 187 188 if ( array_key_exists( $path, $memo ) ) return $memo[ $path ]; 189 190 if ( '/' === $path ) { 191 $memo[ $path ] = true; 192 return true; 193 } 194 195 $parts = wp_parse_url( home_url() ); 196 $base = $parts['scheme'] . '://' . $parts['host']; 197 if ( ! empty( $parts['port'] ) ) { 198 $base .= ':' . $parts['port']; 199 } 200 201 $id = url_to_postid( $base . $path ); 202 if ( 0 === (int) $id ) { 203 $memo[ $path ] = false; 204 return false; 205 } 206 207 $memo[ $path ] = ( 'publish' === get_post_status( $id ) ); 208 return $memo[ $path ]; 209 } 210 211 212 public static function maybe_prepare_path_hash(): void { 213 global $wpdb; 214 215 if ( get_option( 'edgeshaping_path_hash_prepared' ) ) return; 216 217 $table = $wpdb->prefix . self::TABLE; 218 219 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 220 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 221 if ( $exists !== $table ) return; 222 223 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 224 $wpdb->query( $wpdb->prepare( "UPDATE %i SET path_hash = MD5(path) WHERE path_hash = ''", $table ) ); 225 226 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 227 $has_index = $wpdb->get_var( $wpdb->prepare( 228 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND INDEX_NAME = %s', 229 DB_NAME, $table, 'idx_path_hash' 230 ) ); 231 if ( ! $has_index ) { 232 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 233 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD INDEX idx_path_hash (path_hash)', $table ) ); 234 } 235 236 237 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 238 $empty = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE path_hash = ''", $table ) ); 239 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 240 $has_index = $wpdb->get_var( $wpdb->prepare( 241 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND INDEX_NAME = %s', 242 DB_NAME, $table, 'idx_path_hash' 243 ) ); 244 if ( null !== $empty && 0 === (int) $empty && $has_index ) { 245 update_option( 'edgeshaping_path_hash_prepared', 1 ); 246 } 247 } 248 249 250 public static function maybe_restore_unique_key(): void { 251 global $wpdb; 252 253 if ( get_option( 'edgeshaping_unique_key_restored' ) ) return; 254 255 $table = $wpdb->prefix . self::TABLE; 256 257 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 258 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 259 if ( $exists !== $table ) return; 260 261 if ( self::has_unique_key( $table ) ) { 262 update_option( 'edgeshaping_unique_key_restored', 1 ); 263 return; 264 } 265 266 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 267 $empty = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE path_hash = ''", $table ) ); 268 if ( null === $empty || 0 !== (int) $empty ) return; 269 270 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 271 $dup = $wpdb->get_var( $wpdb->prepare( 272 'SELECT 1 FROM %i GROUP BY agg_date, bot_name, path_hash, verified HAVING COUNT(*) > 1 LIMIT 1', 273 $table 274 ) ); 275 if ( null !== $dup ) return; 276 277 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 278 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD UNIQUE KEY idx_unique (agg_date, bot_name, path_hash, verified)', $table ) ); 279 280 281 if ( self::has_unique_key( $table ) ) { 282 update_option( 'edgeshaping_unique_key_restored', 1 ); 283 } 284 } 285 286 287 private static function has_unique_key( string $table ): bool { 288 global $wpdb; 289 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 290 $count = $wpdb->get_var( $wpdb->prepare( 291 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND INDEX_NAME = %s', 292 DB_NAME, $table, 'idx_unique' 293 ) ); 294 return (int) $count > 0; 295 } 296 297 298 public static function maybe_migrate_is_page(): void { 299 global $wpdb; 300 301 if ( get_option( 'edgeshaping_is_page_migrated' ) ) return; 302 303 $table = $wpdb->prefix . self::TABLE; 304 305 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 306 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 307 if ( $exists !== $table ) return; 308 309 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 310 $has = $wpdb->get_var( $wpdb->prepare( 311 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', 312 DB_NAME, $table, 'is_page' 313 ) ); 314 if ( ! $has ) return; 315 316 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 317 $paths = $wpdb->get_col( $wpdb->prepare( 'SELECT DISTINCT path FROM %i WHERE is_page IS NULL LIMIT 500', $table ) ); 318 if ( is_array( $paths ) ) { 319 foreach ( $paths as $path ) { 320 $path = (string) $path; 321 $value = self::is_published_page( $path ) ? 1 : 0; 322 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 323 $wpdb->query( $wpdb->prepare( 324 "UPDATE %i SET is_page = %d WHERE path_hash = %s AND is_page IS NULL", 325 $table, $value, md5( $path ) 326 ) ); 327 } 328 } 329 330 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 331 $remaining = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE is_page IS NULL', $table ) ); 332 if ( null !== $remaining && 0 === (int) $remaining ) { 333 update_option( 'edgeshaping_is_page_migrated', 1 ); 334 } 335 } 336 337 151 338 public static function run_daily( ?string $date = null ): void { 152 339 global $wpdb; … … 156 343 $agg_table = $wpdb->prefix . self::TABLE; 157 344 158 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter159 $wpdb->query( $wpdb->prepare( "DELETE FROM {$agg_table} WHERE agg_date = %s", $date ) );160 161 162 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter345 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 346 $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE agg_date = %s', $agg_table, $date ) ); 347 348 349 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 163 350 $rows = $wpdb->get_results( $wpdb->prepare( 164 "SELECT bot_name, bot_category, request_url, ip, COUNT(*) AS cnt FROM {$log_table} " // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared351 'SELECT bot_name, bot_category, request_url, ip, COUNT(*) AS cnt FROM %i ' 165 352 . 'WHERE visited_at BETWEEN %s AND %s GROUP BY bot_name, bot_category, request_url, ip', 166 $ date . ' 00:00:00', $date . ' 23:59:59'353 $log_table, $date . ' 00:00:00', $date . ' 23:59:59' 167 354 ) ); 168 355 … … 242 429 'path_hash' => md5( $item['path'] ), 243 430 'verified' => (int) $item['verified'], 431 'is_page' => self::is_published_page( $item['path'] ) ? 1 : 0, 244 432 'cnt' => $item['cnt'], 245 433 ], 246 [ '%s', '%s', '%s', '%s', '%s', '%d', '%d' ]434 [ '%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d' ] 247 435 ); 248 436 } … … 265 453 266 454 global $wpdb; 267 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter268 $oldest = $wpdb->get_var( "SELECT DATE(MIN(visited_at)) FROM {$wpdb->prefix}edgeshaping_log");455 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 456 $oldest = $wpdb->get_var( $wpdb->prepare( 'SELECT DATE(MIN(visited_at)) FROM %i', $wpdb->prefix . 'edgeshaping_log' ) ); 269 457 if ( ! $oldest ) { 270 458 update_option( 'edgeshaping_last_aggregated_date', $target ); … … 302 490 303 491 public static function get_counts_by_path( array $bot_names, string $date_from, string $date_to ): array { 492 return self::read_counts_by_path( $bot_names, $date_from, $date_to, 1 ); 493 } 494 495 496 public static function get_inferred_counts( array $bot_names, string $date_from, string $date_to ): array { 497 return self::read_counts_by_path( $bot_names, $date_from, $date_to, 0 ); 498 } 499 500 501 private static function read_counts_by_path( array $bot_names, string $date_from, string $date_to, int $is_page ): array { 304 502 global $wpdb; 305 503 if ( empty( $bot_names ) ) return []; … … 308 506 if ( $date_from > $date_to ) return []; 309 507 508 $is_page = $is_page ? 1 : 0; 310 509 $result = []; 311 510 $table = $wpdb->prefix . self::TABLE; 312 511 $placeholders = implode( ',', array_fill( 0, count( $bot_names ), '%s' ) ); 313 $args = array_merge( $bot_names, [ $date_from, $date_to ] ); 314 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 315 $sql = "SELECT path, SUM(cnt) AS total FROM {$table} WHERE bot_name IN ({$placeholders}) AND agg_date BETWEEN %s AND %s AND verified = 1 GROUP BY path"; 512 $args = array_merge( [ $table ], $bot_names, [ $date_from, $date_to, $is_page ] ); 513 $sql = "SELECT path, SUM(cnt) AS total FROM %i WHERE bot_name IN ({$placeholders}) AND agg_date BETWEEN %s AND %s AND verified = 1 AND is_page = %d GROUP BY path"; 316 514 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 317 515 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); … … 340 538 } 341 539 342 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1' ];343 $args = [ $ date_from, $date_to ];540 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1', 'is_page = 1' ]; 541 $args = [ $table, $date_from, $date_to ]; 344 542 345 543 $cats = array_filter( array_map( 'trim', explode( ',', $category ) ) ); … … 350 548 $where_sql = implode( ' AND ', $where ); 351 549 352 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 353 $sql = "SELECT path, bot_name, SUM(cnt) AS total FROM {$table} WHERE {$where_sql} GROUP BY path, bot_name"; 550 $sql = "SELECT path, bot_name, SUM(cnt) AS total FROM %i WHERE {$where_sql} GROUP BY path, bot_name"; 354 551 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 355 552 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); … … 380 577 if ( $date_from > $date_to ) return []; 381 578 382 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1' ];383 $args = [ $ date_from, $date_to ];579 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1', 'is_page = 1' ]; 580 $args = [ $table, $date_from, $date_to ]; 384 581 $cats = array_filter( array_map( 'trim', explode( ',', $category ) ) ); 385 582 if ( $cats ) { … … 389 586 $where_sql = implode( ' AND ', $where ); 390 587 391 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 392 $sql = "SELECT path, bot_name, bot_category, cnt, agg_date FROM {$table} WHERE {$where_sql}"; 588 $sql = "SELECT path, bot_name, bot_category, cnt, agg_date FROM %i WHERE {$where_sql}"; 393 589 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 394 590 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); … … 417 613 if ( $date_from > $date_to ) return []; 418 614 419 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1' ];420 $args = [ $ date_from, $date_to ];615 $where = [ 'agg_date BETWEEN %s AND %s', 'verified = 1', 'is_page = 1' ]; 616 $args = [ $table, $date_from, $date_to ]; 421 617 $cats = array_filter( array_map( 'trim', explode( ',', $category ) ) ); 422 618 if ( $cats ) { … … 426 622 $where_sql = implode( ' AND ', $where ); 427 623 428 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 429 $sql = "SELECT path, cnt, agg_date FROM {$table} WHERE {$where_sql}"; 624 $sql = "SELECT path, cnt, agg_date FROM %i WHERE {$where_sql}"; 430 625 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 431 626 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); … … 452 647 if ( $date_from > $date_to ) return []; 453 648 454 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 455 $sql = "SELECT path, bot_name, bot_category, cnt, agg_date FROM {$table} WHERE agg_date BETWEEN %s AND %s AND verified = 1"; 456 // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared 457 $rows = $wpdb->get_results( $wpdb->prepare( $sql, $date_from, $date_to ) ); 649 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 650 $rows = $wpdb->get_results( $wpdb->prepare( 651 'SELECT path, bot_name, bot_category, cnt, agg_date FROM %i WHERE agg_date BETWEEN %s AND %s AND verified = 1 AND is_page = 1', 652 $table, $date_from, $date_to 653 ) ); 458 654 459 655 $agg = []; … … 485 681 global $wpdb; 486 682 $table = $wpdb->prefix . self::TABLE; 487 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter488 $cats = $wpdb->get_col( "SELECT DISTINCT bot_category FROM {$table} WHERE bot_category != ''");683 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 684 $cats = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT bot_category FROM %i WHERE bot_category != ''", $table ) ); 489 685 sort( $cats ); 490 686 return $cats; … … 496 692 $table = $wpdb->prefix . self::TABLE; 497 693 498 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter694 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 499 695 $total = (int) $wpdb->get_var( $wpdb->prepare( 500 "SELECT COUNT(*) FROM {$table} WHERE agg_date BETWEEN %s AND %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared501 $ date_from, $date_to502 ) ); 503 504 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter696 "SELECT COUNT(*) FROM %i WHERE agg_date BETWEEN %s AND %s", 697 $table, $date_from, $date_to 698 ) ); 699 700 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 505 701 $rows = $wpdb->get_results( $wpdb->prepare( 506 "SELECT agg_date, bot_name, path, verified, cnt FROM {$table} WHERE agg_date BETWEEN %s AND %s ORDER BY agg_date DESC, bot_name ASC, path ASC, verified ASC LIMIT %d OFFSET %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared507 $ date_from, $date_to, $limit, $offset702 "SELECT agg_date, bot_name, path, verified, cnt FROM %i WHERE agg_date BETWEEN %s AND %s ORDER BY agg_date DESC, bot_name ASC, path ASC, verified ASC LIMIT %d OFFSET %d", 703 $table, $date_from, $date_to, $limit, $offset 508 704 ) ); 509 705 … … 527 723 global $wpdb; 528 724 $table = $wpdb->prefix . self::TABLE; 529 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter530 $wpdb->query( "DROP TABLE IF EXISTS {$table}");725 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 726 $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); 531 727 delete_option( 'edgeshaping_last_aggregated_date' ); 532 728 } -
edgeshaping-lite/trunk/includes/class-ahqg.php
r3735949 r3791852 7 7 return EdgeShaping_Matrix::build( 8 8 self::get_ai_counts( $date_from, $date_to ), 9 EdgeShaping_GSC::get_clicks( $date_from, $date_to ) 9 EdgeShaping_GSC::get_clicks( $date_from, $date_to ), 10 self::get_inferred_counts( $date_from, $date_to ) 10 11 ); 11 12 } … … 15 16 $bots = EdgeShaping_Bot_Dictionary::get_ahqg_bots(); 16 17 return EdgeShaping_Aggregator::get_counts_by_path( $bots, $date_from, $date_to ); 18 } 19 20 21 private static function get_inferred_counts( string $date_from, string $date_to ): array { 22 $bots = EdgeShaping_Bot_Dictionary::get_ahqg_bots(); 23 return EdgeShaping_Aggregator::get_inferred_counts( $bots, $date_from, $date_to ); 17 24 } 18 25 -
edgeshaping-lite/trunk/includes/class-ahtg.php
r3735949 r3791852 7 7 return EdgeShaping_Matrix::build( 8 8 self::get_ai_counts( $date_from, $date_to ), 9 EdgeShaping_Tracker::get_human_pv( $date_from, $date_to ) 9 EdgeShaping_Tracker::get_human_pv( $date_from, $date_to ), 10 self::get_inferred_counts( $date_from, $date_to ) 10 11 ); 11 12 } … … 17 18 } 18 19 20 21 private static function get_inferred_counts( string $date_from, string $date_to ): array { 22 $bots = EdgeShaping_Bot_Dictionary::get_ahqg_bots(); 23 return EdgeShaping_Aggregator::get_inferred_counts( $bots, $date_from, $date_to ); 24 } 25 19 26 public static function label( string $quad ): string { 20 27 return EdgeShaping_Matrix::label( $quad ); -
edgeshaping-lite/trunk/includes/class-bot-dictionary.php
r3735949 r3791852 45 45 'DuckAssistBot' => [ 'company' => 'DuckDuckGo', 'name' => 'DuckAssist Bot', 'category' => 'search_rag', 'tier' => self::TIER_OFFICIAL ], 46 46 47 'ElevenlabsBot' => [ 'company' => 'ElevenLabs', 'name' => 'ElevenLabs Bot', 'category' => 'user_trigger', 'tier' => self::TIER_OFFICIAL ], 48 'ElevenlabsCrawler' => [ 'company' => 'ElevenLabs', 'name' => 'ElevenLabs Crawler', 'category' => 'learning', 'tier' => self::TIER_OFFICIAL ], 49 47 50 'ExaSearchBot' => [ 'company' => 'Exa', 'name' => 'Exa Search Bot', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], 51 'ExaUser' => [ 'company' => 'Exa', 'name' => 'Exa User', 'category' => 'user_trigger', 'tier' => self::TIER_OFFICIAL ], 48 52 49 53 'AdsBot-Google' => [ 'company' => 'Google', 'name' => 'Google Ads Bot', 'category' => 'ads', 'tier' => self::TIER_OFFICIAL ], … … 59 63 60 64 'IbouBot' => [ 'company' => 'Ibou', 'name' => 'Ibou AI Search', 'category' => 'search_rag', 'tier' => self::TIER_OFFICIAL ], 65 'ibou-discovery' => [ 'company' => 'Ibou', 'name' => 'Ibou Discovery', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], 66 'ibou-images' => [ 'company' => 'Ibou', 'name' => 'Ibou Images', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], 67 'ibou-news' => [ 'company' => 'Ibou', 'name' => 'Ibou News', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], 68 'ibou-search' => [ 'company' => 'Ibou', 'name' => 'Ibou Search', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], 69 70 'KeenableBot' => [ 'company' => 'Keenable.ai, Inc.', 'name' => 'Keenable Bot', 'category' => 'search_rag', 'tier' => self::TIER_OFFICIAL ], 61 71 62 72 'LinerBot' => [ 'company' => 'Liner', 'name' => 'Liner AI', 'category' => 'crawl', 'tier' => self::TIER_OFFICIAL ], -
edgeshaping-lite/trunk/includes/class-bot-ipranges.php
r3735949 r3791852 29 29 'IbouBot' => 'ibou_bot', 30 30 'IsonSearchBot' => 'ison_searchbot', 31 'KeenableBot' => 'keenable_bot', 31 32 'Kimi-SearchBot' => 'kimi_searchbot', 32 33 'Kimi-User' => 'kimi_user', 33 34 'KimiBot' => 'kimi_bot', 34 'LinerBot' => 'liner_bot',35 35 'LohiSoftBot' => 'lohisoft_bot', 36 36 'MistralAI-Index' => 'mistral_index', … … 46 46 'bingbot' => 'bing_bingbot', 47 47 'facebookexternalhit' => 'meta_asn', 48 'ibou-discovery' => 'ibou_media', 49 'ibou-news' => 'ibou_media', 50 'ibou-search' => 'ibou_search', 48 51 'meta-externalads' => 'meta_asn', 49 52 'meta-externalagent' => 'meta_asn', … … 3192 3195 ], 3193 3196 'anthropic_all' => [ 3194 [272243269, 272243269], 3195 [316796644, 316796644], 3196 [316924671, 316924671], 3197 [339753424, 339753439], 3198 [342240992, 342241007], 3199 [571154975, 571154975], 3200 [576040098, 576040098], 3201 [580317519, 580317519], 3197 [580418700, 580418700], 3198 [580457918, 580457918], 3199 [581049122, 581049122], 3200 [581064294, 581064294], 3201 [581065318, 581065318], 3202 [581070670, 581070670], 3203 [581081415, 581081415], 3202 3204 [581091153, 581091153], 3203 3205 [581101278, 581101278], 3204 3206 [581104711, 581104711], 3205 [582388831, 582388831], 3206 [582394255, 582394255], 3207 [582408731, 582408731], 3208 [582409301, 582409301], 3209 [582409765, 582409765], 3210 [582410663, 582410663], 3211 [582410903, 582410903], 3212 [582410973, 582410973], 3213 [582642851, 582642851], 3214 [601693614, 601693614], 3215 [603281903, 603281903], 3216 [603303809, 603303809], 3217 [679241008, 679241023], 3218 [2288758992, 2288758992], 3207 [582679556, 582679556], 3208 [2286915579, 2286915579], 3209 [2287146199, 2287146199], 3210 [2570964992, 2570969087], 3211 [2689558528, 2689560575], 3219 3212 [3628718080, 3628719103], 3220 3213 ], … … 3803 3796 [578031872, 578032031], 3804 3797 [578032128, 578032351], 3805 [578032384, 5780327 35],3806 [578032896, 578033 279],3798 [578032384, 578032767], 3799 [578032896, 578033311], 3807 3800 [578033408, 578033535], 3808 3801 [578034688, 578035071], … … 3844 3837 [1806879616, 1806879743], 3845 3838 [1806884864, 1806885375], 3839 [2289862656, 2289862751], 3846 3840 ], 3847 3841 'google_user_triggered_google' => [ … … 3856 3850 [1249760768, 1249761279], 3857 3851 [2398756864, 2398757279], 3858 [2902307840, 29023079 03],3852 [2902307840, 2902307935], 3859 3853 [2902308096, 2902308511], 3860 3854 [2902308608, 2902308863], 3861 3855 [3232892928, 3232893087], 3862 [3232893184, 32328935 67],3856 [3232893184, 3232893599], 3863 3857 [3232893696, 3232894175], 3864 3858 [3232894208, 3232894495], … … 3868 3862 [3648111616, 3648111871], 3869 3863 ], 3864 'ibou_media' => [ 3865 [2746018592, 2746018623], 3866 ], 3867 'ibou_search' => [ 3868 [3169920512, 3169920767], 3869 ], 3870 3870 'ison_searchbot' => [ 3871 3871 [1735987676, 1735987676], 3872 [1738306407, 1738306407], 3872 [1737934249, 1737934249], 3873 ], 3874 'keenable_bot' => [ 3875 [571500091, 571500091], 3876 [573234952, 573234952], 3877 [574104761, 574104761], 3878 [574153928, 574153928], 3879 [574157134, 574157134], 3880 [574851913, 574851913], 3881 [578540162, 578540162], 3882 [578550513, 578550513], 3883 [579108881, 579108881], 3884 [579224957, 579224957], 3885 [599541115, 599541115], 3886 [599547018, 599547018], 3887 [599579798, 599579798], 3888 [599926666, 599926666], 3889 [600442542, 600442542], 3890 [600445005, 600445005], 3891 [600448528, 600448528], 3892 [601812747, 601812747], 3893 [602417899, 602417899], 3894 [603919901, 603919901], 3895 [603949630, 603949630], 3896 [1754986078, 1754986078], 3897 [1757769726, 1757769726], 3898 [1757860114, 1757860114], 3899 [2194896541, 2194896541], 3900 [2286012356, 2286012356], 3901 [2286355477, 2286355477], 3902 [2286389324, 2286389324], 3903 [2289167190, 2289167190], 3904 [2289347745, 2289347745], 3873 3905 ], 3874 3906 'kimi_bot' => [ … … 3889 3921 [793771306, 793771306], 3890 3922 [793771355, 793771355], 3891 ],3892 'liner_bot' => [3893 [571489880, 571489880],3894 [572331825, 572331825],3895 [572368558, 572368558],3896 [572389706, 572389706],3897 [574751062, 574751062],3898 [578358084, 578358084],3899 [579261752, 579261752],3900 [581683130, 581683130],3901 [601933340, 601933340],3902 [602047433, 602047433],3903 3923 ], 3904 3924 'lohisoft_bot' => [ … … 3934 3954 [520962048, 520978431], 3935 3955 [759179264, 759180287], 3936 [965541888, 96554 8543],3956 [965541888, 965549567], 3937 3957 [965738496, 966000639], 3938 3958 [1121751040, 1121755135], … … 3981 4001 [81971216, 81971231], 3982 4002 [81977888, 81977903], 3983 [159449088, 159 481855],4003 [159449088, 159514623], 3984 4004 [161489552, 161489567], 3985 4005 [161489936, 161489951], … … 4033 4053 [349070784, 349070799], 4034 4054 [349361088, 349361103], 4055 [349454032, 349454047], 4035 4056 [349682640, 349682655], 4036 4057 [349690752, 349690767], … … 4039 4060 [349839088, 349839103], 4040 4061 [349915072, 349915087], 4062 [349938112, 349938127], 4041 4063 [349943904, 349943919], 4042 4064 [350102720, 350102735], … … 4047 4069 [351929984, 351929999], 4048 4070 [351963200, 351963215], 4071 [352242128, 352242143], 4049 4072 [392335024, 392335039], 4050 4073 [392346176, 392346191], … … 4059 4082 [676650448, 676650479], 4060 4083 [678709712, 678709727], 4084 [678896880, 678896895], 4061 4085 [679256320, 679256335], 4062 4086 [819800240, 819800255], … … 4088 4112 [884903488, 884903503], 4089 4113 [884915728, 884915743], 4114 [884931440, 884931455], 4090 4115 [887180240, 887180255], 4091 4116 [887561776, 887561791], … … 4135 4160 [2279360976, 2279360991], 4136 4161 [2279361008, 2279361023], 4162 [2279498528, 2279498543], 4137 4163 [2280489936, 2280489951], 4138 4164 [2280490288, 2280490303], … … 4152 4178 [2897711072, 2897711087], 4153 4179 [2897731200, 2897731215], 4154 [2897854896, 2897854911],4155 4180 [2898292944, 2898292959], 4156 4181 [2898632896, 2898632911], … … 4237 4262 ], 4238 4263 'perplexity_bot' => [ 4239 [64191671, 64191671],4240 4264 [64940271, 64940271], 4241 4265 [65027629, 65027629], 4242 [65506155, 65506155], 4243 [308347364, 308347367], 4266 [308347364, 308347364], 4244 4267 [308349280, 308349287], 4245 4268 [315776235, 315776235], … … 4247 4270 ], 4248 4271 'perplexity_user' => [ 4249 [308352256, 308352259],4250 4272 [308357968, 308357975], 4251 4273 [583115572, 583115572], … … 4335 4357 ["\x26\x00\x19\x00\x00\x00\x02\x60\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\x64\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4336 4358 ["\x26\x00\x19\x00\x00\x00\x02\x70\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\x76\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4337 ["\x26\x00\x19\x00\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\x8 2\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"],4359 ["\x26\x00\x19\x00\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\x83\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4338 4360 ["\x26\x00\x19\x00\x00\x00\x02\x90\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\x97\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4339 ["\x26\x00\x19\x00\x00\x00\x02\xA0\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\xA 3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"],4361 ["\x26\x00\x19\x00\x00\x00\x02\xA0\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\xA4\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4340 4362 ["\x26\x00\x19\x00\x00\x00\x02\xB0\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\xB3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4341 4363 ["\x26\x00\x19\x00\x00\x00\x02\xC0\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x02\xC6\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], … … 4357 4379 ["\x26\x00\x19\x00\x00\x00\x03\xC3\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x03\xC4\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4358 4380 ["\x26\x00\x19\x00\x00\x00\x03\xD0\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x03\xD7\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4381 ["\x26\x00\x19\x00\x00\x00\x04\x10\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x19\x00\x00\x00\x04\x12\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4359 4382 ], 4360 4383 'google_user_triggered_google' => [ … … 4365 4388 ["\x20\x01\x48\x60\x48\x01\x40\x1A\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x1C\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4366 4389 ["\x20\x01\x48\x60\x48\x01\x40\x20\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x2B\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4367 ["\x20\x01\x48\x60\x48\x01\x40\x30\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x3E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4368 ["\x20\x01\x48\x60\x48\x01\x40\x40\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x6E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4390 ["\x20\x01\x48\x60\x48\x01\x40\x30\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x6E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4369 4391 ["\x20\x01\x48\x60\x48\x01\x40\x70\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x8B\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4370 4392 ["\x20\x01\x48\x60\x48\x01\x40\x90\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\x96\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], … … 4374 4396 ["\x20\x01\x48\x60\x48\x01\x40\xD0\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x40\xE3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4375 4397 ["\x20\x01\x48\x60\x48\x01\x40\xF0\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x07\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4376 ["\x20\x01\x48\x60\x48\x01\x41\x10\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x1 3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"],4398 ["\x20\x01\x48\x60\x48\x01\x41\x10\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x14\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4377 4399 ["\x20\x01\x48\x60\x48\x01\x41\x20\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x36\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4378 4400 ["\x20\x01\x48\x60\x48\x01\x41\x40\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x47\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4379 4401 ["\x20\x01\x48\x60\x48\x01\x41\x50\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x5E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4380 4402 ["\x20\x01\x48\x60\x48\x01\x41\x60\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x48\x60\x48\x01\x41\x6B\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4403 ], 4404 'ibou_search' => [ 4405 ["\x2A\x0E\x62\x40\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x0E\x62\x40\xE0\x0F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 4381 4406 ], 4382 4407 'meta_asn' => [ -
edgeshaping-lite/trunk/includes/class-cache-bypass.php
r3735949 r3791852 36 36 if ( ! self::should_bypass() ) return; 37 37 if ( ! defined( 'DONOTCACHEPAGE' ) ) { 38 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- 複数のキャッシュプラグイン(W3TC/WP Super Cache等)が共通で認識するサードパーティ規約上の定数名。接頭辞を付けると認識されなくなる。 38 39 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound 39 40 define( 'DONOTCACHEPAGE', true ); 40 41 } -
edgeshaping-lite/trunk/includes/class-cdn-edges.php
r3735949 r3791852 16 16 [306446336, 306511871], 17 17 [409894912, 409927679], 18 [860492800, 860493567], 18 19 [875429888, 875446271], 19 20 [877821952, 877822463], … … 57 58 const RANGES_V6 = [ 58 59 'cloudfront' => [ 60 ["\x20\x01\x3F\xC6\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x3F\xC6\x00\x05\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 61 ["\x20\x01\x3F\xC6\x00\x3C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x20\x01\x3F\xC6\x00\x3D\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 62 ["\x24\x06\xDA\x10\x84\x7F\xA1\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x10\x84\x7F\xA1\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 63 ["\x24\x06\xDA\x11\x04\x38\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x11\x04\x38\x23\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 64 ["\x24\x06\xDA\x12\x00\x4B\xC2\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x12\x00\x4B\xC2\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 65 ["\x24\x06\xDA\x12\x8B\x2E\x9C\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x12\x8B\x2E\x9C\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 66 ["\x24\x06\xDA\x14\x17\xBD\x2F\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x14\x17\xBD\x2F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 67 ["\x24\x06\xDA\x14\x80\xBB\xEA\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x14\x80\xBB\xEA\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 68 ["\x24\x06\xDA\x16\x0C\x01\xC2\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x16\x0C\x01\xC2\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 69 ["\x24\x06\xDA\x18\x09\xFA\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x18\x09\xFA\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 70 ["\x24\x06\xDA\x19\x0E\x19\x4A\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x19\x0E\x19\x4A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 71 ["\x24\x06\xDA\x1A\x06\xDF\x6C\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1A\x06\xDF\x6C\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 72 ["\x24\x06\xDA\x1B\x0E\x7C\xAD\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1B\x0E\x7C\xAD\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 73 ["\x24\x06\xDA\x1C\x07\x87\x2B\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1C\x07\x87\x2B\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 74 ["\x24\x06\xDA\x1C\x8D\x8C\x46\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1C\x8D\x8C\x46\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 75 ["\x24\x06\xDA\x1E\x07\x05\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1E\x07\x05\x16\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 76 ["\x24\x06\xDA\x1F\x03\x96\x91\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x24\x06\xDA\x1F\x03\x96\x91\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 77 ["\x26\x00\x1F\x11\x0E\x79\xA8\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x11\x0E\x79\xA8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 78 ["\x26\x00\x1F\x13\x04\x17\x4D\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x13\x04\x17\x4D\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 79 ["\x26\x00\x1F\x16\x19\x23\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x16\x19\x23\x30\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 80 ["\x26\x00\x1F\x17\x43\x56\xF1\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x17\x43\x56\xF1\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 81 ["\x26\x00\x1F\x18\x75\x30\x72\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x18\x75\x30\x72\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 82 ["\x26\x00\x1F\x1A\x45\x68\xB5\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x1A\x45\x68\xB5\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 83 ["\x26\x00\x1F\x1C\x00\xDA\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x1C\x00\xDA\x06\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 84 ["\x26\x00\x1F\x1E\x00\xA7\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x1F\x1E\x00\xA7\x23\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 59 85 ["\x26\x00\x90\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x90\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 60 86 ["\x26\x00\x90\x00\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x90\x00\x52\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 61 87 ["\x26\x00\x90\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x26\x00\x90\x00\x6F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 88 ["\x2A\x05\xD0\x11\x05\x31\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x11\x05\x31\x18\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 89 ["\x2A\x05\xD0\x12\x05\x81\xB4\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x12\x05\x81\xB4\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 90 ["\x2A\x05\xD0\x14\x13\x62\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x14\x13\x62\xB0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 91 ["\x2A\x05\xD0\x16\x09\xED\xDE\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x16\x09\xED\xDE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 92 ["\x2A\x05\xD0\x18\x1A\x3A\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x18\x1A\x3A\x2D\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 93 ["\x2A\x05\xD0\x19\x08\x0B\xE3\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x19\x08\x0B\xE3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 94 ["\x2A\x05\xD0\x1A\x08\xA9\xBE\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x1A\x08\xA9\xBE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 95 ["\x2A\x05\xD0\x1C\x03\x43\xC3\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x1C\x03\x43\xC3\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 96 ["\x2A\x05\xD0\x25\x0E\x59\xFB\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x2A\x05\xD0\x25\x0E\x59\xFB\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], 62 97 ], 63 98 'cloudflare' => [ -
edgeshaping-lite/trunk/includes/class-gsc.php
r3622188 r3791852 37 37 38 38 39 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter39 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 40 40 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 41 41 return $exists === $table; … … 55 55 global $wpdb; 56 56 $table = $wpdb->prefix . self::TABLE; 57 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter58 $wpdb->query( "DROP TABLE IF EXISTS {$table}");57 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 58 $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); 59 59 delete_option( self::OPTION_LAST_INGESTED ); 60 60 } … … 174 174 global $wpdb; 175 175 $table = $wpdb->prefix . self::TABLE; 176 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter176 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 177 177 $rows = $wpdb->get_results( $wpdb->prepare( 178 "SELECT path, SUM(clicks) AS total FROM {$table} WHERE gsc_date BETWEEN %s AND %s GROUP BY path", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared179 $ date_from, $date_to178 "SELECT path, SUM(clicks) AS total FROM %i WHERE gsc_date BETWEEN %s AND %s GROUP BY path", 179 $table, $date_from, $date_to 180 180 ) ); 181 181 … … 247 247 global $wpdb; 248 248 $table = $wpdb->prefix . 'edgeshaping_daily_stats'; 249 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter250 $oldest = $wpdb->get_var( "SELECT MIN(agg_date) FROM {$table}");249 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 250 $oldest = $wpdb->get_var( $wpdb->prepare( 'SELECT MIN(agg_date) FROM %i', $table ) ); 251 251 $limit = gmdate( 'Y-m-d', strtotime( '-16 months', current_time( 'timestamp' ) ) ); 252 252 … … 265 265 $table = $wpdb->prefix . self::TABLE; 266 266 267 // phpcs:ignore WordPress.DB.DirectDatabaseQuery ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter268 $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE gsc_date = %s", $date ) );267 // phpcs:ignore WordPress.DB.DirectDatabaseQuery 268 $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE gsc_date = %s', $table, $date ) ); 269 269 270 270 foreach ( $rows as $path => $clicks ) { -
edgeshaping-lite/trunk/includes/class-matrix.php
r3682914 r3791852 5 5 6 6 7 public static function build( array $ai_counts, array $human_counts ): array {7 public static function build( array $ai_counts, array $human_counts, array $inferred_counts = [] ): array { 8 8 $sitemap_urls = EdgeShaping_Sitemap::get_urls(); 9 9 10 10 $all_urls = array_unique( array_merge( array_keys( $ai_counts ), array_keys( $human_counts ) ) ); 11 11 12 if ( empty( $all_urls ) ) {12 if ( empty( $all_urls ) && empty( $inferred_counts ) ) { 13 13 return [ 'matrix' => [], 'threshold_ai' => 0, 'threshold_human' => 0, 'inferred' => [], 'dark' => [] ]; 14 14 } … … 20 20 $inferred = []; 21 21 22 23 $inferred_paths = []; 24 foreach ( $inferred_counts as $url => $ai ) { 25 $url = (string) $url; 26 if ( $ai <= 0 ) continue; 27 if ( self::is_spam_path( $url ) || EdgeShaping_Tracker::is_excluded_path( $url ) ) { 28 continue; 29 } 30 $inferred[] = [ 'url' => $url, 'ai' => (int) $ai, 'human' => $human_counts[ $url ] ?? 0 ]; 31 $inferred_paths[ $url ] = true; 32 } 33 34 22 35 foreach ( $all_urls as $url ) { 36 if ( isset( $inferred_paths[ $url ] ) ) continue; 37 23 38 $ai = $ai_counts[ $url ] ?? 0; 24 39 $human = $human_counts[ $url ] ?? 0; 25 26 27 28 if ( ! empty( $sitemap_urls ) && $ai > 0 && ! EdgeShaping_Sitemap::has_path( $url, $sitemap_urls ) ) {29 if ( self::is_spam_path( $url ) || EdgeShaping_Tracker::is_excluded_path( $url ) ) {30 continue;31 }32 $inferred[] = [ 'url' => $url, 'ai' => $ai, 'human' => $human ];33 continue;34 }35 40 36 41 $quad = self::classify( $ai, $human, $threshold_ai, $threshold_human ); … … 41 46 $dark = []; 42 47 if ( ! empty( $sitemap_urls ) ) { 43 $observed = array_map( function( $p ) { return rtrim( $p, '/' ); }, $all_urls);48 $observed = array_map( function( $p ) { return rtrim( (string) $p, '/' ); }, array_merge( $all_urls, array_keys( $inferred_paths ) ) ); 44 49 foreach ( $sitemap_urls as $sitemap_path ) { 45 50 $sitemap_path_trimmed = rtrim( $sitemap_path, '/' ); -
edgeshaping-lite/trunk/includes/class-tracker.php
r3735949 r3791852 47 47 48 48 49 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter49 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 50 50 $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 51 51 return $exists === $table; … … 62 62 ) ); 63 63 if ( ! $exists ) { 64 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter65 $wpdb->query( "ALTER TABLE {$table} ADD COLUMN bot_category VARCHAR(50) NOT NULL DEFAULT '' AFTER bot_name");66 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter67 $wpdb->query( "ALTER TABLE {$table} ADD INDEX idx_bot_category (bot_category)");64 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange 65 $wpdb->query( $wpdb->prepare( "ALTER TABLE %i ADD COLUMN bot_category VARCHAR(50) NOT NULL DEFAULT '' AFTER bot_name", $table ) ); 66 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange 67 $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i ADD INDEX idx_bot_category (bot_category)', $table ) ); 68 68 } 69 69 } … … 77 77 78 78 $table = $wpdb->prefix . self::TABLE; 79 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter79 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 80 80 $exists = $wpdb->get_var( $wpdb->prepare( 81 81 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s', … … 88 88 } 89 89 90 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter91 $wpdb->query( "ALTER TABLE {$table} ADD COLUMN ip VARCHAR(45) NOT NULL DEFAULT '' AFTER request_url");90 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange 91 $wpdb->query( $wpdb->prepare( "ALTER TABLE %i ADD COLUMN ip VARCHAR(45) NOT NULL DEFAULT '' AFTER request_url", $table ) ); 92 92 93 93 … … 108 108 $jp_map = EdgeShaping_Bot_Dictionary::jp_to_key(); 109 109 foreach ( $jp_map as $jp => $en ) { 110 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter110 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 111 111 $wpdb->query( $wpdb->prepare( 112 "UPDATE {$table} SET bot_category = %s WHERE bot_category = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared113 $ en, $jp112 "UPDATE %i SET bot_category = %s WHERE bot_category = %s", 113 $table, $en, $jp 114 114 ) ); 115 115 } 116 116 117 117 118 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter119 $bot_names = $wpdb->get_col( "SELECT DISTINCT bot_name FROM {$table} WHERE bot_category = ''");118 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 119 $bot_names = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT bot_name FROM %i WHERE bot_category = ''", $table ) ); 120 120 if ( empty( $bot_names ) ) return; 121 121 … … 123 123 $category = EdgeShaping_Bot_Dictionary::get_category( $bot_name ); 124 124 if ( '' === $category ) continue; 125 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared125 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 126 126 $wpdb->query( $wpdb->prepare( 127 "UPDATE {$table} SET bot_category = %s WHERE bot_name = %s AND bot_category = ''", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared128 $ category, $bot_name127 "UPDATE %i SET bot_category = %s WHERE bot_name = %s AND bot_category = ''", 128 $table, $category, $bot_name 129 129 ) ); 130 130 } … … 169 169 $today = current_time( 'Y-m-d' ); 170 170 171 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter171 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 172 172 $wpdb->query( $wpdb->prepare( 173 "INSERT INTO {$table} (path, path_hash, pv_date, cnt) VALUES (%s, %s, %s, 1) " // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared173 "INSERT INTO %i (path, path_hash, pv_date, cnt) VALUES (%s, %s, %s, 1) " 174 174 . "ON DUPLICATE KEY UPDATE cnt = cnt + 1", 175 $ path, md5( $path ), $today175 $table, $path, md5( $path ), $today 176 176 ) ); 177 177 … … 231 231 global $wpdb; 232 232 $table = $wpdb->prefix . self::HUMAN_PV_TABLE; 233 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter233 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 234 234 $rows = $wpdb->get_results( $wpdb->prepare( 235 "SELECT path, SUM(cnt) AS total FROM {$table} WHERE pv_date BETWEEN %s AND %s GROUP BY path", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared236 $ date_from, $date_to235 "SELECT path, SUM(cnt) AS total FROM %i WHERE pv_date BETWEEN %s AND %s GROUP BY path", 236 $table, $date_from, $date_to 237 237 ) ); 238 238 … … 268 268 global $wpdb; 269 269 $table = $wpdb->prefix . self::TABLE; 270 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter271 $wpdb->query( "DROP TABLE IF EXISTS {$table}");270 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange 271 $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); 272 272 $human_table = $wpdb->prefix . self::HUMAN_PV_TABLE; 273 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter274 $wpdb->query( "DROP TABLE IF EXISTS {$human_table}");273 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange 274 $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $human_table ) ); 275 275 delete_option( 'edgeshaping_db_version' ); 276 276 } … … 289 289 $table = $wpdb->prefix . self::TABLE; 290 290 $days = defined( 'EDGESHAPING_RETENTION_DAYS' ) ? (int) EDGESHAPING_RETENTION_DAYS : 120; 291 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter292 $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE visited_at < DATE_SUB(NOW(), INTERVAL %d DAY)", $days ) );291 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 292 $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE visited_at < DATE_SUB(NOW(), INTERVAL %d DAY)', $table, $days ) ); 293 293 294 294 $max = defined( 'EDGESHAPING_MAX_ROWS' ) ? (int) EDGESHAPING_MAX_ROWS : 20000; 295 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter296 $count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}");295 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 296 $count = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table ) ); 297 297 if ( $count > $max ) { 298 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter299 $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} ORDER BY visited_at ASC LIMIT %d", $count - $max ) );298 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 299 $wpdb->query( $wpdb->prepare( 'DELETE FROM %i ORDER BY visited_at ASC LIMIT %d', $table, $count - $max ) ); 300 300 } 301 301 302 302 $human_table = $wpdb->prefix . self::HUMAN_PV_TABLE; 303 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter304 $wpdb->query( $wpdb->prepare( "DELETE FROM {$human_table} WHERE pv_date < DATE_SUB(CURDATE(), INTERVAL %d DAY)", $days ) );303 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 304 $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE pv_date < DATE_SUB(CURDATE(), INTERVAL %d DAY)', $human_table, $days ) ); 305 305 } 306 306 … … 366 366 update_option( 'edgeshaping_ip_disabled', 1 ); 367 367 $table = $wpdb->prefix . self::TABLE; 368 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter369 $wpdb->query( "UPDATE {$table} SET ip = '' WHERE ip <> ''");370 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter371 $remaining = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table} WHERE ip <> ''");368 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 369 $wpdb->query( $wpdb->prepare( "UPDATE %i SET ip = '' WHERE ip <> ''", $table ) ); 370 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 371 $remaining = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE ip <> ''", $table ) ); 372 372 return 0 === $remaining; 373 373 } … … 442 442 global $wpdb; 443 443 $table = $wpdb->prefix . self::TABLE; 444 $conditions = self::build_conditions( $date_from, $date_to, $category ); 445 $where = $conditions ? 'WHERE ' . implode( ' AND ', $conditions ) : ''; 446 return $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} {$where} ORDER BY visited_at DESC, id DESC LIMIT %d OFFSET %d", $per_page, $offset ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter 444 [ $where, $args ] = self::build_conditions( $date_from, $date_to, $category ); 445 $sql = "SELECT * FROM %i {$where} ORDER BY visited_at DESC, id DESC LIMIT %d OFFSET %d"; 446 $args = array_merge( [ $table ], $args, [ $per_page, $offset ] ); 447 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared 448 return $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); 447 449 } 448 450 … … 450 452 global $wpdb; 451 453 $table = $wpdb->prefix . self::TABLE; 452 $conditions = self::build_conditions( $date_from, $date_to, $category ); 453 $where = $conditions ? 'WHERE ' . implode( ' AND ', $conditions ) : ''; 454 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter 455 return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table} {$where}" ); 454 [ $where, $args ] = self::build_conditions( $date_from, $date_to, $category ); 455 $sql = "SELECT COUNT(*) FROM %i {$where}"; 456 $args = array_merge( [ $table ], $args ); 457 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared 458 return (int) $wpdb->get_var( $wpdb->prepare( $sql, ...$args ) ); 459 } 460 461 462 public static function get_bot_names( string $date_from, string $date_to ): array { 463 global $wpdb; 464 $table = $wpdb->prefix . self::TABLE; 465 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 466 $names = $wpdb->get_col( $wpdb->prepare( 467 "SELECT DISTINCT bot_name FROM %i WHERE visited_at BETWEEN %s AND %s ORDER BY bot_name ASC", 468 $table, $date_from . ' 00:00:00', 469 $date_to . ' 23:59:59' 470 ) ); 471 return is_array( $names ) ? array_map( 'strval', $names ) : []; 456 472 } 457 473 … … 460 476 global $wpdb; 461 477 $table = $wpdb->prefix . self::TABLE; 462 $conditions = self::build_conditions( $date_from, $date_to, $category ); 463 $where = $conditions ? 'WHERE ' . implode( ' AND ', $conditions ) : ''; 464 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter 465 $rows = $wpdb->get_results( "SELECT bot_name, bot_category, request_url, visited_at FROM {$table} {$where}" ); 478 [ $where, $args ] = self::build_conditions( $date_from, $date_to, $category ); 479 $sql = "SELECT bot_name, bot_category, request_url, visited_at FROM %i {$where}"; 480 $args = array_merge( [ $table ], $args ); 481 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared 482 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); 466 483 467 484 … … 495 512 global $wpdb; 496 513 $table = $wpdb->prefix . self::TABLE; 497 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching ,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter498 return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}");514 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 515 return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table ) ); 499 516 } 500 517 … … 503 520 global $wpdb; 504 521 $table = $wpdb->prefix . self::TABLE; 505 $conditions = self::build_conditions( $date_from, $date_to, $category ); 506 $where = $conditions ? 'WHERE ' . implode( ' AND ', $conditions ) : ''; 507 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter 508 $rows = $wpdb->get_results( "SELECT * FROM {$table} {$where} ORDER BY visited_at DESC" ); 522 [ $where, $args ] = self::build_conditions( $date_from, $date_to, $category ); 523 $sql = "SELECT * FROM %i {$where} ORDER BY visited_at DESC"; 524 $args = array_merge( [ $table ], $args ); 525 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared 526 $rows = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ) ); 509 527 510 528 $result = []; … … 522 540 } 523 541 542 524 543 private static function build_conditions( string $date_from, string $date_to, string $category = '' ): array { 525 global $wpdb;526 544 $conditions = []; 545 $args = []; 527 546 if ( ! empty( $date_from ) ) { 528 $conditions[] = $wpdb->prepare( 'visited_at >= %s', $date_from . ' 00:00:00' ); 547 $conditions[] = 'visited_at >= %s'; 548 $args[] = $date_from . ' 00:00:00'; 529 549 } 530 550 if ( ! empty( $date_to ) ) { 531 $conditions[] = $wpdb->prepare( 'visited_at <= %s', $date_to . ' 23:59:59' ); 551 $conditions[] = 'visited_at <= %s'; 552 $args[] = $date_to . ' 23:59:59'; 532 553 } 533 554 if ( ! empty( $category ) ) { … … 535 556 $cats = array_filter( array_map( 'trim', explode( ',', $category ) ) ); 536 557 if ( count( $cats ) === 1 ) { 537 $conditions[] = $wpdb->prepare( 'bot_category = %s', $cats[0] ); 558 $conditions[] = 'bot_category = %s'; 559 $args[] = $cats[0]; 538 560 } elseif ( count( $cats ) > 1 ) { 539 $ placeholders = implode( ',', array_fill( 0, count( $cats ), '%s' ) );540 // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared541 $conditions[] = $wpdb->prepare( "bot_category IN ({$placeholders})", ...$cats );542 }543 }544 return $conditions;561 $conditions[] = 'bot_category IN (' . implode( ',', array_fill( 0, count( $cats ), '%s' ) ) . ')'; 562 $args = array_merge( $args, $cats ); 563 } 564 } 565 $where = $conditions ? 'WHERE ' . implode( ' AND ', $conditions ) : ''; 566 return [ $where, $args ]; 545 567 } 546 568 } -
edgeshaping-lite/trunk/readme.txt
r3735949 r3791852 2 2 Contributors: mareinterno 3 3 Tags: ai crawler, ai bot, bot log, analytics, llm 4 Requires at least: 6. 04 Requires at least: 6.9 5 5 Tested up to: 7.1 6 Requires PHP: 7.47 Stable tag: 2026.1 0.06 Requires PHP: 8.2 7 Stable tag: 2026.11.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 84 84 AHTG Matrix uses the same four-quadrant model as AHQG, but the human axis is WordPress's own page views instead of Google Search Console clicks — no external connection required, and it reflects all traffic sources, not just search. 85 85 86 = Why is the dashboard empty right after installation? = 87 88 The dashboard and the matrices show data aggregated once a day, up to yesterday, so they start showing data the day after installation. Today's bot visits can be checked in the access log. 89 86 90 == External Services == 87 91 … … 100 104 101 105 == Changelog == 106 107 = 2026.11.0 = 108 * Changed: the bot dictionary is updated for November. The bots used for the AI axis of the AHQG/AHTG matrices follow the updated dictionary, so matrix results for past periods may differ from what you saw before. 109 * Changed: the dashboard and the matrices now count only visits by verified bots to published pages (published posts and pages, and the front page). Inferred Path now lists the other paths visited by verified bots, instead of URLs missing from the sitemap. The access log is unfiltered as before. 110 * Added: an "AI Ready" screen that lists the AI bots that reached your site in a period (including today, up to 30 days). 111 * Changed: requires WordPress 6.9 or later and PHP 8.2 or later. PHP 8.2 reaches the end of official security support on December 31, 2026, and the first release in 2027 will require PHP 8.3 or later. 102 112 103 113 = 2026.10.0 = … … 190 200 == Upgrade Notice == 191 201 202 = 2026.11.0 = 203 November bot dictionary. The dashboard and matrices now count only verified bot visits to published pages, so numbers may be lower than before. Adds an "AI Ready" screen. Requires WordPress 6.9+ and PHP 8.2+; PHP 8.3+ from 2027. Existing data carries over. 204 192 205 = 2026.10.0 = 193 206 Bot dictionary now lists only officially documented crawlers; undocumented bots are no longer recorded and past matrix results may change. Adds a read-only MCP ability and a setting to turn off IP address recording. Existing data carries over.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)