Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 81 additions & 7 deletions Controller/Admin/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,18 @@ public function index(Request $request, Connection $em)

$formFile = $form['import_file']->getData();

$tmpFile = $formFile->getClientOriginalName();
$originalName = $formFile->getClientOriginalName();
// 許可された拡張子のホワイトリスト(二重拡張子を先に判定)
$allowedExtensions = ['tar.gz', 'tar.bz2', 'tgz', 'tar', 'zip'];
$originalExtension = pathinfo($originalName, PATHINFO_EXTENSION);
$lowerName = strtolower($originalName);
foreach ($allowedExtensions as $ext) {
if (substr($lowerName, -strlen('.' . $ext)) === '.' . $ext) {
$originalExtension = $ext;
break;
}
}
$tmpFile = 'import_' . bin2hex(random_bytes(8)) . '.' . $originalExtension;
$tmpDir = $this->pluginService->createTempDir();
$formFile->move($tmpDir, $tmpFile);

Expand Down Expand Up @@ -159,8 +170,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 +1070,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 +1105,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 +1157,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 +1878,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 +2391,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();
}
}
20 changes: 19 additions & 1 deletion 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 @@ -74,6 +80,15 @@ public function setMigrationVersion($em, $tmpDir, $tmpFile)
{
$archive = UnifiedArchive::open($tmpDir . '/' . $tmpFile);
$fileNames = $archive->getFileNames();

// パストラバーサル防御: アーカイブ内のエントリ名を検証
foreach ($fileNames as $entry) {
$normalized = str_replace('\\', '/', $entry);
if (strpos($normalized, '..') !== false || strpos($normalized, '/') === 0) {
throw new \RuntimeException('アーカイブに不正なパスが含まれています: ' . basename($entry));
}
}

// 解凍
$archive->extractFiles($tmpDir, $fileNames);

Expand Down Expand Up @@ -178,7 +193,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
Binary file modified Tests/Fixtures/member_test.tar.gz
Binary file not shown.
Loading
Loading