<?php
 namespace App\Services\Import\Importers; use App\Services\Import\Contracts\ImporterInterface; class CsvImporter implements ImporterInterface { public const MAX_ROWS = 50000; public function key(): string { return 'csv'; } public function supportedEntities(): array { return [ 'clients' => [ 'required' => ['email', 'first_name'], 'optional' => [ 'last_name', 'company_name', 'phone', 'address1', 'address2', 'city', 'state', 'postcode', 'country_code', 'tax_id', 'password_hash', 'external_id', 'status', ], ], 'services' => ['required' => ['client_email', 'product'], 'optional' => ['domain', 'status', 'next_due_date', 'amount']], 'domains' => ['required' => ['client_email', 'domain'], 'optional' => ['status', 'expire_date', 'registrar']], 'invoices' => ['required' => ['client_email', 'total'], 'optional' => ['status', 'date', 'due_date', 'external_id']], ]; } public function analyze(string $entity, array $source): array { $path = $source['path'] ?? null; if (! $path || ! is_readable($path)) { return ['headers' => [], 'sample' => [], 'error' => 'CSV okunamadı.']; } $handle = fopen($path, 'r'); if (! $handle) { return ['headers' => [], 'sample' => [], 'error' => 'CSV açılamadı.']; } $headers = fgetcsv($handle) ?: []; $headers = array_map(fn ($h) => trim((string) $h), $headers); $sample = []; while (count($sample) < 5 && ($row = fgetcsv($handle)) !== false) { $assoc = []; foreach ($headers as $i => $h) { $assoc[$h] = trim((string) ($row[$i] ?? '')); } $sample[] = $assoc; } fclose($handle); return ['headers' => $headers, 'sample' => $sample]; } public function rows(string $entity, array $source, array $mapping, array $options): iterable { $path = $source['path'] ?? null; if (! $path || ! is_readable($path)) { return; } $handle = fopen($path, 'r'); if (! $handle) { return; } $headers = fgetcsv($handle) ?: []; $headers = array_map(fn ($h) => mb_strtolower(trim((string) $h)), $headers); $index = $this->buildColumnIndex($headers, $mapping); $count = 0; while (($raw = fgetcsv($handle)) !== false) { if ($count++ >= self::MAX_ROWS) { yield ['external_ref' => '', 'data' => [], 'error' => 'Satır limiti aşıldı: '.self::MAX_ROWS]; break; } if (count(array_filter($raw, fn ($c) => trim((string) $c) !== '')) === 0) { continue; } $data = []; foreach ($index as $field => $pos) { $data[$field] = trim((string) ($raw[$pos] ?? '')); } $externalRef = $data['external_id'] ?? ''; if ($externalRef === '') { $externalRef = mb_strtolower($data['email'] ?? ''); } yield ['external_ref' => $externalRef, 'data' => $data]; } fclose($handle); } private function buildColumnIndex(array $normalizedHeaders, array $mapping): array { $index = []; foreach ($mapping as $field => $headerName) { if (! $headerName) { continue; } $pos = array_search(mb_strtolower(trim((string) $headerName)), $normalizedHeaders, true); if ($pos !== false) { $index[$field] = $pos; } } return $index; } } 