Skip to content

Commit 7b7f8fa

Browse files
authored
Merge pull request #3491 from codeeu/dev
ticketing system
2 parents bb0b249 + 18be72c commit 7b7f8fa

File tree

102 files changed

+3668
-835
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+3668
-835
lines changed

app/Achievements/AchievementsServiceProvider.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ class AchievementsServiceProvider extends ServiceProvider
5252
Types\InfluencerExpert2024::class,
5353
Types\InfluencerChampion2024::class,
5454
Types\InfluencerLegendary2024::class,
55+
Types\OrganiserActive2026::class,
56+
Types\OrganiserExpert2026::class,
57+
Types\Influencer2026::class,
58+
Types\InfluencerActive2026::class,
59+
Types\InfluencerExpert2026::class,
60+
Types\InfluencerChampion2026::class,
61+
Types\InfluencerLegendary2026::class,
5562

5663
];
5764

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class Influencer2026 extends AchievementType
6+
{
7+
public $icon = 'influencer/influencer_normal_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Influencer 2026';
12+
13+
public function description()
14+
{
15+
return 'Spread your influence more to get 10 bits';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->influence($this->edition) >= 10;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class InfluencerActive2026 extends AchievementType
6+
{
7+
public $icon = 'influencer/influencer_active_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Active Influencer 2026';
12+
13+
public function description()
14+
{
15+
return 'Spread your influence more to get 20 bits';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->influence($this->edition) >= 20;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class InfluencerChampion2026 extends AchievementType
6+
{
7+
public $icon = 'influencer/influencer_champion_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Champion Influencer 2026';
12+
13+
public function description()
14+
{
15+
return 'Spread your influence more to get 40 bits';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->influence($this->edition) >= 40;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class InfluencerExpert2026 extends AchievementType
6+
{
7+
public $icon = 'influencer/influencer_expert_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Expert Influencer 2026';
12+
13+
public function description()
14+
{
15+
return 'Spread your influence more to get 30 bits';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->influence($this->edition) >= 30;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class InfluencerLegendary2026 extends AchievementType
6+
{
7+
public $icon = 'influencer/influencer_legendary_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Legendary Influencer 2026';
12+
13+
public function description()
14+
{
15+
return 'Spread your influence more to get 60 bits';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->influence($this->edition) >= 60;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class OrganiserActive2026 extends AchievementType
6+
{
7+
public $icon = 'organiser/organiser_active_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Active Organiser 2026';
12+
13+
public function description()
14+
{
15+
return 'Report 5 activities to unlock';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->reported($this->edition) >= 5;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Achievements\Types;
4+
5+
class OrganiserExpert2026 extends AchievementType
6+
{
7+
public $icon = 'organiser/organiser_expert_2026.png';
8+
9+
public $edition = 2026;
10+
11+
public $name = 'Expert Organiser 2026';
12+
13+
public function description()
14+
{
15+
return 'Report 10 activities to unlock';
16+
}
17+
18+
public function qualifier($user)
19+
{
20+
return $user->reported($this->edition) >= 10;
21+
}
22+
}
23+
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
namespace App\Certificates;
4+
5+
use App\Traits\LanguageDetection;
6+
use App\Traits\LatexCleaner;
7+
use Carbon\Carbon;
8+
use Illuminate\Support\Facades\Storage;
9+
use Illuminate\Support\Str;
10+
use Symfony\Component\Process\Process;
11+
12+
class SuperOrganiserCertificate
13+
{
14+
use LanguageDetection, LatexCleaner;
15+
16+
private string $templateName;
17+
private string $name_of_certificate_holder;
18+
private int $number_of_activities;
19+
private string $certificate_date;
20+
private string $language;
21+
22+
private string $resource_path;
23+
private string $pdflatex;
24+
private string $personalized_template_name;
25+
private string $id;
26+
27+
public function __construct(string $holderName, int $numberOfActivities, ?string $certificateDate = null, string $language = 'en')
28+
{
29+
ini_set('max_execution_time', '600');
30+
ini_set('memory_limit', '512M');
31+
32+
$this->name_of_certificate_holder = $holderName;
33+
$this->number_of_activities = $numberOfActivities;
34+
$this->certificate_date = $certificateDate ?: Carbon::now()->format('d/m/Y');
35+
$this->language = $language;
36+
37+
$this->templateName = ($language === 'el')
38+
? 'super-organiser-greek-2025.tex'
39+
: 'super-organiser-2025.tex';
40+
41+
$random = Str::random(10);
42+
$this->personalized_template_name = $random.'-'.'0';
43+
44+
$this->resource_path = resource_path('latex');
45+
$this->pdflatex = config('codeweek.pdflatex_path', '/Library/TeX/texbin/pdflatex');
46+
$this->id = '0-'.$random;
47+
}
48+
49+
public function generate(): string
50+
{
51+
$this->customize_and_save_latex();
52+
$this->run_pdf_creation();
53+
$s3path = $this->upload_to_s3();
54+
$this->clean_temp_files();
55+
56+
return $s3path;
57+
}
58+
59+
private function clean_temp_files(): void
60+
{
61+
foreach (['aux', 'log', 'out', 'tex'] as $ext) {
62+
Storage::disk('latex')->delete($this->personalized_template_name.'.'.$ext);
63+
}
64+
}
65+
66+
protected function customize_and_save_latex(): void
67+
{
68+
$base_template = Storage::disk('latex')->get($this->templateName);
69+
70+
$template = str_replace('<CERTIFICATE_HOLDER_NAME>', $this->tex_escape($this->name_of_certificate_holder), $base_template);
71+
$template = str_replace('<NUMBER_OF_ACTIVITIES>', $this->tex_escape((string) $this->number_of_activities), $template);
72+
$template = str_replace('<CERTIFICATE_DATE>', $this->tex_escape($this->certificate_date), $template);
73+
74+
Storage::disk('latex')->put($this->personalized_template_name.'.tex', $template);
75+
}
76+
77+
protected function run_pdf_creation(): void
78+
{
79+
if (!file_exists($this->pdflatex)) {
80+
throw new \RuntimeException("pdflatex binary not found at path: {$this->pdflatex}");
81+
}
82+
83+
$texFile = $this->resource_path.'/'.$this->personalized_template_name.'.tex';
84+
$command = sprintf(
85+
'%s -interaction=nonstopmode -output-directory %s %s',
86+
escapeshellcmd($this->pdflatex),
87+
escapeshellarg($this->resource_path),
88+
escapeshellarg($texFile)
89+
);
90+
91+
$process = Process::fromShellCommandline($command, $this->resource_path);
92+
$process->setTimeout(600);
93+
$process->run();
94+
}
95+
96+
protected function upload_to_s3(): string
97+
{
98+
$pdfFile = $this->personalized_template_name.'.pdf';
99+
$localPath = storage_path('app/latex/'.$pdfFile);
100+
$s3Path = 'certificates/super-organiser/'.$pdfFile;
101+
102+
Storage::disk('s3')->put($s3Path, file_get_contents($localPath), 'public');
103+
104+
return Storage::disk('s3')->url($s3Path);
105+
}
106+
107+
private function tex_escape(string $string): string
108+
{
109+
$map = [
110+
'#' => '\\#',
111+
'$' => '\\$',
112+
'%' => '\\%',
113+
'&' => '\\&',
114+
'~' => '\\~{}',
115+
'_' => '\\_',
116+
'^' => '\\^{}',
117+
'\\' => '\\textbackslash{}',
118+
'{' => '\\{',
119+
'}' => '\\}',
120+
];
121+
122+
return preg_replace_callback(
123+
"/([\\^\\%~\\\\#\\$%&_\\{\\}])/",
124+
fn ($matches) => $map[$matches[0]] ?? $matches[0],
125+
$string
126+
) ?? $string;
127+
}
128+
}
129+

app/Console/Commands/Kernel.php

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)