Passed
Pull Request — 1.11.x (#4668)
by Angel Fernando Quiroz
08:13
created

Agenda::setType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\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 $maxSubscriptions = 0
263
    ) {
264
        $start = api_get_utc_datetime($start);
265
        $end = api_get_utc_datetime($end);
266
        $allDay = isset($allDay) && ($allDay === 'true' || $allDay == 1) ? 1 : 0;
267
        $id = null;
268
269
        $em = Database::getManager();
270
271
        switch ($this->type) {
272
            case 'personal':
273
                $attributes = [
274
                    'user' => api_get_user_id(),
275
                    'title' => $title,
276
                    'text' => $content,
277
                    'date' => $start,
278
                    'enddate' => $end,
279
                    'all_day' => $allDay,
280
                    'color' => $color,
281
                ];
282
283
                $id = Database::insert(
284
                    $this->tbl_personal_agenda,
285
                    $attributes
286
                );
287
288
                if (api_get_configuration_value('agenda_collective_invitations')) {
289
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
290
                }
291
292
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
293
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
294
                    $personalEvent
295
                        ->setSubscriptionVisibility($subscriptionVisibility)
296
                    ;
297
298
                    $subscription = (new AgendaEventSubscription())
299
                        ->setCreator(api_get_user_entity(api_get_user_id()))
300
                        ->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0)
301
                    ;
302
303
                    $personalEvent
304
                        ->setCollective(false)
305
                        ->setInvitation($subscription)
306
                    ;
307
308
                    $em->flush();
309
                }
310
                break;
311
            case 'course':
312
                $attributes = [
313
                    'title' => $title,
314
                    'content' => $content,
315
                    'start_date' => $start,
316
                    'end_date' => $end,
317
                    'all_day' => $allDay,
318
                    'session_id' => $this->getSessionId(),
319
                    'c_id' => $this->course['real_id'],
320
                    'comment' => $eventComment,
321
                    'color' => $color,
322
                ];
323
324
                if (!empty($parentEventId)) {
325
                    $attributes['parent_event_id'] = $parentEventId;
326
                }
327
328
                $senderId = $this->getSenderId();
329
                $sessionId = $this->getSessionId();
330
331
                // Simple course event.
332
                $id = Database::insert($this->tbl_course_agenda, $attributes);
333
334
                if ($id) {
335
                    $sql = "UPDATE ".$this->tbl_course_agenda." SET id = iid WHERE iid = $id";
336
                    Database::query($sql);
337
338
                    $groupId = api_get_group_id();
339
                    $groupInfo = [];
340
                    if ($groupId) {
341
                        $groupInfo = GroupManager::get_group_properties(
342
                            $groupId
343
                        );
344
                    }
345
346
                    if (!empty($usersToSend)) {
347
                        $sendTo = $this->parseSendToArray($usersToSend);
348
                        if ($sendTo['everyone']) {
349
                            api_item_property_update(
350
                                $this->course,
351
                                TOOL_CALENDAR_EVENT,
352
                                $id,
353
                                'AgendaAdded',
354
                                $senderId,
355
                                $groupInfo,
356
                                '',
357
                                $start,
358
                                $end,
359
                                $sessionId
360
                            );
361
                            api_item_property_update(
362
                                $this->course,
363
                                TOOL_CALENDAR_EVENT,
364
                                $id,
365
                                'visible',
366
                                $senderId,
367
                                $groupInfo,
368
                                '',
369
                                $start,
370
                                $end,
371
                                $sessionId
372
                            );
373
                        } else {
374
                            // Storing the selected groups
375
                            if (!empty($sendTo['groups'])) {
376
                                foreach ($sendTo['groups'] as $group) {
377
                                    $groupInfoItem = [];
378
                                    if ($group) {
379
                                        $groupInfoItem = GroupManager::get_group_properties($group);
380
                                    }
381
382
                                    api_item_property_update(
383
                                        $this->course,
384
                                        TOOL_CALENDAR_EVENT,
385
                                        $id,
386
                                        'AgendaAdded',
387
                                        $senderId,
388
                                        $groupInfoItem,
389
                                        0,
390
                                        $start,
391
                                        $end,
392
                                        $sessionId
393
                                    );
394
395
                                    api_item_property_update(
396
                                        $this->course,
397
                                        TOOL_CALENDAR_EVENT,
398
                                        $id,
399
                                        'visible',
400
                                        $senderId,
401
                                        $groupInfoItem,
402
                                        0,
403
                                        $start,
404
                                        $end,
405
                                        $sessionId
406
                                    );
407
                                }
408
                            }
409
410
                            // storing the selected users
411
                            if (!empty($sendTo['users'])) {
412
                                foreach ($sendTo['users'] as $userId) {
413
                                    api_item_property_update(
414
                                        $this->course,
415
                                        TOOL_CALENDAR_EVENT,
416
                                        $id,
417
                                        'AgendaAdded',
418
                                        $senderId,
419
                                        $groupInfo,
420
                                        $userId,
421
                                        $start,
422
                                        $end,
423
                                        $sessionId
424
                                    );
425
426
                                    api_item_property_update(
427
                                        $this->course,
428
                                        TOOL_CALENDAR_EVENT,
429
                                        $id,
430
                                        'visible',
431
                                        $senderId,
432
                                        $groupInfo,
433
                                        $userId,
434
                                        $start,
435
                                        $end,
436
                                        $sessionId
437
                                    );
438
                                }
439
                            }
440
                        }
441
                    }
442
443
                    // Add announcement.
444
                    if ($addAsAnnouncement) {
445
                        $this->storeAgendaEventAsAnnouncement(
446
                            $id,
447
                            $usersToSend
448
                        );
449
                    }
450
451
                    // Add attachment.
452
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
453
                        $counter = 0;
454
                        foreach ($attachmentArray as $attachmentItem) {
455
                            $this->addAttachment(
456
                                $id,
457
                                $attachmentItem,
458
                                $attachmentCommentList[$counter],
459
                                $this->course
460
                            );
461
                            $counter++;
462
                        }
463
                    }
464
                }
465
                break;
466
            case 'admin':
467
                if (api_is_platform_admin()) {
468
                    $attributes = [
469
                        'title' => $title,
470
                        'content' => $content,
471
                        'start_date' => $start,
472
                        'end_date' => $end,
473
                        'all_day' => $allDay,
474
                        'access_url_id' => api_get_current_access_url_id(),
475
                    ];
476
477
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
478
                        $attributes['career_id'] = $careerId;
479
                        $attributes['promotion_id'] = $promotionId;
480
                    }
481
482
                    $id = Database::insert(
483
                        $this->tbl_global_agenda,
484
                        $attributes
485
                    );
486
                }
487
                break;
488
        }
489
490
        if (api_get_configuration_value('agenda_reminders')) {
491
            foreach ($reminders as $reminder) {
492
                $this->addReminder($id, $reminder[0], $reminder[1]);
493
            }
494
        }
495
496
        return $id;
497
    }
498
499
    /**
500
     * @throws Exception
501
     */
502
    public function addReminder($eventId, $count, $period)
503
    {
504
        switch ($period) {
505
            case 'i':
506
                $dateInterval = DateInterval::createFromDateString("$count minutes");
507
                break;
508
            case 'h':
509
                $dateInterval = DateInterval::createFromDateString("$count hours");
510
                break;
511
            case 'd':
512
                $dateInterval = DateInterval::createFromDateString("$count days");
513
                break;
514
            default:
515
                return null;
516
        }
517
518
        $agendaReminder = new AgendaReminder();
519
        $agendaReminder
520
            ->setType($this->type)
521
            ->setEventId($eventId)
522
            ->setDateInterval($dateInterval)
523
        ;
524
525
        $em = Database::getManager();
526
        $em->persist($agendaReminder);
527
        $em->flush();
528
    }
529
530
    public function removeReminders(int $eventId, int $count, string $period)
531
    {
532
        switch ($period) {
533
            case 'i':
534
                $dateInterval = DateInterval::createFromDateString("$count minutes");
535
                break;
536
            case 'h':
537
                $dateInterval = DateInterval::createFromDateString("$count hours");
538
                break;
539
            case 'd':
540
                $dateInterval = DateInterval::createFromDateString("$count days");
541
                break;
542
            default:
543
                return null;
544
        }
545
546
        Database::getManager()
547
            ->createQuery(
548
                'DELETE FROM ChamiloCoreBundle:AgendaReminder ar
549
                WHERE ar.eventId = :eventId AND ar.type = :type AND ar.dateInterval = :dateInterval'
550
            )
551
            ->setParameters(
552
                [
553
                    'eventId' => $eventId,
554
                    'type' => $this->type,
555
                    'dateInterval' => $dateInterval,
556
                ]
557
            )
558
            ->execute();
559
    }
560
561
    public function getReminder(int $eventId, int $count, string $period)
562
    {
563
        switch ($period) {
564
            case 'i':
565
                $dateInterval = DateInterval::createFromDateString("$count minutes");
566
                break;
567
            case 'h':
568
                $dateInterval = DateInterval::createFromDateString("$count hours");
569
                break;
570
            case 'd':
571
                $dateInterval = DateInterval::createFromDateString("$count days");
572
                break;
573
            default:
574
                return null;
575
        }
576
577
        $em = Database::getManager();
578
        $remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
579
580
        return $remindersRepo->findOneBy(
581
            [
582
                'type' => $this->type,
583
                'dateInterval' => $dateInterval,
584
                'eventId' => $eventId,
585
            ]
586
        );
587
    }
588
589
    /**
590
     * @param int $eventId
591
     * @param int $courseId
592
     *
593
     * @return array
594
     */
595
    public function getRepeatedInfoByEvent($eventId, $courseId)
596
    {
597
        $repeatTable = Database::get_course_table(TABLE_AGENDA_REPEAT);
598
        $eventId = (int) $eventId;
599
        $courseId = (int) $courseId;
600
        $sql = "SELECT * FROM $repeatTable
601
                WHERE c_id = $courseId AND cal_id = $eventId";
602
        $res = Database::query($sql);
603
        $repeatInfo = [];
604
        if (Database::num_rows($res) > 0) {
605
            $repeatInfo = Database::fetch_array($res, 'ASSOC');
606
        }
607
608
        return $repeatInfo;
609
    }
610
611
    /**
612
     * @param string $type
613
     * @param string $startEvent      in UTC
614
     * @param string $endEvent        in UTC
615
     * @param string $repeatUntilDate in UTC
616
     *
617
     * @throws Exception
618
     *
619
     * @return array with local times
620
     */
621
    public function generateDatesByType($type, $startEvent, $endEvent, $repeatUntilDate)
622
    {
623
        $continue = true;
624
        $repeatUntilDate = new DateTime($repeatUntilDate, new DateTimeZone('UTC'));
625
        $loopMax = 365;
626
        $counter = 0;
627
        $list = [];
628
629
        switch ($type) {
630
            case 'daily':
631
                $interval = 'P1D';
632
                break;
633
            case 'weekly':
634
                $interval = 'P1W';
635
                break;
636
            case 'monthlyByDate':
637
                $interval = 'P1M';
638
                break;
639
            case 'monthlyByDay':
640
                // not yet implemented
641
                break;
642
            case 'monthlyByDayR':
643
                // not yet implemented
644
                break;
645
            case 'yearly':
646
                $interval = 'P1Y';
647
                break;
648
        }
649
650
        if (empty($interval)) {
651
            return [];
652
        }
653
        $timeZone = api_get_timezone();
654
655
        while ($continue) {
656
            $startDate = new DateTime($startEvent, new DateTimeZone('UTC'));
657
            $endDate = new DateTime($endEvent, new DateTimeZone('UTC'));
658
659
            $startDate->add(new DateInterval($interval));
660
            $endDate->add(new DateInterval($interval));
661
662
            $newStartDate = $startDate->format('Y-m-d H:i:s');
663
            $newEndDate = $endDate->format('Y-m-d H:i:s');
664
665
            $startEvent = $newStartDate;
666
            $endEvent = $newEndDate;
667
668
            if ($endDate > $repeatUntilDate) {
669
                break;
670
            }
671
672
            // @todo remove comment code
673
            // The code below was not adpating to saving light time but was doubling the difference with UTC time.
674
            // Might be necessary to adapt to update saving light time difference.
675
            /*            $startDateInLocal = new DateTime($newStartDate, new DateTimeZone($timeZone));
676
                        if ($startDateInLocal->format('I') == 0) {
677
                            // Is saving time? Then fix UTC time to add time
678
                            $seconds = $startDateInLocal->getOffset();
679
                            $startDate->add(new DateInterval("PT".$seconds."S"));
680
                            //$startDateFixed = $startDate->format('Y-m-d H:i:s');
681
                            //$startDateInLocalFixed = new DateTime($startDateFixed, new DateTimeZone($timeZone));
682
                            //$newStartDate = $startDateInLocalFixed->format('Y-m-d H:i:s');
683
                            //$newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
684
                        }
685
686
                        $endDateInLocal = new DateTime($newEndDate, new DateTimeZone($timeZone));
687
                        if ($endDateInLocal->format('I') == 0) {
688
                            // Is saving time? Then fix UTC time to add time
689
                            $seconds = $endDateInLocal->getOffset();
690
                            $endDate->add(new DateInterval("PT".$seconds."S"));
691
                            //$endDateFixed = $endDate->format('Y-m-d H:i:s');
692
                            //$endDateInLocalFixed = new DateTime($endDateFixed, new DateTimeZone($timeZone));
693
                            //$newEndDate = $endDateInLocalFixed->format('Y-m-d H:i:s');
694
                    }
695
            */
696
            $newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
697
            $newEndDate = $endDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
698
            $list[] = ['start' => $newStartDate, 'end' => $newEndDate];
699
            $counter++;
700
701
            // just in case stop if more than $loopMax
702
            if ($counter > $loopMax) {
703
                break;
704
            }
705
        }
706
707
        return $list;
708
    }
709
710
    /**
711
     * @param int    $eventId
712
     * @param string $type
713
     * @param string $end     in UTC
714
     * @param array  $sentTo
715
     *
716
     * @return bool
717
     */
718
    public function addRepeatedItem($eventId, $type, $end, $sentTo = [])
719
    {
720
        $t_agenda = Database::get_course_table(TABLE_AGENDA);
721
        $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT);
722
723
        if (empty($this->course)) {
724
            return false;
725
        }
726
727
        $courseId = $this->course['real_id'];
728
        $eventId = (int) $eventId;
729
730
        $sql = "SELECT title, content, start_date, end_date, all_day
731
                FROM $t_agenda
732
                WHERE c_id = $courseId AND id = $eventId";
733
        $res = Database::query($sql);
734
735
        if (Database::num_rows($res) !== 1) {
736
            return false;
737
        }
738
739
        $typeList = [
740
            'daily',
741
            'weekly',
742
            'monthlyByDate',
743
            'monthlyByDay',
744
            'monthlyByDayR',
745
            'yearly',
746
        ];
747
748
        if (!in_array($type, $typeList)) {
749
            return false;
750
        }
751
752
        $now = time();
753
754
        // The event has to repeat *in the future*. We don't allow repeated
755
        // events in the past.
756
        $endTimeStamp = api_strtotime($end, 'UTC');
757
758
        if ($endTimeStamp < $now) {
759
            return false;
760
        }
761
762
        $row = Database::fetch_array($res);
763
764
        $title = $row['title'];
765
        $content = $row['content'];
766
        $allDay = $row['all_day'];
767
768
        $type = Database::escape_string($type);
769
        $end = Database::escape_string($end);
770
771
        $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end)
772
                VALUES ($courseId, '$eventId', '$type', '$endTimeStamp')";
773
        Database::query($sql);
774
775
        $generatedDates = $this->generateDatesByType($type, $row['start_date'], $row['end_date'], $end);
776
777
        if (empty($generatedDates)) {
778
            return false;
779
        }
780
781
        foreach ($generatedDates as $dateInfo) {
782
//            $start = api_get_local_time($dateInfo['start']);
783
//            $end = api_get_local_time($dateInfo['end']);
784
            // On line 529 in function generateDatesByType there is a @todo remove comment code
785
            // just before the part updating the date in local time so keep both synchronised
786
            $start = $dateInfo['start'];
787
            $end = $dateInfo['end'];
788
789
            $this->addEvent(
790
                $start,
791
                $end,
792
                $allDay,
793
                $title,
794
                $content,
795
                $sentTo,
796
                false,
797
                $eventId
798
            );
799
        }
800
801
        return true;
802
    }
803
804
    /**
805
     * @param int   $item_id
806
     * @param array $sentTo
807
     *
808
     * @return int
809
     */
810
    public function storeAgendaEventAsAnnouncement($item_id, $sentTo = [])
811
    {
812
        $table_agenda = Database::get_course_table(TABLE_AGENDA);
813
        $courseId = api_get_course_int_id();
814
815
        // Check params
816
        if (empty($item_id) || $item_id != strval(intval($item_id))) {
817
            return -1;
818
        }
819
820
        // Get the agenda item.
821
        $item_id = intval($item_id);
822
        $sql = "SELECT * FROM $table_agenda
823
                WHERE c_id = $courseId AND id = ".$item_id;
824
        $res = Database::query($sql);
825
826
        if (Database::num_rows($res) > 0) {
827
            $row = Database::fetch_array($res, 'ASSOC');
828
829
            // Sending announcement
830
            if (!empty($sentTo)) {
831
                $id = AnnouncementManager::add_announcement(
832
                    api_get_course_info(),
833
                    api_get_session_id(),
834
                    $row['title'],
835
                    $row['content'],
836
                    $sentTo,
837
                    null,
838
                    null,
839
                    $row['end_date']
840
                );
841
842
                AnnouncementManager::sendEmail(
843
                    api_get_course_info(),
844
                    api_get_session_id(),
845
                    $id
846
                );
847
848
                return $id;
849
            }
850
        }
851
852
        return -1;
853
    }
854
855
    /**
856
     * Edits an event.
857
     *
858
     * @param int    $id
859
     * @param string $start                 datetime format: 2012-06-14 09:00:00
860
     * @param string $end                   datetime format: 2012-06-14 09:00:00
861
     * @param int    $allDay                is all day 'true' or 'false'
862
     * @param string $title
863
     * @param string $content
864
     * @param array  $usersToSend
865
     * @param array  $attachmentArray
866
     * @param array  $attachmentCommentList
867
     * @param string $comment
868
     * @param string $color
869
     * @param bool   $addAnnouncement
870
     * @param bool   $updateContent
871
     * @param int    $authorId
872
     *
873
     * @return bool
874
     */
875
    public function editEvent(
876
        $id,
877
        $start,
878
        $end,
879
        $allDay,
880
        $title,
881
        $content,
882
        $usersToSend = [],
883
        $attachmentArray = [],
884
        $attachmentCommentList = [],
885
        $comment = null,
886
        $color = '',
887
        $addAnnouncement = false,
888
        $updateContent = true,
889
        $authorId = 0,
890
        array $inviteesList = [],
891
        bool $isCollective = false,
892
        array $remindersList = [],
893
        int $careerId = 0,
894
        int $promotionId = 0,
895
        int $subscriptionVisibility = 0,
896
        int $maxSubscriptions = 0
897
    ) {
898
        $id = (int) $id;
899
        $start = api_get_utc_datetime($start);
900
        $end = api_get_utc_datetime($end);
901
        $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0;
902
        $currentUserId = api_get_user_id();
903
        $authorId = empty($authorId) ? $currentUserId : (int) $authorId;
904
905
        $em = Database::getManager();
906
907
        switch ($this->type) {
908
            case 'personal':
909
                $eventInfo = $this->get_event($id);
910
                if ($eventInfo['user'] != $currentUserId
911
                    && (
912
                        api_get_configuration_value('agenda_collective_invitations')
913
                            && !self::isUserInvitedInEvent($id, $currentUserId)
914
                    )
915
                ) {
916
                    break;
917
                }
918
                $attributes = [
919
                    'title' => $title,
920
                    'date' => $start,
921
                    'enddate' => $end,
922
                    'all_day' => $allDay,
923
                ];
924
925
                if ($updateContent) {
926
                    $attributes['text'] = $content;
927
                }
928
929
                if (!empty($color)) {
930
                    $attributes['color'] = $color;
931
                }
932
933
                Database::update(
934
                    $this->tbl_personal_agenda,
935
                    $attributes,
936
                    ['id = ?' => $id]
937
                );
938
939
                if (api_get_configuration_value('agenda_collective_invitations')) {
940
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
941
                }
942
943
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
944
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
945
                    $personalEvent
946
                        ->setSubscriptionVisibility($subscriptionVisibility)
947
                    ;
948
949
                    /** @var AgendaEventSubscription $subscription */
950
                    $subscription = $personalEvent->getInvitation();
951
                    $subscription->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0);
952
953
                    $em->flush();
954
                }
