38471-vm/db/migrations/20260502_zzz_payment_methods_schema_sync.php
2026-05-02 05:05:46 +00:00

178 lines
5.8 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../config.php';
if (!function_exists('payment_methods_schema_sync_20260502_run')) {
function payment_methods_schema_sync_20260502_run(): void
{
$pdo = db();
payment_methods_schema_sync_20260502_exec(
$pdo,
"CREATE TABLE IF NOT EXISTS `payment_methods` (
"
. " `id` int(11) NOT NULL AUTO_INCREMENT,
"
. " `name_en` varchar(255) DEFAULT NULL,
"
. " `name_ar` varchar(255) DEFAULT NULL,
"
. " `created_at` timestamp NULL DEFAULT current_timestamp(),
"
. " PRIMARY KEY (`id`)
"
. ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$columns = [
'name_en' => 'VARCHAR(255) DEFAULT NULL',
'name_ar' => 'VARCHAR(255) DEFAULT NULL',
'created_at' => 'TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP',
];
foreach ($columns as $column => $definition) {
if (payment_methods_schema_sync_20260502_column_exists($pdo, 'payment_methods', $column)) {
continue;
}
payment_methods_schema_sync_20260502_exec(
$pdo,
sprintf(
'ALTER TABLE `payment_methods` ADD COLUMN `%s` %s',
str_replace('`', '', $column),
$definition
)
);
}
payment_methods_schema_sync_20260502_backfill_legacy_names($pdo);
payment_methods_schema_sync_20260502_seed_defaults($pdo);
}
function payment_methods_schema_sync_20260502_table_exists(PDO $pdo, string $table): bool
{
$stmt = $pdo->prepare(
'SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table LIMIT 1'
);
$stmt->execute(['table' => $table]);
return (bool)$stmt->fetchColumn();
}
function payment_methods_schema_sync_20260502_column_exists(PDO $pdo, string $table, string $column): bool
{
$stmt = $pdo->prepare(
'SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table AND COLUMN_NAME = :column LIMIT 1'
);
$stmt->execute([
'table' => $table,
'column' => $column,
]);
return (bool)$stmt->fetchColumn();
}
function payment_methods_schema_sync_20260502_backfill_legacy_names(PDO $pdo): void
{
if (!payment_methods_schema_sync_20260502_table_exists($pdo, 'payment_methods')) {
return;
}
$hasLegacyName = payment_methods_schema_sync_20260502_column_exists($pdo, 'payment_methods', 'name');
$hasNameEn = payment_methods_schema_sync_20260502_column_exists($pdo, 'payment_methods', 'name_en');
$hasNameAr = payment_methods_schema_sync_20260502_column_exists($pdo, 'payment_methods', 'name_ar');
if ($hasLegacyName && $hasNameEn) {
$pdo->exec(
"UPDATE `payment_methods`
SET `name_en` = CASE
WHEN `name_en` IS NULL OR TRIM(`name_en`) = '' THEN `name`
ELSE `name_en`
END
WHERE `name` IS NOT NULL AND TRIM(`name`) <> ''"
);
}
if ($hasNameAr) {
$sourceExpression = $hasLegacyName ? "COALESCE(NULLIF(`name_en`, ''), `name`)" : '`name_en`';
$pdo->exec(
"UPDATE `payment_methods`
SET `name_ar` = $sourceExpression
WHERE (`name_ar` IS NULL OR TRIM(`name_ar`) = '')
AND $sourceExpression IS NOT NULL
AND TRIM($sourceExpression) <> ''"
);
}
}
function payment_methods_schema_sync_20260502_seed_defaults(PDO $pdo): void
{
if (!payment_methods_schema_sync_20260502_table_exists($pdo, 'payment_methods')) {
return;
}
$count = (int)$pdo->query('SELECT COUNT(*) FROM `payment_methods`')->fetchColumn();
if ($count > 0) {
return;
}
$defaults = [
['Cash', 'كاش'],
['Credit Card', 'بطاقة بنكية'],
['Bank Transfer', 'تحويل بنكي'],
];
$stmt = $pdo->prepare('INSERT INTO `payment_methods` (`name_en`, `name_ar`) VALUES (?, ?)');
foreach ($defaults as [$nameEn, $nameAr]) {
$stmt->execute([$nameEn, $nameAr]);
}
}
function payment_methods_schema_sync_20260502_exec(PDO $pdo, string $statement): void
{
try {
$pdo->exec($statement);
} catch (PDOException $exception) {
if (payment_methods_schema_sync_20260502_is_ignorable($exception)) {
return;
}
throw $exception;
}
}
function payment_methods_schema_sync_20260502_is_ignorable(PDOException $exception): bool
{
$driverCode = isset($exception->errorInfo[1]) ? (int)$exception->errorInfo[1] : null;
$message = strtolower($exception->getMessage());
$ignorableCodes = [1050, 1060, 1061, 1062, 1091, 1826];
$ignorableSnippets = [
'already exists',
'duplicate column name',
'duplicate key name',
'duplicate entry',
'duplicate foreign key constraint name',
'duplicate key on write or update',
'errno: 121',
'check that column/key exists',
];
if ($driverCode !== null && in_array($driverCode, $ignorableCodes, true)) {
return true;
}
foreach ($ignorableSnippets as $snippet) {
if (str_contains($message, $snippet)) {
return true;
}
}
return false;
}
}
payment_methods_schema_sync_20260502_run();
return true;