| @@ -13,9 +13,9 @@ | ||
| 13 | 13 | * Creates, versions, verifies, and repairs the plugin's tables. |
| 14 | 14 | */ |
| 15 | 15 | class Migrator { |
| 16 | 16 | |
| 17 | - const DB_VERSION = '2.0.0'; | |
| 17 | + const DB_VERSION = '2.0.2'; | |
| 18 | 18 | |
| 19 | 19 | /** |
| 20 | 20 | * Install, upgrade, or repair tables. Safe to call on every load. |
| 21 | 21 | * |
| @@ -119,13 +119,14 @@ | ||
| 119 | 119 | origin VARCHAR(30) NOT NULL DEFAULT 'buffer', |
| 120 | 120 | rendered TINYINT(1) NOT NULL DEFAULT 0, |
| 121 | 121 | above_fold TINYINT(1) NOT NULL DEFAULT 0, |
| 122 | 122 | hits BIGINT UNSIGNED NOT NULL DEFAULT 1, |
| 123 | + beacon_misses SMALLINT UNSIGNED NOT NULL DEFAULT 0, | |
| 123 | 124 | last_seen DATETIME DEFAULT NULL, |
| 124 | 125 | PRIMARY KEY (id), |
| 125 | 126 | UNIQUE KEY uq_usage (usage_key), |
| 126 | 127 | KEY idx_family (family), |
| 127 | - KEY idx_page (page_id) | |
| 128 | + KEY idx_last_seen (last_seen) | |
| 128 | 129 | ) {$charset};" |
| 129 | 130 | ); |
| 130 | 131 | |
| 131 | 132 | dbDelta( |
| @@ -137,14 +138,46 @@ | ||
| 137 | 138 | preload LONGTEXT DEFAULT NULL, |
| 138 | 139 | unload LONGTEXT DEFAULT NULL, |
| 139 | 140 | updated_at DATETIME DEFAULT NULL, |
| 140 | 141 | PRIMARY KEY (id), |
| 141 | - UNIQUE KEY uq_route (route_key) | |
| 142 | + UNIQUE KEY uq_route (route_key), | |
| 143 | + KEY idx_updated (updated_at) | |
| 142 | 144 | ) {$charset};" |
| 143 | 145 | ); |
| 146 | + | |
| 147 | + // dbDelta never DROPs an index that exists in the table but not in the | |
| 148 | + // definition, so retire the now-unused usage.idx_page (it indexed a | |
| 149 | + // column we never query) explicitly. Guarded + idempotent: only runs | |
| 150 | + // when the index is actually present, and a failure can't break install. | |
| 151 | + $this->drop_index_if_exists( 'easyfonts_usage', 'idx_page' ); | |
| 144 | 152 | } |
| 145 | 153 | |
| 146 | 154 | /** |
| 155 | + * Drop an index from a table if it exists. Safe no-op otherwise. | |
| 156 | + * | |
| 157 | + * @param string $name Unprefixed table name. | |
| 158 | + * @param string $index Index name. | |
| 159 | + * @return void | |
| 160 | + */ | |
| 161 | + private function drop_index_if_exists( string $name, string $index ): void { | |
| 162 | + global $wpdb; | |
| 163 | + | |
| 164 | + if ( ! $this->table_exists( $name ) ) { | |
| 165 | + return; | |
| 166 | + } | |
| 167 | + | |
| 168 | + $table = $wpdb->prefix . $name; | |
| 169 | + | |
| 170 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared | |
| 171 | + $found = $wpdb->get_var( $wpdb->prepare( "SHOW INDEX FROM `{$table}` WHERE Key_name = %s", $index ) ); | |
| 172 | + | |
| 173 | + if ( $found ) { | |
| 174 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared | |
| 175 | + $wpdb->query( "ALTER TABLE `{$table}` DROP INDEX `{$index}`" ); | |
| 176 | + } | |
| 177 | + } | |
| 178 | + | |
| 179 | + /** | |
| 147 | 180 | * Drop all three tables (IF EXISTS). |
| 148 | 181 | */ |
| 149 | 182 | private function drop_tables(): void { |
| 150 | 183 | global $wpdb; |
| @@ -166,8 +199,9 @@ | ||
| 166 | 199 | && $this->column_exists( 'easyfonts_fonts', 'is_enabled' ) |
| 167 | 200 | && $this->column_exists( 'easyfonts_fonts', 'load_user_set' ) |
| 168 | 201 | && $this->column_exists( 'easyfonts_fonts', 'preload_user_set' ) |
| 169 | 202 | && $this->column_exists( 'easyfonts_usage', 'usage_key' ) |
| 203 | + && $this->column_exists( 'easyfonts_usage', 'beacon_misses' ) | |
| 170 | 204 | && $this->column_exists( 'easyfonts_decisions', 'route_key' ); |
| 171 | 205 | } |
| 172 | 206 | |
| 173 | 207 | /** |