fix: harden postcodes:import against duplicate headers and test collisions
This commit is contained in:
@@ -6,7 +6,6 @@ use Illuminate\Console\Attributes\Description;
|
||||
use Illuminate\Console\Attributes\Signature;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use RuntimeException;
|
||||
|
||||
#[Signature('postcodes:import {--file= : Path to ONSPD CSV file}')]
|
||||
#[Description('Import UK postcodes (ONSPD) into the local postcodes and outcodes tables')]
|
||||
@@ -27,7 +26,9 @@ final class ImportPostcodes extends Command
|
||||
$handle = fopen($file, 'r');
|
||||
|
||||
if ($handle === false) {
|
||||
throw new RuntimeException("Unable to open {$file}");
|
||||
$this->error("Unable to open {$file}.");
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$header = fgetcsv($handle);
|
||||
@@ -39,6 +40,17 @@ final class ImportPostcodes extends Command
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$headerCounts = array_count_values(array_map('strtolower', $header));
|
||||
|
||||
foreach (['pcd', 'lat', 'long'] as $required) {
|
||||
if (($headerCounts[$required] ?? 0) > 1) {
|
||||
$this->error("Column '{$required}' appears more than once — refusing to import.");
|
||||
fclose($handle);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
$columns = array_change_key_case(array_flip($header), CASE_LOWER);
|
||||
|
||||
foreach (['pcd', 'lat', 'long'] as $required) {
|
||||
|
||||
@@ -5,6 +5,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
if (! function_exists('writeOnspdFixture')) {
|
||||
function writeOnspdFixture(string $contents): string
|
||||
{
|
||||
$path = tempnam(sys_get_temp_dir(), 'onspd_').'.csv';
|
||||
@@ -12,6 +13,7 @@ function writeOnspdFixture(string $contents): string
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
it('imports active postcodes from an ONSPD CSV', function (): void {
|
||||
$csv = <<<'CSV'
|
||||
|
||||
Reference in New Issue
Block a user