Skip to content

Commit 4b72f60

Browse files
committed
Custom writer
1 parent abafba0 commit 4b72f60

1 file changed

Lines changed: 26 additions & 22 deletions

File tree

src/Migration/Destinations/CSV.php

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ protected function import(array $resources, callable $callback): void
9595
}
9696

9797
foreach ($buffer['lines'] as $line) {
98-
if (\fputcsv($handle, $line, $this->delimiter, $this->enclosure, $this->escape) === false) {
98+
if (!$this->writeCSVLine($handle, $line)) {
9999
throw new \Exception("Failed to write CSV line to file: $log");
100100
}
101101
}
@@ -192,6 +192,29 @@ public function shutdown(): void
192192
}
193193
}
194194

195+
/**
196+
* Write a CSV line with RFC 4180 compliant escaping (double-quote method)
197+
* Optimized for maximum performance: array building + single implode
198+
* @param resource $handle
199+
* @param array $fields
200+
* @return bool
201+
*/
202+
protected function writeCSVLine($handle, array $fields): bool
203+
{
204+
$parts = [];
205+
206+
foreach ($fields as $field) {
207+
$field = (string)$field;
208+
if (\strpbrk($field, $this->delimiter . "\n\r" . $this->enclosure) !== false) {
209+
$parts[] = $this->enclosure . \str_replace($this->enclosure, $this->enclosure . $this->enclosure, $field) . $this->enclosure;
210+
} else {
211+
$parts[] = $field;
212+
}
213+
}
214+
215+
return \fwrite($handle, \implode($this->delimiter, $parts) . "\n") !== false;
216+
}
217+
195218
/**
196219
* Helper to ensure a directory exists.
197220
* @throws \Exception
@@ -275,27 +298,10 @@ protected function convertArrayToCSV(array $value): string
275298
if (empty($value)) {
276299
return '';
277300
}
278-
279301
if (isset($value['$id'])) {
280302
return $value['$id'];
281303
}
282-
283-
$isStringArray = \array_reduce(
284-
$value,
285-
fn($carry, $item) => $carry && is_string($item),
286-
true
287-
);
288-
289-
if ($isStringArray) {
290-
// For string arrays, escape quotes and join with commas
291-
return \implode(',', \array_map(
292-
fn($item) => \str_replace('"', '""', $item),
293-
$value
294-
));
295-
}
296-
297-
// For complex arrays, use JSON with escaped quotes
298-
return \str_replace('"', '""', \json_encode($value));
304+
return \json_encode($value);
299305
}
300306

301307
/**
@@ -306,8 +312,6 @@ protected function convertObjectToCSV($value): string
306312
if ($value instanceof Row) {
307313
return $value->getId();
308314
}
309-
310-
// Escape quotes for CSV by doubling them
311-
return \str_replace('"', '""', \json_encode($value));
315+
return \json_encode($value);
312316
}
313317
}

0 commit comments

Comments
 (0)