Teren-app/app/Services/CsvImportService.php
2025-09-29 17:35:54 +02:00

92 lines
2.6 KiB
PHP

<?php
namespace App\Services;
class CsvImportService
{
/**
* Read the first line of a file; returns null on failure.
*/
public function readFirstLine(string $path): ?string
{
$fh = @fopen($path, 'r');
if (!$fh) return null;
$line = fgets($fh);
fclose($fh);
return $line === false ? null : $line;
}
/**
* Detect delimiter and return columns for first row.
* If $hasHeader is false, returns positional indices instead of header names.
* Returns [delimiter, columns].
*/
public function detectColumnsFromCsv(string $path, bool $hasHeader): array
{
// Use actual tab character for TSV; keep other common delimiters
$delims = [',',';','|',"\t"];
$bestDelim = ',';
$bestCols = [];
$firstLine = $this->readFirstLine($path);
if ($firstLine === null) {
return [$bestDelim, []];
}
$maxCount = 0;
foreach ($delims as $d) {
$row = str_getcsv($firstLine, $d);
$count = is_array($row) ? count($row) : 0;
if ($count > $maxCount) {
$maxCount = $count;
$bestDelim = $d;
$bestCols = $row;
}
}
if (!$hasHeader) {
// return positional indices 0..N-1
$cols = [];
for ($i = 0; $i < $maxCount; $i++) {
$cols[] = (string) $i;
}
return [$bestDelim, $cols];
}
// Clean header names
$clean = array_map(function ($v) {
$v = trim((string) $v);
$v = preg_replace('/\s+/', ' ', $v);
return $v;
}, $bestCols);
return [$bestDelim, $clean];
}
/**
* Parse columns from CSV using a specific delimiter. If $hasHeader is false,
* returns positional indices instead of header names.
*/
public function parseColumnsFromCsv(string $path, string $delimiter, bool $hasHeader): array
{
$firstLine = $this->readFirstLine($path);
if ($firstLine === null) {
return [];
}
$row = str_getcsv($firstLine, $delimiter);
$count = is_array($row) ? count($row) : 0;
if ($hasHeader) {
return array_map(function ($v) {
$v = trim((string) $v);
$v = preg_replace('/\s+/', ' ', $v);
return $v;
}, $row ?: []);
}
$cols = [];
for ($i = 0; $i < $count; $i++) {
$cols[] = (string) $i;
}
return $cols;
}
}