Passed
Push — 1.11.x ( 73095b...3fbd99 )
by Angel Fernando Quiroz
09:40
created

Agenda::addSubscriptionFields()   B

Complexity

Conditions 5

Size

Total Lines 86
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 48
c 2
b 0
f 0
dl 0
loc 86
rs 8.8234
cc 5
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\AgendaEventInvitation;
6
use Chamilo\CoreBundle\Entity\AgendaEventInvitee;
7
use Chamilo\CoreBundle\Entity\AgendaEventSubscriber;
8
use Chamilo\CoreBundle\Entity\AgendaEventSubscription;
9
use Chamilo\CoreBundle\Entity\AgendaReminder;
10
use Chamilo\CoreBundle\Entity\PersonalAgenda;
11
use Chamilo\UserBundle\Entity\User;
12
13
/**
14
 * Class Agenda.
15
 *
16
 * @author: Julio Montoya <[email protected]>
17
 */
18
class Agenda
19
{
20
    public $events = [];
21
    /** @var string Current type */
22
    public $type = 'personal';
23
    public $types = ['personal', 'admin', 'course'];
24
    public $sessionId = 0;
25
    public $senderId;
26
    /** @var array */
27
    public $course;
28
    /** @var string */
29
    public $comment;
30
    public $eventStudentPublicationColor;
31
    /** @var array */
32
    private $sessionInfo;
33
    /** @var bool */
34
    private $isAllowedToEdit;
35
36
    /**
37
     * Constructor.
38
     *
39
     * @param string $type
40
     * @param int    $senderId  Optional The user sender ID
41
     * @param int    $courseId  Optional. The course ID
42
     * @param int    $sessionId Optional The session ID
43
     */
44
    public function __construct(
45
        $type,
46
        $senderId = 0,
47
        $courseId = 0,
48
        $sessionId = 0
49
    ) {
50
        // Table definitions
51
        $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
52
        $this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
53
        $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
54
        $this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
55
56
        $this->setType($type);
57
        $this->setSenderId($senderId ?: api_get_user_id());
58
        $isAllowToEdit = false;
59
60
        switch ($type) {
61
            case 'course':
62
                $sessionId = $sessionId ?: api_get_session_id();
63
                $sessionInfo = api_get_session_info($sessionId);
64
                $this->setSessionId($sessionId);
65
                $this->setSessionInfo($sessionInfo);
66
67
                // Setting the course object if we are in a course
68
                $courseInfo = api_get_course_info_by_id($courseId);
69
                if (!empty($courseInfo)) {
70
                    $this->set_course($courseInfo);
71
                }
72
73
                // Check if teacher/admin rights.
74
                $isAllowToEdit = api_is_allowed_to_edit(false, true);
75
                // Check course setting.
76
                if (api_get_course_setting('allow_user_edit_agenda') == '1'
77
                    && api_is_allowed_in_course()
78
                ) {
79
                    $isAllowToEdit = true;
80
                }
81
82
                $groupId = api_get_group_id();
83
                if (!empty($groupId)) {
84
                    $groupInfo = GroupManager::get_group_properties($groupId);
85
                    $userHasAccess = GroupManager::user_has_access(
86
                        api_get_user_id(),
87
                        $groupInfo['iid'],
88
                        GroupManager::GROUP_TOOL_CALENDAR
89
                    );
90
                    $isTutor = GroupManager::is_tutor_of_group(
91
                        api_get_user_id(),
92
                        $groupInfo
93
                    );
94
95
                    $isGroupAccess = $userHasAccess || $isTutor;
96
                    $isAllowToEdit = false;
97
                    if ($isGroupAccess) {
98
                        $isAllowToEdit = true;
99
                    }
100
                }
101
102
                if (false === $isAllowToEdit && !empty($sessionId)) {
103
                    $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
104
                    if ($allowDhrToEdit) {
105
                        $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
106
                        if ($isHrm) {
107
                            $isAllowToEdit = true;
108
                        }
109
                    }
110
                }
111
                break;
112
            case 'admin':
113
                $isAllowToEdit = api_is_platform_admin();
114
                break;
115
            case 'personal':
116
                $isAllowToEdit = !api_is_anonymous();
117
                break;
118
        }
119
120
        $this->setIsAllowedToEdit($isAllowToEdit);
121
        $this->events = [];
122
        $agendaColors = array_merge(
123
            [
124
                'platform' => 'red', //red
125
                'course' => '#458B00', //green
126
                'group' => '#A0522D', //siena
127
                'session' => '#00496D', // kind of green
128
                'other_session' => '#999', // kind of green
129
                'personal' => 'steel blue', //steel blue
130
                'student_publication' => '#FF8C00', //DarkOrange
131
            ],
132
            api_get_configuration_value('agenda_colors') ?: []
133
        );
134
135
        // Event colors
136
        $this->event_platform_color = $agendaColors['platform'];
137
        $this->event_course_color = $agendaColors['course'];
138
        $this->event_group_color = $agendaColors['group'];
139
        $this->event_session_color = $agendaColors['session'];
140
        $this->eventOtherSessionColor = $agendaColors['other_session'];
141
        $this->event_personal_color = $agendaColors['personal'];
142
        $this->eventStudentPublicationColor = $agendaColors['student_publication'];
143
    }
144
145
    /**
146
     * @param int $senderId
147
     */
148
    public function setSenderId($senderId)
149
    {
150
        $this->senderId = (int) $senderId;
151
    }
152
153
    /**
154
     * @return int
155
     */
156
    public function getSenderId()
157
    {
158
        return $this->senderId;
159
    }
160
161
    /**
162
     * @param string $type can be 'personal', 'admin'  or  'course'
163
     */
164
    public function setType($type)
165
    {
166
        $type = (string) trim($type);
167
        $typeList = $this->getTypes();
168
        if (in_array($type, $typeList, true)) {
169
            $this->type = $type;
170
        }
171
    }
172
173
    /**
174
     * Returns the type previously set (and filtered) through setType
175
     * If setType() was not called, then type defaults to "personal" as
176
     * set in the class definition.
177
     */
178
    public function getType()
179
    {
180
        if (isset($this->type)) {
181
            return $this->type;
182
        }
183
    }
184
185
    /**
186
     * @param int $id
187
     */
188
    public function setSessionId($id)
189
    {
190
        $this->sessionId = (int) $id;
191
    }
192
193
    /**
194
     * @param array $sessionInfo
195
     */
196
    public function setSessionInfo($sessionInfo)
197
    {
198
        $this->sessionInfo = $sessionInfo;
199
    }
200
201
    /**
202
     * @return int $id
203
     */
204
    public function getSessionId()
205
    {
206
        return $this->sessionId;
207
    }
208
209
    /**
210
     * @param array $courseInfo
211
     */
212
    public function set_course($courseInfo)
213
    {
214
        $this->course = $courseInfo;
215
    }
216
217
    /**
218
     * @return array
219
     */
220
    public function getTypes()
221
    {
222
        return $this->types;
223
    }
224
225
    /**
226
     * Adds an event to the calendar.
227
     *
228
     * @param string $start                 datetime format: 2012-06-14 09:00:00 in local time
229
     * @param string $end                   datetime format: 2012-06-14 09:00:00 in local time
230
     * @param string $allDay                (true, false)
231
     * @param string $title
232
     * @param string $content
233
     * @param array  $usersToSend           array('everyone') or a list of user/group ids
234
     * @param bool   $addAsAnnouncement     event as a *course* announcement
235
     * @param int    $parentEventId
236
     * @param array  $attachmentArray       array of $_FILES['']
237
     * @param array  $attachmentCommentList
238
     * @param string $eventComment
239
     * @param string $color
240
     *
241
     * @return int
242
     */
243
    public function addEvent(
244
        $start,
245
        $end,
246
        $allDay,
247
        $title,
248
        $content,
249
        $usersToSend = [],
250
        $addAsAnnouncement = false,
251
        $parentEventId = null,
252
        $attachmentArray = [],
253
        $attachmentCommentList = [],
254
        $eventComment = null,
255
        $color = '',
256
        array $inviteesList = [],
257
        bool $isCollective = false,
258
        array $reminders = [],
259
        int $careerId = 0,
260
        int $promotionId = 0,
261
        int $subscriptionVisibility = 0,
262
        ?int $subscriptionItemId = null,
263
        int $maxSubscriptions = 0
264
    ) {
265
        $start = api_get_utc_datetime($start);
266
        $end = api_get_utc_datetime($end);
267
        $allDay = isset($allDay) && ($allDay === 'true' || $allDay == 1) ? 1 : 0;
268
        $id = null;
269
270
        $em = Database::getManager();
271
272
        switch ($this->type) {
273
            case 'personal':
274
                $attributes = [
275
                    'user' => api_get_user_id(),
276
                    'title' => $title,
277
                    'text' => $content,
278
                    'date' => $start,
279
                    'enddate' => $end,
280
                    'all_day' => $allDay,
281
                    'color' => $color,
282
                ];
283
284
                $id = Database::insert(
285
                    $this->tbl_personal_agenda,
286
                    $attributes
287
                );
288
289
                if (api_get_configuration_value('agenda_collective_invitations')) {
290
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
291
                }
292
293
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
294
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
295
296
                    if ($personalEvent->hasInvitation()
297
                        && !($personalEvent->getInvitation() instanceof AgendaEventSubscription)
298
                    ) {
299
                        break;
300
                    }
301
302
                    $personalEvent
303
                        ->setSubscriptionVisibility($subscriptionVisibility)
304
                        ->setSubscriptionItemId($subscriptionItemId ?: null)
305
                    ;
306
307
                    $subscription = (new AgendaEventSubscription())
308
                        ->setCreator(api_get_user_entity(api_get_user_id()))
309
                        ->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0)
310
                    ;
311
312
                    $personalEvent
313
                        ->setCollective(false)
314
                        ->setInvitation($subscription)
315
                    ;
316
317
                    $em->flush();
318
                }
319
                break;
320
            case 'course':
321
                $attributes = [
322
                    'title' => $title,
323
                    'content' => $content,
324
                    'start_date' => $start,
325
                    'end_date' => $end,
326
                    'all_day' => $allDay,
327
                    'session_id' => $this->getSessionId(),
328
                    'c_id' => $this->course['real_id'],
329
                    'comment' => $eventComment,
330
                    'color' => $color,
331
                ];
332
333
                if (!empty($parentEventId)) {
334
                    $attributes['parent_event_id'] = $parentEventId;
335
                }
336
                $this->deleteEventIfAlreadyExists($start, $end, $allDay, $title);
337
                $senderId = $this->getSenderId();
338
                $sessionId = $this->getSessionId();
339
340
                // Simple course event.
341
                $id = Database::insert($this->tbl_course_agenda, $attributes);
342
343
                if ($id) {
344
                    $sql = "UPDATE ".$this->tbl_course_agenda." SET id = iid WHERE iid = $id";
345
                    Database::query($sql);
346
347
                    $groupId = api_get_group_id();
348
                    $groupInfo = [];
349
                    if ($groupId) {
350
                        $groupInfo = GroupManager::get_group_properties(
351
                            $groupId
352
                        );
353
                    }
354
355
                    if (!empty($usersToSend)) {
356
                        $sendTo = $this->parseSendToArray($usersToSend);
357
                        if ($sendTo['everyone']) {
358
                            api_item_property_update(
359
                                $this->course,
360
                                TOOL_CALENDAR_EVENT,
361
                                $id,
362
                                'AgendaAdded',
363
                                $senderId,
364
                                $groupInfo,
365
                                '',
366
                                $start,
367
                                $end,
368
                                $sessionId
369
                            );
370
                            api_item_property_update(
371
                                $this->course,
372
                                TOOL_CALENDAR_EVENT,
373
                                $id,
374
                                'visible',
375
                                $senderId,
376
                                $groupInfo,
377
                                '',
378
                                $start,
379
                                $end,
380
                                $sessionId
381
                            );
382
                        } else {
383
                            // Storing the selected groups
384
                            if (!empty($sendTo['groups'])) {
385
                                foreach ($sendTo['groups'] as $group) {
386
                                    $groupInfoItem = [];
387
                                    if ($group) {
388
                                        $groupInfoItem = GroupManager::get_group_properties($group);
389
                                    }
390
391
                                    api_item_property_update(
392
                                        $this->course,
393
                                        TOOL_CALENDAR_EVENT,
394
                                        $id,
395
                                        'AgendaAdded',
396
                                        $senderId,
397
                                        $groupInfoItem,
398
                                        0,
399
                                        $start,
400
                                        $end,
401
                                        $sessionId
402
                                    );
403
404
                                    api_item_property_update(
405
                                        $this->course,
406
                                        TOOL_CALENDAR_EVENT,
407
                                        $id,
408
                                        'visible',
409
                                        $senderId,
410
                                        $groupInfoItem,
411
                                        0,
412
                                        $start,
413
                                        $end,
414
                                        $sessionId
415
                                    );
416
                                }
417
                            }
418
419
                            // storing the selected users
420
                            if (!empty($sendTo['users'])) {
421
                                foreach ($sendTo['users'] as $userId) {
422
                                    api_item_property_update(
423
                                        $this->course,
424
                                        TOOL_CALENDAR_EVENT,
425
                                        $id,
426
                                        'AgendaAdded',
427
                                        $senderId,
428
                                        $groupInfo,
429
                                        $userId,
430
                                        $start,
431
                                        $end,
432
                                        $sessionId
433
                                    );
434
435
                                    api_item_property_update(
436
                                        $this->course,
437
                                        TOOL_CALENDAR_EVENT,
438
                                        $id,
439
                                        'visible',
440
                                        $senderId,
441
                                        $groupInfo,
442
                                        $userId,
443
                                        $start,
444
                                        $end,
445
                                        $sessionId
446
                                    );
447
                                }
448
                            }
449
                        }
450
                    }
451
452
                    // Add announcement.
453
                    if ($addAsAnnouncement) {
454
                        $this->storeAgendaEventAsAnnouncement(
455
                            $id,
456
                            $usersToSend
457
                        );
458
                    }
459
460
                    // Add attachment.
461
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
462
                        $counter = 0;
463
                        foreach ($attachmentArray as $attachmentItem) {
464
                            $this->addAttachment(
465
                                $id,
466
                                $attachmentItem,
467
                                $attachmentCommentList[$counter],
468
                                $this->course
469
                            );
470
                            $counter++;
471
                        }
472
                    }
473
                }
474
                break;
475
            case 'admin':
476
                if (api_is_platform_admin()) {
477
                    $attributes = [
478
                        'title' => $title,
479
                        'content' => $content,
480
                        'start_date' => $start,
481
                        'end_date' => $end,
482
                        'all_day' => $allDay,
483
                        'access_url_id' => api_get_current_access_url_id(),
484
                    ];
485
486
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
487
                        $attributes['career_id'] = $careerId;
488
                        $attributes['promotion_id'] = $promotionId;
489
                    }
490
491
                    $id = Database::insert(
492
                        $this->tbl_global_agenda,
493
                        $attributes
494
                    );
495
                }
496
                break;
497
        }
498
499
        if (api_get_configuration_value('agenda_reminders')) {
500
            foreach ($reminders as $reminder) {
501
                $this->addReminder($id, $reminder[0], $reminder[1]);
502
            }
503
        }
504
505
        return $id;
506
    }
507
508
    /**
509
     * Checks if an event exists and delete it (right before inserting a modified version in addEvent())
510
     * @param string $start datetime format: 2012-06-14 09:00:00 in local time
511
     * @param string $end   datetime format: 2012-06-14 09:00:00 in local time
512
     * @param int $allDay   (true = 1, false = 0)
513
     * @param string $title
514
     *
515
     * @return bool
516
     * @throws Exception
517
     */
518
    public function deleteEventIfAlreadyExists(
519
        string $start,
520
        string $end,
521
        int $allDay,
522
        string $title
523
    ): bool {
524
        $courseId = $this->course['real_id'];
525
        $start = Database::escape_string($start);
526
        $end = Database::escape_string($end);
527
        $title = Database::escape_string($title);
528
        $sql = "SELECT id FROM ".$this->tbl_course_agenda."
529
                WHERE c_id = $courseId
530
                AND session_id = ".$this->sessionId."
531
                AND start_date = '$start'
532
                AND end_date = '$end'
533
                AND all_day = $allDay
534
                AND title = '$title'";
535
        $res = Database::query($sql);
536
        if (Database::num_rows($res) > 0) {
537
            $row = Database::fetch_array($res, 'ASSOC');
538
            $id = $row['id'];
539
            $this->deleteEvent($id);
540
541
            return true;
542
        }
543
544
        return false;
545
    }
546
547
    /**
548
     * @throws Exception
549
     */
550
    public function addReminder($eventId, $count, $period)
551
    {
552
        switch ($period) {
553
            case 'i':
554
                $dateInterval = DateInterval::createFromDateString("$count minutes");
555
                break;
556
            case 'h':
557
                $dateInterval = DateInterval::createFromDateString("$count hours");
558
                break;
559
            case 'd':
560
                $dateInterval = DateInterval::createFromDateString("$count days");
561
                break;
562
            default:
563
                return null;
564
        }
565
566
        $agendaReminder = new AgendaReminder();
567
        $agendaReminder
568
            ->setType($this->type)
569
            ->setEventId($eventId)
570
            ->setDateInterval($dateInterval)
571
        ;
572
573
        $em = Database::getManager();
574
        $em->persist($agendaReminder);
575
        $em->flush();
576
    }
577
578
    public function removeReminders(int $eventId, int $count, string $period)
579
    {
580
        switch ($period) {
581
            case 'i':
582
                $dateInterval = DateInterval::createFromDateString("$count minutes");
583
                break;
584
            case 'h':
585
                $dateInterval = DateInterval::createFromDateString("$count hours");
586
                break;
587
            case 'd':
588
                $dateInterval = DateInterval::createFromDateString("$count days");
589
                break;
590
            default:
591
                return null;
592
        }
593
594
        Database::getManager()
595
            ->createQuery(
596
                'DELETE FROM ChamiloCoreBundle:AgendaReminder ar
597
                WHERE ar.eventId = :eventId AND ar.type = :type AND ar.dateInterval = :dateInterval'
598
            )
599
            ->setParameters(
600
                [
601
                    'eventId' => $eventId,
602
                    'type' => $this->type,
603
                    'dateInterval' => $dateInterval,
604
                ]
605
            )
606
            ->execute();
607
    }
608
609
    public function getReminder(int $eventId, int $count, string $period)
610
    {
611
        switch ($period) {
612
            case 'i':
613
                $dateInterval = DateInterval::createFromDateString("$count minutes");
614
                break;
615
            case 'h':
616
                $dateInterval = DateInterval::createFromDateString("$count hours");
617
                break;
618
            case 'd':
619
                $dateInterval = DateInterval::createFromDateString("$count days");
620
                break;
621
            default:
622
                return null;
623
        }
624
625
        $em = Database::getManager();
626
        $remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
627
628
        return $remindersRepo->findOneBy(
629
            [
630
                'type' => $this->type,
631
                'dateInterval' => $dateInterval,
632
                'eventId' => $eventId,
633
            ]
634
        );
635
    }
636
637
    /**
638
     * @param int $eventId
639
     * @param int $courseId
640
     *
641
     * @return array
642
     */
643
    public function getRepeatedInfoByEvent($eventId, $courseId)
644
    {
645
        $repeatTable = Database::get_course_table(TABLE_AGENDA_REPEAT);
646
        $eventId = (int) $eventId;
647
        $courseId = (int) $courseId;
648
        $sql = "SELECT * FROM $repeatTable
649
                WHERE c_id = $courseId AND cal_id = $eventId";
650
        $res = Database::query($sql);
651
        $repeatInfo = [];
652
        if (Database::num_rows($res) > 0) {
653
            $repeatInfo = Database::fetch_array($res, 'ASSOC');
654
        }
655
656
        return $repeatInfo;
657
    }
658
659
    /**
660
     * @param string $type
661
     * @param string $startEvent      in UTC
662
     * @param string $endEvent        in UTC
663
     * @param string $repeatUntilDate in UTC
664
     *
665
     * @throws Exception
666
     *
667
     * @return array with local times
668
     */
669
    public function generateDatesByType($type, $startEvent, $endEvent, $repeatUntilDate)
670
    {
671
        $continue = true;
672
        $repeatUntilDate = new DateTime($repeatUntilDate, new DateTimeZone('UTC'));
673
        $loopMax = 365;
674
        $counter = 0;
675
        $list = [];
676
677
        switch ($type) {
678
            case 'daily':
679
                $interval = 'P1D';
680
                break;
681
            case 'weekly':
682
                $interval = 'P1W';
683
                break;
684
            case 'monthlyByDate':
685
                $interval = 'P1M';
686
                break;
687
            case 'monthlyByDay':
688
                // not yet implemented
689
                break;
690
            case 'monthlyByDayR':
691
                // not yet implemented
692
                break;
693
            case 'yearly':
694
                $interval = 'P1Y';
695
                break;
696
        }
697
698
        if (empty($interval)) {
699
            return [];
700
        }
701
        $timeZone = api_get_timezone();
702
703
        while ($continue) {
704
            $startDate = new DateTime($startEvent, new DateTimeZone('UTC'));
705
            $endDate = new DateTime($endEvent, new DateTimeZone('UTC'));
706
707
            $startDate->add(new DateInterval($interval));
708
            $endDate->add(new DateInterval($interval));
709
710
            $newStartDate = $startDate->format('Y-m-d H:i:s');
711
            $newEndDate = $endDate->format('Y-m-d H:i:s');
712
713
            $startEvent = $newStartDate;
714
            $endEvent = $newEndDate;
715
716
            if ($endDate > $repeatUntilDate) {
717
                break;
718
            }
719
720
            // @todo remove comment code
721
            // The code below was not adpating to saving light time but was doubling the difference with UTC time.
722
            // Might be necessary to adapt to update saving light time difference.
723
            /*            $startDateInLocal = new DateTime($newStartDate, new DateTimeZone($timeZone));
724
                        if ($startDateInLocal->format('I') == 0) {
725
                            // Is saving time? Then fix UTC time to add time
726
                            $seconds = $startDateInLocal->getOffset();
727
                            $startDate->add(new DateInterval("PT".$seconds."S"));
728
                            //$startDateFixed = $startDate->format('Y-m-d H:i:s');
729
                            //$startDateInLocalFixed = new DateTime($startDateFixed, new DateTimeZone($timeZone));
730
                            //$newStartDate = $startDateInLocalFixed->format('Y-m-d H:i:s');
731
                            //$newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
732
                        }
733
734
                        $endDateInLocal = new DateTime($newEndDate, new DateTimeZone($timeZone));
735
                        if ($endDateInLocal->format('I') == 0) {
736
                            // Is saving time? Then fix UTC time to add time
737
                            $seconds = $endDateInLocal->getOffset();
738
                            $endDate->add(new DateInterval("PT".$seconds."S"));
739
                            //$endDateFixed = $endDate->format('Y-m-d H:i:s');
740
                            //$endDateInLocalFixed = new DateTime($endDateFixed, new DateTimeZone($timeZone));
741
                            //$newEndDate = $endDateInLocalFixed->format('Y-m-d H:i:s');
742
                    }
743
            */
744
            $newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
745
            $newEndDate = $endDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
746
            $list[] = ['start' => $newStartDate, 'end' => $newEndDate];
747
            $counter++;
748
749
            // just in case stop if more than $loopMax
750
            if ($counter > $loopMax) {
751
                break;
752
            }
753
        }
754
755
        return $list;
756
    }
