Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

Rest::putCourseWorkVisibility()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 15
rs 9.9332
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Course;
6
use Chamilo\CoreBundle\Entity\ExtraFieldValues;
7
use Chamilo\CoreBundle\Entity\Session;
8
use Chamilo\CourseBundle\Entity\CLpCategory;
9
use Chamilo\CourseBundle\Entity\CNotebook;
10
use Chamilo\CourseBundle\Entity\Repository\CNotebookRepository;
11
use Chamilo\UserBundle\Entity\User;
12
13
/**
14
 * Class RestApi.
15
 */
16
class Rest extends WebService
17
{
18
    const SERVICE_NAME = 'MsgREST';
19
    const EXTRA_FIELD_GCM_REGISTRATION = 'gcm_registration_id';
20
21
    const GET_AUTH = 'authenticate';
22
    const SAVE_GCM_ID = 'gcm_id';
23
    const LOGOUT = 'logout';
24
25
    const GET_USER_MESSAGES = 'user_messages';
26
    const GET_USER_MESSAGES_RECEIVED = 'user_messages_received';
27
    const DELETE_USER_MESSAGE = 'delete_user_message';
28
    const GET_USER_MESSAGES_SENT = 'user_messages_sent';
29
    const GET_COUNT_NEW_MESSAGES = 'get_count_new_messages';
30
    const SET_MESSAGE_READ = 'set_message_read';
31
    const POST_USER_MESSAGE_READ = 'user_message_read';
32
    const POST_USER_MESSAGE_UNREAD = 'user_message_unread';
33
    const SAVE_USER_MESSAGE = 'save_user_message';
34
    const GET_MESSAGE_USERS = 'message_users';
35
36
    const GET_USER_COURSES = 'user_courses';
37
    const GET_USER_SESSIONS = 'user_sessions';
38
39
    const GET_PROFILE = 'user_profile';
40
41
    const GET_COURSE_INFO = 'course_info';
42
    const GET_COURSE_DESCRIPTIONS = 'course_descriptions';
43
    const GET_COURSE_DOCUMENTS = 'course_documents';
44
    const GET_COURSE_ANNOUNCEMENTS = 'course_announcements';
45
    const GET_COURSE_ANNOUNCEMENT = 'course_announcement';
46
    const GET_COURSE_AGENDA = 'course_agenda';
47
    const GET_COURSE_NOTEBOOKS = 'course_notebooks';
48
    const GET_COURSE_FORUM_CATEGORIES = 'course_forumcategories';
49
    const GET_COURSE_FORUM = 'course_forum';
50
    const GET_COURSE_FORUM_THREAD = 'course_forumthread';
51
    const GET_COURSE_LEARNPATHS = 'course_learnpaths';
52
    const GET_COURSE_LEARNPATH = 'course_learnpath';
53
    const GET_COURSE_LP_PROGRESS = 'course_lp_progress';
54
    const GET_COURSE_LINKS = 'course_links';
55
    const GET_COURSE_WORKS= 'course_works';
56
57
    const SAVE_COURSE_NOTEBOOK = 'save_course_notebook';
58
59
    const SAVE_FORUM_POST = 'save_forum_post';
60
    const SAVE_FORUM_THREAD = 'save_forum_thread';
61
    const SET_THREAD_NOTIFY = 'set_thread_notify';
62
63
    const PUT_WORK_STUDENT_ITEM_VISIBILITY = 'put_course_work_visibility';
64
65
    const CREATE_CAMPUS = 'add_campus';
66
    const EDIT_CAMPUS = 'edit_campus';
67
    const DELETE_CAMPUS = 'delete_campus';
68
69
    const GET_USERS = 'get_users';
70
    const USERNAME_EXIST = 'username_exist';
71
    const SAVE_USER = 'save_user';
72
    const SAVE_USER_JSON = 'save_user_json';
73
    const UPDATE_USER_FROM_USERNAME = 'update_user_from_username';
74
    const DELETE_USER = 'delete_user';
75
76
    const GET_COURSES = 'get_courses';
77
    const GET_COURSES_FROM_EXTRA_FIELD = 'get_courses_from_extra_field';
78
    const SAVE_COURSE = 'save_course';
79
    const DELETE_COURSE = 'delete_course';
80
81
    const GET_SESSION_FROM_EXTRA_FIELD = 'get_session_from_extra_field';
82
    const SAVE_SESSION = 'save_session';
83
    const CREATE_SESSION_FROM_MODEL = 'create_session_from_model';
84
    const UPDATE_SESSION = 'update_session';
85
86
    const SUBSCRIBE_USER_TO_COURSE = 'subscribe_user_to_course';
87
    const SUBSCRIBE_USER_TO_COURSE_PASSWORD = 'subscribe_user_to_course_password';
88
    const UNSUBSCRIBE_USER_FROM_COURSE = 'unsubscribe_user_from_course';
89
    const GET_USERS_SUBSCRIBED_TO_COURSE = 'get_users_subscribed_to_course';
90
91
    const ADD_COURSES_SESSION = 'add_courses_session';
92
    const ADD_USERS_SESSION = 'add_users_session';
93
    const SUBSCRIBE_USER_TO_SESSION_FROM_USERNAME = 'subscribe_user_to_session_from_username';
94
95
    const GET_COURSE_QUIZ_MDL_COMPAT = 'get_course_quiz_mdl_compat';
96
97
    const UPDATE_USER_PAUSE_TRAINING = 'update_user_pause_training';
98
99
    const CHECK_CONDITIONAL_LOGIN = 'check_conditional_login';
100
    const GET_LEGAL_CONDITIONS = 'get_legal_conditions';
101
    const UPDATE_CONDITION_ACCEPTED = 'update_condition_accepted';
102
103
    /**
104
     * @var Session
105
     */
106
    private $session;
107
108
    /**
109
     * @var Course
110
     */
111
    private $course;
112
113
    /**
114
     * Rest constructor.
115
     *
116
     * @param string $username
117
     * @param string $apiKey
118
     */
119
    public function __construct($username, $apiKey)
120
    {
121
        parent::__construct($username, $apiKey);
122
    }
123
124
    /**
125
     * @param string $username
126
     * @param string $apiKeyToValidate
127
     *
128
     * @throws Exception
129
     *
130
     * @return Rest
131
     */
132
    public static function validate($username, $apiKeyToValidate)
133
    {
134
        $apiKey = self::findUserApiKey($username, self::SERVICE_NAME);
135
136
        if ($apiKey != $apiKeyToValidate) {
137
            throw new Exception(get_lang('InvalidApiKey'));
138
        }
139
140
        return new self($username, $apiKey);
141
    }
142
143
    /**
144
     * Create the gcm_registration_id extra field for users.
145
     */
146
    public static function init()
147
    {
148
        $extraField = new ExtraField('user');
149
        $fieldInfo = $extraField->get_handler_field_info_by_field_variable(self::EXTRA_FIELD_GCM_REGISTRATION);
150
151
        if (empty($fieldInfo)) {
152
            $extraField->save(
153
                [
154
                    'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
155
                    'field_type' => ExtraField::FIELD_TYPE_TEXT,
156
                    'display_text' => self::EXTRA_FIELD_GCM_REGISTRATION,
157
                ]
158
            );
159
        }
160
    }
161
162
    /**
163
     * @param string $encoded
164
     *
165
     * @return array
166
     */
167
    public static function decodeParams($encoded)
168
    {
169
        return json_decode($encoded);
170
    }
171
172
    /**
173
     * Set the current course.
174
     *
175
     * @param int $id
176
     *
177
     * @throws Exception
178
     */
179
    public function setCourse($id)
180
    {
181
        if (!$id) {
182
            $this->course = null;
183
184
            ChamiloSession::erase('_real_cid');
185
            ChamiloSession::erase('_cid');
186
            ChamiloSession::erase('_course');
187
188
            return;
189
        }
190
191
        $em = Database::getManager();
192
        /** @var Course $course */
193
        $course = $em->find('ChamiloCoreBundle:Course', $id);
194
195
        if (!$course) {
0 ignored issues
show
introduced by
$course is of type Chamilo\CoreBundle\Entity\Course, thus it always evaluated to true.
Loading history...
196
            throw new Exception(get_lang('NoCourse'));
197
        }
198
199
        $this->course = $course;
200
201
        ChamiloSession::write('_real_cid', $course->getId());
202
        ChamiloSession::write('_cid', $course->getCode());
203
        ChamiloSession::write('_course', api_get_course_info($course->getCode()));
204
    }
205
206
    /**
207
     * Set the current session.
208
     *
209
     * @param int $id
210
     *
211
     * @throws Exception
212
     */
213
    public function setSession($id)
214
    {
215
        if (!$id) {
216
            $this->session = null;
217
218
            ChamiloSession::erase('session_name');
219
            ChamiloSession::erase('id_session');
220
221
            return;
222
        }
223
224
        $em = Database::getManager();
225
        /** @var Session $session */
226
        $session = $em->find('ChamiloCoreBundle:Session', $id);
227
228
        if (!$session) {
0 ignored issues
show
introduced by
$session is of type Chamilo\CoreBundle\Entity\Session, thus it always evaluated to true.
Loading history...
229
            throw new Exception(get_lang('NoSession'));
230
        }
231
232
        $this->session = $session;
233
234
        ChamiloSession::write('session_name', $session->getName());
235
        ChamiloSession::write('id_session', $session->getId());
236
    }
237
238
    /**
239
     * @param string $registrationId
240
     *
241
     * @return bool
242
     */
243
    public function setGcmId($registrationId)
244
    {
245
        $registrationId = Security::remove_XSS($registrationId);
246
        $extraFieldValue = new ExtraFieldValue('user');
247
248
        return $extraFieldValue->save(
249
            [
250
                'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
251
                'value' => $registrationId,
252
                'item_id' => $this->user->getId(),
253
            ]
254
        );
255
    }
256
257
    /**
258
     * @param int $lastMessageId
259
     *
260
     * @return array
261
     */
262
    public function getUserMessages($lastMessageId = 0)
263
    {
264
        $lastMessages = MessageManager::getMessagesFromLastReceivedMessage($this->user->getId(), $lastMessageId);
265
        $messages = [];
266
267
        foreach ($lastMessages as $message) {
268
            $hasAttachments = MessageManager::hasAttachments($message['id']);
269
270
            $messages[] = [
271
                'id' => $message['id'],
272
                'title' => $message['title'],
273
                'sender' => [
274
                    'id' => $message['user_id'],
275
                    'lastname' => $message['lastname'],
276
                    'firstname' => $message['firstname'],
277
                    'completeName' => api_get_person_name($message['firstname'], $message['lastname']),
278
                ],
279
                'sendDate' => $message['send_date'],
280
                'content' => $message['content'],
281
                'hasAttachments' => $hasAttachments,
282
                'url' => api_get_path(WEB_CODE_PATH).'messages/view_message.php?'
283
                    .http_build_query(['type' => 1, 'id' => $message['id']]),
284
            ];
285
        }
286
287
        return $messages;
288
    }
289
290
    /**
291
     * @return array
292
     */
293
    public function getUserReceivedMessages()
294
    {
295
        $lastMessages = MessageManager::getReceivedMessages($this->user->getId(), 0);
296
        $messages = [];
297
298
        $webPath = api_get_path(WEB_PATH);
299
300
        foreach ($lastMessages as $message) {
301
            $hasAttachments = MessageManager::hasAttachments($message['id']);
302
            $attachmentList = [];
303
            if ($hasAttachments) {
304
                $attachmentList = MessageManager::getAttachmentList($message['id']);
305
            }
306
            $messages[] = [
307
                'id' => $message['id'],
308
                'title' => $message['title'],
309
                'msgStatus' => $message['msg_status'],
310
                'sender' => [
311
                    'id' => $message['user_id'],
312
                    'lastname' => $message['lastname'],
313
                    'firstname' => $message['firstname'],
314
                    'completeName' => api_get_person_name($message['firstname'], $message['lastname']),
315
                    'pictureUri' => $message['pictureUri'],
316
                ],
317
                'sendDate' => $message['send_date'],
318
                'content' => str_replace('src="/"', $webPath, $message['content']),
319
                'hasAttachments' => $hasAttachments,
320
                'attachmentList' => $attachmentList,
321
                'url' => '',
322
            ];
323
        }
324
325
        return $messages;
326
    }
327
328
    /**
329
     * @return array
330
     */
331
    public function getUserSentMessages()
332
    {
333
        $lastMessages = MessageManager::getSentMessages($this->user->getId(), 0);
334
        $messages = [];
335
336
        foreach ($lastMessages as $message) {
337
            $hasAttachments = MessageManager::hasAttachments($message['id']);
338
339
            $messages[] = [
340
                'id' => $message['id'],
341
                'title' => $message['title'],
342
                'msgStatus' => $message['msg_status'],
343
                'receiver' => [
344
                    'id' => $message['user_id'],
345
                    'lastname' => $message['lastname'],
346
                    'firstname' => $message['firstname'],
347
                    'completeName' => api_get_person_name($message['firstname'], $message['lastname']),
348
                    'pictureUri' => $message['pictureUri'],
349
                ],
350
                'sendDate' => $message['send_date'],
351
                'content' => $message['content'],
352
                'hasAttachments' => $hasAttachments,
353
                'url' => '',
354
            ];
355
        }
356
357
        return $messages;
358
    }
359
360
    /**
361
     * Get the user courses.
362
     */
363
    public function getUserCourses($userId = 0): array
364
    {
365
        if (empty($userId)) {
366
            $userId = $this->user->getId();
367
        }
368
369
        Event::courseLogout(
370
            [
371
                'uid' => $userId,
372
                'cid' => api_get_course_id(),
373
                'sid' => api_get_session_id(),
374
            ]
375
        );
376
377
        $courses = CourseManager::get_courses_list_by_user_id($userId);
378
        $data = [];
379
380
        foreach ($courses as $courseInfo) {
381
            /** @var Course $course */
382
            $course = Database::getManager()->find('ChamiloCoreBundle:Course', $courseInfo['real_id']);
383
            $teachers = CourseManager::getTeacherListFromCourseCodeToString($course->getCode());
384
            $picturePath = CourseManager::getPicturePath($course, true)
385
                ?: Display::return_icon('session_default.png', null, null, null, null, true);
386
387
            $data[] = [
388
                'id' => $course->getId(),
389
                'title' => $course->getTitle(),
390
                'code' => $course->getCode(),
391
                'directory' => $course->getDirectory(),
392
                'urlPicture' => $picturePath,
393
                'teachers' => $teachers,
394
                'isSpecial' => !empty($courseInfo['special_course']),
395
            ];
396
        }
397
398
        return $data;
399
    }
400
401
    /**
402
     * @throws Exception
403
     *
404
     * @return array
405
     */
406
    public function getCourseInfo()
407
    {
408
        $teachers = CourseManager::getTeacherListFromCourseCodeToString($this->course->getCode());
409
        $tools = CourseHome::get_tools_category(
410
            TOOL_STUDENT_VIEW,
411
            $this->course->getId(),
412
            $this->session ? $this->session->getId() : 0
413
        );
414
415
        return [
416
            'id' => $this->course->getId(),
417
            'title' => $this->course->getTitle(),
418
            'code' => $this->course->getCode(),
419
            'directory' => $this->course->getDirectory(),
420
            'urlPicture' => CourseManager::getPicturePath($this->course, true),
421
            'teachers' => $teachers,
422
            'tools' => array_map(
423
                function ($tool) {
424
                    return ['type' => $tool['name']];
425
                },
426
                $tools
427
            ),
428
        ];
429
    }
430
431
    /**
432
     * Get the course descriptions.
433
     *
434
     * @throws Exception
435
     *
436
     * @return array
437
     */
438
    public function getCourseDescriptions()
439
    {
440
        Event::event_access_tool(TOOL_COURSE_DESCRIPTION);
441
442
        $descriptions = CourseDescription::get_descriptions($this->course->getId());
443
        $results = [];
444
445
        $webPath = api_get_path(WEB_PATH);
446
447
        /** @var CourseDescription $description */
448
        foreach ($descriptions as $description) {
449
            $results[] = [
450
                'id' => $description->get_description_type(),
451
                'title' => $description->get_title(),
452
                'content' => str_replace('src="/', 'src="'.$webPath, $description->get_content()),
453
            ];
454
        }
455
456
        return $results;
457
    }
458
459
    /**
460
     * @param int $directoryId
461
     *
462
     * @throws Exception
463
     *
464
     * @return array
465
     */
466
    public function getCourseDocuments($directoryId = 0)
467
    {
468
        Event::event_access_tool(TOOL_DOCUMENT);
469
470
        /** @var string $path */
471
        $path = '/';
472
        $sessionId = $this->session ? $this->session->getId() : 0;
473
474
        if ($directoryId) {
475
            $directory = DocumentManager::get_document_data_by_id(
476
                $directoryId,
477
                $this->course->getCode(),
478
                false,
479
                $sessionId
480
            );
481
482
            if (!$directory) {
483
                throw new Exception('NoDataAvailable');
484
            }
485
486
            $path = $directory['path'];
487
        }
488
489
        $courseInfo = api_get_course_info_by_id($this->course->getId());
490
        $documents = DocumentManager::getAllDocumentData(
491
            $courseInfo,
492
            $path,
493
            0,
494
            null,
495
            false,
496
            false,
497
            $sessionId
498
        );
499
        $results = [];
500
501
        if (!empty($documents)) {
502
            $webPath = api_get_path(WEB_CODE_PATH).'document/document.php?';
503
504
            /** @var array $document */
505
            foreach ($documents as $document) {
506
                if ($document['visibility'] != '1') {
507
                    continue;
508
                }
509
510
                $icon = $document['filetype'] == 'file'
511
                    ? choose_image($document['path'])
512
                    : chooseFolderIcon($document['path']);
513
514
                $results[] = [
515
                    'id' => $document['id'],
516
                    'type' => $document['filetype'],
517
                    'title' => $document['title'],
518
                    'path' => $document['path'],
519
                    'url' => $webPath.http_build_query(
520
                        [
521
                            'username' => $this->user->getUsername(),
522
                            'api_key' => $this->apiKey,
523
                            'cidReq' => $this->course->getCode(),
524
                            'id_session' => $sessionId,
525
                            'gidReq' => 0,
526
                            'gradebook' => 0,
527
                            'origin' => '',
528
                            'action' => 'download',
529
                            'id' => $document['id'],
530
                        ]
531
                    ),
532
                    'icon' => $icon,
533
                    'size' => format_file_size($document['size']),
534
                ];
535
            }
536
        }
537
538
        return $results;
539
    }
540
541
    /**
542
     * @throws Exception
543
     *
544
     * @return array
545
     */
546
    public function getCourseAnnouncements()
547
    {
548
        Event::event_access_tool(TOOL_ANNOUNCEMENT);
549
550
        $sessionId = $this->session ? $this->session->getId() : 0;
551
552
        $announcements = AnnouncementManager::getAnnouncements(
553
            null,
554
            null,
555
            false,
556
            null,
557
            null,
558
            null,
559
            null,
560
            null,
561
            0,
562
            $this->user->getId(),
563
            $this->course->getId(),
564
            $sessionId
565
        );
566
567
        $announcements = array_map(
568
            function ($announcement) {
569
                return [
570
                    'id' => (int) $announcement['id'],
571
                    'title' => strip_tags($announcement['title']),
572
                    'creatorName' => strip_tags($announcement['username']),
573
                    'date' => strip_tags($announcement['insert_date']),
574
                ];
575
            },
576
            $announcements
577
        );
578
579
        return $announcements;
580
    }
581
582
    /**
583
     * @param int $announcementId
584
     *
585
     * @throws Exception
586
     *
587
     * @return array
588
     */
589
    public function getCourseAnnouncement($announcementId)
590
    {
591
        Event::event_access_tool(TOOL_ANNOUNCEMENT);
592
593
        $sessionId = $this->session ? $this->session->getId() : 0;
594
        $announcement = AnnouncementManager::getAnnouncementInfoById(
595
            $announcementId,
596
            $this->course->getId(),
597
            $this->user->getId()
598
        );
599
600
        if (!$announcement) {
601
            throw new Exception(get_lang('NoAnnouncement'));
602
        }
603
604
        return [
605
            'id' => $announcement['announcement']->getIid(),
606
            'title' => $announcement['announcement']->getTitle(),
607
            'creatorName' => UserManager::formatUserFullName($announcement['item_property']->getInsertUser()),
608
            'date' => api_convert_and_format_date(
609
                $announcement['item_property']->getInsertDate(),
610
                DATE_TIME_FORMAT_LONG_24H
611
            ),
612
            'content' => AnnouncementManager::parseContent(
613
                $this->user->getId(),
614
                $announcement['announcement']->getContent(),
615
                $this->course->getCode(),
616
                $sessionId
617
            ),
618
        ];
619
    }
620
621
    /**
622
     * @throws Exception
623
     *
624
     * @return array
625
     */
626
    public function getCourseAgenda()
627
    {
628
        Event::event_access_tool(TOOL_CALENDAR_EVENT);
629
630
        $sessionId = $this->session ? $this->session->getId() : 0;
631
632
        $agenda = new Agenda(
633
            'course',
634
            $this->user->getId(),
635
            $this->course->getId(),
636
            $sessionId
637
        );
638
        $result = $agenda->parseAgendaFilter(null);
639
640
        $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
641
        $start->modify('first day of this month');
642
        $start->setTime(0, 0, 0);
643
        $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
644
        $end->modify('last day of this month');
645
        $end->setTime(23, 59, 59);
646
647
        $groupId = current($result['groups']);
648
        $userId = current($result['users']);
649
650
        $events = $agenda->getEvents(
651
            $start->getTimestamp(),
652
            $end->getTimestamp(),
653
            $this->course->getId(),
654
            $groupId,
655
            $userId,
656
            'array'
657
        );
658
659
        if (!is_array($events)) {
660
            return [];
661
        }
662
663
        $webPath = api_get_path(WEB_PATH);
664
665
        return array_map(
666
            function ($event) use ($webPath) {
667
                return [
668
                    'id' => (int) $event['unique_id'],
669
                    'title' => $event['title'],
670
                    'content' => str_replace('src="/', 'src="'.$webPath, $event['description']),
671
                    'startDate' => $event['start_date_localtime'],
672
                    'endDate' => $event['end_date_localtime'],
673
                    'isAllDay' => $event['allDay'] ? true : false,
674
                ];
675
            },
676
            $events
677
        );
678
    }
679
680
    /**
681
     * @throws Exception
682
     *
683
     * @return array
684
     */
685
    public function getCourseNotebooks()
686
    {
687
        Event::event_access_tool(TOOL_NOTEBOOK);
688
689
        $em = Database::getManager();
690
        /** @var CNotebookRepository $notebooksRepo */
691
        $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
692
        $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
693
694
        return array_map(
695
            function (CNotebook $notebook) {
696
                return [
697
                    'id' => $notebook->getIid(),
698
                    'title' => $notebook->getTitle(),
699
                    'description' => $notebook->getDescription(),
700
                    'creationDate' => api_format_date(
701
                        $notebook->getCreationDate()->getTimestamp()
702
                    ),
703
                    'updateDate' => api_format_date(
704
                        $notebook->getUpdateDate()->getTimestamp()
705
                    ),
706
                ];
707
            },
708
            $notebooks
709
        );
710
    }
711
712
    /**
713
     * @throws Exception
714
     *
715
     * @return array
716
     */
717
    public function getCourseForumCategories()
718
    {
719
        Event::event_access_tool(TOOL_FORUM);
720
721
        $sessionId = $this->session ? $this->session->getId() : 0;
722
        $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
723
724
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
725
726
        $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
727
        $categories = [];
728
        $includeGroupsForums = api_get_setting('display_groups_forum_in_general_tool') === 'true';
729
        $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
730
        $forums = [];
731
732
        foreach ($forumsFullData as $forumId => $forumInfo) {
733
            $forum = [
734
                'id' => (int) $forumInfo['iid'],
735
                'catId' => (int) $forumInfo['forum_category'],
736
                'title' => $forumInfo['forum_title'],
737
                'description' => $forumInfo['forum_comment'],
738
                'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
739
                'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval(
740
                    $forumInfo['number_of_threads']
741
                ) : 0,
742
                'lastPost' => null,
743
            ];
744
745
            $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId(), $sessionId);
746
747
            if ($lastPostInfo) {
748
                $forum['lastPost'] = [
749
                    'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
750
                    'user' => api_get_person_name(
751
                        $lastPostInfo['last_poster_firstname'],
752
                        $lastPostInfo['last_poster_lastname']
753
                    ),
754
                ];
755
            }
756
757
            $forums[] = $forum;
758
        }
