Skip to content

Commit e0d1043

Browse files
authored
Merge pull request #2345 from codeeu/dev
Update CertificateParticipation and LatexCleaner to process certs that time out
2 parents 6982f2b + 4f6a521 commit e0d1043

2 files changed

Lines changed: 38 additions & 50 deletions

File tree

app/CertificateParticipation.php

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Carbon\Carbon;
88
use Illuminate\Support\Facades\Storage;
99
use Illuminate\Support\Str;
10-
use Log;
1110
use Symfony\Component\Process\Exception\ProcessFailedException;
1211
use Symfony\Component\Process\Process;
1312

@@ -25,7 +24,6 @@ class CertificateParticipation
2524

2625
private $personalized_template_name;
2726

28-
//private $event;
2927
private $id;
3028

3129
private $event_name;
@@ -40,42 +38,36 @@ class CertificateParticipation
4038

4139
public function __construct($name_for_certificate, $event_name, $event_date)
4240
{
41+
ini_set('max_execution_time', 600); // Set max execution time to 600 seconds
42+
ini_set('memory_limit', '512M'); // Set memory limit to 512 MB (adjust as needed)
43+
4344
$this->name_of_certificate_holder = $name_for_certificate;
4445
$this->event_name = $event_name;
4546
$this->event_date = $event_date;
4647

47-
//if ($this->is_greek_text($this->name_of_certificate_holder)){
4848
$random = Str::random(10);
49-
//} else {
50-
// $random = Str::kebab($this->name_of_certificate_holder) . "-" . Str::random(10);
51-
//}
5249

53-
$this->personalized_template_name = $random.'-'.auth()->id();
54-
$this->resource_path = resource_path().'/latex';
50+
$this->personalized_template_name = $random . '-' . auth()->id();
51+
$this->resource_path = resource_path() . '/latex';
5552
$this->pdflatex = config('codeweek.pdflatex_path');
56-
$this->id = auth()->id().'-'.$random;
57-
Log::info('User ID '.auth()->id().' generating participation certificate with name: '.$name_for_certificate);
53+
$this->id = auth()->id() . '-' . $random;
5854
}
5955

6056
public function generate()
6157
{
62-
6358
$this->customize_and_save_latex();
6459
$this->run_pdf_creation();
6560
$this->clean_temp_files();
6661

6762
return $this->personalized_template_name;
68-
//$s3path = $this->copy_to_s3();
69-
70-
//return $s3path;
71-
7263
}
7364

7465
private function clean_temp_files()
7566
{
76-
Storage::disk('latex')->delete($this->personalized_template_name.'.aux');
77-
Storage::disk('latex')->delete($this->personalized_template_name.'.tex');
78-
Storage::disk('latex')->delete($this->personalized_template_name.'.log');
67+
$extensions = ['aux', 'tex', 'log'];
68+
foreach ($extensions as $ext) {
69+
Storage::disk('latex')->delete($this->personalized_template_name . '.' . $ext);
70+
}
7971
}
8072

8173
protected function update_event($s3path)
@@ -86,26 +78,17 @@ protected function update_event($s3path)
8678
]);
8779
}
8880

89-
/**
90-
* @throws \League\Flysystem\FileNotFoundException
91-
*/
9281
protected function copy_to_s3(): string
9382
{
94-
$inputStream = Storage::disk('latex')->getDriver()->readStream($this->personalized_template_name.'.pdf');
95-
$destination = Storage::disk('s3')->path('/certificates/'.$this->id.'.pdf');
83+
$inputStream = Storage::disk('latex')->getDriver()->readStream($this->personalized_template_name . '.pdf');
84+
$destination = Storage::disk('s3')->path('/certificates/' . $this->id . '.pdf');
9685
Storage::disk('s3')->put($destination, $inputStream);
9786

98-
return Storage::disk('s3')->url('certificates/'.$this->id.'.pdf');
87+
return Storage::disk('s3')->url('certificates/' . $this->id . '.pdf');
9988
}
10089