757
758
    /**
759
     * @param int    $eventId
760
     * @param string $type
761
     * @param string $end     in UTC
762
     * @param array  $sentTo
763
     *
764
     * @return bool
765
     */
766
    public function addRepeatedItem($eventId, $type, $end, $sentTo = [])
767
    {
768
        $t_agenda = Database::get_course_table(TABLE_AGENDA);
769
        $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT);
770
771
        if (empty($this->course)) {
772
            return false;
773
        }
774
775
        $courseId = $this->course['real_id'];
776
        $eventId = (int) $eventId;
777
778
        $sql = "SELECT title, content, start_date, end_date, all_day
779
                FROM $t_agenda
780
                WHERE c_id = $courseId AND id = $eventId";
781
        $res = Database::query($sql);
782
783
        if (Database::num_rows($res) !== 1) {
784
            return false;
785
        }
786
787
        $typeList = [
788
            'daily',
789
            'weekly',
790
            'monthlyByDate',
791
            'monthlyByDay',
792
            'monthlyByDayR',
793
            'yearly',
794
        ];
795
796
        if (!in_array($type, $typeList)) {
797
            return false;
798
        }
799
800
        $now = time();
801
802
        // The event has to repeat *in the future*. We don't allow repeated
803
        // events in the past.
804
        $endTimeStamp = api_strtotime($end, 'UTC');
805
806
        if ($endTimeStamp < $now) {
807
            return false;
808
        }
809
810
        $row = Database::fetch_array($res);
811
812
        $title = $row['title'];
813
        $content = $row['content'];
814
        $allDay = $row['all_day'];
815
816
        $type = Database::escape_string($type);
817
        $end = Database::escape_string($end);
818
819
        $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end)
820
                VALUES ($courseId, '$eventId', '$type', '$endTimeStamp')";
821
        Database::query($sql);
822
823
        $generatedDates = $this->generateDatesByType($type, $row['start_date'], $row['end_date'], $end);
824
825
        if (empty($generatedDates)) {
826
            return false;
827
        }
828
829
        foreach ($generatedDates as $dateInfo) {
830
//            $start = api_get_local_time($dateInfo['start']);
831
//            $end = api_get_local_time($dateInfo['end']);
832
            // On line 529 in function generateDatesByType there is a @todo remove comment code
833
            // just before the part updating the date in local time so keep both synchronised
834
            $start = $dateInfo['start'];
835
            $end = $dateInfo['end'];
836
837
            $this->addEvent(
838
                $start,
839
                $end,
840
                $allDay,
841
                $title,
842
                $content,
843
                $sentTo,
844
                false,
845
                $eventId
846
            );
847
        }
848
849
        return true;
850
    }
851
852
    /**
853
     * @param int   $item_id
854
     * @param array $sentTo
855
     *
856
     * @return int
857
     */
858
    public function storeAgendaEventAsAnnouncement($item_id, $sentTo = [])
859
    {
860
        $table_agenda = Database::get_course_table(TABLE_AGENDA);
861
        $courseId = api_get_course_int_id();
862
863
        // Check params
864
        if (empty($item_id) || $item_id != strval(intval($item_id))) {
865
            return -1;
866
        }
867
868
        // Get the agenda item.
869
        $item_id = intval($item_id);
870
        $sql = "SELECT * FROM $table_agenda
871
                WHERE c_id = $courseId AND id = ".$item_id;
872
        $res = Database::query($sql);
873
874
        if (Database::num_rows($res) > 0) {
875
            $row = Database::fetch_array($res, 'ASSOC');
876
877
            // Sending announcement
878
            if (!empty($sentTo)) {
879
                $id = AnnouncementManager::add_announcement(
880
                    api_get_course_info(),
881
                    api_get_session_id(),
882
                    $row['title'],
883
                    $row['content'],
884
                    $sentTo,
885
                    null,
886
                    null,
887
                    $row['end_date']
888
                );
889
890
                AnnouncementManager::sendEmail(
891
                    api_get_course_info(),
892
                    api_get_session_id(),
893
                    $id
894
                );
895
896
                return $id;
897
            }
898
        }
899
900
        return -1;
901
    }
902
903
    /**
904
     * Edits an event.
905
     *
906
     * @param int    $id
907
     * @param string $start                 datetime format: 2012-06-14 09:00:00
908
     * @param string $end                   datetime format: 2012-06-14 09:00:00
909
     * @param int    $allDay                is all day 'true' or 'false'
910
     * @param string $title
911
     * @param string $content
912
     * @param array  $usersToSend
913
     * @param array  $attachmentArray
914
     * @param array  $attachmentCommentList
915
     * @param string $comment
916
     * @param string $color
917
     * @param bool   $addAnnouncement
918
     * @param bool   $updateContent
919
     * @param int    $authorId
920
     *
921
     * @return bool
922
     */
923
    public function editEvent(
924
        $id,
925
        $start,
926
        $end,
927
        $allDay,
928
        $title,
929
        $content,
930
        $usersToSend = [],
931
        $attachmentArray = [],
932
        $attachmentCommentList = [],
933
        $comment = null,
934
        $color = '',
935
        $addAnnouncement = false,
936
        $updateContent = true,
937
        $authorId = 0,
938
        array $inviteesList = [],
939
        bool $isCollective = false,
940
        array $remindersList = [],
941
        int $careerId = 0,
942
        int $promotionId = 0,
943
        int $subscriptionVisibility = 0,
944
        ?int $subscriptionItemId = null,
945
        int $maxSubscriptions = 0,
946
        array $subscribers = []
947
    ) {
948
        $id = (int) $id;
949
        $start = api_get_utc_datetime($start);
950
        $end = api_get_utc_datetime($end);
951
        $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0;
952
        $currentUserId = api_get_user_id();
953
        $authorId = empty($authorId) ? $currentUserId : (int) $authorId;
954
955
        $em = Database::getManager();
956
957
        switch ($this->type) {
958
            case 'personal':
959
                $eventInfo = $this->get_event($id);
960
                if ($eventInfo['user'] != $currentUserId
961
                    && (
962
                        api_get_configuration_value('agenda_collective_invitations')
963
                            && !self::isUserInvitedInEvent($id, $currentUserId)
964
                    )
965
                ) {
966
                    break;
967
                }
968
                $attributes = [
969
                    'title' => $title,
970
                    'date' => $start,
971
                    'enddate' => $end,
972
                    'all_day' => $allDay,
973
                ];
974
975
                if ($updateContent) {
976
                    $attributes['text'] = $content;
977
                }
978
979
                if (!empty($color)) {
980
                    $attributes['color'] = $color;
981
                }
982
983
                Database::update(
984
                    $this->tbl_personal_agenda,
985
                    $attributes,
986
                    ['id = ?' => $id]
987
                );
988
989
                if (api_get_configuration_value('agenda_collective_invitations')) {
990
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
991
                }
992
993
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
994
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
995
                    $personalEvent->setSubscriptionVisibility($subscriptionVisibility);
996
997
                    /** @var AgendaEventSubscription $subscription */
998
                    $subscription = $personalEvent->getInvitation();
999
                    $subscription->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0);
1000
1001
                    if ($personalEvent->getSubscriptionItemId() != $subscriptionItemId) {
1002
                        $personalEvent->setSubscriptionItemId($subscriptionItemId ?: null);
1003
                        $subscription->removeInvitees();
1004
                    } else {
1005
                        $subscription->removeInviteesNotInIdList($subscribers);
1006
                    }
1007
1008
                    $em->flush();
1009
                }
1010
                break;
1011
            case 'course':
1012
                $eventInfo = $this->get_event($id);
1013
1014
                if (empty($eventInfo)) {
1015
                    return false;
1016
                }
1017
1018
                $groupId = api_get_group_id();
1019
                $groupIid = 0;
1020
                $groupInfo = [];
1021
                if ($groupId) {
1022
                    $groupInfo = GroupManager::get_group_properties($groupId);
1023
                    if ($groupInfo) {
1024
                        $groupIid = $groupInfo['iid'];
1025
                    }
1026
                }
1027
1028
                $courseId = $this->course['real_id'];
1029
1030
                if (empty($courseId)) {
1031
                    return false;
1032
                }
1033
1034
                if (!$this->getIsAllowedToEdit()) {
1035
                    return false;
1036
                }
1037
1038
                $attributes = [
1039
                    'title' => $title,
1040
                    'start_date' => $start,
1041
                    'end_date' => $end,
1042
                    'all_day' => $allDay,
1043
                    'comment' => $comment,
1044
                ];
1045
1046
                if ($updateContent) {
1047
                    $attributes['content'] = $content;
1048
                }
1049
1050
                if (!empty($color)) {
1051
                    $attributes['color'] = $color;
1052
                }
1053
1054
                Database::update(
1055
                    $this->tbl_course_agenda,
1056
                    $attributes,
1057
                    [
1058
                        'id = ? AND c_id = ? AND session_id = ? ' => [
1059
                            $id,
1060
                            $courseId,
1061
                            $this->sessionId,
1062
                        ],
1063
                    ]
1064
                );
1065
1066
                if (!empty($usersToSend)) {
1067
                    $sendTo = $this->parseSendToArray($usersToSend);
1068
1069
                    $usersToDelete = array_diff(
1070
                        $eventInfo['send_to']['users'],
1071
                        $sendTo['users']
1072
                    );
1073
                    $usersToAdd = array_diff(
1074
                        $sendTo['users'],
1075
                        $eventInfo['send_to']['users']
1076
                    );
1077
1078
                    $groupsToDelete = array_diff(
1079
                        $eventInfo['send_to']['groups'],
1080
                        $sendTo['groups']
1081
                    );
1082
                    $groupToAdd = array_diff(
1083
                        $sendTo['groups'],
1084
                        $eventInfo['send_to']['groups']
1085
                    );
1086
1087
                    if ($sendTo['everyone']) {
1088
                        // Delete all from group
1089
                        if (isset($eventInfo['send_to']['groups']) &&
1090
                            !empty($eventInfo['send_to']['groups'])
1091
                        ) {
1092
                            foreach ($eventInfo['send_to']['groups'] as $group) {
1093
                                $groupIidItem = 0;
1094
                                if ($group) {
1095
                                    $groupInfoItem = GroupManager::get_group_properties(
1096
                                        $group
1097
                                    );
1098
                                    if ($groupInfoItem) {
1099
                                        $groupIidItem = $groupInfoItem['iid'];
1100
                                    }
1101
                                }
1102
1103
                                api_item_property_delete(
1104
                                    $this->course,
1105
                                    TOOL_CALENDAR_EVENT,
1106
                                    $id,
1107
                                    0,
1108
                                    $groupIidItem,
1109
                                    $this->sessionId
1110
                                );
1111
                            }
1112
                        }
1113
1114
                        // Storing the selected users.
1115
                        if (isset($eventInfo['send_to']['users']) &&
1116
                            !empty($eventInfo['send_to']['users'])
1117
                        ) {
1118
                            foreach ($eventInfo['send_to']['users'] as $userId) {
1119
                                api_item_property_delete(
1120
                                    $this->course,
1121
                                    TOOL_CALENDAR_EVENT,
1122
                                    $id,
1123
                                    $userId,
1124
                                    $groupIid,
1125
                                    $this->sessionId
1126
                                );
1127
                            }
1128
                        }
1129
1130
                        // Add to everyone only.
1131
                        api_item_property_update(
1132
                            $this->course,
1133
                            TOOL_CALENDAR_EVENT,
1134
                            $id,
1135
                            'visible',
1136
                            $authorId,
1137
                            $groupInfo,
1138
                            null,
1139
                            $start,
1140
                            $end,
1141
                            $this->sessionId
1142
                        );
1143
                    } else {
1144
                        // Delete "everyone".
1145
                        api_item_property_delete(
1146
                            $this->course,
1147
                            TOOL_CALENDAR_EVENT,
1148
                            $id,
1149
                            0,
1150
                            0,
1151
                            $this->sessionId
1152
                        );
1153
1154
                        // Add groups
1155
                        if (!empty($groupToAdd)) {
1156
                            foreach ($groupToAdd as $group) {
1157
                                $groupInfoItem = [];
1158
                                if ($group) {
1159
                                    $groupInfoItem = GroupManager::get_group_properties(
1160
                                        $group
1161
                                    );
1162
                                }
1163
1164
                                api_item_property_update(
1165
                                    $this->course,
1166
                                    TOOL_CALENDAR_EVENT,
1167
                                    $id,
1168
                                    'visible',
1169
                                    $authorId,
1170
                                    $groupInfoItem,
1171
                                    0,
1172
                                    $start,
1173
                                    $end,
1174
                                    $this->sessionId
1175
                                );
1176
                            }
1177
                        }
1178
1179
                        // Delete groups.
1180
                        if (!empty($groupsToDelete)) {
1181
                            foreach ($groupsToDelete as $group) {
1182
                                $groupIidItem = 0;
1183
                                $groupInfoItem = [];
1184
                                if ($group) {
1185
                                    $groupInfoItem = GroupManager::get_group_properties(
1186
                                        $group
1187
                                    );
1188
                                    if ($groupInfoItem) {
1189
                                        $groupIidItem = $groupInfoItem['iid'];
1190
                                    }
1191
                                }
1192
1193
                                api_item_property_delete(
1194
                                    $this->course,
1195
                                    TOOL_CALENDAR_EVENT,
1196
                                    $id,
1197
                                    0,
1198
                                    $groupIidItem,
1199
                                    $this->sessionId
1200
                                );
1201
                            }
1202
                        }
1203
1204
                        // Add users.
1205
                        if (!empty($usersToAdd)) {
1206
                            foreach ($usersToAdd as $userId) {
1207
                                api_item_property_update(
1208
                                    $this->course,
1209
                                    TOOL_CALENDAR_EVENT,
1210
                                    $id,
1211
                                    'visible',
1212
                                    $authorId,
1213
                                    $groupInfo,
1214
                                    $userId,
1215
                                    $start,
1216
                                    $end,
1217
                                    $this->sessionId
1218
                                );
1219
                            }
1220
                        }
1221
1222
                        // Delete users.
1223
                        if (!empty($usersToDelete)) {
1224
                            foreach ($usersToDelete as $userId) {
1225
                                api_item_property_delete(
1226
                                    $this->course,
1227
                                    TOOL_CALENDAR_EVENT,
1228
                                    $id,
1229
                                    $userId,
1230
                                    $groupInfo,
1231
                                    $this->sessionId
1232
                                );
1233
                            }
1234
                        }
1235
                    }
1236
                }
1237
1238
                // Add announcement.
1239
                if (isset($addAnnouncement) && !empty($addAnnouncement)) {
1240
                    $this->storeAgendaEventAsAnnouncement(
1241
                        $id,
1242
                        $usersToSend
1243
                    );
1244
                }
1245
1246
                // Add attachment.
1247
                if (isset($attachmentArray) && !empty($attachmentArray)) {
1248
                    $counter = 0;
1249
                    foreach ($attachmentArray as $attachmentItem) {
1250
                        if (empty($attachmentItem['id'])) {
1251
                            $this->addAttachment(
1252
                                $id,
1253
                                $attachmentItem,
1254
                                $attachmentCommentList[$counter],
1255
                                $this->course
1256
                            );
1257
                        } else {
1258
                            $this->updateAttachment(
1259
                                $attachmentItem['id'],
1260
                                $id,
1261
                                $attachmentItem,
1262
                                $attachmentCommentList[$counter],
1263
                                $this->course
1264
                            );
1265
                        }
1266
                        $counter++;
1267
                    }
1268
                }
1269
                break;
1270
            case 'admin':
1271
            case 'platform':
1272
                if (api_is_platform_admin()) {
1273
                    $attributes = [
1274
                        'title' => $title,
1275
                        'start_date' => $start,
1276
                        'end_date' => $end,
1277
                        'all_day' => $allDay,
1278
                    ];
1279
1280
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
1281
                        $attributes['career_id'] = $careerId;
1282
                        $attributes['promotion_id'] = $promotionId;
1283
                    }
1284
1285
                    if ($updateContent) {
1286
                        $attributes['content'] = $content;
1287
                    }
1288
                    Database::update(
1289
                        $this->tbl_global_agenda,
1290
                        $attributes,
1291
                        ['id = ?' => $id]
1292
                    );
1293
                }
1294
                break;
1295
        }
1296
1297
        $this->editReminders($id, $remindersList);
1298
1299
        return true;
1300
    }
1301
1302
    /**
1303
     * @param int  $id
1304
     * @param bool $deleteAllItemsFromSerie
1305
     *
1306
     * @throws \Doctrine\ORM\ORMException
1307
     * @throws \Doctrine\ORM\OptimisticLockException
1308
     */
1309
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
1310
    {
1311
        $em = Database::getManager();
1312
1313
        switch ($this->type) {
1314
            case 'personal':
1315
                $eventInfo = $this->get_event($id);
1316
                if ($eventInfo['user'] == api_get_user_id()) {
1317
                    Database::delete(
1318
                        $this->tbl_personal_agenda,
1319
                        ['id = ?' => $id]
1320
                    );
1321
                } elseif (api_get_configuration_value('agenda_collective_invitations')) {
1322
                    $currentUser = api_get_user_entity(api_get_user_id());
1323
1324
                    $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
1325
                    $event = $eventRepo->findOneByIdAndInvitee($id, $currentUser);
1326
                    $invitation = $event ? $event->getInvitation() : null;
1327
1328
                    if ($invitation) {
1329
                        $invitation->removeInviteeUser($currentUser);
1330
1331
                        $em->persist($invitation);
1332
                        $em->flush();
1333
                    }
1334
                }
1335
                break;
1336
            case 'course':
1337
                $courseId = api_get_course_int_id();
1338
                $isAllowToEdit = $this->getIsAllowedToEdit();
1339
1340
                if (!empty($courseId) && $isAllowToEdit) {
1341
                    $eventInfo = $this->get_event($id);
1342
                    if ($deleteAllItemsFromSerie) {
1343
                        /* This is one of the children.
1344
                           Getting siblings and delete 'Em all + the father! */
1345
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
1346
                            // Removing items.
1347
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
1348
                            if (!empty($events)) {
1349
                                foreach ($events as $event) {
1350
                                    $this->deleteEvent($event['id']);
1351
                                }
1352
                            }
1353
                            // Removing parent.
1354
                            $this->deleteEvent($eventInfo['parent_event_id']);
1355
                        } else {
1356
                            // This is the father looking for the children.
1357
                            $events = $this->getAllRepeatEvents($id);
1358
                            if (!empty($events)) {
1359
                                foreach ($events as $event) {
1360
                                    $this->deleteEvent($event['id']);
1361
                                }
1362
                            }
1363
                        }
1364
                    }
1365
1366
                    // Removing from events.
1367
                    Database::delete(
1368
                        $this->tbl_course_agenda,
1369
                        ['id = ? AND c_id = ?' => [$id, $courseId]]
1370
                    );
1371
1372
                    api_item_property_update(
1373
                        $this->course,
1374
                        TOOL_CALENDAR_EVENT,
1375
                        $id,
1376
                        'delete',
1377
                        api_get_user_id()
1378
                    );
1379
1380
                    // Removing from series.
1381
                    Database::delete(
1382
                        $this->table_repeat,
1383
                        [
1384
                            'cal_id = ? AND c_id = ?' => [
1385
                                $id,
1386
                                $courseId,
1387
                            ],
1388
                        ]
1389
                    );
1390
1391
                    if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
1392
                        foreach ($eventInfo['attachment'] as $attachment) {
1393
                            self::deleteAttachmentFile(
1394
                                $attachment['id'],
1395
                                $this->course
1396
                            );
1397
                        }
1398
                    }
1399
                }
1400
                break;
1401
            case 'admin':
1402
                if (api_is_platform_admin()) {
1403
                    Database::delete(
1404
                        $this->tbl_global_agenda,
1405
                        ['id = ?' => $id]
1406
                    );
1407
                }
1408
                break;
1409
        }
1410
    }
1411
1412
    public function subscribeCurrentUserToEvent(int $id)
1413
    {
1414
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1415
            return;
1416
        }
1417
1418
        if ('personal' !== $this->type) {
1419
            return;
1420
        }
1421
1422
        $em = Database::getManager();
1423
1424
        $currentUser = api_get_user_entity(api_get_user_id());
1425
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1426
1427
        /** @var AgendaEventSubscription $subscription */
1428
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1429
1430
        if (!$subscription) {
1431
            return;
1432
        }
1433
1434
        if ($subscription->getInvitees()->count() >= $subscription->getMaxAttendees()
1435
            && $subscription->getMaxAttendees() > 0
1436
        ) {
1437
            return;
1438
        }
1439
1440
        if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $personalEvent->getSubscriptionVisibility()) {
1441
            $objGroup = new UserGroup();
1442
            $groupList = $objGroup->getUserGroupListByUser($currentUser->getId(), UserGroup::NORMAL_CLASS);
1443
            $groupIdList = array_column($groupList, 'id');
1444
1445
            if (!in_array($personalEvent->getSubscriptionItemId(), $groupIdList)) {
1446
                return;
1447
            }
1448
        }
1449
1450
        $subscriber = (new AgendaEventSubscriber())
1451
            ->setUser($currentUser)
1452
        ;
1453
1454
        $subscription->addInvitee($subscriber);
1455
1456
        $em->flush();
1457
    }
