Passed
Push — master ( 001816...b315eb )
by Julito
10:17
created

Rest::getUsersSubscribedToCourse()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 0
dl 0
loc 16
rs 9.9332
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\Message;
8
use Chamilo\CoreBundle\Entity\Session;
9
use Chamilo\CoreBundle\Entity\User;
10
use Chamilo\CoreBundle\Framework\Container;
11
use Chamilo\CourseBundle\Entity\CLpCategory;
12
use Chamilo\CourseBundle\Entity\CNotebook;
13
use Chamilo\CourseBundle\Repository\CNotebookRepository;
14
15
/**
16
 * Class RestApi.
17
 */
18
class Rest extends WebService
19
{
20
    public const SERVICE_NAME = 'MsgREST';
21
    public const EXTRA_FIELD_GCM_REGISTRATION = 'gcm_registration_id';
22
23
    public const GET_AUTH = 'authenticate';
24
    public const GET_USER_MESSAGES = 'user_messages';
25
    public const GET_USER_COURSES = 'user_courses';
26
    public const GET_USER_SESSIONS = 'user_sessions';
27
    public const GET_USERS_SUBSCRIBED_TO_COURSE = 'get_users_subscribed_to_course';
28
    public const GET_USER_MESSAGES_RECEIVED = 'user_messages_received';
29
    public const GET_USER_MESSAGES_SENT = 'user_messages_sent';
30
    public const POST_USER_MESSAGE_READ = 'user_message_read';
31
    public const POST_USER_MESSAGE_UNREAD = 'user_message_unread';
32
    public const SAVE_GCM_ID = 'gcm_id';
33
    public const GET_PROFILE = 'user_profile';
34
    public const GET_COURSE_INFO = 'course_info';
35
    public const GET_COURSE_DESCRIPTIONS = 'course_descriptions';
36
    public const GET_COURSE_DOCUMENTS = 'course_documents';
37
    public const GET_COURSE_ANNOUNCEMENTS = 'course_announcements';
38
    public const GET_COURSE_ANNOUNCEMENT = 'course_announcement';
39
    public const GET_COURSE_AGENDA = 'course_agenda';
40
    public const GET_COURSE_NOTEBOOKS = 'course_notebooks';
41
    public const GET_COURSE_FORUM_CATEGORIES = 'course_forumcategories';
42
    public const GET_COURSE_FORUM = 'course_forum';
43
    public const GET_COURSE_FORUM_THREAD = 'course_forumthread';
44
    public const GET_COURSE_LEARNPATHS = 'course_learnpaths';
45
    public const GET_COURSE_LEARNPATH = 'course_learnpath';
46
    public const GET_COURSE_LP_PROGRESS = 'course_lp_progress';
47
    public const SAVE_FORUM_POST = 'save_forum_post';
48
    public const SAVE_USER_MESSAGE = 'save_user_message';
49
    public const GET_MESSAGE_USERS = 'message_users';
50
    public const SAVE_COURSE_NOTEBOOK = 'save_course_notebook';
51
    public const SAVE_FORUM_THREAD = 'save_forum_thread';
52
    public const SAVE_COURSE = 'save_course';
53
    public const SAVE_USER = 'save_user';
54
    public const SAVE_USER_JSON = 'save_user_json';
55
    public const SUBSCRIBE_USER_TO_COURSE = 'subscribe_user_to_course';
56
    public const UNSUBSCRIBE_USER_FROM_COURSE = 'unsubscribe_user_from_course';
57
    public const EXTRAFIELD_GCM_ID = 'gcm_registration_id';
58
    public const DELETE_USER_MESSAGE = 'delete_user_message';
59
    public const SET_MESSAGE_READ = 'set_message_read';
60
    public const CREATE_CAMPUS = 'add_campus';
61
    public const EDIT_CAMPUS = 'edit_campus';
62
    public const DELETE_CAMPUS = 'delete_campus';
63
    public const SAVE_SESSION = 'save_session';
64
    public const GET_USERS = 'get_users';
65
    public const GET_COURSES = 'get_courses';
66
    public const GET_COURSES_FROM_EXTRA_FIELD = 'get_courses_from_extra_field';
67
    public const ADD_COURSES_SESSION = 'add_courses_session';
68
    public const ADD_USERS_SESSION = 'add_users_session';
69
    public const CREATE_SESSION_FROM_MODEL = 'create_session_from_model';
70
    public const SUBSCRIBE_USER_TO_SESSION_FROM_USERNAME = 'subscribe_user_to_session_from_username';
71
    public const GET_SESSION_FROM_EXTRA_FIELD = 'get_session_from_extra_field';
72
    public const UPDATE_USER_FROM_USERNAME = 'update_user_from_username';
73
    public const USERNAME_EXIST = 'username_exist';
74
    public const GET_COURSE_QUIZ_MDL_COMPAT = 'get_course_quiz_mdl_compat';
75
    public const UPDATE_USER_PAUSE_TRAINING = 'update_user_pause_training';
76
    public const DELETE_COURSE = 'delete_course';
77
78
    /**
79
     * @var Session
80
     */
81
    private $session;
82
83
    /**
84
     * @var Course
85
     */
86
    private $course;
87
88
    /**
89
     * Rest constructor.
90
     *
91
     * @param string $username
92
     * @param string $apiKey
93
     */
94
    public function __construct($username, $apiKey)
95
    {
96
        parent::__construct($username, $apiKey);
97
    }
98
99
    /**
100
     * @param string $username
101
     * @param string $apiKeyToValidate
102
     *
103
     * @throws Exception
104
     *
105
     * @return Rest
106
     */
107
    public static function validate($username, $apiKeyToValidate)
108
    {
109
        $apiKey = self::findUserApiKey($username, self::SERVICE_NAME);
110
111
        if ($apiKey != $apiKeyToValidate) {
112
            throw new Exception(get_lang('InvalidApiKey'));
113
        }
114
115
        return new self($username, $apiKey);
116
    }
117
118
    /**
119
     * Create the gcm_registration_id extra field for users.
120
     */
121
    public static function init()
122
    {
123
        $extraField = new ExtraField('user');
124
        $fieldInfo = $extraField->get_handler_field_info_by_field_variable(self::EXTRA_FIELD_GCM_REGISTRATION);
125
126
        if (empty($fieldInfo)) {
127
            $extraField->save(
128
                [
129
                    'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
130
                    'field_type' => ExtraField::FIELD_TYPE_TEXT,
131
                    'display_text' => self::EXTRA_FIELD_GCM_REGISTRATION,
132
                ]
133
            );
134
        }
135
    }
136
137
    /**
138
     * @param string $encoded
139
     *
140
     * @return array
141
     */
142
    public static function decodeParams($encoded)
143
    {
144
        return json_decode($encoded);
145
    }
146
147
    /**
148
     * Set the current course.
149
     *
150
     * @param int $id
151
     *
152
     * @throws Exception
153
     */
154
    public function setCourse($id)
155
    {
156
        if (!$id) {
157
            $this->course = null;
158
159
            return;
160
        }
161
162
        $course = api_get_course_entity($id);
163
164
        if (!$course) {
165
            throw new Exception(get_lang('NoCourse'));
166
        }
167
168
        $this->course = $course;
169
    }
170
171
    /**
172
     * Set the current session.
173
     *
174
     * @param int $id
175
     *
176
     * @throws Exception
177
     */
178
    public function setSession($id)
179
    {
180
        if (!$id) {
181
            $this->session = null;
182
183
            return;
184
        }
185
186
        $session = api_get_session_entity($id);
187
188
        if (!$session) {
189
            throw new Exception(get_lang('NoSession'));
190
        }
191
192
        $this->session = $session;
193
    }
194
195
    /**
196
     * @param string $registrationId
197
     *
198
     * @return bool
199
     */
200
    public function setGcmId($registrationId)
201
    {
202
        $registrationId = Security::remove_XSS($registrationId);
203
        $extraFieldValue = new ExtraFieldValue('user');
204
205
        return $extraFieldValue->save(
206
            [
207
                'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
208
                'value' => $registrationId,
209
                'item_id' => $this->user->getId(),
210
            ]
211
        );
212
    }
213
214
    public function processMessage(Message $message)
215
    {
216
        $illustrationRepo = Container::getIllustrationRepository();
217
        $hasAttachments = $message->getAttachments()->count() > 0;
218
        $attachmentList = [];
219
        if ($hasAttachments) {
220
            $repo = Container::getMessageAttachmentRepository();
221
            $attachments = $message->getAttachments();
222
            foreach ($attachments as $attachment) {
223
                $attachmentList[] = [
224
                    'file_source' => $repo->getResourceFileUrl($attachment),
225
                ];
226
            }
227
        }
228
229
        $picture = $illustrationRepo->getIllustrationUrl($message->getUserSender());
230
231
        return [
232
            'id' => $message->getId(),
233
            'title' => $message->getTitle(),
234
            'sender' => [
235
                'id' => $message->getUserSender()->getId(),
236
                'lastname' => $message->getUserSender()->getLastname(),
237
                'firstname' => $message->getUserSender()->getFirstname(),
238
                'completeName' => UserManager::formatUserFullName($message->getUserSender()),
239
                'pictureUri' => $picture,
240
            ],
241
            'sendDate' => $message->getSendDate()->format('Y-m-d H:i:s'),
242
            'content' => $message->getContent(),
243
            'hasAttachments' => $hasAttachments,
244
            'attachmentList' => $attachmentList,
245
            'url' => api_get_path(WEB_CODE_PATH).'messages/view_message.php?'
246
                .http_build_query(['type' => 1, 'id' => $message->getId()]),
247
        ];
248
    }
249
250
    /**
251
     * @param int $lastMessageId
252
     *
253
     * @return array
254
     */
255
    public function getUserMessages($lastMessageId = 0)
256
    {
257
        $lastMessages = MessageManager::getMessagesFromLastReceivedMessage($this->user->getId(), $lastMessageId);
258
        $messages = [];
259
        foreach ($lastMessages as $message) {
260
            $messages[] = $this->processMessage($message);
261
        }
262
263
        return $messages;
264
    }
265
266
    /**
267
     * @return array
268
     */
269
    public function getUserReceivedMessages()
270
    {
271
        $lastMessages = MessageManager::getReceivedMessages($this->user->getId(), 0);
272
        $messages = [];
273
        foreach ($lastMessages as $message) {
274
            $messages[] = $this->processMessage($message);
275
        }
276
277
        return $messages;
278
    }
279
280
    /**
281
     * @return array
282
     */
283
    public function getUserSentMessages()
284
    {
285
        $lastMessages = MessageManager::getSentMessages($this->user->getId(), 0);
286
        $messages = [];
287
288
        foreach ($lastMessages as $message) {
289
            $messages[] = $this->processMessage($message);
290
        }
291
292
        return $messages;
293
    }
294
295
    /**
296
     * Get the user courses.
297
     */
298
    public function getUserCourses($userId = 0): array
299
    {
300
        if (empty($userId)) {
301
            $userId = $this->user->getId();
302
        }
303
304
        $courses = CourseManager::get_courses_list_by_user_id($userId);
305
        $data = [];
306
307
        foreach ($courses as $courseInfo) {
308
            $course = api_get_course_entity($courseInfo['real_id']);
309
            $teachers = CourseManager::getTeacherListFromCourseCodeToString($course->getCode());
310
            $picturePath = CourseManager::getPicturePath($course, true)
311
                ?: Display::return_icon('session_default.png', null, null, null, null, true);
312
313
            $data[] = [
314
                'id' => $course->getId(),
315
                'title' => $course->getTitle(),
316
                'code' => $course->getCode(),
317
                //'directory' => $course->getDirectory(),
318
                'urlPicture' => $picturePath,
319
                'teachers' => $teachers,
320
                'isSpecial' => !empty($courseInfo['special_course']),
321
            ];
322
        }
323
324
        return $data;
325
    }
326
327
    /**
328
     * @throws Exception
329
     *
330
     * @return array
331
     */
332
    public function getCourseInfo()
333
    {
334
        $teachers = CourseManager::getTeacherListFromCourseCodeToString($this->course->getCode());
335
        $tools = CourseHome::get_tools_category(
336
            TOOL_STUDENT_VIEW,
337
            $this->course->getId(),
338
            $this->session ? $this->session->getId() : 0
339
        );
340
341
        return [
342
            'id' => $this->course->getId(),
343
            'title' => $this->course->getTitle(),
344
            'code' => $this->course->getCode(),
345
            //'directory' => $this->course->getDirectory(),
346
            'urlPicture' => CourseManager::getPicturePath($this->course, true),
347
            'teachers' => $teachers,
348
            'tools' => array_map(
349
                function ($tool) {
350
                    return ['type' => $tool['name']];
351
                },
352
                $tools
353
            ),
354
        ];
355
    }
356
357
    /**
358
     * Get the course descriptions.
359
     *
360
     * @throws Exception
361
     *
362
     * @return array
363
     */
364
    public function getCourseDescriptions()
365
    {
366
        $descriptions = CourseDescription::get_descriptions($this->course->getId());
367
        $results = [];
368
369
        /** @var CourseDescription $description */
370
        foreach ($descriptions as $description) {
371
            $results[] = [
372
                'id' => $description->get_description_type(),
373
                'title' => $description->get_title(),
374
                'content' => str_replace('src="/', 'src="'.api_get_path(WEB_PATH), $description->get_content()),
375
            ];
376
        }
377
378
        return $results;
379
    }
380
381
    /**
382
     * @param int $directoryId
383
     *
384
     * @throws Exception
385
     *
386
     * @return array
387
     */
388
    public function getCourseDocuments($directoryId = 0)
389
    {
390
        /** @var string $path */
391
        $path = '/';
392
        $sessionId = $this->session ? $this->session->getId() : 0;
393
394
        if ($directoryId) {
395
            $directory = DocumentManager::get_document_data_by_id(
396
                $directoryId,
397
                $this->course->getCode(),
398
                false,
399
                $sessionId
400
            );
401
402
            if (!$directory) {
403
                throw new Exception('NoDataAvailable');
404
            }
405
406
            $path = $directory['path'];
407
        }
408
409
        $courseInfo = api_get_course_info_by_id($this->course->getId());
410
        $documents = DocumentManager::getAllDocumentData(
411
            $courseInfo,
412
            $path,
413
            0,
414
            null,
415
            false,
416
            false,
417
            $sessionId
418
        );
419
        $results = [];
420
421
        if (!empty($documents)) {
422
            $webPath = api_get_path(WEB_CODE_PATH).'document/document.php?';
423
424
            /** @var array $document */
425
            foreach ($documents as $document) {
426
                if ('1' != $document['visibility']) {
427
                    continue;
428
                }
429
430
                $icon = 'file' == $document['filetype']
431
                    ? choose_image($document['path'])
432
                    : chooseFolderIcon($document['path']);
433
434
                $results[] = [
435
                    'id' => $document['id'],
436
                    'type' => $document['filetype'],
437
                    'title' => $document['title'],
438
                    'path' => $document['path'],
439
                    'url' => $webPath.http_build_query(
440
                        [
441
                            'username' => $this->user->getUsername(),
442
                            'api_key' => $this->apiKey,
443
                            'cidReq' => $this->course->getCode(),
444
                            'id_session' => $sessionId,
445
                            'gidReq' => 0,
446
                            'gradebook' => 0,
447
                            'origin' => '',
448
                            'action' => 'download',
449
                            'id' => $document['id'],
450
                        ]
451
                    ),
452
                    'icon' => $icon,
453
                    'size' => format_file_size($document['size']),
454
                ];
455
            }
456
        }
457
458
        return $results;
459
    }
460
461
    /**
462
     * @throws Exception
463
     *
464
     * @return array
465
     */
466
    public function getCourseAnnouncements()
467
    {
468
        $sessionId = $this->session ? $this->session->getId() : 0;
469
470
        $announcements = AnnouncementManager::getAnnouncements(
471
            null,
472
            null,
473
            false,
474
            null,
475
            null,
476
            null,
477
            null,
478
            null,
479
            0,
480
            $this->user->getId(),
481
            $this->course->getId(),
482
            $sessionId
483
        );
484
485
        $announcements = array_map(
486
            function ($announcement) {
487
                return [
488
                    'id' => (int) $announcement['id'],
489
                    'title' => strip_tags($announcement['title']),
490
                    'creatorName' => strip_tags($announcement['username']),
491
                    'date' => strip_tags($announcement['insert_date']),
492
                ];
493
            },
494
            $announcements
495
        );
496
497
        return $announcements;
498
    }
499
500
    /**
501
     * @param int $announcementId
502
     *
503
     * @throws Exception
504
     *
505
     * @return array
506
     */
507
    public function getCourseAnnouncement($announcementId)
508
    {
509
        $sessionId = $this->session ? $this->session->getId() : 0;
510
        $announcement = AnnouncementManager::getAnnouncementInfoById(
511
            $announcementId,
512
            $this->course->getId(),
513
            $this->user->getId()
514
        );
515
516
        if (!$announcement) {
517
            throw new Exception(get_lang('NoAnnouncement'));
518
        }
519
520
        return [
521
            'id' => $announcement['announcement']->getIid(),
522
            'title' => $announcement['announcement']->getTitle(),
523
            'creatorName' => UserManager::formatUserFullName($announcement['item_property']->getInsertUser()),
524
            'date' => api_convert_and_format_date(
525
                $announcement['item_property']->getInsertDate(),
526
                DATE_TIME_FORMAT_LONG_24H
527
            ),
528
            'content' => AnnouncementManager::parseContent(
529
                $this->user->getId(),
530
                $announcement['announcement']->getContent(),
531
                $this->course->getCode(),
532
                $sessionId
533
            ),
534
        ];
535
    }
536
537
    /**
538
     * @throws Exception
539
     *
540
     * @return array
541
     */
542
    public function getCourseAgenda()
543
    {
544
        $sessionId = $this->session ? $this->session->getId() : 0;
545
546
        $agenda = new Agenda(
547
            'course',
548
            $this->user->getId(),
549
            $this->course->getId(),
550
            $sessionId
551
        );
552
        $result = $agenda->parseAgendaFilter(null);
553
554
        $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
555
        $start->modify('first day of this month');
556
        $start->setTime(0, 0, 0);
557
        $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
558
        $end->modify('last day of this month');
559
        $end->setTime(23, 59, 59);
560
561
        $groupId = current($result['groups']);
562
        $userId = current($result['users']);
563
564
        $events = $agenda->getEvents(
565
            $start->getTimestamp(),
566
            $end->getTimestamp(),
567
            $this->course->getId(),
568
            $groupId,
569
            $userId,
570
            'array'
571
        );
572
573
        if (!is_array($events)) {
574
            return [];
575
        }
576
577
        $webPath = api_get_path(WEB_PATH);
578
579
        return array_map(
580
            function ($event) use ($webPath) {
581
                return [
582
                    'id' => (int) $event['unique_id'],
583
                    'title' => $event['title'],
584
                    'content' => str_replace('src="/', 'src="'.$webPath, $event['description']),
585
                    'startDate' => $event['start_date_localtime'],
586
                    'endDate' => $event['end_date_localtime'],
587
                    'isAllDay' => $event['allDay'] ? true : false,
588
                ];
589
            },
590
            $events
591
        );
592
    }
593
594
    /**
595
     * @throws Exception
596
     *
597
     * @return array
598
     */
599
    public function getCourseNotebooks()
600
    {
601
        $em = Database::getManager();
602
        /** @var CNotebookRepository $notebooksRepo */
603
        $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
604
        $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
605
606
        return array_map(
607
            function (CNotebook $notebook) {
608
                return [
609
                    'id' => $notebook->getIid(),
610
                    'title' => $notebook->getTitle(),
611
                    'description' => $notebook->getDescription(),
612
                    'creationDate' => api_format_date(
613
                        $notebook->getCreationDate()->getTimestamp()
614
                    ),
615
                    'updateDate' => api_format_date(
616
                        $notebook->getUpdateDate()->getTimestamp()
617
                    ),
618
                ];
619
            },
620
            $notebooks
621
        );
622
    }
623
624
    /**
625
     * @throws Exception
626
     *
627
     * @return array
628
     */
629
    public function getCourseForumCategories()
630
    {
631
        $sessionId = $this->session ? $this->session->getId() : 0;
632
        $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
633
634
        $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
635
        $categories = [];
636
        $includeGroupsForums = 'true' === api_get_setting('display_groups_forum_in_general_tool');
637
        $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
638
        $forums = [];
639
640
        foreach ($forumsFullData as $forumId => $forumInfo) {
641
            $forum = [
642
                'id' => (int) $forumInfo['iid'],
643
                'catId' => (int) $forumInfo['forum_category'],
644
                'title' => $forumInfo['forum_title'],
645
                'description' => $forumInfo['forum_comment'],
646
                'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
647
                'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval(
648
                    $forumInfo['number_of_threads']
649
                ) : 0,
650
                'lastPost' => null,
651
            ];
652
653
            $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId(), $sessionId);
654
655
            if ($lastPostInfo) {
656
                $forum['lastPost'] = [
657
                    'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
658
                    'user' => api_get_person_name(
659
                        $lastPostInfo['last_poster_firstname'],
660
                        $lastPostInfo['last_poster_lastname']
661
                    ),
662
                ];
663
            }
664
665
            $forums[] = $forum;
666
        }
