Skip to content

Commit f56a52c

Browse files
committed
cert tests
1 parent 445e53f commit f56a52c

18 files changed

Lines changed: 121 additions & 32 deletions

app/CertificateExcellence.php

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,30 @@ public function preflight(): void
7979
}
8080
}
8181

82+
/**
83+
* Generate the certificate PDF and save a copy to the given path (e.g. for viewing test certs).
84+
* Does not upload to S3. Cleans up LaTeX temp files after copying.
85+
*
86+
* @return string The full path where the PDF was saved
87+
*/
88+
public function generateAndSavePdfTo(string $fullPath): string
89+
{
90+
try {
91+
$this->customize_and_save_latex();
92+
$this->run_pdf_creation();
93+
$pdfName = $this->personalized_template_name . '.pdf';
94+
$dir = dirname($fullPath);
95+
if (! is_dir($dir) && ! @mkdir($dir, 0775, true) && ! is_dir($dir)) {
96+
throw new \RuntimeException("Cannot create directory: {$dir}");
97+
}
98+
$contents = Storage::disk('latex')->get($pdfName);
99+
file_put_contents($fullPath, $contents);
100+
return $fullPath;
101+
} finally {
102+
$this->clean_temp_files();
103+
}
104+
}
105+
82106
/**
83107
* Clean up LaTeX artifacts for the generated file.
84108
*/
@@ -99,6 +123,14 @@ public function is_greek()
99123
return (count($split) > 1);
100124
}
101125

126+
/**
127+
* Check for Cyrillic characters in the name (Russian, Ukrainian, etc.).
128+
*/
129+
public function is_cyrillic(): bool
130+
{
131+
return (bool) preg_match('/[\p{Cyrillic}]/u', $this->name_of_certificate_holder);
132+
}
133+
102134
/**
103135
* Escape LaTeX special characters in user data.
104136
*/
@@ -141,12 +173,12 @@ protected function customize_and_save_latex()
141173
Log::info("Using template: {$this->templateName}");
142174
$base_template = Storage::disk('latex')->get($this->templateName);
143175

144-
// Always replace <CERTIFICATE_HOLDER_NAME> for both excellence & super-organiser
145-
$template = str_replace(
146-
'<CERTIFICATE_HOLDER_NAME>',
147-
$this->tex_escape($this->name_of_certificate_holder),
148-
$base_template
149-
);
176+
// Name replacement: for default (non-Greek) template, wrap Cyrillic names in russian block so T2A is used
177+
$nameReplacement = $this->tex_escape($this->name_of_certificate_holder);
178+
if (! $this->is_greek() && $this->is_cyrillic()) {
179+
$nameReplacement = '\\begin{otherlanguage*}{russian}' . $nameReplacement . '\\end{otherlanguage*}';
180+
}
181+
$template = str_replace('<CERTIFICATE_HOLDER_NAME>', $nameReplacement, $base_template);
150182