1458
1459
    public function unsubscribeCurrentUserToEvent(int $id)
1460
    {
1461
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1462
            return;
1463
        }
1464
1465
        if ('personal' !== $this->type) {
1466
            return;
1467
        }
1468
1469
        $em = Database::getManager();
1470
1471
        $currentUser = api_get_user_entity(api_get_user_id());
1472
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1473
1474
        /** @var AgendaEventSubscription $subscription */
1475
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1476
1477
        if (!$subscription) {
1478
            return;
1479
        }
1480
1481
        $subscription->removeInviteeUser($currentUser);
1482
1483
        $em->flush();
1484
    }
1485
1486
    /**
1487
     * Get agenda events.
1488
     *
1489
     * @param int    $start
1490
     * @param int    $end
1491
     * @param int    $courseId
1492
     * @param int    $groupId
1493
     * @param int    $user_id
1494
     * @param string $format
1495
     *
1496
     * @return array|string
1497
     */
1498
    public function getEvents(
1499
        $start,
1500
        $end,
1501
        $courseId = null,
1502
        $groupId = null,
1503
        $user_id = 0,
1504
        $format = 'json'
1505
    ) {
1506
        switch ($this->type) {
1507
            case 'admin':
1508
                $this->getPlatformEvents($start, $end);
1509
                break;
1510
            case 'course':
1511
                $courseInfo = api_get_course_info_by_id($courseId);
1512
1513
                // Session coach can see all events inside a session.
1514
                if (api_is_coach()) {
1515
                    // Own course
1516
                    $this->getCourseEvents(
1517
                        $start,
1518
                        $end,
1519
                        $courseInfo,
1520
                        $groupId,
1521
                        $this->sessionId,
1522
                        $user_id
1523
                    );
1524
1525
                    // Others
1526
                    $this->getSessionEvents(
1527
                        $start,
1528
                        $end,
1529
                        $this->sessionId,
1530
                        $user_id,
1531
                        $this->eventOtherSessionColor
1532
                    );
1533
                } else {
1534
                    $this->getCourseEvents(
1535
                        $start,
1536
                        $end,
1537
                        $courseInfo,
1538
                        $groupId,
1539
                        $this->sessionId,
1540
                        $user_id
1541
                    );
1542
                }
1543
                break;
1544
            case 'personal':
1545
            default:
1546
                $sessionFilterActive = false;
1547
                if (!empty($this->sessionId)) {
1548
                    $sessionFilterActive = true;
1549
                }
1550
1551
                if ($sessionFilterActive == false) {
1552
                    // Getting personal events
1553
                    $this->getPersonalEvents($start, $end);
1554
1555
                    // Getting platform/admin events
1556
                    $this->getPlatformEvents($start, $end);
1557
                }
1558
1559
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1560
1561
                $session_list = [];
1562
                // Getting course events
1563
                $my_course_list = [];
1564
                if (!api_is_anonymous()) {
1565
                    $session_list = SessionManager::get_sessions_by_user(
1566
                        api_get_user_id(),
1567
                        $ignoreVisibility
1568
                    );
1569
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1570
                        api_get_user_id(),
1571
                        false
1572
                    );
1573
                }
1574
1575
                if (api_is_drh()) {
1576
                    if (api_drh_can_access_all_session_content()) {
1577
                        $session_list = [];
1578
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1579
                            api_get_user_id(),
1580
                            null,
1581
                            null,
1582
                            null,
1583
                            true,
1584
                            false
1585
                        );
1586
1587
                        if (!empty($sessionList)) {
1588
                            foreach ($sessionList as $sessionItem) {
1589
                                $sessionId = $sessionItem['id'];
1590
                                $courses = SessionManager::get_course_list_by_session_id($sessionId);
1591
                                $sessionInfo = [
1592
                                    'session_id' => $sessionId,
1593
                                    'courses' => $courses,
1594
                                ];
1595
                                $session_list[] = $sessionInfo;
1596
                            }
1597
                        }
1598
                    }
1599
                }
1600
1601
                if (!empty($session_list)) {
1602
                    foreach ($session_list as $session_item) {
1603
                        if ($sessionFilterActive) {
1604
                            if ($this->sessionId != $session_item['session_id']) {
1605
                                continue;
1606
                            }
1607
                        }
1608
1609
                        $my_courses = $session_item['courses'];
1610
                        $my_session_id = $session_item['session_id'];
1611
1612
                        if (!empty($my_courses)) {
1613
                            foreach ($my_courses as $course_item) {
1614
                                $courseInfo = api_get_course_info_by_id(
1615
                                    $course_item['real_id']
1616
                                );
1617
                                $this->getCourseEvents(
1618
                                    $start,
1619
                                    $end,
1620
                                    $courseInfo,
1621
                                    0,
1622
                                    $my_session_id
1623
                                );
1624
                            }
1625
                        }
1626
                    }
1627
                }
1628
1629
                if (!empty($my_course_list) && $sessionFilterActive == false) {
1630
                    foreach ($my_course_list as $courseInfoItem) {
1631
                        $courseInfo = api_get_course_info_by_id(
1632
                            $courseInfoItem['real_id']
1633
                        );
1634
                        if (isset($courseId) && !empty($courseId)) {
1635
                            if ($courseInfo['real_id'] == $courseId) {
1636
                                $this->getCourseEvents(
1637
                                    $start,
1638
                                    $end,
1639
                                    $courseInfo,
1640
                                    0,
1641
                                    0,
1642
                                    $user_id
1643
                                );
1644
                            }
1645
                        } else {
1646
                            $this->getCourseEvents(
1647
                                $start,
1648
                                $end,
1649
                                $courseInfo,
1650
                                0,
1651
                                0,
1652
                                $user_id
1653
                            );
1654
                        }
1655
                    }
1656
                }
1657
1658
                if ($start && $end) {
1659
                    $this->loadSessionsAsEvents($start, $end);
1660
                }
1661
1662
                break;
1663
        }
1664
1665
        if (api_get_configuration_value('agenda_reminders')) {
1666
            $this->events = array_map(
1667
                function (array $eventInfo) {
1668
                    $id = str_replace(['personal_', 'course_', 'session_'], '', $eventInfo['id']);
1669
1670
                    $eventInfo['reminders'] = $this->parseEventReminders(
1671
                        $this->getEventReminders(
1672
                            $id,
1673
                            'session' === $eventInfo['type'] ? 'course' : $eventInfo['type']
1674
                        )
1675
                    );
1676
1677
                    return $eventInfo;
1678
                },
1679
                $this->events
1680
            );
1681
        }
1682
1683
        $this->cleanEvents();
1684
1685
        switch ($format) {
1686
            case 'json':
1687
                if (empty($this->events)) {
1688
                    return '[]';
1689
                }
1690
1691
                return json_encode($this->events);
1692
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1693
            case 'array':
1694
                if (empty($this->events)) {
1695
                    return [];
1696
                }
1697
1698
                return $this->events;
1699
                break;
1700
        }
1701
    }
1702
1703
    /**
1704
     * Clean events.
1705
     *
1706
     * @return bool
1707
     */
1708
    public function cleanEvents()
1709
    {
1710
        if (empty($this->events)) {
1711
            return false;
1712
        }
1713
1714
        foreach ($this->events as &$event) {
1715
            $event['description'] = Security::remove_XSS($event['description']);
1716
            $event['title'] = Security::remove_XSS($event['title']);
1717
        }
1718
1719
        return true;
1720
    }
1721
1722
    /**
1723
     * @param int $id
1724
     * @param int $minute_delta
1725
     *
1726
     * @return int
1727
     */
1728
    public function resizeEvent($id, $minute_delta)
1729
    {
1730
        $id = (int) $id;
1731
        $delta = (int) $minute_delta;
1732
        $event = $this->get_event($id);
1733
        if (!empty($event)) {
1734
            switch ($this->type) {
1735
                case 'personal':
1736
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1737
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1738
							WHERE id = ".$id;
1739
                    Database::query($sql);
1740
                    break;
1741
                case 'course':
1742
                    $sql = "UPDATE $this->tbl_course_agenda SET
1743
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1744
							WHERE
1745
							    c_id = ".$this->course['real_id']." AND
1746
							    id = ".$id;
1747
                    Database::query($sql);
1748
                    break;
1749
                case 'admin':
1750
                    $sql = "UPDATE $this->tbl_global_agenda SET
1751
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1752
							WHERE id = ".$id;
1753
                    Database::query($sql);
1754
                    break;
1755
            }
1756
        }
1757
1758
        return 1;
1759
    }
1760
1761
    /**
1762
     * @param int $id
1763
     * @param int $minute_delta minutes
1764
     * @param int $allDay
1765
     *
1766
     * @return int
1767
     */
1768
    public function move_event($id, $minute_delta, $allDay)
1769
    {
1770
        $id = (int) $id;
1771
        $event = $this->get_event($id);
1772
1773
        if (empty($event)) {
1774
            return false;
1775
        }
1776
1777
        // we convert the hour delta into minutes and add the minute delta
1778
        $delta = (int) $minute_delta;
1779
        $allDay = (int) $allDay;
1780
1781
        if (!empty($event)) {
1782
            switch ($this->type) {
1783
                case 'personal':
1784
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1785
                            all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE),
1786
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1787
							WHERE id=".$id;
1788
                    Database::query($sql);
1789
                    break;
1790
                case 'course':
1791
                    $sql = "UPDATE $this->tbl_course_agenda SET
1792
                            all_day = $allDay,
1793
                            start_date = DATE_ADD(start_date, INTERVAL $delta MINUTE),
1794
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1795
							WHERE
1796
							    c_id = ".$this->course['real_id']." AND
1797
							    id=".$id;
1798
                    Database::query($sql);
1799
                    break;
1800
                case 'admin':
1801
                    $sql = "UPDATE $this->tbl_global_agenda SET
1802
                            all_day = $allDay,
1803
                            start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
1804
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1805
							WHERE id=".$id;
1806
                    Database::query($sql);
1807
                    break;
1808
            }
1809
        }
1810
1811
        return 1;
1812
    }
1813
1814
    /**
1815
     * Gets a single event.
1816
     *
1817
     * @param int $id event id
1818
     *
1819
     * @return array
1820
     */
1821
    public function get_event($id)
1822
    {
1823
        // make sure events of the personal agenda can only be seen by the user himself
1824
        $id = (int) $id;
1825
        $event = null;
1826
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
1827
1828
        switch ($this->type) {
1829
            case 'personal':
1830
                $user = api_get_user_entity(api_get_user_id());
1831
                $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1832
                        WHERE id = $id AND user = ".$user->getId();
1833
                $result = Database::query($sql);
1834
                if (Database::num_rows($result)) {
1835
                    $event = Database::fetch_array($result, 'ASSOC');
1836
                    $event['description'] = $event['text'];
1837
                    $event['content'] = $event['text'];
1838
                    $event['start_date'] = $event['date'];
1839
                    $event['end_date'] = $event['enddate'];
1840
                }
1841
1842
                if (null !== $event) {
1843
                    return $event;
1844
                }
1845
1846
                if ($agendaCollectiveInvitations) {
1847
                    $eventRepo = Database::getManager()->getRepository('ChamiloCoreBundle:PersonalAgenda');
1848
                    $event = $eventRepo->findOneByIdAndInvitee($id, $user);
1849
1850
                    if ($event && $event->isCollective()) {
1851
                        return [
1852
                            'id' => $event->getId(),
1853
                            'user' => $event->getUser(),
1854
                            'title' => $event->getTitle(),
1855
                            'text' => $event->getText(),
1856
                            'date' => $event->getDate()->format('Y-m-d H:i:s'),
1857
                            'enddate' => $event->getEndDate()->format('Y-m-d H:i:s'),
1858
                            'course' => null,
1859
                            'parent_event_id' => $event->getParentEventId(),
1860
                            'all_day' => $event->getAllDay(),
1861
                            'color' => $event->getColor(),
1862
                            'agenda_event_invitation_id' => $event->getInvitation()->getId(),
1863
                            'collective' => $event->isCollective(),
1864
                            'description' => $event->getText(),
1865
                            'content' => $event->getText(),
1866
                            'start_date' => $event->getDate()->format('Y-m-d H:i:s'),
1867
                            'end_date' => $event->getEndDate()->format('Y-m-d H:i:s'),
1868
                        ];
1869
                    }
1870
                }
1871
1872
                return null;
1873
            case 'course':
1874
                if (!empty($this->course['real_id'])) {
1875
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
1876
                            WHERE c_id = ".$this->course['real_id']." AND id = ".$id;
1877
                    $result = Database::query($sql);
1878
                    if (Database::num_rows($result)) {
1879
                        $event = Database::fetch_array($result, 'ASSOC');
1880
                        $event['description'] = $event['content'];
1881
1882
                        // Getting send to array
1883
                        $event['send_to'] = $this->getUsersAndGroupSubscribedToEvent(
1884
                            $id,
1885
                            $this->course['real_id'],
1886
                            $this->sessionId
1887
                        );
1888
1889
                        // Getting repeat info
1890
                        $event['repeat_info'] = $this->getRepeatedInfoByEvent(
1891
                            $id,
1892
                            $this->course['real_id']
1893
                        );
1894
1895
                        if (!empty($event['parent_event_id'])) {
1896
                            $event['parent_info'] = $this->get_event($event['parent_event_id']);
1897
                        }
1898
1899
                        $event['attachment'] = $this->getAttachmentList(
1900
                            $id,
1901
                            $this->course
1902
                        );
1903
                    }
1904
                }
1905
                break;
1906
            case 'admin':
1907
            case 'platform':
1908
                $sql = "SELECT * FROM ".$this->tbl_global_agenda."
1909
                        WHERE id = $id";
1910
                $result = Database::query($sql);
1911
                if (Database::num_rows($result)) {
1912
                    $event = Database::fetch_array($result, 'ASSOC');
1913
                    $event['description'] = $event['content'];
1914
                }
1915
                break;
1916
        }
1917
1918
        return $event;
1919
    }
1920
1921
    /**
1922
     * Gets personal events.
1923
     *
1924
     * @param int $start
1925
     * @param int $end
1926
     *
1927
     * @return array
1928
     */
1929
    public function getPersonalEvents($start, $end)
1930
    {
1931
        $start = (int) $start;
1932
        $end = (int) $end;
1933
        $startDate = null;
1934
        $endDate = null;
1935
        $startCondition = '';
1936
        $endCondition = '';
1937
1938
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
1939
        $agendaEventSubscriptions = api_get_configuration_value('agenda_event_subscriptions');
1940
        $userIsAdmin = api_is_platform_admin();
1941
1942
        $queryParams = [];
1943
1944
        if ($start !== 0) {
1945
            $queryParams['start_date'] = api_get_utc_datetime($start, true, true);
1946
            $startCondition = "AND pa.date >= :start_date";
1947
        }
1948
        if ($end !== 0) {
1949
            $queryParams['end_date'] = api_get_utc_datetime($end, false, true);
1950
            $endCondition = "AND (pa.enddate <= :end_date OR pa.enddate IS NULL)";
1951
        }
1952
        $user_id = api_get_user_id();
1953
1954
        $queryParams['user_id'] = $user_id;
1955
        $userCondition = "pa.user = :user_id";
1956
1957
        $objGroup = new UserGroup();
1958
1959
        if ($agendaEventSubscriptions) {
1960
            $groupList = $objGroup->getUserGroupListByUser($user_id, UserGroup::NORMAL_CLASS);
1961
1962
            $userCondition = "(
1963
                    $userCondition
1964
                    OR (
1965
                        pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_ALL;
1966
1967
            if ($groupList) {
1968
                $userCondition .= "
1969
                        OR (
1970
                            pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_CLASS."
1971
                            AND pa.subscriptionItemId IN (".implode(', ', array_column($groupList, 'id')).")
1972
                        )
1973
                ";
1974
            }
1975
1976
            $userCondition .= "
1977
                    )
1978
                )
1979
            ";
1980
        }
1981
1982
        $sql = "SELECT pa FROM ChamiloCoreBundle:PersonalAgenda AS pa WHERE $userCondition $startCondition $endCondition";
1983
1984
        $result = Database::getManager()
1985
            ->createQuery($sql)
1986
            ->setParameters($queryParams)
1987
            ->getResult();
1988
1989
        $my_events = [];
1990
1991
        /** @var PersonalAgenda $row */
1992
        foreach ($result as $row) {
1993
            $event = [];
1994
            $event['id'] = 'personal_'.$row->getId();
1995
            $event['title'] = $row->getTitle();
1996
            $event['className'] = 'personal';
1997
            $event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
1998
            $event['editable'] = $user_id === (int) $row->getUser();
1999
            $event['sent_to'] = get_lang('Me');
2000
            $event['type'] = 'personal';
2001
2002
            if (!empty($row->getDate())) {
2003
                $event['start'] = $this->formatEventDate($row->getDate());
2004
                $event['start_date_localtime'] = api_get_local_time($row->getDate());
2005
            }
2006
2007
            if (!empty($row->getEnddate())) {
2008
                $event['end'] = $this->formatEventDate($row->getEnddate());
2009
                $event['end_date_localtime'] = api_get_local_time($row->getEnddate());
2010
            }
2011
2012
            $event['description'] = $row->getText();
2013
            $event['allDay'] = $row->getAllDay();
2014
            $event['parent_event_id'] = 0;
2015
            $event['has_children'] = 0;
2016
2017
            if ($agendaCollectiveInvitations || $agendaEventSubscriptions) {
2018
                $subscription = $row->getInvitation();
2019
2020
                if ($subscription instanceof AgendaEventSubscription) {
2021
                    $subscribers = $subscription->getInvitees();
2022
2023
                    $event['subscription_visibility'] = $row->getSubscriptionVisibility();
2024
                    $event['max_subscriptions'] = $subscription->getMaxAttendees();
2025
                    $event['can_subscribe'] = $subscribers->count() < $subscription->getMaxAttendees()
2026
                        || $subscription->getMaxAttendees() === 0;
2027
                    $event['user_is_subscribed'] = $subscription->hasUserAsInvitee(api_get_user_entity($user_id));
2028
                    $event['count_subscribers'] = $subscribers->count();
2029
2030
                    if ($userIsAdmin) {
2031
                        $event['subscribers'] = self::getInviteesForPersonalEvent($row->getId(), AgendaEventSubscriber::class);
2032
                    }
2033
2034
                    if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $row->getSubscriptionVisibility()) {
2035
                        $groupInfo = $objGroup->get($row->getSubscriptionItemId());
2036
                        $event['usergroup'] = $groupInfo['name'];
2037
                    }
2038
                } else {
2039
                    $event['collective'] = $row->isCollective();
2040
                    $event['invitees'] = self::getInviteesForPersonalEvent($row->getId());
2041
                }
2042
            }
2043
2044
            $my_events[] = $event;
2045
            $this->events[] = $event;
2046
        }
2047
2048
        if ($agendaCollectiveInvitations) {
2049
            $this->loadEventsAsInvitee(
2050
                api_get_user_entity($user_id),
2051
                $startDate,
2052
                $endDate
2053
            );
2054
        }
2055
2056
        // Add plugin personal events
2057
2058
        $this->plugin = new AppPlugin();
2059
        $plugins = $this->plugin->getInstalledPluginListObject();
2060
        /** @var Plugin $plugin */
2061
        foreach ($plugins as $plugin) {
2062
            if ($plugin->hasPersonalEvents && method_exists($plugin, 'getPersonalEvents')) {
2063
                $pluginEvents = $plugin->getPersonalEvents($this, $start, $end);
2064
2065
                if (!empty($pluginEvents)) {
2066
                    $this->events = array_merge($this->events, $pluginEvents);
2067
                }
2068
            }
2069
        }
2070
2071
        return $my_events;
2072
    }
2073
2074
    public static function getInviteesForPersonalEvent($eventId, $type = AgendaEventInvitee::class): array
2075
    {
2076
        $em = Database::getManager();
2077
        $event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
2078
2079
        $invitation = $event->getInvitation();
2080
2081
        if ($invitation instanceof AgendaEventSubscription
2082
            && AgendaEventInvitee::class === $type
2083
        ) {
2084
            return [];
2085
        }
2086
2087
        $inviteeRepo = $em->getRepository($type);
2088
        $invitees = $inviteeRepo->findByInvitation($invitation);
2089
2090
        $inviteeList = [];
2091
2092
        foreach ($invitees as $invitee) {
2093
            $inviteeUser = $invitee->getUser();
2094
2095
            $inviteeList[] = [
2096
                'id' => $inviteeUser->getId(),
2097
                'name' => $inviteeUser->getCompleteNameWithUsername(),
2098
            ];
2099
        }
2100
2101
        return $inviteeList;
2102
    }
2103
2104
    /**
2105
     * Get user/group list per event.
2106
     *
2107
     * @param int $eventId
2108
     * @param int $courseId
2109
     * @param int $sessionId
2110
     * @paraù int $sessionId
2111
     *
2112
     * @return array
2113
     */
2114
    public function getUsersAndGroupSubscribedToEvent(
2115
        $eventId,
2116
        $courseId,
2117
        $sessionId
2118
    ) {
2119
        $eventId = (int) $eventId;
2120
        $courseId = (int) $courseId;
2121
        $sessionId = (int) $sessionId;
2122
2123
        $sessionCondition = "ip.session_id = $sessionId";
2124
        if (empty($sessionId)) {
2125
            $sessionCondition = " (ip.session_id = 0 OR ip.session_id IS NULL) ";
2126
        }
2127
2128
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
2129
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2130
2131
        // Get sent_tos
2132
        $sql = "SELECT DISTINCT to_user_id, to_group_id
2133
                FROM $tbl_property ip
2134
                INNER JOIN $tlb_course_agenda agenda
2135
                ON (
2136
                  ip.ref = agenda.id AND
2137
                  ip.c_id = agenda.c_id AND
2138
                  ip.tool = '".TOOL_CALENDAR_EVENT."'
2139
                )
2140
                WHERE
2141
                    ref = $eventId AND
2142
                    ip.visibility = '1' AND
2143
                    ip.c_id = $courseId AND
2144
                    $sessionCondition
2145
                ";
2146
2147
        $result = Database::query($sql);
2148
        $users = [];
2149
        $groups = [];
2150
        $everyone = false;
2151
2152
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2153
            if (!empty($row['to_group_id'])) {
2154
                $groups[] = $row['to_group_id'];
2155
            }
2156
            if (!empty($row['to_user_id'])) {
2157
                $users[] = $row['to_user_id'];
2158
            }
2159
2160
            if (empty($groups) && empty($users)) {
2161
                if ($row['to_group_id'] == 0) {
2162
                    $everyone = true;
2163
                }
2164
            }
2165
        }
