CourseController::autoLaunch()   F
last analyzed

Complexity

Conditions 31
Paths 18192

Size

Total Lines 174
Code Lines 111

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 31
eloc 111
c 0
b 0
f 0
nc 18192
nop 0
dl 0
loc 174
rs 0

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\Entity\Course;
10
use Chamilo\CoreBundle\Entity\CourseRelUser;
11
use Chamilo\CoreBundle\Entity\ExtraField;
12
use Chamilo\CoreBundle\Entity\Session;
13
use Chamilo\CoreBundle\Entity\SessionRelUser;
14
use Chamilo\CoreBundle\Entity\Tag;
15
use Chamilo\CoreBundle\Entity\Tool;
16
use Chamilo\CoreBundle\Entity\User;
17
use Chamilo\CoreBundle\Framework\Container;
18
use Chamilo\CoreBundle\Repository\CourseCategoryRepository;
19
use Chamilo\CoreBundle\Repository\ExtraFieldValuesRepository;
20
use Chamilo\CoreBundle\Repository\LanguageRepository;
21
use Chamilo\CoreBundle\Repository\LegalRepository;
22
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
23
use Chamilo\CoreBundle\Repository\Node\IllustrationRepository;
24
use Chamilo\CoreBundle\Repository\TagRepository;
25
use Chamilo\CoreBundle\Security\Authorization\Voter\CourseVoter;
26
use Chamilo\CoreBundle\Service\CourseService;
27
use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper;
28
use Chamilo\CoreBundle\ServiceHelper\UserHelper;
29
use Chamilo\CoreBundle\Settings\SettingsManager;
30
use Chamilo\CoreBundle\Tool\ToolChain;
31
use Chamilo\CourseBundle\Controller\ToolBaseController;
32
use Chamilo\CourseBundle\Entity\CCourseDescription;
33
use Chamilo\CourseBundle\Entity\CTool;
34
use Chamilo\CourseBundle\Entity\CToolIntro;
35
use Chamilo\CourseBundle\Repository\CCourseDescriptionRepository;
36
use Chamilo\CourseBundle\Repository\CShortcutRepository;
37
use Chamilo\CourseBundle\Repository\CToolRepository;
38
use Chamilo\CourseBundle\Settings\SettingsCourseManager;
39
use Chamilo\CourseBundle\Settings\SettingsFormFactory;
40
use CourseManager;
41
use Database;
42
use Display;
43
use Doctrine\ORM\EntityManagerInterface;
44
use Event;
45
use Exception;
46
use Exercise;
47
use ExtraFieldValue;
48
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
49
use Symfony\Component\HttpFoundation\JsonResponse;
50
use Symfony\Component\HttpFoundation\RedirectResponse;
51
use Symfony\Component\HttpFoundation\Request;
52
use Symfony\Component\HttpFoundation\Response;
53
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
54
use Symfony\Component\Routing\Attribute\Route;
55
use Symfony\Component\Serializer\SerializerInterface;
56
use Symfony\Component\Validator\Exception\ValidatorException;
57
use Symfony\Contracts\Translation\TranslatorInterface;
58
use UserManager;
59
60
/**
61
 * @author Julio Montoya <[email protected]>
62
 */