667
668
        foreach ($categoriesFullData as $category) {
669
            $categoryForums = array_filter(
670
                $forums,
671
                function (array $forum) use ($category) {
672
                    if ($forum['catId'] != $category['cat_id']) {
673
                        return false;
674
                    }
675
676
                    return true;
677
                }
678
            );
679
680
            $categories[] = [
681
                'id' => (int) $category['iid'],
682
                'title' => $category['cat_title'],
683
                'catId' => (int) $category['cat_id'],
684
                'description' => $category['cat_comment'],
685
                'forums' => $categoryForums,
686
                'courseId' => $this->course->getId(),
687
            ];
688
        }
689
690
        return $categories;
691
    }
692
693
    /**
694
     * @param int $forumId
695
     *
696
     * @throws Exception
697
     *
698
     * @return array
699
     */
700
    public function getCourseForum($forumId)
701
    {
702
        $sessionId = $this->session ? $this->session->getId() : 0;
703
        $forumInfo = get_forums($forumId, $this->course->getCode(), true, $sessionId);
704
705
        if (!isset($forumInfo['iid'])) {
706
            throw new Exception(get_lang('NoForum'));
707
        }
708
709
        $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
710
        $forum = [
711
            'id' => $forumInfo['iid'],
712
            'title' => $forumInfo['forum_title'],
713
            'description' => $forumInfo['forum_comment'],
714
            'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
715
            'threads' => [],
716
        ];
717
718
        $threads = get_threads($forumInfo['iid'], $this->course->getId(), $sessionId);
719
720
        foreach ($threads as $thread) {
721
            $forum['threads'][] = [
722
                'id' => $thread['iid'],
723
                'title' => $thread['thread_title'],
724
                'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
725
                'numberOfReplies' => $thread['thread_replies'],
726
                'numberOfViews' => $thread['thread_views'],
727
                'author' => api_get_person_name($thread['firstname'], $thread['lastname']),
728
            ];
729
        }
730
731
        return $forum;
732
    }