2166
2167
        return [
2168
            'everyone' => $everyone,
2169
            'users' => $users,
2170
            'groups' => $groups,
2171
        ];
2172
    }
2173
2174
    /**
2175
     * @param int    $start
2176
     * @param int    $end
2177
     * @param int    $sessionId
2178
     * @param int    $userId
2179
     * @param string $color
2180
     *
2181
     * @return array
2182
     */
2183
    public function getSessionEvents(
2184
        $start,
2185
        $end,
2186
        $sessionId = 0,
2187
        $userId = 0,
2188
        $color = ''
2189
    ) {
2190
        $courses = SessionManager::get_course_list_by_session_id($sessionId);
2191
2192
        if (!empty($courses)) {
2193
            foreach ($courses as $course) {
2194
                $this->getCourseEvents(
2195
                    $start,
2196
                    $end,
2197
                    $course,
2198
                    0,
2199
                    $sessionId,
2200
                    0,
2201
                    $color
2202
                );
2203
            }
2204
        }
2205
    }
2206
2207
    /**
2208
     * @param int    $start
2209
     * @param int    $end
2210
     * @param array  $courseInfo
2211
     * @param int    $groupId
2212
     * @param int    $sessionId
2213
     * @param int    $user_id
2214
     * @param string $color
2215
     *
2216
     * @return array
2217
     */
2218
    public function getCourseEvents(
2219
        $start,
2220
        $end,
2221
        $courseInfo,
2222
        $groupId = 0,
2223
        $sessionId = 0,
2224
        $user_id = 0,
2225
        $color = ''
2226
    ) {
2227
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
2228
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
2229
2230
        if (empty($courseInfo)) {
2231
            return [];
2232
        }
2233
        $courseId = $courseInfo['real_id'];
2234
2235
        if (empty($courseId)) {
2236
            return [];
2237
        }
2238
2239
        $sessionId = (int) $sessionId;
2240
        $user_id = (int) $user_id;
2241
2242
        $groupList = GroupManager::get_group_list(
2243
            null,
2244
            $courseInfo,
2245
            null,
2246
            $sessionId
2247
        );
2248
2249
        $groupNameList = [];
2250
        if (!empty($groupList)) {
2251
            foreach ($groupList as $group) {
2252
                $groupNameList[$group['iid']] = $group['name'];
2253
            }
2254
        }
2255
2256
        if (api_is_platform_admin() || api_is_allowed_to_edit()) {
2257
            $isAllowToEdit = true;
2258
        } else {
2259
            $isAllowToEdit = CourseManager::is_course_teacher(
2260
                api_get_user_id(),
2261
                $courseInfo['code']
2262
            );
2263
        }
2264
2265
        $isAllowToEditByHrm = false;
2266
        if (!empty($sessionId)) {
2267
            $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
2268
            if ($allowDhrToEdit) {
2269
                $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
2270
                if ($isHrm) {
2271
                    $isAllowToEdit = $isAllowToEditByHrm = true;
2272
                }
2273
            }
2274
        }
2275
2276
        $groupMemberships = [];
2277
        if (!empty($groupId)) {
2278
            $groupMemberships = [$groupId];
2279
        } else {
2280
            if ($isAllowToEdit) {
2281
                if (!empty($groupList)) {
2282
                    // c_item_property.to_group_id field was migrated to use
2283
                    // c_group_info.iid
2284
                    $groupMemberships = array_column($groupList, 'iid');
2285
                }
2286
            } else {
2287
                // get only related groups from user
2288
                $groupMemberships = GroupManager::get_group_ids(
2289
                    $courseId,
2290
                    api_get_user_id()
2291
                );
2292
            }
2293
        }
2294
2295
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
2296
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2297
2298
        $shareEventsInSessions = 1 == api_get_course_setting('agenda_share_events_in_sessions', $courseInfo);
2299
2300
        $agendaSessionCondition = str_replace(
2301
            ' AND ',
2302
            '',
2303
            api_get_session_condition($sessionId, true, $shareEventsInSessions, 'agenda.session_id')
2304
        );
2305
        $ipSessionCondition = api_get_session_condition($sessionId, true, $shareEventsInSessions, 'ip.session_id');
2306
2307
        $sessionCondition = "($agendaSessionCondition $ipSessionCondition)";
2308
2309
        if ($isAllowToEdit) {
2310
            // No group filter was asked
2311
            if (empty($groupId)) {
2312
                if (empty($user_id)) {
2313
                    // Show all events not added in group
2314
                    $userCondition = ' (ip.to_group_id IS NULL OR ip.to_group_id = 0) ';
2315
                    // admin see only his stuff
2316
                    if ($this->type === 'personal') {
2317
                        $userCondition = " (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ) ";
2318
                        $userCondition .= " OR ( (ip.to_user_id = 0 OR ip.to_user_id is NULL)  AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ) ";
2319
                    }
2320
2321
                    if (!empty($groupMemberships)) {
2322
                        // Show events sent to selected groups
2323
                        $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2324
                    }
2325
                } else {
2326
                    // Show events of requested user in no group
2327
                    $userCondition = " (ip.to_user_id = $user_id AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
2328
                    // Show events sent to selected groups
2329
                    if (!empty($groupMemberships)) {
2330
                        $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2331
                    }
2332
                }
2333
            } else {
2334
                // Show only selected groups (depending of user status)
2335
                $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2336
2337
                if (!empty($groupMemberships)) {
2338
                    // Show send to $user_id in selected groups
2339
                    $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2340
                }
2341
            }
2342
        } else {
2343
            // No group filter was asked
2344
            if (empty($groupId)) {
2345
                // Show events sent to everyone and no group
2346
                $userCondition = ' ( (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ';
2347
2348
                // Show events sent to selected groups
2349
                if (!empty($groupMemberships)) {
2350
                    $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships)."))) ";
2351
                } else {
2352
                    $userCondition .= " ) ";
2353
                }
2354
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
2355
            } else {
2356
                if (!empty($groupMemberships)) {
2357
                    // Show send to everyone - and only selected groups
2358
                    $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2359
                }
2360
            }
2361
2362
            // Show sent to only me and no group
2363
            if (!empty($groupMemberships)) {
2364
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id().") AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2365
            } else {
2366
                // Show sent to only me and selected groups
2367
            }
2368
        }
2369
2370
        if (api_is_allowed_to_edit()) {
2371
            $visibilityCondition = " (ip.visibility IN ('1', '0'))  ";
2372
        } else {
2373
            $visibilityCondition = " (ip.visibility = '1') ";
2374
        }
2375
2376
        $sql = "SELECT DISTINCT
2377
                    agenda.*,
2378
                    ip.visibility,
2379
                    ip.to_group_id,
2380
                    ip.insert_user_id,
2381
                    ip.ref,
2382
                    to_user_id
2383
                FROM $tlb_course_agenda agenda
2384
                INNER JOIN $tbl_property ip
2385
                ON (
2386
                    agenda.id = ip.ref AND
2387
                    agenda.c_id = ip.c_id AND
2388
                    ip.tool = '".TOOL_CALENDAR_EVENT."'
2389
                )
2390
                WHERE
2391
                    $sessionCondition AND
2392
                    ($userCondition) AND
2393
                    $visibilityCondition AND
2394
                    agenda.c_id = $courseId
2395
        ";
2396
        $dateCondition = '';
2397
        if (!empty($start) && !empty($end)) {
2398
            $dateCondition .= "AND (
2399
                 agenda.start_date BETWEEN '".$start."' AND '".$end."' OR
2400
                 agenda.end_date BETWEEN '".$start."' AND '".$end."' OR
2401
                 (
2402
                     agenda.start_date IS NOT NULL AND agenda.end_date IS NOT NULL AND
2403
                     YEAR(agenda.start_date) = YEAR(agenda.end_date) AND
2404
                     MONTH('$start') BETWEEN MONTH(agenda.start_date) AND MONTH(agenda.end_date)
2405
                 )
2406
            )";
2407
        }
2408
2409
        $sql .= $dateCondition;
2410
        $result = Database::query($sql);
2411
2412
        $coachCanEdit = false;
2413
        if (!empty($sessionId)) {
2414
            $coachCanEdit = api_is_coach($sessionId, $courseId) || api_is_platform_admin();
2415
        }
2416
2417
        if (Database::num_rows($result)) {
2418
            $eventsAdded = array_column($this->events, 'unique_id');
2419
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2420
                $event = [];
2421
                $event['id'] = 'course_'.$row['id'];
2422
                $event['unique_id'] = $row['iid'];
2423
                // To avoid doubles
2424
                if (in_array($event['unique_id'], $eventsAdded)) {
2425
                    continue;
2426
                }
2427
2428
                $eventsAdded[] = $event['unique_id'];
2429
                $eventId = $row['ref'];
2430
                $items = $this->getUsersAndGroupSubscribedToEvent(
2431
                    $eventId,
2432
                    $courseId,
2433
                    $this->sessionId
2434
                );
2435
                $group_to_array = $items['groups'];
2436
                $user_to_array = $items['users'];
2437
                $attachmentList = $this->getAttachmentList(
2438
                    $row['id'],
2439
                    $courseInfo
2440
                );
2441
                $event['attachment'] = '';
2442
                if (!empty($attachmentList)) {
2443
                    foreach ($attachmentList as $attachment) {
2444
                        $has_attachment = Display::return_icon(
2445
                            'attachment.gif',
2446
                            get_lang('Attachment')
2447
                        );
2448
                        $user_filename = $attachment['filename'];
2449
                        $url = api_get_path(WEB_CODE_PATH).'calendar/download.php?file='.$attachment['path'].'&course_id='.$courseId.'&'.api_get_cidreq();
2450
                        $event['attachment'] .= $has_attachment.
2451
                            Display::url(
2452
                                $user_filename,
2453
                                $url
2454
                            ).'<br />';
2455
                    }
2456
                }
2457
2458
                $event['title'] = $row['title'];
2459
                $event['className'] = 'course';
2460
                $event['allDay'] = 'false';
2461
                $event['course_id'] = $courseId;
2462
                $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color;
2463
2464
                $sessionInfo = [];
2465
                if (isset($row['session_id']) && !empty($row['session_id'])) {
2466
                    $sessionInfo = api_get_session_info($sessionId);
2467
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_session_color;
2468
                }
2469
2470
                $event['session_name'] = isset($sessionInfo['name']) ? $sessionInfo['name'] : '';
2471
                $event['course_name'] = isset($courseInfo['title']) ? $courseInfo['title'] : '';
2472
2473
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
2474
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_group_color;
2475
                }
2476
2477
                if (!empty($color)) {
2478
                    $event['borderColor'] = $event['backgroundColor'] = $color;
2479
                }
2480
2481
                if (isset($row['color']) && !empty($row['color'])) {
2482
                    $event['borderColor'] = $event['backgroundColor'] = $row['color'];
2483
                }
2484
2485
                $event['editable'] = false;
2486
                if ($this->getIsAllowedToEdit() && $this->type == 'course') {
2487
                    $event['editable'] = true;
2488
                    if (!empty($sessionId)) {
2489
                        if ($coachCanEdit == false) {
2490
                            $event['editable'] = false;
2491
                        }
2492
                        if ($isAllowToEditByHrm) {
2493
                            $event['editable'] = true;
2494
                        }
2495
                        if ($sessionId != $row['session_id']) {
2496
                            $event['editable'] = false;
2497
                        }
2498
                    }
2499
                    // if user is author then he can edit the item
2500
                    if (api_get_user_id() == $row['insert_user_id']) {
2501
                        $event['editable'] = true;
2502
                    }
2503
                }
2504
2505
                if (!empty($row['start_date'])) {
2506
                    $event['start'] = $this->formatEventDate($row['start_date']);
2507
                    $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2508
                }
2509
                if (!empty($row['end_date'])) {
2510
                    $event['end'] = $this->formatEventDate($row['end_date']);
2511
                    $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2512
                }
2513
2514
                $event['sent_to'] = '';
2515
                $event['type'] = 'course';
2516
                if ($row['session_id'] != 0) {
2517
                    $event['type'] = 'session';
2518
                }
2519
2520
                // Event Sent to a group?
2521
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
2522
                    $sent_to = [];
2523
                    if (!empty($group_to_array)) {
2524
                        foreach ($group_to_array as $group_item) {
2525
                            $sent_to[] = $groupNameList[$group_item];
2526
                        }
2527
                    }
2528
                    $sent_to = implode('@@', $sent_to);
2529
                    $sent_to = str_replace(
2530
                        '@@',
2531
                        '</div><div class="label_tag notice">',
2532
                        $sent_to
2533
                    );
2534
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2535
                    $event['type'] = 'group';
2536
                    $event['group_id'] = $row['to_group_id'];
2537
                }
2538
2539
                // Event sent to a user?
2540
                if (isset($row['to_user_id'])) {
2541
                    $sent_to = [];
2542
                    if (!empty($user_to_array)) {
2543
                        foreach ($user_to_array as $item) {
2544
                            $user_info = api_get_user_info($item);
2545
                            // Add username as tooltip for $event['sent_to'] - ref #4226
2546
                            $username = api_htmlentities(
2547
                                sprintf(
2548
                                    get_lang('LoginX'),
2549
                                    $user_info['username']
2550
                                ),
2551
                                ENT_QUOTES
2552
                            );
2553
                            $sent_to[] = "<span title='".$username."'>".$user_info['complete_name']."</span>";
2554
                        }
2555
                    }
2556
                    $sent_to = implode('@@', $sent_to);
2557
                    $sent_to = str_replace(
2558
                        '@@',
2559
                        '</div><div class="label_tag notice">',
2560
                        $sent_to
2561
                    );
2562
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2563
                }
2564
2565
                //Event sent to everyone!
2566
                if (empty($event['sent_to'])) {
2567
                    $event['sent_to'] = '<div class="label_tag notice">'.get_lang('Everyone').'</div>';
2568
                }
2569
2570
                $event['description'] = Security::remove_XSS($row['content']);
2571
                $event['visibility'] = $row['visibility'];
2572
                $event['real_id'] = $row['id'];
2573
                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2574
                $event['parent_event_id'] = $row['parent_event_id'];
2575
                $event['has_children'] = $this->hasChildren($row['id'], $courseId) ? 1 : 0;
2576
                $event['comment'] = Security::remove_XSS($row['comment']);
2577
                $this->events[] = $event;
2578
            }
2579
        }
2580
2581
        return $this->events;
2582
    }
2583
2584
    /**
2585
     * @param int $start tms
2586
     * @param int $end   tms
2587
     *
2588
     * @return array
2589
     */
2590
    public function getPlatformEvents($start, $end)
2591
    {
2592
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
2593
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
2594
        $dateCondition = '';
2595
2596
        if (!empty($start) && !empty($end)) {
2597
            $dateCondition .= "AND (
2598
                 start_date BETWEEN '".$start."' AND '".$end."' OR
2599
                 end_date BETWEEN '".$start."' AND '".$end."' OR
2600
                 (
2601
                     start_date IS NOT NULL AND end_date IS NOT NULL AND
2602
                     YEAR(start_date) = YEAR(end_date) AND
2603
                     MONTH('$start') BETWEEN MONTH(start_date) AND MONTH(end_date)
2604
                 )
2605
            )";
2606
        }
2607
2608
        $access_url_id = api_get_current_access_url_id();
2609
2610
        $sql = "SELECT *
2611
                FROM ".$this->tbl_global_agenda."
2612
                WHERE access_url_id = $access_url_id
2613
                $dateCondition";
2614
        $result = Database::query($sql);
2615
2616
        if (!Database::num_rows($result)) {
2617
            return [];
2618
        }
2619
2620
        $my_events = [];
2621
        $allowCareersInGlobalAgenda = api_get_configuration_value('allow_careers_in_global_agenda');
2622
        $userId = api_get_user_id();
2623
        $userVisibility = SystemAnnouncementManager::getCurrentUserVisibility();
2624
2625
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2626
            $event = [];
2627
            $event['id'] = 'platform_'.$row['id'];
2628
            $event['title'] = $row['title'];
2629
            $event['className'] = 'platform';
2630
            $event['allDay'] = 'false';
2631
            $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color;
2632
            $event['editable'] = false;
2633
            $event['type'] = 'admin';
2634
2635
            if (api_is_platform_admin() && $this->type === 'admin') {
2636
                $event['editable'] = true;
2637
            }
2638
2639
            if (!empty($row['start_date'])) {
2640
                $event['start'] = $this->formatEventDate($row['start_date']);
2641
                $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2642
            }
2643
2644
            if (!empty($row['end_date'])) {
2645
                $event['end'] = $this->formatEventDate($row['end_date']);
2646
                $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2647
            }
2648
            $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2649
            $event['parent_event_id'] = 0;
2650
            $event['has_children'] = 0;
2651
            $event['description'] = $row['content'];
2652
2653
            if ($allowCareersInGlobalAgenda) {
2654
                $event['career'] = null;
2655
                $event['promotion'] = null;
2656
2657
                $careerId = (int) $row['career_id'];
2658
                $promotionId = (int) $row['promotion_id'];
2659
2660
                $careerPromotionEventIsVisibleForUser = true;
2661
2662
                if (($careerId || $promotionId) && 'admin' !== $this->type) {
2663
                    $careerPromotionEventIsVisibleForUser = SystemAnnouncementManager::isVisibleAnnouncementForUser(
2664
                        $userId,
2665
                        $userVisibility,
2666
                        $careerId,
2667
                        $promotionId
2668
                    );
2669
                }
2670
2671
                if (false === $careerPromotionEventIsVisibleForUser) {
2672
                    continue;
2673
                }
2674
2675
                if (0 !== $careerId) {
2676
                    $careerInfo = (new Career())->get($row['career_id']);
2677
2678
                    unset($careerInfo['status'], $careerInfo['created_at'], $careerInfo['updated_at']);
2679
2680
                    $event['career'] = $careerInfo;
2681
                }
2682
2683
                if (0 !== $promotionId) {
2684
                    $promotionInfo = (new Promotion())->get($row['promotion_id']);
2685
2686
                    unset(
2687
                        $promotionInfo['career_id'],
2688
                        $promotionInfo['status'],
2689
                        $promotionInfo['created_at'],
2690
                        $promotionInfo['updated_at']
2691
                    );
2692
2693
                    $event['promotion'] = $promotionInfo;
2694
                }
2695
            }
2696
2697
            $my_events[] = $event;
2698
            $this->events[] = $event;
2699
        }
2700
2701
        return $my_events;
2702
    }
2703
2704
    /**
2705
     * @param FormValidator $form
2706
     * @param array         $groupList
2707
     * @param array         $userList
2708
     * @param array         $sendTo               array('users' => [1, 2], 'groups' => [3, 4])
2709
     * @param array         $attributes
2710
     * @param bool          $addOnlyItemsInSendTo
2711
     * @param bool          $required
2712
     */
2713
    public function setSendToSelect(
2714
        $form,
2715
        $groupList = [],
2716
        $userList = [],
2717
        $sendTo = [],
2718
        $attributes = [],
2719
        $addOnlyItemsInSendTo = false,
2720
        $required = false
2721
    ) {
2722
        $params = [
2723
            'id' => 'users_to_send_id',
2724
            'data-placeholder' => get_lang('Select'),
2725
            'multiple' => 'multiple',
2726
            'class' => 'multiple-select',
2727
        ];
2728
2729
        if (!empty($attributes)) {
2730
            $params = array_merge($params, $attributes);
2731
            if (empty($params['multiple'])) {
2732
                unset($params['multiple']);
2733
            }
2734
        }
2735
2736
        $sendToGroups = isset($sendTo['groups']) ? $sendTo['groups'] : [];
2737
        $sendToUsers = isset($sendTo['users']) ? $sendTo['users'] : [];
2738
2739
        /** @var HTML_QuickForm_select $select */
2740
        $select = $form->addSelect(
2741
            'users_to_send',
2742
            get_lang('To'),
2743
            null,
2744
            $params
2745
        );
2746
2747
        if ($required) {
2748
            $form->setRequired($select);
2749
        }
2750
2751
        $selectedEveryoneOptions = [];
2752
        if (isset($sendTo['everyone']) && $sendTo['everyone']) {
2753
            $selectedEveryoneOptions = ['selected'];
2754
            $sendToUsers = [];
2755
        }
2756
2757
        $select->addOption(
2758
            get_lang('Everyone'),
2759
            'everyone',
2760
            $selectedEveryoneOptions
2761
        );
2762
2763
        $options = [];
2764
        if (is_array($groupList)) {
2765
            foreach ($groupList as $group) {
2766
                $count_users = isset($group['count_users']) ? $group['count_users'] : $group['userNb'];
2767
                $count_users = " &ndash; $count_users ".get_lang('Users');
2768
                $option = [
2769
                    'text' => $group['name'].$count_users,
2770
                    'value' => "GROUP:".$group['id'],
2771
                ];
2772
                $selected = in_array(
2773
                    $group['id'],
2774
                    $sendToGroups
2775
                ) ? true : false;
2776
                if ($selected) {
2777
                    $option['selected'] = 'selected';
2778
                }
2779
2780
                if ($addOnlyItemsInSendTo) {
2781
                    if ($selected) {
2782
                        $options[] = $option;
2783
                    }
2784
                } else {
2785
                    $options[] = $option;
2786
                }
2787
            }
2788
            $select->addOptGroup($options, get_lang('Groups'));
2789
        }
2790
2791
        // adding the individual users to the select form
2792
        if (is_array($userList)) {
2793
            $options = [];
2794
            foreach ($userList as $user) {
2795
                if ($user['status'] == ANONYMOUS) {
2796
                    continue;
2797
                }
2798
                $option = [
2799
                    'text' => api_get_person_name(
2800
                            $user['firstname'],
2801
                            $user['lastname']
2802
                        ).' ('.$user['username'].')',
2803
                    'value' => "USER:".$user['user_id'],
2804
                ];
2805
2806
                $selected = in_array(
2807
                    $user['user_id'],
2808
                    $sendToUsers
2809
                ) ? true : false;
2810
2811
                if ($selected) {
2812
                    $option['selected'] = 'selected';
2813
                }
2814
2815
                if ($addOnlyItemsInSendTo) {
2816
                    if ($selected) {
2817
                        $options[] = $option;
2818
                    }
2819
                } else {
2820
                    $options[] = $option;
2821
                }
2822
            }
2823
2824
            $select->addOptGroup($options, get_lang('Users'));
2825
        }
2826
    }