63
#[Route('/course')]
64
class CourseController extends ToolBaseController
65
{
66
    public function __construct(
67
        private readonly EntityManagerInterface $em,
68
        private readonly SerializerInterface $serializer,
69
        private readonly UserHelper $userHelper,
70
    ) {}
71
72
    #[Route('/{cid}/checkLegal.json', name: 'chamilo_core_course_check_legal_json')]
73
    public function checkTermsAndConditionJson(
74
        Request $request,
75
        LegalRepository $legalTermsRepo,
76
        LanguageRepository $languageRepository,
77
        ExtraFieldValuesRepository $extraFieldValuesRepository,
78
        SettingsManager $settingsManager
79
    ): Response {
80
        $user = $this->userHelper->getCurrent();
81
        $course = $this->getCourse();
82
        $responseData = [
83
            'redirect' => false,
84
            'url' => '#',
85
        ];
86
87
        if ($user && $user->hasRole('ROLE_STUDENT')
88
            && 'true' === $settingsManager->getSetting('allow_terms_conditions')
89
            && 'course' === $settingsManager->getSetting('load_term_conditions_section')
90
        ) {
91
            $termAndConditionStatus = false;
92
            $extraValue = $extraFieldValuesRepository->findLegalAcceptByItemId($user->getId());
93
            if (!empty($extraValue['value'])) {
94
                $result = $extraValue['value'];
95
                $userConditions = explode(':', $result);
96
                $version = $userConditions[0];
97
                $langId = (int) $userConditions[1];
98
                $realVersion = $legalTermsRepo->getLastVersion($langId);
99
                $termAndConditionStatus = ($version >= $realVersion);
100
            }
101
102
            if (false === $termAndConditionStatus) {
103
                $request->getSession()->set('term_and_condition', ['user_id' => $user->getId()]);
104
            } else {
105
                $request->getSession()->remove('term_and_condition');
106
            }
107
108
            $termsAndCondition = $request->getSession()->get('term_and_condition');
109
            if (null !== $termsAndCondition) {
110
                $redirect = true;
111
                $allow = 'true' === Container::getSettingsManager()
112
                    ->getSetting('course.allow_public_course_with_no_terms_conditions')
113
                ;
114
115
                if (true === $allow
116
                    && null !== $course->getVisibility()
117
                    && Course::OPEN_WORLD === $course->getVisibility()
118
                ) {
119
                    $redirect = false;
120
                }
121
                if ($redirect && !$this->isGranted('ROLE_ADMIN')) {
122
                    $url = '/main/auth/inscription.php';
123
                    $responseData = [
124
                        'redirect' => true,
125
                        'url' => $url,
126
                    ];
127
                }
128
            }
129
        }
130
131
        return new JsonResponse($responseData);
132
    }
133
134
    #[Route('/{cid}/home.json', name: 'chamilo_core_course_home_json')]
135
    public function indexJson(
136
        Request $request,
137
        CShortcutRepository $shortcutRepository,
138
        EntityManagerInterface $em,
139
    ): Response {
140
        $requestData = json_decode($request->getContent(), true);
141
        // Sort behaviour
142
        if (!empty($requestData) && isset($requestData['toolItem'])) {
143
            $index = $requestData['index'];
144
            $toolItem = $requestData['toolItem'];
145
            $toolId = (int) $toolItem['iid'];
146
147
            /** @var CTool $cTool */
148
            $cTool = $em->find(CTool::class, $toolId);
149
150
            if ($cTool) {
151
                $cTool->setPosition($index + 1);
152
                $em->persist($cTool);
153
                $em->flush();
154
            }
155
        }
156
157
        $course = $this->getCourse();
158
        $sessionId = $this->getSessionId();
159
        $isInASession = $sessionId > 0;
160
161
        if (null === $course) {
162
            throw $this->createAccessDeniedException();
163
        }
164
165
        if (empty($sessionId)) {
166
            $this->denyAccessUnlessGranted(CourseVoter::VIEW, $course);
167
        }
168
169
        $sessionHandler = $request->getSession();
170
171
        $userId = 0;
172
173
        $user = $this->userHelper->getCurrent();
174
        if (null !== $user) {
175
            $userId = $user->getId();
176
        }
177
178
        $courseCode = $course->getCode();
179
        $courseId = $course->getId();
180
181
        if ($user && $user->hasRole('ROLE_INVITEE')) {
182
            $isSubscribed = CourseManager::is_user_subscribed_in_course(
183
                $userId,
184
                $courseCode,
185
                $isInASession,
186
                $sessionId
187
            );
188
189
            if (!$isSubscribed) {
190
                throw $this->createAccessDeniedException();
191
            }
192
        }
193
194
        $isSpecialCourse = CourseManager::isSpecialCourse($courseId);
195
196
        if ($user && $isSpecialCourse && (isset($_GET['autoreg']) && 1 === (int) $_GET['autoreg'])
197
            && CourseManager::subscribeUser($userId, $courseId, STUDENT)
198
        ) {
199
            $sessionHandler->set('is_allowed_in_course', true);
200
        }
201
202
        $logInfo = [
203
            'tool' => 'course-main',
204
        ];
205
        Event::registerLog($logInfo);
206
207
        // Deleting the objects
208
        $sessionHandler->remove('toolgroup');
209
        $sessionHandler->remove('_gid');
210
        $sessionHandler->remove('oLP');
211
        $sessionHandler->remove('lpobject');
212
213
        api_remove_in_gradebook();
214
        Exercise::cleanSessionVariables();
215
216
        $shortcuts = [];
217
        if (null !== $user) {
218
            $shortcutQuery = $shortcutRepository->getResources($course->getResourceNode());
219
            $shortcuts = $shortcutQuery->getQuery()->getResult();
220
        }
221
        $responseData = [
222
            'shortcuts' => $shortcuts,
223
            'diagram' => '',
224
        ];
225
226
        $json = $this->serializer->serialize(
227
            $responseData,
228
            'json',
229
            [
230
                'groups' => ['course:read', 'ctool:read', 'tool:read', 'cshortcut:read'],
231
            ]
232
        );
233
234
        return new Response(
235
            $json,
236
            Response::HTTP_OK,
237
            [
238
                'Content-type' => 'application/json',
239
            ]
240
        );
241
    }
242
243
    /**
244
     * Redirects the page to a tool, following the tools settings.
245
     */
246
    #[Route('/{cid}/tool/{toolName}', name: 'chamilo_core_course_redirect_tool')]
247
    public function redirectTool(
248
        Request $request,
249
        string $toolName,
250
        CToolRepository $repo,
251
        ToolChain $toolChain
252
    ): RedirectResponse {
253
        /** @var CTool|null $tool */
254
        $tool = $repo->findOneBy([
255
            'title' => $toolName,
256
        ]);
257
258
        if (null === $tool) {
259
            throw new NotFoundHttpException($this->trans('Tool not found'));
260
        }
261
262
        $tool = $toolChain->getToolFromName($tool->getTool()->getTitle());
263
        $link = $tool->getLink();
264
265
        if (null === $this->getCourse()) {
266
            throw new NotFoundHttpException($this->trans('Course not found'));
267
        }
268
        $optionalParams = '';
269
270
        $optionalParams = $request->query->get('cert') ? '&cert='.$request->query->get('cert') : '';
271
272
        if (strpos($link, 'nodeId')) {
273
            $nodeId = (string) $this->getCourse()->getResourceNode()->getId();
274
            $link = str_replace(':nodeId', $nodeId, $link);
275
        }
276
277
        $url = $link.'?'.$this->getCourseUrlQuery().$optionalParams;
278
279
        return $this->redirect($url);
280
    }
281
282
    /*public function redirectToShortCut(string $toolName, CToolRepository $repo, ToolChain $toolChain): RedirectResponse
283
    {
284
        $tool = $repo->findOneBy([
285
            'name' => $toolName,
286
        ]);
287
288
        if (null === $tool) {
289
            throw new NotFoundHttpException($this->trans('Tool not found'));
290
        }
291
292
        $tool = $toolChain->getToolFromName($tool->getTool()->getTitle());
293
        $link = $tool->getLink();
294
295
        if (strpos($link, 'nodeId')) {
296
            $nodeId = (string) $this->getCourse()->getResourceNode()->getId();
297
            $link = str_replace(':nodeId', $nodeId, $link);
298
        }
299
300
        $url = $link.'?'.$this->getCourseUrlQuery();
301
302
        return $this->redirect($url);
303
    }*/
304
305
    /**
306
     * Edit configuration with given namespace.
307
     */
308
    #[Route('/{course}/settings/{namespace}', name: 'chamilo_core_course_settings')]
309
    public function updateSettings(
310
        Request $request,
311
        #[MapEntity(expr: 'repository.find(cid)')]
312
        Course $course,
313
        string $namespace,
314
        SettingsCourseManager $manager,
315
        SettingsFormFactory $formFactory
316
    ): Response {
317
        $this->denyAccessUnlessGranted(CourseVoter::VIEW, $course);
318
319
        $schemaAlias = $manager->convertNameSpaceToService($namespace);
320
        $settings = $manager->load($namespace);
321
322
        $form = $formFactory->create($schemaAlias);
323
324
        $form->setData($settings);
325
        $form->handleRequest($request);
326
327
        if ($form->isSubmitted() && $form->isValid()) {
328
            $messageType = 'success';
329
330
            try {
331
                $manager->setCourse($course);
332
                $manager->save($form->getData());
333
                $message = $this->trans('Update');
334
            } catch (ValidatorException $validatorException) {
335
                $message = $this->trans($validatorException->getMessage());
336
                $messageType = 'error';
337
            }
338
            $this->addFlash($messageType, $message);
339
340
            if ($request->headers->has('referer')) {
341
                return $this->redirect($request->headers->get('referer'));
342
            }
343
        }
344
345
        $schemas = $manager->getSchemas();
346
347
        return $this->render(
348
            '@ChamiloCore/Course/settings.html.twig',
349
            [
350
                'course' => $course,
351
                'schemas' => $schemas,
352
                'settings' => $settings,
353
                'form' => $form,
354
            ]
355
        );
356
    }
357
358
    #[Route('/{id}/about', name: 'chamilo_core_course_about')]
359
    public function about(
360
        Course $course,
361
        IllustrationRepository $illustrationRepository,
362
        CCourseDescriptionRepository $courseDescriptionRepository,
363
        EntityManagerInterface $em
364
    ): Response {
365
        $courseId = $course->getId();
366
367
        $user = $this->userHelper->getCurrent();
368
369
        $fieldsRepo = $em->getRepository(ExtraField::class);
370
371
        /** @var TagRepository $tagRepo */
372
        $tagRepo = $em->getRepository(Tag::class);
373
374
        $courseDescriptions = $courseDescriptionRepository->getResourcesByCourse($course)->getQuery()->getResult();
375
376
        $courseValues = new ExtraFieldValue('course');
377
378
        $urlCourse = api_get_path(WEB_PATH).sprintf('course/%s/about', $courseId);
379
        $courseTeachers = $course->getTeachersSubscriptions();
380
        $teachersData = [];
381
382
        foreach ($courseTeachers as $teacherSubscription) {
383
            $teacher = $teacherSubscription->getUser();
384
            $userData = [
385
                'complete_name' => UserManager::formatUserFullName($teacher),
386
                'image' => $illustrationRepository->getIllustrationUrl($teacher),
387
                'diploma' => $teacher->getDiplomas(),
388
                'openarea' => $teacher->getOpenarea(),
389
            ];
390
391
            $teachersData[] = $userData;
392
        }
393
394
        /** @var ExtraField $tagField */
395
        $tagField = $fieldsRepo->findOneBy([
396
            'itemType' => ExtraField::COURSE_FIELD_TYPE,
397
            'variable' => 'tags',
398
        ]);
399
400
        $courseTags = [];
401
        if (null !== $tagField) {
402
            $courseTags = $tagRepo->getTagsByItem($tagField, $courseId);
403
        }
404
405
        $courseDescription = $courseObjectives = $courseTopics = $courseMethodology = '';
406
        $courseMaterial = $courseResources = $courseAssessment = '';
407
        $courseCustom = [];
408
        foreach ($courseDescriptions as $descriptionTool) {
409
            switch ($descriptionTool->getDescriptionType()) {
410
                case CCourseDescription::TYPE_DESCRIPTION:
411
                    $courseDescription = $descriptionTool->getContent();
412
413
                    break;
414
415
                case CCourseDescription::TYPE_OBJECTIVES:
416
                    $courseObjectives = $descriptionTool;
417
418
                    break;
419
420
                case CCourseDescription::TYPE_TOPICS:
421
                    $courseTopics = $descriptionTool;
422
423
                    break;
424
425
                case CCourseDescription::TYPE_METHODOLOGY:
426
                    $courseMethodology = $descriptionTool;
427
428
                    break;
429
430
                case CCourseDescription::TYPE_COURSE_MATERIAL:
431
                    $courseMaterial = $descriptionTool;
432
433
                    break;
434
435
                case CCourseDescription::TYPE_RESOURCES:
436
                    $courseResources = $descriptionTool;
437
438
                    break;
439
440
                case CCourseDescription::TYPE_ASSESSMENT:
441
                    $courseAssessment = $descriptionTool;
442
443
                    break;
444
445
                case CCourseDescription::TYPE_CUSTOM:
446
                    $courseCustom[] = $descriptionTool;
447
448
                    break;
449
            }
450
        }
451
452
        $topics = [
453
            'objectives' => $courseObjectives,
454
            'topics' => $courseTopics,
455
            'methodology' => $courseMethodology,
456
            'material' => $courseMaterial,
457
            'resources' => $courseResources,
458
            'assessment' => $courseAssessment,
459
            'custom' => array_reverse($courseCustom),
460
        ];
461
462
        $subscriptionUser = false;
463
464
        if ($user) {
465
            $subscriptionUser = CourseManager::is_user_subscribed_in_course($user->getId(), $course->getCode());
466
        }
467
468
        /*$allowSubscribe = false;
469
        if ($course->getSubscribe() || api_is_platform_admin()) {
470
            $allowSubscribe = true;
471
        }
472
        $plugin = \BuyCoursesPlugin::create();
473
        $checker = $plugin->isEnabled();
474
        $courseIsPremium = null;
475
        if ($checker) {
476
            $courseIsPremium = $plugin->getItemByProduct(
477
                $courseId,
478
                \BuyCoursesPlugin::PRODUCT_TYPE_COURSE
479
            );
480
        }*/
481
482
        $image = Container::getIllustrationRepository()->getIllustrationUrl($course, 'course_picture_medium');
483
484
        $params = [
485
            'course' => $course,
486
            'description' => $courseDescription,
487
            'image' => $image,
488
            'syllabus' => $topics,
489
            'tags' => $courseTags,
490
            'teachers' => $teachersData,
491
            'extra_fields' => $courseValues->getAllValuesForAnItem(
492
                $course->getId(),
493
                null,
494
                true
495
            ),
496
            'subscription' => $subscriptionUser,
497
            'url' => '',
498
            'is_premium' => '',
499
            'token' => '',
500
        ];
501
502
        $metaInfo = '<meta property="og:url" content="'.$urlCourse.'" />';
503
        $metaInfo .= '<meta property="og:type" content="website" />';
504
        $metaInfo .= '<meta property="og:title" content="'.$course->getTitle().'" />';
505
        $metaInfo .= '<meta property="og:description" content="'.strip_tags($courseDescription).'" />';
506
        $metaInfo .= '<meta property="og:image" content="'.$image.'" />';
507
508
        $htmlHeadXtra[] = $metaInfo;
509
        $htmlHeadXtra[] = api_get_asset('readmore-js/readmore.js');
510
511
        return $this->render('@ChamiloCore/Course/about.html.twig', $params);
512
    }
513
514
    #[Route('/{id}/welcome', name: 'chamilo_core_course_welcome')]
515
    public function welcome(Course $course): Response
516
    {
517
        return $this->render('@ChamiloCore/Course/welcome.html.twig', [
518
            'course' => $course,
519
        ]);
520
    }
521
522
    private function findIntroOfCourse(Course $course): ?CTool
523
    {
524
        $qb = $this->em->createQueryBuilder();
525
526
        $query = $qb->select('ct')
527
            ->from(CTool::class, 'ct')
528
            ->where('ct.course = :c_id')
529
            ->andWhere('ct.title = :title')
530
            ->andWhere(
531
                $qb->expr()->orX(
532
                    $qb->expr()->eq('ct.session', ':session_id'),
533
                    $qb->expr()->isNull('ct.session')
534
                )
535
            )
536
            ->setParameters([
537
                'c_id' => $course->getId(),
538
                'title' => 'course_homepage',
539
                'session_id' => 0,
540
            ])
541
            ->getQuery()
542
        ;
543
544
        return $query->getOneOrNullResult();
545
    }
546
547
    #[Route('/{id}/getToolIntro', name: 'chamilo_core_course_gettoolintro')]
548
    public function getToolIntro(Request $request, Course $course, EntityManagerInterface $em): Response
549
    {
550
        $sessionId = (int) $request->get('sid');
551
552
        // $session = $this->getSession();
553
        $responseData = [];
554
        $ctoolRepo = $em->getRepository(CTool::class);
555
        $sessionRepo = $em->getRepository(Session::class);
556
        $createInSession = false;
557
558
        $session = null;
559
560
        if (!empty($sessionId)) {
561
            $session = $sessionRepo->find($sessionId);
562
        }
563
564
        $ctool = $this->findIntroOfCourse($course);
565
566
        if ($session) {
567
            $ctoolSession = $ctoolRepo->findOneBy(['title' => 'course_homepage', 'course' => $course, 'session' => $session]);
568
569
            if (!$ctoolSession) {
570
                $createInSession = true;
571
            } else {
572
                $ctool = $ctoolSession;
573
            }
574
        }
575
576
        if ($ctool) {
577
            $ctoolintroRepo = $em->getRepository(CToolIntro::class);
578
579
            /** @var CToolIntro $ctoolintro */
580
            $ctoolintro = $ctoolintroRepo->findOneBy(['courseTool' => $ctool]);
581
            if ($ctoolintro) {
582
                $responseData = [
583
                    'iid' => $ctoolintro->getIid(),
584
                    'introText' => $ctoolintro->getIntroText(),
585
                    'createInSession' => $createInSession,
586
                    'cToolId' => $ctool->getIid(),
587
                ];
588
            }
589
            $responseData['c_tool'] = [
590
                'iid' => $ctool->getIid(),
591
                'title' => $ctool->getTitle(),
592
            ];
593
        }
594
595
        return new JsonResponse($responseData);
596
    }
597
598
    #[Route('/{id}/addToolIntro', name: 'chamilo_core_course_addtoolintro')]
599
    public function addToolIntro(Request $request, Course $course, EntityManagerInterface $em): Response
600
    {
601
        $data = $request->getContent();
602
        $data = json_decode($data);
603
        $ctoolintroId = $data->iid;
604
        $sessionId = $data->sid ?? 0;
605
606
        $sessionRepo = $em->getRepository(Session::class);
607
        $session = null;
608
        if (!empty($sessionId)) {
609
            $session = $sessionRepo->find($sessionId);
610
        }
611
612
        $ctool = $em->getRepository(CTool::class);
613
        $check = $ctool->findOneBy(['title' => 'course_homepage', 'course' => $course, 'session' => $session]);
614
        if (!$check) {
615
            $toolRepo = $em->getRepository(Tool::class);
616
            $toolEntity = $toolRepo->findOneBy(['title' => 'course_homepage']);
617
            $courseTool = (new CTool())
618
                ->setTool($toolEntity)
619
                ->setTitle('course_homepage')
620
                ->setCourse($course)
621
                ->setPosition(1)
622
                ->setVisibility(true)
623
                ->setParent($course)
624
                ->setCreator($course->getCreator())
625
                ->setSession($session)
626
                ->addCourseLink($course)
627
            ;
628
            $em->persist($courseTool);
629
            $em->flush();
630
            if ($courseTool && !empty($ctoolintroId)) {
631
                $ctoolintroRepo = Container::getToolIntroRepository();
632
633
                /** @var CToolIntro $ctoolintro */
634
                $ctoolintro = $ctoolintroRepo->find($ctoolintroId);
635
                $ctoolintro->setCourseTool($courseTool);
636
                $ctoolintroRepo->update($ctoolintro);
637
            }
638
        }
639
        $responseData = [];
640
        $json = $this->serializer->serialize(
641
            $responseData,
642
            'json',
643
            [
644
                'groups' => ['course:read', 'ctool:read', 'tool:read', 'cshortcut:read'],
645
            ]
646
        );
647
648
        return new JsonResponse($responseData);
649
    }
650
651
    #[Route('/check-enrollments', name: 'chamilo_core_check_enrollments', methods: ['GET'])]
652
    public function checkEnrollments(EntityManagerInterface $em, SettingsManager $settingsManager): JsonResponse
653
    {
654
        $user = $this->userHelper->getCurrent();
655
656
        if (!$user) {
657
            return new JsonResponse(['error' => 'User not found'], Response::HTTP_UNAUTHORIZED);
658
        }
659
660
        $isEnrolledInCourses = $this->isUserEnrolledInAnyCourse($user, $em);
661
        $isEnrolledInSessions = $this->isUserEnrolledInAnySession($user, $em);
662
663
        if (!$isEnrolledInCourses && !$isEnrolledInSessions) {
664
            $defaultMenuEntry = $settingsManager->getSetting('platform.default_menu_entry_for_course_or_session');
665
            $isEnrolledInCourses = 'my_courses' === $defaultMenuEntry;
666
            $isEnrolledInSessions = 'my_sessions' === $defaultMenuEntry;
667
        }
668
669
        return new JsonResponse([
670
            'isEnrolledInCourses' => $isEnrolledInCourses,
671
            'isEnrolledInSessions' => $isEnrolledInSessions,
672
        ]);
673
    }
674
675
    #[Route('/categories', name: 'chamilo_core_course_form_lists')]
676
    public function getCategories(
677
        SettingsManager $settingsManager,
678
        AccessUrlHelper $accessUrlHelper,
679
        CourseCategoryRepository $courseCategoriesRepo
680
    ): JsonResponse {
681
        $allowBaseCourseCategory = 'true' === $settingsManager->getSetting('course.allow_base_course_category');
682
        $accessUrlId = $accessUrlHelper->getCurrent()->getId();
683
684
        $categories = $courseCategoriesRepo->findAllInAccessUrl(
685
            $accessUrlId,
686
            $allowBaseCourseCategory
687
        );
688
689
        $data = [];
690
        $categoryToAvoid = '';
691
        if (!$this->isGranted('ROLE_ADMIN')) {
692
            $categoryToAvoid = $settingsManager->getSetting('course.course_category_code_to_use_as_model');
693
        }
694
695
        foreach ($categories as $category) {
696
            $categoryCode = $category->getCode();
697
            if (!empty($categoryToAvoid) && $categoryToAvoid == $categoryCode) {
698
                continue;
699
            }
700
            $data[] = ['id' => $category->getId(), 'name' => $category->__toString()];
701
        }
702
703
        return new JsonResponse($data);
704
    }
705
706
    #[Route('/search_templates', name: 'chamilo_core_course_search_templates')]
707
    public function searchCourseTemplates(
708
        Request $request,
709
        AccessUrlHelper $accessUrlHelper,
710
        CourseRepository $courseRepository
711
    ): JsonResponse {
712
        $searchTerm = $request->query->get('search', '');
713
        $accessUrl = $accessUrlHelper->getCurrent();
714
715
        $user = $this->userHelper->getCurrent();
716
717
        $courseList = $courseRepository->getCoursesInfoByUser($user, $accessUrl, 1, $searchTerm);
718
        $results = ['items' => []];
719
        foreach ($courseList as $course) {
720
            $title = $course['title'];
721
            $results['items'][] = [
722
                'id' => $course['id'],
723
                'name' => $title.' ('.$course['code'].') ',
724
            ];
725
        }
726
727
        return new JsonResponse($results);
728
    }
729
730
    #[Route('/create', name: 'chamilo_core_course_create')]
731
    public function createCourse(
732
        Request $request,
733
        TranslatorInterface $translator,
734
        CourseService $courseService
735
    ): JsonResponse {
736
        $courseData = json_decode($request->getContent(), true);
737
738
        $title = $courseData['name'] ?? null;
739
        $wantedCode = $courseData['code'] ?? null;
740
        $courseLanguage = $courseData['language']['id'] ?? null;
741
        $categoryCode = $courseData['category'] ?? null;
742
        $exemplaryContent = $courseData['fillDemoContent'] ?? false;
743
        $template = $courseData['template'] ?? '';
744
745
        $params = [
746
            'title' => $title,
747
            'wanted_code' => $wantedCode,
748
            'course_language' => $courseLanguage,
749
            'exemplary_content' => $exemplaryContent,
750
            'course_template' => $template,
751
        ];
752
753
        if ($categoryCode) {
754
            $params['course_categories'] = $categoryCode;
755
        }
756
757
        try {
758
            $course = $courseService->createCourse($params);
759
            if ($course) {
760
                return new JsonResponse([
761
                    'success' => true,
762
                    'message' => $translator->trans('Course created successfully.'),
763
                    'courseId' => $course->getId(),
764
                ]);
765
            }
766
        } catch (Exception $e) {
767
            return new JsonResponse([
768
                'success' => false,
769
                'message' => $translator->trans($e->getMessage()),
770
            ], Response::HTTP_BAD_REQUEST);
771
        }
772
773
        return new JsonResponse(['success' => false, 'message' => $translator->trans('An error occurred while creating the course.')]);
774
    }
775
776
    private function autoLaunch(): void
777
    {
778
        $autoLaunchWarning = '';
779
        $showAutoLaunchLpWarning = false;
780
        $course_id = api_get_course_int_id();
781
        $lpAutoLaunch = api_get_course_setting('enable_lp_auto_launch');
782
        $session_id = api_get_session_id();
783
        $allowAutoLaunchForCourseAdmins =
784
            api_is_platform_admin()
785
            || api_is_allowed_to_edit(true, true)
786
            || api_is_coach();
787
788
        if (!empty($lpAutoLaunch)) {
789
            if (2 === $lpAutoLaunch) {
790
                // LP list
791
                if ($allowAutoLaunchForCourseAdmins) {
792
                    $showAutoLaunchLpWarning = true;
793
                } else {
794
                    $session_key = 'lp_autolaunch_'.$session_id.'_'.$course_id.'_'.api_get_user_id();
795
                    if (!isset($_SESSION[$session_key])) {
796
                        // Redirecting to the LP
797
                        $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.api_get_cidreq();
798
                        $_SESSION[$session_key] = true;
799
                        header(sprintf('Location: %s', $url));
800
801
                        exit;
802
                    }
803
                }
804
            } else {
805
                $lp_table = Database::get_course_table(TABLE_LP_MAIN);
806
                $condition = '';
807
                if (!empty($session_id)) {
808
                    $condition = api_get_session_condition($session_id);
809
                    $sql = "SELECT id FROM {$lp_table}
810
                            WHERE c_id = {$course_id} AND autolaunch = 1 {$condition}
811
                            LIMIT 1";
812
                    $result = Database::query($sql);
813
                    // If we found nothing in the session we just called the session_id =  0 autolaunch
814
                    if (0 === Database::num_rows($result)) {
815
                        $condition = '';
816
                    }
817
                }
818
819
                $sql = "SELECT iid FROM {$lp_table}
820
                        WHERE c_id = {$course_id} AND autolaunch = 1 {$condition}
821
                        LIMIT 1";
822
                $result = Database::query($sql);
823
                if (Database::num_rows($result) > 0) {
824
                    $lp_data = Database::fetch_array($result);
825
                    if (!empty($lp_data['iid'])) {
826
                        if ($allowAutoLaunchForCourseAdmins) {
827
                            $showAutoLaunchLpWarning = true;
828
                        } else {
829
                            $session_key = 'lp_autolaunch_'.$session_id.'_'.api_get_course_int_id().'_'.api_get_user_id();
830
                            if (!isset($_SESSION[$session_key])) {
831
                                // Redirecting to the LP
832
                                $url = api_get_path(WEB_CODE_PATH).
833
                                    'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.$lp_data['iid'];
834
835
                                $_SESSION[$session_key] = true;
836
                                header(sprintf('Location: %s', $url));
837
838
                                exit;
839
                            }
840
                        }
841
                    }
842
                }
843
            }
844
        }
845
846
        if ($showAutoLaunchLpWarning) {
847
            $autoLaunchWarning = get_lang(
848
                'The learning path auto-launch setting is ON. When learners enter this course, they will be automatically redirected to the learning path marked as auto-launch.'
849
            );
850
        }
851
852
        $forumAutoLaunch = (int) api_get_course_setting('enable_forum_auto_launch');
853
        if (1 === $forumAutoLaunch) {
854
            if ($allowAutoLaunchForCourseAdmins) {
855
                if (empty($autoLaunchWarning)) {
856
                    $autoLaunchWarning = get_lang(
857
                        "The forum's auto-launch setting is on. Students will be redirected to the forum tool when entering this course."
858
                    );
859
                }
860
            } else {
861
                $url = api_get_path(WEB_CODE_PATH).'forum/index.php?'.api_get_cidreq();
862
                header(sprintf('Location: %s', $url));
863
864
                exit;
865
            }
866
        }
867
868
        if ('true' === api_get_setting('exercise.allow_exercise_auto_launch')) {
869
            $exerciseAutoLaunch = (int) api_get_course_setting('enable_exercise_auto_launch');
870
            if (2 === $exerciseAutoLaunch) {
871
                if ($allowAutoLaunchForCourseAdmins) {
872
                    if (empty($autoLaunchWarning)) {
873
                        $autoLaunchWarning = get_lang(
874
                            'TheExerciseAutoLaunchSettingIsONStudentsWillBeRedirectToTheExerciseList'
875
                        );
876
                    }
877
                } else {
878
                    // Redirecting to the document
879
                    $url = api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq();
880
                    header(sprintf('Location: %s', $url));
881
882
                    exit;
883
                }
884
            } elseif (1 === $exerciseAutoLaunch) {
885
                if ($allowAutoLaunchForCourseAdmins) {
886
                    if (empty($autoLaunchWarning)) {
887
                        $autoLaunchWarning = get_lang(
888
                            'TheExerciseAutoLaunchSettingIsONStudentsWillBeRedirectToAnSpecificExercise'
889
                        );
890
                    }
891
                } else {
892
                    // Redirecting to an exercise
893
                    $table = Database::get_course_table(TABLE_QUIZ_TEST);
894
                    $condition = '';
895
                    if (!empty($session_id)) {
896
                        $condition = api_get_session_condition($session_id);
897
                        $sql = "SELECT iid FROM {$table}
898
                                WHERE c_id = {$course_id} AND autolaunch = 1 {$condition}
899
                                LIMIT 1";
900
                        $result = Database::query($sql);
901
                        // If we found nothing in the session we just called the session_id = 0 autolaunch
902
                        if (0 === Database::num_rows($result)) {
903
                            $condition = '';
904
                        }
905
                    }
906
907
                    $sql = "SELECT iid FROM {$table}
908
                            WHERE c_id = {$course_id} AND autolaunch = 1 {$condition}
909
                            LIMIT 1";
910
                    $result = Database::query($sql);
911
                    if (Database::num_rows($result) > 0) {
912
                        $row = Database::fetch_array($result);
913
                        $exerciseId = $row['iid'];
914
                        $url = api_get_path(WEB_CODE_PATH).
915
                            'exercise/overview.php?exerciseId='.$exerciseId.'&'.api_get_cidreq();
916
                        header(sprintf('Location: %s', $url));
917
918
                        exit;
919
                    }
920
                }
921
            }
922
        }
923
924
        $documentAutoLaunch = (int) api_get_course_setting('enable_document_auto_launch');
925
        if (1 === $documentAutoLaunch) {
926
            if ($allowAutoLaunchForCourseAdmins) {
927
                if (empty($autoLaunchWarning)) {
928
                    $autoLaunchWarning = get_lang(
929
                        'The document auto-launch feature configuration is enabled. Learners will be automatically redirected to document tool.'
930
                    );
931
                }
932
            } else {
933
                // Redirecting to the document
934
                $url = api_get_path(WEB_CODE_PATH).'document/document.php?'.api_get_cidreq();
935
                header("Location: $url");
936
937
                exit;
938
            }
939
        }
940
941
        /*  SWITCH TO A DIFFERENT HOMEPAGE VIEW
942
         the setting homepage_view is adjustable through
943
         the platform administration section */
944
        if (!empty($autoLaunchWarning)) {
945
            $this->addFlash(
946
                'warning',
947
                Display::return_message(
948
                    $autoLaunchWarning,
949
                    'warning'
950
                )
951
            );
952
        }
953
    }
954
955
    // Implement the real logic to check course enrollment
956
    private function isUserEnrolledInAnyCourse(User $user, EntityManagerInterface $em): bool
957
    {
958
        $enrollmentCount = $em
959
            ->getRepository(CourseRelUser::class)
960
            ->count(['user' => $user])
961
        ;
962
963
        return $enrollmentCount > 0;
964
    }
965
966
    // Implement the real logic to check session enrollment
967
    private function isUserEnrolledInAnySession(User $user, EntityManagerInterface $em): bool
968
    {
969
        $enrollmentCount = $em->getRepository(SessionRelUser::class)
970
            ->count(['user' => $user])
971
        ;
972
973
        return $enrollmentCount > 0;
974
    }
975
}
976