101-
/**
102-
* @return mixed
103-
*
104-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
105-
*/
10690
protected function customize_and_save_latex()
10791
{
108-
10992
if ($this->is_greek_text($this->event_name) || $this->is_greek_text($this->event_date) || $this->is_greek_text($this->name_of_certificate_holder)) {
11093
$this->templateName = 'participation_greek.tex';
11194
}
@@ -121,11 +104,9 @@ protected function customize_and_save_latex()
121104
if ($this->is_greek_text($this->name_of_certificate_holder)) {
122105
$this->certificate_holder_name_lang = 'greek';
123106
}
124-
// Log::info($this->templateName);
125-
//open the latex template
107+
126108
$base_template = Storage::disk('latex')->get($this->templateName);
127109

128-
//replace the text in template
129110
$template = str_replace('<CERTIFICATE_HOLDER_NAME>', $this->tex_escape($this->name_of_certificate_holder), $base_template);
130111
$template = str_replace('<EVENT_NAME>', $this->tex_escape($this->event_name), $template);
131112
$template = str_replace('<EVENT_DATE>', $this->tex_escape($this->event_date), $template);
@@ -134,26 +115,34 @@ protected function customize_and_save_latex()
134115
$template = str_replace('<EVENT_NAME_LANG>', $this->tex_escape($this->event_name_lang), $template);
135116
$template = str_replace('<EVENT_DATE_LANG>', $this->tex_escape($this->event_date_lang), $template);
136117

137-
// dd($template);
138-
139-
//save it locally
140-
Storage::disk('latex')->put($this->personalized_template_name.'.tex', $template);
118+
Storage::disk('latex')->put($this->personalized_template_name . '.tex', $template);
141119
}
142120

143121
protected function run_pdf_creation(): void
144122
{
123+
if (!file_exists($this->pdflatex)) {
124+
throw new \RuntimeException("pdflatex binary not found at path: {$this->pdflatex}");
125+
}
145126

146-
//call the pdflatex command
147-
$command = $this->pdflatex.' -interaction=nonstopmode -output-directory '.$this->resource_path.' '.$this->resource_path.'/'.$this->personalized_template_name.'.tex';
127+
$command = escapeshellcmd($this->pdflatex) . ' -interaction=nonstopmode -output-directory '
128+
. escapeshellarg($this->resource_path) . ' '
129+
. escapeshellarg($this->resource_path . '/' . $this->personalized_template_name . '.tex');
148130

149-
$cwd = $this->resource_path;
150-
$process = Process::fromShellCommandline($command, $cwd);
151-
//$process = new Process($command, $cwd);
152-
$process->run();
131+
$process = Process::fromShellCommandline($command, $this->resource_path);
132+
$process->setTimeout(600); // Allow up to 600 seconds for execution
133+
$this->execute_process($process);
153134

154-
// executes after the command finishes
155-
if (! $process->isSuccessful()) {
135+
if (!$process->isSuccessful()) {
156136
throw new ProcessFailedException($process);
157137
}
158138
}
139+
140+
private function execute_process(Process $process): void
141+
{
142+
$process->start();
143+
144+
while ($process->isRunning()) {
145+
usleep(400000); // Sleep for 400ms
146+
}
147+
}
159148
}

app/Traits/LatexCleaner.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ public function tex_escape($string)
99
$map = [
1010
'ʼ' => "'", // Replace Unicode apostrophe with standard apostrophe
1111
'ə' => '\\textschwa{}', // Handle ə
12+
'"' => "''", // Replace double quotes with two single quotes
1213
'#' => '\\#',
13-
'$' => '\$',
14+
'$' => '\\$',
1415
'%' => '\\%',
1516
'&' => '\\&',
1617
'~' => '\\~{}',
@@ -21,14 +22,12 @@ public function tex_escape($string)
2122
'}' => '\\}',
2223
];
2324

24-
$string = preg_replace_callback(
25-
"/([\^\%~\\\\#\$%&_\{\}ʼ])/",
25+
return preg_replace_callback(
26+
"/([\#\$%&~_\^\\\\{}ʼ\"])/",
2627
function ($matches) use ($map) {
2728
return $map[$matches[0]] ?? $matches[0];
2829
},
2930
$string
3031
);
31-
32-
return $string;
3332
}
3433
}

0 commit comments

Comments
 (0)