133 lines
3.7 KiB
PHP
133 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Import\Handlers;
|
|
|
|
use App\Models\Email;
|
|
use App\Models\Import;
|
|
use App\Services\Import\BaseEntityHandler;
|
|
|
|
class EmailHandler extends BaseEntityHandler
|
|
{
|
|
public function getEntityClass(): string
|
|
{
|
|
return Email::class;
|
|
}
|
|
|
|
/**
|
|
* Override validate to skip validation if email is empty or invalid.
|
|
* Invalid emails should be skipped, not cause transaction rollback.
|
|
*/
|
|
public function validate(array $mapped): array
|
|
{
|
|
$email = $mapped['value'] ?? null;
|
|
if (empty($email) || trim((string)$email) === '') {
|
|
return ['valid' => true, 'errors' => []];
|
|
}
|
|
|
|
// Validate email format - if invalid, mark as valid to skip instead of failing
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
// Return valid=true but we'll skip it in process()
|
|
return ['valid' => true, 'errors' => []];
|
|
}
|
|
|
|
return parent::validate($mapped);
|
|
}
|
|
|
|
public function resolve(array $mapped, array $context = []): mixed
|
|
{
|
|
$value = $mapped['value'] ?? null;
|
|
|
|
if (! $value) {
|
|
return null;
|
|
}
|
|
|
|
return Email::where('value', strtolower(trim($value)))->first();
|
|
}
|
|
|
|
public function process(Import $import, array $mapped, array $raw, array $context = []): array
|
|
{
|
|
// Skip if email is empty or blank
|
|
$email = $mapped['value'] ?? null;
|
|
if (empty($email) || trim((string)$email) === '') {
|
|
return [
|
|
'action' => 'skipped',
|
|
'message' => 'Email is empty',
|
|
];
|
|
}
|
|
|
|
// Skip if email format is invalid
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
return [
|
|
'action' => 'skipped',
|
|
'message' => 'Invalid email format',
|
|
];
|
|
}
|
|
|
|
// Resolve person_id from context
|
|
$personId = $mapped['person_id'] ?? $context['person']['entity']?->id ?? null;
|
|
|
|
if (! $personId) {
|
|
return [
|
|
'action' => 'skipped',
|
|
'message' => 'Email requires person_id',
|
|
];
|
|
}
|
|
|
|
$existing = $this->resolve($mapped, $context);
|
|
|
|
// Check for duplicates if configured
|
|
if ($this->getOption('deduplicate', true) && $existing) {
|
|
// Update person_id if different
|
|
if ($existing->person_id !== $personId) {
|
|
$existing->person_id = $personId;
|
|
$existing->save();
|
|
|
|
return [
|
|
'action' => 'updated',
|
|
'entity' => $existing,
|
|
'applied_fields' => ['person_id'],
|
|
];
|
|
}
|
|
|
|
return [
|
|
'action' => 'skipped',
|
|
'entity' => $existing,
|
|
'message' => 'Email already exists',
|
|
];
|
|
}
|
|
|
|
// Create new email
|
|
$payload = $this->buildPayload($mapped, new Email);
|
|
$payload['person_id'] = $personId;
|
|
|
|
$email = new Email;
|
|
$email->fill($payload);
|
|
$email->save();
|
|
|
|
return [
|
|
'action' => 'inserted',
|
|
'entity' => $email,
|
|
'applied_fields' => array_keys($payload),
|
|
];
|
|
}
|
|
|
|
protected function buildPayload(array $mapped, $model): array
|
|
{
|
|
$payload = [];
|
|
|
|
if (isset($mapped['value'])) {
|
|
$payload['value'] = strtolower(trim($mapped['value']));
|
|
}
|
|
|
|
if (isset($mapped['is_primary'])) {
|
|
$payload['is_primary'] = (bool) $mapped['is_primary'];
|
|
}
|
|
|
|
if (isset($mapped['label'])) {
|
|
$payload['label'] = $mapped['label'];
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
}
|