query($wpdb->prepare( "UPDATE %i SET `for_shipping` = NULL WHERE `for_shipping` = 1", $tableName )); } // Shipping tax overrides are edited as percentages in the admin UI and must // preserve decimal precision across both new installs and upgrades. static::modifyColumnIfExists('for_shipping', 'DECIMAL(10, 2) NULL DEFAULT NULL'); } public static function fixPostcodeRangeSeparator() { // The postcode range separator changed from "..." (legacy) and "::" (intermediate) to // "-" in the current version. Rows still using the old separators will not match ranges // at all; this one-time replacement fixes them silently on upgrade. $wpdb = Schema::db(); $tableName = static::getTableName(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query($wpdb->prepare( "UPDATE %i SET `postcode` = REPLACE(`postcode`, '...', '-') WHERE `postcode` LIKE '%%...%%'", $tableName )); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query($wpdb->prepare( "UPDATE %i SET `postcode` = REPLACE(`postcode`, '::', '-') WHERE `postcode` LIKE '%%::%%'", $tableName )); // Product category tax overrides in fct_meta carry the same postcode value inside // their JSON meta_value — normalize those rows the same way. $metaTable = static::getDbPrefix() . 'fct_meta'; $lastId = 0; $batchSize = 200; do { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $rows = $wpdb->get_results($wpdb->prepare( "SELECT `id`, `meta_value` FROM %i WHERE `object_type` = 'tax_override' AND `meta_key` = 'product_category_override' AND (`meta_value` LIKE '%%...%%' OR `meta_value` LIKE '%%::%%') AND `id` > %d ORDER BY `id` ASC LIMIT %d", $metaTable, $lastId, $batchSize ), ARRAY_A); if (!is_array($rows)) { break; } foreach ($rows as $row) { $lastId = (int) $row['id']; $data = json_decode($row['meta_value'], true); if (!is_array($data) || !isset($data['postcode'])) { continue; } $normalized = str_replace(['...', '::'], '-', $data['postcode']); if ($normalized === $data['postcode']) { continue; } $data['postcode'] = $normalized; $encoded = wp_json_encode($data); if ($encoded === false) { continue; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->update( $metaTable, ['meta_value' => $encoded], ['id' => $row['id']], ['%s'], ['%d'] ); } } while (count($rows) === $batchSize); } }