955
                break;
956
            case 'course':
957
                $eventInfo = $this->get_event($id);
958
959
                if (empty($eventInfo)) {
960
                    return false;
961
                }
962
963
                $groupId = api_get_group_id();
964
                $groupIid = 0;
965
                $groupInfo = [];
966
                if ($groupId) {
967
                    $groupInfo = GroupManager::get_group_properties($groupId);
968
                    if ($groupInfo) {
969
                        $groupIid = $groupInfo['iid'];
970
                    }
971
                }
972
973
                $courseId = $this->course['real_id'];
974
975
                if (empty($courseId)) {
976
                    return false;
977
                }
978
979
                if (!$this->getIsAllowedToEdit()) {
980
                    return false;
981
                }
982
983
                $attributes = [
984
                    'title' => $title,
985
                    'start_date' => $start,
986
                    'end_date' => $end,
987
                    'all_day' => $allDay,
988
                    'comment' => $comment,
989
                ];
990
991
                if ($updateContent) {
992
                    $attributes['content'] = $content;
993
                }
994
995
                if (!empty($color)) {
996
                    $attributes['color'] = $color;
997
                }
998
999
                Database::update(
1000
                    $this->tbl_course_agenda,
1001
                    $attributes,
1002
                    [
1003
                        'id = ? AND c_id = ? AND session_id = ? ' => [
1004
                            $id,
1005
                            $courseId,
1006
                            $this->sessionId,
1007
                        ],
1008
                    ]
1009
                );
1010
1011
                if (!empty($usersToSend)) {
1012
                    $sendTo = $this->parseSendToArray($usersToSend);
1013
1014
                    $usersToDelete = array_diff(
1015
                        $eventInfo['send_to']['users'],
1016
                        $sendTo['users']
1017
                    );
1018
                    $usersToAdd = array_diff(
1019
                        $sendTo['users'],
1020
                        $eventInfo['send_to']['users']
1021
                    );
1022
1023
                    $groupsToDelete = array_diff(
1024
                        $eventInfo['send_to']['groups'],
1025
                        $sendTo['groups']
1026
                    );
1027
                    $groupToAdd = array_diff(
1028
                        $sendTo['groups'],
1029
                        $eventInfo['send_to']['groups']
1030
                    );
1031
1032
                    if ($sendTo['everyone']) {
1033
                        // Delete all from group
1034
                        if (isset($eventInfo['send_to']['groups']) &&
1035
                            !empty($eventInfo['send_to']['groups'])
1036
                        ) {
1037
                            foreach ($eventInfo['send_to']['groups'] as $group) {
1038
                                $groupIidItem = 0;
1039
                                if ($group) {
1040
                                    $groupInfoItem = GroupManager::get_group_properties(
1041
                                        $group
1042
                                    );
1043
                                    if ($groupInfoItem) {
1044
                                        $groupIidItem = $groupInfoItem['iid'];
1045
                                    }
1046
                                }
1047
1048
                                api_item_property_delete(
1049
                                    $this->course,
1050
                                    TOOL_CALENDAR_EVENT,
1051
                                    $id,
1052
                                    0,
1053
                                    $groupIidItem,
1054
                                    $this->sessionId
1055
                                );
1056
                            }
1057
                        }
1058
1059
                        // Storing the selected users.
1060
                        if (isset($eventInfo['send_to']['users']) &&
1061
                            !empty($eventInfo['send_to']['users'])
1062
                        ) {
1063
                            foreach ($eventInfo['send_to']['users'] as $userId) {
1064
                                api_item_property_delete(
1065
                                    $this->course,
1066
                                    TOOL_CALENDAR_EVENT,
1067
                                    $id,
1068
                                    $userId,
1069
                                    $groupIid,
1070
                                    $this->sessionId
1071
                                );
1072
                            }
1073
                        }
1074
1075
                        // Add to everyone only.
1076
                        api_item_property_update(
1077
                            $this->course,
1078
                            TOOL_CALENDAR_EVENT,
1079
                            $id,
1080
                            'visible',
1081
                            $authorId,
1082
                            $groupInfo,
1083
                            null,
1084
                            $start,
1085
                            $end,
1086
                            $this->sessionId
1087
                        );
1088
                    } else {
1089
                        // Delete "everyone".
1090
                        api_item_property_delete(
1091
                            $this->course,
1092
                            TOOL_CALENDAR_EVENT,
1093
                            $id,
1094
                            0,
1095
                            0,
1096
                            $this->sessionId
1097
                        );
1098
1099
                        // Add groups
1100
                        if (!empty($groupToAdd)) {
1101
                            foreach ($groupToAdd as $group) {
1102
                                $groupInfoItem = [];
1103
                                if ($group) {
1104
                                    $groupInfoItem = GroupManager::get_group_properties(
1105
                                        $group
1106
                                    );
1107
                                }
1108
1109
                                api_item_property_update(
1110
                                    $this->course,
1111
                                    TOOL_CALENDAR_EVENT,
1112
                                    $id,
1113
                                    'visible',
1114
                                    $authorId,
1115
                                    $groupInfoItem,
1116
                                    0,
1117
                                    $start,
1118
                                    $end,
1119
                                    $this->sessionId
1120
                                );
1121
                            }
1122
                        }
1123
1124
                        // Delete groups.
1125
                        if (!empty($groupsToDelete)) {
1126
                            foreach ($groupsToDelete as $group) {
1127
                                $groupIidItem = 0;
1128
                                $groupInfoItem = [];
1129
                                if ($group) {
1130
                                    $groupInfoItem = GroupManager::get_group_properties(
1131
                                        $group
1132
                                    );
1133
                                    if ($groupInfoItem) {
1134
                                        $groupIidItem = $groupInfoItem['iid'];
1135
                                    }
1136
                                }
1137
1138
                                api_item_property_delete(
1139
                                    $this->course,
1140
                                    TOOL_CALENDAR_EVENT,
1141
                                    $id,
1142
                                    0,
1143
                                    $groupIidItem,
1144
                                    $this->sessionId
1145
                                );
1146
                            }
1147
                        }
1148
1149
                        // Add users.
1150
                        if (!empty($usersToAdd)) {
1151
                            foreach ($usersToAdd as $userId) {
1152
                                api_item_property_update(
1153
                                    $this->course,
1154
                                    TOOL_CALENDAR_EVENT,
1155
                                    $id,
1156
                                    'visible',
1157
                                    $authorId,
1158
                                    $groupInfo,
1159
                                    $userId,
1160
                                    $start,
1161
                                    $end,
1162
                                    $this->sessionId
1163
                                );
1164
                            }
1165
                        }
1166
1167
                        // Delete users.
1168
                        if (!empty($usersToDelete)) {
1169
                            foreach ($usersToDelete as $userId) {
1170
                                api_item_property_delete(
1171
                                    $this->course,
1172
                                    TOOL_CALENDAR_EVENT,
1173
                                    $id,
1174
                                    $userId,
1175
                                    $groupInfo,
1176
                                    $this->sessionId
1177
                                );
1178
                            }
1179
                        }
1180
                    }
1181
                }
1182
1183
                // Add announcement.
1184
                if (isset($addAnnouncement) && !empty($addAnnouncement)) {
1185
                    $this->storeAgendaEventAsAnnouncement(
1186
                        $id,
1187
                        $usersToSend
1188
                    );
1189
                }
1190
1191
                // Add attachment.
1192
                if (isset($attachmentArray) && !empty($attachmentArray)) {
1193
                    $counter = 0;
1194
                    foreach ($attachmentArray as $attachmentItem) {
1195
                        if (empty($attachmentItems['id'])) {
1196
                            continue;
1197
                        }
1198
1199
                        $this->updateAttachment(
1200
                            $attachmentItem['id'],
1201
                            $id,
1202
                            $attachmentItem,
1203
                            $attachmentCommentList[$counter],
1204
                            $this->course
1205
                        );
1206
                        $counter++;
1207
                    }
1208
                }
1209
                break;
1210
            case 'admin':
1211
            case 'platform':
1212
                if (api_is_platform_admin()) {
1213
                    $attributes = [
1214
                        'title' => $title,
1215
                        'start_date' => $start,
1216
                        'end_date' => $end,
1217
                        'all_day' => $allDay,
1218
                    ];
1219
1220
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
1221
                        $attributes['career_id'] = $careerId;
1222
                        $attributes['promotion_id'] = $promotionId;
1223
                    }
1224
1225
                    if ($updateContent) {
1226
                        $attributes['content'] = $content;
1227
                    }
1228
                    Database::update(
1229
                        $this->tbl_global_agenda,
1230
                        $attributes,
1231
                        ['id = ?' => $id]
1232
                    );
1233
                }
1234
                break;
1235
        }
1236
1237
        $this->editReminders($id, $remindersList);
1238
1239
        return true;
1240
    }
1241
1242
    /**
1243
     * @param int  $id
1244
     * @param bool $deleteAllItemsFromSerie
1245
     *
1246
     * @throws \Doctrine\ORM\ORMException
1247
     * @throws \Doctrine\ORM\OptimisticLockException
1248
     */
1249
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
1250
    {
1251
        $em = Database::getManager();
1252
1253
        switch ($this->type) {
1254
            case 'personal':
1255
                $eventInfo = $this->get_event($id);
1256
                if ($eventInfo['user'] == api_get_user_id()) {
1257
                    Database::delete(
1258
                        $this->tbl_personal_agenda,
1259
                        ['id = ?' => $id]
1260
                    );
1261
                } elseif (api_get_configuration_value('agenda_collective_invitations')) {
1262
                    $currentUser = api_get_user_entity(api_get_user_id());
1263
1264
                    $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
1265
                    $event = $eventRepo->findOneByIdAndInvitee($id, $currentUser);
1266
                    $invitation = $event ? $event->getInvitation() : null;
1267
1268
                    if ($invitation) {
1269
                        $invitation->removeInviteeUser($currentUser);
1270
1271
                        $em->persist($invitation);
1272
                        $em->flush();
1273
                    }
1274
                }
1275
                break;
1276
            case 'course':
1277
                $courseId = api_get_course_int_id();
1278
                $isAllowToEdit = $this->getIsAllowedToEdit();
1279
1280
                if (!empty($courseId) && $isAllowToEdit) {
1281
                    $eventInfo = $this->get_event($id);
1282
                    if ($deleteAllItemsFromSerie) {
1283
                        /* This is one of the children.
1284
                           Getting siblings and delete 'Em all + the father! */
1285
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
1286
                            // Removing items.
1287
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
1288
                            if (!empty($events)) {
1289
                                foreach ($events as $event) {
1290
                                    $this->deleteEvent($event['id']);
1291
                                }
1292
                            }
1293
                            // Removing parent.
1294
                            $this->deleteEvent($eventInfo['parent_event_id']);
1295
                        } else {
1296
                            // This is the father looking for the children.
1297
                            $events = $this->getAllRepeatEvents($id);
1298
                            if (!empty($events)) {
1299
                                foreach ($events as $event) {
1300
                                    $this->deleteEvent($event['id']);
1301
                                }
1302
                            }
1303
                        }
1304
                    }
1305
1306
                    // Removing from events.
1307
                    Database::delete(
1308
                        $this->tbl_course_agenda,
1309
                        ['id = ? AND c_id = ?' => [$id, $courseId]]
1310
                    );
1311
1312
                    api_item_property_update(
1313
                        $this->course,
1314
                        TOOL_CALENDAR_EVENT,
1315
                        $id,
1316
                        'delete',
1317
                        api_get_user_id()
1318
                    );
1319
1320
                    // Removing from series.
1321
                    Database::delete(
1322
                        $this->table_repeat,
1323
                        [
1324
                            'cal_id = ? AND c_id = ?' => [
1325
                                $id,
1326
                                $courseId,
1327
                            ],
1328
                        ]
1329
                    );
1330
1331
                    if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
1332
                        foreach ($eventInfo['attachment'] as $attachment) {
1333
                            self::deleteAttachmentFile(
1334
                                $attachment['id'],
1335
                                $this->course
1336
                            );
1337
                        }
1338
                    }
1339
                }
1340
                break;
1341
            case 'admin':
1342
                if (api_is_platform_admin()) {
1343
                    Database::delete(
1344
                        $this->tbl_global_agenda,
1345
                        ['id = ?' => $id]
1346
                    );
1347
                }
1348
                break;
1349
        }
1350
    }
1351
1352
    public function subscribeCurrentUserToEvent(int $id)
1353
    {
1354
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1355
            return;
1356
        }
1357
1358
        if ('personal' !== $this->type) {
1359
            return;
1360
        }
1361
1362
        $em = Database::getManager();
1363
1364
        $currentUser = api_get_user_entity(api_get_user_id());
1365
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1366
1367
        /** @var AgendaEventSubscription $subscription */
1368
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1369
1370
        if (!$subscription) {
1371
            return;
1372
        }
1373
1374
        if ($subscription->getInvitees()->count() >= $subscription->getMaxAttendees()) {
1375
            return;
1376
        }
1377
1378
        $subscriber = (new AgendaEventSubscriber())
1379
            ->setUser($currentUser)
1380
        ;
1381
1382
        $subscription->addInvitee($subscriber);
1383
1384
        $em->flush();
1385
    }
1386
1387
    public function unsubscribeCurrentUserToEvent(int $id)
1388
    {
1389
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1390
            return;
1391
        }
1392
1393
        if ('personal' !== $this->type) {
1394
            return;
1395
        }
1396
1397
        $em = Database::getManager();
1398
1399
        $currentUser = api_get_user_entity(api_get_user_id());
1400
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1401
1402
        /** @var AgendaEventSubscription $subscription */
1403
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1404
1405
        if (!$subscription) {
1406
            return;
1407
        }
1408
1409
        $subscription->removeInviteeUser($currentUser);
1410
1411
        $em->flush();
1412
    }
1413
1414
    /**
1415
     * Get agenda events.
1416
     *
1417
     * @param int    $start
1418
     * @param int    $end
1419
     * @param int    $courseId
1420
     * @param int    $groupId
1421
     * @param int    $user_id
1422
     * @param string $format
1423
     *
1424
     * @return array|string
1425
     */
1426
    public function getEvents(
1427
        $start,
1428
        $end,
1429
        $courseId = null,
1430
        $groupId = null,
1431
        $user_id = 0,
1432
        $format = 'json'
1433
    ) {
1434
        switch ($this->type) {
1435
            case 'admin':
1436
                $this->getPlatformEvents($start, $end);
1437
                break;
1438
            case 'course':
1439
                $courseInfo = api_get_course_info_by_id($courseId);
1440
1441
                // Session coach can see all events inside a session.
1442
                if (api_is_coach()) {
1443
                    // Own course
1444
                    $this->getCourseEvents(
1445
                        $start,
1446
                        $end,
1447
                        $courseInfo,
1448
                        $groupId,
1449
                        $this->sessionId,
1450
                        $user_id
1451
                    );
1452
1453
                    // Others
1454
                    $this->getSessionEvents(
1455
                        $start,
1456
                        $end,
1457
                        $this->sessionId,
1458
                        $user_id,
1459
                        $this->eventOtherSessionColor
1460
                    );
1461
                } else {
1462
                    $this->getCourseEvents(
1463
                        $start,
1464
                        $end,
1465
                        $courseInfo,
1466
                        $groupId,
1467
                        $this->sessionId,
1468
                        $user_id
1469
                    );
1470
                }
1471
                break;
1472
            case 'personal':
1473
            default:
1474
                $sessionFilterActive = false;
1475
                if (!empty($this->sessionId)) {
1476
                    $sessionFilterActive = true;
1477
                }
1478
1479
                if ($sessionFilterActive == false) {
1480
                    // Getting personal events
1481
                    $this->getPersonalEvents($start, $end);
1482
1483
                    // Getting platform/admin events
1484
                    $this->getPlatformEvents($start, $end);
1485
                }
1486
1487
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1488
1489
                $session_list = [];
1490
                // Getting course events
1491
                $my_course_list = [];
1492
                if (!api_is_anonymous()) {
1493
                    $session_list = SessionManager::get_sessions_by_user(
1494
                        api_get_user_id(),
1495
                        $ignoreVisibility
1496
                    );
1497
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1498
                        api_get_user_id(),
1499
                        false
1500
                    );
1501
                }
1502
1503
                if (api_is_drh()) {
1504
                    if (api_drh_can_access_all_session_content()) {
1505
                        $session_list = [];
1506
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1507
                            api_get_user_id(),
1508
                            null,
1509
                            null,
1510
                            null,
1511
                            true,
1512
                            false
1513
                        );
1514
1515
                        if (!empty($sessionList)) {
1516
                            foreach ($sessionList as $sessionItem) {
1517
                                $sessionId = $sessionItem['id'];
1518
                                $courses = SessionManager::get_course_list_by_session_id($sessionId);
1519
                                $sessionInfo = [
1520
                                    'session_id' => $sessionId,
1521
                                    'courses' => $courses,
1522
                                ];
1523
                                $session_list[] = $sessionInfo;
1524
                            }
1525
                        }
1526
                    }
1527
                }
1528
1529
                if (!empty($session_list)) {
1530
                    foreach ($session_list as $session_item) {
1531
                        if ($sessionFilterActive) {
1532
                            if ($this->sessionId != $session_item['session_id']) {
1533
                                continue;
1534
                            }
1535
                        }
1536
1537
                        $my_courses = $session_item['courses'];
1538
                        $my_session_id = $session_item['session_id'];
1539
1540
                        if (!empty($my_courses)) {
1541
                            foreach ($my_courses as $course_item) {
1542
                                $courseInfo = api_get_course_info_by_id(
1543
                                    $course_item['real_id']
1544
                                );
1545
                                $this->getCourseEvents(
1546
                                    $start,
1547
                                    $end,
1548
                                    $courseInfo,
1549
                                    0,
1550
                                    $my_session_id
1551
                                );
1552
                            }
1553
                        }
1554
                    }
1555
                }
1556
1557
                if (!empty($my_course_list) && $sessionFilterActive == false) {
1558
                    foreach ($my_course_list as $courseInfoItem) {
1559
                        $courseInfo = api_get_course_info_by_id(
1560
                            $courseInfoItem['real_id']
1561
                        );
1562
                        if (isset($courseId) && !empty($courseId)) {
1563
                            if ($courseInfo['real_id'] == $courseId) {
1564
                                $this->getCourseEvents(
1565
                                    $start,
1566
                                    $end,
1567
                                    $courseInfo,
1568
                                    0,
1569
                                    0,
1570
                                    $user_id
1571
                                );
1572
                            }
1573
                        } else {
1574
                            $this->getCourseEvents(
1575
                                $start,
1576
                                $end,
1577
                                $courseInfo,
1578
                                0,
1579
                                0,
1580
                                $user_id
1581
                            );
1582
                        }
1583
                    }
1584
                }
1585
1586
                if ($start && $end) {
1587
                    $this->loadSessionsAsEvents($start, $end);
1588
                }
1589
1590
                break;
1591
        }
1592
1593
        if (api_get_configuration_value('agenda_reminders')) {
1594
            $this->events = array_map(
1595
                function (array $eventInfo) {
1596
                    $id = str_replace(['personal_', 'course_', 'session_'], '', $eventInfo['id']);
1597
1598
                    $eventInfo['reminders'] = $this->parseEventReminders(
1599
                        $this->getEventReminders(
1600
                            $id,
1601
                            'session' === $eventInfo['type'] ? 'course' : $eventInfo['type']
1602
                        )
1603
                    );
1604
1605
                    return $eventInfo;
1606
                },
1607
                $this->events
1608
            );
1609
        }
1610
1611
        $this->cleanEvents();
1612
1613
        switch ($format) {
1614
            case 'json':
1615
                if (empty($this->events)) {
1616
                    return '[]';
1617
                }
1618
1619
                return json_encode($this->events);
1620
                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...
1621
            case 'array':
1622
                if (empty($this->events)) {
1623
                    return [];
1624
                }
1625
1626
                return $this->events;
1627
                break;
1628
        }
1629
    }
1630
1631
    /**
1632
     * Clean events.
1633
     *
1634
     * @return bool
1635
     */
1636
    public function cleanEvents()