759
760
        foreach ($categoriesFullData as $category) {
761
            $categoryForums = array_filter(
762
                $forums,
763
                function (array $forum) use ($category) {
764
                    if ($forum['catId'] != $category['cat_id']) {
765
                        return false;
766
                    }
767
768
                    return true;
769
                }
770
            );
771
772
            $categories[] = [
773
                'id' => (int) $category['iid'],
774
                'title' => $category['cat_title'],
775
                'catId' => (int) $category['cat_id'],
776
                'description' => $category['cat_comment'],
777
                'forums' => $categoryForums,
778
                'courseId' => $this->course->getId(),
779
            ];
780
        }
781
782
        return $categories;
783
    }
784
785
    /**
786
     * @param int $forumId
787
     *
788
     * @throws Exception
789
     *
790
     * @return array
791
     */
792
    public function getCourseForum($forumId)
793
    {
794
        Event::event_access_tool(TOOL_FORUM);
795
796
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
797
798
        $sessionId = $this->session ? $this->session->getId() : 0;
799
        $forumInfo = get_forums($forumId, $this->course->getCode(), true, $sessionId);
800
801
        if (!isset($forumInfo['iid'])) {
802
            throw new Exception(get_lang('NoForum'));
803
        }
804
805
        $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
806
        $forum = [
807
            'id' => $forumInfo['iid'],
808
            'title' => $forumInfo['forum_title'],
809
            'description' => $forumInfo['forum_comment'],
810
            'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
811
            'threads' => [],
812
        ];
813
814
        $threads = get_threads($forumInfo['iid'], $this->course->getId(), $sessionId);
815
816
        foreach ($threads as $thread) {
817
            $forum['threads'][] = [
818
                'id' => $thread['iid'],
819
                'title' => $thread['thread_title'],
820
                'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
821
                'numberOfReplies' => $thread['thread_replies'],
822
                'numberOfViews' => $thread['thread_views'],
823
                'author' => api_get_person_name($thread['firstname'], $thread['lastname']),
824
            ];
825
        }
826
827
        return $forum;
828
    }
