Skip to content
Open
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
19 changes: 8 additions & 11 deletions src/Migration/Sources/CSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -469,36 +469,33 @@ private function validateCSVHeaders(array $headers, array $columnTypes, array $r
$internals = ['$id', '$permissions', '$createdAt', '$updatedAt'];
$allKnown = \array_keys($columnTypes);

// Only validate that required columns are present
$messages = [];

// Check for missing required columns — warn but don't fail
$missingRequired = [];
foreach (\array_keys($requiredColumns) as $requiredColumn) {
if (!\in_array($requiredColumn, $headers)) {
$missingRequired[] = $requiredColumn;
}
}

$messages = [];

// If there are missing required columns, throw an exception
if (!empty($missingRequired)) {
$label = \count($missingRequired) === 1 ? 'Missing required column' : 'Missing required columns';
$messages[] = "$label: '" . \implode("', '", $missingRequired) . "'";
}
if (!empty($missingRequired)) {
throw new \Exception('CSV header validation failed: ' . \implode('. ', $messages), Exception::CODE_VALIDATION);
$messages[] = "$label: '" . \implode("', '", $missingRequired) . "' (rows will have null values)";
}

// If there are unknown columns but no missing required columns, just log a warning
// Check for unknown columns
$unknown = \array_diff($headers, $allKnown, $internals);
if (!empty($unknown)) {
$label = \count($unknown) === 1 ? 'Unknown column' : 'Unknown columns';
$messages[] = "$label: '" . \implode("', '", $unknown) . "' (will be ignored)";
}
if (!empty($unknown)) {

if (!empty($messages)) {
$this->addWarning(new Warning(
UtopiaResource::TYPE_ROW,
Transfer::GROUP_DATABASES,
\implode(', ', $messages),
\implode('. ', $messages),
$this->resourceId
));
}
Expand Down
43 changes: 43 additions & 0 deletions tests/Migration/Unit/General/CSVTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,49 @@ public function testCSVExportImportCompatibility()
}
}

/**
* @throws \ReflectionException
*/
private function callValidateCSVHeaders(array $headers, array $columnTypes, array $requiredColumns): void
{
$reflection = new \ReflectionClass(CSV::class);
$instance = $reflection->newInstanceWithoutConstructor();

$refProp = $reflection->getProperty('resourceId');
$refProp->setAccessible(true);
$refProp->setValue($instance, 'test_db:test_table');

$refMethod = $reflection->getMethod('validateCSVHeaders');
$refMethod->setAccessible(true);

$refMethod->invoke($instance, $headers, $columnTypes, $requiredColumns);
}

public function testValidateCSVHeadersMissingRequiredColumnDoesNotThrow(): void
{
// A CSV with only 'name' column, but 'texte' is required in the schema
$headers = ['name'];
$columnTypes = ['name' => 'string', 'texte' => 'string'];
$requiredColumns = ['texte' => true];

// This should NOT throw — missing required columns should be a warning, not an error
$this->callValidateCSVHeaders($headers, $columnTypes, $requiredColumns);

// If we reach here, the test passes (no exception thrown)
$this->assertTrue(true);
}

public function testValidateCSVHeadersAllRequiredPresent(): void
{
$headers = ['name', 'texte'];
$columnTypes = ['name' => 'string', 'texte' => 'string'];
$requiredColumns = ['texte' => true];

// Should not throw when all required columns are present
$this->callValidateCSVHeaders($headers, $columnTypes, $requiredColumns);
$this->assertTrue(true);
}

private function recursiveDelete(string $dir): void
{
if (is_dir($dir)) {
Expand Down
Loading