Passed
Push — master ( a5830d...268b85 )
by
unknown
16:33 queued 08:04
created

CertificateController::view()   F

Complexity

Conditions 17
Paths 777

Size

Total Lines 51
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 17
eloc 33
c 2
b 0
f 0
nc 777
nop 1
dl 0
loc 51
rs 1.3596

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Framework\Container;
10
use Chamilo\CoreBundle\Helpers\UserHelper;
11
use Chamilo\CoreBundle\Repository\GradebookCertificateRepository;
12
use Chamilo\CoreBundle\Settings\SettingsManager;
13
use Mpdf\Mpdf;
14
use Mpdf\MpdfException;
15
use Mpdf\Output\Destination;
16
use RuntimeException;
17
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
20
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
21
use Symfony\Component\Routing\Attribute\Route;
22
23
#[Route('/certificates')]
24
class CertificateController extends AbstractController
25
{
26
    public function __construct(
27
        private readonly GradebookCertificateRepository $certificateRepository,
28
        private readonly SettingsManager $settingsManager,
29
        private readonly UserHelper $userHelper
30
    ) {}
31
32
    #[Route('/{hash}.html', name: 'chamilo_certificate_public_view', methods: ['GET'])]
33
    public function view(string $hash): Response
34
    {
35
        // Build the expected certificate filename from the hash
36
        $filename = $hash.'.html';
37
        $candidates = [$filename, '/'.$filename, $hash, '/'.$hash];
38
39
        $certificate = null;
40
        $matchedPath = '';
41
        foreach ($candidates as $cand) {
42
            $row = $this->certificateRepository->findOneBy(['pathCertificate' => $cand]);
43
            if ($row) { $certificate = $row; $matchedPath = $cand; break; }
44
        }
45
        if (!$certificate) {
46
            throw new NotFoundHttpException('The requested certificate does not exist.');
47
        }
48
49
        // Check if public access is globally allowed and certificate is marked as published
50
        $allowPublic = 'true' === $this->settingsManager->getSetting('course.allow_public_certificates', true);
51
        $allowSessionAdmin = 'true' === $this->settingsManager->getSetting('certificate.session_admin_can_download_all_certificates', true);
52
        $user = $this->userHelper->getCurrent();
53
        $securityUser = $this->getUser();
54
        $isOwner = $securityUser && method_exists($securityUser, 'getId') && $user->getId() === $securityUser->getId();
55
        $isPlatformAdmin = method_exists($user, 'isAdmin') && $user->isAdmin();
56
57
        if (!$isOwner && !$isPlatformAdmin) {
58
            $isPublic = ($allowPublic && $certificate->getPublish());
59
            $isSessAdminAllowed = ($allowSessionAdmin && method_exists($user, 'isSessionAdmin') && $user->isSessionAdmin());
60
            if (!$isPublic && !$isSessAdminAllowed) {
61
                throw new AccessDeniedHttpException('The requested certificate is not public.');
62
            }
63
        }
64
65
        // Fetch the actual certificate file from personal files using its title
66
        $personalFileRepo = Container::getPersonalFileRepository();
67
        $pf = null;
68
        $pfMatch = '';
69
        foreach ($candidates as $cand) {
70
            $row = $personalFileRepo->findOneBy(['title' => $cand]);
71
            if ($row) { $pf = $row; $pfMatch = $cand; break; }
72
        }
73
        if (!$pf) {
74
            throw new NotFoundHttpException('The certificate file was not found.');
75
        }
76
77
        $content = $personalFileRepo->getResourceFileContent($pf);
78
        $content = str_replace(' media="screen"', '', $content);
79
80
        // Return the certificate as a raw HTML response
81
        return new Response('<!DOCTYPE html>'.$content, 200, [
82
            'Content-Type' => 'text/html; charset=UTF-8',
83
        ]);
84
    }
85
86
    #[Route('/{hash}.pdf', name: 'chamilo_certificate_public_pdf', methods: ['GET'])]
87
    public function downloadPdf(string $hash): Response
88
    {
89
        $filename = $hash.'.html';
90
        $candidates = [$filename, '/'.$filename, $hash, '/'.$hash];
91
92
        $certificate = null;
93
        $matchedPath = '';
94
        foreach ($candidates as $cand) {
95
            $row = $this->certificateRepository->findOneBy(['pathCertificate' => $cand]);
96
            if ($row) { $certificate = $row; $matchedPath = $cand; break; }
97
        }
98
        if (!$certificate) {
99
            throw $this->createNotFoundException('The requested certificate does not exist.');
100
        }
101
102
        $allowPublic = 'true' === $this->settingsManager->getSetting('course.allow_public_certificates', true);
103
        $allowSessionAdmin = 'true' === $this->settingsManager->getSetting('certificate.session_admin_can_download_all_certificates', true);
104
        $user = $this->userHelper->getCurrent();
105
        $securityUser = $this->getUser();
106
        $isOwner = $securityUser && method_exists($securityUser, 'getId') && $user->getId() === $securityUser->getId();
107
        $isPlatformAdmin = method_exists($user, 'isAdmin') && $user->isAdmin();
108
109
        if (!$isOwner && !$isPlatformAdmin) {
110
            $isPublic = ($allowPublic && $certificate->getPublish());
111
            $isSessAdminAllowed = ($allowSessionAdmin && method_exists($user, 'isSessionAdmin') && $user->isSessionAdmin());
112
            if (!$isPublic && !$isSessAdminAllowed) {
113
                throw new AccessDeniedHttpException('The requested certificate is not public.');
114
            }
115
        }
116
117
        $personalFileRepo = Container::getPersonalFileRepository();
118
        $pf = null;
119
        $pfMatch = '';
120
        foreach ($candidates as $cand) {
121
            $row = $personalFileRepo->findOneBy(['title' => $cand]);
122
            if ($row) { $pf = $row; $pfMatch = $cand; break; }
123
        }
124
        if (!$pf) {
125
            throw $this->createNotFoundException('The certificate file was not found.');
126
        }
127
128
        $html = $personalFileRepo->getResourceFileContent($pf);
129
        $html = str_replace(' media="screen"', '', $html);
130
131
        try {
132
            $mpdf = new Mpdf([
133
                'format' => 'A4',
134
                'tempDir' => api_get_path(SYS_ARCHIVE_PATH).'mpdf/',
135
            ]);
136
            $mpdf->WriteHTML($html);
137
138
            return new Response(
139
                $mpdf->Output('certificate.pdf', Destination::DOWNLOAD),
140
                200,
141
                [
142
                    'Content-Type' => 'application/pdf',
143
                    'Content-Disposition' => 'attachment; filename="certificate.pdf"',
144
                ]
145
            );
146
        } catch (MpdfException $e) {
147
            throw new RuntimeException('Failed to generate PDF: '.$e->getMessage(), 500, $e);
148
        }
149
    }
150
}
151