829
830
    /**
831
     * @param int $forumId
832
     * @param int $threadId
833
     *
834
     * @return array
835
     */
836
    public function getCourseForumThread($forumId, $threadId)
837
    {
838
        Event::event_access_tool(TOOL_FORUM);
839
840
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
841
842
        $sessionId = $this->session ? $this->session->getId() : 0;
843
        $threadInfo = get_thread_information($forumId, $threadId, $sessionId);
844
845
        $thread = [
846
            'id' => intval($threadInfo['iid']),
847
            'cId' => intval($threadInfo['c_id']),
848
            'title' => $threadInfo['thread_title'],
849
            'forumId' => intval($threadInfo['forum_id']),
850
            'posts' => [],
851
        ];
852
853
        $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode(), true, $sessionId);
854
        $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
855
856
        foreach ($postsInfo as $postInfo) {
857
            $thread['posts'][] = [
858
                'id' => $postInfo['iid'],
859
                'title' => $postInfo['post_title'],
860
                'text' => $postInfo['post_text'],
861
                'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
862
                'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
863
                'parentId' => $postInfo['post_parent_id'],
864
            ];
865
        }
866
867
        return $thread;
868
    }
869
870
    public function getCourseLinks(): array
871
    {
872
        Event::event_access_tool(TOOL_LINK);
873
874
        $courseId = $this->course->getId();
875
        $sessionId = $this->session ? $this->session->getId() : 0;
876
877
        $webCodePath = api_get_path(WEB_CODE_PATH);
878
        $cidReq = api_get_cidreq();
879
880
        $categories = array_merge(
881
            [
882
                [
883
                    'iid' => 0,
884
                    'c_id' => $courseId,
885
                    'id' => 0,
886
                    'category_title' => get_lang('NoCategory'),
887
                    'description' => '',
888
                    'display_order' => 0,
889
                    'session_id' => $sessionId,
890
                    'visibility' => 1,
891
                ],
892
            ],
893
            Link::getLinkCategories($courseId, $sessionId)
894
        );
895
896
        $categories = array_filter(
897
            $categories,
898
            function (array $category) {
899
                return $category['visibility'] != 0;
900
            }
901
        );
902
903
        return array_map(
904
            function (array $category) use ($webCodePath, $cidReq, $courseId, $sessionId) {
905
                $links = array_filter(
906
                    Link::getLinksPerCategory($category['iid'], $courseId, $sessionId),
907
                    function (array $link) {
908
                        return $link['visibility'] != 0;
909
                    }
910
                );
911
912
                $links = array_map(
913
                    function (array $link) use ($webCodePath, $cidReq) {
914
                        return [
915
                            'id' => (int) $link['id'],
916
                            'title' => Security::remove_XSS($link['title']),
917
                            'description' => Security::remove_XSS($link['description']),
918
                            'visibility' => (int) $link['visibility'],
919
                            'url' => $webCodePath."link/link_goto.php?$cidReq&link_id=".$link['id'],
920
                        ];
921
                    },
922
                    $links
923
                );
924
925
                return [
926
                    'id' => (int) $category['iid'],
927
                    'title' => Security::remove_XSS($category['category_title']),
928
                    'description' => Security::remove_XSS($category['description']),
929
                    'visibility' => (int) $category['visibility'],
930
                    'links' => $links,
931
                ];
932
            },
933
            $categories
934
        );
935
    }
936
937
    /**
938
     * @return array
939
     */
940
    public function getUserProfile()
941
    {
942
        $pictureInfo = UserManager::get_user_picture_path_by_id($this->user->getId(), 'web');
943
944
        $result = [
945
            'pictureUri' => $pictureInfo['dir'].$pictureInfo['file'],
946
            'id' => $this->user->getId(),
947
            'status' => $this->user->getStatus(),
948
            'fullName' => UserManager::formatUserFullName($this->user),
949
            'username' => $this->user->getUsername(),
950
            'officialCode' => $this->user->getOfficialCode(),
951
            'phone' => $this->user->getPhone(),
952
            'extra' => [],
953
        ];
954
955
        $fieldValue = new ExtraFieldValue('user');
956
        $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
957
958
        foreach ($extraInfo as $extra) {
959
            /** @var ExtraFieldValues $extraValue */
960
            $extraValue = $extra['value'];
961
            $result['extra'][] = [
962
                'title' => $extraValue->getField()->getDisplayText(true),
963
                'value' => $extraValue->getValue(),
964
            ];
965
        }
966
967
        return $result;
968
    }
969
970
    public function getCourseLpProgress()
971
    {
972
        $sessionId = $this->session ? $this->session->getId() : 0;
973
        $userId = $this->user->getId();
974
975
        /*$sessionId = $this->session ? $this->session->getId() : 0;
976
        $courseId = $this->course->getId();*/
977
978
        $result = Tracking::getCourseLpProgress($userId, $sessionId);
979
980
        return [$result];
981
    }
982
983
    /**
984
     * @throws Exception
985
     *
986
     * @return array
987
     */
988
    public function getCourseLearnPaths()
