| @@ -32,8 +32,33 @@ | ||
| 32 | 32 | */ |
| 33 | 33 | protected $entity_class; |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | + * Whether caching is enabled. Evaluated once per request via the 'sequra_cache_enabled' filter. | |
| 37 | + * | |
| 38 | + * Public to allow test suites to reset the static state between tests | |
| 39 | + * without requiring Reflection. | |
| 40 | + * | |
| 41 | + * @var bool|null | |
| 42 | + */ | |
| 43 | + public static $cache_enabled = null; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * Cache group for table existence checks. | |
| 47 | + */ | |
| 48 | + public const TABLE_EXISTS_CACHE_GROUP = 'sequra_table_exists'; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * Cache group for data query results and version counters. | |
| 52 | + */ | |
| 53 | + public const DATA_CACHE_GROUP = 'sequra_data'; | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * TTL for cache entries in seconds. | |
| 57 | + */ | |
| 58 | + private const CACHE_TTL = 300; | |
| 59 | + | |
| 60 | + /** | |
| 36 | 61 | * Database session object. |
| 37 | 62 | * |
| 38 | 63 | * @var \wpdb |
| 39 | 64 | */ |
| @@ -39,8 +64,15 @@ | ||
| 39 | 64 | */ |
| 40 | 65 | protected $db; |
| 41 | 66 | |
| 42 | 67 | /** |
| 68 | + * Cache repository. | |
| 69 | + * | |
| 70 | + * @var Interface_Cache_Repository | |
| 71 | + */ | |
| 72 | + protected $cache; | |
| 73 | + | |
| 74 | + /** | |
| 43 | 75 | * Returns unprefixed table name. |
| 44 | 76 | */ |
| 45 | 77 | abstract protected function get_unprefixed_table_name(): string; |
| 46 | 78 | |
| @@ -69,12 +101,34 @@ | ||
| 69 | 101 | $db = ServiceRegister::getService( \wpdb::class ); |
| 70 | 102 | if ( ! $db instanceof \wpdb ) { |
| 71 | 103 | throw new \RuntimeException( 'Database service not found.' ); |
| 72 | 104 | } |
| 73 | - $this->db = $db; | |
| 105 | + $this->db = $db; | |
| 106 | + $this->cache = ServiceRegister::getService( Interface_Cache_Repository::class ); | |
| 74 | 107 | } |
| 75 | 108 | |
| 76 | 109 | /** |
| 110 | + * Check if caching is enabled. | |
| 111 | + * Result is evaluated once per request and cached statically. | |
| 112 | + * | |
| 113 | + * Disable all repository caching by adding to functions.php or an mu-plugin: | |
| 114 | + * add_filter( 'sequra_cache_enabled', '__return_false' ); | |
| 115 | + */ | |
| 116 | + private static function is_cache_enabled(): bool { | |
| 117 | + if ( null === self::$cache_enabled ) { | |
| 118 | + /** | |
| 119 | + * Whether repository caching is enabled. | |
| 120 | + * Set to false to disable all repository caching and fall back to direct database queries. | |
| 121 | + * | |
| 122 | + * @since 4.2.0 | |
| 123 | + * @param bool $enabled Whether caching is enabled. Default true. | |
| 124 | + */ | |
| 125 | + self::$cache_enabled = (bool) \apply_filters( 'sequra_cache_enabled', true ); | |
| 126 | + } | |
| 127 | + return self::$cache_enabled; | |
| 128 | + } | |
| 129 | + | |
| 130 | + /** | |
| 77 | 131 | * Returns full class name. |
| 78 | 132 | * |
| 79 | 133 | * @return string Full class name. |
| 80 | 134 | */ |
| @@ -96,14 +150,14 @@ | ||
| 96 | 150 | |
| 97 | 151 | /** |
| 98 | 152 | * Executes select query. |
| 99 | 153 | * |
| 100 | - * @param QueryFilter $filter Filter for query. | |
| 154 | + * @param QueryFilter|null $filter Filter for query. | |
| 101 | 155 | * |
| 102 | 156 | * @return Entity[] A list of found entities ot empty array. |
| 103 | 157 | * @throws QueryFilterInvalidParamException If filter condition is invalid. |
| 104 | 158 | */ |
| 105 | - public function select( QueryFilter $filter = null ) { | |
| 159 | + public function select( ?QueryFilter $filter = null ) { | |
| 106 | 160 | /** |
| 107 | 161 | * Entity object. |
| 108 | 162 | * |
| 109 | 163 | * @var Entity $entity |
| @@ -109,14 +163,26 @@ | ||
| 109 | 163 | * @var Entity $entity |
| 110 | 164 | */ |
| 111 | 165 | $entity = new $this->entity_class(); |
| 112 | 166 | $type = $entity->getConfig()->getType(); |
| 113 | - | |
| 167 | + | |
| 114 | 168 | $query = "SELECT * FROM {$this->get_table_name()} WHERE type = '$type' "; |
| 115 | 169 | if ( $filter ) { |
| 116 | 170 | $query .= $this->apply_query_filter( $filter, IndexHelper::mapFieldsToIndexes( $entity ) ); |
| 117 | 171 | } |
| 118 | - | |
| 172 | + | |
| 173 | + // Only cache bounded queries (with LIMIT) to avoid exceeding the 1 MB cache entry size limit. | |
| 174 | + // Unbounded selects (e.g. deleteAllOrders) can return arbitrarily large result sets. | |
| 175 | + $is_cacheable = self::is_cache_enabled() && null !== $filter && $filter->getLimit() > 0; | |
| 176 | + | |
| 177 | + if ( $is_cacheable ) { | |
| 178 | + $found = false; | |
| 179 | + $cached = $this->cache->get( $this->build_data_cache_key( $query ), self::DATA_CACHE_GROUP, $found ); | |
| 180 | + if ( $found ) { | |
| 181 | + return $cached; | |
| 182 | + } | |
| 183 | + } | |
| 184 | + | |
| 119 | 185 | $raw_results = array(); |
| 120 | 186 | if ( $this->table_exists() ) { |
| 121 | 187 | $raw_results = $this->db->get_results( $query, ARRAY_A ); |
| 122 | 188 | if ( ! is_array( $raw_results ) ) { |
| @@ -124,10 +190,10 @@ | ||
| 124 | 190 | } |
| 125 | 191 | } |
| 126 | 192 | if ( $this->table_exists( true ) ) { |
| 127 | 193 | // If the legacy table exists the data may be there. |
| 128 | - $query = str_replace( $this->get_table_name(), $this->get_legacy_table_name(), $query ); | |
| 129 | - $legacy_raw_results = $this->db->get_results( $query, ARRAY_A ); | |
| 194 | + $legacy_query = str_replace( $this->get_table_name(), $this->get_legacy_table_name(), $query ); | |
| 195 | + $legacy_raw_results = $this->db->get_results( $legacy_query, ARRAY_A ); | |
| 130 | 196 | if ( ! is_array( $legacy_raw_results ) ) { |
| 131 | 197 | $legacy_raw_results = array(); |
| 132 | 198 | } |
| 133 | 199 | $raw_results = array_merge( $raw_results, $legacy_raw_results ); |
| @@ -132,20 +198,26 @@ | ||
| 132 | 198 | } |
| 133 | 199 | $raw_results = array_merge( $raw_results, $legacy_raw_results ); |
| 134 | 200 | } |
| 135 | 201 | |
| 136 | - return $this->translateToEntities( $raw_results ); | |
| 202 | + $entities = $this->translateToEntities( $raw_results ); | |
| 203 | + | |
| 204 | + if ( $is_cacheable ) { | |
| 205 | + $this->cache->set( $this->build_data_cache_key( $query ), $entities, self::DATA_CACHE_GROUP, self::CACHE_TTL ); | |
| 206 | + } | |
| 207 | + | |
| 208 | + return $entities; | |
| 137 | 209 | } |
| 138 | 210 | |
| 139 | 211 | /** |
| 140 | 212 | * Executes select query and returns first result. |
| 141 | 213 | * |
| 142 | - * @param QueryFilter $filter Filter for query. | |
| 214 | + * @param QueryFilter|null $filter Filter for query. | |
| 143 | 215 | * |
| 144 | 216 | * @return Entity|null First found entity or NULL. |
| 145 | 217 | * @throws QueryFilterInvalidParamException If filter condition is invalid. |
| 146 | 218 | */ |
| 147 | - public function selectOne( QueryFilter $filter = null ) { | |
| 219 | + public function selectOne( ?QueryFilter $filter = null ) { | |
| 148 | 220 | if ( ! $filter ) { |
| 149 | 221 | $filter = new QueryFilter(); |
| 150 | 222 | } |
| 151 | 223 | |
| @@ -172,9 +244,12 @@ | ||
| 172 | 244 | |
| 173 | 245 | return $entity->getId(); |
| 174 | 246 | } |
| 175 | 247 | |
| 176 | - return $this->save_entity_to_storage( $entity ); | |
| 248 | + $id = $this->save_entity_to_storage( $entity ); | |
| 249 | + $this->bump_data_version(); | |
| 250 | + | |
| 251 | + return $id; | |
| 177 | 252 | } |
| 178 | 253 | |
| 179 | 254 | /** |
| 180 | 255 | * Executes update query and returns success flag. |
| @@ -210,12 +285,17 @@ | ||
| 210 | 285 | return false; |
| 211 | 286 | } |
| 212 | 287 | // Delete the row from the legacy table. |
| 213 | 288 | $this->db->delete( $this->get_legacy_table_name(), $where ); |
| 289 | + $this->bump_data_version(); | |
| 214 | 290 | return true; |
| 215 | 291 | } |
| 216 | 292 | // Only one record should be updated. |
| 217 | - return 1 === $this->db->update( $this->get_table_name(), $item, $where ); | |
| 293 | + $updated = 1 === $this->db->update( $this->get_table_name(), $item, $where ); | |
| 294 | + if ( $updated ) { | |
| 295 | + $this->bump_data_version(); | |
| 296 | + } | |
| 297 | + return $updated; | |
| 218 | 298 | } |
| 219 | 299 | |
| 220 | 300 | /** |
| 221 | 301 | * Executes delete query and returns success flag. |
| @@ -235,8 +315,11 @@ | ||
| 235 | 315 | // Delete from legacy table. |
| 236 | 316 | $result = $this->db->delete( $this->get_legacy_table_name(), $where ); |
| 237 | 317 | $deleted = $deleted || ! empty( $result ); |
| 238 | 318 | } |
| 319 | + if ( $deleted ) { | |
| 320 | + $this->bump_data_version(); | |
| 321 | + } | |
| 239 | 322 | return $deleted; |
| 240 | 323 | } |
| 241 | 324 | |
| 242 | 325 | /** |
| @@ -241,14 +324,14 @@ | ||
| 241 | 324 | |
| 242 | 325 | /** |
| 243 | 326 | * Counts records that match filter criteria. |
| 244 | 327 | * |
| 245 | - * @param QueryFilter $filter Filter for query. | |
| 328 | + * @param QueryFilter|null $filter Filter for query. | |
| 246 | 329 | * |
| 247 | 330 | * @return int Number of records that match filter criteria. |
| 248 | 331 | * @throws QueryFilterInvalidParamException If filter condition is invalid. |
| 249 | 332 | */ |
| 250 | - public function count( QueryFilter $filter = null ) { | |
| 333 | + public function count( ?QueryFilter $filter = null ) { | |
| 251 | 334 | /** |
| 252 | 335 | * Entity object. |
| 253 | 336 | * |
| 254 | 337 | * @var Entity $entity |
| @@ -259,8 +342,21 @@ | ||
| 259 | 342 | $query = "SELECT COUNT(*) as `total` FROM {$this->get_table_name()} WHERE type = '$type' "; |
| 260 | 343 | if ( $filter ) { |
| 261 | 344 | $query .= $this->apply_query_filter( $filter, IndexHelper::mapFieldsToIndexes( $entity ) ); |
| 262 | 345 | } |
| 346 | + | |
| 347 | + // count() always returns a single integer — safe to cache regardless of result set size. | |
| 348 | + $is_cacheable = self::is_cache_enabled(); | |
| 349 | + $cache_key = $this->build_data_cache_key( 'count:' . $query ); | |
| 350 | + | |
| 351 | + if ( $is_cacheable ) { | |
| 352 | + $found = false; | |
| 353 | + $cached = $this->cache->get( $cache_key, self::DATA_CACHE_GROUP, $found ); | |
| 354 | + if ( $found && is_numeric( $cached ) ) { | |
| 355 | + return (int) $cached; | |
| 356 | + } | |
| 357 | + } | |
| 358 | + | |
| 263 | 359 | $count = 0; |
| 264 | 360 | if ( $this->table_exists() ) { |
| 265 | 361 | $result = $this->db->get_results( $query, ARRAY_A ); |
| 266 | 362 | $count += empty( $result[0]['total'] ) || ! is_numeric( $result[0]['total'] ) ? 0 : (int) $result[0]['total']; |
| @@ -266,12 +362,17 @@ | ||
| 266 | 362 | $count += empty( $result[0]['total'] ) || ! is_numeric( $result[0]['total'] ) ? 0 : (int) $result[0]['total']; |
| 267 | 363 | } |
| 268 | 364 | if ( $this->table_exists( true ) ) { |
| 269 | 365 | // If the legacy table exists, count the data there too. |
| 270 | - $query = str_replace( $this->get_table_name(), $this->get_legacy_table_name(), $query ); | |
| 271 | - $result = $this->db->get_results( $query, ARRAY_A ); | |
| 272 | - $count += empty( $result[0]['total'] ) || ! is_numeric( $result[0]['total'] ) ? 0 : (int) $result[0]['total']; | |
| 366 | + $legacy_query = str_replace( $this->get_table_name(), $this->get_legacy_table_name(), $query ); | |
| 367 | + $result = $this->db->get_results( $legacy_query, ARRAY_A ); | |
| 368 | + $count += empty( $result[0]['total'] ) || ! is_numeric( $result[0]['total'] ) ? 0 : (int) $result[0]['total']; | |
| 273 | 369 | } |
| 370 | + | |
| 371 | + if ( $is_cacheable ) { | |
| 372 | + $this->cache->set( $cache_key, $count, self::DATA_CACHE_GROUP, self::CACHE_TTL ); | |
| 373 | + } | |
| 374 | + | |
| 274 | 375 | return $count; |
| 275 | 376 | } |
| 276 | 377 | |
| 277 | 378 | /** |
| @@ -281,9 +382,9 @@ | ||
| 281 | 382 | * |
| 282 | 383 | * @return string Escaped value. |
| 283 | 384 | */ |
| 284 | 385 | protected function escape( $value ) { |
| 285 | - return addslashes( strval( $value ) ); | |
| 386 | + return addslashes( \strval( $value ) ); | |
| 286 | 387 | } |
| 287 | 388 | |
| 288 | 389 | /** |
| 289 | 390 | * Checks if value exists and escapes it if it's not. |
| @@ -341,9 +442,9 @@ | ||
| 341 | 442 | */ |
| 342 | 443 | $values = $condition->getValue(); |
| 343 | 444 | $escaped_values = array(); |
| 344 | 445 | foreach ( $values as $value ) { |
| 345 | - $escaped_values[] = is_string( $value ) ? $this->escape_value( $value ) : $value; | |
| 446 | + $escaped_values[] = \is_string( $value ) ? $this->escape_value( $value ) : $value; | |
| 346 | 447 | } |
| 347 | 448 | |
| 348 | 449 | $value = '(' . implode( ', ', $escaped_values ) . ')'; |
| 349 | 450 | break; |
| @@ -419,9 +520,9 @@ | ||
| 419 | 520 | */ |
| 420 | 521 | if ( ! isset( $item['data'] ) || ! isset( $item['id'] ) ) { |
| 421 | 522 | continue; |
| 422 | 523 | } |
| 423 | - $data = (array) json_decode( strval( $item['data'] ), true ); | |
| 524 | + $data = (array) json_decode( \strval( $item['data'] ), true ); | |
| 424 | 525 | /** |
| 425 | 526 | * Entity object. |
| 426 | 527 | * |
| 427 | 528 | * @var Entity $entity |
| @@ -501,9 +602,9 @@ | ||
| 501 | 602 | * |
| 502 | 603 | * @return void |
| 503 | 604 | */ |
| 504 | 605 | protected function validate_index_column( $column, array $index_map ) { |
| 505 | - if ( 'id' !== $column && ! array_key_exists( $column, $index_map ) ) { | |
| 606 | + if ( 'id' !== $column && ! \array_key_exists( $column, $index_map ) ) { | |
| 506 | 607 | throw new QueryFilterInvalidParamException( esc_html__( 'Column is not id or index.', 'sequra' ) ); |
| 507 | 608 | } |
| 508 | 609 | } |
| 509 | 610 | |
| @@ -529,8 +630,11 @@ | ||
| 529 | 630 | if ( $this->table_exists( true ) ) { |
| 530 | 631 | $result = $this->db->query( str_replace( $this->get_table_name(), $this->get_legacy_table_name(), $sql ) ); |
| 531 | 632 | $deleted = $deleted || ! empty( $result ); |
| 532 | 633 | } |
| 634 | + if ( $deleted ) { | |
| 635 | + $this->bump_data_version(); | |
| 636 | + } | |
| 533 | 637 | return $deleted; |
| 534 | 638 | } |
| 535 | 639 | |
| 536 | 640 | /** |
| @@ -548,12 +652,72 @@ | ||
| 548 | 652 | * @param boolean $legacy If true, check for legacy table. |
| 549 | 653 | */ |
| 550 | 654 | public function table_exists( $legacy = false ): bool { |
| 551 | 655 | $table_name = \sanitize_text_field( ! $legacy ? $this->get_table_name() : $this->get_legacy_table_name() ); |
| 552 | - return $this->db->get_var( "SHOW TABLES LIKE '{$table_name}'" ) === $table_name; | |
| 656 | + | |
| 657 | + if ( self::is_cache_enabled() ) { | |
| 658 | + $found = false; | |
| 659 | + $cached = $this->cache->get( $table_name, self::TABLE_EXISTS_CACHE_GROUP, $found ); | |
| 660 | + if ( $found ) { | |
| 661 | + return (bool) $cached; | |
| 662 | + } | |
| 663 | + } | |
| 664 | + | |
| 665 | + $result = $this->db->get_var( "SHOW TABLES LIKE '{$table_name}'" ) === $table_name; | |
| 666 | + | |
| 667 | + if ( self::is_cache_enabled() ) { | |
| 668 | + $this->cache->set( $table_name, $result, self::TABLE_EXISTS_CACHE_GROUP, self::CACHE_TTL ); | |
| 669 | + } | |
| 670 | + | |
| 671 | + return $result; | |
| 553 | 672 | } |
| 554 | 673 | |
| 555 | 674 | /** |
| 675 | + * Invalidate the table existence cache for a specific table. | |
| 676 | + * | |
| 677 | + * @param string $table_name The table name to invalidate. | |
| 678 | + */ | |
| 679 | + private function invalidate_table_exists_cache( $table_name ): void { | |
| 680 | + if ( self::is_cache_enabled() ) { | |
| 681 | + $this->cache->delete( $table_name, self::TABLE_EXISTS_CACHE_GROUP ); | |
| 682 | + } | |
| 683 | + } | |
| 684 | + | |
| 685 | + /** | |
| 686 | + * Build a versioned cache key for a data query. | |
| 687 | + * The version is bumped on every write, making previous keys stale. | |
| 688 | + * | |
| 689 | + * @param string $query The SQL query string used as the cache discriminator. | |
| 690 | + */ | |
| 691 | + private function build_data_cache_key( $query ): string { | |
| 692 | + return $this->entity_class . ':' . md5( $query ) . ':v' . $this->get_data_version(); | |
| 693 | + } | |
| 694 | + | |
| 695 | + /** | |
| 696 | + * Get the current data version for this entity class. | |
| 697 | + */ | |
| 698 | + private function get_data_version(): int { | |
| 699 | + $found = false; | |
| 700 | + $version = $this->cache->get( $this->get_data_version_key(), self::DATA_CACHE_GROUP, $found ); | |
| 701 | + return $found && is_numeric( $version ) ? (int) $version : 0; | |
| 702 | + } | |
| 703 | + | |
| 704 | + /** | |
| 705 | + * Get the cache key that stores the data version for this entity class. | |
| 706 | + */ | |
| 707 | + private function get_data_version_key(): string { | |
| 708 | + return 'version:' . $this->entity_class . ':' . $this->get_table_name(); | |
| 709 | + } | |
| 710 | + | |
| 711 | + /** | |
| 712 | + * Bump the data version for this entity class, invalidating all cached reads. | |
| 713 | + * Uses an atomic increment to avoid a read-then-write race on concurrent requests. | |
| 714 | + */ | |
| 715 | + protected function bump_data_version(): void { | |
| 716 | + $this->cache->increment( $this->get_data_version_key(), self::DATA_CACHE_GROUP, self::CACHE_TTL ); | |
| 717 | + } | |
| 718 | + | |
| 719 | + /** | |
| 556 | 720 | * Remove entities that are older than a certain date or that are invalid. |
| 557 | 721 | * This performs a cleanup of the repository data. |
| 558 | 722 | */ |
| 559 | 723 | public function delete_old_and_invalid() { |
| @@ -598,9 +762,9 @@ | ||
| 598 | 762 | if ( ! $this->table_exists() || ! $this->table_exists( true ) ) { |
| 599 | 763 | return; |
| 600 | 764 | } |
| 601 | 765 | $raw_results = $this->db->get_results( "SELECT * FROM {$this->get_legacy_table_name()} LIMIT 1;", ARRAY_A ); |
| 602 | - if ( ! is_array( $raw_results ) ) { | |
| 766 | + if ( ! \is_array( $raw_results ) ) { | |
| 603 | 767 | return; |
| 604 | 768 | } |
| 605 | 769 | |
| 606 | 770 | $entity = $this->translateToEntities( $raw_results )[0] ?? null; |
| @@ -616,8 +780,9 @@ | ||
| 616 | 780 | $result = $this->db->insert( $this->get_table_name(), $storage_item ); |
| 617 | 781 | if ( false !== $result ) { |
| 618 | 782 | // Delete the row from the legacy table. |
| 619 | 783 | $this->db->delete( $this->get_legacy_table_name(), array( 'id' => $entity->getId() ) ); |
| 784 | + $this->bump_data_version(); | |
| 620 | 785 | } |
| 621 | 786 | } |
| 622 | 787 | |
| 623 | 788 | /** |
| @@ -677,11 +842,12 @@ | ||
| 677 | 842 | if ( ! empty( $indexes ) ) { |
| 678 | 843 | $indexes = ', ' . $indexes; |
| 679 | 844 | } |
| 680 | 845 | |
| 681 | - $sql = sprintf( $this->get_create_table_sql(), $indexes ); | |
| 846 | + $sql = \sprintf( $this->get_create_table_sql(), $indexes ); | |
| 682 | 847 | require_once ABSPATH . 'wp-admin/includes/upgrade.php'; |
| 683 | 848 | $result = \dbDelta( $sql ); |
| 849 | + $this->invalidate_table_exists_cache( $this->get_table_name() ); | |
| 684 | 850 | if ( ! $this->table_exists() ) { |
| 685 | 851 | throw new Exception( \esc_html( "SQL: $sql\nResult: " . implode( '. ', $result ) ) ); |
| 686 | 852 | } |
| 687 | 853 | } |
| @@ -695,10 +861,12 @@ | ||
| 695 | 861 | // Rename the table to legacy table if it doesn't exist. |
| 696 | 862 | if ( ! $this->table_exists( true ) && false === $this->db->query( "RENAME TABLE {$this->get_table_name()} TO {$this->get_legacy_table_name()};" ) ) { |
| 697 | 863 | throw new Exception( \esc_html( "Could not rename table {$this->get_table_name()} to {$this->get_legacy_table_name()}" ) ); |
| 698 | 864 | } |
| 865 | + $this->invalidate_table_exists_cache( $this->get_table_name() ); | |
| 866 | + $this->invalidate_table_exists_cache( $this->get_legacy_table_name() ); | |
| 699 | 867 | |
| 700 | - if ( ! $this->table_exists() ) { | |
| 868 | + if ( ! $this->table_exists() ) { | |
| 701 | 869 | // Create the table if not exists. |
| 702 | 870 | $this->create_table(); |
| 703 | 871 | |
| 704 | 872 | // Add the auto-increment next value to the new table. |
| @@ -723,9 +891,14 @@ | ||
| 723 | 891 | if ( ! empty( $raw_results ) ) { |
| 724 | 892 | // Legacy table is not empty, do not remove it. |
| 725 | 893 | return false; |
| 726 | 894 | } |
| 727 | - return false !== $this->db->query( "DROP TABLE IF EXISTS `{$this->get_legacy_table_name()}`;" ); | |
| 895 | + $dropped = false !== $this->db->query( "DROP TABLE IF EXISTS `{$this->get_legacy_table_name()}`;" ); | |
| 896 | + if ( $dropped ) { | |
| 897 | + $this->invalidate_table_exists_cache( $this->get_legacy_table_name() ); | |
| 898 | + $this->bump_data_version(); | |
| 899 | + } | |
| 900 | + return $dropped; | |
| 728 | 901 | } |
| 729 | 902 | |
| 730 | 903 | /** |
| 731 | 904 | * Get a list of indexes that are required for the table. |