Passed
Pull Request — master (#6472)
by
unknown
09:00
created

SessionController   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 389
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 227
dl 0
loc 389
rs 9.36
c 0
b 0
f 0
wmc 38

4 Methods

Rating   Name   Duplication   Size   Complexity  
B getNextSession() 0 54 8
A __construct() 0 5 1
C sendCourseNotification() 0 110 10
F about() 0 212 19
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Controller;
8
9
use BuyCoursesPlugin;
10
use Chamilo\CoreBundle\Entity\AccessUrlRelUser;
11
use Chamilo\CoreBundle\Entity\ExtraField;
12
use Chamilo\CoreBundle\Entity\SequenceResource;
13
use Chamilo\CoreBundle\Entity\Session;
14
use Chamilo\CoreBundle\Entity\SessionRelCourse;
15
use Chamilo\CoreBundle\Entity\SessionRelUser;
16
use Chamilo\CoreBundle\Entity\Tag;
17
use Chamilo\CoreBundle\Entity\User;
18
use Chamilo\CoreBundle\Framework\Container;
19
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
20
use Chamilo\CoreBundle\Helpers\MessageHelper;
21
use Chamilo\CoreBundle\Helpers\UserHelper;
22
use Chamilo\CoreBundle\Repository\Node\IllustrationRepository;
23
use Chamilo\CoreBundle\Repository\Node\UserRepository;
24
use Chamilo\CoreBundle\Repository\SequenceRepository;
25
use Chamilo\CoreBundle\Repository\SequenceResourceRepository;
26
use Chamilo\CoreBundle\Repository\TagRepository;
27
use Chamilo\CourseBundle\Entity\CCourseDescription;
28
use CourseDescription;
29
use DateTime;
30
use Doctrine\ORM\EntityManagerInterface;
31
use Doctrine\ORM\EntityRepository;
32
use Essence\Essence;
33
use ExtraFieldValue;
34
use Graphp\GraphViz\GraphViz;
35
use SessionManager;
36
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
37
use Symfony\Bundle\SecurityBundle\Security;
38
use Symfony\Component\HttpFoundation\JsonResponse;
39
use Symfony\Component\HttpFoundation\Request;
40
use Symfony\Component\HttpFoundation\RequestStack;
41
use Symfony\Component\HttpFoundation\Response;
42
use Symfony\Component\Routing\Attribute\Route;
43
use Symfony\Contracts\Translation\TranslatorInterface;
44
use UserManager;
45
46
#[Route('/sessions')]
47
class SessionController extends AbstractController
48
{
49
    public function __construct(
50
        private readonly UserHelper $userHelper,
51
        private readonly TranslatorInterface $translator,
52
        private readonly RequestStack $requestStack
53
    ) {}
54
55
    #[Route(path: '/{sid}/about', name: 'chamilo_core_session_about')]
56
    public function about(
57
        Request $request,
58
        Session $session,
59
        IllustrationRepository $illustrationRepo,
60
        UserRepository $userRepo,
61
        EntityManagerInterface $em
62
    ): Response {
63
        $requestSession = $request->getSession();
64
        $htmlHeadXtra[] = api_get_asset('readmore-js/readmore.js');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$htmlHeadXtra was never initialized. Although not strictly required by PHP, it is generally a good practice to add $htmlHeadXtra = array(); before regardless.
Loading history...
65
66
        $sessionId = $session->getId();
67
        $courses = [];
68
        $sessionCourses = $session->getCourses();
69
70
        /** @var EntityRepository $fieldsRepo */
71
        $fieldsRepo = $em->getRepository(ExtraField::class);
72
73
        /** @var TagRepository $tagRepo */
74
        $tagRepo = $em->getRepository(Tag::class);
75
76
        /** @var SequenceRepository $sequenceResourceRepo */
77
        $sequenceResourceRepo = $em->getRepository(SequenceResource::class);
78
79
        /** @var ExtraField $tagField */
80
        $tagField = $fieldsRepo->findOneBy([
81
            'itemType' => ExtraField::COURSE_FIELD_TYPE,
82
            'variable' => 'tags',
83
        ]);
84
85
        $courseValues = new ExtraFieldValue('course');
86
        $userValues = new ExtraFieldValue('user');
87
        $sessionValues = new ExtraFieldValue('session');
88
89
        /** @var SessionRelCourse $sessionRelCourse */
90
        foreach ($sessionCourses as $sessionRelCourse) {
91
            $sessionCourse = $sessionRelCourse->getCourse();
92
            $courseTags = [];
93
94
            if (null !== $tagField) {
95
                $courseTags = $tagRepo->getTagsByItem($tagField, $sessionCourse->getId());
96
            }
97
98
            $courseCoaches = $userRepo->getCoachesForSessionCourse($session, $sessionCourse);
99
            $coachesData = [];
100
101
            /** @var User $courseCoach */
102
            foreach ($courseCoaches as $courseCoach) {
103
                $coachData = [
104
                    'complete_name' => UserManager::formatUserFullName($courseCoach),
105
                    'image' => $illustrationRepo->getIllustrationUrl($courseCoach),
106
                    'diploma' => $courseCoach->getDiplomas(),
107
                    'openarea' => $courseCoach->getOpenarea(),
108
                    'extra_fields' => $userValues->getAllValuesForAnItem(
109
                        $courseCoach->getId(),
110
                        null,
111
                        true
112
                    ),
113
                ];
114
115
                $coachesData[] = $coachData;
116
            }
117
118
            $cd = new CourseDescription();
119
            $cd->set_course_id($sessionCourse->getId());
120
            $cd->set_session_id($session->getId());
121
            $descriptionsData = $cd->get_description_data();
122
123
            $courseDescription = [];
124
            $courseObjectives = [];
125
            $courseTopics = [];
126
            $courseMethodology = [];
127
            $courseMaterial = [];
128
            $courseResources = [];
129
            $courseAssessment = [];
130
            $courseCustom = [];
131
132
            if (!empty($descriptionsData)) {
133
                foreach ($descriptionsData as $descriptionInfo) {
134
                    $type = $descriptionInfo->getDescriptionType();
135
136
                    switch ($type) {
137
                        case CCourseDescription::TYPE_DESCRIPTION:
138
                            $courseDescription[] = $descriptionInfo;
139
140
                            break;
141
142
                        case CCourseDescription::TYPE_OBJECTIVES:
143
                            $courseObjectives[] = $descriptionInfo;
144
145
                            break;
146
147
                        case CCourseDescription::TYPE_TOPICS:
148
                            $courseTopics[] = $descriptionInfo;
149
150
                            break;
151
152
                        case CCourseDescription::TYPE_METHODOLOGY:
153
                            $courseMethodology[] = $descriptionInfo;
154
155
                            break;
156
157
                        case CCourseDescription::TYPE_COURSE_MATERIAL:
158
                            $courseMaterial[] = $descriptionInfo;
159
160
                            break;
161
162
                        case CCourseDescription::TYPE_RESOURCES:
163
                            $courseResources[] = $descriptionInfo;
164
165
                            break;
166
167
                        case CCourseDescription::TYPE_ASSESSMENT:
168
                            $courseAssessment[] = $descriptionInfo;
169
170
                            break;
171
172
                        case CCourseDescription::TYPE_CUSTOM:
173
                            $courseCustom[] = $descriptionInfo;
174
175
                            break;
176
                    }
177
                }
178
            }
179
180
            $courses[] = [
181
                'course' => $sessionCourse,
182
                'description' => $courseDescription,
183
                'image' => Container::getIllustrationRepository()->getIllustrationUrl($sessionCourse),
184
                'tags' => $courseTags,
185
                'objectives' => $courseObjectives,
186
                'topics' => $courseTopics,
187
                'methodology' => $courseMethodology,
188
                'material' => $courseMaterial,
189
                'resources' => $courseResources,
190
                'assessment' => $courseAssessment,
191
                'custom' => array_reverse($courseCustom),
192
                'coaches' => $coachesData,
193
                'extra_fields' => $courseValues->getAllValuesForAnItem(
194
                    $sessionCourse->getId(),
195
                    null,
196
                    true
197
                ),
198
            ];
199
        }
200
201
        $sessionDates = SessionManager::parseSessionDates($session, true);
202
203
        $hasRequirements = false;
204
205
        /*$sessionRequirements = $sequenceResourceRepo->getRequirements(
206
         * $session->getId(),
207
         * SequenceResource::SESSION_TYPE
208
         * );
209
         * foreach ($sessionRequirements as $sequence) {
210
         * if (!empty($sequence['requirements'])) {
211
         * $hasRequirements = true;
212
         * break;
213
         * }
214
         * }*/
215
        $plugin = BuyCoursesPlugin::create();
216
        $checker = $plugin->isEnabled();
217
        $sessionIsPremium = null;
218
        if ($checker) {
219
            $sessionIsPremium = $plugin->getItemByProduct(
220
                $sessionId,
221
                BuyCoursesPlugin::PRODUCT_TYPE_SESSION
222
            );
223
            if ([] !== $sessionIsPremium) {
224
                $requestSession->set('SessionIsPremium', true);
225
                $requestSession->set('sessionId', $sessionId);
226
            }
227
        }
228
229
        $redirectToSession = ('true' === Container::getSettingsManager()->getSetting('session.allow_redirect_to_session_after_inscription_about'));
230
        $redirectToSession = $redirectToSession ? '?s='.$sessionId : false;
231
232
        $coursesInThisSession = SessionManager::get_course_list_by_session_id($sessionId);
233
        $coursesCount = \count($coursesInThisSession);
234
        $redirectToSession = 1 === $coursesCount && $redirectToSession
235
            ? ($redirectToSession.'&cr='.array_values($coursesInThisSession)[0]['directory'])
236
            : $redirectToSession;
237
238
        $essence = new Essence();
239
240
        $params = [
241
            'session' => $session,
242
            'redirect_to_session' => $redirectToSession,
243
            'courses' => $courses,
244
            'essence' => $essence,
245
            'session_extra_fields' => $sessionValues->getAllValuesForAnItem($session->getId(), null, true),
246
            'has_requirements' => $hasRequirements,
247
            // 'sequences' => $sessionRequirements,
248
            'is_premium' => $sessionIsPremium,
249
            'show_tutor' => 'true' === api_get_setting('show_session_coach'),
250
            'page_url' => api_get_path(WEB_PATH).\sprintf('sessions/%s/about/', $session->getId()),
251
            'session_date' => $sessionDates,
252
            'is_subscribed' => SessionManager::isUserSubscribedAsStudent(
253
                $session->getId(),
254
                api_get_user_id()
255
            ),
256
            'user_session_time' => SessionManager::getDayLeftInSession(
257
                [
258
                    'id' => $session->getId(),
259
                    'duration' => $session->getDuration(),
260
                ],
261
                api_get_user_id()
262
            ),
263
            'base_url' => $request->getSchemeAndHttpHost(),
264
        ];
265
266
        return $this->render('@ChamiloCore/Session/about.html.twig', $params);
267
    }
268
269
    #[Route('/{id}/send-course-notification', name: 'chamilo_core_session_send_course_notification', methods: ['POST'])]
270
    public function sendCourseNotification(
271
        int $id,
272
        Request $request,
273
        UserRepository $userRepo,
274
        EntityManagerInterface $em,
275
        MessageHelper $messageHelper,
276
        AccessUrlHelper $accessUrlHelper
277
    ): Response {
278
        $session = $em->getRepository(Session::class)->find($id);
279
        $currentUser = $this->userHelper->getCurrent();
280
281
        if (!$session) {
282
            return $this->json(['error' => 'Session not found'], Response::HTTP_NOT_FOUND);
283
        }
284
285
        $studentId = $request->request->get('studentId');
286
        if (!$studentId) {
287
            return $this->json(['error' => 'Missing studentId'], Response::HTTP_BAD_REQUEST);
288
        }
289
290
        $user = $userRepo->find($studentId);
291
        if (!$user) {
292
            return $this->json(['error' => 'User not found'], Response::HTTP_NOT_FOUND);
293
        }
294
295
        $email = $user->getEmail();
296
        if (empty($email)) {
297
            return $this->json(['error' => 'User has no email address.'], Response::HTTP_BAD_REQUEST);
298
        }
299
300
        if (!$user->isActive()) {
301
            $user->setActive(User::ACTIVE);
302
            $em->persist($user);
303
        }
304
305
        $accessUrl = $accessUrlHelper->getCurrent();
306
307
        if ($accessUrl) {
308
            $hasAccess = $user->getPortals()->exists(
309
                fn ($k, $rel) => $rel->getUrl()?->getId() === $accessUrl->getId()
310
            );
311
312
            if (!$hasAccess) {
313
                $rel = new AccessUrlRelUser();
314
                $rel->setUser($user);
315
                $rel->setUrl($accessUrl);
316
317
                $em->persist($rel);
318
            }
319
        }
320
321
        $em->flush();
322
323
        $now = new \DateTime();
324
        $relSessions = $em->getRepository(SessionRelUser::class)->findBy([
325
            'user' => $user,
326
            'relationType' => Session::STUDENT,
327
        ]);
328
329
        $activeSessions = array_filter($relSessions, function (SessionRelUser $rel) use ($now) {
330
            $s = $rel->getSession();
331
            return $s->getAccessStartDate() <= $now && $s->getAccessEndDate() >= $now;
332
        });
333
334
        $sessionListHtml = '';
335
        foreach ($activeSessions as $rel) {
336
            $s = $rel->getSession();
337
            $sessionListHtml .= '<li>'.htmlspecialchars($s->getTitle()).'</li>';
338
        }
339
340
        $request = $this->requestStack->getCurrentRequest();
341
        $baseUrl = $request->getSchemeAndHttpHost().$request->getBasePath();
342
        $sessionUrl = $baseUrl.'/sessions';
343
344
        $subject = $this->translator->trans('You have been enrolled in a new course');
345
346
        $bodyTemplate = $this->translator->trans(
347
            'Hello %s,<br><br>'.
348
            'You have been enrolled in a new session: <strong>%s</strong>.<br>'.
349
            'You can access your courses from <a href="%s">here</a>.<br><br>'.
350
            'Your current active sessions are:<br><ul>%s</ul><br>'.
351
            'Best regards,<br>'.
352
            'Chamilo'
353
        );
354
355
        $body = \sprintf(
356
            $bodyTemplate,
357
            $user->getFullName(),
358
            $session->getTitle(),
359
            $sessionUrl,
360
            $sessionListHtml
361
        );
362
363
        $messageHelper->sendMessage(
364
            $user->getId(),
365
            $subject,
366
            $body,
367
            [],
368
            [],
369
            0,
370
            0,
371
            0,
372
            $currentUser->getId(),
373
            0,
374
            false,
375
            true
376
        );
377
378
        return $this->json(['success' => true]);
379
    }
380
381
    #[Route('/{sessionId}/next-session', name: 'chamilo_session_next_session')]
382
    public function getNextSession(
383
        int $sessionId,
384
        Request $request,
385
        SequenceResourceRepository $repo,
386
        Security $security
387
    ): JsonResponse {
388
        $requirementAndDependencies = $repo->getRequirementAndDependencies(
389
            $sessionId,
390
            SequenceResource::SESSION_TYPE
391
        );
392
393
        $requirements = [];
394
        $dependencies = [];
395
396
        if (!empty($requirementAndDependencies['requirements'])) {
397
            foreach ($requirementAndDependencies['requirements'] as $requirement) {
398
                $requirements[] = [
399
                    'id' => $requirement['id'],
400
                    'name' => $requirement['name'],
401
                    'admin_link' => $requirement['admin_link'],
402
                ];
403
            }
404
        }
405
406
        if (!empty($requirementAndDependencies['dependencies'])) {
407
            foreach ($requirementAndDependencies['dependencies'] as $dependency) {
408
                $dependencies[] = [
409
                    'id' => $dependency['id'],
410
                    'name' => $dependency['name'],
411
                    'admin_link' => $dependency['admin_link'],
412
                ];
413
            }
414
        }
415
416
        $sequenceResource = $repo->findRequirementForResource(
417
            $sessionId,
418
            SequenceResource::SESSION_TYPE
419
        );
420
421
        $graphImage = null;
422
        if ($sequenceResource && $sequenceResource->hasGraph()) {
423
            $graph = $sequenceResource->getSequence()->getUnSerializeGraph();
424
            if (null !== $graph) {
425
                $graph->setAttribute('graphviz.node.fontname', 'arial');
426
                $graphviz = new GraphViz();
427
                $graphImage = $graphviz->createImageSrc($graph);
428
            }
429
        }
430
431
        return new JsonResponse([
432
            'requirements' => $requirements,
433
            'dependencies' => $dependencies,
434
            'graph' => $graphImage,
435
        ]);
436
    }
437
}
438