989
    {
990
        Event::event_access_tool(TOOL_LEARNPATH);
991
992
        $sessionId = $this->session ? $this->session->getId() : 0;
993
        $categoriesTempList = learnpath::getCategories($this->course->getId());
994
995
        $categoryNone = new CLpCategory();
996
        $categoryNone->setId(0);
997
        $categoryNone->setName(get_lang('WithOutCategory'));
998
        $categoryNone->setPosition(0);
999
1000
        $categories = array_merge([$categoryNone], $categoriesTempList);
1001
        $categoryData = [];
1002
1003
        /** @var CLpCategory $category */
1004
        foreach ($categories as $category) {
1005
            $learnPathList = new LearnpathList(
1006
                $this->user->getId(),
1007
                api_get_course_info($this->course->getCode()),
1008
                $sessionId,
1009
                null,
1010
                false,
1011
                $category->getId()
1012
            );
1013
1014
            $flatLpList = $learnPathList->get_flat_list();
1015
1016
            if (empty($flatLpList)) {
1017
                continue;
1018
            }
1019
1020
            $listData = [];
1021
1022
            foreach ($flatLpList as $lpId => $lpDetails) {
1023
                if ($lpDetails['lp_visibility'] == 0) {
1024
                    continue;
1025
                }
1026
1027
                if (!learnpath::is_lp_visible_for_student(
1028
                    $lpId,
1029
                    $this->user->getId(),
1030
                    api_get_course_info($this->course->getCode()),
1031
                    $sessionId
1032
                )) {
1033
                    continue;
1034
                }
1035
1036
                $timeLimits = false;
1037
1038
                // This is an old LP (from a migration 1.8.7) so we do nothing
1039
                if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
1040
                    $timeLimits = false;
1041
                }
1042
1043
                // Checking if expired_on is ON
1044
                if (!empty($lpDetails['expired_on'])) {
1045
                    $timeLimits = true;
1046
                }
1047
1048
                if ($timeLimits) {
1049
                    if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
1050
                        $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
1051
                        $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
1052
                        $now = time();
1053
                        $isActiveTime = false;
1054
1055
                        if ($now > $startTime && $endTime > $now) {
1056
                            $isActiveTime = true;
1057
                        }
1058
1059
                        if (!$isActiveTime) {
1060
                            continue;
1061
                        }
1062
                    }
1063
                }
1064
1065
                $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
1066
1067
                $listData[] = [
1068
                    'id' => $lpId,
1069
                    'title' => Security::remove_XSS($lpDetails['lp_name']),
1070
                    'progress' => $progress,
1071
                    'url' => api_get_path(WEB_CODE_PATH).'webservices/api/v2.php?'.http_build_query(
1072
                        [
1073
                            'hash' => $this->encodeParams(
1074
                                [
1075
                                    'action' => 'course_learnpath',
1076
                                    'lp_id' => $lpId,
1077
                                    'course' => $this->course->getId(),
1078
                                    'session' => $sessionId,
1079
                                ]
1080
                            ),
1081
                        ]
1082
                    ),
1083
                ];
1084
            }
1085
1086
            if (empty($listData)) {
1087
                continue;
1088
            }
1089
1090
            $categoryData[] = [
1091
                'id' => $category->getId(),
1092
                'name' => $category->getName(),
1093
                'learnpaths' => $listData,
1094
            ];
1095
        }
1096
1097
        return $categoryData;
1098
    }
1099
1100
    /**
1101
     * Start login for a user. Then make a redirect to show the learnpath.
1102
     *
1103
     * @param int $lpId
1104
     */
1105
    public function showLearningPath($lpId)
1106
    {
1107
        $loggedUser['user_id'] = $this->user->getId();
1108
        $loggedUser['status'] = $this->user->getStatus();
1109
        $loggedUser['uidReset'] = true;
1110
        $sessionId = $this->session ? $this->session->getId() : 0;
1111
1112
        ChamiloSession::write('_user', $loggedUser);
1113
        Login::init_user($this->user->getId(), true);
1114
1115
        $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.http_build_query(
1116
            [
1117
                'cidReq' => $this->course->getCode(),
1118
                'id_session' => $sessionId,
1119
                'gidReq' => 0,
1120
                'gradebook' => 0,
1121
                'origin' => '',
1122
                'action' => 'view',
1123
                'lp_id' => (int) $lpId,
1124
                'isStudentView' => 'true',
1125
            ]
1126
        );
1127
1128
        header("Location: $url");
1129
        exit;
1130
    }
1131
1132
    /**
1133
     * @param int $forumId
1134
     *
1135
     * @return array
1136
     */
1137
    public function saveForumPost(array $postValues, $forumId)
1138
    {
1139
        Event::event_access_tool(TOOL_FORUM);
1140
1141
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
1142
1143
        $forum = get_forums($forumId, $this->course->getCode());
1144
        store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
1145
1146
        return [
1147
            'registered' => true,
1148
        ];
1149
    }
1150
1151
    /**
1152
     * Get the list of sessions for current user.
1153
     *
1154
     * @return array the sessions list
1155
     */
1156
    public function getUserSessions()
1157
    {
1158
        $data = [];
1159
        $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
1160
1161
        foreach ($sessionsByCategory as $category) {
1162
            $categorySessions = [];
1163
1164
            foreach ($category['sessions'] as $sessions) {
1165
                $sessionCourses = [];
1166
1167
                foreach ($sessions['courses'] as $course) {
1168
                    $courseInfo = api_get_course_info_by_id($course['real_id']);
1169
                    $teachers = SessionManager::getCoachesByCourseSessionToString(
1170
                        $sessions['session_id'],
1171
                        $course['real_id']
1172
                    );
1173
1174
                    $sessionCourses[] = [
1175
                        'id' => $courseInfo['real_id'],
1176
                        'title' => $courseInfo['title'],
1177
                        'code' => $courseInfo['code'],
1178
                        'directory' => $courseInfo['directory'],
1179
                        'pictureUrl' => $courseInfo['course_image_large'],
1180
                        'urlPicture' => $courseInfo['course_image_large'],
1181
                        'teachers' => $teachers,
1182
                    ];
1183
                }
1184
1185
                $sessionBox = Display::getSessionTitleBox($sessions['session_id']);
1186
1187
                $categorySessions[] = [
1188
                    'name' => $sessionBox['title'],
1189
                    'id' => $sessions['session_id'],
1190
                    'date' => $sessionBox['dates'],
1191
                    'duration' => isset($sessionBox['duration']) ? $sessionBox['duration'] : null,
1192
                    'courses' => $sessionCourses,
1193
                ];
1194
            }
1195
1196
            $data[] = [
1197
                'id' => $category['session_category']['id'],
1198
                'name' => $category['session_category']['name'],
1199
                'sessions' => $categorySessions,
1200
            ];
1201
        }
1202
1203
        return $data;
1204
    }
1205
1206
    public function getUsersSubscribedToCourse()
1207
    {
1208
        $users = CourseManager::get_user_list_from_course_code($this->course->getCode());
1209
1210
        $userList = [];
1211
        foreach ($users as $user) {
1212
            $userList[] = [
1213
                'user_id' => $user['user_id'],
1214
                'username' => $user['username'],
1215
                'firstname' => $user['firstname'],
1216
                'lastname' => $user['lastname'],
1217
                'status_rel' => $user['status_rel'],
1218
            ];
1219
        }
1220
1221
        return $userList;
1222
    }
1223
1224
    /**
1225
     * @param string $subject
1226
     * @param string $text
1227
     *
1228
     * @return array
1229
     */
1230
    public function saveUserMessage($subject, $text, array $receivers)
1231
    {
1232
        foreach ($receivers as $userId) {
1233
            MessageManager::send_message($userId, $subject, $text);
1234
        }
1235
1236
        return [
1237
            'sent' => true,
1238
        ];
1239
    }
1240
1241
    /**
1242
     * @param string $search
1243
     *
1244
     * @return array
1245
     */
1246
    public function getMessageUsers($search)
1247
    {
1248
        $repo = UserManager::getRepository();
1249
1250
        $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
1251
        $showEmail = api_get_setting('show_email_addresses') === 'true';
1252
        $data = [];
1253
1254
        /** @var User $user */
1255
        foreach ($users as $user) {
1256
            $userName = UserManager::formatUserFullName($user);
1257
1258
            if ($showEmail) {
1259
                $userName .= " ({$user->getEmail()})";
1260
            }
1261
1262
            $data[] = [
1263
                'id' => $user->getId(),
1264
                'name' => $userName,
1265
            ];
1266
        }
1267
1268
        return $data;
1269
    }
1270
1271
    /**
1272
     * @param string $title
1273
     * @param string $text
1274
     *
1275
     * @return array
1276
     */
1277
    public function saveCourseNotebook($title, $text)
1278
    {
1279
        Event::event_access_tool(TOOL_NOTEBOOK);
1280
1281
        $values = ['note_title' => $title, 'note_comment' => $text];
1282
        $sessionId = $this->session ? $this->session->getId() : 0;
1283
1284
        $noteBookId = NotebookManager::save_note(
1285
            $values,
1286
            $this->user->getId(),
1287
            $this->course->getId(),
1288
            $sessionId
1289
        );
1290
1291
        return [
1292
            'registered' => $noteBookId,
1293
        ];
1294
    }
1295
1296
    /**
1297
     * @param int $forumId
1298
     *
1299
     * @return array
1300
     */
1301
    public function saveForumThread(array $values, $forumId)
1302
    {
1303
        Event::event_access_tool(TOOL_FORUM);
1304
1305
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
1306
1307
        $sessionId = $this->session ? $this->session->getId() : 0;
1308
        $forum = get_forums($forumId, $this->course->getCode(), true, $sessionId);
1309
        $courseInfo = api_get_course_info($this->course->getCode());
1310
        $thread = store_thread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
1311
1312
        return [
1313
            'registered' => $thread->getIid(),
1314
        ];
1315
    }
1316
1317
    /**
1318
     * @return array
1319
     */
1320
    public function getUsersCampus(array $params)
1321
    {
1322
        $conditions = [
1323
            'status' => $params['status'],
1324
        ];
1325
        $idCampus = $params['id_campus'];
1326
        $users = UserManager::get_user_list($conditions, ['firstname'], false, false, $idCampus);
1327
        $list = [];
1328
        foreach ($users as $item) {
1329
            $listTemp = [
1330
                'id' => $item['user_id'],
1331
                'firstname' => $item['firstname'],
1332
                'lastname' => $item['lastname'],
1333
                'email' => $item['email'],
1334
            ];
1335
            $list[] = $listTemp;
1336
        }
1337
1338
        return $list;
1339
    }
1340
1341
    /**
1342
     * @return array
1343
     */
1344
    public function getCoursesCampus(array $params)
1345
    {
1346
        $idCampus = $params['id_campus'];
1347
1348
        return CourseManager::get_courses_list(
1349
            0, //offset
1350
            0, //howMany
1351
            1, //$orderby = 1
1352
            'ASC',
1353
            -1, //visibility
1354
            null,
1355
            $idCampus, //$urlId
1356
            true //AlsoSearchCode
1357
        );
1358
    }
1359
1360
    /**
1361
     * @return array
1362
     */
1363
    public function addSession(array $params)
