Passed
Pull Request — master (#6357)
by Angel Fernando Quiroz
07:55
created

SessionAdminController::extendSessionByWeek()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 36
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 22
nc 4
nop 3
dl 0
loc 36
rs 8.9457
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Controller\Admin;
8
9
use Chamilo\CoreBundle\Controller\BaseController;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\GradebookCertificate;
12
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
13
use Chamilo\CoreBundle\Entity\SessionRelUser;
14
use Chamilo\CoreBundle\Repository\GradebookCertificateRepository;
15
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
16
use Chamilo\CoreBundle\Repository\SessionRelCourseRelUserRepository;
17
use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper;
18
use DateTime;
19
use Doctrine\ORM\EntityManagerInterface;
20
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
21
use Symfony\Component\HttpFoundation\JsonResponse;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\Routing\Annotation\Route;
25
26
#[Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_SESSION_MANAGER')")]
27
#[Route('/admin/sessionadmin')]
28
class SessionAdminController extends BaseController
29
{
30
    public function __construct(
31
        private readonly CourseRepository $courseRepository,
32
        private readonly AccessUrlHelper $accessUrlHelper
33
    ) {}
34
35
    #[Route('/courses', name: 'chamilo_core_admin_sessionadmin_courses', methods: ['GET'])]
36
    public function listCourses(): JsonResponse
37
    {
38
        $url     = $this->accessUrlHelper->getCurrent();
39
        $courses = $this->courseRepository->getCoursesByAccessUrl($url);
40
41
        $data = array_map(static function (Course $course) {
42
            return [
43
                'id'          => $course->getId(),
44
                'title'       => $course->getTitle(),
45
                'code' => $course->getCode(),
46
                'description' => $course->getDescription(),
47
                'visibility'  => $course->getVisibility(),
48
                'illustrationUrl' => method_exists($course, 'getIllustrationUrl')
49
                    ? $course->getIllustrationUrl()
50
                    : null,
51
            ];
52
        }, $courses);
53
54
        return $this->json($data);
55
    }
56
57
    #[Route('/courses/completed', name: 'chamilo_core_admin_sessionadmin_courses_completed', methods: ['GET'])]
58
    public function listCompleted(
59
        Request $request,
60
        GradebookCertificateRepository $repo,
61
        AccessUrlHelper $accessUrlHelper,
62
    ): JsonResponse {
63
        // Extract and validate pagination parameters from the query
64
        $offset = max(0, (int) $request->query->get('offset', 0));
65
        $limit  = max(1, (int) $request->query->get('limit', 50));
66
67
        // Determine current access URL context
68
        $url = $accessUrlHelper->getCurrent();
69
70
        // Retrieve certificates with associated session and course context
71
        $certs = $repo->findCertificatesWithContext($url->getId(), $offset, $limit);
72
73
        // Transform the certificate entities into a frontend-friendly structure
74
        $mapCertificate = function (GradebookCertificate $gc) {
75
            $sessionRel = $gc->getCategory()->getCourse()->getSessions()[0] ?? null;
76
            $session = $sessionRel?->getSession();
77
            $hash = pathinfo($gc->getPathCertificate(), PATHINFO_FILENAME);
78
79
            return [
80
                'id'        => $gc->getId(),
81
                'issuedAt'  => $gc->getCreatedAt()->format('Y-m-d H:i:s'),
82
                'user'      => [
83
                    'id'   => $gc->getUser()->getId(),
84
                    'name' => $gc->getUser()->getFullName(),
85
                ],
86
                'course'    => [
87
                    'id'    => $gc->getCategory()->getCourse()->getId(),
88
                    'title' => $gc->getCategory()->getCourse()->getTitle(),
89
                ],
90
                'session'   => $session ? [
91
                    'id'    => $session->getId(),
92
                    'title' => $session->getTitle(),
93
                ] : null,
94
                'downloadUrl' => '/certificates/'.$hash.'.pdf',
0 ignored issues
show
Bug introduced by
Are you sure $hash of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
                'downloadUrl' => '/certificates/'./** @scrutinizer ignore-type */ $hash.'.pdf',
Loading history...
95
            ];
96
        };
97
98
        $items = array_map($mapCertificate, $certs);
99
100
        // Return JSON response with pagination metadata and certificate list
101
        return $this->json([
102
            'items'  => $items,
103
            'offset' => $offset,
104
            'limit'  => $limit,
105
            'count'  => \count($items),
106
        ]);
107
    }
108
109
    #[Route('/courses/incomplete', name: 'chamilo_core_admin_sessionadmin_courses_incomplete', methods: ['GET'])]
110
    public function listIncomplete(
111
        GradebookCertificateRepository $repo,
112
        AccessUrlHelper $accessUrlHelper
113
    ): JsonResponse {
114
        $url = $accessUrlHelper->getCurrent();
115
        $results = $repo->findIncompleteCertificates($url->getId());
116
117
        $items = array_map(function (SessionRelUser $sru) {
118
            $user = $sru->getUser();
119
            $session = $sru->getSession();
120
121
            $courses = $session->getCourses();
122
            $courseItems = [];
123
124
            foreach ($courses as $src) {
125
                $course = $src->getCourse();
126
127
                $courseItems[] = [
128
                    'user' => [
129
                        'id'   => $user->getId(),
130
                        'name' => $user->getFullName(),
131
                    ],
132
                    'course' => [
133
                        'id'    => $course->getId(),
134
                        'title' => $course->getTitle(),
135
                    ],
136
                    'session' => [
137
                        'id'    => $session->getId(),
138
                        'title' => $session->getTitle(),
139
                        'startDate' => $session->getAccessStartDate()?->format('Y-m-d'),
140
                        'endDate'   => $session->getAccessEndDate()?->format('Y-m-d'),
141
                    ],
142
                ];
143
            }
144
145
            return $courseItems;
146
        }, $results);
147
148
        $flatItems = array_merge(...$items);
149
150
        return $this->json([
151
            'items' => $flatItems,
152
            'count' => count($flatItems),
153
        ]);
154
    }
155
156
    #[Route('/courses/restartable', name: 'chamilo_core_admin_sessionadmin_courses_restartable', methods: ['GET'])]
157
    public function listRestartables(
158
        Request $request,
159
        GradebookCertificateRepository $repo,
160
        AccessUrlHelper $accessUrlHelper
161
    ): JsonResponse {
162
        $offset = max(0,  (int) $request->query->get('offset', 0));
163
        $limit  = max(1,  (int) $request->query->get('limit', 10));
164
165
        $urlId  = $accessUrlHelper->getCurrent()->getId();
166
167
        /** @var SessionRelCourseRelUser[] $rows */
168
        $rows = $repo->findRestartableSessions($urlId, $offset, $limit);
169
170
        $items = array_map(static function (SessionRelCourseRelUser $srcu) {
171
            $session = $srcu->getSession();
172
            $course  = $srcu->getCourse();
173
            $user    = $srcu->getUser();
174
175
            return [
176
                'user'    => ['id' => $user->getId(),   'name' => $user->getFullName()],
177
                'course'  => ['id' => $course->getId(), 'title'=> $course->getTitle()],
178
                'session' => [
179
                    'id'      => $session->getId(),
180
                    'title'   => $session->getTitle(),
181
                    'endDate' => $session->getAccessEndDate()?->format('Y-m-d'),
182
                ],
183
            ];
184
        }, $rows);
185
186
        return $this->json([
187
            'items'  => $items,
188
            'offset' => $offset,
189
            'limit'  => $limit,
190
            'count'  => \count($items),
191
        ]);
192
    }
193
194
    #[Route('/courses/extend_week', name: 'chamilo_core_admin_sessionadmin_session_extend_one_week', methods: ['POST'])]
195
    public function extendSessionByWeek(Request $request, SessionRelCourseRelUserRepository $sessionRelCourseRelUserRepository, EntityManagerInterface $entityManager): JsonResponse
196
    {
197
        $data = json_decode($request->getContent(), true);
198
        $sessionId = (int) ($data['sessionId'] ?? 0);
199
        $userId    = (int) ($data['userId'] ?? 0);
200
        $courseId  = (int) ($data['courseId'] ?? 0);
201
202
        if (!$sessionId || !$userId || !$courseId) {
203
            return $this->json(['error' => 'Missing data'], Response::HTTP_BAD_REQUEST);
204
        }
205
206
        $rel = $sessionRelCourseRelUserRepository->findOneBy([
207
            'session' => $sessionId,
208
            'user' => $userId,
209
            'course' => $courseId,
210
        ]);
211
212
        if (!$rel) {
213
            return $this->json(['error' => 'Relation not found'], Response::HTTP_NOT_FOUND);
214
        }
215
216
        $session = $rel->getSession();
217
218
        $now = new DateTime('now');
219
        $currentEndDate = $session->getAccessEndDate();
220
221
        $baseDate = $now > $currentEndDate ? $now : $currentEndDate;
222
223
        $newEndDate = clone $baseDate;
224
        $newEndDate->modify('+1 week');
225
226
        $session->setAccessEndDate($newEndDate);
227
        $entityManager->flush();
228
229
        return $this->json(['success' => true, 'message' => 'Session extended by one week.', 'newEndDate' => $newEndDate->format('Y-m-d')]);
230
    }
231
}
232