1637
    {
1638
        if (empty($this->events)) {
1639
            return false;
1640
        }
1641
1642
        foreach ($this->events as &$event) {
1643
            $event['description'] = Security::remove_XSS($event['description']);
1644
            $event['title'] = Security::remove_XSS($event['title']);
1645
        }
1646
1647
        return true;
1648
    }
1649
1650
    /**
1651
     * @param int $id
1652
     * @param int $minute_delta
1653
     *
1654
     * @return int
1655
     */
1656
    public function resizeEvent($id, $minute_delta)
1657
    {
1658
        $id = (int) $id;
1659
        $delta = (int) $minute_delta;
1660
        $event = $this->get_event($id);
1661
        if (!empty($event)) {
1662
            switch ($this->type) {
1663
                case 'personal':
1664
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1665
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1666
							WHERE id = ".$id;
1667
                    Database::query($sql);
1668
                    break;
1669
                case 'course':
1670
                    $sql = "UPDATE $this->tbl_course_agenda SET
1671
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1672
							WHERE
1673
							    c_id = ".$this->course['real_id']." AND
1674
							    id = ".$id;
1675
                    Database::query($sql);
1676
                    break;
1677
                case 'admin':
1678
                    $sql = "UPDATE $this->tbl_global_agenda SET
1679
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1680
							WHERE id = ".$id;
1681
                    Database::query($sql);
1682
                    break;
1683
            }
1684
        }
1685
1686
        return 1;
1687
    }
1688
1689
    /**
1690
     * @param int $id
1691
     * @param int $minute_delta minutes
1692
     * @param int $allDay
1693
     *
1694
     * @return int
1695
     */
1696
    public function move_event($id, $minute_delta, $allDay)
1697
    {
1698
        $id = (int) $id;
1699
        $event = $this->get_event($id);
1700
1701
        if (empty($event)) {
1702
            return false;
1703
        }
1704
1705
        // we convert the hour delta into minutes and add the minute delta
1706
        $delta = (int) $minute_delta;
1707
        $allDay = (int) $allDay;
1708
1709
        if (!empty($event)) {
1710
            switch ($this->type) {
1711
                case 'personal':
1712
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1713
                            all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE),
1714
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1715
							WHERE id=".$id;
1716
                    Database::query($sql);
1717
                    break;
1718
                case 'course':
1719
                    $sql = "UPDATE $this->tbl_course_agenda SET
1720
                            all_day = $allDay,
1721
                            start_date = DATE_ADD(start_date, INTERVAL $delta MINUTE),
1722
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1723
							WHERE
1724
							    c_id = ".$this->course['real_id']." AND
1725
							    id=".$id;
1726
                    Database::query($sql);
1727
                    break;
1728
                case 'admin':
1729
                    $sql = "UPDATE $this->tbl_global_agenda SET
1730
                            all_day = $allDay,
1731
                            start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
1732
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1733
							WHERE id=".$id;
1734
                    Database::query($sql);
1735
                    break;
1736
            }
1737
        }
1738
1739
        return 1;
1740
    }
1741
1742
    /**
1743
     * Gets a single event.
1744
     *
1745
     * @param int $id event id
1746
     *
1747
     * @return array
1748
     */
1749
    public function get_event($id)
1750
    {
1751
        // make sure events of the personal agenda can only be seen by the user himself
1752
        $id = (int) $id;
1753
        $event = null;
1754
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
1755
1756
        switch ($this->type) {
1757
            case 'personal':
1758
                $user = api_get_user_entity(api_get_user_id());
1759
                $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1760
                        WHERE id = $id AND user = ".$user->getId();
1761
                $result = Database::query($sql);
1762
                if (Database::num_rows($result)) {
1763
                    $event = Database::fetch_array($result, 'ASSOC');
1764
                    $event['description'] = $event['text'];
1765
                    $event['content'] = $event['text'];
1766
                    $event['start_date'] = $event['date'];
1767
                    $event['end_date'] = $event['enddate'];
1768
                }
1769
1770
                if (null !== $event) {
1771
                    return $event;
1772
                }
1773
1774
                if ($agendaCollectiveInvitations) {
1775
                    $eventRepo = Database::getManager()->getRepository('ChamiloCoreBundle:PersonalAgenda');
1776
                    $event = $eventRepo->findOneByIdAndInvitee($id, $user);
1777
1778
                    if ($event && $event->isCollective()) {
1779
                        return [
1780
                            'id' => $event->getId(),
1781
                            'user' => $event->getUser(),
1782
                            'title' => $event->getTitle(),
1783
                            'text' => $event->getText(),
1784
                            'date' => $event->getDate()->format('Y-m-d H:i:s'),
1785
                            'enddate' => $event->getEndDate()->format('Y-m-d H:i:s'),
1786
                            'course' => null,
1787
                            'parent_event_id' => $event->getParentEventId(),
1788
                            'all_day' => $event->getAllDay(),
1789
                            'color' => $event->getColor(),
1790
                            'agenda_event_invitation_id' => $event->getInvitation()->getId(),
1791
                            'collective' => $event->isCollective(),
1792
                            'description' => $event->getText(),
1793
                            'content' => $event->getText(),
1794
                            'start_date' => $event->getDate()->format('Y-m-d H:i:s'),
1795
                            'end_date' => $event->getEndDate()->format('Y-m-d H:i:s'),
1796
                        ];
1797
                    }
1798
                }
1799
1800
                return null;
1801
            case 'course':
1802
                if (!empty($this->course['real_id'])) {
1803
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
1804
                            WHERE c_id = ".$this->course['real_id']." AND id = ".$id;
1805
                    $result = Database::query($sql);
1806
                    if (Database::num_rows($result)) {
1807
                        $event = Database::fetch_array($result, 'ASSOC');
1808
                        $event['description'] = $event['content'];
1809
1810
                        // Getting send to array
1811
                        $event['send_to'] = $this->getUsersAndGroupSubscribedToEvent(
1812
                            $id,
1813
                            $this->course['real_id'],
1814
                            $this->sessionId
1815
                        );
1816
1817
                        // Getting repeat info
1818
                        $event['repeat_info'] = $this->getRepeatedInfoByEvent(
1819
                            $id,
1820
                            $this->course['real_id']
1821
                        );
1822
1823
                        if (!empty($event['parent_event_id'])) {
1824
                            $event['parent_info'] = $this->get_event($event['parent_event_id']);
1825
                        }
1826
1827
                        $event['attachment'] = $this->getAttachmentList(
1828
                            $id,
1829
                            $this->course
1830
                        );
1831
                    }
1832
                }
1833
                break;
1834
            case 'admin':
1835
            case 'platform':
1836
                $sql = "SELECT * FROM ".$this->tbl_global_agenda."
1837
                        WHERE id = $id";
1838
                $result = Database::query($sql);
1839
                if (Database::num_rows($result)) {
1840
                    $event = Database::fetch_array($result, 'ASSOC');
1841
                    $event['description'] = $event['content'];
1842
                }
1843
                break;
1844
        }
1845
1846
        return $event;
1847
    }
1848
1849
    /**
1850
     * Gets personal events.
1851
     *
1852
     * @param int $start
1853
     * @param int $end
1854
     *
1855
     * @return array
1856
     */
1857
    public function getPersonalEvents($start, $end)
1858
    {
1859
        $start = (int) $start;
1860
        $end = (int) $end;
1861
        $startDate = null;
1862
        $endDate = null;
1863
        $startCondition = '';
1864
        $endCondition = '';
1865
1866
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
1867
        $agendaEventSubscriptions = api_get_configuration_value('agenda_event_subscriptions');
1868
        $userIsAdmin = api_is_platform_admin();
1869
1870
        $queryParams = [];
1871
1872
        if ($start !== 0) {
1873
            $queryParams['start_date'] = api_get_utc_datetime($start, true, true);
1874
            $startCondition = "AND pa.date >= :start_date";
1875
        }
1876
        if ($end !== 0) {
1877
            $queryParams['end_date'] = api_get_utc_datetime($end, false, true);
1878
            $endCondition = "AND (pa.enddate <= :end_date OR pa.enddate IS NULL)";
1879
        }
1880
        $user_id = api_get_user_id();
1881
1882
        $queryParams['user_id'] = $user_id;
1883
        $userCondition = "pa.user = :user_id";
1884
1885
        if ($agendaEventSubscriptions) {
1886
            $objGroup = new UserGroup();
1887
            $groupList = $objGroup->get_groups_by_user($user_id);
1888
1889
            $userCondition = "(
1890
                    $userCondition
1891
                    OR (
1892
                        pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_ALL;
1893
1894
            if ($groupList) {
1895
                $userCondition .= "
1896
                        OR (
1897
                            pa.subscriptionVisibility = ".AgendaEventSubscription::SUBSCRIPTION_CLASS."
1898
                            AND pa.subscriptionItemId IN (".implode(', ', array_keys($groupList)).")
1899
                        ) 
1900
                ";
1901
            }
1902
1903
            $userCondition .= "
1904
                    )
1905
                )
1906
            ";
1907
        }
1908
1909
        $sql = "SELECT pa FROM ChamiloCoreBundle:PersonalAgenda AS pa WHERE $userCondition $startCondition $endCondition";
1910
1911
        $result = Database::getManager()
1912
            ->createQuery($sql)
1913
            ->setParameters($queryParams)
1914
            ->getResult();
1915
1916
        $my_events = [];
1917
1918
        /** @var PersonalAgenda $row */
1919
        foreach ($result as $row) {
1920
            $event = [];
1921
            $event['id'] = 'personal_'.$row->getId();
1922
            $event['title'] = $row->getTitle();
1923
            $event['className'] = 'personal';
1924
            $event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
1925
            $event['editable'] = $user_id === (int) $row->getUser();
1926
            $event['sent_to'] = get_lang('Me');
1927
            $event['type'] = 'personal';
1928
1929
            if (!empty($row->getDate())) {
1930
                $event['start'] = $this->formatEventDate($row->getDate());
1931
                $event['start_date_localtime'] = api_get_local_time($row->getDate());
1932
            }
1933
1934
            if (!empty($row->getEnddate())) {
1935
                $event['end'] = $this->formatEventDate($row->getEnddate());
1936
                $event['end_date_localtime'] = api_get_local_time($row->getEnddate());
1937
            }
1938
1939
            $event['description'] = $row->getText();
1940
            $event['allDay'] = $row->getAllDay();
1941
            $event['parent_event_id'] = 0;
1942
            $event['has_children'] = 0;
1943
1944
            if ($agendaCollectiveInvitations) {
1945
                $event['collective'] = $row->isCollective();
1946
                $event['invitees'] = self::getInviteesForPersonalEvent($row->getId());
1947
            }
1948
1949
            if ($agendaEventSubscriptions) {
1950
                /** @var AgendaEventSubscription $subscription */
1951
                $subscription = $row->getInvitation();
1952
                $subscribers = $subscription->getInvitees();
1953
1954
                $event['subscription_visibility'] = $row->getSubscriptionVisibility();
1955
                $event['max_subscriptions'] = $subscription->getMaxAttendees();
1956
                $event['can_subscribe'] = $subscribers->count() < $subscription->getMaxAttendees();
1957
                $event['user_is_subscribed'] = $subscription->hasUserAsInvitee(api_get_user_entity($user_id));
1958
                $event['count_subscribers'] = $subscribers->count();
1959
1960
                if ($userIsAdmin) {
1961
                    $event['subscribers'] = self::getInviteesForPersonalEvent($row->getId(), AgendaEventSubscriber::class);
1962
                }
1963
            }
1964
1965
            $my_events[] = $event;
1966
            $this->events[] = $event;
1967
        }
1968
1969
        if ($agendaCollectiveInvitations) {
1970
            $this->loadEventsAsInvitee(
1971
                api_get_user_entity($user_id),
1972
                $startDate,
1973
                $endDate
1974
            );
1975
        }
1976
1977
        // Add plugin personal events
1978
1979
        $this->plugin = new AppPlugin();
1980
        $plugins = $this->plugin->getInstalledPluginListObject();
1981
        /** @var Plugin $plugin */
1982
        foreach ($plugins as $plugin) {
1983
            if ($plugin->hasPersonalEvents && method_exists($plugin, 'getPersonalEvents')) {
1984
                $pluginEvents = $plugin->getPersonalEvents($this, $start, $end);
1985
1986
                if (!empty($pluginEvents)) {
1987
                    $this->events = array_merge($this->events, $pluginEvents);
1988
                }
1989
            }
1990
        }
1991
1992
        return $my_events;
1993
    }
1994
1995
    public static function getInviteesForPersonalEvent($eventId, $type = AgendaEventInvitee::class): array
1996
    {
1997
        $em = Database::getManager();
1998
        $event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
1999
2000
        $invitation = $event->getInvitation();
2001
2002
        if ($invitation instanceof AgendaEventSubscription
2003
            && AgendaEventInvitee::class === $type
2004
        ) {
2005
            return [];
2006
        }
2007
2008
        $inviteeRepo = $em->getRepository($type);
2009
        $invitees = $inviteeRepo->findByInvitation($invitation);
2010
2011
        $inviteeList = [];
2012
2013
        foreach ($invitees as $invitee) {
2014
            $inviteeUser = $invitee->getUser();
2015
2016
            $inviteeList[] = [
2017
                'id' => $inviteeUser->getId(),
2018
                'name' => $inviteeUser->getCompleteNameWithUsername(),
2019
            ];
2020
        }
2021
2022
        return $inviteeList;
2023
    }
2024
2025
    /**
2026
     * Get user/group list per event.
2027
     *
2028
     * @param int $eventId
2029
     * @param int $courseId
2030
     * @param int $sessionId
2031
     * @paraù int $sessionId
2032
     *
2033
     * @return array
2034
     */
2035
    public function getUsersAndGroupSubscribedToEvent(
2036
        $eventId,
2037
        $courseId,
2038
        $sessionId
2039
    ) {
2040
        $eventId = (int) $eventId;
2041
        $courseId = (int) $courseId;
2042
        $sessionId = (int) $sessionId;
2043
2044
        $sessionCondition = "ip.session_id = $sessionId";
2045
        if (empty($sessionId)) {
2046
            $sessionCondition = " (ip.session_id = 0 OR ip.session_id IS NULL) ";
2047
        }
2048
2049
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
2050
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2051
2052
        // Get sent_tos
2053
        $sql = "SELECT DISTINCT to_user_id, to_group_id
2054
                FROM $tbl_property ip
2055
                INNER JOIN $tlb_course_agenda agenda
2056
                ON (
2057
                  ip.ref = agenda.id AND
2058
                  ip.c_id = agenda.c_id AND
2059
                  ip.tool = '".TOOL_CALENDAR_EVENT."'
2060
                )
2061
                WHERE
2062
                    ref = $eventId AND
2063
                    ip.visibility = '1' AND
2064
                    ip.c_id = $courseId AND
2065
                    $sessionCondition
2066
                ";
2067
2068
        $result = Database::query($sql);
2069
        $users = [];
2070
        $groups = [];
2071
        $everyone = false;
2072
2073
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2074
            if (!empty($row['to_group_id'])) {
2075
                $groups[] = $row['to_group_id'];
2076
            }
2077
            if (!empty($row['to_user_id'])) {
2078
                $users[] = $row['to_user_id'];
2079
            }
2080
2081
            if (empty($groups) && empty($users)) {
2082
                if ($row['to_group_id'] == 0) {
2083
                    $everyone = true;
2084
                }
2085
            }
2086
        }
2087
2088
        return [
2089
            'everyone' => $everyone,
2090
            'users' => $users,
2091
            'groups' => $groups,
2092
        ];
2093
    }
2094
2095
    /**
2096
     * @param int    $start
2097
     * @param int    $end
2098
     * @param int    $sessionId
2099
     * @param int    $userId
2100
     * @param string $color
2101
     *
2102
     * @return array
2103
     */
2104
    public function getSessionEvents(
2105
        $start,
2106
        $end,
2107
        $sessionId = 0,
2108
        $userId = 0,
2109
        $color = ''
2110
    ) {
2111
        $courses = SessionManager::get_course_list_by_session_id($sessionId);
2112
2113
        if (!empty($courses)) {
2114
            foreach ($courses as $course) {
2115
                $this->getCourseEvents(
2116
                    $start,
2117
                    $end,
2118
                    $course,
2119
                    0,
2120
                    $sessionId,
2121
                    0,
2122
                    $color
2123
                );
2124
            }
2125
        }
2126
    }
2127
2128
    /**
2129
     * @param int    $start
2130
     * @param int    $end
2131
     * @param array  $courseInfo
2132
     * @param int    $groupId
2133
     * @param int    $sessionId
2134
     * @param int    $user_id
2135
     * @param string $color
2136
     *
2137
     * @return array
2138
     */
2139
    public function getCourseEvents(
2140
        $start,
2141
        $end,
2142
        $courseInfo,
2143
        $groupId = 0,
2144
        $sessionId = 0,
2145
        $user_id = 0,
2146
        $color = ''
2147
    ) {
2148
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
2149
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
2150
2151
        if (empty($courseInfo)) {
2152
            return [];
2153
        }
2154
        $courseId = $courseInfo['real_id'];
2155
2156
        if (empty($courseId)) {
2157
            return [];
2158
        }
2159
2160
        $sessionId = (int) $sessionId;
2161
        $user_id = (int) $user_id;
2162
2163
        $groupList = GroupManager::get_group_list(
2164
            null,
2165
            $courseInfo,
2166
            null,
2167
            $sessionId
2168
        );
2169
2170
        $groupNameList = [];
2171
        if (!empty($groupList)) {
2172
            foreach ($groupList as $group) {
2173
                $groupNameList[$group['iid']] = $group['name'];
2174
            }
2175
        }
2176
2177
        if (api_is_platform_admin() || api_is_allowed_to_edit()) {
2178
            $isAllowToEdit = true;
2179
        } else {
2180
            $isAllowToEdit = CourseManager::is_course_teacher(
2181
                api_get_user_id(),
2182
                $courseInfo['code']
2183
            );
2184
        }
2185
2186
        $isAllowToEditByHrm = false;
2187
        if (!empty($sessionId)) {
2188
            $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
2189
            if ($allowDhrToEdit) {
2190
                $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
2191
                if ($isHrm) {
2192
                    $isAllowToEdit = $isAllowToEditByHrm = true;
2193
                }
2194
            }
2195
        }
2196
2197
        $groupMemberships = [];
2198
        if (!empty($groupId)) {
2199
            $groupMemberships = [$groupId];
2200
        } else {
2201
            if ($isAllowToEdit) {
2202
                if (!empty($groupList)) {
2203
                    // c_item_property.to_group_id field was migrated to use
2204
                    // c_group_info.iid
2205
                    $groupMemberships = array_column($groupList, 'iid');
2206
                }
2207
            } else {
2208
                // get only related groups from user
2209
                $groupMemberships = GroupManager::get_group_ids(
2210
                    $courseId,
2211
                    api_get_user_id()
2212
                );
2213
            }
2214
        }
2215
2216
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
2217
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2218
2219
        $shareEventsInSessions = 1 == api_get_course_setting('agenda_share_events_in_sessions', $courseInfo);
2220
2221
        $agendaSessionCondition = str_replace(
2222
            ' AND ',
2223
            '',
2224
            api_get_session_condition($sessionId, true, $shareEventsInSessions, 'agenda.session_id')
2225
        );
2226
        $ipSessionCondition = api_get_session_condition($sessionId, true, $shareEventsInSessions, 'ip.session_id');
2227
2228
        $sessionCondition = "($agendaSessionCondition $ipSessionCondition)";
2229
2230
        if ($isAllowToEdit) {
2231
            // No group filter was asked
2232
            if (empty($groupId)) {
2233
                if (empty($user_id)) {
2234
                    // Show all events not added in group
2235
                    $userCondition = ' (ip.to_group_id IS NULL OR ip.to_group_id = 0) ';
2236
                    // admin see only his stuff
2237
                    if ($this->type === 'personal') {
2238
                        $userCondition = " (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ) ";
2239
                        $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) ) ";
2240
                    }
2241
2242
                    if (!empty($groupMemberships)) {
2243
                        // Show events sent to selected groups
2244
                        $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2245
                    }
2246
                } else {
2247
                    // Show events of requested user in no group
2248
                    $userCondition = " (ip.to_user_id = $user_id AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
2249
                    // Show events sent to selected groups
2250
                    if (!empty($groupMemberships)) {
2251
                        $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2252
                    }
2253
                }
2254
            } else {
2255
                // Show only selected groups (depending of user status)
2256
                $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2257
2258
                if (!empty($groupMemberships)) {
2259
                    // Show send to $user_id in selected groups
2260
                    $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2261
                }
2262
            }
