Skip to content

Commit 5b9989a

Browse files
authored
Merge pull request #3441 from codeeu/week_10_feb
Greek Fix
2 parents cffbf6d + 3dfd5d0 commit 5b9989a

6 files changed

Lines changed: 156 additions & 8 deletions

app/CertificateExcellence.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,41 @@ public function generate()
6565
return $s3path;
6666
}
6767

68+
/**
69+
* Regenerate the certificate and overwrite the existing S3 file so the same URL serves the new PDF.
70+
* Use when fixing content (e.g. Greek template text) without resending email; existing links keep working.
71+
*
72+
* @param string $existingCertificateUrl Current certificate_url (e.g. from Excellence row)
73+
* @return string The same URL (file overwritten on S3)
74+
*/
75+
public function generateReplacing(string $existingCertificateUrl): string
76+
{
77+
$id = $this->parseIdFromCertificateUrl($existingCertificateUrl);
78+
if ($id === '') {
79+
throw new \InvalidArgumentException('Could not parse certificate id from URL: ' . $existingCertificateUrl);
80+
}
81+
$this->id = $id;
82+
$this->personalized_template_name = $id;
83+
84+
$this->customize_and_save_latex();
85+
$this->run_pdf_creation();
86+
$url = $this->copy_to_s3();
87+
$this->clean_temp_files();
88+
89+
return $url;
90+
}
91+
92+
private function parseIdFromCertificateUrl(string $url): string
93+
{
94+
$path = parse_url($url, PHP_URL_PATH);
95+
if ($path === null || $path === '') {
96+
return '';
97+
}
98+
$filename = basename($path);
99+
100+
return (string) preg_replace('/\.pdf$/i', '', $filename);
101+
}
102+
68103
/**
69104
* Dry-run style preflight: compile the certificate locally without S3 upload.
70105
* Cleans up temp files regardless of success/failure.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use App\CertificateExcellence;
6+
use App\Excellence;
7+
use Illuminate\Console\Command;
8+
9+
class CertificateRegenerateGreekSuperOrganiser extends Command
10+
{
11+
protected $signature = 'certificate:regenerate-greek-super-organiser
12+
{--edition=2025 : Edition year}
13+
{--dry-run : Only count and list, do not regenerate}';
14+
15+
protected $description = 'Regenerate PDFs only for Greek Super Organisers (fix garbled “coding activities” text). Does not resend email.';
16+
17+
public function handle(): int
18+
{
19+
$edition = (int) $this->option('edition');
20+
$dryRun = (bool) $this->option('dry-run');
21+
22+
$query = Excellence::query()
23+
->where('edition', $edition)
24+
->where('type', 'SuperOrganiser')
25+
->whereNotNull('certificate_url')
26+
->with('user')
27+
->orderBy('id');
28+
29+
$rows = $query->get();
30+
$greekRows = $rows->filter(function (Excellence $e) {
31+
$name = $e->name_for_certificate ?? ($e->user ? trim(($e->user->firstname ?? '') . ' ' . ($e->user->lastname ?? '')) : '');
32+
return $this->nameContainsGreek($name);
33+
});
34+
35+
$total = $greekRows->count();
36+
if ($total === 0) {
37+
$this->info("No Greek Super Organiser certificates found for edition {$edition} (with existing certificate_url).");
38+
return self::SUCCESS;
39+
}
40+
41+
$this->info("Found {$total} Greek Super Organiser certificate(s) for edition {$edition}.");
42+
if ($dryRun) {
43+
$this->line('Dry run: no regeneration. Sample:');
44+
$greekRows->take(10)->each(fn (Excellence $e) => $this->line(' ' . ($e->user?->email ?? '?') . '' . ($e->name_for_certificate ?? $e->user?->firstname . ' ' . $e->user?->lastname)));
45+
if ($total > 10) {
46+
$this->line(' ... and ' . ($total - 10) . ' more.');
47+
}
48+
return self::SUCCESS;
49+
}
50+
51+
$this->info('Regenerating PDFs only (certificate_url will be updated; no email sent).');
52+
$bar = $this->output->createProgressBar($total);
53+
$bar->start();
54+
55+
$ok = 0;
56+
$failed = 0;
57+
$failures = [];
58+
59+
foreach ($greekRows as $excellence) {
60+
$bar->advance();
61+
$user = $excellence->user;
62+
if (! $user) {
63+
$failed++;
64+
$failures[] = ['id' => $excellence->id, 'email' => '-', 'error' => 'User missing'];
65+
continue;
66+
}
67+
68+
$name = $excellence->name_for_certificate ?? trim(($user->firstname ?? '') . ' ' . ($user->lastname ?? ''));
69+
$name = $name !== '' ? $name : 'Unknown';
70+
$numberOfActivities = (int) $user->activities($edition);
71+
72+
try {
73+
$cert = new CertificateExcellence(
74+
$edition,
75+
$name,
76+
'super-organiser',
77+
$numberOfActivities,
78+
(int) $user->id,
79+
(string) ($user->email ?? '')
80+
);
81+
// Overwrite existing S3 file so the same URL serves the new PDF (no need to resend email)
82+
$url = $cert->generateReplacing($excellence->certificate_url);
83+
$excellence->update([
84+
'certificate_url' => $url,
85+
'certificate_generation_error' => null,
86+
]);
87+
$ok++;
88+
} catch (\Throwable $e) {
89+
$failed++;
90+
$excellence->update(['certificate_generation_error' => $e->getMessage()]);
91+
$failures[] = ['id' => $excellence->id, 'email' => $user->email ?? '-', 'error' => $e->getMessage()];
92+
}
93+
}
94+
95+
$bar->finish();
96+
$this->newLine(2);
97+
$this->info("Done. Regenerated: {$ok}, Failed: {$failed}. No emails sent; existing certificate links now point to the new PDFs.");
98+
if ($failed > 0 && count($failures) > 0) {
99+
$this->table(['id', 'email', 'error'], array_slice($failures, 0, 20));
100+
if (count($failures) > 20) {
101+
$this->line('(First 20 failures shown.)');
102+
}
103+
}
104+
105+
return $failed > 0 ? self::FAILURE : self::SUCCESS;
106+
}
107+
108+
private function nameContainsGreek(string $name): bool
109+
{
110+
$split = preg_split('/[\p{Greek}]/u', $name);
111+
return $split !== false && count($split) > 1;
112+
}
113+
}

resources/latex/SuperOrganiser_greek-2024.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@
6565
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6666
\vspace{0.5cm}
6767

68-
% Greek translation for activities
68+
% Greek: "X δραστηριότητες προγραμματισμού το 2024" = "X coding activities in 2024"
6969
\begin{otherlanguage*}{greek}
7070
\textcolor{DarkBlue500}{\fontsize{20}{20}\selectfont
71-
\textbf{<NUMBER_OF_ACTIVITIES> coding activities in 2024}
71+
\textbf{<NUMBER_OF_ACTIVITIES> δραστηριότητες προγραμματισμού το 2024}
7272
}
7373
\end{otherlanguage*} \\
7474

resources/latex/super-organiser_greek-2024.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@
6565
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6666
\vspace{0.5cm}
6767

68-
% Greek translation for activities
68+
% Greek: "X δραστηριότητες προγραμματισμού το 2024" = "X coding activities in 2024"
6969
\begin{otherlanguage*}{greek}
7070
\textcolor{DarkBlue500}{\fontsize{20}{20}\selectfont
71-
\textbf{<NUMBER_OF_ACTIVITIES> coding activities in 2024}
71+
\textbf{<NUMBER_OF_ACTIVITIES> δραστηριότητες προγραμματισμού το 2024}
7272
}
7373
\end{otherlanguage*} \\
7474

resources/latex/super-organiser_greek-2025.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@
6565
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6666
\vspace{0.5cm}
6767

68-
% Greek translation for activities
68+
% Greek: "X δραστηριότητες προγραμματισμού το 2025" = "X coding activities in 2025"
6969
\begin{otherlanguage*}{greek}
7070
\textcolor{DarkBlue500}{\fontsize{20}{20}\selectfont
71-
\textbf{<NUMBER_OF_ACTIVITIES> coding activities in 2025}
71+
\textbf{<NUMBER_OF_ACTIVITIES> δραστηριότητες προγραμματισμού το 2025}
7272
}
7373
\end{otherlanguage*} \\
7474

resources/latex/super-organiser_greek-2026.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@
6565
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6666
\vspace{0.5cm}
6767

68-
% Greek translation for activities
68+
% Greek: "X δραστηριότητες προγραμματισμού το 2026" = "X coding activities in 2026"
6969
\begin{otherlanguage*}{greek}
7070
\textcolor{DarkBlue500}{\fontsize{20}{20}\selectfont
71-
\textbf{<NUMBER_OF_ACTIVITIES> coding activities in 2026}
71+
\textbf{<NUMBER_OF_ACTIVITIES> δραστηριότητες προγραμματισμού το 2026}
7272
}
7373
\end{otherlanguage*} \\
7474

0 commit comments

Comments
 (0)