733
734
    /**
735
     * @param int $forumId
736
     * @param int $threadId
737
     *
738
     * @return array
739
     */
740
    public function getCourseForumThread($forumId, $threadId)
741
    {
742
        $sessionId = $this->session ? $this->session->getId() : 0;
743
        $threadInfo = get_thread_information($forumId, $threadId, $sessionId);
744
745
        $thread = [
746
            'id' => intval($threadInfo['iid']),
747
            'cId' => intval($threadInfo['c_id']),
748
            'title' => $threadInfo['thread_title'],
749
            'forumId' => intval($threadInfo['forum_id']),
750
            'posts' => [],
751
        ];
752
753
        $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode(), true, $sessionId);
754
        $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
755
756
        foreach ($postsInfo as $postInfo) {
757
            $thread['posts'][] = [
758
                'id' => $postInfo['iid'],
759
                'title' => $postInfo['post_title'],
760
                'text' => $postInfo['post_text'],
761
                'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
762
                'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
763
                'parentId' => $postInfo['post_parent_id'],
764
            ];
765
        }
766
767
        return $thread;
768
    }
769
770
    /**
771
     * @return array
772
     */
773
    public function getUserProfile()
774
    {
775
        $illustrationRepo = Container::getIllustrationRepository();
776
        $url = $illustrationRepo->getIllustrationUrl($this->user);
777
778
        $result = [
779
            'pictureUri' => $url,
780
            'id' => $this->user->getId(),
781
            'status' => $this->user->getStatus(),
782
            'fullName' => UserManager::formatUserFullName($this->user),
783
            'username' => $this->user->getUsername(),
784
            'officialCode' => $this->user->getOfficialCode(),
785
            'phone' => $this->user->getPhone(),
786
            'extra' => [],
787
        ];
788
789
        $fieldValue = new ExtraFieldValue('user');
790
        $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
791
792
        foreach ($extraInfo as $extra) {
793
            /** @var ExtraFieldValues $extraValue */
794
            $extraValue = $extra['value'];
795
            $result['extra'][] = [
796
                'title' => $extraValue->getField()->getDisplayText(true),
797
                'value' => $extraValue->getValue(),
798
            ];
799
        }
800
801
        return $result;
802
    }