2263
        } else {
2264
            // No group filter was asked
2265
            if (empty($groupId)) {
2266
                // Show events sent to everyone and no group
2267
                $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) ';
2268
2269
                // Show events sent to selected groups
2270
                if (!empty($groupMemberships)) {
2271
                    $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships)."))) ";
2272
                } else {
2273
                    $userCondition .= " ) ";
2274
                }
2275
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
2276
            } else {
2277
                if (!empty($groupMemberships)) {
2278
                    // Show send to everyone - and only selected groups
2279
                    $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2280
                }
2281
            }
2282
2283
            // Show sent to only me and no group
2284
            if (!empty($groupMemberships)) {
2285
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id().") AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
2286
            } else {
2287
                // Show sent to only me and selected groups
2288
            }
2289
        }
2290
2291
        if (api_is_allowed_to_edit()) {
2292
            $visibilityCondition = " (ip.visibility IN ('1', '0'))  ";
2293
        } else {
2294
            $visibilityCondition = " (ip.visibility = '1') ";
2295
        }
2296
2297
        $sql = "SELECT DISTINCT
2298
                    agenda.*,
2299
                    ip.visibility,
2300
                    ip.to_group_id,
2301
                    ip.insert_user_id,
2302
                    ip.ref,
2303
                    to_user_id
2304
                FROM $tlb_course_agenda agenda
2305
                INNER JOIN $tbl_property ip
2306
                ON (
2307
                    agenda.id = ip.ref AND
2308
                    agenda.c_id = ip.c_id AND
2309
                    ip.tool = '".TOOL_CALENDAR_EVENT."'
2310
                )
2311
                WHERE
2312
                    $sessionCondition AND
2313
                    ($userCondition) AND
2314
                    $visibilityCondition AND
2315
                    agenda.c_id = $courseId
2316
        ";
2317
        $dateCondition = '';
2318
        if (!empty($start) && !empty($end)) {
2319
            $dateCondition .= "AND (
2320
                 agenda.start_date BETWEEN '".$start."' AND '".$end."' OR
2321
                 agenda.end_date BETWEEN '".$start."' AND '".$end."' OR
2322
                 (
2323
                     agenda.start_date IS NOT NULL AND agenda.end_date IS NOT NULL AND
2324
                     YEAR(agenda.start_date) = YEAR(agenda.end_date) AND
2325
                     MONTH('$start') BETWEEN MONTH(agenda.start_date) AND MONTH(agenda.end_date)
2326
                 )
2327
            )";
2328
        }
2329
2330
        $sql .= $dateCondition;
2331
        $result = Database::query($sql);
2332
2333
        $coachCanEdit = false;
2334
        if (!empty($sessionId)) {
2335
            $coachCanEdit = api_is_coach($sessionId, $courseId) || api_is_platform_admin();
2336
        }
2337
2338
        if (Database::num_rows($result)) {
2339
            $eventsAdded = array_column($this->events, 'unique_id');
2340
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2341
                $event = [];
2342
                $event['id'] = 'course_'.$row['id'];
2343
                $event['unique_id'] = $row['iid'];
2344
                // To avoid doubles
2345
                if (in_array($event['unique_id'], $eventsAdded)) {
2346
                    continue;
2347
                }
2348
2349
                $eventsAdded[] = $event['unique_id'];
2350
                $eventId = $row['ref'];
2351
                $items = $this->getUsersAndGroupSubscribedToEvent(
2352
                    $eventId,
2353
                    $courseId,
2354
                    $this->sessionId
2355
                );
2356
                $group_to_array = $items['groups'];
2357
                $user_to_array = $items['users'];
2358
                $attachmentList = $this->getAttachmentList(
2359
                    $row['id'],
2360
                    $courseInfo
2361
                );
2362
                $event['attachment'] = '';
2363
                if (!empty($attachmentList)) {
2364
                    foreach ($attachmentList as $attachment) {
2365
                        $has_attachment = Display::return_icon(
2366
                            'attachment.gif',
2367
                            get_lang('Attachment')
2368
                        );
2369
                        $user_filename = $attachment['filename'];
2370
                        $url = api_get_path(WEB_CODE_PATH).'calendar/download.php?file='.$attachment['path'].'&course_id='.$courseId.'&'.api_get_cidreq();
2371
                        $event['attachment'] .= $has_attachment.
2372
                            Display::url(
2373
                                $user_filename,
2374
                                $url
2375
                            ).'<br />';
2376
                    }
2377
                }
2378
2379
                $event['title'] = $row['title'];
2380
                $event['className'] = 'course';
2381
                $event['allDay'] = 'false';
2382
                $event['course_id'] = $courseId;
2383
                $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color;
2384
2385
                $sessionInfo = [];
2386
                if (isset($row['session_id']) && !empty($row['session_id'])) {
2387
                    $sessionInfo = api_get_session_info($sessionId);
2388
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_session_color;
2389
                }
2390
2391
                $event['session_name'] = isset($sessionInfo['name']) ? $sessionInfo['name'] : '';
2392
                $event['course_name'] = isset($courseInfo['title']) ? $courseInfo['title'] : '';
2393
2394
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
2395
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_group_color;
2396
                }
2397
2398
                if (!empty($color)) {
2399
                    $event['borderColor'] = $event['backgroundColor'] = $color;
2400
                }
2401
2402
                if (isset($row['color']) && !empty($row['color'])) {
2403
                    $event['borderColor'] = $event['backgroundColor'] = $row['color'];
2404
                }
2405
2406
                $event['editable'] = false;
2407
                if ($this->getIsAllowedToEdit() && $this->type == 'course') {
2408
                    $event['editable'] = true;
2409
                    if (!empty($sessionId)) {
2410
                        if ($coachCanEdit == false) {
2411
                            $event['editable'] = false;
2412
                        }
2413
                        if ($isAllowToEditByHrm) {
2414
                            $event['editable'] = true;
2415
                        }
2416
                        if ($sessionId != $row['session_id']) {
2417
                            $event['editable'] = false;
2418
                        }
2419
                    }
2420
                    // if user is author then he can edit the item
2421
                    if (api_get_user_id() == $row['insert_user_id']) {
2422
                        $event['editable'] = true;
2423
                    }
2424
                }
2425
2426
                if (!empty($row['start_date'])) {
2427
                    $event['start'] = $this->formatEventDate($row['start_date']);
2428
                    $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2429
                }
2430
                if (!empty($row['end_date'])) {
2431
                    $event['end'] = $this->formatEventDate($row['end_date']);
2432
                    $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2433
                }
2434
2435
                $event['sent_to'] = '';
2436
                $event['type'] = 'course';
2437
                if ($row['session_id'] != 0) {
2438
                    $event['type'] = 'session';
2439
                }
2440
2441
                // Event Sent to a group?
2442
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
2443
                    $sent_to = [];
2444
                    if (!empty($group_to_array)) {
2445
                        foreach ($group_to_array as $group_item) {
2446
                            $sent_to[] = $groupNameList[$group_item];
2447
                        }
2448
                    }
2449
                    $sent_to = implode('@@', $sent_to);
2450
                    $sent_to = str_replace(
2451
                        '@@',
2452
                        '</div><div class="label_tag notice">',
2453
                        $sent_to
2454
                    );
2455
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2456
                    $event['type'] = 'group';
2457
                }
2458
2459
                // Event sent to a user?
2460
                if (isset($row['to_user_id'])) {
2461
                    $sent_to = [];
2462
                    if (!empty($user_to_array)) {
2463
                        foreach ($user_to_array as $item) {
2464
                            $user_info = api_get_user_info($item);
2465
                            // Add username as tooltip for $event['sent_to'] - ref #4226
2466
                            $username = api_htmlentities(
2467
                                sprintf(
2468
                                    get_lang('LoginX'),
2469
                                    $user_info['username']
2470
                                ),
2471
                                ENT_QUOTES
2472
                            );
2473
                            $sent_to[] = "<span title='".$username."'>".$user_info['complete_name']."</span>";
2474
                        }
2475
                    }
2476
                    $sent_to = implode('@@', $sent_to);
2477
                    $sent_to = str_replace(
2478
                        '@@',
2479
                        '</div><div class="label_tag notice">',
2480
                        $sent_to
2481
                    );
2482
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2483
                }
2484
2485
                //Event sent to everyone!
2486
                if (empty($event['sent_to'])) {
2487
                    $event['sent_to'] = '<div class="label_tag notice">'.get_lang('Everyone').'</div>';
2488
                }
2489
2490
                $event['description'] = Security::remove_XSS($row['content']);
2491
                $event['visibility'] = $row['visibility'];
2492
                $event['real_id'] = $row['id'];
2493
                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2494
                $event['parent_event_id'] = $row['parent_event_id'];
2495
                $event['has_children'] = $this->hasChildren($row['id'], $courseId) ? 1 : 0;
2496
                $event['comment'] = Security::remove_XSS($row['comment']);
2497
                $this->events[] = $event;
2498
            }
2499
        }
2500
2501
        return $this->events;
2502
    }
2503
2504
    /**
2505
     * @param int $start tms
2506
     * @param int $end   tms
2507
     *
2508
     * @return array
2509
     */
2510
    public function getPlatformEvents($start, $end)
2511
    {
2512
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
2513
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
2514
        $dateCondition = '';
2515
2516
        if (!empty($start) && !empty($end)) {
2517
            $dateCondition .= "AND (
2518
                 start_date BETWEEN '".$start."' AND '".$end."' OR
2519
                 end_date BETWEEN '".$start."' AND '".$end."' OR
2520
                 (
2521
                     start_date IS NOT NULL AND end_date IS NOT NULL AND
2522
                     YEAR(start_date) = YEAR(end_date) AND
2523
                     MONTH('$start') BETWEEN MONTH(start_date) AND MONTH(end_date)
2524
                 )
2525
            )";
2526
        }
2527
2528
        $access_url_id = api_get_current_access_url_id();
2529
2530
        $sql = "SELECT *
2531
                FROM ".$this->tbl_global_agenda."
2532
                WHERE access_url_id = $access_url_id
2533
                $dateCondition";
2534
        $result = Database::query($sql);
2535
2536
        if (!Database::num_rows($result)) {
2537
            return [];
2538
        }
2539
2540
        $my_events = [];
2541
        $allowCareersInGlobalAgenda = api_get_configuration_value('allow_careers_in_global_agenda');
2542
        $userId = api_get_user_id();
2543
        $userVisibility = SystemAnnouncementManager::getCurrentUserVisibility();
2544
2545
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2546
            $event = [];
2547
            $event['id'] = 'platform_'.$row['id'];
2548
            $event['title'] = $row['title'];
2549
            $event['className'] = 'platform';
2550
            $event['allDay'] = 'false';
2551
            $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color;
2552
            $event['editable'] = false;
2553
            $event['type'] = 'admin';
2554
2555
            if (api_is_platform_admin() && $this->type === 'admin') {
2556
                $event['editable'] = true;
2557
            }
2558
2559
            if (!empty($row['start_date'])) {
2560
                $event['start'] = $this->formatEventDate($row['start_date']);
2561
                $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2562
            }
2563
2564
            if (!empty($row['end_date'])) {
2565
                $event['end'] = $this->formatEventDate($row['end_date']);
2566
                $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2567
            }
2568
            $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2569
            $event['parent_event_id'] = 0;
2570
            $event['has_children'] = 0;
2571
            $event['description'] = $row['content'];
2572
2573
            if ($allowCareersInGlobalAgenda) {
2574
                $event['career'] = null;
2575
                $event['promotion'] = null;
2576
2577
                $careerId = (int) $row['career_id'];
2578
                $promotionId = (int) $row['promotion_id'];
2579
2580
                $careerPromotionEventIsVisibleForUser = true;
2581
2582
                if (($careerId || $promotionId) && 'admin' !== $this->type) {
2583
                    $careerPromotionEventIsVisibleForUser = SystemAnnouncementManager::isVisibleAnnouncementForUser(
2584
                        $userId,
2585
                        $userVisibility,
2586
                        $careerId,
2587
                        $promotionId
2588
                    );
2589
                }
2590
2591
                if (false === $careerPromotionEventIsVisibleForUser) {
2592
                    continue;
2593
                }
2594
2595
                if (0 !== $careerId) {
2596
                    $careerInfo = (new Career())->get($row['career_id']);
2597
2598
                    unset($careerInfo['status'], $careerInfo['created_at'], $careerInfo['updated_at']);
2599
2600
                    $event['career'] = $careerInfo;
2601
                }
2602
2603
                if (0 !== $promotionId) {
2604
                    $promotionInfo = (new Promotion())->get($row['promotion_id']);
2605
2606
                    unset(
2607
                        $promotionInfo['career_id'],
2608
                        $promotionInfo['status'],
2609
                        $promotionInfo['created_at'],
2610
                        $promotionInfo['updated_at']
2611
                    );
2612
2613
                    $event['promotion'] = $promotionInfo;
2614
                }
2615
            }
2616
2617
            $my_events[] = $event;
2618
            $this->events[] = $event;
2619
        }
2620
2621
        return $my_events;
2622
    }
2623
2624
    /**
2625
     * @param FormValidator $form
2626
     * @param array         $groupList
2627
     * @param array         $userList
2628
     * @param array         $sendTo               array('users' => [1, 2], 'groups' => [3, 4])
2629
     * @param array         $attributes
2630
     * @param bool          $addOnlyItemsInSendTo
2631
     * @param bool          $required
2632
     */
2633
    public function setSendToSelect(
2634
        $form,
2635
        $groupList = [],
2636
        $userList = [],
2637
        $sendTo = [],
2638
        $attributes = [],
2639
        $addOnlyItemsInSendTo = false,
2640
        $required = false
2641
    ) {
2642
        $params = [
2643
            'id' => 'users_to_send_id',
2644
            'data-placeholder' => get_lang('Select'),
2645
            'multiple' => 'multiple',
2646
            'class' => 'multiple-select',
2647
        ];
2648
2649
        if (!empty($attributes)) {
2650
            $params = array_merge($params, $attributes);
2651
            if (empty($params['multiple'])) {
2652
                unset($params['multiple']);
2653
            }
2654
        }
2655
2656
        $sendToGroups = isset($sendTo['groups']) ? $sendTo['groups'] : [];
2657
        $sendToUsers = isset($sendTo['users']) ? $sendTo['users'] : [];
2658
2659
        /** @var HTML_QuickForm_select $select */
2660
        $select = $form->addSelect(
2661
            'users_to_send',
2662
            get_lang('To'),
2663
            null,
2664
            $params
2665
        );
2666
2667
        if ($required) {
2668
            $form->setRequired($select);
2669
        }
2670
2671
        $selectedEveryoneOptions = [];
2672
        if (isset($sendTo['everyone']) && $sendTo['everyone']) {
2673
            $selectedEveryoneOptions = ['selected'];
2674
            $sendToUsers = [];
2675
        }
2676
2677
        $select->addOption(
2678
            get_lang('Everyone'),
2679
            'everyone',
2680
            $selectedEveryoneOptions
2681
        );
2682
2683
        $options = [];
2684
        if (is_array($groupList)) {
2685
            foreach ($groupList as $group) {
2686
                $count_users = isset($group['count_users']) ? $group['count_users'] : $group['userNb'];
2687
                $count_users = " &ndash; $count_users ".get_lang('Users');
2688
                $option = [
2689
                    'text' => $group['name'].$count_users,
2690
                    'value' => "GROUP:".$group['id'],
2691
                ];
2692
                $selected = in_array(
2693
                    $group['id'],
2694
                    $sendToGroups
2695
                ) ? true : false;
2696
                if ($selected) {
2697
                    $option['selected'] = 'selected';
2698
                }
2699
2700
                if ($addOnlyItemsInSendTo) {
2701
                    if ($selected) {
2702
                        $options[] = $option;
2703
                    }
2704
                } else {
2705
                    $options[] = $option;
2706
                }
2707
            }
2708
            $select->addOptGroup($options, get_lang('Groups'));
2709
        }
2710
2711
        // adding the individual users to the select form
2712
        if (is_array($userList)) {
2713
            $options = [];
2714
            foreach ($userList as $user) {
2715
                if ($user['status'] == ANONYMOUS) {
2716
                    continue;
2717
                }
2718
                $option = [
2719
                    'text' => api_get_person_name(
2720
                            $user['firstname'],
2721
                            $user['lastname']
2722
                        ).' ('.$user['username'].')',
2723
                    'value' => "USER:".$user['user_id'],
2724
                ];
2725
2726
                $selected = in_array(
2727
                    $user['user_id'],
2728
                    $sendToUsers
2729
                ) ? true : false;
2730
2731
                if ($selected) {
2732
                    $option['selected'] = 'selected';
2733
                }
2734
2735
                if ($addOnlyItemsInSendTo) {
2736
                    if ($selected) {
2737
                        $options[] = $option;
2738
                    }
2739
                } else {
2740
                    $options[] = $option;
2741
                }
2742
            }
2743
2744
            $select->addOptGroup($options, get_lang('Users'));
2745
        }
2746
    }
2747
2748
    /**
2749
     * Separates the users and groups array
2750
     * users have a value USER:XXX (with XXX the user id
2751
     * groups have a value GROUP:YYY (with YYY the group id)
2752
     * use the 'everyone' key.
2753
     *
2754
     * @author Julio Montoya based in separate_users_groups in agenda.inc.php
2755
     *
2756
     * @param array $to
2757
     *
2758
     * @return array
2759
     */
2760
    public function parseSendToArray($to)
2761
    {
2762
        $groupList = [];
2763
        $userList = [];
2764
        $sendTo = null;
2765
2766
        $sendTo['everyone'] = false;
2767
        if (is_array($to) && count($to) > 0) {
2768
            foreach ($to as $item) {
2769
                if ($item == 'everyone') {
2770
                    $sendTo['everyone'] = true;
2771
                } else {
2772
                    list($type, $id) = explode(':', $item);
2773
                    switch ($type) {
2774
                        case 'GROUP':
2775
                            $groupList[] = $id;
2776
                            break;
2777
                        case 'USER':
2778
                            $userList[] = $id;
2779
                            break;
2780
                    }
2781
                }
2782
            }
2783
            $sendTo['groups'] = $groupList;
2784
            $sendTo['users'] = $userList;
2785
        }
2786
2787
        return $sendTo;
2788
    }
2789
2790
    /**
2791
     * @param int    $eventId
2792
     * @param string $type
2793
     *
2794
     * @return array<int, AgendaReminder>
2795
     */
2796
    public function getEventReminders($eventId, $type = null): array
2797
    {
2798
        $em = Database::getManager();
2799
        $remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
2800
2801
        return $remindersRepo->findBy(
2802
            [
2803
                'eventId' => $eventId,
2804
                'type' => $type ?: $this->type,
2805
            ]
2806
        );
2807
    }
2808
2809
    public function parseEventReminders(array $eventReminders): array
2810
    {
2811
        return array_map(
2812
            function (AgendaReminder $reminder) {
2813
                $interval = $reminder->getDateInterval();
2814
2815
                $reminderInfo = [
2816
                    'id' => $reminder->getId(),
2817
                    'type' => $reminder->getType(),
2818
                    'sent' => $reminder->isSent(),
2819
                    'date_interval' => [$interval->format('%a'), 'd'],
2820
                ];
2821
2822
                if ($interval->i) {
2823
                    $reminderInfo['date_interval'] = [$interval->i, 'i'];
2824
                } elseif ($interval->h) {
2825
                    $reminderInfo['date_interval'] = [$interval->h, 'h'];
2826
                } elseif ($interval->d) {
2827
                    $reminderInfo['date_interval'] = [$interval->d, 'd'];
2828
                }
2829
2830
                return $reminderInfo;
2831
            },
2832
            $eventReminders
2833
        );
2834
    }
2835
2836
    /**
2837
     * @param array $params
2838
     *
2839
     * @return FormValidator
2840
     */
2841
    public function getForm($params = [])
