diff --git a/plugins/baser-core/src/Service/BcDatabaseService.php b/plugins/baser-core/src/Service/BcDatabaseService.php index 7c95c473b8..3d0316a7b3 100644 --- a/plugins/baser-core/src/Service/BcDatabaseService.php +++ b/plugins/baser-core/src/Service/BcDatabaseService.php @@ -718,13 +718,18 @@ public function loadCsvToArray($path, $encoding = 'auto') return false; } - $head = fgetcsv($fp, 10240); + $head = fgetcsv($fp, null, ',', '"', ''); + if ($head === false || $head === [null] || $head === []) { + fclose($fp); + return []; + } // UTF-8(BOM付)で何故か、配列の最初のキーに""が付加されてしまう - $head[0] = preg_replace('/^(.+)$/', "$1", $head[0]); - $head[0] = preg_replace('/^"(.+)"$/', "$1", $head[0]); - + $head[0] = preg_replace("/^\xEF\xBB\xBF(.+)$/", '$1', (string)$head[0]); + $head[0] = preg_replace('/^"(.+)"$/', "$1", (string)$head[0]); $records = []; - while(($record = BcUtil::fgetcsvReg($fp, 10240)) !== false) { + // length = null(行長制限なし) escape = 空文字(独自エスケープ無効) + while(($record = fgetcsv($fp, null, ',', '"', '')) !== false) { + if ($record === [null] || $record === []) continue; if ($encoding && $appEncoding != $encoding) { mb_convert_variables($appEncoding, $encoding, $record); } diff --git a/plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php b/plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php index 47a8183645..aec6bc6c92 100644 --- a/plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php +++ b/plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php @@ -348,16 +348,32 @@ public function test_loadCsvToArray() //SJIS のCSVファイルを作成 $options = [ 'path' => $path, - 'encoding' => 'sjis', + 'encoding' => 'SJIS-win', 'init' => false, ]; $this->BcDatabaseService->writeCsv('contents', $options); - $rs = $this->BcDatabaseService->loadCsvToArray($path); + $rs = $this->BcDatabaseService->loadCsvToArray($path, 'SJIS-win'); $this->assertIsArray($rs); // 戻り値の配列の値のエンコードがUTF-8になっている事を確認 $this->assertEquals('メインサイト', $rs[0]['title']); $this->assertTrue(mb_check_encoding($rs[0]['title'], 'UTF-8')); + // SJISのCSVで「能」や埋め込み引用符を含んでも正しくUTF-8へ変換できることを確認 + $csvContent = "\"a\",\"i\",\"u\",\"e\"\n"; + $csvContent .= "\"あ\",\"い\",\"う\",\"能\"\"能\"\n"; + file_put_contents($path, mb_convert_encoding($csvContent, 'SJIS-win', 'UTF-8')); + $rs = $this->BcDatabaseService->loadCsvToArray($path, 'SJIS-win'); + $this->assertEquals('能"能', $rs[0]['e']); + $this->assertTrue(mb_check_encoding($rs[0]['e'], 'UTF-8')); + + // 長大な引用符を含む値でも、列が欠落せずに読み込めることを確認 + $csvContent = "\"a\",\"i\",\"u\",\"e\"\n"; + $csvContent .= "\"あ\",\"い\",\"う\",\"" . str_repeat('""', 13000) . "\"\n"; + file_put_contents($path, $csvContent); + $rs = $this->BcDatabaseService->loadCsvToArray($path, 'UTF-8'); + $this->assertCount(4, $rs[0]); + $this->assertEquals(13000, strlen($rs[0]['e'])); + $file = new BcFile($path); $file->delete(); }