1364
    {
1365
        $name = $params['name'];
1366
        $coach_username = (int) $params['coach_username'];
1367
        $startDate = $params['access_start_date'];
1368
        $endDate = $params['access_end_date'];
1369
        $displayStartDate = $startDate;
1370
        $displayEndDate = $endDate;
1371
        $description = $params['description'];
1372
        $idUrlCampus = $params['id_campus'];
1373
        $extraFields = isset($params['extra']) ? $params['extra'] : [];
1374
1375
        $return = SessionManager::create_session(
1376
            $name,
1377
            $startDate,
1378
            $endDate,
1379
            $displayStartDate,
1380
            $displayEndDate,
1381
            null,
1382
            null,
1383
            $coach_username,
1384
            null,
1385
            1,
1386
            false,
1387
            null,
1388
            $description,
1389
            1,
1390
            $extraFields,
1391
            null,
1392
            false,
1393
            $idUrlCampus
1394
        );
1395
1396
        if ($return) {
1397
            $out = [
1398
                'status' => true,
1399
                'message' => get_lang('ANewSessionWasCreated'),
1400
                'id_session' => $return,
1401
            ];
1402
        } else {
1403
            $out = [
1404
                'status' => false,
1405
                'message' => get_lang('ErrorOccurred'),
1406
            ];
1407
        }
1408
1409
        return $out;
1410
    }
1411
1412
    public function addCourse(array $courseParam): array
1413
    {
1414
        $idCampus = isset($courseParam['id_campus']) ? $courseParam['id_campus'] : 1;
1415
        $title = isset($courseParam['title']) ? $courseParam['title'] : '';
1416
        $wantedCode = isset($courseParam['wanted_code']) ? $courseParam['wanted_code'] : null;
1417
        $diskQuota = isset($courseParam['disk_quota']) ? $courseParam['disk_quota'] : '100';
1418
        $visibility = isset($courseParam['visibility']) ? (int) $courseParam['visibility'] : null;
1419
        $removeCampusId = $courseParam['remove_campus_id_from_wanted_code'] ?? 0;
1420
        $language = $courseParam['language'] ?? '';
1421
1422
        if (isset($courseParam['visibility'])) {
1423
            if ($courseParam['visibility'] &&
1424
                $courseParam['visibility'] >= 0 &&
1425
                $courseParam['visibility'] <= 3
1426
            ) {
1427
                $visibility = (int) $courseParam['visibility'];
1428
            }
1429
        }
1430
1431
        $params = [];
1432
        $params['title'] = $title;
1433
        $params['wanted_code'] = 'CAMPUS_'.$idCampus.'_'.$wantedCode;
1434
        if (1 === (int) $removeCampusId) {
1435
            $params['wanted_code'] = $wantedCode;
1436
        }
1437
        $params['user_id'] = $this->user->getId();
1438
        $params['visibility'] = $visibility;
1439
        $params['disk_quota'] = $diskQuota;
1440
        $params['course_language'] = $language;
1441
1442
        foreach ($courseParam as $key => $value) {
1443
            if (substr($key, 0, 6) === 'extra_') { //an extra field
1444
                $params[$key] = $value;
1445
            }
1446
        }
1447
1448
        $courseInfo = CourseManager::create_course($params, $params['user_id'], $idCampus);
1449
        $results = [];
1450
        if (!empty($courseInfo)) {
1451
            $results['status'] = true;
1452
            $results['code_course'] = $courseInfo['code'];
1453
            $results['title_course'] = $courseInfo['title'];
1454
            $extraFieldValues = new ExtraFieldValue('course');
1455
            $extraFields = $extraFieldValues->getAllValuesByItem($courseInfo['real_id']);
1456
            $results['extra_fields'] = $extraFields;
1457
            $results['message'] = sprintf(get_lang('CourseXAdded'), $courseInfo['code']);
1458
        } else {
1459
            $results['status'] = false;
1460
            $results['message'] = get_lang('CourseCreationFailed');
1461
        }
1462
1463
        return $results;
1464
    }
1465
1466
    /**
1467
     * @param $userParam
1468
     *
1469
     * @throws Exception
1470
     *
1471
     * @return array
1472
     */
1473
    public function addUser($userParam)
1474
    {
1475
        $firstName = $userParam['firstname'];
1476
        $lastName = $userParam['lastname'];
1477
        $status = $userParam['status'];
1478
        $email = $userParam['email'];
1479
        $loginName = $userParam['loginname'];
1480
        $password = $userParam['password'];
1481
1482
        $official_code = '';
1483
        $language = '';
1484
        $phone = '';
1485
        $picture_uri = '';
1486
        $auth_source = $userParam['auth_source'] ?? PLATFORM_AUTH_SOURCE;
1487
        $expiration_date = '';
1488
        $active = 1;
1489
        $hr_dept_id = 0;
1490
        $original_user_id_name = $userParam['original_user_id_name'];
1491
        $original_user_id_value = $userParam['original_user_id_value'];
1492
1493
        $extra_list = isset($userParam['extra']) ? $userParam['extra'] : [];
1494
        if (isset($userParam['language'])) {
1495
            $language = $userParam['language'];
1496
        }
1497
        if (isset($userParam['phone'])) {
1498
            $phone = $userParam['phone'];
1499
        }
1500
        if (isset($userParam['expiration_date'])) {
1501
            $expiration_date = $userParam['expiration_date'];
1502
        }
1503
1504
        // Default language.
1505
        if (empty($language)) {
1506
            $language = api_get_setting('platformLanguage');
1507
        }
1508
1509
        // First check wether the login already exists.
1510
        if (!UserManager::is_username_available($loginName)) {
1511
            throw new Exception(get_lang('UserNameNotAvailable'));
1512
        }
1513
1514
        $userId = UserManager::create_user(
1515
            $firstName,
1516
            $lastName,
1517
            $status,
1518
            $email,
1519
            $loginName,
1520
            $password,
1521
            $official_code,
1522
            $language,
1523
            $phone,
1524
            $picture_uri,
1525
            $auth_source,
1526
            $expiration_date,
1527
            $active,
1528
            $hr_dept_id
1529
        );
1530
1531
        if (empty($userId)) {
1532
            throw new Exception(get_lang('UserNotRegistered'));
1533
        }
1534
1535
        if (api_is_multiple_url_enabled()) {
1536
            if (api_get_current_access_url_id() != -1) {
1537
                UrlManager::add_user_to_url(
1538
                    $userId,
1539
                    api_get_current_access_url_id()
1540
                );
1541
            } else {
1542
                UrlManager::add_user_to_url($userId, 1);
1543
            }
1544
        } else {
1545
            // We add by default the access_url_user table with access_url_id = 1
1546
            UrlManager::add_user_to_url($userId, 1);
1547
        }
1548
1549
        // Save new field label into user_field table.
1550
        UserManager::create_extra_field(
1551
            $original_user_id_name,
1552
            1,
1553
            $original_user_id_name,
1554
            ''
1555
        );
1556
        // Save the external system's id into user_field_value table.
1557
        UserManager::update_extra_field_value(
1558
            $userId,
1559
            $original_user_id_name,
1560
            $original_user_id_value
1561
        );
1562
1563
        if (is_array($extra_list) && count($extra_list) > 0) {
1564
            foreach ($extra_list as $extra) {
1565
                $extra_field_name = $extra['field_name'];
1566
                $extra_field_value = $extra['field_value'];
1567
                // Save new field label into user_field table.
1568
                UserManager::create_extra_field(
1569
                    $extra_field_name,
1570
                    1,
1571
                    $extra_field_name,
1572
                    ''
1573
                );
1574
                // Save the external system's id into user_field_value table.
1575
                UserManager::update_extra_field_value(
1576
                    $userId,
1577
                    $extra_field_name,
1578
                    $extra_field_value
1579
                );
1580
            }
1581
        }
1582
1583
        return [$userId];
1584
    }
1585
1586
    /**
1587
     * Subscribe User to Course.
1588
     *
1589
     * @param array $params
1590
     *
1591
     * @return array
1592
     */
1593
    public function subscribeUserToCourse($params)
1594
    {
1595
        $course_id = $params['course_id'];
1596
        $course_code = $params['course_code'];
1597
        $user_id = $params['user_id'];
1598
        $status = $params['status'] ?? STUDENT;
1599
1600
        if (!$course_id && !$course_code) {
1601
            return [false];
1602
        }
1603
        if (!$course_code) {
1604
            $course_code = CourseManager::get_course_code_from_course_id($course_id);
1605
        }
1606
1607
        if (CourseManager::subscribeUser($user_id, $course_code, $status, 0, 0, false)) {
1608
            return [true];
1609
        }
1610
1611
        return [false];
1612
    }
1613
1614
    /**
1615
     * @throws Exception
1616
     */
1617
    public function subscribeUserToCoursePassword($courseCode, $password)
1618
    {
1619
        $courseInfo = api_get_course_info($courseCode);
1620
1621
        if (empty($courseInfo)) {
1622
            throw new Exception(get_lang('NoCourse'));
1623
        }
1624
1625
        if (sha1($password) === $courseInfo['registration_code']) {
1626
            CourseManager::processAutoSubscribeToCourse($courseCode);
1627
1628
            return;
1629
        }
1630
1631
        throw new Exception(get_lang('CourseRegistrationCodeIncorrect'));
1632
    }
1633
1634
    public function unSubscribeUserToCourse(array $params): array
1635
    {
1636
        $courseId = $params['course_id'];
1637
        $courseCode = $params['course_code'];
1638
        $userId = $params['user_id'];
1639
1640
        if (!$courseId && !$courseCode) {
1641
            return [false];
1642
        }
1643
1644
        if (!$courseCode) {
1645
            $courseCode = CourseManager::get_course_code_from_course_id($courseId);
1646
        }
1647
1648
        if (CourseManager::unsubscribe_user($userId, $courseCode)) {
1649
            return [true];
1650
        }
1651
1652
        return [false];
1653
    }
1654
1655
    public function deleteUserMessage($messageId, $messageType)
1656
    {
1657
        if ($messageType === 'sent') {
1658
            return MessageManager::delete_message_by_user_sender($this->user->getId(), $messageId);
1659
        } else {
1660
            return MessageManager::delete_message_by_user_receiver($this->user->getId(), $messageId);
1661
        }
1662
    }
1663
1664
    public function setMessageRead($messageId)
1665
    {
1666
        MessageManager::update_message($this->user->getId(), $messageId);
1667
    }
1668
1669
    /**
1670
     * Add Campus Virtual.
1671
     *
1672
     * @param array Params Campus
1673
     *
1674
     * @return array
1675
     */
1676
    public function createCampusURL($params)
1677
    {
1678
        $urlCampus = Security::remove_XSS($params['url']);
1679
        $description = Security::remove_XSS($params['description']);
1680
1681
        $active = isset($params['active']) ? intval($params['active']) : 0;
1682
        $num = UrlManager::url_exist($urlCampus);
1683
        if ($num == 0) {
1684
            // checking url
1685
            if (substr($urlCampus, strlen($urlCampus) - 1, strlen($urlCampus)) == '/') {
1686
                $idCampus = UrlManager::add($urlCampus, $description, $active, true);
1687
            } else {
1688
                //create
1689
                $idCampus = UrlManager::add($urlCampus.'/', $description, $active, true);
1690
            }
1691
1692
            return [
1693
                'status' => true,
1694
                'id_campus' => $idCampus,
1695
            ];
1696
        }
1697
1698
        return [
1699
            'status' => false,
1700
            'id_campus' => 0,
1701
        ];
1702
    }