803
804
    public function getCourseLpProgress()
805
    {
806
        $sessionId = $this->session ? $this->session->getId() : 0;
807
        $userId = $this->user->getId();
808
809
        /*$sessionId = $this->session ? $this->session->getId() : 0;
810
        $courseId = $this->course->getId();*/
811
812
        $result = Tracking::getCourseLpProgress($userId, $sessionId);
813
814
        return [$result];
815
    }
816
817
    /**
818
     * @throws Exception
819
     *
820
     * @return array
821
     */
822
    public function getCourseLearnPaths()
823
    {
824
        $sessionId = $this->session ? $this->session->getId() : 0;
825
        $categoriesTempList = learnpath::getCategories($this->course->getId());
826
827
        $categoryNone = new CLpCategory();
828
        $categoryNone->setName(get_lang('WithOutCategory'));
829
        $categoryNone->setPosition(0);
830
831
        $categories = array_merge([$categoryNone], $categoriesTempList);
832
        $categoryData = [];
833
        /** @var CLpCategory $category */
834
        foreach ($categories as $category) {
835
            $learnPathList = new LearnpathList(
836
                $this->user->getId(),
837
                api_get_course_info($this->course->getCode()),
838
                $sessionId,
839
                null,
840
                false,
841
                $category->getIid()
842
            );
843
844
            $flatLpList = $learnPathList->get_flat_list();
845
846
            if (empty($flatLpList)) {
847
                continue;
848
            }
849
850
            $listData = [];
851
852
            foreach ($flatLpList as $lpId => $lpDetails) {
853
                if (0 == $lpDetails['lp_visibility']) {
854
                    continue;
855
                }
856
857
                if (!learnpath::is_lp_visible_for_student(
858
                    $lpId,
859
                    $this->user->getId(),
860
                    $this->course,
861
                    $this->session
862
                )) {
863
                    continue;
864
                }
865
866
                $timeLimits = false;
867
868
                // This is an old LP (from a migration 1.8.7) so we do nothing
869
                if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
870
                    $timeLimits = false;
871
                }
872
873
                // Checking if expired_on is ON
874
                if (!empty($lpDetails['expired_on'])) {
875
                    $timeLimits = true;
876
                }
877
878
                if ($timeLimits) {
879
                    if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
880
                        $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
881
                        $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
882
                        $now = time();
883
                        $isActiveTime = false;
884
885
                        if ($now > $startTime && $endTime > $now) {
886
                            $isActiveTime = true;
887
                        }
888
889
                        if (!$isActiveTime) {
890
                            continue;
891
                        }
892
                    }
893
                }
894
895
                $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
896
897
                $listData[] = [
898
                    'id' => $lpId,
899
                    'title' => Security::remove_XSS($lpDetails['lp_name']),
900
                    'progress' => $progress,
901
                    'url' => api_get_path(WEB_CODE_PATH).'webservices/api/v2.php?'.http_build_query(
902
                        [
903
                            'hash' => $this->encodeParams(
904
                                [
905
                                    'action' => 'course_learnpath',
906
                                    'lp_id' => $lpId,
907
                                    'course' => $this->course->getId(),
908
                                    'session' => $sessionId,
909
                                ]
910
                            ),
911
                        ]
912
                    ),
913
                ];
914
            }
915
916
            if (empty($listData)) {
917
                continue;
918
            }
919
920
            $categoryData[] = [
921
                'id' => $category->getId(),
922
                'name' => $category->getName(),
923
                'learnpaths' => $listData,
924
            ];
925
        }
926
927
        return $categoryData;
928
    }
929
930
    /**
931
     * Start login for a user. Then make a redirect to show the learnpath.
932
     *
933
     * @param int $lpId
934
     */
935
    public function showLearningPath($lpId)
936
    {
937
        $loggedUser['user_id'] = $this->user->getId();
938
        $loggedUser['status'] = $this->user->getStatus();
939
        $loggedUser['uidReset'] = true;
940
        $sessionId = $this->session ? $this->session->getId() : 0;
941
942
        ChamiloSession::write('_user', $loggedUser);
943
        Login::init_user($this->user->getId(), true);
944
945
        $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.http_build_query(
946
            [
947
                'cidReq' => $this->course->getCode(),
948
                'id_session' => $sessionId,
949
                'gidReq' => 0,
950
                'gradebook' => 0,
951
                'origin' => '',
952
                'action' => 'view',
953
                'lp_id' => (int) $lpId,
954
                'isStudentView' => 'true',
955
            ]
956
        );
957
958
        header("Location: $url");
959
        exit;
960
    }
961
962
    /**
963
     * @param int $forumId
964
     *
965
     * @return array
966
     */
967
    public function saveForumPost(array $postValues, $forumId)
968
    {
969
        $forum = get_forums($forumId, $this->course->getCode());
970
        store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
971
972
        return [
973
            'registered' => true,
974
        ];
975
    }
976
977
    /**
978
     * Get the list of sessions for current user.
979
     *
980
     * @return array the sessions list
981
     */
982
    public function getUserSessions()
983
    {
984
        $data = [];
985
        $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
986
987
        foreach ($sessionsByCategory as $category) {
988
            $categorySessions = [];
989
990
            foreach ($category['sessions'] as $sessions) {
991
                $sessionCourses = [];
992
993
                foreach ($sessions['courses'] as $course) {
994
                    $courseInfo = api_get_course_info_by_id($course['real_id']);
995
                    $teachers = SessionManager::getCoachesByCourseSessionToString(
996
                        $sessions['session_id'],
997
                        $course['real_id']
998
                    );
999
1000
                    $sessionCourses[] = [
1001
                        'id' => $courseInfo['real_id'],
1002
                        'title' => $courseInfo['title'],
1003
                        'code' => $courseInfo['code'],
1004
                        'directory' => $courseInfo['directory'],
1005
                        'pictureUrl' => $courseInfo['course_image_large'],
1006
                        'urlPicture' => $courseInfo['course_image_large'],
1007
                        'teachers' => $teachers,
1008
                    ];
1009
                }
1010
1011
                $sessionBox = Display::getSessionTitleBox($sessions['session_id']);
1012
1013
                $categorySessions[] = [
1014
                    'name' => $sessionBox['title'],
1015
                    'id' => $sessions['session_id'],
1016
                    'date' => $sessionBox['dates'],
1017
                    'duration' => isset($sessionBox['duration']) ? $sessionBox['duration'] : null,
1018
                    'courses' => $sessionCourses,
1019
                ];
1020
            }
1021
1022
            $data[] = [
1023
                'id' => $category['session_category']['id'],
1024
                'name' => $category['session_category']['name'],
1025
                'sessions' => $categorySessions,
1026
            ];
1027
        }
1028
1029
        return $data;
1030
    }
1031
1032
    public function getUsersSubscribedToCourse()
1033
    {
1034
        $users = CourseManager::get_user_list_from_course_code($this->course->getCode());
1035
1036
        $userList = [];
1037
        foreach ($users as $user) {
1038
            $userList[] = [
1039
                'user_id' => $user['user_id'],
1040
                'username' => $user['username'],
1041
                'firstname' => $user['firstname'],
1042
                'lastname' => $user['lastname'],
1043
                'status_rel' => $user['status_rel'],
1044
            ];
1045
        }
1046
1047
        return $userList;
1048
    }
1049
    /**
1050
     * @param string $subject
1051
     * @param string $text
1052
     *
1053
     * @return array
1054
     */
1055
    public function saveUserMessage($subject, $text, array $receivers)
1056
    {
1057
        foreach ($receivers as $userId) {
1058
            MessageManager::send_message($userId, $subject, $text);
1059
        }
1060
1061
        return [
1062
            'sent' => true,
1063
        ];
1064
    }
