| @@ -2,8 +2,9 @@ | ||
| 2 | 2 | |
| 3 | 3 | namespace SyncBasalam\Migrations; |
| 4 | 4 | |
| 5 | 5 | use SyncBasalam\Admin\Settings\SettingsConfig; |
| 6 | +use SyncBasalam\Services\Products\ProductConnection; | |
| 6 | 7 | use SyncBasalam\Services\WebhookService; |
| 7 | 8 | use SyncBasalam\Utilities\ProductMetaKey; |
| 8 | 9 | |
| 9 | 10 | defined('ABSPATH') || exit; |
| @@ -22,8 +23,9 @@ | ||
| 22 | 23 | $source = $this->wpdb->prefix . 'bsl_payments'; |
| 23 | 24 | $target = $this->wpdb->prefix . 'sync_basalam_payments'; |
| 24 | 25 | |
| 25 | 26 | if ($this->tableExists($source) && $this->tableExists($target)) { |
| 27 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 26 | 28 | $this->wpdb->query("INSERT INTO $target (payment_id, invoice_id, user_id, city_id, province_id, order_id) |
| 27 | 29 | SELECT payment_id, invoice_id, user_id, city_id, province_id, order_id FROM $source"); |
| 28 | 30 | } |
| 29 | 31 | } |
| @@ -33,8 +35,9 @@ | ||
| 33 | 35 | $source = $this->wpdb->prefix . 'bsl_map_options'; |
| 34 | 36 | $target = $this->wpdb->prefix . 'sync_basalam_map_options'; |
| 35 | 37 | |
| 36 | 38 | if ($this->tableExists($source) && $this->tableExists($target)) { |
| 39 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 37 | 40 | $this->wpdb->query("INSERT INTO $target (woo_name, sync_basalam_name) |
| 38 | 41 | SELECT woo_name, bslm_name FROM $source"); |
| 39 | 42 | } |
| 40 | 43 | } |
| @@ -44,8 +47,9 @@ | ||
| 44 | 47 | $source = $this->wpdb->prefix . 'bsl_uploaded_photo'; |
| 45 | 48 | $target = $this->wpdb->prefix . 'sync_basalam_uploaded_media'; |
| 46 | 49 | |
| 47 | 50 | if ($this->tableExists($source) && $this->tableExists($target)) { |
| 51 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 48 | 52 | $this->wpdb->query( |
| 49 | 53 | "INSERT IGNORE INTO {$target} (type, source_identity, media_id, media_url, created_at) |
| 50 | 54 | SELECT 'photo', CONCAT('attachment:', woo_photo_id), bslm_photo_id, bslm_photo_url, NOW() |
| 51 | 55 | FROM {$source} |
| @@ -55,8 +59,9 @@ | ||
| 55 | 59 | } |
| 56 | 60 | |
| 57 | 61 | public function migratePostMeta() |
| 58 | 62 | { |
| 63 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 59 | 64 | $this->wpdb->query( |
| 60 | 65 | "UPDATE {$this->wpdb->postmeta} |
| 61 | 66 | SET meta_key = REPLACE(meta_key, 'bslm_', 'sync_basalam_') |
| 62 | 67 | WHERE meta_key LIKE '%bslm_%'" |
| @@ -61,8 +66,9 @@ | ||
| 61 | 66 | SET meta_key = REPLACE(meta_key, 'bslm_', 'sync_basalam_') |
| 62 | 67 | WHERE meta_key LIKE '%bslm_%'" |
| 63 | 68 | ); |
| 64 | 69 | |
| 70 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 65 | 71 | $this->wpdb->query( |
| 66 | 72 | "UPDATE {$this->wpdb->postmeta} |
| 67 | 73 | SET meta_key = REPLACE(meta_key, 'bsl_', 'sync_basalam_') |
| 68 | 74 | WHERE meta_key LIKE '%bsl_%'" |
| @@ -70,8 +76,9 @@ | ||
| 70 | 76 | } |
| 71 | 77 | |
| 72 | 78 | public function migrateOptionsRows() |
| 73 | 79 | { |
| 80 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 74 | 81 | $this->wpdb->query( |
| 75 | 82 | "UPDATE {$this->wpdb->options} |
| 76 | 83 | SET option_name = REPLACE(option_name, 'bslm_', 'sync_basalam_') |
| 77 | 84 | WHERE option_name LIKE '%bslm_%'" |
| @@ -76,8 +83,9 @@ | ||
| 76 | 83 | SET option_name = REPLACE(option_name, 'bslm_', 'sync_basalam_') |
| 77 | 84 | WHERE option_name LIKE '%bslm_%'" |
| 78 | 85 | ); |
| 79 | 86 | |
| 87 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix / core $wpdb properties, not user input. | |
| 80 | 88 | $this->wpdb->query( |
| 81 | 89 | "UPDATE {$this->wpdb->options} |
| 82 | 90 | SET option_name = REPLACE(option_name, 'bsl_', 'sync_basalam_') |
| 83 | 91 | WHERE option_name LIKE '%bsl_%'" |
| @@ -87,8 +95,9 @@ | ||
| 87 | 95 | public function migrateActions() |
| 88 | 96 | { |
| 89 | 97 | $source = $this->wpdb->prefix . 'actionscheduler_actions'; |
| 90 | 98 | |
| 99 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input; values are prepared. | |
| 91 | 100 | $this->wpdb->query( |
| 92 | 101 | $this->wpdb->prepare( |
| 93 | 102 | "UPDATE $source |
| 94 | 103 | SET hook = REPLACE(hook, 'bslm_', 'sync_basalam_') |
| @@ -97,8 +106,9 @@ | ||
| 97 | 106 | 'pending' |
| 98 | 107 | ) |
| 99 | 108 | ); |
| 100 | 109 | |
| 110 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input; values are prepared. | |
| 101 | 111 | $this->wpdb->query( |
| 102 | 112 | $this->wpdb->prepare( |
| 103 | 113 | "UPDATE $source |
| 104 | 114 | SET hook = REPLACE(hook, 'bsl_', 'sync_basalam_') |
| @@ -112,8 +122,9 @@ | ||
| 112 | 122 | public function migrateSettings() |
| 113 | 123 | { |
| 114 | 124 | $settingsRowName = 'sync_basalam_settings'; |
| 115 | 125 | |
| 126 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from core $wpdb property, not user input; value is prepared. | |
| 116 | 127 | $settingsSerialized = $this->wpdb->get_var( |
| 117 | 128 | $this->wpdb->prepare( |
| 118 | 129 | "SELECT option_value FROM {$this->wpdb->options} WHERE option_name = %s", |
| 119 | 130 | $settingsRowName |
| @@ -132,9 +143,9 @@ | ||
| 132 | 143 | 'basalam_token' => 'token', |
| 133 | 144 | 'basalam_refresh_token' => 'refresh_token', |
| 134 | 145 | 'basalam_vendor_id' => 'vendor_id', |
| 135 | 146 | 'basalam_is_vendor' => 'is_vendor', |
| 136 | - 'basalam_increase' => 'increase_price_value', | |
| 147 | + 'basalam_increase' => 'price_change_value', | |
| 137 | 148 | 'basalam_round' => 'round_price', |
| 138 | 149 | 'basalam_webhook_token' => 'webhook_header_token', |
| 139 | 150 | 'basalam_auto_confirm_order' => 'auto_confirm_order', |
| 140 | 151 | 'basalam_product_wholesale' => 'all_products_wholesale', |
| @@ -157,8 +168,9 @@ | ||
| 157 | 168 | ]; |
| 158 | 169 | |
| 159 | 170 | foreach ($tables as $table) { |
| 160 | 171 | if ($this->tableExists($table)) { |
| 172 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 161 | 173 | $this->wpdb->query("RENAME TABLE $table TO {$table}_old"); |
| 162 | 174 | } |
| 163 | 175 | } |
| 164 | 176 | } |
| @@ -165,8 +177,9 @@ | ||
| 165 | 177 | |
| 166 | 178 | private function tableExists($table) |
| 167 | 179 | { |
| 168 | 180 | |
| 181 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Legacy-data migration; no object cache for these one-time operational queries. | |
| 169 | 182 | return $this->wpdb->get_var($this->wpdb->prepare("SHOW TABLES LIKE %s", $table)) === $table; |
| 170 | 183 | } |
| 171 | 184 | |
| 172 | 185 | private function columnExists($table, $column) |
| @@ -171,8 +184,9 @@ | ||
| 171 | 184 | |
| 172 | 185 | private function columnExists($table, $column) |
| 173 | 186 | { |
| 174 | 187 | |
| 188 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input; value is prepared. | |
| 175 | 189 | $result = $this->wpdb->get_results($this->wpdb->prepare( |
| 176 | 190 | "SHOW COLUMNS FROM `$table` LIKE %s", |
| 177 | 191 | $column |
| 178 | 192 | )); |
| @@ -185,8 +199,9 @@ | ||
| 185 | 199 | |
| 186 | 200 | $table = $this->wpdb->prefix . 'sync_basalam_uploaded_photo'; |
| 187 | 201 | |
| 188 | 202 | if ($this->tableExists($table) && !$this->columnExists($table, 'created_at')) { |
| 203 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 189 | 204 | $this->wpdb->query("ALTER TABLE $table ADD COLUMN created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); |
| 190 | 205 | } |
| 191 | 206 | } |
| 192 | 207 | |
| @@ -211,8 +226,9 @@ | ||
| 211 | 226 | ]; |
| 212 | 227 | |
| 213 | 228 | foreach ($columns as $columnName => $sql) { |
| 214 | 229 | if (!$this->columnExists($table, $columnName)) { |
| 230 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; ALTER statement built from static SQL with a $wpdb->prefix table identifier, not user input. | |
| 215 | 231 | $this->wpdb->query($sql); |
| 216 | 232 | } |
| 217 | 233 | } |
| 218 | 234 | } |
| @@ -224,8 +240,9 @@ | ||
| 224 | 240 | if (!$this->tableExists($table)) { |
| 225 | 241 | return; |
| 226 | 242 | } |
| 227 | 243 | |
| 244 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Legacy-data migration; no object cache for these one-time operational queries; values are prepared. | |
| 228 | 245 | $existingIndex = $this->wpdb->get_var( |
| 229 | 246 | $this->wpdb->prepare( |
| 230 | 247 | "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS |
| 231 | 248 | WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND INDEX_NAME = %s LIMIT 1", |
| @@ -240,8 +257,9 @@ | ||
| 240 | 257 | |
| 241 | 258 | $this->removeDuplicateInvoicePayments($table); |
| 242 | 259 | |
| 243 | 260 | $this->wpdb->hide_errors(); |
| 261 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 244 | 262 | $this->wpdb->query("ALTER TABLE {$table} ADD UNIQUE KEY unique_invoice_id (invoice_id)"); |
| 245 | 263 | $this->wpdb->show_errors(); |
| 246 | 264 | } |
| 247 | 265 | |
| @@ -246,8 +264,9 @@ | ||
| 246 | 264 | } |
| 247 | 265 | |
| 248 | 266 | private function removeDuplicateInvoicePayments($table) |
| 249 | 267 | { |
| 268 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input. | |
| 250 | 269 | $duplicates = $this->wpdb->get_results( |
| 251 | 270 | "SELECT invoice_id, MIN(id) AS keep_id |
| 252 | 271 | FROM {$table} |
| 253 | 272 | WHERE invoice_id IS NOT NULL AND invoice_id > 0 |
| @@ -262,8 +281,9 @@ | ||
| 262 | 281 | foreach ($duplicates as $duplicate) { |
| 263 | 282 | $invoiceId = (int) $duplicate->invoice_id; |
| 264 | 283 | $keepId = (int) $duplicate->keep_id; |
| 265 | 284 | |
| 285 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input; values are prepared. | |
| 266 | 286 | $rowsToDelete = $this->wpdb->get_results( |
| 267 | 287 | $this->wpdb->prepare( |
| 268 | 288 | "SELECT id, order_id FROM {$table} WHERE invoice_id = %d AND id <> %d", |
| 269 | 289 | $invoiceId, |
| @@ -285,8 +305,9 @@ | ||
| 285 | 305 | } |
| 286 | 306 | } |
| 287 | 307 | } |
| 288 | 308 | |
| 309 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Legacy-data migration; no object cache for these one-time operational queries. | |
| 289 | 310 | $this->wpdb->delete($table, ['id' => (int) $row->id], ['%d']); |
| 290 | 311 | } |
| 291 | 312 | |
| 292 | 313 | \SyncBasalam\Logger\Logger::debug( |
| @@ -298,14 +319,17 @@ | ||
| 298 | 319 | public function addRetryAfterColumnToJobManager() |
| 299 | 320 | { |
| 300 | 321 | $tableName = $this->wpdb->prefix . 'sync_basalam_job_manager'; |
| 301 | 322 | |
| 323 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from $wpdb->prefix, not user input; value is prepared. | |
| 302 | 324 | $columnExists = $this->wpdb->get_var( |
| 303 | 325 | $this->wpdb->prepare("SHOW COLUMNS FROM `{$tableName}` LIKE %s", 'retry_after') |
| 304 | 326 | ); |
| 305 | 327 | |
| 306 | 328 | if (!$columnExists) { |
| 329 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 307 | 330 | $this->wpdb->query("ALTER TABLE {$tableName} ADD COLUMN retry_after BIGINT(20) NULL DEFAULT NULL"); |
| 331 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 308 | 332 | $this->wpdb->query("ALTER TABLE {$tableName} ADD INDEX idx_retry_after (retry_after)"); |
| 309 | 333 | } |
| 310 | 334 | } |
| 311 | 335 | |
| @@ -329,8 +353,9 @@ | ||
| 329 | 353 | |
| 330 | 354 | foreach ($metaKeyMap as $oldMetaKey => $newMetaKey) { |
| 331 | 355 | if ($oldMetaKey === $newMetaKey) continue; |
| 332 | 356 | |
| 357 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from core $wpdb property, not user input; values are prepared. | |
| 333 | 358 | $this->wpdb->query( |
| 334 | 359 | $this->wpdb->prepare( |
| 335 | 360 | "INSERT INTO {$postmetaTable} (post_id, meta_key, meta_value) |
| 336 | 361 | SELECT old_meta.post_id, %s, old_meta.meta_value |
| @@ -345,8 +370,9 @@ | ||
| 345 | 370 | $oldMetaKey |
| 346 | 371 | ) |
| 347 | 372 | ); |
| 348 | 373 | |
| 374 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifier from core $wpdb property, not user input; value is prepared. | |
| 349 | 375 | $this->wpdb->query( |
| 350 | 376 | $this->wpdb->prepare( |
| 351 | 377 | "DELETE FROM {$postmetaTable} WHERE meta_key = %s", |
| 352 | 378 | $oldMetaKey |
| @@ -365,8 +391,29 @@ | ||
| 365 | 391 | |
| 366 | 392 | update_option('sync_basalam_settings', $settings); |
| 367 | 393 | } |
| 368 | 394 | |
| 395 | + /** | |
| 396 | + * Variant price/stock used to follow the product price/stock checkboxes of the custom sync mode. | |
| 397 | + * Copy the old values so variable products keep syncing after the new checkboxes are introduced. | |
| 398 | + */ | |
| 399 | + public function backfillVariantSyncFields() | |
| 400 | + { | |
| 401 | + $settings = get_option('sync_basalam_settings', []); | |
| 402 | + if (!is_array($settings)) return; | |
| 403 | + | |
| 404 | + // The new keys may already have been filled with their "0" default by a settings read. | |
| 405 | + if (empty($settings[SettingsConfig::SYNC_PRODUCT_FIELD_VARIANT_PRICE])) { | |
| 406 | + $settings[SettingsConfig::SYNC_PRODUCT_FIELD_VARIANT_PRICE] = $settings[SettingsConfig::SYNC_PRODUCT_FIELD_PRICE] ?? 0; | |
| 407 | + } | |
| 408 | + | |
| 409 | + if (empty($settings[SettingsConfig::SYNC_PRODUCT_FIELD_VARIANT_STOCK])) { | |
| 410 | + $settings[SettingsConfig::SYNC_PRODUCT_FIELD_VARIANT_STOCK] = $settings[SettingsConfig::SYNC_PRODUCT_FIELD_STOCK] ?? 0; | |
| 411 | + } | |
| 412 | + | |
| 413 | + update_option('sync_basalam_settings', $settings); | |
| 414 | + } | |
| 415 | + | |
| 369 | 416 | public function createUploadedMediaTable() |
| 370 | 417 | { |
| 371 | 418 | require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); |
| 372 | 419 | |
| @@ -390,8 +437,17 @@ | ||
| 390 | 437 | |
| 391 | 438 | $this->migrateLegacyUploadedPhotos($tableName); |
| 392 | 439 | } |
| 393 | 440 | |
| 441 | + /** | |
| 442 | + * اصلاح محصولاتی که به دلیل کپی شدن، به یک محصول باسلام اتصال مشترک دارند. | |
| 443 | + * قدیمیترین محصول (محصول اصلی) متصل میماند و اتصال نسخههای کپی حذف میشود. | |
| 444 | + */ | |
| 445 | + public function repairDuplicateProductConnections(): void | |
| 446 | + { | |
| 447 | + ProductConnection::repairDuplicateConnections(); | |
| 448 | + } | |
| 449 | + | |
| 394 | 450 | private function migrateLegacyUploadedPhotos(string $targetTable): void |
| 395 | 451 | { |
| 396 | 452 | $legacyTable = $this->wpdb->prefix . 'sync_basalam_uploaded_photo'; |
| 397 | 453 | |
| @@ -396,8 +452,9 @@ | ||
| 396 | 452 | $legacyTable = $this->wpdb->prefix . 'sync_basalam_uploaded_photo'; |
| 397 | 453 | |
| 398 | 454 | if (!$this->tableExists($legacyTable)) return; |
| 399 | 455 | |
| 456 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Legacy-data migration; table identifiers from $wpdb->prefix, not user input. | |
| 400 | 457 | $this->wpdb->query( |
| 401 | 458 | "INSERT IGNORE INTO {$targetTable} (type, source_identity, media_id, media_url, created_at) |
| 402 | 459 | SELECT 'photo', CONCAT('attachment:', woo_photo_id), sync_basalam_photo_id, sync_basalam_photo_url, COALESCE(created_at, NOW()) |
| 403 | 460 | FROM {$legacyTable} |
| @@ -403,8 +460,9 @@ | ||
| 403 | 460 | FROM {$legacyTable} |
| 404 | 461 | WHERE woo_photo_id IS NOT NULL" |
| 405 | 462 | ); |
| 406 | 463 | |
| 464 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter -- One-time schema migration; table identifier from $wpdb->prefix, not user input. | |
| 407 | 465 | $this->wpdb->query("DROP TABLE IF EXISTS {$legacyTable}"); |
| 408 | 466 | } |
| 409 | 467 | |
| 410 | 468 | } |