Passed
Pull Request — master (#6343)
by
unknown
08:02
created

CertificateController::downloadPdf()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 26
nc 7
nop 1
dl 0
loc 40
rs 8.8817
c 1
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Controller;
8
9
use Chamilo\CoreBundle\Repository\GradebookCertificateRepository;
10
use Chamilo\CoreBundle\Settings\SettingsManager;
11
use Chamilo\CoreBundle\Framework\Container;
12
use Mpdf\Mpdf;
13
use Mpdf\MpdfException;
14
use Mpdf\Output\Destination;
15
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
16
use Symfony\Component\HttpFoundation\Response;
17
use Symfony\Component\Routing\Attribute\Route;
18
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
20
21
#[Route('/certificates')]
22
class CertificateController extends AbstractController
23
{
24
    public function __construct(
25
        private readonly GradebookCertificateRepository $certificateRepository,
26
        private readonly SettingsManager $settingsManager
27
    ) {}
28
29
    #[Route('/{hash}.html', name: 'chamilo_certificate_public_view', methods: ['GET'])]
30
    public function view(string $hash): Response
31
    {
32
        // Build the expected certificate filename from the hash
33
        $filename = $hash . '.html';
34
35
        // Look up the certificate record by its path
36
        $certificate = $this->certificateRepository->findOneBy([
37
            'pathCertificate' => $filename,
38
        ]);
39
40
        if (!$certificate) {
41
            throw new NotFoundHttpException('The requested certificate does not exist.');
42
        }
43
44
        // Check if public access is globally allowed and certificate is marked as published
45
        $allowPublic = 'true' === $this->settingsManager->getSetting('course.allow_public_certificates', true);
46
        if (!$allowPublic || !$certificate->getPublish()) {
47
            throw new AccessDeniedHttpException('The requested certificate is not public.');
48
        }
49
50
        // Fetch the actual certificate file from personal files using its title
51
        $personalFileRepo = Container::getPersonalFileRepository();
52
        $personalFile = $personalFileRepo->findOneBy(['title' => $filename]);
53
54
        if (!$personalFile) {
55
            throw new NotFoundHttpException('The certificate file was not found.');
56
        }
57
58
        // Read the certificate HTML content and sanitize for print compatibility
59
        $content = $personalFileRepo->getResourceFileContent($personalFile);
60
        $content = str_replace(' media="screen"', '', $content);
61
62
        // Return the certificate as a raw HTML response
63
        return new Response('<!DOCTYPE html>' . $content, 200, [
64
            'Content-Type' => 'text/html; charset=UTF-8',
65
        ]);
66
    }
67
68
    #[Route('/{hash}.pdf', name: 'chamilo_certificate_public_pdf', methods: ['GET'])]
69
    public function downloadPdf(string $hash): Response
70
    {
71
        $filename = $hash . '.html';
72
73
        $certificate = $this->certificateRepository->findOneBy(['pathCertificate' => $filename]);
74
        if (!$certificate) {
75
            throw $this->createNotFoundException('The requested certificate does not exist.');
76
        }
77
78
        $allowPublic = 'true' === $this->settingsManager->getSetting('course.allow_public_certificates', true);
79
        if (!$allowPublic || !$certificate->getPublish()) {
80
            throw $this->createAccessDeniedException('The requested certificate is not public.');
81
        }
82
83
        $personalFileRepo = Container::getPersonalFileRepository();
84
        $personalFile = $personalFileRepo->findOneBy(['title' => $filename]);
85
        if (!$personalFile) {
86
            throw $this->createNotFoundException('The certificate file was not found.');
87
        }
88
89
        $html = $personalFileRepo->getResourceFileContent($personalFile);
90
        $html = str_replace(' media="screen"', '', $html);
91
92
        try {
93
            $mpdf = new Mpdf([
94
                'format' => 'A4',
95
                'tempDir' => api_get_path(SYS_ARCHIVE_PATH).'mpdf/',
96
            ]);
97
            $mpdf->WriteHTML($html);
98
            return new Response(
99
                $mpdf->Output('certificate.pdf', Destination::DOWNLOAD),
100
                200,
101
                [
102
                    'Content-Type' => 'application/pdf',
103
                    'Content-Disposition' => 'attachment; filename="certificate.pdf"',
104
                ]
105
            );
106
        } catch (MpdfException $e) {
107
            throw new \RuntimeException('Failed to generate PDF: '.$e->getMessage(), 500, $e);
108
        }
109
    }
110
}
111