1065
1066
    /**
1067
     * @param string $search
1068
     *
1069
     * @return array
1070
     */
1071
    public function getMessageUsers($search)
1072
    {
1073
        $repo = UserManager::getRepository();
1074
1075
        $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
1076
        $showEmail = 'true' === api_get_setting('show_email_addresses');
1077
        $data = [];
1078
1079
        /** @var User $user */
1080
        foreach ($users as $user) {
1081
            $userName = UserManager::formatUserFullName($user);
1082
1083
            if ($showEmail) {
1084
                $userName .= " ({$user->getEmail()})";
1085
            }
1086
1087
            $data[] = [
1088
                'id' => $user->getId(),
1089
                'name' => $userName,
1090
            ];
1091
        }
1092
1093
        return $data;
1094
    }
1095
1096
    /**
1097
     * @param string $title
1098
     * @param string $text
1099
     *
1100
     * @return array
1101
     */
1102
    public function saveCourseNotebook($title, $text)
1103
    {
1104
        $values = ['note_title' => $title, 'note_comment' => $text];
1105
        $sessionId = $this->session ? $this->session->getId() : 0;
1106
1107
        $noteBookId = NotebookManager::save_note(
1108
            $values,
1109
            $this->user->getId(),
1110
            $this->course->getId(),
1111
            $sessionId
1112
        );
1113
1114
        return [
1115
            'registered' => $noteBookId,
1116
        ];
1117
    }
1118
1119
    /**
1120
     * @param int $forumId
1121
     *
1122
     * @return array
1123
     */
1124
    public function saveForumThread(array $values, $forumId)
1125
    {
1126
        $sessionId = $this->session ? $this->session->getId() : 0;
1127
        $forum = get_forums($forumId, $this->course->getCode(), true, $sessionId);
1128
        $courseInfo = api_get_course_info($this->course->getCode());
1129
        $thread = saveThread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
1130
1131
        return [
1132
            'registered' => $thread->getIid(),
1133
        ];
1134
    }
1135
1136
    /**
1137
     * @return array
1138
     */
1139
    public function getUsersCampus(array $params)
1140
    {
1141
        $conditions = [
1142
            'status' => $params['status'],
1143
        ];
1144
        $idCampus = $params['id_campus'];
1145
        $users = UserManager::get_user_list($conditions, ['firstname'], false, false, $idCampus);
1146
        $list = [];
1147
        foreach ($users as $item) {
1148
            $listTemp = [
1149
                'id' => $item['user_id'],
1150
                'firstname' => $item['firstname'],
1151
                'lastname' => $item['lastname'],
1152
                'email' => $item['email'],
1153
            ];
1154
            $list[] = $listTemp;
1155
        }
1156
1157
        return $list;
1158
    }
1159
1160
    /**
1161
     * @return array
1162
     */
1163
    public function getCoursesCampus(array $params)
1164
    {
1165
        $idCampus = $params['id_campus'];
1166
1167
        return CourseManager::get_courses_list(
1168
            0, //offset
1169
            0, //howMany
1170
            1, //$orderby = 1
1171
            'ASC',
1172
            -1, //visibility
1173
            null,
1174
            $idCampus, //$urlId
1175
            true //AlsoSearchCode
1176
        );
1177
1178
    }
1179
1180
    /**
1181
     * @return array
1182
     */
1183
    public function addSession(array $params)
1184
    {
1185
        $name = $params['name'];
1186
        $coach_username = (int) $params['coach_username'];
1187
        $startDate = $params['access_start_date'];
1188
        $endDate = $params['access_end_date'];
1189
        $displayStartDate = $startDate;
1190
        $displayEndDate = $endDate;
1191
        $description = $params['description'];
1192
        $idUrlCampus = $params['id_campus'];
1193
        $extraFields = isset($params['extra']) ? $params['extra'] : [];
1194
1195
        $return = SessionManager::create_session(
1196
            $name,
1197
            $startDate,
1198
            $endDate,
1199
            $displayStartDate,
1200
            $displayEndDate,
1201
            null,
1202
            null,
1203
            $coach_username,
1204
            null,
1205
            1,
1206
            false,
1207
            null,
1208
            $description,
1209
            1,
1210
            $extraFields,
1211
            null,
1212
            false,
1213
            $idUrlCampus
1214
        );
1215
1216
        if ($return) {
1217
            $out = [
1218
                'status' => true,
1219
                'message' => get_lang('ANewSessionWasCreated'),
1220
                'id_session' => $return,
1221
            ];
1222
        } else {
1223
            $out = [
1224
                'status' => false,
1225
                'message' => get_lang('ErrorOccurred'),
1226
            ];
1227
        }
1228
1229
        return $out;
1230
    }
1231
1232
    public function addCourse(array $courseParam): array
1233
    {
1234
        $idCampus = isset($courseParam['id_campus']) ? $courseParam['id_campus'] : 1;
1235
        $title = isset($courseParam['title']) ? $courseParam['title'] : '';
1236
        $wantedCode = isset($courseParam['wanted_code']) ? $courseParam['wanted_code'] : null;
1237
        $diskQuota = isset($courseParam['disk_quota']) ? $courseParam['disk_quota'] : '100';
1238
        $visibility = isset($courseParam['visibility']) ? (int) $courseParam['visibility'] : null;
1239
        $removeCampusId = $courseParam['remove_campus_id_from_wanted_code'] ?? 0;
1240
        $language = $courseParam['language'] ?? '';
1241
1242
        if (isset($courseParam['visibility'])) {
1243
            if ($courseParam['visibility'] &&
1244
                $courseParam['visibility'] >= 0 &&
1245
                $courseParam['visibility'] <= 3
1246
            ) {
1247
                $visibility = (int) $courseParam['visibility'];
1248
            }
1249
        }
1250
1251
        $params = [];
1252
        $params['title'] = $title;
1253
        $params['wanted_code'] = 'CAMPUS_'.$idCampus.'_'.$wantedCode;
1254
        if (1 === (int) $removeCampusId) {
1255
            $params['wanted_code'] = $wantedCode;
1256
        }
1257
        $params['user_id'] = $this->user->getId();
1258
        $params['visibility'] = $visibility;
1259
        $params['disk_quota'] = $diskQuota;
1260
        $params['course_language'] = $language;
1261
1262
        foreach ($courseParam as $key => $value) {
1263
            if (substr($key, 0, 6) === 'extra_') { //an extra field
1264
                $params[$key] = $value;
1265
            }
1266
        }
1267
1268
        $courseInfo = CourseManager::create_course($params, $params['user_id'], $idCampus);
1269
1270
        $results = [];
1271
        if (!empty($courseInfo)) {
1272
            $results['status'] = true;
1273
            $results['code_course'] = $courseInfo['code'];
1274
            $results['title_course'] = $courseInfo['title'];
1275
            $extraFieldValues = new ExtraFieldValue('course');
1276
            $extraFields = $extraFieldValues->getAllValuesByItem($courseInfo['real_id']);
1277
            $results['extra_fields'] = $extraFields;
1278
            $results['message'] = sprintf(get_lang('CourseXAdded'), $courseInfo['code']);
1279
        } else {
1280
            $results['status'] = false;
1281
            $results['message'] = get_lang('CourseCreationFailed');
1282
        }
1283
1284
        return $results;
1285
    }
1286
1287
    /**
1288
     * @param $userParam
1289
     *
1290
     * @throws Exception
1291
     *
1292
     * @return array
1293
     */
1294
    public function addUser($userParam)