2827
2828
    /**
2829
     * Separates the users and groups array
2830
     * users have a value USER:XXX (with XXX the user id
2831
     * groups have a value GROUP:YYY (with YYY the group id)
2832
     * use the 'everyone' key.
2833
     *
2834
     * @author Julio Montoya based in separate_users_groups in agenda.inc.php
2835
     *
2836
     * @param array $to
2837
     *
2838
     * @return array
2839
     */
2840
    public function parseSendToArray($to)
2841
    {
2842
        $groupList = [];
2843
        $userList = [];
2844
        $sendTo = null;
2845
2846
        $sendTo['everyone'] = false;
2847
        if (is_array($to) && count($to) > 0) {
2848
            foreach ($to as $item) {
2849
                if ($item == 'everyone') {
2850
                    $sendTo['everyone'] = true;
2851
                } else {
2852
                    list($type, $id) = explode(':', $item);
2853
                    switch ($type) {
2854
                        case 'GROUP':
2855
                            $groupList[] = $id;
2856
                            break;
2857
                        case 'USER':
2858
                            $userList[] = $id;
2859
                            break;
2860
                    }
2861
                }
2862
            }
2863
            $sendTo['groups'] = $groupList;
2864
            $sendTo['users'] = $userList;
2865
        }
2866
2867
        return $sendTo;
2868
    }
2869
2870
    /**
2871
     * @param int    $eventId
2872
     * @param string $type
2873
     *
2874
     * @return array<int, AgendaReminder>
2875
     */
2876
    public function getEventReminders($eventId, $type = null): array
2877
    {
2878
        $em = Database::getManager();
2879
        $remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
2880
2881
        return $remindersRepo->findBy(
2882
            [
2883
                'eventId' => $eventId,
2884
                'type' => $type ?: $this->type,
2885
            ]
2886
        );
2887
    }
2888
2889
    public function parseEventReminders(array $eventReminders): array
2890
    {
2891
        return array_map(
2892
            function (AgendaReminder $reminder) {
2893
                $interval = $reminder->getDateInterval();
2894
2895
                $reminderInfo = [
2896
                    'id' => $reminder->getId(),
2897
                    'type' => $reminder->getType(),
2898
                    'sent' => $reminder->isSent(),
2899
                    'date_interval' => [$interval->format('%a'), 'd'],
2900
                ];
2901
2902
                if ($interval->i) {
2903
                    $reminderInfo['date_interval'] = [$interval->i, 'i'];
2904
                } elseif ($interval->h) {
2905
                    $reminderInfo['date_interval'] = [$interval->h, 'h'];
2906
                } elseif ($interval->d) {
2907
                    $reminderInfo['date_interval'] = [$interval->d, 'd'];
2908
                }
2909
2910
                return $reminderInfo;
2911
            },
2912
            $eventReminders
2913
        );
2914
    }
2915
2916
    /**
2917
     * @param array $params
2918
     *
2919
     * @return FormValidator
2920
     */
2921
    public function getForm($params = [])
2922
    {
2923
        $action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
2924
        $id = isset($params['id']) ? (int) $params['id'] : 0;
2925
2926
        $em = Database::getManager();
2927
        $personalEvent = 'personal' === $this->type && $id ? $em->find('ChamiloCoreBundle:PersonalAgenda', $id) : null;
2928
2929
        $url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
2930
        if ($this->type == 'course') {
2931
            $url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
2932
        }
2933
2934
        $form = new FormValidator(
2935
            'add_event',
2936
            'post',
2937
            $url,
2938
            null,
2939
            ['enctype' => 'multipart/form-data']
2940
        );
2941
2942
        $idAttach = isset($params['id_attach']) ? (int) $params['id_attach'] : null;
2943
        $groupId = api_get_group_id();
2944
        $form_Title = get_lang('AddCalendarItem');
2945
        if (!empty($id)) {
2946
            $form_Title = get_lang('ModifyCalendarItem');
2947
        }
2948
2949
        $form->addHeader($form_Title);
2950
        $form->addElement('hidden', 'id', $id);
2951
        $form->addElement('hidden', 'action', $action);
2952
        $form->addElement('hidden', 'id_attach', $idAttach);
2953
2954
        $isSubEventEdition = false;
2955
        $isParentFromSerie = false;
2956
        $showAttachmentForm = true;
2957
2958
        if ($this->type == 'course') {
2959
            // Edition mode.
2960
            if (!empty($id)) {
2961
                $showAttachmentForm = false;
2962
                if (isset($params['parent_event_id']) && !empty($params['parent_event_id'])) {
2963
                    $isSubEventEdition = true;
2964
                }
2965
                if (!empty($params['repeat_info'])) {
2966
                    $isParentFromSerie = true;
2967
                }
2968
            }
2969
        }
2970
2971
        if ($isSubEventEdition) {
2972
            $form->addElement(
2973
                'label',
2974
                null,
2975
                Display::return_message(
2976
                    get_lang('EditingThisEventWillRemoveItFromTheSerie'),
2977
                    'warning'
2978
                )
2979
            );
2980
        }
2981
2982
        $form->addElement('text', 'title', get_lang('ItemTitle'));
2983
2984
        if (isset($groupId) && !empty($groupId)) {
2985
            $form->addElement(
2986
                'hidden',
2987
                'users_to_send[]',
2988
                "GROUP:$groupId"
2989
            );
2990
            $form->addElement('hidden', 'to', 'true');
2991
        } else {
2992
            $sendTo = isset($params['send_to']) ? $params['send_to'] : ['everyone' => true];
2993
            if ($this->type == 'course') {
2994
                $this->showToForm($form, $sendTo, [], false, true);
2995
            }
2996
        }
2997
2998
        $form->addDateRangePicker(
2999
            'date_range',
3000
            get_lang('DateRange'),
3001
            false,
3002
            ['id' => 'date_range']
3003
        );
3004
        $form->addElement('checkbox', 'all_day', null, get_lang('AllDay'));
3005
3006
        if ($this->type == 'course') {
3007
            $repeat = $form->addElement(
3008
                'checkbox',
3009
                'repeat',
3010
                null,
3011
                get_lang('RepeatEvent'),
3012
                ['onclick' => 'return plus_repeated_event();']
3013
            );
3014
            $form->addElement(
3015
                'html',
3016
                '<div id="options2" style="display:none">'
3017
            );
3018
            $form->addElement(
3019
                'select',
3020
                'repeat_type',
3021
                get_lang('RepeatType'),
3022
                self::getRepeatTypes()
3023
            );
3024
            $form->addElement(
3025
                'date_picker',
3026
                'repeat_end_day',
3027
                get_lang('RepeatEnd'),
3028
                ['id' => 'repeat_end_date_form']
3029
            );
3030
3031
            if ($isSubEventEdition || $isParentFromSerie) {
3032
                $repeatInfo = $params['repeat_info'];
3033
                if ($isSubEventEdition) {
3034
                    $parentEvent = $params['parent_info'];
3035
                    $repeatInfo = $parentEvent['repeat_info'];
3036
                }
3037
                $params['repeat'] = 1;
3038
                $params['repeat_type'] = $repeatInfo['cal_type'];
3039
                $params['repeat_end_day'] = substr(
3040
                    api_get_local_time($repeatInfo['cal_end']),
3041
                    0,
3042
                    10
3043
                );
3044
3045
                $form->freeze(['repeat_type', 'repeat_end_day']);
3046
                $repeat->_attributes['disabled'] = 'disabled';
3047
            }
3048
            $form->addElement('html', '</div>');
3049
        }
3050
3051
        if (!empty($id)) {
3052
            if (empty($params['end_date'])) {
3053
                $params['date_range'] = $params['end_date'];
3054
            }
3055
3056
            $params['date_range'] =
3057
                substr(api_get_local_time($params['start_date']), 0, 16).' / '.
3058
                substr(api_get_local_time($params['end_date']), 0, 16);
3059
        }
3060
3061
        $toolbar = 'Agenda';
3062
        if (!api_is_allowed_to_edit(null, true)) {
3063
            $toolbar = 'AgendaStudent';
3064
        }
3065
3066
        $form->addElement(
3067
            'html_editor',
3068
            'content',
3069
            get_lang('Description'),
3070
            null,
3071
            [
3072
                'ToolbarSet' => $toolbar,
3073
                'Width' => '100%',
3074
                'Height' => '200',
3075
            ]
3076
        );
3077
3078
        if ($this->type == 'course') {
3079
            $form->addElement('textarea', 'comment', get_lang('Comment'));
3080
            $form->addLabel(
3081
                get_lang('FilesAttachment'),
3082
                '<div id="filepaths" class="file-upload-event">
3083
3084
                        <div id="filepath_1">
3085
                            <input type="file" name="attach_1"/>
3086
3087
                            <label>'.get_lang('Description').'</label>
3088
                            <input class="form-control" type="text" name="legend[]" />
3089
                        </div>
3090
3091
                    </div>'
3092
            );
3093
3094
            $form->addLabel(
3095
                '',
3096
                '<span id="link-more-attach">
3097
                    <a href="javascript://" onclick="return add_image_form()">'.
3098
                get_lang('AddOneMoreFile').'</a>
3099
                 </span>&nbsp;('.sprintf(
3100
                    get_lang('MaximunFileSizeX'),
3101
                    format_file_size(
3102
                        api_get_setting('message_max_upload_filesize')
3103
                    )
3104
                ).')'
3105
            );
3106
3107
            if (isset($params['attachment']) && !empty($params['attachment'])) {
3108
                $attachmentList = $params['attachment'];
3109
                foreach ($attachmentList as $attachment) {
3110
                    $params['file_comment'] = $attachment['comment'];
3111
                    if (!empty($attachment['path'])) {
3112
                        $form->addElement(
3113
                            'checkbox',
3114
                            'delete_attachment['.$attachment['id'].']',
3115
                            null,
3116
                            get_lang(
3117
                                'DeleteAttachment'
3118
                            ).': '.$attachment['filename']
3119
                        );
3120
                    }
3121
                }
3122
            }
3123
3124
            $form->addElement(
3125
                'textarea',
3126
                'file_comment',
3127
                get_lang('FileComment')
3128
            );
3129
        }
3130
3131
        if (empty($id) && 'course' === $this->type) {
3132
            $form->addElement(
3133
                'checkbox',
3134
                'add_announcement',
3135
                null,
3136
                get_lang('AddAnnouncement').'&nbsp('.get_lang('SendMail').')'
3137
            );
3138
        }
3139
3140
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
3141
        $agendaEventSubscriptions = api_is_platform_admin()
3142
            && true === api_get_configuration_value('agenda_event_subscriptions');
3143
3144
        $allowCollectiveInvitations = $agendaCollectiveInvitations && 'personal' === $this->type;
3145
        $allowEventSubscriptions = 'personal' === $this->type && $agendaEventSubscriptions;
3146
3147
        if ($allowCollectiveInvitations && $allowEventSubscriptions && !$personalEvent) {
3148
            $form->addRadio(
3149
                'invitation_type',
3150
                get_lang('Allowed'),
3151
                [
3152
                    'invitations' => get_lang('Invitations'),
3153
                    'subscriptions' => get_lang('Subscriptions'),
3154
                ],
3155
                [
3156
                    'onchange' => "$('#invitations-block, #subscriptions-block').hide(); $('#' + this.value + '-block').show();",
3157
                ]
3158
            );
3159
        }
3160
3161
        if ($allowCollectiveInvitations) {
3162
            $this->addCollectiveInvitationsFields($form, $personalEvent);
3163
        }
3164
3165
        if ($agendaEventSubscriptions) {
3166
            $this->addSubscriptionFields($form, $personalEvent);
3167
        }
3168
3169
        if (api_get_configuration_value('agenda_reminders')) {
3170
            $form->addHtml('<div id="notification_list">');
3171
3172
            if ($id) {
3173
                $this->addFieldsForRemindersToForm($id, $form);
3174
            }
3175
3176
            $form->addHtml('</div>');
3177
            $form->addButton('add_notification', get_lang('AddNotification'), 'bell-o')->setType('button');
3178
            $form->addHtml('<hr>');
3179
        }
3180
3181
        if (api_get_configuration_value('allow_careers_in_global_agenda') && 'admin' === $this->type) {
3182
            Career::addCareerFieldsToForm($form);
3183
            $form->addHtml('<hr>');
3184
        }
3185
3186
        if ($id) {
3187
            $form->addButtonUpdate(get_lang('ModifyEvent'));
3188
        } else {
3189
            $form->addButtonSave(get_lang('AgendaAdd'));
3190
        }
3191
3192
        $form->setDefaults($params);
3193
        $form->addRule(
3194
            'date_range',
3195
            get_lang('ThisFieldIsRequired'),
3196
            'required'
3197
        );
3198
        $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
3199
3200
        return $form;
3201
    }
3202
3203
    private function addCollectiveInvitationsFields(FormValidator $form, ?PersonalAgenda $personalEvent)
3204
    {
3205
        $invitees = [];
3206
        $isCollective = false;
3207
        $withInvitation = false;
3208
3209
        if ($personalEvent) {
3210
            $eventInvitation = $personalEvent->getInvitation();
3211
            $withInvitation = !($eventInvitation instanceof AgendaEventSubscription);
3212
3213
            if ($withInvitation) {
3214
                foreach ($eventInvitation->getInvitees() as $invitee) {
3215
                    $inviteeUser = $invitee->getUser();
3216
3217
                    $invitees[$inviteeUser->getId()] = $inviteeUser->getCompleteNameWithUsername();
3218
                }
3219
            }
3220
3221
            $isCollective = $personalEvent->isCollective();
3222
        }
3223
3224
        $form->addHtml(
3225
            '<div id="invitations-block" style="display: '.($withInvitation ? 'block;' : 'none;').'">'
3226
        );
3227
        $form->addHeader(get_lang('Invitations'));
3228
        $form->addSelectAjax(
3229
            'invitees',
3230
            get_lang('Invitees'),
3231
            $invitees,
3232
            [
3233
                'multiple' => 'multiple',
3234
                'url' => api_get_path(WEB_AJAX_PATH).'message.ajax.php?a=find_users',
3235
            ]
3236
        );
3237
        $form->addCheckBox('collective', '', get_lang('IsItEditableByTheInvitees'));
3238
        $form->addHtml('<hr>');
3239
        $form->addHtml('</div>');
3240
3241
        $form->setDefaults([
3242
            'invitees' => array_keys($invitees),
3243
            'collective' => $isCollective
3244
        ]);
3245
    }
3246
3247
    private function addSubscriptionFields(FormValidator $form, ?PersonalAgenda $personalEvent)