2842
    {
2843
        $action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
2844
        $id = isset($params['id']) ? (int) $params['id'] : 0;
2845
2846
        $em = Database::getManager();
2847
        $personalEvent = $id ? $em->find('ChamiloCoreBundle:PersonalAgenda', $id) : null;
2848
2849
        $url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
2850
        if ($this->type == 'course') {
2851
            $url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
2852
        }
2853
2854
        $form = new FormValidator(
2855
            'add_event',
2856
            'post',
2857
            $url,
2858
            null,
2859
            ['enctype' => 'multipart/form-data']
2860
        );
2861
2862
        $idAttach = isset($params['id_attach']) ? (int) $params['id_attach'] : null;
2863
        $groupId = api_get_group_id();
2864
        $form_Title = get_lang('AddCalendarItem');
2865
        if (!empty($id)) {
2866
            $form_Title = get_lang('ModifyCalendarItem');
2867
        }
2868
2869
        $form->addHeader($form_Title);
2870
        $form->addElement('hidden', 'id', $id);
2871
        $form->addElement('hidden', 'action', $action);
2872
        $form->addElement('hidden', 'id_attach', $idAttach);
2873
2874
        $isSubEventEdition = false;
2875
        $isParentFromSerie = false;
2876
        $showAttachmentForm = true;
2877
2878
        if ($this->type == 'course') {
2879
            // Edition mode.
2880
            if (!empty($id)) {
2881
                $showAttachmentForm = false;
2882
                if (isset($params['parent_event_id']) && !empty($params['parent_event_id'])) {
2883
                    $isSubEventEdition = true;
2884
                }
2885
                if (!empty($params['repeat_info'])) {
2886
                    $isParentFromSerie = true;
2887
                }
2888
            }
2889
        }
2890
2891
        if ($isSubEventEdition) {
2892
            $form->addElement(
2893
                'label',
2894
                null,
2895
                Display::return_message(
2896
                    get_lang('EditingThisEventWillRemoveItFromTheSerie'),
2897
                    'warning'
2898
                )
2899
            );
2900
        }
2901
2902
        $form->addElement('text', 'title', get_lang('ItemTitle'));
2903
2904
        if (isset($groupId) && !empty($groupId)) {
2905
            $form->addElement(
2906
                'hidden',
2907
                'users_to_send[]',
2908
                "GROUP:$groupId"
2909
            );
2910
            $form->addElement('hidden', 'to', 'true');
2911
        } else {
2912
            $sendTo = isset($params['send_to']) ? $params['send_to'] : ['everyone' => true];
2913
            if ($this->type == 'course') {
2914
                $this->showToForm($form, $sendTo, [], false, true);
2915
            }
2916
        }
2917
2918
        $form->addDateRangePicker(
2919
            'date_range',
2920
            get_lang('DateRange'),
2921
            false,
2922
            ['id' => 'date_range']
2923
        );
2924
        $form->addElement('checkbox', 'all_day', null, get_lang('AllDay'));
2925
2926
        if ($this->type == 'course') {
2927
            $repeat = $form->addElement(
2928
                'checkbox',
2929
                'repeat',
2930
                null,
2931
                get_lang('RepeatEvent'),
2932
                ['onclick' => 'return plus_repeated_event();']
2933
            );
2934
            $form->addElement(
2935
                'html',
2936
                '<div id="options2" style="display:none">'
2937
            );
2938
            $form->addElement(
2939
                'select',
2940
                'repeat_type',
2941
                get_lang('RepeatType'),
2942
                self::getRepeatTypes()
2943
            );
2944
            $form->addElement(
2945
                'date_picker',
2946
                'repeat_end_day',
2947
                get_lang('RepeatEnd'),
2948
                ['id' => 'repeat_end_date_form']
2949
            );
2950
2951
            if ($isSubEventEdition || $isParentFromSerie) {
2952
                $repeatInfo = $params['repeat_info'];
2953
                if ($isSubEventEdition) {
2954
                    $parentEvent = $params['parent_info'];
2955
                    $repeatInfo = $parentEvent['repeat_info'];
2956
                }
2957
                $params['repeat'] = 1;
2958
                $params['repeat_type'] = $repeatInfo['cal_type'];
2959
                $params['repeat_end_day'] = substr(
2960
                    api_get_local_time($repeatInfo['cal_end']),
2961
                    0,
2962
                    10
2963
                );
2964
2965
                $form->freeze(['repeat_type', 'repeat_end_day']);
2966
                $repeat->_attributes['disabled'] = 'disabled';
2967
            }
2968
            $form->addElement('html', '</div>');
2969
        }
2970
2971
        if (!empty($id)) {
2972
            if (empty($params['end_date'])) {
2973
                $params['date_range'] = $params['end_date'];
2974
            }
2975
2976
            $params['date_range'] =
2977
                substr(api_get_local_time($params['start_date']), 0, 16).' / '.
2978
                substr(api_get_local_time($params['end_date']), 0, 16);
2979
        }
2980
2981
        $toolbar = 'Agenda';
2982
        if (!api_is_allowed_to_edit(null, true)) {
2983
            $toolbar = 'AgendaStudent';
2984
        }
2985
2986
        $form->addElement(
2987
            'html_editor',
2988
            'content',
2989
            get_lang('Description'),
2990
            null,
2991
            [
2992
                'ToolbarSet' => $toolbar,
2993
                'Width' => '100%',
2994
                'Height' => '200',
2995
            ]
2996
        );
2997
2998
        if ($this->type == 'course') {
2999
            $form->addElement('textarea', 'comment', get_lang('Comment'));
3000
            $form->addLabel(
3001
                get_lang('FilesAttachment'),
3002
                '<div id="filepaths" class="file-upload-event">
3003
3004
                        <div id="filepath_1">
3005
                            <input type="file" name="attach_1"/>
3006
3007
                            <label>'.get_lang('Description').'</label>
3008
                            <input class="form-control" type="text" name="legend[]" />
3009
                        </div>
3010
3011
                    </div>'
3012
            );
3013
3014
            $form->addLabel(
3015
                '',
3016
                '<span id="link-more-attach">
3017
                    <a href="javascript://" onclick="return add_image_form()">'.
3018
                get_lang('AddOneMoreFile').'</a>
3019
                 </span>&nbsp;('.sprintf(
3020
                    get_lang('MaximunFileSizeX'),
3021
                    format_file_size(
3022
                        api_get_setting('message_max_upload_filesize')
3023
                    )
3024
                ).')'
3025
            );
3026
3027
            if (isset($params['attachment']) && !empty($params['attachment'])) {
3028
                $attachmentList = $params['attachment'];
3029
                foreach ($attachmentList as $attachment) {
3030
                    $params['file_comment'] = $attachment['comment'];
3031
                    if (!empty($attachment['path'])) {
3032
                        $form->addElement(
3033
                            'checkbox',
3034
                            'delete_attachment['.$attachment['id'].']',
3035
                            null,
3036
                            get_lang(
3037
                                'DeleteAttachment'
3038
                            ).': '.$attachment['filename']
3039
                        );
3040
                    }
3041
                }
3042
            }
3043
3044
            $form->addElement(
3045
                'textarea',
3046
                'file_comment',
3047
                get_lang('FileComment')
3048
            );
3049
        }
3050
3051
        if (empty($id) && 'course' === $this->type) {
3052
            $form->addElement(
3053
                'checkbox',
3054
                'add_announcement',
3055
                null,
3056
                get_lang('AddAnnouncement').'&nbsp('.get_lang('SendMail').')'
3057
            );
3058
        }
3059
3060
        $agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
3061
3062
        if ($agendaCollectiveInvitations && 'personal' === $this->type) {
3063
            $invitees = [];
3064
            $isCollective = false;
3065
            $allowInvitees = true;
3066
3067
            if ($personalEvent) {
3068
                $eventInvitation = $personalEvent->getInvitation();
3069
                $allowInvitees = !$eventInvitation instanceof AgendaEventSubscription;
3070
3071
                if ($eventInvitation && $allowInvitees) {
3072
                    foreach ($eventInvitation->getInvitees() as $invitee) {
3073
                        $inviteeUser = $invitee->getUser();
3074
3075
                        $invitees[$inviteeUser->getId()] = $inviteeUser->getCompleteNameWithUsername();
3076
                    }
3077
                }
3078
3079
                $isCollective = $personalEvent->isCollective();
3080
            }
3081
3082
            if ($allowInvitees) {
3083
                $form->addSelectAjax(
3084
                    'invitees',
3085
                    get_lang('Invitees'),
3086
                    $invitees,
3087
                    [
3088
                        'multiple' => 'multiple',
3089
                        'url' => api_get_path(WEB_AJAX_PATH).'message.ajax.php?a=find_users',
3090
                    ]
3091
                );
3092
                $form->addCheckBox('collective', '', get_lang('IsItEditableByTheInvitees'));
3093
                $form->addHtml('<hr>');
3094
3095
                $params['invitees'] = array_keys($invitees);
3096
                $params['collective'] = $isCollective;
3097
            }
3098
        }
3099
3100
        if (api_get_configuration_value('agenda_reminders')) {
3101
            $form->addHtml('<hr><div id="notification_list">');
3102
3103
            if ($id) {
3104
                $this->addFieldsForRemindersToForm($id, $form);
3105
            }
3106
3107
            $form->addHtml('</div>');
3108
            $form->addButton('add_notification', get_lang('AddNotification'), 'bell-o')->setType('button');
3109
            $form->addHtml('<hr>');
3110
        }
3111
3112
        if (api_is_platform_admin()
3113
            && true === api_get_configuration_value('agenda_event_subscriptions')
3114
        ) {
3115
            $form->addSelect(
3116
                'subscription_visibility',
3117
                get_lang('AllowSubscriptions'),
3118
                [
3119
                    AgendaEventSubscription::SUBSCRIPTION_NO => get_lang('No'),
3120
                    AgendaEventSubscription::SUBSCRIPTION_ALL => get_lang('AllUsersOfThePlatform'),
3121
                ]
3122
            );
3123
            $form->addNumeric(
3124
                'max_subscriptions',
3125
                ['', get_lang('MaxSubscriptionsLeaveEmptyToNotLimit')],
3126
                [
3127
                    'disabled' => 'disabled',
3128
                    'step' => 1,
3129
                    'min' => 0,
3130
                    'value' => 0,
3131
                ]
3132
            );
3133
            $form->addHtml("<script>
3134
                $(function () {
3135
                    $('#add_event_subscription_visibility')
3136
                        .on('change', function () {
3137
                            $('#max_subscriptions').prop('disabled', this.value == 0);                        
3138
                        })
3139
                        .trigger('change');
3140
                })
3141
                </script>
3142
            ");
3143
3144
            if ($personalEvent) {
3145
                $subscribers = array_map(
3146
                    function (array $subscriberInfo) {
3147
                        return '<li>'.$subscriberInfo['name'].'</li>';
3148
                    },
3149
                    self::getInviteesForPersonalEvent($personalEvent->getId(), AgendaEventSubscriber::class)
3150
                );
3151
3152
                $form->addLabel(
3153
                    get_lang('Subscribers'),
3154
                    '<ul class="form-control-static list-unstyled">'
3155
                        .implode(PHP_EOL, $subscribers)
3156
                        .'</ul>'
3157
                );
3158
3159
                /** @var AgendaEventSubscription $subscription */
3160
                $subscription = $personalEvent->getInvitation();
3161
                $params['max_subscriptions'] = $subscription->getMaxAttendees();
3162
            }
3163
        }
3164
3165
        if (api_get_configuration_value('allow_careers_in_global_agenda') && 'admin' === $this->type) {
3166
            Career::addCareerFieldsToForm($form);
3167
            $form->addHtml('<hr>');
3168
        }
3169
3170
        if ($id) {
3171
            $form->addButtonUpdate(get_lang('ModifyEvent'));
3172
        } else {
3173
            $form->addButtonSave(get_lang('AgendaAdd'));
3174
        }
3175
3176
        $form->setDefaults($params);
3177
        $form->addRule(
3178
            'date_range',
3179
            get_lang('ThisFieldIsRequired'),
3180
            'required'
3181
        );
3182
        $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
3183
3184
        return $form;
3185
    }
3186
3187
    public function addFieldsForRemindersToForm(int $eventId, FormValidator $form)
3188
    {
3189
        $remindersList = $this->parseEventReminders(
3190
            $this->getEventReminders($eventId)
3191
        );
3192
3193
        foreach ($remindersList as $reminderInfo) {
3194
            $form->addHtml('<div class="form-group">');
3195
            $form
3196
                ->addNumeric('notification_count[]', '', ['step' => 1, 'min' => 0])
3197
                ->setValue($reminderInfo['date_interval'][0])
3198
            ;
3199
            $form
3200
                ->addSelect(
3201
                'notification_period[]',
3202
                '',
3203
                    [
3204
                        'i' => get_lang('Minutes'),
3205
                        'h' => get_lang('Hours'),
3206
                        'd' => get_lang('Days'),
3207
                    ]
3208
                )
3209
                ->setValue($reminderInfo['date_interval'][1])
3210
            ;
3211
            $form->addHtml('<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>');
3212
            $form->addHtml(
3213
                '<div class="text-right col-sm-2">'
3214
                .'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>'
3215
                .'</div>'
3216
            );
3217
            $form->addHtml('</div>');
3218
        }
3219
3220
        $renderer = $form->defaultRenderer();
3221
        $renderer->setElementTemplate(
3222
            '<div class="col-sm-offset-2 col-sm-3">{element}</div>',
3223
            'notification_count[]'
3224
        );
3225
        $renderer->setElementTemplate(
3226
            '<div class="col-sm-3">{element}</div>',
3227
            'notification_period[]'
3228
        );
3229
    }
3230
3231
    /**
3232
     * @param FormValidator $form
3233
     * @param array         $sendTo               array('everyone' => false, 'users' => [1, 2], 'groups' => [3, 4])
3234
     * @param array         $attributes
3235
     * @param bool          $addOnlyItemsInSendTo
3236
     * @param bool          $required
3237
     *
3238
     * @return bool
3239
     */
3240
    public function showToForm(
3241
        $form,
3242
        $sendTo = [],
3243
        $attributes = [],
3244
        $addOnlyItemsInSendTo = false,
3245
        $required = false
3246
    ) {
3247
        if ($this->type != 'course') {
3248
            return false;
3249
        }
3250
3251
        $order = 'lastname';
3252
        if (api_is_western_name_order()) {
3253
            $order = 'firstname';
3254
        }
3255
3256
        $userList = CourseManager::get_user_list_from_course_code(
3257
            api_get_course_id(),
3258
            $this->sessionId,
3259
            null,
3260
            $order
3261
        );
3262
3263
        $groupList = CourseManager::get_group_list_of_course(
3264
            api_get_course_id(),
3265
            $this->sessionId
3266
        );
3267
3268
        $this->setSendToSelect(
3269
            $form,
3270
            $groupList,
3271
            $userList,
3272
            $sendTo,
3273
            $attributes,
3274
            $addOnlyItemsInSendTo,
3275
            $required
3276
        );
3277
3278
        return true;
3279
    }
3280
3281
    /**
3282
     * @param int   $id
3283
     * @param int   $visibility 0= invisible, 1 visible
3284
     * @param array $courseInfo
3285
     * @param int   $userId
3286
     */
3287
    public static function changeVisibility(
3288
        $id,
3289
        $visibility,
3290
        $courseInfo,
3291
        $userId = null
3292
    ) {
3293
        $id = intval($id);
3294
        if (empty($userId)) {
3295
            $userId = api_get_user_id();
3296
        } else {
3297
            $userId = intval($userId);
3298
        }
3299
3300
        if ($visibility == 0) {
3301
            api_item_property_update(
3302
                $courseInfo,
3303
                TOOL_CALENDAR_EVENT,
3304
                $id,
3305
                'invisible',
3306
                $userId
3307
            );
3308
        } else {
3309
            api_item_property_update(
3310
                $courseInfo,
3311
                TOOL_CALENDAR_EVENT,
3312
                $id,
3313
                'visible',
3314
                $userId
3315
            );
3316
        }
3317
    }
3318
3319
    /**
3320
     * Get repeat types.
3321
     *
3322
     * @return array
3323
     */
3324
    public static function getRepeatTypes()
3325
    {
3326
        return [
3327
            'daily' => get_lang('RepeatDaily'),
3328
            'weekly' => get_lang('RepeatWeekly'),
3329
            'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
3330
            //monthlyByDay"> get_lang('RepeatMonthlyByDay');
3331
            //monthlyByDayR' => get_lang('RepeatMonthlyByDayR'),
3332
            'yearly' => get_lang('RepeatYearly'),
3333
        ];
3334
    }
3335
3336
    /**
3337
     * Show a list with all the attachments according to the post's id.
3338
     *
3339
     * @param int   $eventId
3340
     * @param array $courseInfo
3341
     *
3342
     * @return array with the post info
3343
     */
3344
    public function getAttachmentList($eventId, $courseInfo)
3345
    {
3346
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3347
        $courseId = (int) $courseInfo['real_id'];
3348
        $eventId = (int) $eventId;
3349
3350
        $sql = "SELECT id, path, filename, comment
3351
                FROM $tableAttachment
3352
                WHERE
3353
                    c_id = $courseId AND
3354
                    agenda_id = $eventId";
3355
        $result = Database::query($sql);
3356
        $list = [];
3357
        if (Database::num_rows($result) != 0) {
3358
            $list = Database::store_result($result, 'ASSOC');
3359
        }
3360
3361
        return $list;
3362
    }
3363
3364
    /**
3365
     * Show a list with all the attachments according to the post's id.
3366
     *
3367
     * @param int   $attachmentId
3368
     * @param int   $eventId
3369
     * @param array $courseInfo
3370
     *
3371
     * @return array with the post info
3372
     */
3373
    public function getAttachment($attachmentId, $eventId, $courseInfo)
3374
    {
3375
        if (empty($courseInfo) || empty($attachmentId) || empty($eventId)) {
3376
            return [];
3377
        }
3378
3379
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3380
        $courseId = (int) $courseInfo['real_id'];
3381
        $eventId = (int) $eventId;
3382
        $attachmentId = (int) $attachmentId;
3383
3384
        $row = [];
3385
        $sql = "SELECT id, path, filename, comment
3386
                FROM $tableAttachment
3387
                WHERE
3388
                    c_id = $courseId AND
3389
                    agenda_id = $eventId AND
3390
                    id = $attachmentId
3391
                ";
3392
        $result = Database::query($sql);
3393
        if (Database::num_rows($result) != 0) {
3394
            $row = Database::fetch_array($result, 'ASSOC');
3395
        }
3396
3397
        return $row;
3398
    }
3399
3400
    /**
3401
     * Add an attachment file into agenda.
3402
     *
3403
     * @param int    $eventId
3404
     * @param array  $fileUserUpload ($_FILES['user_upload'])
3405
     * @param string $comment        about file
3406
     * @param array  $courseInfo
3407
     *
3408
     * @return string
3409
     */
3410
    public function addAttachment(
3411
        $eventId,
3412
        $fileUserUpload,
3413
        $comment,
3414
        $courseInfo
3415
    ) {
3416
        $agenda_table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3417
        $eventId = (int) $eventId;
3418
3419
        // Storing the attachments
3420
        $upload_ok = false;
3421
        if (!empty($fileUserUpload['name'])) {
3422
            $upload_ok = process_uploaded_file($fileUserUpload);
3423
        }
3424
3425
        if (!empty($upload_ok)) {
3426
            $courseDir = $courseInfo['directory'].'/upload/calendar';
3427
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
3428
            $uploadDir = $sys_course_path.$courseDir;
3429
3430
            // Try to add an extension to the file if it hasn't one
3431
            $new_file_name = add_ext_on_mime(
3432
                stripslashes($fileUserUpload['name']),
3433
                $fileUserUpload['type']
3434
            );
3435
3436
            // user's file name
3437
            $file_name = $fileUserUpload['name'];
3438
3439
            if (!filter_extension($new_file_name)) {
3440
                return Display::return_message(
3441
                    get_lang('UplUnableToSaveFileFilteredExtension'),
3442
                    'error'
3443
                );
3444
            } else {
3445
                $new_file_name = uniqid('');
3446
                $new_path = $uploadDir.'/'.$new_file_name;
3447
                $result = @move_uploaded_file(
3448
                    $fileUserUpload['tmp_name'],
3449
                    $new_path
3450
                );
3451
                $courseId = api_get_course_int_id();
3452
                $size = intval($fileUserUpload['size']);
3453
                // Storing the attachments if any
3454
                if ($result) {
3455
                    $params = [
3456
                        'c_id' => $courseId,
3457
                        'filename' => $file_name,
3458
                        'comment' => $comment,
3459
                        'path' => $new_file_name,
3460
                        'agenda_id' => $eventId,
3461
                        'size' => $size,
3462
                    ];
3463
                    $id = Database::insert($agenda_table_attachment, $params);
3464
                    if ($id) {
3465
                        $sql = "UPDATE $agenda_table_attachment
3466
                                SET id = iid WHERE iid = $id";
3467
                        Database::query($sql);
3468
3469
                        api_item_property_update(
3470
                            $courseInfo,
3471
                            'calendar_event_attachment',
3472
                            $id,
3473
                            'AgendaAttachmentAdded',
3474
                            api_get_user_id()
3475
                        );
3476
                    }
3477
                }
3478
            }
3479
        }
3480
    }
3481
3482
    /**
3483
     * @param int    $attachmentId
3484
     * @param int    $eventId
3485
     * @param array  $fileUserUpload
3486
     * @param string $comment
3487
     * @param array  $courseInfo
3488
     */
3489
    public function updateAttachment(
3490
        $attachmentId,
3491
        $eventId,
3492
        $fileUserUpload,
3493
        $comment,
3494
        $courseInfo
3495
    ) {
3496
        $attachment = $this->getAttachment(
3497
            $attachmentId,
3498
            $eventId,
3499
            $courseInfo
3500
        );
3501
        if (!empty($attachment)) {
3502
            $this->deleteAttachmentFile($attachmentId, $courseInfo);
3503
        }
3504
        $this->addAttachment($eventId, $fileUserUpload, $comment, $courseInfo);
3505
    }
3506
3507
    /**
3508
     * This function delete a attachment file by id.
3509
     *
3510
     * @param int   $attachmentId
3511
     * @param array $courseInfo
3512
     *
3513
     * @return string
3514
     */
3515
    public function deleteAttachmentFile($attachmentId, $courseInfo)
3516
    {
3517
        $table = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3518
        $attachmentId = (int) $attachmentId;
3519
        $courseId = $courseInfo['real_id'];
3520
3521
        if (empty($courseId) || empty($attachmentId)) {
3522
            return false;
3523
        }
3524
3525
        $sql = "DELETE FROM $table
3526
                WHERE c_id = $courseId AND id = ".$attachmentId;
3527
        $result = Database::query($sql);
3528
3529
        // update item_property
3530
        api_item_property_update(
3531
            $courseInfo,
3532
            'calendar_event_attachment',
3533
            $attachmentId,
3534
            'AgendaAttachmentDeleted',
3535
            api_get_user_id()
3536
        );
3537
3538
        if (!empty($result)) {
3539
            return Display::return_message(
3540
                get_lang("AttachmentFileDeleteSuccess"),
3541
                'confirmation'
3542
            );
3543
        }
3544
    }
3545
3546
    /**
3547
     * @param int $eventId
3548
     *
3549
     * @return array
3550
     */
3551
    public function getAllRepeatEvents($eventId)
3552
    {
3553
        $events = [];
3554
        $eventId = (int) $eventId;
3555
3556
        switch ($this->type) {
3557
            case 'personal':
3558
                break;
3559
            case 'course':
3560
                if (!empty($this->course['real_id'])) {
3561
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
3562
                            WHERE
3563
                                c_id = ".$this->course['real_id']." AND
3564
                                parent_event_id = ".$eventId;
3565
                    $result = Database::query($sql);
3566
                    if (Database::num_rows($result)) {
3567
                        while ($row = Database::fetch_array($result, 'ASSOC')) {
3568
                            $events[] = $row;
3569
                        }
3570
                    }
3571
                }
3572
                break;
3573
        }
3574
3575
        return $events;
3576
    }
3577
3578
    /**
3579
     * @param int $eventId
3580
     * @param int $courseId
3581
     *
3582
     * @return bool
3583
     */
3584
    public function hasChildren($eventId, $courseId)
3585
    {
3586
        $eventId = (int) $eventId;
3587
        $courseId = (int) $courseId;
3588
3589
        $sql = "SELECT count(DISTINCT(id)) as count
3590
                FROM ".$this->tbl_course_agenda."
3591
                WHERE
3592
                    c_id = $courseId AND
3593
                    parent_event_id = $eventId";
3594
        $result = Database::query($sql);
3595
        if (Database::num_rows($result)) {
3596
            $row = Database::fetch_array($result, 'ASSOC');
3597
3598
            return $row['count'] > 0;
3599
        }
3600
3601
        return false;
3602
    }
3603
3604
    public function displayActions(string $view, ?string $filter = ''): string
3605
    {
3606
        $groupInfo = GroupManager::get_group_properties(api_get_group_id());
3607
        $groupIid = $groupInfo['iid'] ?? 0;
3608
3609
        $codePath = api_get_path(WEB_CODE_PATH);
3610
3611
        $currentUserId = api_get_user_id();
3612
        $cidReq = api_get_cidreq();
3613
3614
        $actionsLeft = Display::url(
3615
            Display::return_icon('calendar.png', get_lang('Calendar'), [], ICON_SIZE_MEDIUM),
3616
            $codePath."calendar/agenda_js.php?type={$this->type}&$cidReq"
3617
        );
3618
        $actionsLeft .= Display::url(
3619
            Display::return_icon('week.png', get_lang('AgendaList'), [], ICON_SIZE_MEDIUM),
3620
            $codePath."calendar/agenda_list.php?type={$this->type}&$cidReq"
3621
        );
3622
3623
        $isAllowedToEdit = api_is_allowed_to_edit(false, true);
3624
3625
        $form = '';
3626
        if ($isAllowedToEdit
3627
            || ('personal' === $this->type && !api_is_anonymous() && 'true' === api_get_setting('allow_personal_agenda'))
3628
            || (
3629
                '1' === api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous() &&
3630
                api_is_allowed_to_session_edit(false, true))
3631
            || (
3632
                GroupManager::user_has_access($currentUserId, $groupIid, GroupManager::GROUP_TOOL_CALENDAR)
3633
                && GroupManager::is_tutor_of_group($currentUserId, $groupInfo)
3634
            )
3635
        ) {
3636
            $actionsLeft .= Display::url(
3637
                Display::return_icon('new_event.png', get_lang('AgendaAdd'), [], ICON_SIZE_MEDIUM),
3638
                $codePath."calendar/agenda.php?action=add&type={$this->type}&$cidReq"
3639
            );
3640
3641
            $actionsLeft .= Display::url(
3642
                Display::return_icon('import_calendar.png', get_lang('ICalFileImport'), [], ICON_SIZE_MEDIUM),
3643
                $codePath."calendar/agenda.php?action=importical&type={$this->type}&$cidReq"
3644
            );
3645
3646
            if ($this->type === 'course') {
3647
                if (!isset($_GET['action'])) {
3648
                    $form = new FormValidator(
3649
                        'form-search',
3650
                        'post',
3651
                        '',
3652
                        '',
3653
                        [],
3654
                        FormValidator::LAYOUT_INLINE
3655
                    );
3656
                    $attributes = [
3657
                        'multiple' => false,
3658
                        'id' => 'select_form_id_search',
3659
                    ];
3660
                    $selectedValues = $this->parseAgendaFilter($filter);
3661
                    $this->showToForm($form, $selectedValues, $attributes);
3662
                    $form = $form->returnForm();
3663
                }
3664
3665
                if (true === api_get_configuration_value('agenda_reminders') && $isAllowedToEdit) {
3666
                    $actionsLeft .= Display::url(
3667
                        Display::return_icon(
3668
                            'course_request_pending.png',
3669
                            get_lang('ImportCourseEvents'),
3670
                            [],
3671
                            ICON_SIZE_MEDIUM
3672
                        ),
3673
                        $codePath."calendar/agenda.php?action=import_course_agenda_reminders&type={$this->type}&$cidReq"
3674
                    );
3675
                }
3676
            }
3677
        }
3678
3679
        if ($this->type === 'personal' && !api_is_anonymous()) {
3680
            $actionsLeft .= Display::url(
3681
                Display::return_icon('1day.png', get_lang('SessionsPlanCalendar'), [], ICON_SIZE_MEDIUM),
3682
                $codePath.'calendar/planification.php'
3683
            );
3684
3685
            if (api_is_student_boss() || api_is_platform_admin()) {
3686
                $actionsLeft .= Display::url(
3687
                    Display::return_icon('calendar-user.png', get_lang('MyStudentsSchedule'), [], ICON_SIZE_MEDIUM),
3688
                    $codePath.'mySpace/calendar_plan.php'
3689
                );
3690
            }
3691
        }
3692
3693
        if (api_is_platform_admin()
3694
            || api_is_teacher()
3695
            || api_is_student_boss()
3696
            || api_is_drh()
3697
            || api_is_session_admin()
3698
            || api_is_coach()
3699
        ) {
3700
            if ($this->type == 'personal') {
3701
                $form = '';
3702
                if (!isset($_GET['action'])) {
3703
                    $form = new FormValidator(
3704
                        'form-search',
3705
                        'get',
3706
                        api_get_self().'?type=personal&',
3707
                        '',
3708
                        [],
3709
                        FormValidator::LAYOUT_INLINE
3710
                    );
3711
3712
                    $sessions = [];
3713
3714
                    if (api_is_drh()) {
3715
                        $sessionList = SessionManager::get_sessions_followed_by_drh($currentUserId);
3716
                        if (!empty($sessionList)) {
3717
                            foreach ($sessionList as $sessionItem) {
3718
                                $sessions[$sessionItem['id']] = strip_tags($sessionItem['name']);
3719
                            }
3720
                        }
3721
                    } else {
3722
                        $sessions = SessionManager::get_sessions_by_user($currentUserId);
3723
                        $sessions = array_column($sessions, 'session_name', 'session_id');
3724
                    }
3725
3726
                    $form->addHidden('type', 'personal');
3727
                    $sessions = ['0' => get_lang('SelectAnOption')] + $sessions;
3728
3729
                    $form->addSelect(
3730
                        'session_id',
3731
                        get_lang('Session'),
3732
                        $sessions,
3733
                        ['id' => 'session_id', 'onchange' => 'submit();']
3734
                    );
3735
3736
                    $form->addButton('reset', get_lang('Reset'), 'eraser');
3737
                    $form = $form->returnForm();
3738
                }
3739
            }
3740
        }
3741
3742
        $actionsRight = '';
3743
        if ($view == 'calendar') {
3744
            $actionsRight .= $form;
3745
        }
3746
3747
        return Display::toolbarAction(
3748
            'toolbar-agenda',
3749
            [$actionsLeft, $actionsRight]
3750
        );
3751
    }
3752
3753
    /**
3754
     * @return FormValidator
3755
     */
3756
    public function getImportCalendarForm()
3757
    {
3758
        $form = new FormValidator(
3759
            'frm_import_ical',
3760
            'post',
3761
            api_get_self().'?action=importical&type='.$this->type,
3762
            ['enctype' => 'multipart/form-data']
3763
        );
3764
        $form->addHeader(get_lang('ICalFileImport'));
3765
        $form->addElement('file', 'ical_import', get_lang('ICalFileImport'));
3766
        $form->addRule(
3767
            'ical_import',
3768
            get_lang('ThisFieldIsRequired'),
3769
            'required'
3770
        );
3771
        $form->addButtonImport(get_lang('Import'), 'ical_submit');
3772
3773
        return $form;
3774
    }
3775
3776
    /**
3777
     * @param array $courseInfo
3778
     * @param $file
3779
     *
3780
     * @return false|string
3781
     */
3782
    public function importEventFile($courseInfo, $file)
3783
    {
3784
        $charset = api_get_system_encoding();
3785
        $filepath = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
3786
        $messages = [];
3787
3788
        if (!@move_uploaded_file($file['tmp_name'], $filepath)) {
3789
            error_log(
3790
                'Problem moving uploaded file: '.$file['error'].' in '.__FILE__.' line '.__LINE__
3791
            );
3792
3793
            return false;
3794
        }
3795
3796
        $data = file_get_contents($filepath);
3797
3798
        $trans = [
3799
            'DAILY' => 'daily',
3800
            'WEEKLY' => 'weekly',
3801
            'MONTHLY' => 'monthlyByDate',
3802
            'YEARLY' => 'yearly',
3803
        ];
3804
        $sentTo = ['everyone' => true];
3805
        $calendar = Sabre\VObject\Reader::read($data);
3806
        $currentTimeZone = api_get_timezone();
3807
        if (!empty($calendar->VEVENT)) {
3808
            /** @var Sabre\VObject\Component\VEvent $event */
3809
            foreach ($calendar->VEVENT as $event) {
3810
                $tempDate = $event->DTSTART->getValue();
3811
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3812
                    $event->DTSTART->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3813
                }
3814
                $tempDate = $event->DTEND->getValue();
3815
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3816
                    $event->DTEND->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3817
                }
3818
                $start = $event->DTSTART->getDateTime();
3819
                $end = $event->DTEND->getDateTime();
3820
                //Sabre\VObject\DateTimeParser::parseDateTime(string $dt, \Sabre\VObject\DateTimeZone $tz)
3821
3822
                $startDateTime = api_get_local_time(
3823
                    $start->format('Y-m-d H:i:s'),
3824
                    $currentTimeZone,
3825
                    $start->format('e')
3826
                );
3827
                $endDateTime = api_get_local_time(
3828
                    $end->format('Y-m-d H:i'),
3829
                    $currentTimeZone,
3830
                    $end->format('e')
3831
                );
3832
                $title = api_convert_encoding(
3833
                    (string) $event->summary,
3834
                    $charset,
3835
                    'UTF-8'
3836
                );
3837
                $description = api_convert_encoding(
3838
                    (string) $event->description,
3839
                    $charset,
3840
                    'UTF-8'
3841
                );
3842
3843
                $id = $this->addEvent(
3844
                    $startDateTime,
3845
                    $endDateTime,
3846
                    'false',
3847
                    $title,
3848
                    $description,
3849
                    $sentTo
3850
                );
3851
3852
                $messages[] = " $title - ".$startDateTime." - ".$endDateTime;
3853
3854
                //$attendee = (string)$event->attendee;
3855
                /** @var Sabre\VObject\Property\ICalendar\Recur $repeat */
3856
                $repeat = $event->RRULE;
3857
                if ($id && !empty($repeat)) {
3858
                    $repeat = $repeat->getParts();
3859
                    $freq = $trans[$repeat['FREQ']];
3860
3861
                    if (isset($repeat['UNTIL']) && !empty($repeat['UNTIL'])) {
3862
                        // Check if datetime or just date (strlen == 8)
3863
                        if (strlen($repeat['UNTIL']) == 8) {
3864
                            // Fix the datetime format to avoid exception in the next step
3865
                            $repeat['UNTIL'] .= 'T000000';
3866
                        }
3867
                        $until = Sabre\VObject\DateTimeParser::parseDateTime(
3868
                            $repeat['UNTIL'],
3869
                            new DateTimeZone($currentTimeZone)
3870
                        );
3871
                        $until = $until->format('Y-m-d H:i:s');
3872
                        $this->addRepeatedItem(
3873
                            $id,
3874
                            $freq,
3875
                            $until,
3876
                            $sentTo
3877
                        );
3878
                    }
3879
3880
                    if (!empty($repeat['COUNT'])) {
3881
                        /*$count = $repeat['COUNT'];
3882
                        $interval = $repeat['INTERVAL'];
3883
                        $endDate = null;
3884
                        switch($freq) {
3885
                            case 'daily':
3886
                                $start = api_strtotime($startDateTime);
3887
                                $date = new DateTime($startDateTime);
3888
                                $days = $count * $interval;
3889
                                var_dump($days);
3890
                                $date->add(new DateInterval("P".$days."D"));
3891
                                $endDate = $date->format('Y-m-d H:i');
3892
                                //$endDate = $count *
3893
                                for ($i = 0; $i < $count; $i++) {
3894
                                    $days = 86400 * 7
3895
                                }
3896
                            }
3897
                        }*/
3898
                        //$res = agenda_add_repeat_item($courseInfo, $id, $freq, $count, $attendee);
3899
                        /*$this->addRepeatedItem(
3900
                            $id,
3901
                            $freq,
3902
                            $endDate,
3903
                            $sentTo
3904
                        );*/
3905
                    }
3906
                }
3907
            }
3908
        }