1295
    {
1296
        $firstName = $userParam['firstname'];
1297
        $lastName = $userParam['lastname'];
1298
        $status = $userParam['status'];
1299
        $email = $userParam['email'];
1300
        $loginName = $userParam['loginname'];
1301
        $password = $userParam['password'];
1302
1303
        $official_code = '';
1304
        $language = '';
1305
        $phone = '';
1306
        $picture_uri = '';
1307
        $auth_source = $userParam['auth_source'] ?? PLATFORM_AUTH_SOURCE;
1308
        $expiration_date = '';
1309
        $active = 1;
1310
        $hr_dept_id = 0;
1311
1312
        $original_user_id_name = $userParam['original_user_id_name'];
1313
        $original_user_id_value = $userParam['original_user_id_value'];
1314
1315
        $extra_list = isset($userParam['extra']) ? $userParam['extra'] : [];
1316
        if (isset($userParam['language'])) {
1317
            $language = $userParam['language'];
1318
        }
1319
        if (isset($userParam['phone'])) {
1320
            $phone = $userParam['phone'];
1321
        }
1322
        if (isset($userParam['expiration_date'])) {
1323
            $expiration_date = $userParam['expiration_date'];
1324
        }
1325
1326
        // Default language.
1327
        if (empty($language)) {
1328
            $language = api_get_setting('platformLanguage');
1329
        }
1330
1331
        // First check wether the login already exists.
1332
        if (!UserManager::is_username_available($loginName)) {
1333
            throw new Exception(get_lang('UserNameNotAvailable'));
1334
        }
1335
1336
        $userId = UserManager::create_user(
1337
            $firstName,
1338
            $lastName,
1339
            $status,
1340
            $email,
1341
            $loginName,
1342
            $password,
1343
            $official_code,
1344
            $language,
1345
            $phone,
1346
            $picture_uri,
1347
            $auth_source,
1348
            $expiration_date,
1349
            $active,
1350
            $hr_dept_id
1351
        );
1352
1353
        if (empty($userId)) {
1354
            throw new Exception(get_lang('UserNotRegistered'));
1355
        }
1356
1357
        if (api_is_multiple_url_enabled()) {
1358
            if (-1 != api_get_current_access_url_id()) {
1359
                UrlManager::add_user_to_url(
1360
                    $userId,
1361
                    api_get_current_access_url_id()
1362
                );
1363
            } else {
1364
                UrlManager::add_user_to_url($userId, 1);
1365
            }
1366
        } else {
1367
            // We add by default the access_url_user table with access_url_id = 1
1368
            UrlManager::add_user_to_url($userId, 1);
1369
        }
1370
1371
        // Save new field label into user_field table.
1372
        UserManager::create_extra_field(
1373
            $original_user_id_name,
1374
            1,
1375
            $original_user_id_name,
1376
            ''
1377
        );
1378
        // Save the external system's id into user_field_value table.
1379
        UserManager::update_extra_field_value(
1380
            $userId,
1381
            $original_user_id_name,
1382
            $original_user_id_value
1383
        );
1384
1385
        if (is_array($extra_list) && count($extra_list) > 0) {
1386
            foreach ($extra_list as $extra) {
1387
                $extra_field_name = $extra['field_name'];
1388
                $extra_field_value = $extra['field_value'];
1389
                // Save new field label into user_field table.
1390
                UserManager::create_extra_field(
1391
                    $extra_field_name,
1392
                    1,
1393
                    $extra_field_name,
1394
                    ''
1395
                );
1396
                // Save the external system's id into user_field_value table.
1397
                UserManager::update_extra_field_value(
1398
                    $userId,
1399
                    $extra_field_name,
1400
                    $extra_field_value
1401
                );
1402
            }
1403
        }
1404
1405
        return [$userId];
1406
    }
1407
1408
    /**
1409
     * Subscribe User to Course.
1410
     *
1411
     * @param array $params
1412
     *
1413
     * @return array
1414
     */
1415
    public function subscribeUserToCourse($params)
1416
    {
1417
        $course_id = $params['course_id'];
1418
        $course_code = $params['course_code'];
1419
        $user_id = $params['user_id'];
1420
        $status = $params['status'] ?? STUDENT;
1421
        if (!$course_id && !$course_code) {
1422
            return [false];
1423
        }
1424
        if (!$course_code) {
1425
            $course_code = CourseManager::get_course_code_from_course_id($course_id);
1426
        }
1427
1428
        if (CourseManager::subscribeUser($user_id, $course_code, $status, 0, 0, false)) {
1429
            return [true];
1430
        }
1431
1432
        return [false];
1433
    }
1434
1435
    public function unSubscribeUserToCourse(array $params): array
1436
    {
1437
        $courseId = $params['course_id'];
1438
        $courseCode = $params['course_code'];
1439
        $userId = $params['user_id'];
1440
1441
        if (!$courseId && !$courseCode) {
1442
            return [false];
1443
        }
1444
1445
        if (!$courseCode) {
1446
            $courseCode = CourseManager::get_course_code_from_course_id($courseId);
1447
        }
1448
1449
        if (CourseManager::unsubscribe_user($userId, $courseCode)) {
1450
            return [true];
1451
        }
1452
1453
        return [false];
1454
    }
1455
1456
    public function deleteUserMessage($messageId, $messageType)
1457
    {
1458
        if ("sent" === $messageType) {
1459
            return MessageManager::delete_message_by_user_sender($this->user->getId(), $messageId);
1460
        } else {
1461
            return MessageManager::delete_message_by_user_receiver($this->user->getId(), $messageId);
1462
        }
1463
    }
1464
1465
    public function setMessageRead($messageId)
1466
    {
1467
        MessageManager::update_message($this->user->getId(), $messageId);
1468
    }
1469
1470
    /**
1471
     * Add Campus Virtual.
1472
     *
1473
     * @param array Params Campus
1474
     *
1475
     * @return array
1476
     */
1477
    public function createCampusURL($params)
1478
    {
1479
        $urlCampus = Security::remove_XSS($params['url']);
1480
        $description = Security::remove_XSS($params['description']);
1481
        $active = isset($params['active']) ? (int) $params['active'] : 0;
1482
1483
        if ('/' == substr($urlCampus, strlen($urlCampus) - 1, strlen($urlCampus))) {
1484
            $url = UrlManager::add($urlCampus, $description, $active, true);
1485
        } else {
1486
            $url = UrlManager::add($urlCampus.'/', $description, $active, true);
1487
        }
1488
1489
        if (null === $url) {
1490
            return [
1491
                'status' => false,
1492
                'id_campus' => 0,
1493
            ];
1494
        }
1495
1496
        return [
1497
            'status' => true,
1498
            'id_campus' => $url->getId(),
1499
        ];
1500
    }
1501
1502
    /**
1503
     * Edit Campus Virtual.
1504
     *
1505
     * @param array Params Campus
1506
     *
1507
     * @return array
1508
     */
1509
    public function editCampusURL($params)
1510
    {
1511
        $urlCampus = Security::remove_XSS($params['url']);
1512
        $description = Security::remove_XSS($params['description']);
1513
1514
        $active = isset($params['active']) ? intval($params['active']) : 0;
1515
        $url_id = isset($params['id']) ? intval($params['id']) : 0;
1516
1517
        if (!empty($url_id)) {
1518
            //we can't change the status of the url with id=1
1519
            if (1 == $url_id) {
1520
                $active = 1;
1521
            }
1522
            //checking url
1523
            if ('/' == substr($urlCampus, strlen($urlCampus) - 1, strlen($urlCampus))) {
1524
                UrlManager::update($url_id, $urlCampus, $description, $active);
1525
            } else {
1526
                UrlManager::update($url_id, $urlCampus.'/', $description, $active);
1527
            }
1528
1529
            return [true];
1530
        }
1531
1532
        return [false];
1533
    }
1534
1535
    /**
1536
     * Delete Campus Virtual.
1537
     *
1538
     * @param array Params Campus
1539
     *
1540
     * @return array
1541
     */
1542
    public function deleteCampusURL($params)
1543
    {
1544
        $url_id = isset($params['id']) ? intval($params['id']) : 0;
1545
1546
        $result = UrlManager::delete($url_id);
1547
        if ($result) {
1548
            return [
1549
                'status' => true,
1550
                'message' => get_lang('URLDeleted'),
1551
            ];
1552
        } else {
1553
            return [
1554
                'status' => false,
1555
                'message' => get_lang('Error'),
1556
            ];
1557
        }
1558
    }
1559
1560
    /**
1561
     * @throws Exception
1562
     *
1563
     * @return array
1564
     */
1565
    public function addCoursesSession(array $params)
1566
    {
1567
        $sessionId = $params['id_session'];
1568
        $courseList = $params['list_courses'];
1569
        $importAssignments = isset($params['import_assignments']) ? 1 === (int) $params['import_assignments'] : false;
1570
1571
        $result = SessionManager::add_courses_to_session(
1572
            $sessionId,
1573
            $courseList,
1574
            true,
1575
            false,
1576
            false,
1577
            $importAssignments
1578
        );
1579
1580
        if ($result) {
1581
            return [
1582
                'status' => $result,
1583
                'message' => get_lang('Updated'),
1584
            ];
1585
        }
1586
1587
        return [
1588
                'status' => $result,
1589
                'message' => get_lang('ErrorOccurred'),
1590
            ];
1591
    }
