Passed
Push — master ( f10e67...52beba )
by Julito
07:56
created

Rest::init()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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