Passed
Pull Request — 1.11.x (#4109)
by Angel Fernando Quiroz
11:30
created

Agenda::calculate_start_end_of_week()   A

Complexity

Conditions 1

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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