| Server IP : 185.143.234.238 / Your IP : 185.215.232.195 Web Server : LiteSpeed System : Linux saman.shetabanhost.com 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64 User : behrakir ( 1361) PHP Version : 8.1.34 Disable Function : symlink,shell_exec,show_source,exec,popen,system,passthru,proc_open,proc_close,pcntl_exec,mail MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/behrakir/khanomam.com/wp-content/plugins/sync-basalam/includes/Migrations/ |
Upload File : |
<?php
namespace SyncBasalam\Migrations;
use SyncBasalam\Admin\Settings\SettingsConfig;
use SyncBasalam\Services\WebhookService;
use SyncBasalam\Utilities\ProductMetaKey;
defined('ABSPATH') || exit;
class MigratorService
{
private $wpdb;
public function __construct()
{
global $wpdb;
$this->wpdb = $wpdb;
}
public function migratePayments()
{
$source = $this->wpdb->prefix . 'bsl_payments';
$target = $this->wpdb->prefix . 'sync_basalam_payments';
if ($this->tableExists($source) && $this->tableExists($target)) {
$this->wpdb->query("INSERT INTO $target (payment_id, invoice_id, user_id, city_id, province_id, order_id)
SELECT payment_id, invoice_id, user_id, city_id, province_id, order_id FROM $source");
}
}
public function migrateOptions()
{
$source = $this->wpdb->prefix . 'bsl_map_options';
$target = $this->wpdb->prefix . 'sync_basalam_map_options';
if ($this->tableExists($source) && $this->tableExists($target)) {
$this->wpdb->query("INSERT INTO $target (woo_name, sync_basalam_name)
SELECT woo_name, bslm_name FROM $source");
}
}
public function migrateUploadedPhotos()
{
$source = $this->wpdb->prefix . 'bsl_uploaded_photo';
$target = $this->wpdb->prefix . 'sync_basalam_uploaded_media';
if ($this->tableExists($source) && $this->tableExists($target)) {
$this->wpdb->query(
"INSERT IGNORE INTO {$target} (type, source_identity, media_id, media_url, created_at)
SELECT 'photo', CONCAT('attachment:', woo_photo_id), bslm_photo_id, bslm_photo_url, NOW()
FROM {$source}
WHERE woo_photo_id IS NOT NULL"
);
}
}
public function migratePostMeta()
{
$this->wpdb->query(
"UPDATE {$this->wpdb->postmeta}
SET meta_key = REPLACE(meta_key, 'bslm_', 'sync_basalam_')
WHERE meta_key LIKE '%bslm_%'"
);
$this->wpdb->query(
"UPDATE {$this->wpdb->postmeta}
SET meta_key = REPLACE(meta_key, 'bsl_', 'sync_basalam_')
WHERE meta_key LIKE '%bsl_%'"
);
}
public function migrateOptionsRows()
{
$this->wpdb->query(
"UPDATE {$this->wpdb->options}
SET option_name = REPLACE(option_name, 'bslm_', 'sync_basalam_')
WHERE option_name LIKE '%bslm_%'"
);
$this->wpdb->query(
"UPDATE {$this->wpdb->options}
SET option_name = REPLACE(option_name, 'bsl_', 'sync_basalam_')
WHERE option_name LIKE '%bsl_%'"
);
}
public function migrateActions()
{
$source = $this->wpdb->prefix . 'actionscheduler_actions';
$this->wpdb->query(
$this->wpdb->prepare(
"UPDATE $source
SET hook = REPLACE(hook, 'bslm_', 'sync_basalam_')
WHERE hook LIKE %s AND status = %s",
'%bslm_%',
'pending'
)
);
$this->wpdb->query(
$this->wpdb->prepare(
"UPDATE $source
SET hook = REPLACE(hook, 'bsl_', 'sync_basalam_')
WHERE hook LIKE %s AND status = %s",
'%bsl_%',
'pending'
)
);
}
public function migrateSettings()
{
$settingsRowName = 'sync_basalam_settings';
$settingsSerialized = $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT option_value FROM {$this->wpdb->options} WHERE option_name = %s",
$settingsRowName
)
);
if (!$settingsSerialized) return;
$settings = maybe_unserialize($settingsSerialized);
if (!is_array($settings)) return;
$keyMap = [
'basalam_client_id' => 'client_id',
'basalam_webhook_id' => 'webhook_id',
'basalam_token' => 'token',
'basalam_refresh_token' => 'refresh_token',
'basalam_vendor_id' => 'vendor_id',
'basalam_is_vendor' => 'is_vendor',
'basalam_increase' => 'increase_price_value',
'basalam_round' => 'round_price',
'basalam_webhook_token' => 'webhook_header_token',
'basalam_auto_confirm_order' => 'auto_confirm_order',
'basalam_product_wholesale' => 'all_products_wholesale',
];
$newSettings = [];
foreach ($settings as $key => $value) {
$newSettings[$keyMap[$key] ?? $key] = $value;
}
update_option($settingsRowName, $newSettings);
}
public function renameOldTables()
{
$tables = [
$this->wpdb->prefix . 'bsl_payments',
$this->wpdb->prefix . 'bsl_map_options',
$this->wpdb->prefix . 'bsl_uploaded_photo',
];
foreach ($tables as $table) {
if ($this->tableExists($table)) {
$this->wpdb->query("RENAME TABLE $table TO {$table}_old");
}
}
}
private function tableExists($table)
{
return $this->wpdb->get_var($this->wpdb->prepare("SHOW TABLES LIKE %s", $table)) === $table;
}
private function columnExists($table, $column)
{
$result = $this->wpdb->get_results($this->wpdb->prepare(
"SHOW COLUMNS FROM `$table` LIKE %s",
$column
));
return !empty($result);
}
public function addCreatedAtColumnToUploadedPhoto()
{
$table = $this->wpdb->prefix . 'sync_basalam_uploaded_photo';
if ($this->tableExists($table) && !$this->columnExists($table, 'created_at')) {
$this->wpdb->query("ALTER TABLE $table ADD COLUMN created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
}
}
public function addNewWebhookEvents()
{
$webhookService = new WebhookService();
$webhookService->setupWebhook();
}
public function addFinancialDataColumns()
{
$table = $this->wpdb->prefix . 'sync_basalam_payments';
if (!$this->tableExists($table)) {
return;
}
$columns = [
'fee_amount' => "ALTER TABLE $table ADD COLUMN fee_amount DECIMAL(10,2) DEFAULT 0",
'balance_amount' => "ALTER TABLE $table ADD COLUMN balance_amount DECIMAL(10,2) DEFAULT 0",
'purchase_count' => "ALTER TABLE $table ADD COLUMN purchase_count INT DEFAULT 0"
];
foreach ($columns as $columnName => $sql) {
if (!$this->columnExists($table, $columnName)) {
$this->wpdb->query($sql);
}
}
}
public function addUniqueInvoiceIdIndex()
{
$table = $this->wpdb->prefix . 'sync_basalam_payments';
if (!$this->tableExists($table)) {
return;
}
$existingIndex = $this->wpdb->get_var(
$this->wpdb->prepare(
"SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND INDEX_NAME = %s LIMIT 1",
$table,
'unique_invoice_id'
)
);
if ($existingIndex) {
return;
}
$this->removeDuplicateInvoicePayments($table);
$this->wpdb->hide_errors();
$this->wpdb->query("ALTER TABLE {$table} ADD UNIQUE KEY unique_invoice_id (invoice_id)");
$this->wpdb->show_errors();
}
private function removeDuplicateInvoicePayments($table)
{
$duplicates = $this->wpdb->get_results(
"SELECT invoice_id, MIN(id) AS keep_id
FROM {$table}
WHERE invoice_id IS NOT NULL AND invoice_id > 0
GROUP BY invoice_id
HAVING COUNT(*) > 1"
);
if (empty($duplicates)) {
return;
}
foreach ($duplicates as $duplicate) {
$invoiceId = (int) $duplicate->invoice_id;
$keepId = (int) $duplicate->keep_id;
$rowsToDelete = $this->wpdb->get_results(
$this->wpdb->prepare(
"SELECT id, order_id FROM {$table} WHERE invoice_id = %d AND id <> %d",
$invoiceId,
$keepId
)
);
foreach ($rowsToDelete as $row) {
$orderId = (int) ($row->order_id ?? 0);
if ($orderId > 0 && function_exists('wc_get_order')) {
$order = wc_get_order($orderId);
if ($order instanceof \WC_Order) {
try {
$order->delete(true);
} catch (\Throwable $e) {
\SyncBasalam\Logger\Logger::error(
"حذف سفارش تکراری ووکامرس با شناسه {$orderId} ناموفق بود: " . $e->getMessage()
);
}
}
}
$this->wpdb->delete($table, ['id' => (int) $row->id], ['%d']);
}
\SyncBasalam\Logger\Logger::debug(
"سفارشات تکراری برای invoice_id {$invoiceId} پاکسازی شدند، شناسه نگهداشتهشده: {$keepId}"
);
}
}
public function addRetryAfterColumnToJobManager()
{
$tableName = $this->wpdb->prefix . 'sync_basalam_job_manager';
$columnExists = $this->wpdb->get_var(
$this->wpdb->prepare("SHOW COLUMNS FROM `{$tableName}` LIKE %s", 'retry_after')
);
if (!$columnExists) {
$this->wpdb->query("ALTER TABLE {$tableName} ADD COLUMN retry_after BIGINT(20) NULL DEFAULT NULL");
$this->wpdb->query("ALTER TABLE {$tableName} ADD INDEX idx_retry_after (retry_after)");
}
}
public function migrateProductMetaKeysToVendorId()
{
$settings = get_option('sync_basalam_settings', []);
if (!is_array($settings)) return;
$vendorId = $settings[SettingsConfig::VENDOR_ID] ?? null;
$vendorId = preg_replace('/[^a-zA-Z0-9_-]/', '', (string) $vendorId);
if ($vendorId === '') return;
$postmetaTable = $this->wpdb->postmeta;
$metaKeyMap = [
ProductMetaKey::PRODUCT_ID => ProductMetaKey::basalamProductId($vendorId),
ProductMetaKey::PRODUCT_SYNC_STATUS => ProductMetaKey::basalamProductSyncStatus($vendorId),
ProductMetaKey::PRODUCT_STATUS => ProductMetaKey::basalamProductStatus($vendorId),
];
foreach ($metaKeyMap as $oldMetaKey => $newMetaKey) {
if ($oldMetaKey === $newMetaKey) continue;
$this->wpdb->query(
$this->wpdb->prepare(
"INSERT INTO {$postmetaTable} (post_id, meta_key, meta_value)
SELECT old_meta.post_id, %s, old_meta.meta_value
FROM {$postmetaTable} old_meta
LEFT JOIN {$postmetaTable} new_meta
ON new_meta.post_id = old_meta.post_id
AND new_meta.meta_key = %s
WHERE old_meta.meta_key = %s
AND new_meta.meta_id IS NULL",
$newMetaKey,
$newMetaKey,
$oldMetaKey
)
);
$this->wpdb->query(
$this->wpdb->prepare(
"DELETE FROM {$postmetaTable} WHERE meta_key = %s",
$oldMetaKey
)
);
}
}
public function clearAuthTokens()
{
$settings = get_option('sync_basalam_settings', []);
if (!is_array($settings)) return;
$settings[SettingsConfig::TOKEN] = null;
$settings[SettingsConfig::REFRESH_TOKEN] = null;
update_option('sync_basalam_settings', $settings);
}
public function createUploadedMediaTable()
{
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
$tableName = $this->wpdb->prefix . 'sync_basalam_uploaded_media';
$charsetCollate = $this->wpdb->get_charset_collate();
$sql = "CREATE TABLE $tableName (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
type VARCHAR(16) NOT NULL,
source_identity VARCHAR(191) NOT NULL,
media_id BIGINT UNSIGNED NULL,
media_url VARCHAR(2083) NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY unique_type_source (type, source_identity),
KEY idx_type_created (type, created_at),
KEY idx_created_at (created_at)
) $charsetCollate;";
dbDelta($sql);
$this->migrateLegacyUploadedPhotos($tableName);
}
private function migrateLegacyUploadedPhotos(string $targetTable): void
{
$legacyTable = $this->wpdb->prefix . 'sync_basalam_uploaded_photo';
if (!$this->tableExists($legacyTable)) return;
$this->wpdb->query(
"INSERT IGNORE INTO {$targetTable} (type, source_identity, media_id, media_url, created_at)
SELECT 'photo', CONCAT('attachment:', woo_photo_id), sync_basalam_photo_id, sync_basalam_photo_url, COALESCE(created_at, NOW())
FROM {$legacyTable}
WHERE woo_photo_id IS NOT NULL"
);
$this->wpdb->query("DROP TABLE IF EXISTS {$legacyTable}");
}
}