1703
1704
    /**
1705
     * Edit Campus Virtual.
1706
     *
1707
     * @param array Params Campus
1708
     *
1709
     * @return array
1710
     */
1711
    public function editCampusURL($params)
1712
    {
1713
        $urlCampus = Security::remove_XSS($params['url']);
1714
        $description = Security::remove_XSS($params['description']);
1715
1716
        $active = isset($params['active']) ? intval($params['active']) : 0;
1717
        $url_id = isset($params['id']) ? intval($params['id']) : 0;
1718
1719
        if (!empty($url_id)) {
1720
            //we can't change the status of the url with id=1
1721
            if ($url_id == 1) {
1722
                $active = 1;
1723
            }
1724
            //checking url
1725
            if (substr($urlCampus, strlen($urlCampus) - 1, strlen($urlCampus)) == '/') {
1726
                UrlManager::update($url_id, $urlCampus, $description, $active);
1727
            } else {
1728
                UrlManager::update($url_id, $urlCampus.'/', $description, $active);
1729
            }
1730
1731
            return [true];
1732
        }
1733
1734
        return [false];
1735
    }
1736
1737
    /**
1738
     * Delete Campus Virtual.
1739
     *
1740
     * @param array Params Campus
1741
     *
1742
     * @return array
1743
     */
1744
    public function deleteCampusURL($params)
1745
    {
1746
        $url_id = isset($params['id']) ? intval($params['id']) : 0;
1747
1748
        $result = UrlManager::delete($url_id);
1749
        if ($result) {
1750
            return [
1751
                'status' => true,
1752
                'message' => get_lang('URLDeleted'),
1753
            ];
1754
        } else {
1755
            return [
1756
                'status' => false,
1757
                'message' => get_lang('Error'),
1758
            ];
1759
        }
1760
    }
1761
1762
    /**
1763
     * @throws Exception
1764
     *
1765
     * @return array
1766
     */
1767
    public function addCoursesSession(array $params)
1768
    {
1769
        $sessionId = $params['id_session'];
1770
        $courseList = $params['list_courses'];
1771
        $importAssignments = isset($params['import_assignments']) ? 1 === (int) $params['import_assignments'] : false;
1772
1773
        $result = SessionManager::add_courses_to_session(
1774
            $sessionId,
1775
            $courseList,
1776
            true,
1777
            false,
1778
            false,
1779
            $importAssignments
1780
        );
1781
1782
        if ($result) {
1783
            return [
1784
                'status' => $result,
1785
                'message' => get_lang('Updated'),
1786
            ];
1787
        }
1788
1789
        return [
1790
            'status' => $result,
1791
            'message' => get_lang('ErrorOccurred'),
1792
        ];
1793
    }
1794
1795
    /**
1796
     * @return array
1797
     */
1798
    public function addUsersSession(array $params)
1799
    {
1800
        $sessionId = $params['id_session'];
1801
        $userList = $params['list_users'];
1802
1803
        if (!is_array($userList)) {
1804
            $userList = [];
1805
        }
1806
1807
        SessionManager::subscribeUsersToSession(
1808
            $sessionId,
1809
            $userList,
1810
            null,
1811
            false
1812
        );
1813
1814
        return [
1815
            'status' => true,
1816
            'message' => get_lang('UsersAdded'),
1817
        ];
1818
    }
1819
1820
    /**
1821
     * Creates a session from a model session.
1822
     *
1823
     * @param $modelSessionId
1824
     * @param $sessionName
1825
     * @param $startDate
1826
     * @param $endDate
1827
     *
1828
     * @throws Exception
1829
     *
1830
     * @return int, the id of the new session
1831
     */
1832
    public function createSessionFromModel($modelSessionId, $sessionName, $startDate, $endDate, array $extraFields = [])
1833
    {
1834
        if (empty($modelSessionId) || empty($sessionName) || empty($startDate) || empty($endDate)) {
1835
            throw new Exception(get_lang('NoData'));
1836
        }
1837
1838
        if (!SessionManager::isValidId($modelSessionId)) {
1839
            throw new Exception(get_lang('ModelSessionDoesNotExist'));
1840
        }
1841
1842
        $modelSession = SessionManager::fetch($modelSessionId);
1843
1844
        $modelSession['accessUrlId'] = 1;
1845
        if (api_is_multiple_url_enabled()) {
1846
            if (api_get_current_access_url_id() != -1) {
1847
                $modelSession['accessUrlId'] = api_get_current_access_url_id();
1848
            }
1849
        }
1850
1851
        $newSessionId = SessionManager::create_session(
1852
            $sessionName,
1853
            $startDate,
1854
            $endDate,
1855
            $startDate,
1856
            $endDate,
1857
            $startDate,
1858
            $endDate,
1859
            $modelSession['id_coach'],
1860
            $modelSession['session_category_id'],
1861
            $modelSession['visibility'],
1862
            false,
1863
            $modelSession['duration'],
1864
            $modelSession['description'],
1865
            $modelSession['show_description'],
1866
            $extraFields,
1867
            $modelSession['session_admin_id'],
1868
            $modelSession['send_subscription_notification'],
1869
            $modelSession['accessUrlId']
1870
        );
1871
1872
        if (empty($newSessionId)) {
1873
            throw new Exception(get_lang('SessionNotRegistered'));
1874
        }
1875
1876
        if (is_string($newSessionId)) {
1877
            throw new Exception($newSessionId);
1878
        }
1879
1880
        $promotionId = $modelSession['promotion_id'];
1881
        if ($promotionId) {
1882
            $sessionList = array_keys(SessionManager::get_all_sessions_by_promotion($promotionId));
1883
            $sessionList[] = $newSessionId;
1884
            SessionManager::subscribe_sessions_to_promotion($modelSession['promotion_id'], $sessionList);
1885
        }
1886
1887
        $modelExtraFields = [];
1888
        $fields = SessionManager::getFilteredExtraFields($modelSessionId);
1889
        if (is_array($fields) and !empty($fields)) {
1890
            foreach ($fields as $field) {
1891
                $modelExtraFields[$field['variable']] = $field['value'];
1892
            }
1893
        }
1894
        $allExtraFields = array_merge($modelExtraFields, $extraFields);
1895
        foreach ($allExtraFields as $name => $value) {
1896
            // SessionManager::update_session_extra_field_value returns false when no row is changed,
1897
            // which can happen since extra field values are initialized by SessionManager::create_session
1898
            // therefore we do not throw an exception when false is returned
1899
            SessionManager::update_session_extra_field_value($newSessionId, $name, $value);
1900
        }
1901
1902
        $courseList = array_keys(SessionManager::get_course_list_by_session_id($modelSessionId));
1903
        if (is_array($courseList)
1904
            && !empty($courseList)
1905
            && !SessionManager::add_courses_to_session($newSessionId, $courseList)) {
1906
            throw new Exception(get_lang('CoursesNotAddedToSession'));
1907
        }
1908
1909
        if (api_is_multiple_url_enabled()) {
1910
            if (api_get_current_access_url_id() != -1) {
1911
                UrlManager::add_session_to_url(
1912
                    $newSessionId,
1913
                    api_get_current_access_url_id()
1914
                );
1915
            } else {
1916
                UrlManager::add_session_to_url($newSessionId, 1);
1917
            }
1918
        } else {
1919
            UrlManager::add_session_to_url($newSessionId, 1);
1920
        }
1921
1922
        return $newSessionId;
1923
    }
1924
1925
    /**
1926
     * subscribes a user to a session.
1927
     *
1928
     * @param int    $sessionId the session id
1929
     * @param string $loginName the user's login name
1930
     *
1931
     * @throws Exception
1932
     *
1933
     * @return boolean, whether it worked
1934
     */
1935
    public function subscribeUserToSessionFromUsername($sessionId, $loginName)
1936
    {
1937
        if (!SessionManager::isValidId($sessionId)) {
1938
            throw new Exception(get_lang('SessionNotFound'));
1939
        }
1940
1941
        $userId = UserManager::get_user_id_from_username($loginName);
1942
        if (false === $userId) {
1943
            throw new Exception(get_lang('UserNotFound'));
1944
        }
1945
1946
        $subscribed = SessionManager::subscribeUsersToSession(
1947
            $sessionId,
1948
            [$userId],
1949
            SESSION_VISIBLE_READ_ONLY,
1950
            false
1951
        );
1952
        if (!$subscribed) {
1953
            throw new Exception(get_lang('UserNotSubscribed'));
1954
        }
1955
1956
        return true;
1957
    }
1958
1959
    /**
1960
     * finds the session which has a specific value in a specific extra field.
1961
     *
1962
     * @param $fieldName
1963
     * @param $fieldValue
1964
     *
1965
     * @throws Exception when no session matched or more than one session matched
1966
     *
1967
     * @return int, the matching session id
1968
     */
1969
    public function getSessionFromExtraField($fieldName, $fieldValue)
1970
    {
1971
        // find sessions that that have value in field
1972
        $valueModel = new ExtraFieldValue('session');
1973
        $sessionIdList = $valueModel->get_item_id_from_field_variable_and_field_value(
1974
            $fieldName,
1975
            $fieldValue,
1976
            false,
1977
            false,
1978
            true
1979
        );
1980
1981
        // throw if none found
1982
        if (empty($sessionIdList)) {
1983
            throw new Exception(get_lang('NoSessionMatched'));
1984
        }
1985
1986
        // throw if more than one found
1987
        if (count($sessionIdList) > 1) {
1988
            throw new Exception(get_lang('MoreThanOneSessionMatched'));
1989
        }
1990
1991
        // return sessionId
1992
        return intval($sessionIdList[0]['item_id']);
1993
    }
1994
1995
    /**
1996
     * updates a user identified by its login name.
1997
     *
1998
     * @param array $parameters
1999
     *
2000
     * @throws Exception on failure
2001
     *
2002
     * @return boolean, true on success
2003
     */
2004
    public function updateUserFromUserName($parameters)
2005
    {
2006
        // find user
2007
        $userId = null;
2008
        if (!is_array($parameters) || empty($parameters)) {
2009
            throw new Exception('NoData');
2010
        }
2011
        foreach ($parameters as $name => $value) {
2012
            if (strtolower($name) === 'loginname') {
2013
                $userId = UserManager::get_user_id_from_username($value);
2014
                if (false === $userId) {
2015
                    throw new Exception(get_lang('UserNotFound'));
2016
                }
2017
                break;
2018
            }
2019
        }
2020
        if (is_null($userId)) {
2021
            throw new Exception(get_lang('NoData'));
2022
        }
2023
        /** @var User $user */
2024
        $user = UserManager::getRepository()->find($userId);
2025
        if (empty($user)) {
2026
            throw new Exception(get_lang('CouldNotLoadUser'));
2027
        }
2028
2029
        // tell the world we are about to update a user
2030
        $hook = HookUpdateUser::create();
2031
        if (!empty($hook)) {
2032
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE);
2033
        }
