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:
parent
bb82e9a4b9
commit
fdbf9a3210
1 changed files with 152 additions and 2 deletions
|
|
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue