Skip to content
Closed
75 changes: 69 additions & 6 deletions Controller/Admin/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,11 @@ public function index(Request $request, Connection $em)

// 全データ移行
$this->saveCustomer($em, $csvDir);
$this->releaseCustomerPhaseMemory();
$this->saveProduct($em, $csvDir);
$this->releaseProductPhaseMemory();
$this->saveOrder($em, $csvDir);
$this->releaseOrderPhaseMemory();
}

// plg_customerplusの移行処理を作る
Expand Down Expand Up @@ -1056,8 +1059,14 @@ protected function upsertAuthorityAndMember($em, $dir)
]);
}
if ($hasMember) {
// 既存メンバーを一旦非稼働化
$em->exec('UPDATE dtb_member SET work_id = 0');
// 2.x系の場合はDELETE+INSERTで全置換(MySQL saveToC と同等)
$is2xData = !$this->dataMigrationService->isVersion('4.0/4.1');
if ($is2xData) {
$this->dataMigrationService->resetTable($em, 'dtb_member');
} else {
// 4.0/4.1系:既存メンバーを一旦非稼働化してUPSERT
$em->exec('UPDATE dtb_member SET work_id = 0');
}
// CSV を読み取り UPSERT
$file = $memberCsv;
if (($handle = fopen($file, 'r')) === false) {
Expand Down Expand Up @@ -1085,7 +1094,25 @@ protected function upsertAuthorityAndMember($em, $dir)
$insertValues[$col] = $data[$col] ?? 'member';
continue;
}
// 4.0系のカラム名マッピング
// 2.x系: member_id → id
if ($col === 'id' && !array_key_exists('id', $data) && array_key_exists('member_id', $data)) {
$insertValues[$col] = $data['member_id'];
continue;
}
// 2.x系: authority → authority_id, work → work_id
if ($col === 'authority_id' && !array_key_exists($col, $data) && array_key_exists('authority', $data)) {
$insertValues[$col] = $data['authority'];
continue;
}
if ($col === 'work_id' && !array_key_exists($col, $data) && array_key_exists('work', $data)) {
$insertValues[$col] = ($data['del_flg'] ?? '0') === '1' ? 0 : $data['work'];
continue;
}
if ($col === 'sort_no' && !array_key_exists($col, $data) && array_key_exists('rank', $data)) {
$insertValues[$col] = $data['rank'];
continue;
}
// 4.0系: work_id → work, authority_id → authority
if ($col === 'work' && !array_key_exists($col, $data) && array_key_exists('work_id', $data)) {
$insertValues[$col] = $data['work_id'];
continue;
Expand Down Expand Up @@ -1119,15 +1146,23 @@ protected function upsertAuthorityAndMember($em, $dir)
$insertValues['two_factor_auth_enabled'] = 0;
}
if (array_key_exists('two_factor_auth_key', $insertValues) && $insertValues['two_factor_auth_key'] === null) {
$insertValues['two_factor_auth_key'] = null; // NULL許可(この行は冗長だが明示的に残す)
$insertValues['two_factor_auth_key'] = null;
}
// saveToC と同等: creator_id のデフォルト値
if (array_key_exists('creator_id', $insertValues) && empty($insertValues['creator_id'])) {
$insertValues['creator_id'] = 1;
}
// PostgreSQL用の型変換
$insertValues = $this->dataMigrationService->convertDataTypesForPostgreSQL($em, 'dtb_member', $insertValues);
$colsSql = implode(',', array_map(fn($c) => '"' . $c . '"', array_keys($insertValues)));
$placeholders = implode(',', array_fill(0, count($insertValues), '?'));
$updateSql = implode(', ', array_map(fn($c) => '"' . $c . '" = EXCLUDED."' . $c . '"', $updateCols));
$sql = 'INSERT INTO dtb_member (' . $colsSql . ') VALUES (' . $placeholders . ') ON CONFLICT (id) DO UPDATE SET ' . $updateSql;
$em->prepare($sql)->executeStatement(array_values($insertValues));
}
fclose($handle);
// PostgreSQL: シーケンスを最大ID+1にリセット
$this->dataMigrationService->setIdSeq($em, 'dtb_member');
}
// メンバーIDキャッシュ
try {
Expand Down Expand Up @@ -1832,8 +1867,10 @@ private function saveToO($em, $tmpDir, $csvName, $tableName = null, $allow_zero
}
}

