Add manual signature confirmation by email address

Add new menu option to manually confirm signatures by email address
Search through all petition files to find matching emails
Update status from pending to confirmed when found
Display results with confirmation status and petition IDs
Handle multiple emails via comma-separated input
Maintain proper file locking to prevent race conditions
This commit is contained in:
Ruben 2026-02-01 20:27:34 +01:00
parent bb82e9a4b9
commit fdbf9a3210

View file

@ -407,7 +407,8 @@ function showMenu(): void {
echo " 3) Send e-post pa nytt til mislykkede\n"; echo " 3) Send e-post pa nytt til mislykkede\n";
echo " 4) Send bekreftelse pa nytt til ubekreftede\n"; echo " 4) Send bekreftelse pa nytt til ubekreftede\n";
echo " 5) Marker oppforinger som ignorert\n"; echo " 5) Marker oppforinger som ignorert\n";
echo " 6) Avslutt\n"; echo " 6) Manuell bekreftelse av signaturer\n";
echo " 7) Avslutt\n";
echo "\n"; echo "\n";
} }
@ -642,6 +643,152 @@ function resendToUnconfirmed(): void {
printColor("Ferdig: {$success} vellykket, {$failures} mislykket\n", $failures > 0 ? 'yellow' : 'green'); printColor("Ferdig: {$success} vellykket, {$failures} mislykket\n", $failures > 0 ? 'yellow' : 'green');
} }
/**
* Manually confirm signatures by email address
*/
function manuallyConfirmSignatures(): void {
echo "\n";
printColor("Manuell bekreftelse av signaturer\n", 'cyan');
echo "\n";
$input = prompt("Skriv inn e-postadresse(r) (kommaseparert): ");
if (empty(trim($input))) {
echo "Ingen e-postadresser oppgitt.\n";
return;
}
// Parse and clean email addresses
$emails = array_map('trim', explode(',', $input));
$emails = array_filter($emails, fn($e) => !empty($e));
$emails = array_map('strtolower', $emails);
if (empty($emails)) {
echo "Ingen gyldige e-postadresser oppgitt.\n";
return;
}
echo "\n";
echo "Soker etter " . count($emails) . " e-postadresse(r)...\n\n";
$found = [];
$notFound = [];
// Search through all petition files
foreach (getPetitionFiles() as $petitionId) {
$csvPath = PETITIONS_DIR . '/' . $petitionId . '.csv';
if (!file_exists($csvPath)) {
continue;
}
// Open with r+ to allow reading and writing, acquire exclusive lock immediately
// This matches the pattern used in petition-form.php to prevent race conditions
$fp = fopen($csvPath, 'r+');
if (!$fp) {
printColor(" Advarsel: Kunne ikke apne {$petitionId}.csv\n", 'yellow');
continue;
}
if (!flock($fp, LOCK_EX)) {
fclose($fp);
printColor(" Advarsel: Kunne ikke lase {$petitionId}.csv\n", 'yellow');
continue;
}
// Read all rows while holding the lock
$rows = [];
$header = fgetcsv($fp, null, ',', '"', '');
if ($header === false) {
// Empty file, skip
flock($fp, LOCK_UN);
fclose($fp);
continue;
}
while (($row = fgetcsv($fp, null, ',', '"', '')) !== false) {
$rows[] = $row;
}
$modified = false;
foreach ($rows as &$row) {
if (!isset($row[1]) || !isset($row[6])) {
continue;
}
$rowEmail = strtolower($row[1]);
if (in_array($rowEmail, $emails)) {
if ($row[6] === 'pending') {
$row[6] = 'confirmed';
$modified = true;
$found[] = [
'email' => $row[1],
'name' => ($row[2] ?? '') . ' ' . ($row[3] ?? ''),
'petition_id' => $petitionId,
'was_pending' => true
];
} else {
$found[] = [
'email' => $row[1],
'name' => ($row[2] ?? '') . ' ' . ($row[3] ?? ''),
'petition_id' => $petitionId,
'was_pending' => false,
'status' => $row[6]
];
}
}
}
unset($row);
// Write back if modified (still holding the lock)
if ($modified) {
rewind($fp);
ftruncate($fp, 0);
fputcsv($fp, $header, ',', '"', '');
foreach ($rows as $row) {
fputcsv($fp, $row, ',', '"', '');
}
}
flock($fp, LOCK_UN);
fclose($fp);
}
// Determine which emails were not found
$foundEmails = array_map(fn($f) => strtolower($f['email']), $found);
foreach ($emails as $email) {
if (!in_array($email, $foundEmails)) {
$notFound[] = $email;
}
}
// Display results
if (!empty($found)) {
printColor("Funnet:\n", 'green');
foreach ($found as $entry) {
$status = $entry['was_pending']
? "BEKREFTET"
: "allerede " . $entry['status'];
echo " - {$entry['email']} ({$entry['name']}) - {$entry['petition_id']}: ";
if ($entry['was_pending']) {
printColor("{$status}\n", 'green');
} else {
printColor("{$status}\n", 'yellow');
}
}
}
if (!empty($notFound)) {
echo "\n";
printColor("Ikke funnet:\n", 'red');
foreach ($notFound as $email) {
echo " - {$email}\n";
}
}
$confirmedCount = count(array_filter($found, fn($f) => $f['was_pending']));
echo "\n";
printColor("Ferdig: {$confirmedCount} signatur(er) bekreftet\n", 'green');
}
/** /**
* Interactive ignore marking * Interactive ignore marking
*/ */
@ -823,13 +970,16 @@ function main(): void {
markAsIgnored(); markAsIgnored();
break; break;
case '6': case '6':
manuallyConfirmSignatures();
break;
case '7':
case 'q': case 'q':
case 'quit': case 'quit':
case 'exit': case 'exit':
echo "Ha det!\n"; echo "Ha det!\n";
exit(0); exit(0);
default: default:
printColor("Ugyldig valg. Velg 1-6.\n", 'red'); printColor("Ugyldig valg. Velg 1-7.\n", 'red');
} }
} }
} }