103 lines
4.4 KiB
PHP
103 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
final class Asm3ContactImporter
|
|
{
|
|
public static function run(string $path, PDO $db, bool $apply = false, bool $createBackup = true): array
|
|
{
|
|
$plan = Asm3ContactPlanner::plan($path, $db);
|
|
$hash = hash_file('sha256', $path);
|
|
if ($hash === false) {
|
|
throw new RuntimeException(t('asm3.hash_unavailable'));
|
|
}
|
|
$result = [
|
|
'mode' => $apply ? 'apply' : 'dry-run',
|
|
'entity' => 'contacts',
|
|
'planned' => $plan['summary'],
|
|
'created' => 0,
|
|
'linked_matches' => 0,
|
|
'skipped_match' => 0,
|
|
'skipped_review' => $plan['summary']['review'],
|
|
'backup' => null,
|
|
'read_only' => !$apply,
|
|
'would_create' => $plan['summary']['create'],
|
|
];
|
|
if (!$apply) {
|
|
return $result;
|
|
}
|
|
if ($createBackup) {
|
|
$backup = BackupService::create('pre-asm3-import');
|
|
$result['backup'] = $backup['name'] ?? null;
|
|
}
|
|
$ownsTransaction = !$db->inTransaction();
|
|
if ($ownsTransaction) {
|
|
$db->beginTransaction();
|
|
}
|
|
try {
|
|
$db->prepare(
|
|
"INSERT INTO asm3_import_runs(source_name,source_sha256,status,summary_json,backup_name) VALUES(:name,:hash,'completed','{}',:backup)",
|
|
)->execute([':name' => basename($path) . ' · contacts', ':hash' => $hash, ':backup' => $result['backup']]);
|
|
$runId = (int) $db->lastInsertId();
|
|
foreach ($plan['items'] as $item) {
|
|
if ($item['action'] === 'review') {
|
|
continue;
|
|
}
|
|
$check = $db->prepare(
|
|
"SELECT target_id FROM asm3_import_links WHERE source_sha256=:hash AND entity_type='contact' AND source_id=:source",
|
|
);
|
|
$check->execute([':hash' => $hash, ':source' => $item['asm3_id']]);
|
|
if ($check->fetchColumn()) {
|
|
continue;
|
|
}
|
|
$c = $item['mapped'];
|
|
if ($item['action'] === 'match') {
|
|
$target = (int) ($item['globinours_candidates'][0]['id'] ?? 0);
|
|
if ($target <= 0) {
|
|
$result['skipped_match']++;
|
|
continue;
|
|
}
|
|
$result['linked_matches']++;
|
|
} else {
|
|
$db->prepare(
|
|
'INSERT INTO directory_contacts(kind,name,phone,email,address,postal_code,city,country,notes) VALUES(:kind,:name,:phone,:email,:address,:postal,:city,:country,:notes)',
|
|
)->execute([
|
|
':kind' => $c['kind'],
|
|
':name' => $c['name'],
|
|
':phone' => $c['phone'],
|
|
':email' => $c['email'],
|
|
':address' => $c['address'],
|
|
':postal' => $c['postal_code'],
|
|
':city' => $c['city'],
|
|
':country' => $c['country'],
|
|
':notes' => $c['notes'],
|
|
]);
|
|
$target = (int) $db->lastInsertId();
|
|
$result['created']++;
|
|
}
|
|
$role = $db->prepare(
|
|
'INSERT OR IGNORE INTO directory_contact_roles(contact_id,role) VALUES(:contact,:role)',
|
|
);
|
|
foreach ($c['roles'] as $value) {
|
|
$role->execute([':contact' => $target, ':role' => $value]);
|
|
}
|
|
$db->prepare(
|
|
"INSERT INTO asm3_import_links(source_sha256,entity_type,source_id,target_id,import_run_id) VALUES(:hash,'contact',:source,:target,:run)",
|
|
)->execute([':hash' => $hash, ':source' => $item['asm3_id'], ':target' => $target, ':run' => $runId]);
|
|
}
|
|
$db->prepare('UPDATE asm3_import_runs SET summary_json=:summary WHERE id=:id')->execute([
|
|
':summary' => json_encode($result, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
|
|
':id' => $runId,
|
|
]);
|
|
if ($ownsTransaction) {
|
|
$db->commit();
|
|
}
|
|
} catch (Throwable $e) {
|
|
if ($ownsTransaction && $db->inTransaction()) {
|
|
$db->rollBack();
|
|
}
|
|
throw $e;
|
|
}
|
|
return $result;
|
|
}
|
|
}
|