3248
    {
3249
        $subscribers = [];
3250
        $withSubscription = false;
3251
        $maxSubscriptions = 0;
3252
        $groupId = null;
3253
3254
        if ($personalEvent) {
3255
            $eventInvitation = $personalEvent->getInvitation();
3256
            $withSubscription = $eventInvitation instanceof AgendaEventSubscription;
3257
            $maxSubscriptions = $withSubscription ? $eventInvitation->getMaxAttendees() : 0;
3258
            $groupId = $personalEvent->getSubscriptionItemId();
3259
3260
            $subscribers = self::getInviteesForPersonalEvent($personalEvent->getId(), AgendaEventSubscriber::class);
3261
            $subscribers = array_combine(
3262
                array_column($subscribers, 'id'),
3263
                array_column($subscribers, 'name')
3264
            );
3265
        }
3266
3267
        $form->addHtml(
3268
            '<div id="subscriptions-block" style="display: '.($withSubscription ? 'block;' : 'none;').'">'
3269
        );
3270
        $form->addHeader(get_lang('Subscriptions'));
3271
        $form->addSelect(
3272
            'subscription_visibility',
3273
            get_lang('AllowSubscriptions'),
3274
            [
3275
                AgendaEventSubscription::SUBSCRIPTION_NO => get_lang('No'),
3276
                AgendaEventSubscription::SUBSCRIPTION_ALL => get_lang('AllUsersOfThePlatform'),
3277
                AgendaEventSubscription::SUBSCRIPTION_CLASS => get_lang('UsersInsideClass'),
3278
            ]
3279
        );
3280
        $slctItem = $form->addSelectAjax(
3281
            'subscription_item',
3282
            get_lang('SocialGroup').' / '.get_lang('Class'),
3283
            [],
3284
            [
3285
                'url' => api_get_path(WEB_AJAX_PATH).'usergroup.ajax.php?a=get_class_by_keyword',
3286
                'disabled' => 'disabled',
3287
            ]
3288
        );
3289
3290
        $form->addNumeric(
3291
            'max_subscriptions',
3292
            ['', get_lang('MaxSubscriptionsLeaveEmptyToNotLimit')],
3293
            [
3294
                'disabled' => 'disabled',
3295
                'step' => 1,
3296
                'min' => 0,
3297
                'value' => 0,
3298
            ]
3299
        );
3300
        $form->addHtml("<script>
3301
            $(function () {
3302
                $('#add_event_subscription_visibility')
3303
                    .on('change', function () {
3304
                        $('#max_subscriptions').prop('disabled', this.value == 0);
3305
                        $('#add_event_subscription_item').prop('disabled', this.value != 2);
3306
                    })
3307
                    .trigger('change');
3308
            })
3309
            </script>
3310
        ");
3311
3312
        $form->addSelect(
3313
            'subscribers',
3314
            get_lang('Subscribers'),
3315
            $subscribers,
3316
            ['multiple' => 'multiple']
3317
        );
3318
3319
        $form->setDefaults([
3320
            'subscribers' => array_keys($subscribers),
3321
            'max_subscriptions' => $maxSubscriptions,
3322
        ]);
3323
3324
        if ($groupId) {
3325
            $objUserGroup = new UserGroup();
3326
3327
            $groupInfo = $objUserGroup->get($groupId);
3328
3329
            $slctItem->addOption($groupInfo['name'], $groupId);
3330
        }
3331
3332
        $form->addHtml('</div>');
3333
    }
3334
3335
    public function addFieldsForRemindersToForm(int $eventId, FormValidator $form)
3336
    {
3337
        $remindersList = $this->parseEventReminders(
3338
            $this->getEventReminders($eventId)
3339
        );
3340
3341
        foreach ($remindersList as $reminderInfo) {
3342
            $form->addHtml('<div class="form-group">');
3343
            $form
3344
                ->addNumeric('notification_count[]', '', ['step' => 1, 'min' => 0])
3345
                ->setValue($reminderInfo['date_interval'][0])
3346
            ;
3347
            $form
3348
                ->addSelect(
3349
                'notification_period[]',
3350
                '',
3351
                    [
3352
                        'i' => get_lang('Minutes'),
3353
                        'h' => get_lang('Hours'),
3354
                        'd' => get_lang('Days'),
3355
                    ]
3356
                )
3357
                ->setValue($reminderInfo['date_interval'][1])
3358
            ;
3359
            $form->addHtml('<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>');
3360
            $form->addHtml(
3361
                '<div class="text-right col-sm-2">'
3362
                .'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>'
3363
                .'</div>'
3364
            );
3365
            $form->addHtml('</div>');
3366
        }
3367
3368
        $renderer = $form->defaultRenderer();
3369
        $renderer->setElementTemplate(
3370
            '<div class="col-sm-offset-2 col-sm-3">{element}</div>',
3371
            'notification_count[]'
3372
        );
3373
        $renderer->setElementTemplate(
3374
            '<div class="col-sm-3">{element}</div>',
3375
            'notification_period[]'
3376
        );
3377
    }
3378
3379
    /**
3380
     * @param FormValidator $form
3381
     * @param array         $sendTo               array('everyone' => false, 'users' => [1, 2], 'groups' => [3, 4])
3382
     * @param array         $attributes
3383
     * @param bool          $addOnlyItemsInSendTo
3384
     * @param bool          $required
3385
     *
3386
     * @return bool
3387
     */
3388
    public function showToForm(
3389
        $form,
3390
        $sendTo = [],
3391
        $attributes = [],
3392
        $addOnlyItemsInSendTo = false,
3393
        $required = false
3394
    ) {
3395
        if ($this->type != 'course') {
3396
            return false;
3397
        }
3398
3399
        $order = 'lastname';
3400
        if (api_is_western_name_order()) {
3401
            $order = 'firstname';
3402
        }
3403
3404
        $userList = CourseManager::get_user_list_from_course_code(
3405
            api_get_course_id(),
3406
            $this->sessionId,
3407
            null,
3408
            $order
3409
        );
3410
3411
        $groupList = CourseManager::get_group_list_of_course(
3412
            api_get_course_id(),
3413
            $this->sessionId
3414
        );
3415
3416
        $this->setSendToSelect(
3417
            $form,
3418
            $groupList,
3419
            $userList,
3420
            $sendTo,
3421
            $attributes,
3422
            $addOnlyItemsInSendTo,
3423
            $required
3424
        );
3425
3426
        return true;
3427
    }
3428
3429
    /**
3430
     * @param int   $id
3431
     * @param int   $visibility 0= invisible, 1 visible
3432
     * @param array $courseInfo
3433
     * @param int   $userId
3434
     */
3435
    public static function changeVisibility(
3436
        $id,
3437
        $visibility,
3438
        $courseInfo,
3439
        $userId = null
3440
    ) {
3441
        $id = intval($id);
3442
        if (empty($userId)) {
3443
            $userId = api_get_user_id();
3444
        } else {
3445
            $userId = intval($userId);
3446
        }
3447
3448
        if ($visibility == 0) {
3449
            api_item_property_update(
3450
                $courseInfo,
3451
                TOOL_CALENDAR_EVENT,
3452
                $id,
3453
                'invisible',
3454
                $userId
3455
            );
3456
        } else {
3457
            api_item_property_update(
3458
                $courseInfo,
3459
                TOOL_CALENDAR_EVENT,
3460
                $id,
3461
                'visible',
3462
                $userId
3463
            );
3464
        }
3465
    }
3466
3467
    /**
3468
     * Get repeat types.
3469
     *
3470
     * @return array
3471
     */
3472
    public static function getRepeatTypes()
3473
    {
3474
        return [
3475
            'daily' => get_lang('RepeatDaily'),
3476
            'weekly' => get_lang('RepeatWeekly'),
3477
            'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
3478
            //monthlyByDay"> get_lang('RepeatMonthlyByDay');
3479
            //monthlyByDayR' => get_lang('RepeatMonthlyByDayR'),
3480
            'yearly' => get_lang('RepeatYearly'),
3481
        ];
3482
    }
3483
3484
    /**
3485
     * Show a list with all the attachments according to the post's id.
3486
     *
3487
     * @param int   $eventId
3488
     * @param array $courseInfo
3489
     *
3490
     * @return array with the post info
3491
     */
3492
    public function getAttachmentList($eventId, $courseInfo)
3493
    {
3494
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3495
        $courseId = (int) $courseInfo['real_id'];
3496
        $eventId = (int) $eventId;
3497
3498
        $sql = "SELECT id, path, filename, comment
3499
                FROM $tableAttachment
3500
                WHERE
3501
                    c_id = $courseId AND
3502
                    agenda_id = $eventId";
3503
        $result = Database::query($sql);
3504
        $list = [];
3505
        if (Database::num_rows($result) != 0) {
3506
            $list = Database::store_result($result, 'ASSOC');
3507
        }
3508
3509
        return $list;
3510
    }
3511
3512
    /**
3513
     * Show a list with all the attachments according to the post's id.
3514
     *
3515
     * @param int   $attachmentId
3516
     * @param int   $eventId
3517
     * @param array $courseInfo
3518
     *
3519
     * @return array with the post info
3520
     */
3521
    public function getAttachment($attachmentId, $eventId, $courseInfo)
3522
    {
3523
        if (empty($courseInfo) || empty($attachmentId) || empty($eventId)) {
3524
            return [];
3525
        }
3526
3527
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3528
        $courseId = (int) $courseInfo['real_id'];
3529
        $eventId = (int) $eventId;
3530
        $attachmentId = (int) $attachmentId;
3531
3532
        $row = [];
3533
        $sql = "SELECT id, path, filename, comment
3534
                FROM $tableAttachment
3535
                WHERE
3536
                    c_id = $courseId AND
3537
                    agenda_id = $eventId AND
3538
                    id = $attachmentId
3539
                ";
3540
        $result = Database::query($sql);
3541
        if (Database::num_rows($result) != 0) {
3542
            $row = Database::fetch_array($result, 'ASSOC');
3543
        }
3544
3545
        return $row;
3546
    }
3547
3548
    /**
3549
     * Add an attachment file into agenda.
3550
     *
3551
     * @param int    $eventId
3552
     * @param array  $fileUserUpload ($_FILES['user_upload'])
3553
     * @param string $comment        about file
3554
     * @param array  $courseInfo
3555
     *
3556
     * @return string
3557
     */
3558
    public function addAttachment(
3559
        $eventId,
3560
        $fileUserUpload,
3561
        $comment,
3562
        $courseInfo
3563
    ) {
3564
        $agenda_table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3565
        $eventId = (int) $eventId;
3566
3567
        // Storing the attachments
3568
        $upload_ok = false;
3569
        if (!empty($fileUserUpload['name'])) {
3570
            $upload_ok = process_uploaded_file($fileUserUpload);
3571
        }
3572
3573
        if (!empty($upload_ok)) {
3574
            $courseDir = $courseInfo['directory'].'/upload/calendar';
3575
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
3576
            $uploadDir = $sys_course_path.$courseDir;
3577
3578
            // Try to add an extension to the file if it hasn't one
3579
            $new_file_name = add_ext_on_mime(
3580
                stripslashes($fileUserUpload['name']),
3581
                $fileUserUpload['type']
3582
            );
3583
3584
            // user's file name
3585
            $file_name = $fileUserUpload['name'];
3586
3587
            if (!filter_extension($new_file_name)) {
3588
                return Display::return_message(
3589
                    get_lang('UplUnableToSaveFileFilteredExtension'),
3590
                    'error'
3591
                );
3592
            } else {
3593
                $new_file_name = uniqid('');
3594
                $new_path = $uploadDir.'/'.$new_file_name;
3595
                $result = @move_uploaded_file(
3596
                    $fileUserUpload['tmp_name'],
3597
                    $new_path
3598
                );
3599
                $courseId = api_get_course_int_id();
3600
                $size = intval($fileUserUpload['size']);
3601
                // Storing the attachments if any
3602
                if ($result) {
3603
                    $params = [
3604
                        'c_id' => $courseId,
3605
                        'filename' => $file_name,
3606
                        'comment' => $comment,
3607
                        'path' => $new_file_name,
3608
                        'agenda_id' => $eventId,
3609
                        'size' => $size,
3610
                    ];
3611
                    $id = Database::insert($agenda_table_attachment, $params);
3612
                    if ($id) {
3613
                        $sql = "UPDATE $agenda_table_attachment
3614
                                SET id = iid WHERE iid = $id";
3615
                        Database::query($sql);
3616
3617
                        api_item_property_update(
3618
                            $courseInfo,
3619
                            'calendar_event_attachment',
3620
                            $id,
3621
                            'AgendaAttachmentAdded',
3622
                            api_get_user_id()
3623
                        );
3624
                    }
3625
                }
3626
            }
3627
        }
3628
    }
3629
3630
    /**
3631
     * @param int    $attachmentId
3632
     * @param int    $eventId
3633
     * @param array  $fileUserUpload
3634
     * @param string $comment
3635
     * @param array  $courseInfo
3636
     */
3637
    public function updateAttachment(
3638
        $attachmentId,
3639
        $eventId,
3640
        $fileUserUpload,
3641
        $comment,
3642
        $courseInfo
3643
    ) {
3644
        $attachment = $this->getAttachment(
3645
            $attachmentId,
3646
            $eventId,
3647
            $courseInfo
3648
        );
3649
        if (!empty($attachment)) {
3650
            $this->deleteAttachmentFile($attachmentId, $courseInfo);
3651
        }
3652
        $this->addAttachment($eventId, $fileUserUpload, $comment, $courseInfo);
3653
    }
3654
3655
    /**
3656
     * This function delete a attachment file by id.
3657
     *
3658
     * @param int   $attachmentId
3659
     * @param array $courseInfo
3660
     *
3661
     * @return string
3662
     */
3663
    public function deleteAttachmentFile($attachmentId, $courseInfo)
3664
    {
3665
        $table = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3666
        $attachmentId = (int) $attachmentId;
3667
        $courseId = $courseInfo['real_id'];
3668
3669
        if (empty($courseId) || empty($attachmentId)) {
3670
            return false;
3671
        }
3672
3673
        $sql = "DELETE FROM $table
3674
                WHERE c_id = $courseId AND id = ".$attachmentId;
3675
        $result = Database::query($sql);
3676
3677
        // update item_property
3678
        api_item_property_update(
3679
            $courseInfo,
3680
            'calendar_event_attachment',
3681
            $attachmentId,
3682
            'AgendaAttachmentDeleted',
3683
            api_get_user_id()
3684
        );
3685
3686
        if (!empty($result)) {
3687
            return Display::return_message(
3688
                get_lang("AttachmentFileDeleteSuccess"),
3689
                'confirmation'
3690
            );
3691
        }
3692
    }
3693
3694
    /**
3695
     * @param int $eventId
3696
     *
3697
     * @return array
3698
     */
3699
    public function getAllRepeatEvents($eventId)
3700
    {
3701
        $events = [];
3702
        $eventId = (int) $eventId;
3703
3704
        switch ($this->type) {
3705
            case 'personal':
3706
                break;
3707
            case 'course':
3708
                if (!empty($this->course['real_id'])) {
3709
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
3710
                            WHERE
3711
                                c_id = ".$this->course['real_id']." AND
3712
                                parent_event_id = ".$eventId;
3713
                    $result = Database::query($sql);
3714
                    if (Database::num_rows($result)) {
3715
                        while ($row = Database::fetch_array($result, 'ASSOC')) {
3716
                            $events[] = $row;
3717
                        }
3718
                    }
3719
                }
3720
                break;
3721
        }
3722
3723
        return $events;
3724
    }
3725
3726
    /**
3727
     * @param int $eventId
3728
     * @param int $courseId
3729
     *
3730
     * @return bool
3731
     */
3732
    public function hasChildren($eventId, $courseId)
3733
    {
3734
        $eventId = (int) $eventId;
3735
        $courseId = (int) $courseId;
3736
3737
        $sql = "SELECT count(DISTINCT(id)) as count
3738
                FROM ".$this->tbl_course_agenda."
3739
                WHERE
3740
                    c_id = $courseId AND
3741
                    parent_event_id = $eventId";
3742
        $result = Database::query($sql);
3743
        if (Database::num_rows($result)) {
3744
            $row = Database::fetch_array($result, 'ASSOC');
3745
3746
            return $row['count'] > 0;
3747
        }
3748
3749
        return false;
3750
    }
3751
3752
    public function displayActions(string $view, ?string $filter = ''): string
3753
    {
3754
        $groupInfo = GroupManager::get_group_properties(api_get_group_id());
3755
        $groupIid = $groupInfo['iid'] ?? 0;
3756
3757
        $codePath = api_get_path(WEB_CODE_PATH);
3758
3759
        $currentUserId = api_get_user_id();
3760
        $cidReq = api_get_cidreq();
3761
3762
        $actionsLeft = Display::url(
3763
            Display::return_icon('calendar.png', get_lang('Calendar'), [], ICON_SIZE_MEDIUM),
3764
            $codePath."calendar/agenda_js.php?type={$this->type}&$cidReq"
3765
        );
3766
        $actionsLeft .= Display::url(
3767
            Display::return_icon('week.png', get_lang('AgendaList'), [], ICON_SIZE_MEDIUM),
3768
            $codePath."calendar/agenda_list.php?type={$this->type}&$cidReq"
3769
        );
3770
3771
        $isAllowedToEdit = api_is_allowed_to_edit(false, true);
3772
3773
        $form = '';
3774
        if ($isAllowedToEdit
3775
            || ('personal' === $this->type && !api_is_anonymous() && 'true' === api_get_setting('allow_personal_agenda'))
3776
            || (
3777
                '1' === api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous() &&
3778
                api_is_allowed_to_session_edit(false, true))
3779
            || (
3780
                GroupManager::user_has_access($currentUserId, $groupIid, GroupManager::GROUP_TOOL_CALENDAR)
3781
                && GroupManager::is_tutor_of_group($currentUserId, $groupInfo)
3782
            )
3783
        ) {
3784
            $actionsLeft .= Display::url(
3785
                Display::return_icon('new_event.png', get_lang('AgendaAdd'), [], ICON_SIZE_MEDIUM),
3786
                $codePath."calendar/agenda.php?action=add&type={$this->type}&$cidReq"
3787
            );
3788
3789
            $actionsLeft .= Display::url(
3790
                Display::return_icon('import_calendar.png', get_lang('ICalFileImport'), [], ICON_SIZE_MEDIUM),
3791
                $codePath."calendar/agenda.php?action=importical&type={$this->type}&$cidReq"
3792
            );
3793
3794
            if ($this->type === 'course') {
3795
                if (!isset($_GET['action'])) {
3796
                    $form = new FormValidator(
3797
                        'form-search',
3798
                        'post',
3799
                        '',
3800
                        '',
3801
                        [],
3802
                        FormValidator::LAYOUT_INLINE
3803
                    );
3804
                    $attributes = [
3805
                        'multiple' => false,
3806
                        'id' => 'select_form_id_search',
3807
                    ];
3808
                    $selectedValues = $this->parseAgendaFilter($filter);
3809
                    $this->showToForm($form, $selectedValues, $attributes);
3810
                    $form = $form->returnForm();
3811
                }
3812
3813
                if (true === api_get_configuration_value('agenda_reminders') && $isAllowedToEdit) {
3814
                    $actionsLeft .= Display::url(
3815
                        Display::return_icon(
3816
                            'course_request_pending.png',
3817
                            get_lang('ImportCourseEvents'),
3818
                            [],
3819
                            ICON_SIZE_MEDIUM
3820
                        ),
3821
                        $codePath."calendar/agenda.php?action=import_course_agenda_reminders&type={$this->type}&$cidReq"
3822
                    );
3823
                }
3824
            }
3825
        }
3826
3827
        if ($this->type === 'personal' && !api_is_anonymous()) {
3828
            $actionsLeft .= Display::url(
3829
                Display::return_icon('1day.png', get_lang('SessionsPlanCalendar'), [], ICON_SIZE_MEDIUM),
3830
                $codePath.'calendar/planification.php'
3831
            );
3832
3833
            if (api_is_student_boss() || api_is_platform_admin()) {
3834
                $actionsLeft .= Display::url(
3835
                    Display::return_icon('calendar-user.png', get_lang('MyStudentsSchedule'), [], ICON_SIZE_MEDIUM),
3836
                    $codePath.'mySpace/calendar_plan.php'
3837
                );
3838
            }
3839
        }
3840
3841
        if (api_is_platform_admin()
3842
            || api_is_teacher()
3843
            || api_is_student_boss()
3844
            || api_is_drh()
3845
            || api_is_session_admin()
3846
            || api_is_coach()
3847
        ) {
3848
            if ($this->type == 'personal') {
3849
                $form = '';
3850
                if (!isset($_GET['action'])) {
3851
                    $form = new FormValidator(
3852
                        'form-search',
3853
                        'get',
3854
                        api_get_self().'?type=personal&',
3855
                        '',
3856
                        [],
3857
                        FormValidator::LAYOUT_INLINE
3858
                    );
3859
3860
                    $sessions = [];
3861
3862
                    if (api_is_drh()) {
3863
                        $sessionList = SessionManager::get_sessions_followed_by_drh($currentUserId);
3864
                        if (!empty($sessionList)) {
3865
                            foreach ($sessionList as $sessionItem) {
3866
                                $sessions[$sessionItem['id']] = strip_tags($sessionItem['name']);
3867
                            }
3868
                        }
3869
                    } else {
3870
                        $sessions = SessionManager::get_sessions_by_user($currentUserId);
3871
                        $sessions = array_column($sessions, 'session_name', 'session_id');
3872
                    }
3873
3874
                    $form->addHidden('type', 'personal');
3875
                    $sessions = ['0' => get_lang('SelectAnOption')] + $sessions;
3876
3877
                    $form->addSelect(
3878
                        'session_id',
3879
                        get_lang('Session'),
3880
                        $sessions,
3881
                        ['id' => 'session_id', 'onchange' => 'submit();']
3882
                    );
3883
3884
                    $form->addButton('reset', get_lang('Reset'), 'eraser');
3885
                    $form = $form->returnForm();
3886
                }
3887
            }
3888
        }
3889
3890
        $actionsRight = '';
3891
        if ($view == 'calendar') {
3892
            $actionsRight .= $form;
3893
        }
3894
3895
        return Display::toolbarAction(
3896
            'toolbar-agenda',
3897
            [$actionsLeft, $actionsRight]
3898
        );
3899
    }
3900
3901
    /**
3902
     * @return FormValidator
3903
     */
3904
    public function getImportCalendarForm()
3905
    {
3906
        $form = new FormValidator(
3907
            'frm_import_ical',
3908
            'post',
3909
            api_get_self().'?action=importical&type='.$this->type,
3910
            ['enctype' => 'multipart/form-data']
3911
        );
3912
        $form->addHeader(get_lang('ICalFileImport'));
3913
        $form->addElement('file', 'ical_import', get_lang('ICalFileImport'));
3914
        $form->addRule(
3915
            'ical_import',
3916
            get_lang('ThisFieldIsRequired'),
3917
            'required'
3918
        );
3919
        $form->addButtonImport(get_lang('Import'), 'ical_submit');
3920
3921
        return $form;
3922
    }
3923
3924
    /**
3925
     * @param array $courseInfo
3926
     * @param $file
3927
     *
3928
     * @return false|string
3929
     */
3930
    public function importEventFile($courseInfo, $file)
3931
    {
3932
        $charset = api_get_system_encoding();
3933
        $filepath = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
3934
        $messages = [];
3935
3936
        if (!@move_uploaded_file($file['tmp_name'], $filepath)) {
3937
            error_log(
3938
                'Problem moving uploaded file: '.$file['error'].' in '.__FILE__.' line '.__LINE__
3939
            );
3940
3941
            return false;
3942
        }
3943
3944
        $data = file_get_contents($filepath);
3945
3946
        $trans = [
3947
            'DAILY' => 'daily',
3948
            'WEEKLY' => 'weekly',
3949
            'MONTHLY' => 'monthlyByDate',
3950
            'YEARLY' => 'yearly',
3951
        ];
3952
        $sentTo = ['everyone' => true];
3953
        $calendar = Sabre\VObject\Reader::read($data);
3954
        $currentTimeZone = api_get_timezone();
3955
        if (!empty($calendar->VEVENT)) {
3956
            /** @var Sabre\VObject\Component\VEvent $event */
3957
            foreach ($calendar->VEVENT as $event) {
3958
                $tempDate = $event->DTSTART->getValue();
3959
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3960
                    $event->DTSTART->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3961
                }
3962
                $tempDate = $event->DTEND->getValue();
3963
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3964
                    $event->DTEND->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3965
                }
3966
                $start = $event->DTSTART->getDateTime();
3967
                $end = $event->DTEND->getDateTime();
3968
                //Sabre\VObject\DateTimeParser::parseDateTime(string $dt, \Sabre\VObject\DateTimeZone $tz)
3969
3970
                $startDateTime = api_get_local_time(
3971
                    $start->format('Y-m-d H:i:s'),
3972
                    $currentTimeZone,
3973
                    $start->format('e')
3974
                );
3975
                $endDateTime = api_get_local_time(
3976
                    $end->format('Y-m-d H:i'),
3977
                    $currentTimeZone,
3978
                    $end->format('e')
3979
                );
3980
                $title = api_convert_encoding(
3981
                    (string) $event->summary,
3982
                    $charset,
3983
                    'UTF-8'
3984
                );
3985
                $description = api_convert_encoding(
3986
                    (string) $event->description,
3987
                    $charset,
3988
                    'UTF-8'
3989
                );
3990
3991
                $id = $this->addEvent(
3992
                    $startDateTime,
3993
                    $endDateTime,
3994
                    'false',
3995
                    $title,
3996
                    $description,
3997
                    $sentTo
3998
                );
3999
4000
                $messages[] = " $title - ".$startDateTime." - ".$endDateTime;
4001
4002
                //$attendee = (string)$event->attendee;
4003
                /** @var Sabre\VObject\Property\ICalendar\Recur $repeat */
4004
                $repeat = $event->RRULE;
4005
                if ($id && !empty($repeat)) {
4006
                    $repeat = $repeat->getParts();
4007
                    $freq = $trans[$repeat['FREQ']];
4008
4009
                    if (isset($repeat['UNTIL']) && !empty($repeat['UNTIL'])) {
4010
                        // Check if datetime or just date (strlen == 8)
4011
                        if (strlen($repeat['UNTIL']) == 8) {
4012
                            // Fix the datetime format to avoid exception in the next step
4013
                            $repeat['UNTIL'] .= 'T000000';
4014
                        }
4015
                        $until = Sabre\VObject\DateTimeParser::parseDateTime(
4016
                            $repeat['UNTIL'],
4017
                            new DateTimeZone($currentTimeZone)
4018
                        );
4019
                        $until = $until->format('Y-m-d H:i:s');
4020
                        $this->addRepeatedItem(
4021
                            $id,
4022
                            $freq,
4023
                            $until,
4024
                            $sentTo
4025
                        );
4026
                    }
4027
4028
                    if (!empty($repeat['COUNT'])) {
4029
                        /*$count = $repeat['COUNT'];
4030
                        $interval = $repeat['INTERVAL'];
4031
                        $endDate = null;
4032
                        switch($freq) {
4033
                            case 'daily':
4034
                                $start = api_strtotime($startDateTime);
4035
                                $date = new DateTime($startDateTime);
4036
                                $days = $count * $interval;
4037
                                var_dump($days);
4038
                                $date->add(new DateInterval("P".$days."D"));
4039
                                $endDate = $date->format('Y-m-d H:i');
4040
                                //$endDate = $count *
4041
                                for ($i = 0; $i < $count; $i++) {
4042
                                    $days = 86400 * 7
4043
                                }
4044
                            }
4045
                        }*/
4046
                        //$res = agenda_add_repeat_item($courseInfo, $id, $freq, $count, $attendee);
4047
                        /*$this->addRepeatedItem(
4048
                            $id,
4049
                            $freq,
4050
                            $endDate,
4051
                            $sentTo
4052
                        );*/
4053
                    }
4054
                }
4055
            }
4056
        }
4057
4058
        if (!empty($messages)) {
4059
            $messages = implode('<br /> ', $messages);
4060
        } else {
4061
            $messages = get_lang('NoAgendaItems');
4062
        }
4063
4064
        return $messages;
4065
    }
4066
4067
    /**
4068
     * Parse filter turns USER:12 to ['users' => [12])] or G:1 ['groups' => [1]].
4069
     *
4070
     * @param int $filter
4071
     *
4072
     * @return array
4073
     */
4074
    public function parseAgendaFilter($filter)
4075
    {
4076
        $everyone = false;
4077
        $groupId = null;
4078
        $userId = null;
4079
4080
        if ($filter == 'everyone') {
4081
            $everyone = true;
4082
        } else {
4083
            if (substr($filter, 0, 1) == 'G') {
4084
                $groupId = str_replace('GROUP:', '', $filter);
4085
            } else {
4086
                $userId = str_replace('USER:', '', $filter);
4087
            }
4088
        }
4089
        if (empty($userId) && empty($groupId)) {
4090
            $everyone = true;
4091
        }
4092
4093
        return [
4094
            'everyone' => $everyone,
4095
            'users' => [$userId],
4096
            'groups' => [$groupId],
4097
        ];
4098
    }
4099
4100
    /**
4101
     *    This function retrieves all the agenda items of all the courses the user is subscribed to.
4102
     */