// shippingに紐付けるデータを保持
$this->shipping_order[$data['id']] = $data;
// shippingに紐付けるデータを保持(必要なフィールドのみ)
$this->shipping_order[$data['id']] = [
'commit_date' => $data['commit_date'] ?? null,
];

break;

Expand Down Expand Up @@ -2343,4 +2380,30 @@ private function fix4x($em, $tmpDir, $csvName)
return $i; // indexを返す
}
}

private function releaseCustomerPhaseMemory(): void
{
$this->customer_point = [];
gc_collect_cycles();
}

private function releaseProductPhaseMemory(): void
{
$this->stock = [];
$this->product_images = [];
$this->dtb_class_combination = [];
$this->delivery_id = [];
$this->product_class_id = [];
gc_collect_cycles();
}

private function releaseOrderPhaseMemory(): void
{
$this->order_item = [];
$this->shipping_id = [];
$this->shipping_order = [];
$this->tax_rule = [];
$this->delivery_time = [];
gc_collect_cycles();
}
}
45 changes: 29 additions & 16 deletions Service/DataMigrationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class DataMigrationService
*/
private $mappingCache = [];

/**
* テーブルカラム情報のキャッシュ(テーブル名 => カラム配列)
* @var array
*/
private $tableColumnsCache = [];

/**
* Customer item option data for migration
* @var array
Expand Down Expand Up @@ -136,21 +142,23 @@ public function updateEnv($newMagicValue)
file_put_contents($envFile, $env);
}

public function resetTable(Connection $em, $tableName)
/**
* テーブル名のバリデーション
*/
private function validateTableName(string $tableName): void
{
$platform = $em->getDatabasePlatform()->getName();

if ($platform == 'mysql') {
$em->exec('DELETE FROM ' . $tableName);
} elseif ($platform == 'postgresql') {
// PostgreSQLでは fix4x() はUPSERTを使うため、このメソッドは呼ばれない
// saveToC() などから呼ばれる場合はDELETEを実行
$em->exec('DELETE FROM "' . $tableName . '"');
} else {
$em->exec('DELETE FROM ' . $tableName);
if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]{0,63}$/', $tableName)) {
throw new \InvalidArgumentException('Invalid table name: ' . $tableName);
}
}

public function resetTable(Connection $em, $tableName)
{
$this->validateTableName($tableName);
$quoted = $em->quoteIdentifier($tableName);
$em->executeStatement('DELETE FROM ' . $quoted);
}

public function convertNULL($data)
{
foreach ($data as &$v) {
Expand Down Expand Up @@ -178,7 +186,10 @@ public function convertDataTypesForPostgreSQL($em, $tableName, $data)


try {
$columns = $em->getSchemaManager()->listTableColumns($tableName);
if (!isset($this->tableColumnsCache[$tableName])) {
$this->tableColumnsCache[$tableName] = $em->getSchemaManager()->listTableColumns($tableName);
}
$columns = $this->tableColumnsCache[$tableName];
$hasConversion = false;

foreach ($data as $key => &$value) {
Expand Down Expand Up @@ -305,7 +316,7 @@ public function begin($em, $context = NULL)
foreach ($targetTables as $t) {
$exists = $em->fetchOne("SELECT 1 FROM pg_tables WHERE schemaname='public' AND tablename=?", [$t]);
if ($exists) {
$existing[] = '"' . str_replace('"', '""', $t) . '"';
$existing[] = $em->quoteIdentifier($t);
}
}
if ($existing) {
Expand All @@ -324,11 +335,13 @@ public function begin($em, $context = NULL)

public function setIdSeq($em, $tableName)
{
$max = $em->fetchOne('SELECT coalesce(max(id), 0) + 1 FROM ' . $tableName);
$this->validateTableName($tableName);
$quoted = $em->quoteIdentifier($tableName);
$max = (int) $em->fetchOne('SELECT COALESCE(MAX(id), 0) + 1 FROM ' . $quoted);
$seq = $tableName . '_id_seq';
$count = $em->fetchOne("select count(*) from pg_class where relname = '$seq';");
$count = $em->fetchOne('SELECT COUNT(*) FROM pg_class WHERE relname = ?', [$seq]);
if ($count) {
$em->exec("SELECT setval('$seq', $max);");
$em->executeStatement('SELECT setval(?, ?)', [$seq, $max]);
}
}

Expand Down
Binary file modified Tests/Fixtures/member_test.tar.gz
Binary file not shown.
Loading
Loading