Passed
Pull Request — master (#6357)
by
unknown
10:25
created

SessionAdminController::searchUsers()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 57
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 34
c 0
b 0
f 0
nc 16
nop 6
dl 0
loc 57
rs 8.7537

How to fix   Long Method   

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
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\Helpers\AccessUrlHelper;
15
use Chamilo\CoreBundle\Entity\ExtraField;
16
use Chamilo\CoreBundle\Repository\ExtraFieldRepository;
17
use Chamilo\CoreBundle\Repository\ExtraFieldValuesRepository;
18
use Chamilo\CoreBundle\Repository\GradebookCertificateRepository;
19
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
20
use Chamilo\CoreBundle\Repository\Node\UserRepository;
21
use Chamilo\CoreBundle\Repository\SessionRelCourseRelUserRepository;
22
use Chamilo\CoreBundle\Settings\SettingsManager;
23
use DateTime;
24
use Doctrine\ORM\EntityManagerInterface;
25
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
26
use Symfony\Component\HttpFoundation\JsonResponse;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\Routing\Annotation\Route;
30
31
#[Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_SESSION_MANAGER')")]
32
#[Route('/admin/sessionadmin')]
33
class SessionAdminController extends BaseController
34
{
35
    public function __construct(
36
        private readonly CourseRepository $courseRepository,
37
        private readonly AccessUrlHelper $accessUrlHelper,
38
        private readonly SettingsManager $settingsManager
39
    ) {}
40
41
    #[Route('/courses', name: 'chamilo_core_admin_sessionadmin_courses', methods: ['GET'])]
42
    public function listCourses(): JsonResponse
43
    {
44
        $url     = $this->accessUrlHelper->getCurrent();
45
        $courses = $this->courseRepository->getCoursesByAccessUrl($url);
46
47
        $data = array_map(static function (Course $course) {
48
            return [
49
                'id'          => $course->getId(),
50
                'title'       => $course->getTitle(),
51
                'code' => $course->getCode(),
52
                'description' => $course->getDescription(),
53
                'visibility'  => $course->getVisibility(),
54
                'illustrationUrl' => method_exists($course, 'getIllustrationUrl')
55
                    ? $course->getIllustrationUrl()
56
                    : null,
57
            ];
58
        }, $courses);
59
60
        return $this->json($data);
61
    }
62
63
    #[Route('/courses/completed', name: 'chamilo_core_admin_sessionadmin_courses_completed', methods: ['GET'])]
64
    public function listCompleted(
65
        Request $request,
66
        GradebookCertificateRepository $repo,
67
        AccessUrlHelper $accessUrlHelper,
68
    ): JsonResponse {
69
        // Extract and validate pagination parameters from the query
70
        $offset = max(0, (int) $request->query->get('offset', 0));
71
        $limit  = max(1, (int) $request->query->get('limit', 50));
72
73
        // Determine current access URL context
74
        $url = $accessUrlHelper->getCurrent();
75
76
        // Retrieve certificates with associated session and course context
77
        $certs = $repo->findCertificatesWithContext($url->getId(), $offset, $limit);
78
79
        // Transform the certificate entities into a frontend-friendly structure
80
        $mapCertificate = function (GradebookCertificate $gc) {
81
            $sessionRel = $gc->getCategory()->getCourse()->getSessions()[0] ?? null;
82
            $session = $sessionRel?->getSession();
83
            $path = $gc->getPathCertificate();
84
85
            $hash = null;
86
            $downloadUrl = null;
87
88
            if (!empty($path)) {
89
                $hash = pathinfo($path, PATHINFO_FILENAME);
90
                $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

90
                $downloadUrl = '/certificates/'./** @scrutinizer ignore-type */ $hash.'.pdf';
Loading history...
91
            }
92
93
            return [
94
                'id'        => $gc->getId(),
95
                'issuedAt'  => $gc->getCreatedAt()->format('Y-m-d H:i:s'),
96
                'user'      => [
97
                    'id'   => $gc->getUser()->getId(),
98
                    'name' => $gc->getUser()->getFullName(),
99
                ],
100
                'course'    => [
101
                    'id'    => $gc->getCategory()->getCourse()->getId(),
102
                    'title' => $gc->getCategory()->getCourse()->getTitle(),
103
                ],
104
                'session'   => $session ? [
105
                    'id'    => $session->getId(),
106
                    'title' => $session->getTitle(),
107
                ] : null,
108
                'downloadUrl' => $downloadUrl,
109
            ];
110
        };
111
112
        $items = array_map($mapCertificate, $certs);
113
114
        // Return JSON response with pagination metadata and certificate list
115
        return $this->json([
116
            'items'  => $items,
117
            'offset' => $offset,
118
            'limit'  => $limit,
119
            'count'  => \count($items),
120
        ]);
121
    }
122
123
    #[Route('/courses/incomplete', name: 'chamilo_core_admin_sessionadmin_courses_incomplete', methods: ['GET'])]
124
    public function listIncomplete(
125
        GradebookCertificateRepository $repo,
126
        AccessUrlHelper $accessUrlHelper
127
    ): JsonResponse {
128
        $url = $accessUrlHelper->getCurrent();
129
        $results = $repo->findIncompleteCertificates($url->getId());
130
131
        $items = array_map(function (SessionRelUser $sru) {
132
            $user = $sru->getUser();
133
            $session = $sru->getSession();
134
135
            $courses = $session->getCourses();
136
            $courseItems = [];
137
138
            foreach ($courses as $src) {
139
                $course = $src->getCourse();
140
141
                $courseItems[] = [
142
                    'user' => [
143
                        'id'   => $user->getId(),
144
                        'name' => $user->getFullName(),
145
                    ],
146
                    'course' => [
147
                        'id'    => $course->getId(),
148
                        'title' => $course->getTitle(),
149
                    ],
150
                    'session' => [
151
                        'id'    => $session->getId(),
152
                        'title' => $session->getTitle(),
153
                        'startDate' => $session->getAccessStartDate()?->format('Y-m-d'),
154
                        'endDate'   => $session->getAccessEndDate()?->format('Y-m-d'),
155
                    ],
156
                ];
157
            }
158
159
            return $courseItems;
160
        }, $results);
161
162
        $flatItems = array_merge(...$items);
163
164
        return $this->json([
165
            'items' => $flatItems,
166
            'count' => count($flatItems),
167
        ]);
168
    }
169
170
    #[Route('/courses/restartable', name: 'chamilo_core_admin_sessionadmin_courses_restartable', methods: ['GET'])]
171
    public function listRestartables(
172
        Request $request,
173
        GradebookCertificateRepository $repo,
174
        AccessUrlHelper $accessUrlHelper
175
    ): JsonResponse {
176
        $offset = max(0,  (int) $request->query->get('offset', 0));
177
        $limit  = max(1,  (int) $request->query->get('limit', 10));
178
179
        $urlId  = $accessUrlHelper->getCurrent()->getId();
180
181
        /** @var SessionRelCourseRelUser[] $rows */
182
        $rows = $repo->findRestartableSessions($urlId, $offset, $limit);
183
184
        $items = array_map(static function (SessionRelCourseRelUser $srcu) {
185
            $session = $srcu->getSession();
186
            $course  = $srcu->getCourse();
187
            $user    = $srcu->getUser();
188
189
            return [
190
                'user'    => ['id' => $user->getId(),   'name' => $user->getFullName()],
191
                'course'  => ['id' => $course->getId(), 'title'=> $course->getTitle()],
192
                'session' => [
193
                    'id'      => $session->getId(),
194
                    'title'   => $session->getTitle(),
195
                    'endDate' => $session->getAccessEndDate()?->format('Y-m-d'),
196
                ],
197
            ];
198
        }, $rows);
199
200
        return $this->json([
201
            'items'  => $items,
202
            'offset' => $offset,
203
            'limit'  => $limit,
204
            'count'  => \count($items),
205
        ]);
206
    }
207
208
    #[Route('/courses/extend_week', name: 'chamilo_core_admin_sessionadmin_session_extend_one_week', methods: ['POST'])]
209
    public function extendSessionByWeek(Request $request, SessionRelCourseRelUserRepository $sessionRelCourseRelUserRepository, EntityManagerInterface $entityManager): JsonResponse
210
    {
211
        $data = json_decode($request->getContent(), true);
212
        $sessionId = (int) ($data['sessionId'] ?? 0);
213
        $userId    = (int) ($data['userId'] ?? 0);
214
        $courseId  = (int) ($data['courseId'] ?? 0);
215
216
        if (!$sessionId || !$userId || !$courseId) {
217
            return $this->json(['error' => 'Missing data'], Response::HTTP_BAD_REQUEST);
218
        }
219
220
        $rel = $sessionRelCourseRelUserRepository->findOneBy([
221
            'session' => $sessionId,
222
            'user' => $userId,
223
            'course' => $courseId,
224
        ]);
225
226
        if (!$rel) {
227
            return $this->json(['error' => 'Relation not found'], Response::HTTP_NOT_FOUND);
228
        }
229
230
        $session = $rel->getSession();
231
232
        $now = new DateTime('now');
233
        $currentEndDate = $session->getAccessEndDate();
234
235
        $baseDate = $now > $currentEndDate ? $now : $currentEndDate;
236
237
        $newEndDate = clone $baseDate;
238
        $newEndDate->modify('+1 week');
239
240
        $session->setAccessEndDate($newEndDate);
241
        $entityManager->flush();
242
243
        return $this->json(['success' => true, 'message' => 'Session extended by one week.', 'newEndDate' => $newEndDate->format('Y-m-d')]);
244
    }
245
246
    #[Route('/courses/{id}', name: 'chamilo_core_admin_sessionadmin_course_view', methods: ['GET'])]
247
    public function getCourseForSessionAdmin(int $id): JsonResponse
248
    {
249
        $course = $this->courseRepository->find($id);
250
251
        if (!$course) {
252
            return $this->json(['error' => 'Course not found'], Response::HTTP_NOT_FOUND);
253
        }
254
255
        return $this->json([
256
            'id' => $course->getId(),
257
            'title' => $course->getTitle(),
258
            'code' => $course->getCode(),
259
            'description' => $course->getDescription(),
260
            'illustrationUrl' => method_exists($course, 'getIllustrationUrl') ? $course->getIllustrationUrl() : null,
261
        ]);
262
    }
263
264
    #[Route('/users', name: 'chamilo_core_admin_sessionadmin_search_users', methods: ['GET'])]
265
    public function searchUsers(
266
        Request $request,
267
        UserRepository $userRepo,
268
        ExtraFieldRepository $extraFieldRepo,
269
        ExtraFieldValuesRepository $extraFieldValuesRepo,
270
        AccessUrlHelper $accessUrlHelper,
271
        SettingsManager $settingsManager,
272
    ): JsonResponse {
273
        $lastname = $request->query->get('lastname');
274
        $firstname = $request->query->get('firstname');
275
        $extraFilters = $request->query->all('extraFilters');
276
277
        $configuredExtraFieldVariable = $settingsManager->getSetting('platform.session_admin_user_subscription_search_extra_field_to_search', true);
278
279
        $filters = [];
280
        if ($lastname) {
281
            $filters['lastname'] = $lastname;
282
        }
283
        if ($firstname) {
284
            $filters['firstname'] = $firstname;
285
        }
286
        if ($configuredExtraFieldVariable && !empty($extraFilters[$configuredExtraFieldVariable])) {
287
            $filters['extraFilters'] = [
288
                $configuredExtraFieldVariable => $extraFilters[$configuredExtraFieldVariable],
289
            ];
290
        }
291
292
        $users = $userRepo->findUsersForSessionAdmin(
293
            $filters['lastname'] ?? null,
294
            $filters['firstname'] ?? null,
295
            $filters['extraFilters'] ?? [],
296
            $accessUrlHelper->getCurrent(),
297
        );
298
299
        $data = [];
300
        foreach ($users as $user) {
301
            $extraValue = $extraFieldValuesRepo->getValueByVariableAndItem(
302
                $configuredExtraFieldVariable,
303
                $user->getId(),
304
                ExtraField::USER_FIELD_TYPE
305
            );
306
307
            $extra[$configuredExtraFieldVariable] = $extraValue->getFieldValue();
308
309
            $data[] = [
310
                'id' => $user->getId(),
311
                'lastname' => $user->getLastname(),
312
                'firstname' => $user->getFirstname(),
313
                'fullname' => trim($user->getFirstname() . ' ' . $user->getLastname()),
314
                'email' => $user->getEmail(),
315
                'extra' => $extra,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extra seems to be defined later in this foreach loop on line 307. Are you sure it is defined here?
Loading history...
316
            ];
317
        }
318
319
        return $this->json([
320
            'items' => $data,
321
        ]);
322
    }
323
}
324