Passed
Push — 1.11.x ( 0cbedc...2beec7 )
by Angel Fernando Quiroz
08:41 queued 15s
created

Rest::viewMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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