2034
2035
        // apply submitted modifications
2036
        foreach ($parameters as $name => $value) {
2037
            switch (strtolower($name)) {
2038
                case 'email':
2039
                    $user->setEmail($value);
2040
                    break;
2041
                case 'enabled':
2042
                    $user->setEnabled($value);
2043
                    break;
2044
                case 'lastname':
2045
                    $user->setLastname($value);
2046
                    break;
2047
                case 'firstname':
2048
                    $user->setFirstname($value);
2049
                    break;
2050
                case 'phone':
2051
                    $user->setPhone($value);
2052
                    break;
2053
                case 'address':
2054
                    $user->setAddress($value);
2055
                    break;
2056
                case 'roles':
2057
                    $user->setRoles($value);
2058
                    break;
2059
                case 'profile_completed':
2060
                    $user->setProfileCompleted($value);
2061
                    break;
2062
                case 'auth_source':
2063
                    $user->setAuthSource($value);
2064
                    break;
2065
                case 'status':
2066
                    $user->setStatus($value);
2067
                    break;
2068
                case 'official_code':
2069
                    $user->setOfficialCode($value);
2070
                    break;
2071
                case 'picture_uri':
2072
                    $user->setPictureUri($value);
2073
                    break;
2074
                case 'creator_id':
2075
                    $user->setCreatorId($value);
2076
                    break;
2077
                case 'competences':
2078
                    $user->setCompetences($value);
2079
                    break;
2080
                case 'diplomas':
2081
                    $user->setDiplomas($value);
2082
                    break;
2083
                case 'openarea':
2084
                    $user->setOpenArea($value);
2085
                    break;
2086
                case 'teach':
2087
                    $user->setTeach($value);
2088
                    break;
2089
                case 'productions':
2090
                    $user->setProductions($value);
2091
                    break;
2092
                case 'language':
2093
                    $languages = api_get_languages();
2094
                    if (!in_array($value, $languages['folder'])) {
2095
                        throw new Exception(get_lang('LanguageUnavailable'));
2096
                    }
2097
                    $user->setLanguage($value);
2098
                    break;
2099
                case 'registration_date':
2100
                    $user->setRegistrationDate($value);
2101
                    break;
2102
                case 'expiration_date':
2103
                    $user->setExpirationDate(
2104
                        new DateTime(
2105
                            api_get_utc_datetime($value),
2106
                            new DateTimeZone('UTC')
2107
                        )
2108
                    );
2109
                    break;
2110
                case 'active':
2111
                    // see UserManager::update_user() usermanager.lib.php:1205
2112
                    if ($user->getActive() != $value) {
2113
                        $user->setActive($value);
2114
                        Event::addEvent($value ? LOG_USER_ENABLE : LOG_USER_DISABLE, LOG_USER_ID, $userId);
2115
                    }
2116
                    break;
2117
                case 'openid':
2118
                    $user->setOpenId($value);
2119
                    break;
2120
                case 'theme':
2121
                    $user->setTheme($value);
2122
                    break;
2123
                case 'hr_dept_id':
2124
                    $user->setHrDeptId($value);
2125
                    break;
2126
                case 'extra':
2127
                    if (is_array($value)) {
2128
                        if (count($value) > 0) {
2129
                            if (is_array($value[0])) {
2130
                                foreach ($value as $field) {
2131
                                    $fieldName = $field['field_name'];
2132
                                    $fieldValue = $field['field_value'];
2133
                                    if (!isset($fieldName) || !isset($fieldValue) ||
2134
                                        !UserManager::update_extra_field_value($userId, $fieldName, $fieldValue)) {
2135
                                        throw new Exception(get_lang('CouldNotUpdateExtraFieldValue').': '.print_r($field, true));
2136
                                    }
2137
                                }
2138
                            } else {
2139
                                foreach ($value as $fieldName => $fieldValue) {
2140
                                    if (!UserManager::update_extra_field_value($userId, $fieldName, $fieldValue)) {
2141
                                        throw new Exception(get_lang('CouldNotUpdateExtraFieldValue').': '.$fieldName);
2142
                                    }
2143
                                }
2144
                            }
2145
                        }
2146
                    }
2147
                    break;
2148
                case 'username':
2149
                case 'api_key':
2150
                case 'action':
2151
                case 'loginname':
2152
                    break;
2153
                case 'email_canonical':
2154
                case 'locked':
2155
                case 'expired':
2156
                case 'credentials_expired':
2157
                case 'credentials_expire_at':
2158
                case 'expires_at':
2159
                case 'salt':
2160
                case 'last_login':
2161
                case 'created_at':
2162
                case 'updated_at':
2163
                case 'confirmation_token':
2164
                case 'password_requested_at':
2165
                case 'password': // see UserManager::update_user usermanager.lib.php:1182
2166
                case 'username_canonical':
2167
                default:
2168
                    throw new Exception(get_lang('UnsupportedUpdate')." '$name'");
2169
            }
2170
        }
2171
2172
        // save modifications
2173
        UserManager::getManager()->updateUser($user, true);
2174
2175
        // tell the world we just updated this user
2176
        if (!empty($hook)) {
2177
            $hook->setEventData(['user' => $user]);
2178
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST);
2179
        }
2180
2181
        // invalidate cache for this user
2182
        $cacheAvailable = api_get_configuration_value('apc');
2183
        if ($cacheAvailable === true) {
2184
            $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$userId;
2185
            if (apcu_exists($apcVar)) {
2186
                apcu_delete($apcVar);
2187
            }
2188
        }
2189
2190
        return true;
2191
    }
2192
2193
    /**
2194
     * Returns whether a user login name exists.
2195
     *
2196
     * @param string $loginname the user login name
2197
     *
2198
     * @return bool whether the user login name exists
2199
     */
2200
    public function usernameExist($loginname)
2201
    {
2202
        return false !== api_get_user_info_from_username($loginname);
2203
    }
2204
2205
    /**
2206
     * This service roughly matches what the call to MDL's API core_course_get_contents function returns.
2207
     *
2208
     * @return array
2209
     */
2210
    public function getCourseQuizMdlCompat()
2211
    {
2212
        $userId = $this->user->getId();
2213
        $courseId = $this->course->getId();
2214
        $sessionId = $this->session ? $this->session->getId() : 0;
2215
2216
        $toolVisibility = CourseHome::getToolVisibility(TOOL_QUIZ, $courseId, $sessionId);
2217
2218
        $json = [
2219
            "id" => $this->course->getId(),
2220
            "name" => get_lang('Exercises'),
2221
            "visible" => (int) $toolVisibility,
2222
            "summary" => '',
2223
            "summaryformat" => 1,
2224
            "section" => 1,
2225
            "hiddenbynumsections" => 0,
2226
            "uservisible" => $toolVisibility,
2227
            "modules" => [],
2228
        ];
2229
2230
        $quizIcon = Display::return_icon('quiz.png', '', [], ICON_SIZE_SMALL, false, true);
2231
2232
        $json['modules'] = array_map(
2233
            function (array $exercise) use ($quizIcon) {
2234
                return [
2235
                    'id' => $exercise['id'],
2236
                    'url' => $exercise['url'],
2237
                    'name' => $exercise['name'],
2238
                    'instance' => 1,
2239
                    'visible' => 1,
2240
                    'uservisible' => true,
2241
                    'visibleoncoursepage' => 0,
2242
                    'modicon' => $quizIcon,
2243
                    'modname' => 'quiz',
2244
                    'modplural' => get_lang('Exercises'),
2245
                    'availability' => null,
2246
                    'indent' => 0,
2247
                    'onclick' => '',
2248
                    'afterlink' => null,
2249
                    'customdata' => "",
2250
                    'noviewlink' => false,
2251
                    'completion' => (int) ($exercise[1] > 0),
2252
                ];
2253
            },
2254
            Exercise::exerciseGrid(0, '', $userId, $courseId, $sessionId, true)
2255
        );
2256
2257
        return [$json];
2258
    }
2259
2260
    /**
2261
     * @throws Exception
2262
     */
2263
    public function updateSession(array $params): array