4103
    public static function get_myagendaitems(
4104
        $user_id,
4105
        $courses_dbs,
4106
        $month,
4107
        $year
4108
    ) {
4109
        $user_id = intval($user_id);
4110
4111
        $items = [];
4112
        $my_list = [];
4113
4114
        // get agenda-items for every course
4115
        foreach ($courses_dbs as $key => $array_course_info) {
4116
            //databases of the courses
4117
            $TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
4118
            $TABLE_ITEMPROPERTY = Database::get_course_table(
4119
                TABLE_ITEM_PROPERTY
4120
            );
4121
4122
            $group_memberships = GroupManager::get_group_ids(
4123
                $array_course_info['real_id'],
4124
                $user_id
4125
            );
4126
            $course_user_status = CourseManager::getUserInCourseStatus(
4127
                $user_id,
4128
                $array_course_info['real_id']
4129
            );
4130
            // if the user is administrator of that course we show all the agenda items
4131
            if ($course_user_status == '1') {
4132
                //echo "course admin";
4133
                $sqlquery = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4134
							FROM ".$TABLEAGENDA." agenda,
4135
								 ".$TABLE_ITEMPROPERTY." ip
4136
							WHERE agenda.id = ip.ref
4137
							AND MONTH(agenda.start_date)='".$month."'
4138
							AND YEAR(agenda.start_date)='".$year."'
4139
							AND ip.tool='".TOOL_CALENDAR_EVENT."'
4140
							AND ip.visibility='1'
4141
							GROUP BY agenda.id
4142
							ORDER BY start_date ";
4143
            } else {
4144
                // if the user is not an administrator of that course
4145
                if (is_array($group_memberships) && count(
4146
                        $group_memberships
4147
                    ) > 0
4148
                ) {
4149
                    $sqlquery = "SELECT	agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4150
								FROM ".$TABLEAGENDA." agenda,
4151
									".$TABLE_ITEMPROPERTY." ip
4152
								WHERE agenda.id = ip.ref
4153
								AND MONTH(agenda.start_date)='".$month."'
4154
								AND YEAR(agenda.start_date)='".$year."'
4155
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4156
								AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4157
                            ", ",
4158
                            $group_memberships
4159
                        ).")) )
4160
								AND ip.visibility='1'
4161
								ORDER BY start_date ";
4162
                } else {
4163
                    $sqlquery = "SELECT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4164
								FROM ".$TABLEAGENDA." agenda,
4165
									".$TABLE_ITEMPROPERTY." ip
4166
								WHERE agenda.id = ip.ref
4167
								AND MONTH(agenda.start_date)='".$month."'
4168
								AND YEAR(agenda.start_date)='".$year."'
4169
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4170
								AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL)
4171
								AND ip.visibility='1'
4172
								ORDER BY start_date ";
4173
                }
4174
            }
4175
            $result = Database::query($sqlquery);
4176
4177
            while ($item = Database::fetch_array($result, 'ASSOC')) {
4178
                $agendaday = -1;
4179
                if (!empty($item['start_date'])) {
4180
                    $item['start_date'] = api_get_local_time(
4181
                        $item['start_date']
4182
                    );
4183
                    $item['start_date_tms'] = api_strtotime(
4184
                        $item['start_date']
4185
                    );
4186
                    $agendaday = date("j", $item['start_date_tms']);
4187
                }
4188
                if (!empty($item['end_date'])) {
4189
                    $item['end_date'] = api_get_local_time($item['end_date']);
4190
                }
4191
4192
                $url = api_get_path(
4193
                        WEB_CODE_PATH
4194
                    )."calendar/agenda.php?cidReq=".urlencode(
4195
                        $array_course_info["code"]
4196
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4197
4198
                $item['url'] = $url;
4199
                $item['course_name'] = $array_course_info['title'];
4200
                $item['calendar_type'] = 'course';
4201
                $item['course_id'] = $array_course_info['course_id'];
4202
4203
                $my_list[$agendaday][] = $item;
4204
            }
4205
        }
4206
4207
        // sorting by hour for every day
4208
        $agendaitems = [];
4209
        foreach ($items as $agendaday => $tmpitems) {
4210
            if (!isset($agendaitems[$agendaday])) {
4211
                $agendaitems[$agendaday] = '';
4212
            }
4213
            sort($tmpitems);
4214
            foreach ($tmpitems as $val) {
4215
                $agendaitems[$agendaday] .= $val;
4216
            }
4217
        }
4218
4219
        return $my_list;
4220
    }
4221
4222
    /**
4223
     * This function retrieves one personal agenda item returns it.
4224
     *
4225
     * @param    array    The array containing existing events. We add to this array.
4226
     * @param    int        Day
4227
     * @param    int        Month
4228
     * @param    int        Year (4 digits)
4229
     * @param    int        Week number
4230
     * @param    string    Type of view (month_view, week_view, day_view)
4231
     *
4232
     * @return array The results of the database query, or null if not found
4233
     */