1592
1593
    /**
1594
     * @return array
1595
     */
1596
    public function addUsersSession(array $params)
1597
    {
1598
        $sessionId = $params['id_session'];
1599
        $userList = $params['list_users'];
1600
1601
        if (!is_array($userList)) {
1602
            $userList = [];
1603
        }
1604
1605
        SessionManager::subscribeUsersToSession(
1606
            $sessionId,
1607
            $userList,
1608
            null,
1609
            false
1610
        );
1611
1612
        return [
1613
            'status' => true,
1614
            'message' => get_lang('UsersAdded'),
1615
        ];
1616
    }
1617
1618
    /**
1619
     * Creates a session from a model session.
1620
     *
1621
     * @param $modelSessionId
1622
     * @param $sessionName
1623
     * @param $startDate
1624
     * @param $endDate
1625
     *
1626
     * @throws Exception
1627
     *
1628
     * @return int, the id of the new session
1629
     */
1630
    public function createSessionFromModel($modelSessionId, $sessionName, $startDate, $endDate, array $extraFields = [])
1631
    {
1632
        if (empty($modelSessionId) || empty($sessionName) || empty($startDate) || empty($endDate)) {
1633
            throw new Exception(get_lang('NoData'));
1634
        }
1635
1636
        if (!SessionManager::isValidId($modelSessionId)) {
1637
            throw new Exception(get_lang('ModelSessionDoesNotExist'));
1638
        }
1639
1640
        $modelSession = SessionManager::fetch($modelSessionId);
1641
1642
        $modelSession['accessUrlId'] = 1;
1643
        if (api_is_multiple_url_enabled()) {
1644
            if (-1 != api_get_current_access_url_id()) {
1645
                $modelSession['accessUrlId'] = api_get_current_access_url_id();
1646
            }
1647
        }
1648
1649
        $newSessionId = SessionManager::create_session(
1650
            $sessionName,
1651
            $startDate,
1652
            $endDate,
1653
            $startDate,
1654
            $endDate,
1655
            $startDate,
1656
            $endDate,
1657
            $modelSession['id_coach'],
1658
            $modelSession['session_category_id'],
1659
            $modelSession['visibility'],
1660
            false,
1661
            $modelSession['duration'],
1662
            $modelSession['description'],
1663
            $modelSession['show_description'],
1664
            $extraFields,
1665
            $modelSession['session_admin_id'],
1666
            $modelSession['send_subscription_notification'],
1667
            $modelSession['accessUrlId']
1668
        );
1669
1670
        if (empty($newSessionId)) {
1671
            throw new Exception(get_lang('SessionNotRegistered'));
1672
        }
1673
1674
        if (is_string($newSessionId)) {
1675
            throw new Exception($newSessionId);
1676
        }
1677
1678
        $promotionId = $modelSession['promotion_id'];
1679
        if ($promotionId) {
1680
            $sessionList = array_keys(SessionManager::get_all_sessions_by_promotion($promotionId));
1681
            $sessionList[] = $newSessionId;
1682
            SessionManager::subscribe_sessions_to_promotion($modelSession['promotion_id'], $sessionList);
1683
        }
1684
1685
        $modelExtraFields = [];
1686
        $fields = SessionManager::getFilteredExtraFields($modelSessionId);
1687
        if (is_array($fields) and !empty($fields)) {
1688
            foreach ($fields as $field) {
1689
                $modelExtraFields[$field['variable']] = $field['value'];
1690
            }
1691
        }
1692
        $allExtraFields = array_merge($modelExtraFields, $extraFields);
1693
        foreach ($allExtraFields as $name => $value) {
1694
            // SessionManager::update_session_extra_field_value returns false when no row is changed,
1695
            // which can happen since extra field values are initialized by SessionManager::create_session
1696
            // therefore we do not throw an exception when false is returned
1697
            SessionManager::update_session_extra_field_value($newSessionId, $name, $value);
1698
        }
1699
1700
        $courseList = array_keys(SessionManager::get_course_list_by_session_id($modelSessionId));
1701
        if (is_array($courseList)
1702
            && !empty($courseList)
1703
            && !SessionManager::add_courses_to_session($newSessionId, $courseList)) {
1704
            throw new Exception(get_lang('CoursesNotAddedToSession'));
1705
        }
1706
1707
        if (api_is_multiple_url_enabled()) {
1708
            if (-1 != api_get_current_access_url_id()) {
1709
                UrlManager::add_session_to_url(
1710
                    $newSessionId,
1711
                    api_get_current_access_url_id()
1712
                );
1713
            } else {
1714
                UrlManager::add_session_to_url($newSessionId, 1);
1715
            }
1716
        } else {
1717
            UrlManager::add_session_to_url($newSessionId, 1);
1718
        }
1719
1720
        return $newSessionId;
1721
    }
1722
1723
    /**
1724
     * subscribes a user to a session.
1725
     *
1726
     * @param int    $sessionId the session id
1727
     * @param string $loginName the user's login name
1728
     *
1729
     * @throws Exception
1730
     *
1731
     * @return boolean, whether it worked
1732
     */
1733
    public function subscribeUserToSessionFromUsername($sessionId, $loginName)
1734
    {
1735
        if (!SessionManager::isValidId($sessionId)) {
1736
            throw new Exception(get_lang('SessionNotFound'));
1737
        }
1738
1739
        $userId = UserManager::get_user_id_from_username($loginName);
1740
        if (false === $userId) {
1741
            throw new Exception(get_lang('UserNotFound'));
1742
        }
1743
1744
        $subscribed = SessionManager::subscribeUsersToSession(
1745
            $sessionId,
1746
            [$userId],
1747
            SESSION_VISIBLE_READ_ONLY,
1748
            false
1749
        );
1750
        if (!$subscribed) {
1751
            throw new Exception(get_lang('UserNotSubscribed'));
1752
        }
1753
1754
        return true;
1755
    }
1756
1757
    /**
1758
     * finds the session which has a specific value in a specific extra field.
1759
     *
1760
     * @param $fieldName
1761
     * @param $fieldValue
1762
     *
1763
     * @throws Exception when no session matched or more than one session matched
1764
     *
1765
     * @return int, the matching session id
1766
     */
1767
    public function getSessionFromExtraField($fieldName, $fieldValue)
1768
    {
1769
        // find sessions that that have value in field
1770
        $valueModel = new ExtraFieldValue('session');
1771
        $sessionIdList = $valueModel->get_item_id_from_field_variable_and_field_value(
1772
            $fieldName,
1773
            $fieldValue,
1774
            false,
1775
            false,
1776
            true
1777
        );
1778
1779
        // throw if none found
1780
        if (empty($sessionIdList)) {
1781
            throw new Exception(get_lang('NoSessionMatched'));
1782
        }
1783
1784
        // throw if more than one found
1785
        if (count($sessionIdList) > 1) {
1786
            throw new Exception(get_lang('MoreThanOneSessionMatched'));
1787
        }
1788
1789
        // return sessionId
1790
        return intval($sessionIdList[0]['item_id']);
1791
    }
1792
1793
    /**
1794
     * updates a user identified by its login name.
1795
     *
1796
     * @param array $parameters
1797
     *
1798
     * @throws Exception on failure
1799
     *
1800
     * @return boolean, true on success
1801
     */
1802
    public function updateUserFromUserName($parameters)
1803
    {
1804
        // find user
1805
        $userId = null;
1806
        if (!is_array($parameters) || empty($parameters)) {
1807
            throw new Exception('NoData');
1808
        }
1809
        foreach ($parameters as $name => $value) {
1810
            if ('loginname' === strtolower($name)) {
1811
                $userId = UserManager::get_user_id_from_username($value);
1812
                if (false === $userId) {
1813
                    throw new Exception(get_lang('UserNotFound'));
1814
                }
1815
                break;
1816
            }
1817
        }
1818
        if (is_null($userId)) {
1819
            throw new Exception(get_lang('NoData'));
1820
        }
1821
        $user = api_get_user_entity($userId);
1822
        if (empty($user)) {
1823
            throw new Exception(get_lang('CouldNotLoadUser'));
1824
        }
1825
1826
        // tell the world we are about to update a user
1827
        $hook = HookUpdateUser::create();
1828
        if (!empty($hook)) {
1829
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE);
1830
        }
1831
1832
        // apply submitted modifications