3909
3910
        if (!empty($messages)) {
3911
            $messages = implode('<br /> ', $messages);
3912
        } else {
3913
            $messages = get_lang('NoAgendaItems');
3914
        }
3915
3916
        return $messages;
3917
    }
3918
3919
    /**
3920
     * Parse filter turns USER:12 to ['users' => [12])] or G:1 ['groups' => [1]].
3921
     *
3922
     * @param int $filter
3923
     *
3924
     * @return array
3925
     */
3926
    public function parseAgendaFilter($filter)
3927
    {
3928
        $everyone = false;
3929
        $groupId = null;
3930
        $userId = null;
3931
3932
        if ($filter == 'everyone') {
3933
            $everyone = true;
3934
        } else {
3935
            if (substr($filter, 0, 1) == 'G') {
3936
                $groupId = str_replace('GROUP:', '', $filter);
3937
            } else {
3938
                $userId = str_replace('USER:', '', $filter);
3939
            }
3940
        }
3941
        if (empty($userId) && empty($groupId)) {
3942
            $everyone = true;
3943
        }
3944
3945
        return [
3946
            'everyone' => $everyone,
3947
            'users' => [$userId],
3948
            'groups' => [$groupId],
3949
        ];
3950
    }
3951
3952
    /**
3953
     *    This function retrieves all the agenda items of all the courses the user is subscribed to.
3954
     */
3955
    public static function get_myagendaitems(
3956
        $user_id,
3957
        $courses_dbs,
3958
        $month,
3959
        $year
3960
    ) {
3961
        $user_id = intval($user_id);
3962
3963
        $items = [];
3964
        $my_list = [];
3965
3966
        // get agenda-items for every course
3967
        foreach ($courses_dbs as $key => $array_course_info) {
3968
            //databases of the courses
3969
            $TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
3970
            $TABLE_ITEMPROPERTY = Database::get_course_table(
3971
                TABLE_ITEM_PROPERTY
3972
            );
3973
3974
            $group_memberships = GroupManager::get_group_ids(
3975
                $array_course_info['real_id'],
3976
                $user_id
3977
            );
3978
            $course_user_status = CourseManager::getUserInCourseStatus(
3979
                $user_id,
3980
                $array_course_info['real_id']
3981
            );
3982
            // if the user is administrator of that course we show all the agenda items
3983
            if ($course_user_status == '1') {
3984
                //echo "course admin";
3985
                $sqlquery = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
3986
							FROM ".$TABLEAGENDA." agenda,
3987
								 ".$TABLE_ITEMPROPERTY." ip
3988
							WHERE agenda.id = ip.ref
3989
							AND MONTH(agenda.start_date)='".$month."'
3990
							AND YEAR(agenda.start_date)='".$year."'
3991
							AND ip.tool='".TOOL_CALENDAR_EVENT."'
3992
							AND ip.visibility='1'
3993
							GROUP BY agenda.id
3994
							ORDER BY start_date ";
3995
            } else {
3996
                // if the user is not an administrator of that course
3997
                if (is_array($group_memberships) && count(
3998
                        $group_memberships
3999
                    ) > 0
4000
                ) {
4001
                    $sqlquery = "SELECT	agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4002
								FROM ".$TABLEAGENDA." agenda,
4003
									".$TABLE_ITEMPROPERTY." ip
4004
								WHERE agenda.id = ip.ref
4005
								AND MONTH(agenda.start_date)='".$month."'
4006
								AND YEAR(agenda.start_date)='".$year."'
4007
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4008
								AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4009
                            ", ",
4010
                            $group_memberships
4011
                        ).")) )
4012
								AND ip.visibility='1'
4013
								ORDER BY start_date ";
4014
                } else {
4015
                    $sqlquery = "SELECT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4016
								FROM ".$TABLEAGENDA." agenda,
4017
									".$TABLE_ITEMPROPERTY." ip
4018
								WHERE agenda.id = ip.ref
4019
								AND MONTH(agenda.start_date)='".$month."'
4020
								AND YEAR(agenda.start_date)='".$year."'
4021
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4022
								AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL)
4023
								AND ip.visibility='1'
4024
								ORDER BY start_date ";
4025
                }
4026
            }
4027
            $result = Database::query($sqlquery);
4028
4029
            while ($item = Database::fetch_array($result, 'ASSOC')) {
4030
                $agendaday = -1;
4031
                if (!empty($item['start_date'])) {
4032
                    $item['start_date'] = api_get_local_time(
4033
                        $item['start_date']
4034
                    );
4035
                    $item['start_date_tms'] = api_strtotime(
4036
                        $item['start_date']
4037
                    );
4038
                    $agendaday = date("j", $item['start_date_tms']);
4039
                }
4040
                if (!empty($item['end_date'])) {
4041
                    $item['end_date'] = api_get_local_time($item['end_date']);
4042
                }
4043
4044
                $url = api_get_path(
4045
                        WEB_CODE_PATH
4046
                    )."calendar/agenda.php?cidReq=".urlencode(
4047
                        $array_course_info["code"]
4048
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4049
4050
                $item['url'] = $url;
4051
                $item['course_name'] = $array_course_info['title'];
4052
                $item['calendar_type'] = 'course';
4053
                $item['course_id'] = $array_course_info['course_id'];
4054
4055
                $my_list[$agendaday][] = $item;
4056
            }
4057
        }