2264
    {
2265
        $id = $params['session_id'];
2266
        $reset = $params['reset'] ?? null;
2267
        $name = $params['name'] ?? null;
2268
        $coachId = isset($params['id_coach']) ? (int) $params['id_coach'] : null;
2269
        $sessionCategoryId = isset($params['session_category_id']) ? (int) $params['session_category_id'] : null;
2270
        $description = $params['description'] ?? null;
2271
        $showDescription = $params['show_description'] ?? null;
2272
        $duration = $params['duration'] ?? null;
2273
        $visibility = $params['visibility'] ?? null;
2274
        $promotionId = $params['promotion_id'] ?? null;
2275
        $displayStartDate = $params['display_start_date'] ?? null;
2276
        $displayEndDate = $params['display_end_date'] ?? null;
2277
        $accessStartDate = $params['access_start_date'] ?? null;
2278
        $accessEndDate = $params['access_end_date'] ?? null;
2279
        $coachStartDate = $params['coach_access_start_date'] ?? null;
2280
        $coachEndDate = $params['coach_access_end_date'] ?? null;
2281
        $sendSubscriptionNotification = $params['send_subscription_notification'] ?? null;
2282
        $extraFields = $params['extra'] ?? [];
2283
2284
        $reset = (bool) $reset;
2285
        $visibility = (int) $visibility;
2286
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
2287
2288
        if (!SessionManager::isValidId($id)) {
2289
            throw new Exception(get_lang('NoData'));
2290
        }
2291
2292
        if (!empty($accessStartDate) && !api_is_valid_date($accessStartDate, 'Y-m-d H:i') &&
2293
            !api_is_valid_date($accessStartDate, 'Y-m-d H:i:s')
2294
        ) {
2295
            throw new Exception(get_lang('InvalidDate'));
2296
        }
2297
2298
        if (!empty($accessEndDate) && !api_is_valid_date($accessEndDate, 'Y-m-d H:i') &&
2299
            !api_is_valid_date($accessEndDate, 'Y-m-d H:i:s')
2300
        ) {
2301
            throw new Exception(get_lang('InvalidDate'));
2302
        }
2303
2304
        if (!empty($accessStartDate) && !empty($accessEndDate) && $accessStartDate >= $accessEndDate) {
2305
            throw new Exception(get_lang('InvalidDate'));
2306
        }
2307
2308
        $values = [];
2309
2310
        if ($reset) {
2311
            $values['name'] = $name;
2312
            $values['id_coach'] = $coachId;
2313
            $values['session_category_id'] = $sessionCategoryId;
2314
            $values['description'] = $description;
2315
            $values['show_description'] = $showDescription;
2316
            $values['duration'] = $duration;
2317
            $values['visibility'] = $visibility;
2318
            $values['promotion_id'] = $promotionId;
2319
            $values['display_start_date'] = !empty($displayStartDate) ? api_get_utc_datetime($displayStartDate) : null;
2320
            $values['display_end_date'] = !empty($displayEndDate) ? api_get_utc_datetime($displayEndDate) : null;
2321
            $values['access_start_date'] = !empty($accessStartDate) ? api_get_utc_datetime($accessStartDate) : null;
2322
            $values['access_end_date'] = !empty($accessEndDate) ? api_get_utc_datetime($accessEndDate) : null;
2323
            $values['coach_access_start_date'] = !empty($coachStartDate) ? api_get_utc_datetime($coachStartDate) : null;
2324
            $values['coach_access_end_date'] = !empty($coachEndDate) ? api_get_utc_datetime($coachEndDate) : null;
2325
            $values['send_subscription_notification'] = $sendSubscriptionNotification;
2326
        } else {
2327
            if (!empty($name)) {
2328
                $values['name'] = $name;
2329
            }
2330
2331
            if (!empty($coachId)) {
2332
                $values['id_coach'] = $coachId;
2333
            }
2334
2335
            if (!empty($sessionCategoryId)) {
2336
                $values['session_category_id'] = $sessionCategoryId;
2337
            }
2338
2339
            if (!empty($description)) {
2340
                $values['description'] = $description;
2341
            }
2342
2343
            if (!empty($showDescription)) {
2344
                $values['show_description'] = $showDescription;
2345
            }
2346
2347
            if (!empty($duration)) {
2348
                $values['duration'] = $duration;
2349
            }
2350
2351
            if (!empty($visibility)) {
2352
                $values['visibility'] = $visibility;
2353
            }
2354
2355
            if (!empty($promotionId)) {
2356
                $values['promotion_id'] = $promotionId;
2357
            }
2358
2359
            if (!empty($displayStartDate)) {
2360
                $values['display_start_date'] = api_get_utc_datetime($displayStartDate);
2361
            }
2362
2363
            if (!empty($displayEndDate)) {
2364
                $values['display_end_date'] = api_get_utc_datetime($displayEndDate);
2365
            }
2366
2367
            if (!empty($accessStartDate)) {
2368
                $values['access_start_date'] = api_get_utc_datetime($accessStartDate);
2369
            }
2370
2371
            if (!empty($accessEndDate)) {
2372
                $values['access_end_date'] = api_get_utc_datetime($accessEndDate);
2373
            }
2374
2375
            if (!empty($coachStartDate)) {
2376
                $values['coach_access_start_date'] = api_get_utc_datetime($coachStartDate);
2377
            }
2378
2379
            if (!empty($coachEndDate)) {
2380
                $values['coach_access_end_date'] = api_get_utc_datetime($coachEndDate);
2381
            }
2382
2383
            if (!empty($sendSubscriptionNotification)) {
2384
                $values['send_subscription_notification'] = $sendSubscriptionNotification;
2385
            }
2386
        }
2387
2388
        Database::update(
2389
            $tblSession,
2390
            $values,
2391
            ['id = ?' => $id]
2392
        );
2393
2394
        if (!empty($extraFields)) {
2395
            $extraFields['item_id'] = $id;
2396
            $sessionFieldValue = new ExtraFieldValue('session');
2397
            $sessionFieldValue->saveFieldValues($extraFields);
2398
        }
2399
2400
        return [
2401
            'status' => true,
2402
            'message' => get_lang('Updated'),
2403
            'id_session' => $id,
2404
        ];
2405
    }
2406
2407
    public function checkConditionalLogin(): bool
2408
    {
2409
        $file = api_get_path(SYS_CODE_PATH).'auth/conditional_login/conditional_login.php';
2410
2411
        if (!file_exists($file)) {
2412
            return true;
2413
        }
2414
2415
        include_once $file;
2416
2417
        if (!isset($login_conditions)) {
2418
            return true;
2419
        }
2420
2421
        foreach ($login_conditions as $condition) {
2422
            //If condition fails we redirect to the URL defined by the condition
2423
            if (!isset($condition['conditional_function'])) {
2424
                continue;
2425
            }
2426
2427
            $function = $condition['conditional_function'];
2428
            $result = $function(['user_id' => $this->user->getId()]);
2429
2430
            if ($result == false) {
2431
                return false;
2432
            }
2433
        }
2434
2435
        return true;
2436
    }
2437
2438
    public function getLegalConditions(): array
2439
    {
2440
        $language = api_get_language_id(
2441
            api_get_interface_language()
2442
        );
2443
2444
        $termPreview = LegalManager::get_last_condition($language);
2445
2446
        if ($termPreview) {
2447
            return $termPreview;
2448
        }
2449
2450
        $language = api_get_language_id(
2451
            api_get_setting('platformLanguage')
2452
        );
2453
2454
        $termPreview = LegalManager::get_last_condition($language);
2455
2456
        if ($termPreview) {
2457
            return $termPreview;
2458
        }
2459
2460
        $language = api_get_language_id('english');
2461
2462
        return LegalManager::get_last_condition($language);
2463
    }
2464
2465
    public function updateConditionAccepted()
2466
    {
2467
        $legalAcceptType = $_POST['legal_accept_type'] ?? null;
2468
2469
        $condArray = explode(':', $legalAcceptType);
2470
        $condArray = array_map('intval', $condArray);
2471
2472
        if (empty($condArray[0]) || empty($condArray[1])) {
2473
            return;
2474
        }
2475
2476
        $conditionToSave = intval($condArray[0]).':'.intval($condArray[1]).':'.time();
2477
2478
        LegalManager::sendEmailToUserBoss(
2479
            $this->user->getId(),
2480
            $conditionToSave
2481
        );
2482
    }
2483
2484
    public function logout()
2485
    {
2486
        online_logout($this->user->getId());
2487
2488
        Event::courseLogout(
2489
            [
2490
                'uid' => $this->user->getId(),
2491
                'cid' => $this->course ? $this->course->getId() : 0,
2492
                'sid' => $this->session ? $this->session->getId() : 0,
2493
            ]
2494
        );
2495
    }
2496
2497
    /**
2498
     * @throws Exception
2499
     */
2500
    public function setThreadNotify(int $threadId): string
2501
    {
2502
        require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
2503
2504
        $result = set_notification(
2505
            'thread',
2506
            $threadId,
2507
            false,
2508
            api_get_user_info($this->user->getId()),
2509
            api_get_course_info($this->course->getCode())
2510
        );
2511
2512
        if (false === $result) {
2513
            throw new Exception(get_lang('NotAllowed'));
2514
        }
2515
2516
        return $result;
2517
    }
2518
2519
    public function getCourseWorks(): array
2520
    {
2521
        Event::event_access_tool(TOOL_STUDENTPUBLICATION);
2522
2523
        require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
2524
2525
        $isAllowedToEdit = $this->user->getStatus() !== STUDENT;
2526
2527
        $courseId = $this->course->getId();
2528
        $sessionId = $this->session ? $this->session->getId() : 0;
2529
2530
        $courseInfo = api_get_course_info_by_id($this->course->getId());
2531
2532
        $works = array_filter(
2533
            getWorkListTeacherData($courseId, $sessionId, 0, 0, 0, 'title', 'ASC', ''),
2534
            function (array $work) use ($isAllowedToEdit, $courseInfo, $courseId, $sessionId) {
2535
                if (!$isAllowedToEdit
2536
                    && !userIsSubscribedToWork($this->user->getId(), $work['id'], $courseId)
2537
                ) {
2538
                    return false;
2539
                }
2540
2541
                $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $sessionId);
2542
2543
                if (!$isAllowedToEdit && $visibility != 1) {
2544
                    return false;
2545
                }
2546
2547
                return true;
2548
            }
2549
        );
2550
2551
        return array_map(
2552
            function (array $work) use ($isAllowedToEdit, $courseInfo, $courseId, $sessionId) {
2553
                $work['type'] = 'work.png';
2554
2555
                if (!$isAllowedToEdit) {
2556
                    $workList = get_work_user_list(
2557
                        0,
2558
                        1000,
2559
                        null,
2560
                        null,
2561
                        $work['id'],
2562
                        ' AND u.id = '.$this->user->getId()
2563
                    );
2564
2565
                    $count = getTotalWorkComment($workList, $courseInfo);
2566
                    $lastWork = getLastWorkStudentFromParentByUser($this->user->getId(), $work, $courseInfo);
2567
2568
                    $work['feedback'] = ' '.Display::label('0 '.get_lang('Feedback'), 'warning');
2569
2570
                    if (!empty($count)) {
2571
                        $work['feedback'] = ' '.Display::label($count.' '.get_lang('Feedback'), 'info');
2572
                    }
2573
2574
                    $work['last_upload'] = '';
2575
2576
                    if (!empty($lastWork)) {
2577
                        $work['last_upload'] = !empty($lastWork['qualification'])
2578
                            ? $lastWork['qualification_rounded'].' - '
2579
                            : '';
2580
                        $work['last_upload'] .= api_get_local_time($lastWork['sent_date']);
2581
                    }
2582
                }
2583
2584
                return $work;
2585
            },
2586
            $works
2587
        );
2588
    }
2589
2590
    /**
2591
     * @throws Exception
2592
     */
2593
    public function putCourseWorkVisibility(int $workId, int $status): bool
2594
    {
2595
        Event::event_access_tool(TOOL_STUDENTPUBLICATION);
2596
2597
        $courseInfo = api_get_course_info_by_id($this->course->getId());
2598
2599
        require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
2600
2601
        switch ($status) {
2602
            case 1:
2603
                return makeVisible($workId, $courseInfo);
2604
            case 0;
2605
                return makeInvisible($workId, $courseInfo);
2606
            default:
2607
                throw new Exception(get_lang('ActionNotAllowed'));
2608
        }
2609
    }
2610
2611
    public static function isAllowedByRequest(bool $inpersonate = false): bool
2612
    {
2613
        $username = $_GET['username'] ?? null;
2614
        $apiKey = $_GET['api_key'] ?? null;
2615
2616
        if (empty($username) || empty($apiKey)) {
2617
            return false;
2618
        }
2619
2620
        try {
2621
            $restApi = self::validate($username, $apiKey);
2622
        } catch (Exception $e) {
2623
            return false;
2624
        }
2625
2626
        if ($inpersonate) {
2627
            Login::init_user($restApi->getUser()->getId(), true);
2628
        }
2629
2630
        return (bool) $restApi;
2631
    }
2632
2633
    /**
2634
     * @param array $additionalParams Optional
2635
     *
2636
     * @return string
2637
     */
2638
    private function encodeParams(array $additionalParams = [])
2639
    {
2640
        $params = array_merge(
2641
            $additionalParams,
2642
            [
2643
                'api_key' => $this->apiKey,
2644
                'username' => $this->user->getUsername(),
2645
            ]
2646
        );
2647
2648
        return json_encode($params);
2649
    }
2650
}
2651