1833
        foreach ($parameters as $name => $value) {
1834
            switch (strtolower($name)) {
1835
                case 'email':
1836
                    $user->setEmail($value);
1837
                    break;
1838
                case 'enabled':
1839
                    $user->setEnabled($value);
1840
                    break;
1841
                case 'lastname':
1842
                    $user->setLastname($value);
1843
                    break;
1844
                case 'firstname':
1845
                    $user->setFirstname($value);
1846
                    break;
1847
                case 'phone':
1848
                    $user->setPhone($value);
1849
                    break;
1850
                case 'address':
1851
                    $user->setAddress($value);
1852
                    break;
1853
                case 'roles':
1854
                    $user->setRoles($value);
1855
                    break;
1856
                case 'profile_completed':
1857
                    $user->setProfileCompleted($value);
1858
                    break;
1859
                case 'auth_source':
1860
                    $user->setAuthSource($value);
1861
                    break;
1862
                case 'status':
1863
                    $user->setStatus($value);
1864
                    break;
1865
                case 'official_code':
1866
                    $user->setOfficialCode($value);
1867
                    break;
1868
                case 'picture_uri':
1869
                    $user->setPictureUri($value);
1870
                    break;
1871
                case 'creator_id':
1872
                    $user->setCreatorId($value);
1873
                    break;
1874
                case 'competences':
1875
                    $user->setCompetences($value);
1876
                    break;
1877
                case 'diplomas':
1878
                    $user->setDiplomas($value);
1879
                    break;
1880
                case 'openarea':
1881
                    $user->setOpenArea($value);
1882
                    break;
1883
                case 'teach':
1884
                    $user->setTeach($value);
1885
                    break;
1886
                case 'productions':
1887
                    $user->setProductions($value);
1888
                    break;
1889
                case 'language':
1890
                    $languages = api_get_languages();
1891
                    if (!in_array($value, $languages['folder'])) {
1892
                        throw new Exception(get_lang('LanguageUnavailable'));
1893
                    }
1894
                    $user->setLocale($value);
1895
                    break;
1896
                case 'registration_date':
1897
                    $user->setRegistrationDate($value);
1898
                    break;
1899
                case 'expiration_date':
1900
                    $user->setExpirationDate(
1901
                        new DateTime(
1902
                            api_get_utc_datetime($value),
1903
                            new DateTimeZone('UTC')
1904
                        )
1905
                    );
1906
                    break;
1907
                case 'active':
1908
                    // see UserManager::update_user() usermanager.lib.php:1205
1909
                    if ($user->getActive() != $value) {
1910
                        $user->setActive($value);
1911
                        Event::addEvent($value ? LOG_USER_ENABLE : LOG_USER_DISABLE, LOG_USER_ID, $userId);
1912
                    }
1913
                    break;
1914
                case 'openid':
1915
                    $user->setOpenId($value);
1916
                    break;
1917
                case 'theme':
1918
                    $user->setTheme($value);
1919
                    break;
1920
                case 'hr_dept_id':
1921
                    $user->setHrDeptId($value);
1922
                    break;
1923
                case 'extra':
1924
                    if (is_array($value)) {
1925
                        if (count($value) > 0) {
1926
                            if (is_array($value[0])) {
1927
                                foreach ($value as $field) {
1928
                                    $fieldName = $field['field_name'];
1929
                                    $fieldValue = $field['field_value'];
1930
                                    if (!isset($fieldName) || !isset($fieldValue) ||
1931
                                        !UserManager::update_extra_field_value($userId, $fieldName, $fieldValue)) {
1932
                                        throw new Exception(get_lang('CouldNotUpdateExtraFieldValue').': '.print_r($field, true));
1933
                                    }
1934
                                }
1935
                            } else {
1936
                                foreach ($value as $fieldName => $fieldValue) {
1937
                                    if (!UserManager::update_extra_field_value($userId, $fieldName, $fieldValue)) {
1938
                                        throw new Exception(get_lang('CouldNotUpdateExtraFieldValue').': '.$fieldName);
1939
                                    }
1940
                                }
1941
                            }
1942
                        }
1943
                    }
1944
                    break;
1945
                case 'username':
1946
                case 'api_key':
1947
                case 'action':
1948
                case 'loginname':
1949
                    break;
1950
                case 'email_canonical':
1951
                case 'locked':
1952
                case 'expired':
1953
                case 'credentials_expired':
1954
                case 'credentials_expire_at':
1955
                case 'expires_at':
1956
                case 'salt':
1957
                case 'last_login':
1958
                case 'created_at':
1959
                case 'updated_at':
1960
                case 'confirmation_token':
1961
                case 'password_requested_at':
1962
                case 'password': // see UserManager::update_user usermanager.lib.php:1182
1963
                case 'username_canonical':
1964
                default:
1965
                    throw new Exception(get_lang('UnsupportedUpdate')." '$name'");
1966
            }
1967
        }
1968
1969
        // save modifications
1970
        UserManager::getRepository()->updateUser($user, true);
1971
1972
        // tell the world we just updated this user
1973
        if (!empty($hook)) {
1974
            $hook->setEventData(['user' => $user]);
1975
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST);
1976
        }
1977
1978
        // invalidate cache for this user
1979
        $cacheAvailable = api_get_configuration_value('apc');
1980
        if (true === $cacheAvailable) {
1981
            $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$userId;
1982
            if (apcu_exists($apcVar)) {
1983
                apcu_delete($apcVar);
1984
            }
1985
        }
1986
1987
        return true;
1988
    }
1989
1990
    /**
1991
     * Returns whether a user login name exists.
1992
     *
1993
     * @param string $loginname the user login name
1994
     *
1995
     * @return bool whether the user login name exists
1996
     */
1997
    public function usernameExist($loginname)
1998
    {
1999
        return false !== api_get_user_info_from_username($loginname);
2000
    }
2001
2002
    /**
2003
     * This service roughly matches what the call to MDL's API core_course_get_contents function returns.
2004
     *
2005
     * @return array
2006
     */
2007
    public function getCourseQuizMdlCompat()
2008
    {
2009
        $userId = $this->user->getId();
2010
        $courseId = $this->course->getId();
2011
        $sessionId = $this->session ? $this->session->getId() : 0;
2012
2013
        $toolVisibility = CourseHome::getToolVisibility(TOOL_QUIZ, $courseId, $sessionId);
2014
2015
        $json = [
2016
            "id" => $this->course->getId(),
2017
            "name" => get_lang('Exercises'),
2018
            "visible" => (int) $toolVisibility,
2019
            "summary" => '',
2020
            "summaryformat" => 1,
2021
            "section" => 1,
2022
            "hiddenbynumsections" => 0,
2023
            "uservisible" => $toolVisibility,
2024
            "modules" => [],
2025
        ];
2026
2027
        $quizIcon = Display::return_icon('quiz.png', '', [], ICON_SIZE_SMALL, false, true);
2028
2029
        $json['modules'] = array_map(
2030
            function (array $exercise) use ($quizIcon) {
2031
                return [
2032
                    'id' => $exercise['id'],
2033
                    'url' => $exercise['url'],
2034
                    'name' => $exercise['name'],
2035
                    'instance' => 1,
2036
                    'visible' => 1,
2037
                    'uservisible' => true,
2038
                    'visibleoncoursepage' => 0,
2039
                    'modicon' => $quizIcon,
2040
                    'modname' => 'quiz',
2041
                    'modplural' => get_lang('Exercises'),
2042
                    'availability' => null,
2043
                    'indent' => 0,
2044
                    'onclick' => '',
2045
                    'afterlink' => null,
2046
                    'customdata' => '',
2047
                    'noviewlink' => false,
2048
                    'completion' => (int) ($exercise[1] > 0),
2049
                ];
2050
            },
2051
            Exercise::exerciseGridResource(0, '', $userId, $courseId, $sessionId, true)
2052
        );
2053
2054
        return [$json];
2055
    }
2056
2057
    /**
2058
     * @param array $additionalParams Optional
2059
     *
2060
     * @return string
2061
     */
2062
    private function encodeParams(array $additionalParams = [])
2063
    {
2064
        $params = array_merge(
2065
            $additionalParams,
2066
            [
2067
                'api_key' => $this->apiKey,
2068
                'username' => $this->user->getUsername(),
2069
            ]
2070
        );
2071
2072
        return json_encode($params);
2073
    }
2074
}
2075