151183
// If super-organiser, we also replace these:
152184
if ($this->type === 'super-organiser') {

app/Console/Commands/CertificateTestTwo.php

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,104 @@
44

55
use App\CertificateExcellence;
66
use Illuminate\Console\Command;
7-
use Illuminate\Support\Facades\Storage;
87

98
class CertificateTestTwo extends Command
109
{
1110
protected $signature = 'certificate:test-two
1211
{--edition=2025 : Edition year}
13-
{--no-pdf : Only run preflight (no S3), do not keep PDFs}';
12+
{--type=all : excellence|super-organiser|all}
13+
{--no-pdf : Preflight only (no S3, no PDFs kept); default}
14+
{--keep-pdf : Generate PDFs and save locally so you can view them (storage/app/test-certificates/)}
15+
{--generate : Generate and upload to S3 (use with care)}';
1416

15-
protected $description = 'Generate two test certificates locally: one Greek name, one Russian name';
17+
protected $description = 'Run preflight for a few test names (Greek, Cyrillic, Latin, accented); use --keep-pdf to save viewable PDFs';
18+
19+
/** @var array<int, array{name: string, label: string}> */
20+
private static array $testNames = [
21+
['name' => 'Βασιλική Μπαμπαλή', 'label' => 'Greek'],
22+
['name' => 'Юлія Колісниченко', 'label' => 'Ukrainian (Cyrillic)'],
23+
['name' => 'Иван Петров', 'label' => 'Russian (Cyrillic)'],
24+
['name' => 'John Smith', 'label' => 'English'],
25+
['name' => 'José García', 'label' => 'Accented Latin'],
26+
['name' => 'María Fernández', 'label' => 'Accented Latin 2'],
27+
];
1628

1729
public function handle(): int
1830
{
1931
$edition = (int) $this->option('edition');
20-
$preflightOnly = (bool) $this->option('no-pdf');
32+
$typeOption = strtolower(trim((string) $this->option('type')));
33+
$keepPdf = (bool) $this->option('keep-pdf');
34+
$uploadToS3 = (bool) $this->option('generate');
35+
$preflightOnly = ! $keepPdf && ! $uploadToS3;
36+
37+
$typeList = $this->resolveTypes($typeOption);
38+
if ($typeList === null) {
39+
$this->error("Invalid --type: {$typeOption}. Use excellence, super-organiser, or all.");
40+
return self::FAILURE;
41+
}
2142

22-
$tests = [
23-
['name' => 'Βασιλική Μπαμπαλή', 'label' => 'Greek'],
24-
['name' => 'Иван Петров', 'label' => 'Russian'],
25-
];
43+
$outDir = $keepPdf ? storage_path('app/test-certificates') : null;
44+
if ($outDir !== null && ! is_dir($outDir)) {
45+
mkdir($outDir, 0775, true);
46+
}
2647

27-
foreach ($tests as $test) {
28-
$this->info("Testing {$test['label']}: {$test['name']}");
48+
$mode = $preflightOnly ? 'Preflight only (no PDFs kept)' : ($keepPdf ? 'Generating PDFs to ' . $outDir : 'Generating and uploading to S3');
49+
$this->info('Certificate test names. Edition: ' . $edition . ', types: ' . implode(', ', $typeList) . '. ' . $mode);
50+
$this->newLine();
51+
52+
$failed = 0;
53+
$index = 0;
54+
foreach (self::$testNames as $test) {
55+
$this->line("--- {$test['label']}: {$test['name']} ---");
2956
$cert = new CertificateExcellence($edition, $test['name'], 'excellence', 0, 999999, 'test@example.com');
30-
$this->line(' is_greek(): ' . ($cert->is_greek() ? 'true' : 'false'));
31-
32-
try {
33-
if ($preflightOnly) {
34-
$cert->preflight();
35-
$this->info(" Preflight OK (no PDF kept).");
36-
} else {
37-
$url = $cert->generate();
38-
$this->info(" Generated: {$url}");
57+
$this->line(' is_greek(): ' . ($cert->is_greek() ? 'true' : 'false') . ', is_cyrillic(): ' . ($cert->is_cyrillic() ? 'true' : 'false'));
58+
59+
$safeLabel = preg_replace('/[^a-zA-Z0-9_-]/', '_', $test['label']);
60+
foreach ($typeList as $certType) {
61+
$activities = $certType === 'super-organiser' ? 10 : 0;
62+
$certTest = new CertificateExcellence($edition, $test['name'], $certType, $activities, 999999, 'test@example.com');
63+
$label = $certType === 'super-organiser' ? 'SuperOrganiser' : 'Excellence';
64+
try {
65+
if ($preflightOnly) {
66+
$certTest->preflight();
67+
$this->info(" [{$label}] Preflight OK.");
68+
} elseif ($keepPdf) {
69+
$index++;
70+
$filename = sprintf('%02d-%s-%s.pdf', $index, $safeLabel, $label);
71+
$path = $certTest->generateAndSavePdfTo($outDir . DIRECTORY_SEPARATOR . $filename);
72+
$this->info(" [{$label}] Saved: {$path}");
73+
} else {
74+
$url = $certTest->generate();
75+
$this->info(" [{$label}] Generated: {$url}");
76+
}
77+
} catch (\Throwable $e) {
78+
$this->error(" [{$label}] Failed: " . $e->getMessage());
79+
$failed++;
3980
}
40-
} catch (\Throwable $e) {
41-
$this->error(' Failed: ' . $e->getMessage());
42-
return self::FAILURE;
4381
}
82+
$this->newLine();
4483
}
4584

46-
$this->newLine();
47-
$this->info('Both certificates OK. Greek uses _greek template; Russian uses default template.');
85+
if ($failed > 0) {
86+
$this->error("{$failed} test(s) failed.");
87+
return self::FAILURE;
88+
}
89+
if ($keepPdf) {
90+
$this->info('All test PDFs saved. Open: ' . $outDir);
91+
} else {
92+
$this->info('All test names passed.');
93+
}
4894
return self::SUCCESS;
4995
}
96+
97+
/** @return array<string>|null */
98+
private function resolveTypes(string $typeOption): ?array
99+
{
100+
return match ($typeOption) {
101+
'all' => ['excellence', 'super-organiser'],
102+
'excellence' => ['excellence'],
103+
'super-organiser', 'superorganiser' => ['super-organiser'],
104+
default => null,
105+
};
106+
}
50107
}

resources/latex/super-organiser-2024.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
\vspace{0.5cm}
5555
\textcolor{Slate600}{\fontsize{13}{13}\selectfont To} \\
5656
\vspace{0.5cm}
57-
\textcolor{Orange500}{\fontsize{28}{32}\selectfont\begin{otherlanguage*}{russian}<CERTIFICATE_HOLDER_NAME>\end{otherlanguage*}} \\
57+
\textcolor{Orange500}{\fontsize{28}{32}\selectfont <CERTIFICATE_HOLDER_NAME>} \\
5858
\vspace{0.5cm}
5959
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6060
\vspace{0.5cm}

resources/latex/super-organiser-2025.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
\vspace{0.5cm}
5555
\textcolor{Slate600}{\fontsize{13}{13}\selectfont To} \\
5656
\vspace{0.5cm}
57-
\textcolor{Orange500}{\fontsize{28}{32}\selectfont\begin{otherlanguage*}{russian}<CERTIFICATE_HOLDER_NAME>\end{otherlanguage*}} \\
57+
\textcolor{Orange500}{\fontsize{28}{32}\selectfont <CERTIFICATE_HOLDER_NAME>} \\
5858
\vspace{0.5cm}
5959
\textcolor{Slate600}{\fontsize{13}{13}\selectfont For Organising} \\
6060
\vspace{0.5cm}
192 KB
Binary file not shown.
167 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)