4234
    public static function get_global_agenda_items(
4235
        $agendaitems,
4236
        $day,
4237
        $month,
4238
        $year,
4239
        $week,
4240
        $type
4241
    ) {
4242
        $tbl_global_agenda = Database::get_main_table(
4243
            TABLE_MAIN_SYSTEM_CALENDAR
4244
        );
4245
        $month = intval($month);
4246
        $year = intval($year);
4247
        $week = intval($week);
4248
        $day = intval($day);
4249
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4250
4251
        $current_access_url_id = api_get_current_access_url_id();
4252
4253
        if ($type == "month_view" || $type == "") {
4254
            // We are in month view
4255
            $sql = "SELECT * FROM ".$tbl_global_agenda."
4256
                    WHERE
4257
                        MONTH(start_date) = ".$month." AND
4258
                        YEAR(start_date) = ".$year."  AND
4259
                        access_url_id = $current_access_url_id
4260
                    ORDER BY start_date ASC";
4261
        }
4262
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4263
        if ($type == "week_view") { // we are in week view
4264
            $start_end_day_of_week = self::calculate_start_end_of_week(
4265
                $week,
4266
                $year
4267
            );
4268
            $start_day = $start_end_day_of_week['start']['day'];
4269
            $start_month = $start_end_day_of_week['start']['month'];
4270
            $start_year = $start_end_day_of_week['start']['year'];
4271
            $end_day = $start_end_day_of_week['end']['day'];
4272
            $end_month = $start_end_day_of_week['end']['month'];
4273
            $end_year = $start_end_day_of_week['end']['year'];
4274
            // in sql statements you have to use year-month-day for date calculations
4275
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4276
            $start_filter = api_get_utc_datetime($start_filter);
4277
4278
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4279
            $end_filter = api_get_utc_datetime($end_filter);
4280
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."' AND  access_url_id = $current_access_url_id ";
4281
        }
4282
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4283
        if ($type == "day_view") { // we are in day view
4284
            // we could use mysql date() function but this is only available from 4.1 and higher
4285
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4286
            $start_filter = api_get_utc_datetime($start_filter);
4287
4288
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4289
            $end_filter = api_get_utc_datetime($end_filter);
4290
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."'  AND  access_url_id = $current_access_url_id";
4291
        }
4292
4293
        $result = Database::query($sql);
4294
4295
        while ($item = Database::fetch_array($result)) {
4296
            if (!empty($item['start_date'])) {
4297
                $item['start_date'] = api_get_local_time($item['start_date']);
4298
                $item['start_date_tms'] = api_strtotime($item['start_date']);
4299
            }
4300
            if (!empty($item['end_date'])) {
4301
                $item['end_date'] = api_get_local_time($item['end_date']);
4302
            }
4303
4304
            // we break the date field in the database into a date and a time part
4305
            $agenda_db_date = explode(" ", $item['start_date']);
4306
            $date = $agenda_db_date[0];
4307
            $time = $agenda_db_date[1];
4308
            // we divide the date part into a day, a month and a year
4309
            $agendadate = explode("-", $date);
4310
            $year = intval($agendadate[0]);
4311
            $month = intval($agendadate[1]);
4312
            $day = intval($agendadate[2]);
4313
            // we divide the time part into hour, minutes, seconds
4314
            $agendatime = explode(":", $time);
4315
            $hour = $agendatime[0];
4316
            $minute = $agendatime[1];
4317
            $second = $agendatime[2];
4318
4319
            if ($type == 'month_view') {
4320
                $item['calendar_type'] = 'global';
4321
                $agendaitems[$day][] = $item;
4322
                continue;
4323
            }
4324
4325
            $start_time = api_format_date(
4326
                $item['start_date'],
4327
                TIME_NO_SEC_FORMAT
4328
            );
4329
            $end_time = '';
4330
            if (!empty($item['end_date'])) {
4331
                $end_time = ' - '.api_format_date(
4332
                        $item['end_date'],
4333
                        DATE_TIME_FORMAT_LONG
4334
                    );
4335
            }
4336
4337
            // if the student has specified a course we a add a link to that course
4338
            if ($item['course'] != "") {
4339
                $url = api_get_path(
4340
                        WEB_CODE_PATH
4341
                    )."admin/agenda.php?cidReq=".urlencode(
4342
                        $item['course']
4343
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4344
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4345
            } else {
4346
                $course_link = "";
4347
            }
4348
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4349
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4350
            if ($type !== "day_view") {
4351
                // This is the array construction for the WEEK or MONTH view
4352
                //Display the Agenda global in the tab agenda (administrator)
4353
                $agendaitems[$day] .= "<i>$start_time $end_time</i>&nbsp;-&nbsp;";
4354
                $agendaitems[$day] .= "<b>".get_lang('GlobalEvent')."</b>";
4355
                $agendaitems[$day] .= "<div>".$item['title']."</div><br>";
4356
            } else {
4357
                // this is the array construction for the DAY view
4358
                $halfhour = 2 * $agendatime['0'];
4359
                if ($agendatime['1'] >= '30') {
4360
                    $halfhour = $halfhour + 1;
4361
                }
4362
                if (!is_array($agendaitems[$halfhour])) {
4363
                    $content = $agendaitems[$halfhour];
4364
                }
4365
                $agendaitems[$halfhour] = $content."<div><i>$hour:$minute</i> <b>".get_lang(
4366
                        'GlobalEvent'
4367
                    ).":  </b>".$item['title']."</div>";
4368
            }
4369
        }
4370
4371
        return $agendaitems;
4372
    }
4373
4374
    /**
4375
     * This function retrieves all the personal agenda items and add them to the agenda items found by the other
4376
     * functions.
4377
     */
4378
    public static function get_personal_agenda_items(
4379
        $user_id,
4380
        $agendaitems,
4381
        $day,
4382
        $month,
4383
        $year,
4384
        $week,
4385
        $type
4386
    ) {
4387
        $tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
4388
        $user_id = intval($user_id);
4389
4390
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4391
        if ($type === "month_view" || $type === "") {
4392
            // we are in month view
4393
            $sql = "SELECT * FROM $tbl_personal_agenda
4394
                    WHERE
4395
                        user='".$user_id."' AND
4396
                        MONTH(date)='".$month."' AND
4397
                        YEAR(date) = '".$year."'
4398
                     ORDER BY date ASC";
4399
        }
4400
4401
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4402
        // we are in week view
4403
        if ($type == "week_view") {
4404
            $start_end_day_of_week = self::calculate_start_end_of_week(
4405
                $week,
4406
                $year
4407
            );
4408
            $start_day = $start_end_day_of_week['start']['day'];
4409
            $start_month = $start_end_day_of_week['start']['month'];
4410
            $start_year = $start_end_day_of_week['start']['year'];
4411
            $end_day = $start_end_day_of_week['end']['day'];
4412
            $end_month = $start_end_day_of_week['end']['month'];
4413
            $end_year = $start_end_day_of_week['end']['year'];
4414
            // in sql statements you have to use year-month-day for date calculations
4415
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4416
            $start_filter = api_get_utc_datetime($start_filter);
4417
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4418
            $end_filter = api_get_utc_datetime($end_filter);
4419
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4420
        }
4421
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4422
        if ($type == "day_view") {
4423
            // we are in day view
4424
            // we could use mysql date() function but this is only available from 4.1 and higher
4425
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4426
            $start_filter = api_get_utc_datetime($start_filter);
4427
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4428
            $end_filter = api_get_utc_datetime($end_filter);
4429
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4430
        }
4431
4432
        $result = Database::query($sql);
4433
        while ($item = Database::fetch_array($result, 'ASSOC')) {
4434
            $time_minute = api_convert_and_format_date(
4435
                $item['date'],
4436
                TIME_NO_SEC_FORMAT
4437
            );
4438
            $item['date'] = api_get_local_time($item['date']);
4439
            $item['start_date_tms'] = api_strtotime($item['date']);
4440
            $item['content'] = $item['text'];
4441
4442
            // we break the date field in the database into a date and a time part
4443
            $agenda_db_date = explode(" ", $item['date']);
4444
            $date = $agenda_db_date[0];
4445
            $time = $agenda_db_date[1];
4446
            // we divide the date part into a day, a month and a year
4447
            $agendadate = explode("-", $item['date']);
4448
            $year = intval($agendadate[0]);
4449
            $month = intval($agendadate[1]);
4450
            $day = intval($agendadate[2]);
4451
            // we divide the time part into hour, minutes, seconds
4452
            $agendatime = explode(":", $time);
4453
4454
            $hour = $agendatime[0];
4455
            $minute = $agendatime[1];
4456
            $second = $agendatime[2];
4457
4458
            if ($type == 'month_view') {
4459
                $item['calendar_type'] = 'personal';
4460
                $item['start_date'] = $item['date'];
4461
                $agendaitems[$day][] = $item;
4462
                continue;
4463
            }
4464
4465
            // if the student has specified a course we a add a link to that course
4466
            if ($item['course'] != "") {
4467
                $url = api_get_path(
4468
                        WEB_CODE_PATH
4469
                    )."calendar/agenda.php?cidReq=".urlencode(
4470
                        $item['course']
4471
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4472
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4473
            } else {
4474
                $course_link = "";
4475
            }
4476
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4477
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4478
            if ($type !== "day_view") {
4479
                // This is the array construction for the WEEK or MONTH view
4480
4481
                //Display events in agenda
4482
                $agendaitems[$day] .= "<div><i>$time_minute</i> $course_link <a href=\"myagenda.php?action=view&view=personal&day=$day&month=$month&year=$year&id=".$item['id']."#".$item['id']."\" class=\"personal_agenda\">".$item['title']."</a></div><br />";
4483
            } else {
4484
                // this is the array construction for the DAY view
4485
                $halfhour = 2 * $agendatime['0'];
4486
                if ($agendatime['1'] >= '30') {
4487
                    $halfhour = $halfhour + 1;
4488
                }
4489
4490
                //Display events by list
4491
                $agendaitems[$halfhour] .= "<div><i>$time_minute</i> $course_link <a href=\"myagenda.php?action=view&view=personal&day=$day&month=$month&year=$year&id=".$item['id']."#".$item['id']."\" class=\"personal_agenda\">".$item['title']."</a></div>";
4492
            }
4493
        }
4494
4495
        return $agendaitems;
4496
    }
4497
4498
    /**
4499
     * Show the monthcalender of the given month.
4500
     *
4501
     * @param    array    Agendaitems
4502
     * @param    int    Month number
4503
     * @param    int    Year number
4504
     * @param    array    Array of strings containing long week day names (deprecated, you can send an empty array
4505
     *                          instead)
4506
     * @param    string    The month name
4507
     */
4508
    public static function display_mymonthcalendar(
4509
        $user_id,
4510
        $agendaitems,
4511
        $month,
4512
        $year,
4513
        $weekdaynames,
4514
        $monthName,
4515
        $show_content = true
4516
    ) {
4517
        global $DaysShort, $course_path;
4518
        //Handle leap year
4519
        $numberofdays = [
4520
            0,
4521
            31,
4522
            28,
4523
            31,
4524
            30,
4525
            31,
4526
            30,
4527
            31,
4528
            31,
4529
            30,
4530
            31,
4531
            30,
4532
            31,
4533
        ];
4534
        if (($year % 400 == 0) or ($year % 4 == 0 and $year % 100 != 0)) {
4535
            $numberofdays[2] = 29;
4536
        }
4537
        //Get the first day of the month
4538
        $dayone = getdate(mktime(0, 0, 0, $month, 1, $year));
4539
        //Start the week on monday
4540
        $startdayofweek = $dayone['wday'] != 0 ? ($dayone['wday'] - 1) : 6;
4541
        $g_cc = (isset($_GET['courseCode']) ? $_GET['courseCode'] : '');
4542
4543
        $next_month = ($month == 1 ? 12 : $month - 1);
4544
        $prev_month = ($month == 12 ? 1 : $month + 1);
4545
4546
        $next_year = ($month == 1 ? $year - 1 : $year);
4547
        $prev_year = ($month == 12 ? $year + 1 : $year);
4548
4549
        if ($show_content) {
4550
            $back_url = Display::url(
4551
                get_lang('Previous'),
4552
                api_get_self()."?coursePath=".urlencode(
4553
                    $course_path
4554
                )."&courseCode=".Security::remove_XSS(
4555
                    $g_cc
4556
                )."&action=view&view=month&month=".$next_month."&year=".$next_year
4557
            );
4558
            $next_url = Display::url(
4559
                get_lang('Next'),
4560
                api_get_self()."?coursePath=".urlencode(
4561
                    $course_path
4562
                )."&courseCode=".Security::remove_XSS(
4563
                    $g_cc
4564
                )."&action=view&view=month&month=".$prev_month."&year=".$prev_year
4565
            );
4566
        } else {
4567
            $back_url = Display::url(
4568
                get_lang('Previous'),
4569
                '',
4570
                [
4571
                    'onclick' => "load_calendar('".$user_id."','".$next_month."', '".$next_year."'); ",
4572
                    'class' => 'btn ui-button ui-widget ui-state-default',
4573
                ]
4574
            );
4575
            $next_url = Display::url(
4576
                get_lang('Next'),
4577
                '',
4578
                [
4579
                    'onclick' => "load_calendar('".$user_id."','".$prev_month."', '".$prev_year."'); ",
4580
                    'class' => 'pull-right btn ui-button ui-widget ui-state-default',
4581
                ]
4582
            );
4583
        }
4584
        $html = '';
4585
        $html .= '<div class="actions">';
4586
        $html .= '<div class="row">';
4587
        $html .= '<div class="col-md-4">'.$back_url.'</div>';
4588
        $html .= '<div class="col-md-4"><p class="agenda-title text-center">'.$monthName." ".$year.'</p></div>';
4589
        $html .= '<div class="col-md-4">'.$next_url.'</div>';
4590
        $html .= '</div>';
4591
        $html .= '</div>';
4592
        $html .= '<table id="agenda_list2" class="table table-bordered">';
4593
        $html .= '<tr>';
4594
        for ($ii = 1; $ii < 8; $ii++) {
4595
            $html .= '<td class="weekdays">'.$DaysShort[$ii % 7].'</td>';
4596
        }
4597
        $html .= '</tr>';
4598
4599
        $curday = -1;
4600
        $today = getdate();
4601
        while ($curday <= $numberofdays[$month]) {
4602
            $html .= "<tr>";
4603
            for ($ii = 0; $ii < 7; $ii++) {
4604
                if (($curday == -1) && ($ii == $startdayofweek)) {
4605
                    $curday = 1;
4606
                }
4607
                if (($curday > 0) && ($curday <= $numberofdays[$month])) {
4608
                    $bgcolor = $class = 'class="days_week"';
4609
                    $dayheader = Display::div(
4610
                        $curday,
4611
                        ['class' => 'agenda_day']
4612
                    );
4613
                    if (($curday == $today['mday']) && ($year == $today['year']) && ($month == $today['mon'])) {
4614
                        $class = "class=\"days_today\" style=\"width:10%;\"";
4615
                    }
4616
4617
                    $html .= "<td ".$class.">".$dayheader;
4618
4619
                    if (!empty($agendaitems[$curday])) {
4620
                        $items = $agendaitems[$curday];
4621
                        $items = msort($items, 'start_date_tms');
4622
4623
                        foreach ($items as $value) {
4624
                            $value['title'] = Security::remove_XSS(
4625
                                $value['title']
4626
                            );
4627
                            $start_time = api_format_date(
4628
                                $value['start_date'],
4629
                                TIME_NO_SEC_FORMAT
4630
                            );
4631
                            $end_time = '';
4632
4633
                            if (!empty($value['end_date'])) {
4634
                                $end_time = '-&nbsp;<i>'.api_format_date(
4635
                                        $value['end_date'],
4636
                                        DATE_TIME_FORMAT_LONG
4637
                                    ).'</i>';
4638
                            }
4639
                            $complete_time = '<i>'.api_format_date(
4640
                                    $value['start_date'],
4641
                                    DATE_TIME_FORMAT_LONG
4642
                                ).'</i>&nbsp;'.$end_time;
4643
                            $time = '<i>'.$start_time.'</i>';
4644
4645
                            switch ($value['calendar_type']) {
4646
                                case 'personal':
4647
                                    $bg_color = '#D0E7F4';
4648
                                    $icon = Display::return_icon(
4649
                                        'user.png',
4650
                                        get_lang('MyAgenda'),
4651
                                        [],
4652
                                        ICON_SIZE_SMALL
4653
                                    );
4654
                                    break;
4655
                                case 'global':
4656
                                    $bg_color = '#FFBC89';
4657
                                    $icon = Display::return_icon(
4658
                                        'view_remove.png',
4659
                                        get_lang('GlobalEvent'),
4660
                                        [],
4661
                                        ICON_SIZE_SMALL
4662
                                    );
4663
                                    break;
4664
                                case 'course':
4665
                                    $bg_color = '#CAFFAA';
4666
                                    $icon_name = 'course.png';
4667
                                    if (!empty($value['session_id'])) {
4668
                                        $icon_name = 'session.png';
4669
                                    }
4670
                                    if ($show_content) {
4671
                                        $icon = Display::url(
4672
                                            Display::return_icon(
4673
                                                $icon_name,
4674
                                                $value['course_name'].' '.get_lang(
4675
                                                    'Course'
4676
                                                ),
4677
                                                [],
4678
                                                ICON_SIZE_SMALL
4679
                                            ),
4680
                                            $value['url']
4681
                                        );
4682
                                    } else {
4683
                                        $icon = Display::return_icon(
4684
                                            $icon_name,
4685
                                            $value['course_name'].' '.get_lang(
4686
                                                'Course'
4687
                                            ),
4688
                                            [],
4689
                                            ICON_SIZE_SMALL
4690
                                        );
4691
                                    }
4692
                                    break;
4693
                                default:
4694
                                    break;
4695
                            }
4696
4697
                            $result = '<div class="rounded_div_agenda" style="background-color:'.$bg_color.';">';
4698
4699
                            if ($show_content) {
4700
                                //Setting a personal event to green
4701
                                $icon = Display::div(
4702
                                    $icon,
4703
                                    ['style' => 'float:right']
4704
                                );
4705
4706
                                $link = $value['calendar_type'].'_'.$value['id'].'_'.$value['course_id'].'_'.$value['session_id'];
4707
4708
                                //Link to bubble
4709
                                $url = Display::url(
4710
                                    cut($value['title'], 40),
4711
                                    '#',
4712
                                    ['id' => $link, 'class' => 'opener']
4713
                                );
4714
                                $result .= $time.' '.$icon.' '.Display::div(
4715
                                        $url
4716
                                    );
4717
4718
                                //Hidden content
4719
                                $content = Display::div(
4720
                                    $icon.Display::tag(
4721
                                        'h2',
4722
                                        $value['course_name']
4723
                                    ).'<hr />'.Display::tag(
4724
                                        'h3',
4725
                                        $value['title']
4726
                                    ).$complete_time.'<hr />'.Security::remove_XSS(
4727
                                        $value['content']
4728
                                    )
4729
                                );
4730
4731
                                //Main div
4732
                                $result .= Display::div(
4733
                                    $content,
4734
                                    [
4735
                                        'id' => 'main_'.$link,
4736
                                        'class' => 'dialog',
4737
                                        'style' => 'display:none',
4738
                                    ]
4739
                                );
4740
                                $result .= '</div>';
4741
                                $html .= $result;
4742
                            } else {
4743
                                $html .= $result .= $icon.'</div>';
4744
                            }
4745
                        }
4746
                    }
4747
                    $html .= "</td>";
4748
                    $curday++;
4749
                } else {
4750
                    $html .= "<td></td>";
4751
                }
4752
            }
4753
            $html .= "</tr>";
4754
        }
4755
        $html .= "</table>";
4756
        echo $html;
4757
    }
4758
4759
    /**
4760
     * Get personal agenda items between two dates (=all events from all registered courses).
4761
     *
4762
     * @param int $user_id user ID of the user
4763
     * @param    string    Optional start date in datetime format (if no start date is given, uses today)
4764
     * @param    string    Optional end date in datetime format (if no date is given, uses one year from now)
4765
     *
4766
     * @return array array of events ordered by start date, in
4767
     *               [0]('datestart','dateend','title'),[1]('datestart','dateend','title','link','coursetitle') format,
4768
     *               where datestart and dateend are in yyyyMMddhhmmss format
4769
     *
4770
     * @deprecated use agenda events
4771
     */
4772
    public static function get_personal_agenda_items_between_dates(
4773
        $user_id,
4774
        $date_start = '',
4775
        $date_end = ''
4776
    ) {
4777
        $items = [];
4778
        if ($user_id != strval(intval($user_id))) {
4779
            return $items;
4780
        }
4781
        if (empty($date_start)) {
4782
            $date_start = date('Y-m-d H:i:s');
4783
        }
4784
        if (empty($date_end)) {
4785
            $date_end = date(
4786
                'Y-m-d H:i:s',
4787
                mktime(0, 0, 0, date("m"), date("d"), date("Y") + 1)
4788
            );
4789
        }
4790
        $expr = '/\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}/';
4791
        if (!preg_match($expr, $date_start)) {
4792
            return $items;
4793
        }
4794
        if (!preg_match($expr, $date_end)) {
4795
            return $items;
4796
        }
4797
4798
        // get agenda-items for every course
4799
        $courses = api_get_user_courses($user_id, false);
4800
        foreach ($courses as $id => $course) {
4801
            $c = api_get_course_info_by_id($course['real_id']);
4802
            //databases of the courses
4803
            $t_a = Database::get_course_table(TABLE_AGENDA, $course['db']);
4804
            $t_ip = Database::get_course_table(
4805
                TABLE_ITEM_PROPERTY,
4806
                $course['db']
4807
            );
4808
            // get the groups to which the user belong
4809
            $group_memberships = GroupManager::get_group_ids(
4810
                $course['db'],
4811
                $user_id
4812
            );
4813
            // if the user is administrator of that course we show all the agenda items
4814
            if ($course['status'] == '1') {
4815
                //echo "course admin";
4816
                $sqlquery = "SELECT ".
4817
                    " DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4818
                    " FROM ".$t_a." agenda, ".
4819
                    $t_ip." ip ".
4820
                    " WHERE agenda.id = ip.ref ".
4821
                    " AND agenda.start_date>='$date_start' ".
4822
                    " AND agenda.end_date<='$date_end' ".
4823
                    " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4824
                    " AND ip.visibility='1' ".
4825
                    " GROUP BY agenda.id ".
4826
                    " ORDER BY start_date ";
4827
            } else {
4828
                // if the user is not an administrator of that course, then...
4829
                if (is_array($group_memberships) && count(
4830
                        $group_memberships
4831
                    ) > 0
4832
                ) {
4833
                    $sqlquery = "SELECT ".
4834
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4835
                        " FROM ".$t_a." agenda, ".
4836
                        $t_ip." ip ".
4837
                        " WHERE agenda.id = ip.ref ".
4838
                        " AND agenda.start_date>='$date_start' ".
4839
                        " AND agenda.end_date<='$date_end' ".
4840
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4841
                        " AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4842
                            ", ",
4843
                            $group_memberships
4844
                        ).")) ) ".
4845
                        " AND ip.visibility='1' ".
4846
                        " ORDER BY start_date ";
4847
                } else {
4848
                    $sqlquery = "SELECT ".
4849
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4850
                        " FROM ".$t_a." agenda, ".
4851
                        $t_ip." ip ".
4852
                        " WHERE agenda.id = ip.ref ".
4853
                        " AND agenda.start_date>='$date_start' ".
4854
                        " AND agenda.end_date<='$date_end' ".
4855
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4856
                        " AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL) ".
4857
                        " AND ip.visibility='1' ".
4858
                        " ORDER BY start_date ";
4859
                }
4860
            }
4861
4862
            $result = Database::query($sqlquery);
4863
            while ($item = Database::fetch_array($result)) {
4864
                $agendaday = date("j", strtotime($item['start_date']));
4865
                $month = date("n", strtotime($item['start_date']));
4866
                $year = date("Y", strtotime($item['start_date']));
4867
                $URL = api_get_path(
4868
                        WEB_PATH
4869
                    )."main/calendar/agenda.php?cidReq=".urlencode(
4870
                        $course["code"]
4871
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4872
                list($year, $month, $day, $hour, $min, $sec) = explode(
4873
                    '[-: ]',
4874
                    $item['start_date']
4875
                );
4876
                $start_date = $year.$month.$day.$hour.$min;
4877
                list($year, $month, $day, $hour, $min, $sec) = explode(
4878
                    '[-: ]',
4879
                    $item['end_date']
4880
                );
4881
                $end_date = $year.$month.$day.$hour.$min;
4882
4883
                $items[] = [
4884
                    'datestart' => $start_date,
4885
                    'dateend' => $end_date,
4886
                    'title' => $item['title'],
4887
                    'link' => $URL,
4888
                    'coursetitle' => $c['name'],
4889
                ];
4890
            }
4891
        }
4892
4893
        return $items;
4894
    }
4895
4896
    /**
4897
     * This function calculates the startdate of the week (monday)
4898
     * and the enddate of the week (sunday)
4899
     * and returns it as an array.
4900
     */
4901
    public static function calculate_start_end_of_week($week_number, $year)
4902
    {
4903
        // determine the start and end date
4904
        // step 1: we calculate a timestamp for a day in this week
4905
        $random_day_in_week = mktime(
4906
                0,
4907
                0,
4908
                0,
4909
                1,
4910
                1,
4911
                $year
4912
            ) + ($week_number) * (7 * 24 * 60 * 60); // we calculate a random day in this week
4913
        // step 2: we which day this is (0=sunday, 1=monday, ...)
4914
        $number_day_in_week = date('w', $random_day_in_week);
4915
        // step 3: we calculate the timestamp of the monday of the week we are in
4916
        $start_timestamp = $random_day_in_week - (($number_day_in_week - 1) * 24 * 60 * 60);
4917
        // step 4: we calculate the timestamp of the sunday of the week we are in
4918
        $end_timestamp = $random_day_in_week + ((7 - $number_day_in_week + 1) * 24 * 60 * 60) - 3600;
4919
        // step 5: calculating the start_day, end_day, start_month, end_month, start_year, end_year
4920
        $start_day = date('j', $start_timestamp);
4921
        $start_month = date('n', $start_timestamp);
4922
        $start_year = date('Y', $start_timestamp);
4923
        $end_day = date('j', $end_timestamp);
4924
        $end_month = date('n', $end_timestamp);
4925
        $end_year = date('Y', $end_timestamp);
4926
        $start_end_array['start']['day'] = $start_day;
4927
        $start_end_array['start']['month'] = $start_month;
4928
        $start_end_array['start']['year'] = $start_year;
4929
        $start_end_array['end']['day'] = $end_day;
4930
        $start_end_array['end']['month'] = $end_month;
4931
        $start_end_array['end']['year'] = $end_year;
4932
4933
        return $start_end_array;
4934
    }
4935
4936
    /**
4937
     * @return bool
4938
     */
4939
    public function getIsAllowedToEdit()
4940
    {
4941
        return $this->isAllowedToEdit;
4942
    }
4943
4944
    /**
4945
     * @param bool $isAllowedToEdit
4946
     */
4947
    public function setIsAllowedToEdit($isAllowedToEdit)
4948
    {
4949
        $this->isAllowedToEdit = $isAllowedToEdit;
4950
    }
4951
4952
    /**
4953
     * Format needed for the Fullcalendar js lib.
4954
     *
4955
     * @param string $utcTime
4956
     *
4957
     * @return bool|string
4958
     */
4959
    public function formatEventDate($utcTime)
4960
    {
4961
        if ($utcTime instanceof DateTime) {
4962
            $eventDate = $utcTime;
4963
        } else {
4964
            $utcTimeZone = new DateTimeZone('UTC');
4965
            $eventDate = new DateTime($utcTime, $utcTimeZone);
4966
        }
4967
4968
        $platformTimeZone = new DateTimeZone(api_get_timezone());
4969
4970
        $eventDate->setTimezone($platformTimeZone);
4971
4972
        return $eventDate->format(DateTime::ISO8601);
4973
    }
4974
4975
    /**
4976
     * @throws \Doctrine\ORM\OptimisticLockException
4977
     * @throws \Doctrine\ORM\ORMException
4978
     * @throws \Doctrine\ORM\TransactionRequiredException
4979
     */
4980
    public static function saveCollectiveProperties(array $inviteeUserList, bool $isCollective, int $eventId)
4981
    {
4982
        if (empty($inviteeUserList)) {
4983
            return;
4984
        }
4985
4986
        $em = Database::getManager();
4987
4988
        $event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
4989
4990
        $invitation = $event->getInvitation();
4991
4992
        if ($invitation instanceof AgendaEventSubscription) {
4993
            return;
4994
        }
4995
4996
        if (!$invitation) {
4997
            $invitation = new AgendaEventInvitation();
4998
            $invitation->setCreator(api_get_user_entity(api_get_user_id()));
4999
5000
            $event->setInvitation($invitation);
5001
        }
5002
5003
        $event->setCollective($isCollective);
5004
5005
        foreach ($inviteeUserList as $inviteeId) {
5006
            $userInvitee = api_get_user_entity($inviteeId);
5007
5008
            if (!$invitation->hasUserAsInvitee($userInvitee)) {
5009
                $invitee = new AgendaEventInvitee();
5010
                $invitee
5011
                    ->setUser($userInvitee)
5012
                    ->setInvitation($invitation)
5013
                ;
5014
5015
                $em->persist($invitee);
5016
            }
5017
        }
5018
5019
        $em->flush();
5020
    }
5021
5022
    public static function getJsForReminders(string $cssSelectorBtnAdd): string
5023
    {
5024
        return '
5025
            var template = \'<div class="form-group">\' +
5026
                \'<div class="col-sm-offset-2 col-sm-3">\' +
5027
                \'<input min="0" step="1" id="notification_count[]" type="number" class=" form-control" name="notification_count[]">\' +
5028
                \'</div>\' +
5029
                \'<div class="col-sm-3">\' +
5030
                \'<select class="form-control" name="notification_period[]" id="form_notification_period[]">\' +
5031
                \'<option value="i">'.get_lang('Minutes').'</option>\' +
5032
                \'<option value="h">'.get_lang('Hours').'</option>\' +
5033
                \'<option value="d">'.get_lang('Days').'</option>\' +
5034
                \'</select>\' +
5035
                \'</div>\' +
5036
                \'<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>\' +
5037
                \'<div class="text-right col-sm-2">\' +
5038
                \'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>\' +
5039
                \'</div>\' +
5040
                \'</div>\';
5041
5042
            $("'.$cssSelectorBtnAdd.'").on("click", function (e) {
5043
                e.preventDefault();
5044
5045
                $(template).appendTo("#notification_list");
5046
                $("#notification_list select").selectpicker("refresh");
5047
            });
5048
5049
            $("#notification_list").on("click", ".delete-notification", function (e) {
5050
                e.preventDefault();
5051
5052
                $(this).parents(".form-group").remove();
5053
            });';
5054
    }
5055
5056
    public static function returnGoogleCalendarUrl(int $userId): ?string
5057
    {
5058
        $extraFieldInfo = UserManager::get_extra_user_data_by_field($userId, 'google_calendar_url');
5059
5060
        if (empty($extraFieldInfo) || empty($extraFieldInfo['google_calendar_url'])) {
5061
            return null;
5062
        }
5063
5064
        return $extraFieldInfo['google_calendar_url'];
5065
    }
5066
5067
    public static function returnFullCalendarExtraSettings(): ?string
5068
    {
5069
        $settings = api_get_configuration_value('fullcalendar_settings');
5070
5071
        if (empty($settings) || empty($settings['settings'])) {
5072
            return null;
5073
        }
5074
5075
        $encoded = json_encode($settings['settings']);
5076
5077
        return substr($encoded, 1, -1).',';
5078
    }
5079
5080
    public static function returnOnHoverInfo()
5081
    {
5082
        $onHoverInfo = api_get_configuration_value('agenda_on_hover_info');
5083
5084
        if (!empty($onHoverInfo)) {
5085
            return $onHoverInfo['options'];
5086
        }
5087
5088
        return [
5089
            'comment' => true,
5090
            'description' => true,
5091
        ];
5092
    }
5093
5094
    private function editReminders(int $eventId, array $reminderList = [])
5095
    {
5096
        if (false === api_get_configuration_value('agenda_reminders')) {
5097
            return;
5098
        }
5099
5100
        $eventReminders = $this->parseEventReminders(
5101
            $this->getEventReminders($eventId)
5102
        );
5103
        $eventIntervalList = array_column($eventReminders, 'date_interval');
5104
5105
        foreach ($eventIntervalList as $eventIntervalInfo) {
5106
            if (!in_array($eventIntervalInfo, $reminderList)) {
5107
                $this->removeReminders($eventId, $eventIntervalInfo[0], $eventIntervalInfo[1]);
5108
            }
5109
        }
5110
5111
        foreach ($reminderList as $reminderInfo) {
5112
            if (!in_array($reminderInfo, $eventIntervalList)) {
5113
                $this->addReminder($eventId, $reminderInfo[0], $reminderInfo[1]);
5114
            }
5115
        }
5116
    }
5117
5118
    private static function isUserInvitedInEvent(int $id, int $userId): bool
5119
    {
5120
        $user = api_get_user_entity($userId);
5121
5122
        $event = Database::getManager()
5123
            ->getRepository('ChamiloCoreBundle:PersonalAgenda')
5124
            ->findOneByIdAndInvitee($id, $user)
5125
        ;
5126
5127
        return null !== $event;
5128
    }
5129
5130
    private function loadEventsAsInvitee(User $user, ?DateTime $startDate, ?DateTime $endDate)
5131
    {
5132
        $em = Database::getManager();
5133
        $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
5134
        $events = $eventRepo->getEventsForInvitee($user, $startDate, $endDate);
5135
5136
        foreach ($events as $event) {
5137
            $eventInfo = [];
5138
            $eventInfo['id'] = 'personal_'.$event->getId();
5139
            $eventInfo['title'] = $event->getTitle();
5140
            $eventInfo['className'] = 'personal';
5141
            $eventInfo['borderColor'] = $eventInfo['backgroundColor'] = $this->event_personal_color;
5142
            $eventInfo['editable'] = $event->isCollective();
5143
            $eventInfo['sent_to'] = get_lang('Me');
5144
            $eventInfo['type'] = 'personal';
5145
5146
            if ($event->getDate()) {
5147
                $eventInfo['start'] = $this->formatEventDate($event->getDate()->format('Y-m-d H:i:s'));
5148
                $eventInfo['start_date_localtime'] = api_get_local_time($event->getDate());
5149
            }
5150
5151
            if ($event->getEnddate()) {
5152
                $eventInfo['end'] = $this->formatEventDate($event->getEnddate()->format('Y-m-d H:i:s'));
5153
                $eventInfo['end_date_localtime'] = api_get_local_time($event->getEnddate());
5154
            }
5155
5156
            $eventInfo['description'] = $event->getText();
5157
            $eventInfo['allDay'] = $event->getAllDay();
5158
            $eventInfo['parent_event_id'] = 0;
5159
            $eventInfo['has_children'] = 0;
5160
            $eventInfo['collective'] = $event->isCollective();
5161
            $eventInfo['invitees'] = [];
5162
5163
            $invitation = $event->getInvitation();
5164
5165
            if ($invitation) {
5166
                foreach ($invitation->getInvitees() as $invitee) {
5167
                    $inviteeUser = $invitee->getUser();
5168
5169
                    $eventInfo['invitees'][] = [
5170
                        'id' => $inviteeUser->getId(),
5171
                        'name' => $inviteeUser->getCompleteNameWithUsername(),
5172
                    ];
5173
                }
5174
            }
5175
5176
            $this->events[] = $eventInfo;
5177
        }
5178
    }
5179
5180
    /**
5181
     * @throws Exception
5182
     */
5183
    private function convertSessionWithDuration(int $userId, array $sessionInfo, DateTime $start, DateTime $end): array
5184
    {
5185
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
5186
            $sessionInfo['session_id'],
5187
            $userId
5188
        );
5189
5190
        if (empty($courseAccess)) {
5191
            throw new Exception();
5192
        }
5193
5194
        $firstAccessDate = new DateTime($courseAccess['login_course_date'], new DateTimeZone('UTC'));
5195
        $lastAccessDate = clone $firstAccessDate;
5196
        $lastAccessDate->modify('+'.$sessionInfo['duration'].' days');
5197
5198
        if ($firstAccessDate->format('Y-m-d H:i:s') > $start
5199
            && $lastAccessDate->format('Y-m-d H:i:s') < $end
5200
        ) {
5201
            throw new Exception();
5202
        }
5203
5204
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5205
        $firstCourse = current($courseList);
5206
5207
        return [
5208
            'id' => 'session_'.$sessionInfo['id'],
5209
            'session_id' => $sessionInfo['id'],
5210
            'title' => $sessionInfo['name'],
5211
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5212
            'className' => 'personal',
5213
            'borderColor' => $this->event_personal_color,
5214
            'backgroundColor' => $this->event_personal_color,
5215
            'editable' => false,
5216
            'sent_to' => get_lang('Me'),
5217
            'type' => 'session',
5218
            'start' => $firstAccessDate->format(DateTime::ISO8601),
5219
            'start_date_localtime' => api_get_local_time($firstAccessDate),
5220
            'end' => $lastAccessDate->format(DateTime::ISO8601),
5221
            'end_date_localtime' => api_get_local_time($lastAccessDate),
5222
            'allDay' => 0,
5223
            'parent_event_id' => 0,
5224
            'has_children' => 0,
5225
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5226
        ];
5227
    }
5228
5229
    /**
5230
     * @throws Exception
5231
     */
5232
    private function convertSessionWithDates(array $sessionInfo, DateTime $start, DateTime $end): array
5233
    {
5234
        if ($sessionInfo['display_start_date'] < $start
5235
            && $sessionInfo['display_end_date'] > $end
5236
        ) {
5237
            throw new Exception();
5238
        }
5239
5240
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5241
        $firstCourse = current($courseList);
5242
5243
        return [
5244
            'id' => 'session_'.$sessionInfo['id'],
5245
            'session_id' => $sessionInfo['id'],
5246
            'title' => $sessionInfo['name'],
5247
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5248
            'className' => 'personal',
5249
            'borderColor' => $this->event_personal_color,
5250
            'backgroundColor' => $this->event_personal_color,
5251
            'editable' => false,
5252
            'sent_to' => get_lang('Me'),
5253
            'type' => 'session_subscription',
5254
            'start' => $sessionInfo['display_start_date'],
5255
            'start_date_localtime' => $sessionInfo['display_start_date']
5256
                ? $this->formatEventDate($sessionInfo['display_start_date'])
5257
                : '',
5258
            'end' => $sessionInfo['display_end_date'],
5259
            'end_date_localtime' => $sessionInfo['display_end_date']
5260
                ? $this->formatEventDate($sessionInfo['display_end_date'])
5261
                : '',
5262
            'allDay' => 0,
5263
            'parent_event_id' => 0,
5264
            'has_children' => 0,
5265
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5266
        ];
5267
    }
5268
5269
    private function loadSessionsAsEvents(int $start, int $end)
5270
    {
5271
        if (false === api_get_configuration_value('personal_calendar_show_sessions_occupation')) {
5272
            return;
5273
        }
5274
5275
        $start = api_get_utc_datetime($start, false, true);
5276
        $end = api_get_utc_datetime($end, false, true);
5277
        $userInfo = api_get_user_info();
5278
        $sessionList = SessionManager::getSessionsFollowedByUser($userInfo['id'], $userInfo['status']);
5279
5280
        foreach ($sessionList as $sessionInfo) {
5281
            if (!empty($sessionInfo['duration'])) {
5282
                try {
5283
                    $this->events[] = $this->convertSessionWithDuration($userInfo['id'], $sessionInfo, $start, $end);
5284
                } catch (Exception $e) {
5285
                    continue;
5286
                }
5287
5288
                continue;
5289
            }
5290
5291
            if (empty($sessionInfo['display_start_date']) || empty($sessionInfo['display_end_date'])) {
5292
                continue;
5293
            }
5294
5295
            try {
5296
                $this->events[] = $this->convertSessionWithDates($sessionInfo, $start, $end);
5297
            } catch (Exception $e) {
5298
                continue;
5299
            }
5300
        }
5301
    }
5302
}
5303