4058
4059
        // sorting by hour for every day
4060
        $agendaitems = [];
4061
        foreach ($items as $agendaday => $tmpitems) {
4062
            if (!isset($agendaitems[$agendaday])) {
4063
                $agendaitems[$agendaday] = '';
4064
            }
4065
            sort($tmpitems);
4066
            foreach ($tmpitems as $val) {
4067
                $agendaitems[$agendaday] .= $val;
4068
            }
4069
        }
4070
4071
        return $my_list;
4072
    }
4073
4074
    /**
4075
     * This function retrieves one personal agenda item returns it.
4076
     *
4077
     * @param    array    The array containing existing events. We add to this array.
4078
     * @param    int        Day
4079
     * @param    int        Month
4080
     * @param    int        Year (4 digits)
4081
     * @param    int        Week number
4082
     * @param    string    Type of view (month_view, week_view, day_view)
4083
     *
4084
     * @return array The results of the database query, or null if not found
4085
     */
4086
    public static function get_global_agenda_items(
4087
        $agendaitems,
4088
        $day,
4089
        $month,
4090
        $year,
4091
        $week,
4092
        $type
4093
    ) {
4094
        $tbl_global_agenda = Database::get_main_table(
4095
            TABLE_MAIN_SYSTEM_CALENDAR
4096
        );
4097
        $month = intval($month);
4098
        $year = intval($year);
4099
        $week = intval($week);
4100
        $day = intval($day);
4101
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4102
4103
        $current_access_url_id = api_get_current_access_url_id();
4104
4105
        if ($type == "month_view" || $type == "") {
4106
            // We are in month view
4107
            $sql = "SELECT * FROM ".$tbl_global_agenda."
4108
                    WHERE
4109
                        MONTH(start_date) = ".$month." AND
4110
                        YEAR(start_date) = ".$year."  AND
4111
                        access_url_id = $current_access_url_id
4112
                    ORDER BY start_date ASC";
4113
        }
4114
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4115
        if ($type == "week_view") { // we are in week view
4116
            $start_end_day_of_week = self::calculate_start_end_of_week(
4117
                $week,
4118
                $year
4119
            );
4120
            $start_day = $start_end_day_of_week['start']['day'];
4121
            $start_month = $start_end_day_of_week['start']['month'];
4122
            $start_year = $start_end_day_of_week['start']['year'];
4123
            $end_day = $start_end_day_of_week['end']['day'];
4124
            $end_month = $start_end_day_of_week['end']['month'];
4125
            $end_year = $start_end_day_of_week['end']['year'];
4126
            // in sql statements you have to use year-month-day for date calculations
4127
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4128
            $start_filter = api_get_utc_datetime($start_filter);
4129
4130
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4131
            $end_filter = api_get_utc_datetime($end_filter);
4132
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."' AND  access_url_id = $current_access_url_id ";
4133
        }
4134
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4135
        if ($type == "day_view") { // we are in day view
4136
            // we could use mysql date() function but this is only available from 4.1 and higher
4137
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4138
            $start_filter = api_get_utc_datetime($start_filter);
4139
4140
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4141
            $end_filter = api_get_utc_datetime($end_filter);
4142
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."'  AND  access_url_id = $current_access_url_id";
4143
        }
4144
4145
        $result = Database::query($sql);
4146
4147
        while ($item = Database::fetch_array($result)) {
4148
            if (!empty($item['start_date'])) {
4149
                $item['start_date'] = api_get_local_time($item['start_date']);
4150
                $item['start_date_tms'] = api_strtotime($item['start_date']);
4151
            }
4152
            if (!empty($item['end_date'])) {
4153
                $item['end_date'] = api_get_local_time($item['end_date']);
4154
            }
4155
4156
            // we break the date field in the database into a date and a time part
4157
            $agenda_db_date = explode(" ", $item['start_date']);
4158
            $date = $agenda_db_date[0];
4159
            $time = $agenda_db_date[1];
4160
            // we divide the date part into a day, a month and a year
4161
            $agendadate = explode("-", $date);
4162
            $year = intval($agendadate[0]);
4163
            $month = intval($agendadate[1]);
4164
            $day = intval($agendadate[2]);
4165
            // we divide the time part into hour, minutes, seconds
4166
            $agendatime = explode(":", $time);
4167
            $hour = $agendatime[0];
4168
            $minute = $agendatime[1];
4169
            $second = $agendatime[2];
4170
4171
            if ($type == 'month_view') {
4172
                $item['calendar_type'] = 'global';
4173
                $agendaitems[$day][] = $item;
4174
                continue;
4175
            }
4176
4177
            $start_time = api_format_date(
4178
                $item['start_date'],
4179
                TIME_NO_SEC_FORMAT
4180
            );
4181
            $end_time = '';
4182
            if (!empty($item['end_date'])) {
4183
                $end_time = ' - '.api_format_date(
4184
                        $item['end_date'],
4185
                        DATE_TIME_FORMAT_LONG
4186
                    );
4187
            }
4188
4189
            // if the student has specified a course we a add a link to that course
4190
            if ($item['course'] != "") {
4191
                $url = api_get_path(
4192
                        WEB_CODE_PATH
4193
                    )."admin/agenda.php?cidReq=".urlencode(
4194
                        $item['course']
4195
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4196
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4197
            } else {
4198
                $course_link = "";
4199
            }
4200
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4201
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4202
            if ($type !== "day_view") {
4203
                // This is the array construction for the WEEK or MONTH view
4204
                //Display the Agenda global in the tab agenda (administrator)
4205
                $agendaitems[$day] .= "<i>$start_time $end_time</i>&nbsp;-&nbsp;";
4206
                $agendaitems[$day] .= "<b>".get_lang('GlobalEvent')."</b>";
4207
                $agendaitems[$day] .= "<div>".$item['title']."</div><br>";
4208
            } else {
4209
                // this is the array construction for the DAY view
4210
                $halfhour = 2 * $agendatime['0'];
4211
                if ($agendatime['1'] >= '30') {
4212
                    $halfhour = $halfhour + 1;
4213
                }
4214
                if (!is_array($agendaitems[$halfhour])) {
4215
                    $content = $agendaitems[$halfhour];
4216
                }
4217
                $agendaitems[$halfhour] = $content."<div><i>$hour:$minute</i> <b>".get_lang(
4218
                        'GlobalEvent'
4219
                    ).":  </b>".$item['title']."</div>";
4220
            }
4221
        }
4222
4223
        return $agendaitems;
4224
    }
4225
4226
    /**
4227
     * This function retrieves all the personal agenda items and add them to the agenda items found by the other
4228
     * functions.
4229
     */
4230
    public static function get_personal_agenda_items(
4231
        $user_id,
4232
        $agendaitems,
4233
        $day,
4234
        $month,
4235
        $year,
4236
        $week,
4237
        $type
4238
    ) {
4239
        $tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
4240
        $user_id = intval($user_id);
4241
4242
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4243
        if ($type === "month_view" || $type === "") {
4244
            // we are in month view
4245
            $sql = "SELECT * FROM $tbl_personal_agenda
4246
                    WHERE
4247
                        user='".$user_id."' AND
4248
                        MONTH(date)='".$month."' AND
4249
                        YEAR(date) = '".$year."'
4250
                     ORDER BY date ASC";
4251
        }
4252
4253
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4254
        // we are in week view
4255
        if ($type == "week_view") {
4256
            $start_end_day_of_week = self::calculate_start_end_of_week(
4257
                $week,
4258
                $year
4259
            );
4260
            $start_day = $start_end_day_of_week['start']['day'];
4261
            $start_month = $start_end_day_of_week['start']['month'];
4262
            $start_year = $start_end_day_of_week['start']['year'];
4263
            $end_day = $start_end_day_of_week['end']['day'];
4264
            $end_month = $start_end_day_of_week['end']['month'];
4265
            $end_year = $start_end_day_of_week['end']['year'];
4266
            // in sql statements you have to use year-month-day for date calculations
4267
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4268
            $start_filter = api_get_utc_datetime($start_filter);
4269
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4270
            $end_filter = api_get_utc_datetime($end_filter);
4271
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4272
        }
4273
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4274
        if ($type == "day_view") {
4275
            // we are in day view
4276
            // we could use mysql date() function but this is only available from 4.1 and higher
4277
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4278
            $start_filter = api_get_utc_datetime($start_filter);
4279
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4280
            $end_filter = api_get_utc_datetime($end_filter);
4281
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4282
        }
4283
4284
        $result = Database::query($sql);
4285
        while ($item = Database::fetch_array($result, 'ASSOC')) {
4286
            $time_minute = api_convert_and_format_date(
4287
                $item['date'],
4288
                TIME_NO_SEC_FORMAT
4289
            );
4290
            $item['date'] = api_get_local_time($item['date']);
4291
            $item['start_date_tms'] = api_strtotime($item['date']);
4292
            $item['content'] = $item['text'];
4293
4294
            // we break the date field in the database into a date and a time part
4295
            $agenda_db_date = explode(" ", $item['date']);
4296
            $date = $agenda_db_date[0];
4297
            $time = $agenda_db_date[1];
4298
            // we divide the date part into a day, a month and a year
4299
            $agendadate = explode("-", $item['date']);
4300
            $year = intval($agendadate[0]);
4301
            $month = intval($agendadate[1]);
4302
            $day = intval($agendadate[2]);
4303
            // we divide the time part into hour, minutes, seconds
4304
            $agendatime = explode(":", $time);
4305
4306
            $hour = $agendatime[0];
4307
            $minute = $agendatime[1];
4308
            $second = $agendatime[2];
4309
4310
            if ($type == 'month_view') {
4311
                $item['calendar_type'] = 'personal';
4312
                $item['start_date'] = $item['date'];
4313
                $agendaitems[$day][] = $item;
4314
                continue;
4315
            }
4316
4317
            // if the student has specified a course we a add a link to that course
4318
            if ($item['course'] != "") {
4319
                $url = api_get_path(
4320
                        WEB_CODE_PATH
4321
                    )."calendar/agenda.php?cidReq=".urlencode(
4322
                        $item['course']
4323
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4324
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4325
            } else {
4326
                $course_link = "";
4327
            }
4328
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4329
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4330
            if ($type !== "day_view") {
4331
                // This is the array construction for the WEEK or MONTH view
4332
4333
                //Display events in agenda
4334
                $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 />";
4335
            } else {
4336
                // this is the array construction for the DAY view
4337
                $halfhour = 2 * $agendatime['0'];
4338
                if ($agendatime['1'] >= '30') {
4339
                    $halfhour = $halfhour + 1;
4340
                }
4341
4342
                //Display events by list
4343
                $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>";
4344
            }
4345
        }
4346
4347
        return $agendaitems;
4348
    }
4349
4350
    /**
4351
     * Show the monthcalender of the given month.
4352
     *
4353
     * @param    array    Agendaitems
4354
     * @param    int    Month number
4355
     * @param    int    Year number
4356
     * @param    array    Array of strings containing long week day names (deprecated, you can send an empty array
4357
     *                          instead)
4358
     * @param    string    The month name
4359
     */
4360
    public static function display_mymonthcalendar(
4361
        $user_id,
4362
        $agendaitems,
4363
        $month,
4364
        $year,
4365
        $weekdaynames,
4366
        $monthName,
4367
        $show_content = true
4368
    ) {
4369
        global $DaysShort, $course_path;
4370
        //Handle leap year
4371
        $numberofdays = [
4372
            0,
4373
            31,
4374
            28,
4375
            31,
4376
            30,
4377
            31,
4378
            30,
4379
            31,
4380
            31,
4381
            30,
4382
            31,
4383
            30,
4384
            31,
4385
        ];
4386
        if (($year % 400 == 0) or ($year % 4 == 0 and $year % 100 != 0)) {
4387
            $numberofdays[2] = 29;
4388
        }
4389
        //Get the first day of the month
4390
        $dayone = getdate(mktime(0, 0, 0, $month, 1, $year));
4391
        //Start the week on monday
4392
        $startdayofweek = $dayone['wday'] != 0 ? ($dayone['wday'] - 1) : 6;
4393
        $g_cc = (isset($_GET['courseCode']) ? $_GET['courseCode'] : '');
4394
4395
        $next_month = ($month == 1 ? 12 : $month - 1);
4396
        $prev_month = ($month == 12 ? 1 : $month + 1);
4397
4398
        $next_year = ($month == 1 ? $year - 1 : $year);
4399
        $prev_year = ($month == 12 ? $year + 1 : $year);
4400
4401
        if ($show_content) {
4402
            $back_url = Display::url(
4403
                get_lang('Previous'),
4404
                api_get_self()."?coursePath=".urlencode(
4405
                    $course_path
4406
                )."&courseCode=".Security::remove_XSS(
4407
                    $g_cc
4408
                )."&action=view&view=month&month=".$next_month."&year=".$next_year
4409
            );
4410
            $next_url = Display::url(
4411
                get_lang('Next'),
4412
                api_get_self()."?coursePath=".urlencode(
4413
                    $course_path
4414
                )."&courseCode=".Security::remove_XSS(
4415
                    $g_cc
4416
                )."&action=view&view=month&month=".$prev_month."&year=".$prev_year
4417
            );
4418
        } else {
4419
            $back_url = Display::url(
4420
                get_lang('Previous'),
4421
                '',
4422
                [
4423
                    'onclick' => "load_calendar('".$user_id."','".$next_month."', '".$next_year."'); ",
4424
                    'class' => 'btn ui-button ui-widget ui-state-default',
4425
                ]
4426
            );
4427
            $next_url = Display::url(
4428
                get_lang('Next'),
4429
                '',
4430
                [
4431
                    'onclick' => "load_calendar('".$user_id."','".$prev_month."', '".$prev_year."'); ",
4432
                    'class' => 'pull-right btn ui-button ui-widget ui-state-default',
4433
                ]
4434
            );
4435
        }
4436
        $html = '';
4437
        $html .= '<div class="actions">';
4438
        $html .= '<div class="row">';
4439
        $html .= '<div class="col-md-4">'.$back_url.'</div>';
4440
        $html .= '<div class="col-md-4"><p class="agenda-title text-center">'.$monthName." ".$year.'</p></div>';
4441
        $html .= '<div class="col-md-4">'.$next_url.'</div>';
4442
        $html .= '</div>';
4443
        $html .= '</div>';
4444
        $html .= '<table id="agenda_list2" class="table table-bordered">';
4445
        $html .= '<tr>';
4446
        for ($ii = 1; $ii < 8; $ii++) {
4447
            $html .= '<td class="weekdays">'.$DaysShort[$ii % 7].'</td>';
4448
        }
4449
        $html .= '</tr>';
4450
4451
        $curday = -1;
4452
        $today = getdate();
4453
        while ($curday <= $numberofdays[$month]) {
4454
            $html .= "<tr>";
4455
            for ($ii = 0; $ii < 7; $ii++) {
4456
                if (($curday == -1) && ($ii == $startdayofweek)) {
4457
                    $curday = 1;
4458
                }
4459
                if (($curday > 0) && ($curday <= $numberofdays[$month])) {
4460
                    $bgcolor = $class = 'class="days_week"';
4461
                    $dayheader = Display::div(
4462
                        $curday,
4463
                        ['class' => 'agenda_day']
4464
                    );
4465
                    if (($curday == $today['mday']) && ($year == $today['year']) && ($month == $today['mon'])) {
4466
                        $class = "class=\"days_today\" style=\"width:10%;\"";
4467
                    }
4468
4469
                    $html .= "<td ".$class.">".$dayheader;
4470
4471
                    if (!empty($agendaitems[$curday])) {
4472
                        $items = $agendaitems[$curday];
4473
                        $items = msort($items, 'start_date_tms');
4474
4475
                        foreach ($items as $value) {
4476
                            $value['title'] = Security::remove_XSS(
4477
                                $value['title']
4478
                            );
4479
                            $start_time = api_format_date(
4480
                                $value['start_date'],
4481
                                TIME_NO_SEC_FORMAT
4482
                            );
4483
                            $end_time = '';
4484
4485
                            if (!empty($value['end_date'])) {
4486
                                $end_time = '-&nbsp;<i>'.api_format_date(
4487
                                        $value['end_date'],
4488
                                        DATE_TIME_FORMAT_LONG
4489
                                    ).'</i>';
4490
                            }
4491
                            $complete_time = '<i>'.api_format_date(
4492
                                    $value['start_date'],
4493
                                    DATE_TIME_FORMAT_LONG
4494
                                ).'</i>&nbsp;'.$end_time;
4495
                            $time = '<i>'.$start_time.'</i>';
4496
4497
                            switch ($value['calendar_type']) {
4498
                                case 'personal':
4499
                                    $bg_color = '#D0E7F4';
4500
                                    $icon = Display::return_icon(
4501
                                        'user.png',
4502
                                        get_lang('MyAgenda'),
4503
                                        [],
4504
                                        ICON_SIZE_SMALL
4505
                                    );
4506
                                    break;
4507
                                case 'global':
4508
                                    $bg_color = '#FFBC89';
4509
                                    $icon = Display::return_icon(
4510
                                        'view_remove.png',
4511
                                        get_lang('GlobalEvent'),
4512
                                        [],
4513
                                        ICON_SIZE_SMALL
4514
                                    );
4515
                                    break;
4516
                                case 'course':
4517
                                    $bg_color = '#CAFFAA';
4518
                                    $icon_name = 'course.png';
4519
                                    if (!empty($value['session_id'])) {
4520
                                        $icon_name = 'session.png';
4521
                                    }
4522
                                    if ($show_content) {
4523
                                        $icon = Display::url(
4524
                                            Display::return_icon(
4525
                                                $icon_name,
4526
                                                $value['course_name'].' '.get_lang(
4527
                                                    'Course'
4528
                                                ),
4529
                                                [],
4530
                                                ICON_SIZE_SMALL
4531
                                            ),
4532
                                            $value['url']
4533
                                        );
4534
                                    } else {
4535
                                        $icon = Display::return_icon(
4536
                                            $icon_name,
4537
                                            $value['course_name'].' '.get_lang(
4538
                                                'Course'
4539
                                            ),
4540
                                            [],
4541
                                            ICON_SIZE_SMALL
4542
                                        );
4543
                                    }
4544
                                    break;
4545
                                default:
4546
                                    break;
4547
                            }
4548
4549
                            $result = '<div class="rounded_div_agenda" style="background-color:'.$bg_color.';">';
4550
4551
                            if ($show_content) {
4552
                                //Setting a personal event to green
4553
                                $icon = Display::div(
4554
                                    $icon,
4555
                                    ['style' => 'float:right']
4556
                                );
4557
4558
                                $link = $value['calendar_type'].'_'.$value['id'].'_'.$value['course_id'].'_'.$value['session_id'];
4559
4560
                                //Link to bubble
4561
                                $url = Display::url(
4562
                                    cut($value['title'], 40),
4563
                                    '#',
4564
                                    ['id' => $link, 'class' => 'opener']
4565
                                );
4566
                                $result .= $time.' '.$icon.' '.Display::div(
4567
                                        $url
4568
                                    );
4569
4570
                                //Hidden content
4571
                                $content = Display::div(
4572
                                    $icon.Display::tag(
4573
                                        'h2',
4574
                                        $value['course_name']
4575
                                    ).'<hr />'.Display::tag(
4576
                                        'h3',
4577
                                        $value['title']
4578
                                    ).$complete_time.'<hr />'.Security::remove_XSS(
4579
                                        $value['content']
4580
                                    )
4581
                                );
4582
4583
                                //Main div
4584
                                $result .= Display::div(
4585
                                    $content,
4586
                                    [
4587
                                        'id' => 'main_'.$link,
4588
                                        'class' => 'dialog',
4589
                                        'style' => 'display:none',
4590
                                    ]
4591
                                );
4592
                                $result .= '</div>';
4593
                                $html .= $result;
4594
                            } else {
4595
                                $html .= $result .= $icon.'</div>';
4596
                            }
4597
                        }
4598
                    }
4599
                    $html .= "</td>";
4600
                    $curday++;
4601
                } else {
4602
                    $html .= "<td></td>";
4603
                }
4604
            }
4605
            $html .= "</tr>";
4606
        }
4607
        $html .= "</table>";
4608
        echo $html;
4609
    }
4610
4611
    /**
4612
     * Get personal agenda items between two dates (=all events from all registered courses).
4613
     *
4614
     * @param int $user_id user ID of the user
4615
     * @param    string    Optional start date in datetime format (if no start date is given, uses today)
4616
     * @param    string    Optional end date in datetime format (if no date is given, uses one year from now)
4617
     *
4618
     * @return array array of events ordered by start date, in
4619
     *               [0]('datestart','dateend','title'),[1]('datestart','dateend','title','link','coursetitle') format,
4620
     *               where datestart and dateend are in yyyyMMddhhmmss format
4621
     *
4622
     * @deprecated use agenda events
4623
     */
4624
    public static function get_personal_agenda_items_between_dates(
4625
        $user_id,
4626
        $date_start = '',
4627
        $date_end = ''
4628
    ) {
4629
        $items = [];
4630
        if ($user_id != strval(intval($user_id))) {
4631
            return $items;
4632
        }
4633
        if (empty($date_start)) {
4634
            $date_start = date('Y-m-d H:i:s');
4635
        }
4636
        if (empty($date_end)) {
4637
            $date_end = date(
4638
                'Y-m-d H:i:s',
4639
                mktime(0, 0, 0, date("m"), date("d"), date("Y") + 1)
4640
            );
4641
        }
4642
        $expr = '/\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}/';
4643
        if (!preg_match($expr, $date_start)) {
4644
            return $items;
4645
        }
4646
        if (!preg_match($expr, $date_end)) {
4647
            return $items;
4648
        }
4649
4650
        // get agenda-items for every course
4651
        $courses = api_get_user_courses($user_id, false);
4652
        foreach ($courses as $id => $course) {
4653
            $c = api_get_course_info_by_id($course['real_id']);
4654
            //databases of the courses
4655
            $t_a = Database::get_course_table(TABLE_AGENDA, $course['db']);
4656
            $t_ip = Database::get_course_table(
4657
                TABLE_ITEM_PROPERTY,
4658
                $course['db']
4659
            );
4660
            // get the groups to which the user belong
4661
            $group_memberships = GroupManager::get_group_ids(
4662
                $course['db'],
4663
                $user_id
4664
            );
4665
            // if the user is administrator of that course we show all the agenda items
4666
            if ($course['status'] == '1') {
4667
                //echo "course admin";
4668
                $sqlquery = "SELECT ".
4669
                    " DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4670
                    " FROM ".$t_a." agenda, ".
4671
                    $t_ip." ip ".
4672
                    " WHERE agenda.id = ip.ref ".
4673
                    " AND agenda.start_date>='$date_start' ".
4674
                    " AND agenda.end_date<='$date_end' ".
4675
                    " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4676
                    " AND ip.visibility='1' ".
4677
                    " GROUP BY agenda.id ".
4678
                    " ORDER BY start_date ";
4679
            } else {
4680
                // if the user is not an administrator of that course, then...
4681
                if (is_array($group_memberships) && count(
4682
                        $group_memberships
4683
                    ) > 0
4684
                ) {
4685
                    $sqlquery = "SELECT ".
4686
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4687
                        " FROM ".$t_a." agenda, ".
4688
                        $t_ip." ip ".
4689
                        " WHERE agenda.id = ip.ref ".
4690
                        " AND agenda.start_date>='$date_start' ".
4691
                        " AND agenda.end_date<='$date_end' ".
4692
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4693
                        " AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4694
                            ", ",
4695
                            $group_memberships
4696
                        ).")) ) ".
4697
                        " AND ip.visibility='1' ".
4698
                        " ORDER BY start_date ";
4699
                } else {
4700
                    $sqlquery = "SELECT ".
4701
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4702
                        " FROM ".$t_a." agenda, ".
4703
                        $t_ip." ip ".
4704
                        " WHERE agenda.id = ip.ref ".
4705
                        " AND agenda.start_date>='$date_start' ".
4706
                        " AND agenda.end_date<='$date_end' ".
4707
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4708
                        " AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL) ".
4709
                        " AND ip.visibility='1' ".
4710
                        " ORDER BY start_date ";
4711
                }
4712
            }
4713
4714
            $result = Database::query($sqlquery);
4715
            while ($item = Database::fetch_array($result)) {
4716
                $agendaday = date("j", strtotime($item['start_date']));
4717
                $month = date("n", strtotime($item['start_date']));
4718
                $year = date("Y", strtotime($item['start_date']));
4719
                $URL = api_get_path(
4720
                        WEB_PATH
4721
                    )."main/calendar/agenda.php?cidReq=".urlencode(
4722
                        $course["code"]
4723
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4724
                list($year, $month, $day, $hour, $min, $sec) = explode(
4725
                    '[-: ]',
4726
                    $item['start_date']
4727
                );
4728
                $start_date = $year.$month.$day.$hour.$min;
4729
                list($year, $month, $day, $hour, $min, $sec) = explode(
4730
                    '[-: ]',
4731
                    $item['end_date']
4732
                );
4733
                $end_date = $year.$month.$day.$hour.$min;
4734
4735
                $items[] = [
4736
                    'datestart' => $start_date,
4737
                    'dateend' => $end_date,
4738
                    'title' => $item['title'],
4739
                    'link' => $URL,
4740
                    'coursetitle' => $c['name'],
4741
                ];
4742
            }
4743
        }
4744
4745
        return $items;
4746
    }
4747
4748
    /**
4749
     * This function calculates the startdate of the week (monday)
4750
     * and the enddate of the week (sunday)
4751
     * and returns it as an array.
4752
     */
4753
    public static function calculate_start_end_of_week($week_number, $year)
4754
    {
4755
        // determine the start and end date
4756
        // step 1: we calculate a timestamp for a day in this week
4757
        $random_day_in_week = mktime(
4758
                0,
4759
                0,
4760
                0,
4761
                1,
4762
                1,
4763
                $year
4764
            ) + ($week_number) * (7 * 24 * 60 * 60); // we calculate a random day in this week
4765
        // step 2: we which day this is (0=sunday, 1=monday, ...)
4766
        $number_day_in_week = date('w', $random_day_in_week);
4767
        // step 3: we calculate the timestamp of the monday of the week we are in
4768
        $start_timestamp = $random_day_in_week - (($number_day_in_week - 1) * 24 * 60 * 60);
4769
        // step 4: we calculate the timestamp of the sunday of the week we are in
4770
        $end_timestamp = $random_day_in_week + ((7 - $number_day_in_week + 1) * 24 * 60 * 60) - 3600;
4771
        // step 5: calculating the start_day, end_day, start_month, end_month, start_year, end_year
4772
        $start_day = date('j', $start_timestamp);
4773
        $start_month = date('n', $start_timestamp);
4774
        $start_year = date('Y', $start_timestamp);
4775
        $end_day = date('j', $end_timestamp);
4776
        $end_month = date('n', $end_timestamp);
4777
        $end_year = date('Y', $end_timestamp);
4778
        $start_end_array['start']['day'] = $start_day;
4779
        $start_end_array['start']['month'] = $start_month;
4780
        $start_end_array['start']['year'] = $start_year;
4781
        $start_end_array['end']['day'] = $end_day;
4782
        $start_end_array['end']['month'] = $end_month;
4783
        $start_end_array['end']['year'] = $end_year;
4784
4785
        return $start_end_array;
4786
    }
4787
4788
    /**
4789
     * @return bool
4790
     */
4791
    public function getIsAllowedToEdit()
4792
    {
4793
        return $this->isAllowedToEdit;
4794
    }
4795
4796
    /**
4797
     * @param bool $isAllowedToEdit
4798
     */
4799
    public function setIsAllowedToEdit($isAllowedToEdit)
4800
    {
4801
        $this->isAllowedToEdit = $isAllowedToEdit;
4802
    }
4803
4804
    /**
4805
     * Format needed for the Fullcalendar js lib.
4806
     *
4807
     * @param string $utcTime
4808
     *
4809
     * @return bool|string
4810
     */
4811
    public function formatEventDate($utcTime)
4812
    {
4813
        if ($utcTime instanceof DateTime) {
4814
            $eventDate = $utcTime;
4815
        } else {
4816
            $utcTimeZone = new DateTimeZone('UTC');
4817
            $eventDate = new DateTime($utcTime, $utcTimeZone);
4818
        }
4819
4820
        $platformTimeZone = new DateTimeZone(api_get_timezone());
4821
4822
        $eventDate->setTimezone($platformTimeZone);
4823
4824
        return $eventDate->format(DateTime::ISO8601);
4825
    }
4826
4827
    /**
4828
     * @throws \Doctrine\ORM\OptimisticLockException
4829
     * @throws \Doctrine\ORM\ORMException
4830
     * @throws \Doctrine\ORM\TransactionRequiredException
4831
     */
4832
    public static function saveCollectiveProperties(array $inviteeUserList, bool $isCollective, int $eventId)
4833
    {
4834
        $em = Database::getManager();
4835
4836
        $event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
4837
4838
        $invitation = new AgendaEventInvitation();
4839
        $invitation->setCreator(api_get_user_entity(api_get_user_id()));
4840
4841
        $event
4842
            ->setCollective($isCollective)
4843
            ->setInvitation($invitation)
4844
        ;
4845
4846
        $em->persist($event);
4847
4848
        foreach ($inviteeUserList as $inviteeId) {
4849
            $invitee = new AgendaEventInvitee();
4850
            $invitee
4851
                ->setUser(api_get_user_entity($inviteeId))
4852
                ->setInvitation($invitation)
4853
            ;
4854
4855
            $em->persist($invitee);
4856
        }
4857
4858
        $em->flush();
4859
    }
4860
4861
    public static function getJsForReminders(string $cssSelectorBtnAdd): string
4862
    {
4863
        return '
4864
            var template = \'<div class="form-group">\' +
4865
                \'<div class="col-sm-offset-2 col-sm-3">\' +
4866
                \'<input min="0" step="1" id="notification_count[]" type="number" class=" form-control" name="notification_count[]">\' +
4867
                \'</div>\' +
4868
                \'<div class="col-sm-3">\' +
4869
                \'<select class="form-control" name="notification_period[]" id="form_notification_period[]">\' +
4870
                \'<option value="i">'.get_lang('Minutes').'</option>\' +
4871
                \'<option value="h">'.get_lang('Hours').'</option>\' +
4872
                \'<option value="d">'.get_lang('Days').'</option>\' +
4873
                \'</select>\' +
4874
                \'</div>\' +
4875
                \'<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>\' +
4876
                \'<div class="text-right col-sm-2">\' +
4877
                \'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>\' +
4878
                \'</div>\' +
4879
                \'</div>\';
4880
4881
            $("'.$cssSelectorBtnAdd.'").on("click", function (e) {
4882
                e.preventDefault();
4883
4884
                $(template).appendTo("#notification_list");
4885
                $("#notification_list select").selectpicker("refresh");
4886
            });
4887
4888
            $("#notification_list").on("click", ".delete-notification", function (e) {
4889
                e.preventDefault();
4890
4891
                $(this).parents(".form-group").remove();
4892
            });';
4893
    }
4894
4895
    public static function returnGoogleCalendarUrl(int $userId): ?string
4896
    {
4897
        $extraFieldInfo = UserManager::get_extra_user_data_by_field($userId, 'google_calendar_url');
4898
4899
        if (empty($extraFieldInfo) || empty($extraFieldInfo['google_calendar_url'])) {
4900
            return null;
4901
        }
4902
4903
        return $extraFieldInfo['google_calendar_url'];
4904
    }
4905
4906
    public static function returnFullCalendarExtraSettings(): ?string
4907
    {
4908
        $settings = api_get_configuration_value('fullcalendar_settings');
4909
4910
        if (empty($settings) || empty($settings['settings'])) {
4911
            return null;
4912
        }
4913
4914
        $encoded = json_encode($settings['settings']);
4915
4916
        return substr($encoded, 1, -1).',';
4917
    }
4918
4919
    public static function returnOnHoverInfo()
4920
    {
4921
        $onHoverInfo = api_get_configuration_value('agenda_on_hover_info');
4922
4923
        if (!empty($onHoverInfo)) {
4924
            return $onHoverInfo['options'];
4925
        }
4926
4927
        return [
4928
            'comment' => true,
4929
            'description' => true,
4930
        ];
4931
    }
4932
4933
    private function editReminders(int $eventId, array $reminderList = [])
4934
    {
4935
        if (false === api_get_configuration_value('agenda_reminders')) {
4936
            return;
4937
        }
4938
4939
        $eventReminders = $this->parseEventReminders(
4940
            $this->getEventReminders($eventId)
4941
        );
4942
        $eventIntervalList = array_column($eventReminders, 'date_interval');
4943
4944
        foreach ($eventIntervalList as $eventIntervalInfo) {
4945
            if (!in_array($eventIntervalInfo, $reminderList)) {
4946
                $this->removeReminders($eventId, $eventIntervalInfo[0], $eventIntervalInfo[1]);
4947
            }
4948
        }
4949
4950
        foreach ($reminderList as $reminderInfo) {
4951
            if (!in_array($reminderInfo, $eventIntervalList)) {
4952
                $this->addReminder($eventId, $reminderInfo[0], $reminderInfo[1]);
4953
            }
4954
        }
4955
    }
4956
4957
    private static function isUserInvitedInEvent(int $id, int $userId): bool
4958
    {
4959
        $user = api_get_user_entity($userId);
4960
4961
        $event = Database::getManager()
4962
            ->getRepository('ChamiloCoreBundle:PersonalAgenda')
4963
            ->findOneByIdAndInvitee($id, $user)
4964
        ;
4965
4966
        return null !== $event;
4967
    }
4968
4969
    private function loadEventsAsInvitee(User $user, ?DateTime $startDate, ?DateTime $endDate)
4970
    {
4971
        $em = Database::getManager();
4972
        $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
4973
        $events = $eventRepo->getEventsForInvitee($user, $startDate, $endDate);
4974
4975
        foreach ($events as $event) {
4976
            $eventInfo = [];
4977
            $eventInfo['id'] = 'personal_'.$event->getId();
4978
            $eventInfo['title'] = $event->getTitle();
4979
            $eventInfo['className'] = 'personal';
4980
            $eventInfo['borderColor'] = $eventInfo['backgroundColor'] = $this->event_personal_color;
4981
            $eventInfo['editable'] = $event->isCollective();
4982
            $eventInfo['sent_to'] = get_lang('Me');
4983
            $eventInfo['type'] = 'personal';
4984
4985
            if ($event->getDate()) {
4986
                $eventInfo['start'] = $this->formatEventDate($event->getDate()->format('Y-m-d H:i:s'));
4987
                $eventInfo['start_date_localtime'] = api_get_local_time($event->getDate());
4988
            }
4989
4990
            if ($event->getEnddate()) {
4991
                $eventInfo['end'] = $this->formatEventDate($event->getEnddate()->format('Y-m-d H:i:s'));
4992
                $eventInfo['end_date_localtime'] = api_get_local_time($event->getEnddate());
4993
            }
4994
4995
            $eventInfo['description'] = $event->getText();
4996
            $eventInfo['allDay'] = $event->getAllDay();
4997
            $eventInfo['parent_event_id'] = 0;
4998
            $eventInfo['has_children'] = 0;
4999
            $eventInfo['collective'] = $event->isCollective();
5000
            $eventInfo['invitees'] = [];
5001
5002
            $invitation = $event->getInvitation();
5003
5004
            if ($invitation) {
5005
                foreach ($invitation->getInvitees() as $invitee) {
5006
                    $inviteeUser = $invitee->getUser();
5007
5008
                    $eventInfo['invitees'][] = [
5009
                        'id' => $inviteeUser->getId(),
5010
                        'name' => $inviteeUser->getCompleteNameWithUsername(),
5011
                    ];
5012
                }
5013
            }
5014
5015
            $this->events[] = $eventInfo;
5016
        }
5017
    }
5018
5019
    /**
5020
     * @throws Exception
5021
     */
5022
    private function convertSessionWithDuration(int $userId, array $sessionInfo, DateTime $start, DateTime $end): array
5023
    {
5024
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
5025
            $sessionInfo['session_id'],
5026
            $userId
5027
        );
5028
5029
        if (empty($courseAccess)) {
5030
            throw new Exception();
5031
        }
5032
5033
        $firstAccessDate = new DateTime($courseAccess['login_course_date'], new DateTimeZone('UTC'));
5034
        $lastAccessDate = clone $firstAccessDate;
5035
        $lastAccessDate->modify('+'.$sessionInfo['duration'].' days');
5036
5037
        if ($firstAccessDate->format('Y-m-d H:i:s') > $start
5038
            && $lastAccessDate->format('Y-m-d H:i:s') < $end
5039
        ) {
5040
            throw new Exception();
5041
        }
5042
5043
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5044
        $firstCourse = current($courseList);
5045
5046
        return [
5047
            'id' => 'session_'.$sessionInfo['id'],
5048
            'session_id' => $sessionInfo['id'],
5049
            'title' => $sessionInfo['name'],
5050
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5051
            'className' => 'personal',
5052
            'borderColor' => $this->event_personal_color,
5053
            'backgroundColor' => $this->event_personal_color,
5054
            'editable' => false,
5055
            'sent_to' => get_lang('Me'),
5056
            'type' => 'session',
5057
            'start' => $firstAccessDate->format(DateTime::ISO8601),
5058
            'start_date_localtime' => api_get_local_time($firstAccessDate),
5059
            'end' => $lastAccessDate->format(DateTime::ISO8601),
5060
            'end_date_localtime' => api_get_local_time($lastAccessDate),
5061
            'allDay' => 0,
5062
            'parent_event_id' => 0,
5063
            'has_children' => 0,
5064
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5065
        ];
5066
    }
5067
5068
    /**
5069
     * @throws Exception
5070
     */
5071
    private function convertSessionWithDates(array $sessionInfo, DateTime $start, DateTime $end): array
5072
    {
5073
        if ($sessionInfo['display_start_date'] < $start
5074
            && $sessionInfo['display_end_date'] > $end
5075
        ) {
5076
            throw new Exception();
5077
        }
5078
5079
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5080
        $firstCourse = current($courseList);
5081
5082
        return [
5083
            'id' => 'session_'.$sessionInfo['id'],
5084
            'session_id' => $sessionInfo['id'],
5085
            'title' => $sessionInfo['name'],
5086
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5087
            'className' => 'personal',
5088
            'borderColor' => $this->event_personal_color,
5089
            'backgroundColor' => $this->event_personal_color,
5090
            'editable' => false,
5091
            'sent_to' => get_lang('Me'),
5092
            'type' => 'session_subscription',
5093
            'start' => $sessionInfo['display_start_date'],
5094
            'start_date_localtime' => $sessionInfo['display_start_date']
5095
                ? $this->formatEventDate($sessionInfo['display_start_date'])
5096
                : '',
5097
            'end' => $sessionInfo['display_end_date'],
5098
            'end_date_localtime' => $sessionInfo['display_end_date']
5099
                ? $this->formatEventDate($sessionInfo['display_end_date'])
5100
                : '',
5101
            'allDay' => 0,
5102
            'parent_event_id' => 0,
5103
            'has_children' => 0,
5104
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5105
        ];
5106
    }
5107
5108
    private function loadSessionsAsEvents(int $start, int $end)
5109
    {
5110
        if (false === api_get_configuration_value('personal_calendar_show_sessions_occupation')) {
5111
            return;
5112
        }
5113
5114
        $start = api_get_utc_datetime($start, false, true);
5115
        $end = api_get_utc_datetime($end, false, true);
5116
        $userInfo = api_get_user_info();
5117
        $sessionList = SessionManager::getSessionsFollowedByUser($userInfo['id'], $userInfo['status']);
5118
5119
        foreach ($sessionList as $sessionInfo) {
5120
            if (!empty($sessionInfo['duration'])) {
5121
                try {
5122
                    $this->events[] = $this->convertSessionWithDuration($userInfo['id'], $sessionInfo, $start, $end);
5123
                } catch (Exception $e) {
5124
                    continue;
5125
                }
5126
5127
                continue;
5128
            }
5129
5130
            if (empty($sessionInfo['display_start_date']) || empty($sessionInfo['display_end_date'])) {
5131
                continue;
5132
            }
5133
5134
            try {
5135
                $this->events[] = $this->convertSessionWithDates($sessionInfo, $start, $end);
5136
            } catch (Exception $e) {
5137
                continue;
5138
            }
5139
        }
5140
    }
5141
}
5142