Passed
Push — master ( cc68cc...50453a )
by Julito
09:11
created

Agenda::hasChildren()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 2
dl 0
loc 18
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\PersonalAgenda;
6
use Chamilo\CoreBundle\Entity\SysCalendar;
7
use Chamilo\CoreBundle\Framework\Container;
8
use Chamilo\CourseBundle\Entity\CCalendarEvent;
9
use Chamilo\CourseBundle\Entity\CCalendarEventAttachment;
10
use Chamilo\CourseBundle\Entity\CGroup;
11
use Symfony\Component\HttpFoundation\File\UploadedFile;
12
13
/**
14
 * Class Agenda.
15
 *
16
 * @author: Julio Montoya <[email protected]>
17
 */
18
class Agenda
19
{
20
    public $events = [];
21
    /** @var string Current type */
22
    public $type = 'personal';
23
    public $types = ['personal', 'admin', 'course'];
24
    public $sessionId = 0;
25
    public $senderId;
26
    /** @var array */
27
    public $course;
28
    /** @var string */
29
    public $comment;
30
    public $eventStudentPublicationColor;
31
    /** @var array */
32
    private $sessionInfo;
33
    /** @var bool */
34
    private $isAllowedToEdit;
35
36
    /**
37
     * Constructor.
38
     *
39
     * @param string $type
40
     * @param int    $senderId  Optional The user sender ID
41
     * @param int    $courseId  Optional. The course ID
42
     * @param int    $sessionId Optional The session ID
43
     */
44
    public function __construct(
45
        $type,
46
        $senderId = 0,
47
        $courseId = 0,
48
        $sessionId = 0
49
    ) {
50
        // Table definitions
51
        $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
52
        $this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
53
        $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
54
        $this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
55
56
        $this->setType($type);
57
        $this->setSenderId($senderId ?: api_get_user_id());
58
        $isAllowToEdit = false;
59
60
        switch ($type) {
61
            case 'course':
62
                $sessionId = $sessionId ?: api_get_session_id();
63
                $sessionInfo = api_get_session_info($sessionId);
64
                $this->setSessionId($sessionId);
65
                $this->setSessionInfo($sessionInfo);
66
67
                // Setting the course object if we are in a course
68
                $courseInfo = api_get_course_info_by_id($courseId);
69
                if (!empty($courseInfo)) {
70
                    $this->set_course($courseInfo);
71
                }
72
73
                // Check if teacher/admin rights.
74
                $isAllowToEdit = api_is_allowed_to_edit(false, true);
75
                // Check course setting.
76
                if ('1' === api_get_course_setting('allow_user_edit_agenda')
77
                    && api_is_allowed_in_course()
78
                ) {
79
                    $isAllowToEdit = true;
80
                }
81
82
                $groupId = api_get_group_id();
83
                if (!empty($groupId)) {
84
                    $groupInfo = GroupManager::get_group_properties($groupId);
85
                    $userHasAccess = GroupManager::user_has_access(
86
                        api_get_user_id(),
87
                        $groupInfo['iid'],
88
                        GroupManager::GROUP_TOOL_CALENDAR
89
                    );
90
                    $isTutor = GroupManager::is_tutor_of_group(
91
                        api_get_user_id(),
92
                        $groupInfo
93
                    );
94
95
                    $isGroupAccess = $userHasAccess || $isTutor;
96
                    $isAllowToEdit = false;
97
                    if ($isGroupAccess) {
98
                        $isAllowToEdit = true;
99
                    }
100
                }
101
102
                if (!empty($sessionId)) {
103
                    $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
104
                    if ($allowDhrToEdit) {
105
                        $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
106
                        if ($isHrm) {
107
                            $isAllowToEdit = true;
108
                        }
109
                    }
110
                }
111
                break;
112
            case 'admin':
113
                $isAllowToEdit = api_is_platform_admin();
114
                break;
115
            case 'personal':
116
                $isAllowToEdit = !api_is_anonymous();
117
                break;
118
        }
119
120
        $this->setIsAllowedToEdit($isAllowToEdit);
121
        $this->events = [];
122
        $agendaColors = array_merge(
123
            [
124
                'platform' => 'red', //red
125
                'course' => '#458B00', //green
126
                'group' => '#A0522D', //siena
127
                'session' => '#00496D', // kind of green
128
                'other_session' => '#999', // kind of green
129
                'personal' => 'steel blue', //steel blue
130
                'student_publication' => '#FF8C00', //DarkOrange
131
            ],
132
            api_get_configuration_value('agenda_colors') ?: []
133
        );
134
135
        // Event colors
136
        $this->event_platform_color = $agendaColors['platform'];
137
        $this->event_course_color = $agendaColors['course'];
138
        $this->event_group_color = $agendaColors['group'];
139
        $this->event_session_color = $agendaColors['session'];
140
        $this->eventOtherSessionColor = $agendaColors['other_session'];
141
        $this->event_personal_color = $agendaColors['personal'];
142
        $this->eventStudentPublicationColor = $agendaColors['student_publication'];
143
    }
144
145
    /**
146
     * @param int $senderId
147
     */
148
    public function setSenderId($senderId)
149
    {
150
        $this->senderId = (int) $senderId;
151
    }
152
153
    /**
154
     * @return int
155
     */
156
    public function getSenderId()
157
    {
158
        return $this->senderId;
159
    }
160
161
    /**
162
     * @param string $type can be 'personal', 'admin'  or  'course'
163
     */
164
    public function setType($type)
165
    {
166
        $typeList = $this->getTypes();
167
        if (in_array($type, $typeList)) {
168
            $this->type = $type;
169
        }
170
    }
171
172
    /**
173
     * Returns the type previously set (and filtered) through setType
174
     * If setType() was not called, then type defaults to "personal" as
175
     * set in the class definition.
176
     */
177
    public function getType()
178
    {
179
        if (isset($this->type)) {
180
            return $this->type;
181
        }
182
    }
183
184
    /**
185
     * @param int $id
186
     */
187
    public function setSessionId($id)
188
    {
189
        $this->sessionId = (int) $id;
190
    }
191
192
    /**
193
     * @param array $sessionInfo
194
     */
195
    public function setSessionInfo($sessionInfo)
196
    {
197
        $this->sessionInfo = $sessionInfo;
198
    }
199
200
    /**
201
     * @return int $id
202
     */
203
    public function getSessionId()
204
    {
205
        return $this->sessionId;
206
    }
207
208
    /**
209
     * @param array $courseInfo
210
     */
211
    public function set_course($courseInfo)
212
    {
213
        $this->course = $courseInfo;
214
    }
215
216
    /**
217
     * @return array
218
     */
219
    public function getTypes()
220
    {
221
        return $this->types;
222
    }
223
224
    /**
225
     * Adds an event to the calendar.
226
     *
227
     * @param string         $start                 datetime format: 2012-06-14 09:00:00 in local time
228
     * @param string         $end                   datetime format: 2012-06-14 09:00:00 in local time
229
     * @param string         $allDay                (true, false)
230
     * @param string         $title
231
     * @param string         $content
232
     * @param array          $usersToSend           array('everyone') or a list of user/group ids
233
     * @param bool           $addAsAnnouncement     event as a *course* announcement
234
     * @param int            $parentEventId
235
     * @param UploadedFile[] $attachmentArray       array of $_FILES['']
236
     * @param array          $attachmentCommentList
237
     * @param string         $eventComment
238
     * @param string         $color
239
     *
240
     * @return int
241
     */
242
    public function addEvent(
243
        $start,
244
        $end,
245
        $allDay,
246
        $title,
247
        $content,
248
        $usersToSend = [],
249
        $addAsAnnouncement = false,
250
        $parentEventId = null,
251
        $attachmentArray = [],
252
        $attachmentCommentList = [],
253
        $eventComment = null,
254
        $color = ''
255
    ) {
256
        $start = api_get_utc_datetime($start, false, true);
257
        $end = api_get_utc_datetime($end, false, true);
258
        $allDay = isset($allDay) && 'true' === $allDay ? 1 : 0;
259
        $id = null;
260
261
        $em = Database::getManager();
262
        switch ($this->type) {
263
            case 'personal':
264
                $event = new PersonalAgenda();
265
                $event
266
                    ->setTitle($title)
267
                    ->setText($content)
268
                    ->setDate($start)
269
                    ->setEndDate($end)
270
                    ->setAllDay($allDay)
271
                    ->setColor($color)
272
                    ->setUser(api_get_user_entity())
273
                ;
274
                $em->persist($event);
275
                $em->flush();
276
                $id = $event->getId();
277
                break;
278
            case 'course':
279
                $sessionId = $this->getSessionId();
280
                $sessionEntity = api_get_session_entity($sessionId);
281
                $courseEntity = api_get_course_entity($this->course['real_id']);
282
                $groupEntity = api_get_group_entity(api_get_group_id());
283
284
                $event = new CCalendarEvent();
285
                $event
286
                    ->setTitle($title)
287
                    ->setContent($content)
288
                    ->setStartDate($start)
289
                    ->setEndDate($end)
290
                    ->setAllDay($allDay)
291
                    ->setColor($color)
292
                    ->setComment($eventComment)
293
                ;
294
295
                if (!empty($parentEventId)) {
296
                    $repo = Container::getCalendarEventRepository();
297
                    $parentEvent = $repo->find($parentEventId);
298
                    $event->setParentEvent($parentEvent);
299
                }
300
301
                $event->setParent($courseEntity);
302
303
                if (!empty($usersToSend)) {
304
                    $sendTo = $this->parseSendToArray($usersToSend);
305
                    if ($sendTo['everyone']) {
306
                        $event->addCourseLink($courseEntity, $sessionEntity, $groupEntity);
307
                    } else {
308
                        // Storing the selected groups
309
                        if (!empty($sendTo['groups'])) {
310
                            foreach ($sendTo['groups'] as $group) {
311
                                $groupInfo = null;
312
                                if ($group) {
313
                                    $groupInfo = api_get_group_entity($group);
314
                                    $event->addCourseLink($courseEntity, $sessionEntity, $groupInfo);
315
                                }
316
                            }
317
                        }
318
319
                        // storing the selected users
320
                        if (!empty($sendTo['users'])) {
321
                            foreach ($sendTo['users'] as $userId) {
322
                                $event->addUserLink(
323
                                    api_get_user_entity($userId),
324
                                    $courseEntity,
325
                                    $sessionEntity,
326
                                    $groupEntity
327
                                );
328
                            }
329
                        }
330
                    }
331
                }
332
333
                $em->persist($event);
334
                $em->flush();
335
                $id = $event->getIid();
336
337
                if ($id) {
338
                    // Add announcement.
339
                    if ($addAsAnnouncement) {
340
                        $this->storeAgendaEventAsAnnouncement($id, $usersToSend);
341
                    }
342
343
                    // Add attachment.
344
                    if (!empty($attachmentArray)) {
345
                        $counter = 0;
346
                        foreach ($attachmentArray as $attachmentItem) {
347
                            $this->addAttachment(
348
                                $event,
349
                                $attachmentItem,
350
                                $attachmentCommentList[$counter],
351
                                $this->course
352
                            );
353
                            $counter++;
354
                        }
355
                    }
356
                }
357
                break;
358
            case 'admin':
359
                if (api_is_platform_admin()) {
360
                    $event = new SysCalendar();
361
                    $event
362
                        ->setTitle($title)
363
                        ->setContent($content)
364
                        ->setStartDate($start)
365
                        ->setEndDate($end)
366
                        ->setAllDay($allDay)
367
                        ->setAccessUrlId(api_get_current_access_url_id())
368
                    ;
369
                    $em->persist($event);
370
                    $em->flush();
371
                    $id = $event->getId();
372
                }
373
                break;
374
        }
375
376
        return $id;
377
    }
378
379
    /**
380
     * @param string $type
381
     * @param string $startEvent      in UTC
382
     * @param string $endEvent        in UTC
383
     * @param string $repeatUntilDate in UTC
384
     *
385
     * @throws Exception
386
     *
387
     * @return array
388
     */
389
    public function generateDatesByType($type, $startEvent, $endEvent, $repeatUntilDate)
390
    {
391
        $continue = true;
392
        $repeatUntilDate = new DateTime($repeatUntilDate, new DateTimeZone('UTC'));
393
        $loopMax = 365;
394
        $counter = 0;
395
        $list = [];
396
397
        switch ($type) {
398
            case 'daily':
399
                $interval = 'P1D';
400
                break;
401
            case 'weekly':
402
                $interval = 'P1W';
403
                break;
404
            case 'monthlyByDate':
405
                $interval = 'P1M';
406
                break;
407
            case 'monthlyByDay':
408
            case 'monthlyByDayR':
409
                // not yet implemented
410
                break;
411
            case 'yearly':
412
                $interval = 'P1Y';
413
                break;
414
        }
415
416
        if (empty($interval)) {
417
            return [];
418
        }
419
        $timeZone = api_get_timezone();
420
421
        while ($continue) {
422
            $startDate = new DateTime($startEvent, new DateTimeZone('UTC'));
423
            $endDate = new DateTime($endEvent, new DateTimeZone('UTC'));
424
425
            $startDate->add(new DateInterval($interval));
426
            $endDate->add(new DateInterval($interval));
427
428
            $newStartDate = $startDate->format('Y-m-d H:i:s');
429
            $newEndDate = $endDate->format('Y-m-d H:i:s');
430
431
            $startEvent = $newStartDate;
432
            $endEvent = $newEndDate;
433
434
            if ($endDate > $repeatUntilDate) {
435
                break;
436
            }
437
438
            // @todo remove comment code
439
            $startDateInLocal = new DateTime($newStartDate, new DateTimeZone($timeZone));
440
            if (0 == $startDateInLocal->format('I')) {
441
                // Is saving time? Then fix UTC time to add time
442
                $seconds = $startDateInLocal->getOffset();
443
                $startDate->add(new DateInterval("PT".$seconds."S"));
444
                $startDateFixed = $startDate->format('Y-m-d H:i:s');
445
                $startDateInLocalFixed = new DateTime($startDateFixed, new DateTimeZone($timeZone));
446
                $newStartDate = $startDateInLocalFixed->format('Y-m-d H:i:s');
447
            }
448
449
            $endDateInLocal = new DateTime($newEndDate, new DateTimeZone($timeZone));
450
            if (0 == $endDateInLocal->format('I')) {
451
                // Is saving time? Then fix UTC time to add time
452
                $seconds = $endDateInLocal->getOffset();
453
                $endDate->add(new DateInterval("PT".$seconds."S"));
454
                $endDateFixed = $endDate->format('Y-m-d H:i:s');
455
                $endDateInLocalFixed = new DateTime($endDateFixed, new DateTimeZone($timeZone));
456
                $newEndDate = $endDateInLocalFixed->format('Y-m-d H:i:s');
457
            }
458
            $list[] = ['start' => $newStartDate, 'end' => $newEndDate, 'i' => $startDateInLocal->format('I')];
459
            $counter++;
460
461
            // just in case stop if more than $loopMax
462
            if ($counter > $loopMax) {
463
                break;
464
            }
465
        }
466
467
        return $list;
468
    }
469
470
    /**
471
     * @param int    $eventId
472
     * @param string $type
473
     * @param string $end     in UTC
474
     * @param array  $sentTo
475
     *
476
     * @return bool
477
     */
478
    public function addRepeatedItem($eventId, $type, $end, $sentTo = [])
479
    {
480
        $t_agenda = Database::get_course_table(TABLE_AGENDA);
481
        $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT);
482
483
        if (empty($this->course)) {
484
            return false;
485
        }
486
487
        $courseId = $this->course['real_id'];
488
        $eventId = (int) $eventId;
489
490
        $sql = "SELECT title, content, start_date, end_date, all_day
491
                FROM $t_agenda
492
                WHERE c_id = $courseId AND id = $eventId";
493
        $res = Database::query($sql);
494
495
        if (1 !== Database::num_rows($res)) {
496
            return false;
497
        }
498
499
        $typeList = [
500
            'daily',
501
            'weekly',
502
            'monthlyByDate',
503
            'monthlyByDay',
504
            'monthlyByDayR',
505
            'yearly',
506
        ];
507
508
        if (!in_array($type, $typeList)) {
509
            return false;
510
        }
511
512
        $now = time();
513
514
        // The event has to repeat *in the future*. We don't allow repeated
515
        // events in the past
516
        if ($end > $now) {
517
            return false;
518
        }
519
520
        $row = Database::fetch_array($res);
521
522
        $title = $row['title'];
523
        $content = $row['content'];
524
        $allDay = $row['all_day'];
525
526
        $type = Database::escape_string($type);
527
        $end = Database::escape_string($end);
528
        $endTimeStamp = api_strtotime($end, 'UTC');
529
        $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end)
530
                VALUES ($courseId, '$eventId', '$type', '$endTimeStamp')";
531
        Database::query($sql);
532
533
        $generatedDates = $this->generateDatesByType($type, $row['start_date'], $row['end_date'], $end);
534
535
        if (empty($generatedDates)) {
536
            return false;
537
        }
538
539
        foreach ($generatedDates as $dateInfo) {
540
            $start = api_get_local_time($dateInfo['start']);
541
            $end = api_get_local_time($dateInfo['end']);
542
            $this->addEvent(
543
                $start,
544
                $end,
545
                $allDay,
546
                $title,
547
                $content,
548
                $sentTo,
549
                false,
550
                $eventId
551
            );
552
        }
553
554
        return true;
555
    }
556
557
    /**
558
     * @param int   $item_id
559
     * @param array $sentTo
560
     *
561
     * @return int
562
     */
563
    public function storeAgendaEventAsAnnouncement($item_id, $sentTo = [])
564
    {
565
        $table_agenda = Database::get_course_table(TABLE_AGENDA);
566
        $courseId = api_get_course_int_id();
567
568
        // Get the agenda item.
569
        $item_id = (int) $item_id;
570
        $sql = "SELECT * FROM $table_agenda
571
                WHERE c_id = $courseId AND id = ".$item_id;
572
        $res = Database::query($sql);
573
574
        if (Database::num_rows($res) > 0) {
575
            $row = Database::fetch_array($res, 'ASSOC');
576
577
            // Sending announcement
578
            if (!empty($sentTo)) {
579
                $id = AnnouncementManager::add_announcement(
580
                    api_get_course_info(),
581
                    api_get_session_id(),
582
                    $row['title'],
583
                    $row['content'],
584
                    $sentTo,
585
                    null,
586
                    null,
587
                    $row['end_date']
588
                );
589
590
                AnnouncementManager::sendEmail(
591
                    api_get_course_info(),
592
                    api_get_session_id(),
593
                    $id
594
                );
595
596
                return $id;
597
            }
598
        }
599
600
        return -1;
601
    }
602
603
    /**
604
     * Edits an event.
605
     *
606
     * @param int    $id
607
     * @param string $start                 datetime format: 2012-06-14 09:00:00
608
     * @param string $end                   datetime format: 2012-06-14 09:00:00
609
     * @param int    $allDay                is all day 'true' or 'false'
610
     * @param string $title
611
     * @param string $content
612
     * @param array  $usersToSend
613
     * @param array  $attachmentArray
614
     * @param array  $attachmentCommentList
615
     * @param string $comment
616
     * @param string $color
617
     * @param bool   $addAnnouncement
618
     * @param bool   $updateContent
619
     * @param int    $authorId
620
     *
621
     * @return bool
622
     */
623
    public function editEvent(
624
        $id,
625
        $start,
626
        $end,
627
        $allDay,
628
        $title,
629
        $content,
630
        $usersToSend = [],
631
        $attachmentArray = [],
632
        $attachmentCommentList = [],
633
        $comment = '',
634
        $color = '',
635
        $addAnnouncement = false,
636
        $updateContent = true,
637
        $authorId = 0
638
    ) {
639
        $startObject = api_get_utc_datetime($start, true, true);
640
        $endObject = api_get_utc_datetime($end, true, true);
641
        $start = api_get_utc_datetime($start);
642
        $end = api_get_utc_datetime($end);
643
        $allDay = isset($allDay) && 'true' == $allDay ? 1 : 0;
644
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
645
646
        switch ($this->type) {
647
            case 'personal':
648
                $eventInfo = $this->get_event($id);
649
                if ($eventInfo['user'] != api_get_user_id()) {
650
                    break;
651
                }
652
                $attributes = [
653
                    'title' => $title,
654
                    'date' => $start,
655
                    'enddate' => $end,
656
                    'all_day' => $allDay,
657
                ];
658
659
                if ($updateContent) {
660
                    $attributes['text'] = $content;
661
                }
662
663
                if (!empty($color)) {
664
                    $attributes['color'] = $color;
665
                }
666
667
                Database::update(
668
                    $this->tbl_personal_agenda,
669
                    $attributes,
670
                    ['id = ?' => $id]
671
                );
672
                break;
673
            case 'course':
674
                $repo = Container::getCalendarEventRepository();
675
                $em = $repo->getEntityManager();
676
                /** @var CCalendarEvent $event */
677
                $event = $repo->find($id);
678
679
                if (empty($event)) {
680
                    return false;
681
                }
682
683
                $sentToEvent = $event->getUsersAndGroupSubscribedToEvent();
684
                $courseId = $this->course['real_id'];
685
686
                if (empty($courseId)) {
687
                    return false;
688
                }
689
690
                $courseEntity = api_get_course_entity($courseId);
691
                $sessionEntity = api_get_session_entity($this->sessionId);
692
                $groupEntity = api_get_group_entity(api_get_group_id());
693
694
                if ($this->getIsAllowedToEdit()) {
695
                    $event
696
                        ->setTitle($title)
697
                        ->setStartDate($startObject)
698
                        ->setEndDate($endObject)
699
                        ->setAllDay($allDay)
700
                        ->setComment($comment)
701
                    ;
702
703
                    if ($updateContent) {
704
                        $event->setContent($content);
705
                    }
706
707
                    if (!empty($color)) {
708
                        $event->setColor($color);
709
                    }
710
711
                    if (!empty($usersToSend)) {
712
                        $sendTo = $this->parseSendToArray($usersToSend);
713
714
                        $usersToDelete = array_diff($sentToEvent['users'], $sendTo['users']);
715
                        $usersToAdd = array_diff($sendTo['users'], $sentToEvent['users']);
716
                        $groupsToDelete = array_diff($sentToEvent['groups'], $sendTo['groups']);
717
                        $groupToAdd = array_diff($sendTo['groups'], $sentToEvent['groups']);
718
719
                        //var_dump($sendTo['everyone'], $usersToDelete, $usersToAdd, $groupsToDelete, $groupToAdd);exit;
720
                        $links = $event->getResourceNode()->getResourceLinks();
721
722
                        if ($sendTo['everyone']) {
723
                            // Delete all from group
724
                            if (isset($sentToEvent['groups']) && !empty($sentToEvent['groups'])) {
725
                                foreach ($sentToEvent['groups'] as $group) {
726
                                    foreach ($links as $link) {
727
                                        if ($link->hasGroup() && $link->getGroup()->getIid() === $group) {
728
                                            $em->remove($link);
729
                                        }
730
                                    }
731
                                }
732
                            }
733
734
                            // Storing the selected users.
735
                            if (isset($sentToEvent['users']) && !empty($sentToEvent['users'])) {
736
                                foreach ($sentToEvent['users'] as $userId) {
737
                                    foreach ($links as $link) {
738
                                        if ($link->hasUser() && $link->getUser()->getId() === $userId) {
739
                                            $em->remove($link);
740
                                        }
741
                                    }
742
                                }
743
                            }
744
                        } else {
745
                            foreach ($links as $link) {
746
                                $em->remove($link);
747
                            }
748
749
                            // Add groups
750
                            if (!empty($groupToAdd)) {
751
                                foreach ($groupToAdd as $group) {
752
                                    $group = api_get_group_entity($group);
753
                                    $event->addCourseLink($courseEntity, $sessionEntity, $group);
754
                                }
755
                            }
756
757
                            // Delete groups.
758
                            if (!empty($groupsToDelete)) {
759
                                foreach ($groupsToDelete as $group) {
760
                                    foreach ($links as $link) {
761
                                        if ($link->hasGroup() && $link->getGroup()->getIid() === $group) {
762
                                            $em->remove($link);
763
                                        }
764
                                    }
765
                                }
766
                            }
767
768
                            // Add users.
769
                            if (!empty($usersToAdd)) {
770
                                foreach ($usersToAdd as $userId) {
771
                                    $event = $event->addUserLink(
772
                                        api_get_user_entity($userId),
773
                                        $courseEntity,
774
                                        $sessionEntity,
775
                                        $groupEntity
776
                                    );
777
                                }
778
                            }
779
780
                            // Delete users.
781
                            if (!empty($usersToDelete)) {
782
                                foreach ($usersToDelete as $userId) {
783
                                    foreach ($links as $link) {
784
                                        if ($link->hasUser() && $link->getUser()->getId() === $userId) {
785
                                            $em->remove($link);
786
                                        }
787
                                    }
788
                                }
789
                            }
790
                        }
791
                    }
792
793
                    $repo->updateResource($event);
794
795
                    // Add announcement.
796
                    if (isset($addAnnouncement) && !empty($addAnnouncement)) {
797
                        $this->storeAgendaEventAsAnnouncement($id, $usersToSend);
798
                    }
799
800
                    // Add attachment.
801
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
802
                        $counter = 0;
803
                        foreach ($attachmentArray as $attachmentItem) {
804
                            if (isset($attachmentItem['id'])) {
805
                                $this->updateAttachment(
806
                                    $attachmentItem['id'],
807
                                    $id,
808
                                    $attachmentItem,
809
                                    $attachmentCommentList[$counter],
810
                                    $this->course
811
                                );
812
                                $counter++;
813
                            }
814
                        }
815
                    }
816
817
                    return true;
818
                }
819
820
                return false;
821
                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...
822
            case 'admin':
823
            case 'platform':
824
                if (api_is_platform_admin()) {
825
                    $attributes = [
826
                        'title' => $title,
827
                        'start_date' => $start,
828
                        'end_date' => $end,
829
                        'all_day' => $allDay,
830
                    ];
831
832
                    if ($updateContent) {
833
                        $attributes['content'] = $content;
834
                    }
835
                    Database::update(
836
                        $this->tbl_global_agenda,
837
                        $attributes,
838
                        ['id = ?' => $id]
839
                    );
840
                }
841
                break;
842
        }
843
    }
844
845
    /**
846
     * @param int  $id
847
     * @param bool $deleteAllItemsFromSerie
848
     */
849
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
850
    {
851
        switch ($this->type) {
852
            case 'personal':
853
                $eventInfo = $this->get_event($id);
854
                if ($eventInfo['user'] == api_get_user_id()) {
855
                    Database::delete(
856
                        $this->tbl_personal_agenda,
857
                        ['id = ?' => $id]
858
                    );
859
                }
860
                break;
861
            case 'course':
862
                $courseId = api_get_course_int_id();
863
                $isAllowToEdit = $this->getIsAllowedToEdit();
864
865
                if (!empty($courseId) && $isAllowToEdit) {
866
                    // Delete
867
                    $eventInfo = $this->get_event($id);
868
869
                    if ($deleteAllItemsFromSerie) {
870
                        /* This is one of the children.
871
                           Getting siblings and delete 'Em all + the father! */
872
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
873
                            // Removing items.
874
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
875
                            if (!empty($events)) {
876
                                foreach ($events as $event) {
877
                                    $this->deleteEvent($event['id']);
878
                                }
879
                            }
880
                            // Removing parent.
881
                            $this->deleteEvent($eventInfo['parent_event_id']);
882
                        } else {
883
                            // This is the father looking for the children.
884
                            $events = $this->getAllRepeatEvents($id);
885
                            if (!empty($events)) {
886
                                foreach ($events as $event) {
887
                                    $this->deleteEvent($event['id']);
888
                                }
889
                            }
890
                        }
891
                    }
892
893
                    $repo = Container::getCalendarEventRepository();
894
                    $event = $repo->find($id);
895
896
                    if ($event) {
897
                        $repo->getEntityManager()->remove($event);
898
                        $repo->getEntityManager()->flush();
899
900
                        // Removing from events.
901
                        /*Database::delete(
902
                            $this->tbl_course_agenda,
903
                            ['id = ? AND c_id = ?' => [$id, $courseId]]
904
                        );*/
905
906
                        /*api_item_property_update(
907
                            $this->course,
908
                            TOOL_CALENDAR_EVENT,
909
                            $id,
910
                            'delete',
911
                            api_get_user_id()
912
                        );*/
913
914
                        // Removing from series.
915
                        Database::delete(
916
                            $this->table_repeat,
917
                            [
918
                                'cal_id = ? AND c_id = ?' => [
919
                                    $id,
920
                                    $courseId,
921
                                ],
922
                            ]
923
                        );
924
                        // Attachments are already deleted using the doctrine remove() function.
925
                        /*if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
926
                            foreach ($eventInfo['attachment'] as $attachment) {
927
                                self::deleteAttachmentFile(
928
                                    $attachment['id'],
929
                                    $this->course
930
                                );
931
                            }
932
                        }*/
933
                    }
934
                }
935
                break;
936
            case 'admin':
937
                if (api_is_platform_admin()) {
938
                    Database::delete(
939
                        $this->tbl_global_agenda,
940
                        ['id = ?' => $id]
941
                    );
942
                }
943
                break;
944
        }
945
    }
946
947
    /**
948
     * Get agenda events.
949
     *
950
     * @param int    $start
951
     * @param int    $end
952
     * @param int    $courseId
953
     * @param int    $groupId
954
     * @param int    $user_id
955
     * @param string $format
956
     *
957
     * @return array|string
958
     */
959
    public function getEvents(
960
        $start,
961
        $end,
962
        $courseId = null,
963
        $groupId = null,
964
        $user_id = 0,
965
        $format = 'json'
966
    ) {
967
        switch ($this->type) {
968
            case 'admin':
969
                $this->getPlatformEvents($start, $end);
970
                break;
971
            case 'course':
972
                $courseInfo = api_get_course_info_by_id($courseId);
973
974
                // Session coach can see all events inside a session.
975
                if (api_is_coach()) {
976
                    // Own course
977
                    $this->getCourseEvents(
978
                        $start,
979
                        $end,
980
                        $courseInfo,
981
                        $groupId,
982
                        $this->sessionId,
983
                        $user_id
984
                    );
985
986
                    // Others
987
                    $this->getSessionEvents(
988
                        $start,
989
                        $end,
990
                        $this->sessionId,
991
                        $user_id,
992
                        $this->eventOtherSessionColor
993
                    );
994
                } else {
995
                    $this->getCourseEvents(
996
                        $start,
997
                        $end,
998
                        $courseInfo,
999
                        $groupId,
1000
                        $this->sessionId,
1001
                        $user_id
1002
                    );
1003
                }
1004
                break;
1005
            case 'personal':
1006
            default:
1007
                $sessionFilterActive = false;
1008
                if (!empty($this->sessionId)) {
1009
                    $sessionFilterActive = true;
1010
                }
1011
1012
                if (false == $sessionFilterActive) {
1013
                    // Getting personal events
1014
                    $this->getPersonalEvents($start, $end);
1015
1016
                    // Getting platform/admin events
1017
                    $this->getPlatformEvents($start, $end);
1018
                }
1019
1020
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1021
1022
                // Getting course events
1023
                $my_course_list = [];
1024
                if (!api_is_anonymous()) {
1025
                    $session_list = SessionManager::get_sessions_by_user(
1026
                        api_get_user_id(),
1027
                        $ignoreVisibility
1028
                    );
1029
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1030
                        api_get_user_id(),
1031
                        false
1032
                    );
1033
                }
1034
1035
                if (api_is_drh()) {
1036
                    if (api_drh_can_access_all_session_content()) {
1037
                        $session_list = [];
1038
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1039
                            api_get_user_id(),
1040
                            null,
1041
                            null,
1042
                            null,
1043
                            true,
1044
                            false
1045
                        );
1046
1047
                        if (!empty($sessionList)) {
1048
                            foreach ($sessionList as $sessionItem) {
1049
                                $sessionId = $sessionItem['id'];
1050
                                $courses = SessionManager::get_course_list_by_session_id(
1051
                                    $sessionId
1052
                                );
1053
                                $sessionInfo = [
1054
                                    'session_id' => $sessionId,
1055
                                    'courses' => $courses,
1056
                                ];
1057
                                $session_list[] = $sessionInfo;
1058
                            }
1059
                        }
1060
                    }
1061
                }
1062
1063
                if (!empty($session_list)) {
1064
                    foreach ($session_list as $session_item) {
1065
                        if ($sessionFilterActive) {
1066
                            if ($this->sessionId != $session_item['session_id']) {
1067
                                continue;
1068
                            }
1069
                        }
1070
1071
                        $my_courses = $session_item['courses'];
1072
                        $my_session_id = $session_item['session_id'];
1073
1074
                        if (!empty($my_courses)) {
1075
                            foreach ($my_courses as $course_item) {
1076
                                $courseInfo = api_get_course_info_by_id(
1077
                                    $course_item['real_id']
1078
                                );
1079
                                $this->getCourseEvents(
1080
                                    $start,
1081
                                    $end,
1082
                                    $courseInfo,
1083
                                    0,
1084
                                    $my_session_id
1085
                                );
1086
                            }
1087
                        }
1088
                    }
1089
                }
1090
1091
                if (!empty($my_course_list) && false == $sessionFilterActive) {
1092
                    foreach ($my_course_list as $courseInfoItem) {
1093
                        $courseInfo = api_get_course_info_by_id(
1094
                            $courseInfoItem['real_id']
1095
                        );
1096
                        if (isset($courseId) && !empty($courseId)) {
1097
                            if ($courseInfo['real_id'] == $courseId) {
1098
                                $this->getCourseEvents(
1099
                                    $start,
1100
                                    $end,
1101
                                    $courseInfo,
1102
                                    0,
1103
                                    0,
1104
                                    $user_id
1105
                                );
1106
                            }
1107
                        } else {
1108
                            $this->getCourseEvents(
1109
                                $start,
1110
                                $end,
1111
                                $courseInfo,
1112
                                0,
1113
                                0,
1114
                                $user_id
1115
                            );
1116
                        }
1117
                    }
1118
                }
1119
                break;
1120
        }
1121
1122
        $this->cleanEvents();
1123
1124
        switch ($format) {
1125
            case 'json':
1126
                if (empty($this->events)) {
1127
                    return '[]';
1128
                }
1129
1130
                return json_encode($this->events);
1131
                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...
1132
            case 'array':
1133
                if (empty($this->events)) {
1134
                    return [];
1135
                }
1136
1137
                return $this->events;
1138
                break;
1139
        }
1140
    }
1141
1142
    /**
1143
     * Clean events.
1144
     *
1145
     * @return bool
1146
     */
1147
    public function cleanEvents()
1148
    {
1149
        if (empty($this->events)) {
1150
            return false;
1151
        }
1152
1153
        foreach ($this->events as &$event) {
1154
            $event['description'] = Security::remove_XSS($event['description']);
1155
            $event['title'] = Security::remove_XSS($event['title']);
1156
        }
1157
1158
        return true;
1159
    }
1160
1161
    /**
1162
     * @param int $id
1163
     * @param int $minute_delta
1164
     *
1165
     * @return int
1166
     */
1167
    public function resizeEvent($id, $minute_delta)
1168
    {
1169
        $id = (int) $id;
1170
        $delta = (int) $minute_delta;
1171
        $event = $this->get_event($id);
1172
        if (!empty($event)) {
1173
            switch ($this->type) {
1174
                case 'personal':
1175
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1176
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1177
							WHERE id = ".$id;
1178
                    Database::query($sql);
1179
                    break;
1180
                case 'course':
1181
                    $sql = "UPDATE $this->tbl_course_agenda SET
1182
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1183
							WHERE
1184
							    c_id = ".$this->course['real_id']." AND
1185
							    id = ".$id;
1186
                    Database::query($sql);
1187
                    break;
1188
                case 'admin':
1189
                    $sql = "UPDATE $this->tbl_global_agenda SET
1190
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1191
							WHERE id = ".$id;
1192
                    Database::query($sql);
1193
                    break;
1194
            }
1195
        }
1196
1197
        return 1;
1198
    }
1199
1200
    /**
1201
     * @param int $id
1202
     * @param int $minute_delta minutes
1203
     * @param int $allDay
1204
     *
1205
     * @return int
1206
     */
1207
    public function move_event($id, $minute_delta, $allDay)
1208
    {
1209
        $id = (int) $id;
1210
        $event = $this->get_event($id);
1211
1212
        if (empty($event)) {
1213
            return false;
1214
        }
1215
1216
        // we convert the hour delta into minutes and add the minute delta
1217
        $delta = (int) $minute_delta;
1218
        $allDay = (int) $allDay;
1219
1220
        if (!empty($event)) {
1221
            switch ($this->type) {
1222
                case 'personal':
1223
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1224
                            all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE),
1225
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1226
							WHERE id=".$id;
1227
                    Database::query($sql);
1228
                    break;
1229
                case 'course':
1230
                    $sql = "UPDATE $this->tbl_course_agenda SET
1231
                            all_day = $allDay,
1232
                            start_date = DATE_ADD(start_date, INTERVAL $delta MINUTE),
1233
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1234
							WHERE
1235
							    c_id = ".$this->course['real_id']." AND
1236
							    id=".$id;
1237
                    Database::query($sql);
1238
                    break;
1239
                case 'admin':
1240
                    $sql = "UPDATE $this->tbl_global_agenda SET
1241
                            all_day = $allDay,
1242
                            start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
1243
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1244
							WHERE id=".$id;
1245
                    Database::query($sql);
1246
                    break;
1247
            }
1248
        }
1249
1250
        return 1;
1251
    }
1252
1253
    /**
1254
     * Gets a single event.
1255
     *
1256
     * @param int $id event id
1257
     *
1258
     * @return array
1259
     */
1260
    public function get_event($id)
1261
    {
1262
        // make sure events of the personal agenda can only be seen by the user himself
1263
        $id = (int) $id;
1264
        $event = null;
1265
        switch ($this->type) {
1266
            case 'personal':
1267
                $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1268
                        WHERE id = $id AND user = ".api_get_user_id();
1269
                $result = Database::query($sql);
1270
                if (Database::num_rows($result)) {
1271
                    $event = Database::fetch_array($result, 'ASSOC');
1272
                    $event['description'] = $event['text'];
1273
                    $event['content'] = $event['text'];
1274
                    $event['start_date'] = $event['date'];
1275
                    $event['end_date'] = $event['enddate'];
1276
                }
1277
                break;
1278
            case 'course':
1279
                $repo = Container::getCalendarEventRepository();
1280
                /** @var CCalendarEvent $eventEntity */
1281
                $eventEntity = $repo->find($id);
1282
1283
                if (!empty($this->course['real_id'])) {
1284
                    if ($eventEntity) {
1285
                        $event = [];
1286
                        $event['iid'] = $eventEntity->getIid();
1287
                        $event['title'] = $eventEntity->getTitle();
1288
                        $event['content'] = $eventEntity->getContent();
1289
                        $event['all_day'] = $eventEntity->getAllDay();
1290
                        $event['start_date'] = $eventEntity->getStartDate()->format('Y-m-d H:i:s');
1291
                        $event['end_date'] = $eventEntity->getEndDate()->format('Y-m-d H:i:s');
1292
                        $event['description'] = $eventEntity->getComment();
1293
1294
                        // Getting send to array
1295
                        $event['send_to'] = $eventEntity->getUsersAndGroupSubscribedToEvent();
1296
1297
                        // Getting repeat info
1298
                        $event['repeat_info'] = $eventEntity->getRepeatEvents();
1299
1300
                        if (!empty($event['parent_event_id'])) {
1301
                            $event['parent_info'] = $eventEntity->getParentEvent();
1302
                        }
1303
1304
                        $event['attachment'] = $eventEntity->getAttachments();
1305
                    }
1306
                }
1307
                break;
1308
            case 'admin':
1309
            case 'platform':
1310
                $sql = "SELECT * FROM ".$this->tbl_global_agenda."
1311
                        WHERE id = $id";
1312
                $result = Database::query($sql);
1313
                if (Database::num_rows($result)) {
1314
                    $event = Database::fetch_array($result, 'ASSOC');
1315
                    $event['description'] = $event['content'];
1316
                }
1317
                break;
1318
        }
1319
1320
        return $event;
1321
    }
1322
1323
    /**
1324
     * Gets personal events.
1325
     *
1326
     * @param int $start
1327
     * @param int $end
1328
     *
1329
     * @return array
1330
     */
1331
    public function getPersonalEvents($start, $end)
1332
    {
1333
        $start = (int) $start;
1334
        $end = (int) $end;
1335
        $startCondition = '';
1336
        $endCondition = '';
1337
1338
        if (0 !== $start) {
1339
            $startCondition = "AND date >= '".api_get_utc_datetime($start)."'";
1340
        }
1341
        if (0 !== $start) {
1342
            $endCondition = "AND (enddate <= '".api_get_utc_datetime($end)."' OR enddate IS NULL)";
1343
        }
1344
        $user_id = api_get_user_id();
1345
1346
        $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1347
                WHERE user = $user_id $startCondition $endCondition";
1348
1349
        $result = Database::query($sql);
1350
        $my_events = [];
1351
        if (Database::num_rows($result)) {
1352
            while ($row = Database::fetch_array($result, 'ASSOC')) {
1353
                $event = [];
1354
                $event['id'] = 'personal_'.$row['id'];
1355
                $event['title'] = $row['title'];
1356
                $event['className'] = 'personal';
1357
                $event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
1358
                $event['editable'] = true;
1359
                $event['sent_to'] = get_lang('Me');
1360
                $event['type'] = 'personal';
1361
1362
                if (!empty($row['date'])) {
1363
                    $event['start'] = $this->formatEventDate($row['date']);
1364
                    $event['start_date_localtime'] = api_get_local_time($row['date']);
1365
                }
1366
1367
                if (!empty($row['enddate'])) {
1368
                    $event['end'] = $this->formatEventDate($row['enddate']);
1369
                    $event['end_date_localtime'] = api_get_local_time($row['enddate']);
1370
                }
1371
1372
                $event['description'] = $row['text'];
1373
                $event['allDay'] = isset($row['all_day']) && 1 == $row['all_day'] ? $row['all_day'] : 0;
1374
                $event['parent_event_id'] = 0;
1375
                $event['has_children'] = 0;
1376
1377
                $my_events[] = $event;
1378
                $this->events[] = $event;
1379
            }
1380
        }
1381
1382
        // Add plugin personal events
1383
        $this->plugin = new AppPlugin();
1384
        $plugins = $this->plugin->getInstalledPluginListObject();
1385
        /** @var Plugin $plugin */
1386
        foreach ($plugins as $plugin) {
1387
            if ($plugin->hasPersonalEvents && method_exists($plugin, 'getPersonalEvents')) {
1388
                $pluginEvents = $plugin->getPersonalEvents($this, $start, $end);
1389
1390
                if (!empty($pluginEvents)) {
1391
                    $this->events = array_merge($this->events, $pluginEvents);
1392
                }
1393
            }
1394
        }
1395
1396
        return $my_events;
1397
    }
1398
1399
    /**
1400
     * @param int    $start
1401
     * @param int    $end
1402
     * @param int    $sessionId
1403
     * @param int    $userId
1404
     * @param string $color
1405
     *
1406
     * @return array
1407
     */
1408
    public function getSessionEvents(
1409
        $start,
1410
        $end,
1411
        $sessionId = 0,
1412
        $userId = 0,
1413
        $color = ''
1414
    ) {
1415
        $courses = SessionManager::get_course_list_by_session_id($sessionId);
1416
1417
        if (!empty($courses)) {
1418
            foreach ($courses as $course) {
1419
                $this->getCourseEvents(
1420
                    $start,
1421
                    $end,
1422
                    $course,
1423
                    0,
1424
                    $sessionId,
1425
                    0,
1426
                    $color
1427
                );
1428
            }
1429
        }
1430
    }
1431
1432
    /**
1433
     * @param int    $start
1434
     * @param int    $end
1435
     * @param array  $courseInfo
1436
     * @param int    $groupId
1437
     * @param int    $sessionId
1438
     * @param int    $user_id
1439
     * @param string $color
1440
     *
1441
     * @return array
1442
     */
1443
    public function getCourseEvents(
1444
        $start,
1445
        $end,
1446
        $courseInfo,
1447
        $groupId = 0,
1448
        $sessionId = 0,
1449
        $user_id = 0,
1450
        $color = ''
1451
    ) {
1452
        $start = (int) $start;
1453
        $end = (int) $end;
1454
1455
        $start = !empty($start) ? api_get_utc_datetime($start) : null;
1456
        $end = !empty($end) ? api_get_utc_datetime($end) : null;
1457
1458
        if (empty($courseInfo)) {
1459
            return [];
1460
        }
1461
1462
        $courseId = $courseInfo['real_id'];
1463
1464
        if (empty($courseId)) {
1465
            return [];
1466
        }
1467
1468
        $userId = api_get_user_id();
1469
        $sessionId = (int) $sessionId;
1470
        $user_id = (int) $user_id;
1471
1472
        $groupList = GroupManager::get_group_list(
1473
            null,
1474
            $courseInfo,
1475
            null,
1476
            $sessionId
1477
        );
1478
1479
        $groupNameList = [];
1480
        if (!empty($groupList)) {
1481
            foreach ($groupList as $group) {
1482
                $groupNameList[$group['iid']] = $group['name'];
1483
            }
1484
        }
1485
1486
        if (api_is_platform_admin() || api_is_allowed_to_edit()) {
1487
            $isAllowToEdit = true;
1488
        } else {
1489
            $isAllowToEdit = CourseManager::isCourseTeacher(
1490
                $userId,
1491
                $courseId
1492
            );
1493
        }
1494
1495
        $isAllowToEditByHrm = false;
1496
        if (!empty($sessionId)) {
1497
            $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
1498
            if ($allowDhrToEdit) {
1499
                $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, $userId);
1500
                if ($isHrm) {
1501
                    $isAllowToEdit = $isAllowToEditByHrm = true;
1502
                }
1503
            }
1504
        }
1505
1506
        $groupMemberships = [];
1507
        if (!empty($groupId)) {
1508
            $groupMemberships = [$groupId];
1509
        } else {
1510
            if ($isAllowToEdit) {
1511
                if (!empty($groupList)) {
1512
                    // c_item_property.to_group_id field was migrated to use
1513
                    // c_group_info.iid
1514
                    $groupMemberships = array_column($groupList, 'iid');
1515
                }
1516
            } else {
1517
                // get only related groups from user
1518
                $groupMemberships = GroupManager::get_group_ids($courseId, $userId);
1519
            }
1520
        }
1521
1522
        $repo = Container::getCalendarEventRepository();
1523
        $courseEntity = api_get_course_entity($courseId);
1524
        $session = api_get_session_entity($sessionId);
1525
        $qb = $repo->getResourcesByCourseOnly($courseEntity, $courseEntity->getResourceNode());
1526
        $userCondition = '';
1527
1528
        if ($isAllowToEdit) {
1529
            // No group filter was asked
1530
            if (empty($groupId)) {
1531
                if (empty($user_id)) {
1532
                    // Show all events not added in group
1533
                    $userCondition = ' (links.group IS NULL) ';
1534
                    // admin see only his stuff
1535
                    if ('personal' === $this->type) {
1536
                        $userCondition = " (links.user = ".api_get_user_id()." AND (links.group IS NULL) ";
1537
                        //$userCondition = " (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ) ";
1538
                        $userCondition .= " OR ( (links.user IS NULL)  AND (links.group IS NULL ))) ";
1539
                        //$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) ) ";
1540
                    }
1541
1542
                    if (!empty($groupMemberships)) {
1543
                        // Show events sent to selected groups
1544
                        $userCondition .= " OR (links.user IS NULL) AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1545
                    }
1546
                } else {
1547
                    // Show events of requested user in no group
1548
                    $userCondition = " (links.user = $user_id AND links.group IS NULL) ";
1549
                    // Show events sent to selected groups
1550
                    if (!empty($groupMemberships)) {
1551
                        $userCondition .= " OR (links.user = $user_id) AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1552
                    }
1553
                }
1554
            } else {
1555
                // Show only selected groups (depending of user status)
1556
                $userCondition = " (links.user is NULL) AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1557
1558
                if (!empty($groupMemberships)) {
1559
                    // Show send to $user_id in selected groups
1560
                    $userCondition .= " OR (links.user = $user_id) AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1561
                }
1562
            }
1563
        } else {
1564
            // No group filter was asked
1565
            if (empty($groupId)) {
1566
                // Show events sent to everyone and no group
1567
                $userCondition = ' ( (links.user is NULL) AND (links.group IS NULL) ';
1568
                // Show events sent to selected groups
1569
                if (!empty($groupMemberships)) {
1570
                    $userCondition .= " OR (links.user is NULL) AND (links.group IN (".implode(", ", $groupMemberships)."))) ";
1571
                } else {
1572
                    $userCondition .= " ) ";
1573
                }
1574
                $userCondition .= " OR (links.user = ".api_get_user_id()." AND (links.group IS NULL )) ";
1575
            } else {
1576
                if (!empty($groupMemberships)) {
1577
                    // Show send to everyone - and only selected groups
1578
                    $userCondition = " (links.user is NULL) AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1579
                }
1580
            }
1581
1582
            // Show sent to only me and no group
1583
            if (!empty($groupMemberships)) {
1584
                $userCondition .= " OR (links.user = ".api_get_user_id().") AND (links.group IN (".implode(", ", $groupMemberships).")) ";
1585
            }
1586
        }
1587
1588
        if (!empty($userCondition)) {
1589
            $qb->andWhere($userCondition);
1590
        }
1591
1592
        /*if (!empty($groupMemberships)) {
1593
            $orX = $qb->expr()->orX();
1594
            foreach ($groupMemberships as $groupId) {
1595
                $group = api_get_group_entity($groupId);
1596
                $orX->add("links.group = :group$groupId");
1597
                $qb->setParameter("group$groupId", $group);
1598
            }
1599
            $qb->andWhere($orX);
1600
        }*/
1601
1602
        //$dateCondition = '';
1603
        if (!empty($start) && !empty($end)) {
1604
            $qb->andWhere(
1605
                $qb->expr()->orX(
1606
                    'resource.startDate BETWEEN :start AND :end',
1607
                    'resource.endDate BETWEEN :start AND :end',
1608
                    $qb->expr()->orX(
1609
                        'resource.startDate IS NOT NULL AND resource.endDate IS NOT NULL AND
1610
                            YEAR(resource.startDate) = YEAR(resource.endDate) AND
1611
                            MONTH(:start) BETWEEN MONTH(resource.startDate) AND MONTH(resource.endDate)
1612
                        '
1613
                    )
1614
                )
1615
            )
1616
            ->setParameter('start', $start)
1617
            ->setParameter('end', $end);
1618
1619
            /*
1620
            $dateCondition .= "AND (
1621
                 agenda.start_date BETWEEN '".$start."' AND '".$end."' OR
1622
                 agenda.end_date BETWEEN '".$start."' AND '".$end."' OR
1623
                 (
1624
                     agenda.start_date IS NOT NULL AND agenda.end_date IS NOT NULL AND
1625
                     YEAR(agenda.start_date) = YEAR(agenda.end_date) AND
1626
                     MONTH('$start') BETWEEN MONTH(agenda.start_date) AND MONTH(agenda.end_date)
1627
                 )
1628
            )";*/
1629
        }
1630
1631
        /*
1632
        if (empty($sessionId)) {
1633
            $sessionCondition = "
1634
            (
1635
                agenda.session_id = 0 AND (ip.session_id IS NULL OR ip.session_id = 0)
1636
            ) ";
1637
        } else {
1638
            $sessionCondition = "
1639
            (
1640
                agenda.session_id = $sessionId AND
1641
                ip.session_id = $sessionId
1642
            ) ";
1643
        }
1644
1645
        if (api_is_allowed_to_edit()) {
1646
            $visibilityCondition = " (ip.visibility IN ('1', '0'))  ";
1647
        } else {
1648
            $visibilityCondition = " (ip.visibility = '1') ";
1649
        }
1650
1651
        $sql = "SELECT DISTINCT
1652
                    agenda.*,
1653
                    ip.visibility,
1654
                    ip.to_group_id,
1655
                    ip.insert_user_id,
1656
                    ip.ref,
1657
                    to_user_id
1658
                FROM $tlb_course_agenda agenda
1659
                INNER JOIN $tbl_property ip
1660
                ON (
1661
                    agenda.id = ip.ref AND
1662
                    agenda.c_id = ip.c_id AND
1663
                    ip.tool = '".TOOL_CALENDAR_EVENT."'
1664
                )
1665
                WHERE
1666
                    $sessionCondition AND
1667
                    ($userCondition) AND
1668
                    $visibilityCondition AND
1669
                    agenda.c_id = $courseId
1670
        ";
1671
        $dateCondition = '';
1672
        if (!empty($start) && !empty($end)) {
1673
            $dateCondition .= "AND (
1674
                 agenda.start_date BETWEEN '".$start."' AND '".$end."' OR
1675
                 agenda.end_date BETWEEN '".$start."' AND '".$end."' OR
1676
                 (
1677
                     agenda.start_date IS NOT NULL AND agenda.end_date IS NOT NULL AND
1678
                     YEAR(agenda.start_date) = YEAR(agenda.end_date) AND
1679
                     MONTH('$start') BETWEEN MONTH(agenda.start_date) AND MONTH(agenda.end_date)
1680
                 )
1681
            )";
1682
        }
1683
1684
        $sql .= $dateCondition;
1685
        $result = Database::query($sql);*/
1686
        $coachCanEdit = false;
1687
        if (!empty($sessionId)) {
1688
            $coachCanEdit = api_is_coach($sessionId, $courseId) || api_is_platform_admin();
1689
        }
1690
        $events = $qb->getQuery()->getResult();
1691
1692
        $repo = Container::getCalendarEventAttachmentRepository();
1693
1694
        /** @var CCalendarEvent $row */
1695
        foreach ($events as $row) {
1696
            $eventId = $row->getIid();
1697
            $event = [];
1698
            $event['id'] = 'course_'.$eventId;
1699
            $event['unique_id'] = $eventId;
1700
1701
            $eventsAdded[] = $eventId;
1702
            //$eventId = $row['ref'];
1703
            /*$items = $this->getUsersAndGroupSubscribedToEvent(
1704
                $eventId,
1705
                $courseId,
1706
                $this->sessionId
1707
            );
1708
            $group_to_array = $items['groups'];
1709
            $user_to_array = $items['users'];*/
1710
            /*$attachmentList = $this->getAttachmentList(
1711
                $eventId,
1712
                $courseInfo
1713
            );*/
1714
            $attachmentList = $row->getAttachments();
1715
            $event['attachment'] = '';
1716
            if (!empty($attachmentList)) {
1717
                $icon = Display::returnFontAwesomeIcon(
1718
                    'paperclip',
1719
                    '1'
1720
                );
1721
                /** @var CCalendarEventAttachment $attachment */
1722
                foreach ($attachmentList as $attachment) {
1723
                    $url = $repo->getResourceFileDownloadUrl($attachment);
1724
                    $event['attachment'] .= $icon.
1725
                        Display::url(
1726
                            $attachment->getFilename(),
1727
                            $url
1728
                        ).'<br />';
1729
                }
1730
            }
1731
1732
            $event['title'] = $row->getTitle();
1733
            $event['className'] = 'course';
1734
            $event['allDay'] = 'false';
1735
            $event['course_id'] = $courseId;
1736
            $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color;
1737
1738
            $sessionInfo = [];
1739
            /*if (!empty($row->getSessionId())) {
1740
                $sessionInfo = api_get_session_info($row->getSessionId());
1741
                $event['borderColor'] = $event['backgroundColor'] = $this->event_session_color;
1742
            }*/
1743
1744
            $event['session_name'] = $sessionInfo['name'] ?? '';
1745
            $event['course_name'] = $courseInfo['title'] ?? '';
1746
1747
            /*if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
1748
                $event['borderColor'] = $event['backgroundColor'] = $this->event_group_color;
1749
            }*/
1750
1751
            if (!empty($color)) {
1752
                $event['borderColor'] = $event['backgroundColor'] = $color;
1753
            }
1754
1755
            if ($row->getColor()) {
1756
                $event['borderColor'] = $event['backgroundColor'] = $row->getColor();
1757
            }
1758
1759
            $event['resourceEditable'] = false;
1760
            if ($this->getIsAllowedToEdit() && 'course' === $this->type) {
1761
                $event['resourceEditable'] = true;
1762
                if (!empty($sessionId)) {
1763
                    if (false == $coachCanEdit) {
1764
                        $event['resourceEditable'] = false;
1765
                    }
1766
                    if ($isAllowToEditByHrm) {
1767
                        $event['resourceEditable'] = true;
1768
                    }
1769
                }
1770
                // if user is author then he can edit the item
1771
                if (api_get_user_id() == $row->getResourceNode()->getCreator()->getId()) {
1772
                    $event['resourceEditable'] = true;
1773
                }
1774
            }
1775
1776
            if (!empty($row->getStartDate())) {
1777
                $event['start'] = $this->formatEventDate($row->getStartDate()->format('Y-m-d H:i:s'));
1778
                $event['start_date_localtime'] = api_get_local_time($row->getStartDate()->format('Y-m-d H:i:s'));
1779
            }
1780
            if (!empty($row->getEndDate())) {
1781
                $event['end'] = $this->formatEventDate($row->getEndDate()->format('Y-m-d H:i:s'));
1782
                $event['end_date_localtime'] = api_get_local_time($row->getEndDate()->format('Y-m-d H:i:s'));
1783
            }
1784
1785
            $event['sent_to'] = '';
1786
            $event['type'] = 'course';
1787
            /*if (0 != $row->getSessionId()) {
1788
                $event['type'] = 'session';
1789
            }*/
1790
1791
            $everyone = false;
1792
            $links = $row->getResourceNode()->getResourceLinks();
1793
            $sentTo = [];
1794
            foreach ($links as $link) {
1795
                if ($link->getUser()) {
1796
                    $sentTo[] = $link->getUser()->getFirstname();
1797
                }
1798
                if ($link->getCourse()) {
1799
                    $sentTo[] = $link->getCourse()->getName();
1800
                }
1801
                if ($link->getSession()) {
1802
                    $sentTo[] = $link->getSession()->getName();
1803
                }
1804
                if ($link->getGroup()) {
1805
                    $sentTo[] = $link->getGroup()->getName();
1806
                }
1807
            }
1808
1809
            // Event Sent to a group?
1810
            /*if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
1811
                $sent_to = [];
1812
                if (!empty($group_to_array)) {
1813
                    foreach ($group_to_array as $group_item) {
1814
                        $sent_to[] = $groupNameList[$group_item];
1815
                    }
1816
                }
1817
                $sent_to = implode('@@', $sent_to);
1818
                $sent_to = str_replace(
1819
                    '@@',
1820
                    '</div><div class="label_tag notice">',
1821
                    $sent_to
1822
                );
1823
                $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
1824
                $event['type'] = 'group';
1825
            }*/
1826
1827
            // Event sent to a user?
1828
            /*if (isset($row['to_user_id'])) {
1829
                $sent_to = [];
1830
                if (!empty($user_to_array)) {
1831
                    foreach ($user_to_array as $item) {
1832
                        $user_info = api_get_user_info($item);
1833
                        // Add username as tooltip for $event['sent_to'] - ref #4226
1834
                        $username = api_htmlentities(
1835
                            sprintf(
1836
                                get_lang('Login: %s'),
1837
                                $user_info['username']
1838
                            ),
1839
                            ENT_QUOTES
1840
                        );
1841
                        $sent_to[] = "<span title='".$username."'>".$user_info['complete_name']."</span>";
1842
                    }
1843
                }
1844
                $sent_to = implode('@@', $sent_to);
1845
                $sent_to = str_replace(
1846
                    '@@',
1847
                    '</div><div class="label_tag notice">',
1848
                    $sent_to
1849
                );
1850
                $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
1851
            }*/
1852
1853
            //Event sent to everyone!
1854
            /*if (empty($event['sent_to'])) {
1855
                $event['sent_to'] = '<div class="label_tag notice">'.get_lang('Everyone').'</div>';
1856
            }*/
1857
            $event['sent_to'] = implode('<br />', $sentTo);
1858
            $event['description'] = $row->getContent();
1859
            $event['visibility'] = $row->isVisible($courseEntity, $session) ? 1 : 0;
1860
            $event['real_id'] = $eventId;
1861
            $event['allDay'] = $row->getAllDay();
1862
            $event['parent_event_id'] = $row->getParentEvent() ? $row->getParentEvent()->getIid() : null;
1863
            $event['has_children'] = $row->getChildren()->count() > 0;
1864
            $event['comment'] = $row->getComment();
1865
            $this->events[] = $event;
1866
        }
1867
1868
        return $this->events;
1869
    }
1870
1871
    /**
1872
     * @param int $start tms
1873
     * @param int $end   tms
1874
     *
1875
     * @return array
1876
     */
1877
    public function getPlatformEvents($start, $end)
1878
    {
1879
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
1880
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
1881
        $dateCondition = '';
1882
1883
        if (!empty($start) && !empty($end)) {
1884
            $dateCondition .= "AND (
1885
                 start_date BETWEEN '".$start."' AND '".$end."' OR
1886
                 end_date BETWEEN '".$start."' AND '".$end."' OR
1887
                 (
1888
                     start_date IS NOT NULL AND end_date IS NOT NULL AND
1889
                     YEAR(start_date) = YEAR(end_date) AND
1890
                     MONTH('$start') BETWEEN MONTH(start_date) AND MONTH(end_date)
1891
                 )
1892
            )";
1893
        }
1894
1895
        $access_url_id = api_get_current_access_url_id();
1896
1897
        $sql = "SELECT *
1898
                FROM ".$this->tbl_global_agenda."
1899
                WHERE access_url_id = $access_url_id
1900
                $dateCondition";
1901
        $result = Database::query($sql);
1902
        $my_events = [];
1903
        if (Database::num_rows($result)) {
1904
            while ($row = Database::fetch_array($result, 'ASSOC')) {
1905
                $event = [];
1906
                $event['id'] = 'platform_'.$row['id'];
1907
                $event['title'] = $row['title'];
1908
                $event['className'] = 'platform';
1909
                $event['allDay'] = 'false';
1910
                $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color;
1911
                $event['editable'] = false;
1912
                $event['type'] = 'admin';
1913
1914
                if (api_is_platform_admin() && 'admin' === $this->type) {
1915
                    $event['editable'] = true;
1916
                }
1917
1918
                if (!empty($row['start_date'])) {
1919
                    $event['start'] = $this->formatEventDate($row['start_date']);
1920
                    $event['start_date_localtime'] = api_get_local_time($row['start_date']);
1921
                }
1922
1923
                if (!empty($row['end_date'])) {
1924
                    $event['end'] = $this->formatEventDate($row['end_date']);
1925
                    $event['end_date_localtime'] = api_get_local_time($row['end_date']);
1926
                }
1927
                $event['allDay'] = isset($row['all_day']) && 1 == $row['all_day'] ? $row['all_day'] : 0;
1928
                $event['parent_event_id'] = 0;
1929
                $event['has_children'] = 0;
1930
                $event['description'] = $row['content'];
1931
1932
                $my_events[] = $event;
1933
                $this->events[] = $event;
1934
            }
1935
        }
1936
1937
        return $my_events;
1938
    }
1939
1940
    /**
1941
     * @param CGroup[] $groupList
1942
     * @param array    $userList
1943
     * @param array    $sendTo               array('users' => [1, 2], 'groups' => [3, 4])
1944
     * @param array    $attributes
1945
     * @param bool     $addOnlyItemsInSendTo
1946
     * @param bool     $required
1947
     */
1948
    public function setSendToSelect(
1949
        FormValidator $form,
1950
        $groupList = [],
1951
        $userList = [],
1952
        $sendTo = [],
1953
        $attributes = [],
1954
        $addOnlyItemsInSendTo = false,
1955
        $required = false
1956
    ) {
1957
        $params = [
1958
            'id' => 'users_to_send_id',
1959
            'data-placeholder' => get_lang('Select'),
1960
            'multiple' => 'multiple',
1961
            'class' => 'multiple-select',
1962
        ];
1963
1964
        if (!empty($attributes)) {
1965
            $params = array_merge($params, $attributes);
1966
            if (empty($params['multiple'])) {
1967
                unset($params['multiple']);
1968
            }
1969
        }
1970
1971
        $sendToGroups = isset($sendTo['groups']) ? $sendTo['groups'] : [];
1972
        $sendToUsers = isset($sendTo['users']) ? $sendTo['users'] : [];
1973
1974
        $select = $form->addSelect(
1975
            'users_to_send',
1976
            get_lang('To'),
1977
            null,
1978
            $params
1979
        );
1980
1981
        if ($required) {
1982
            $form->setRequired($select);
1983
        }
1984
1985
        $selectedEveryoneOptions = [];
1986
        if (isset($sendTo['everyone']) && $sendTo['everyone']) {
1987
            $selectedEveryoneOptions = ['selected'];
1988
            $sendToUsers = [];
1989
        }
1990
1991
        $select->addOption(
1992
            get_lang('Everyone'),
1993
            'everyone',
1994
            $selectedEveryoneOptions
1995
        );
1996
1997
        $options = [];
1998
        if (is_array($groupList)) {
1999
            foreach ($groupList as $group) {
2000
                $groupId = $group->getIid();
2001
                $count = $group->getMembers()->count();
2002
                $countUsers = " &ndash; $count ".get_lang('Users');
2003
                $option = [
2004
                    'text' => $group->getName().$countUsers,
2005
                    'value' => "GROUP:".$groupId,
2006
                ];
2007
2008
                $selected = in_array(
2009
                    $groupId,
2010
                    $sendToGroups
2011
                ) ? true : false;
2012
                if ($selected) {
2013
                    $option['selected'] = 'selected';
2014
                }
2015
2016
                if ($addOnlyItemsInSendTo) {
2017
                    if ($selected) {
2018
                        $options[] = $option;
2019
                    }
2020
                } else {
2021
                    $options[] = $option;
2022
                }
2023
            }
2024
            $select->addOptGroup($options, get_lang('Groups'));
2025
        }
2026
2027
        // adding the individual users to the select form
2028
        if (is_array($userList)) {
2029
            $options = [];
2030
            foreach ($userList as $user) {
2031
                if (ANONYMOUS == $user['status']) {
2032
                    continue;
2033
                }
2034
                $option = [
2035
                    'text' => api_get_person_name(
2036
                            $user['firstname'],
2037
                            $user['lastname']
2038
                        ).' ('.$user['username'].')',
2039
                    'value' => "USER:".$user['user_id'],
2040
                ];
2041
2042
                $selected = in_array(
2043
                    $user['user_id'],
2044
                    $sendToUsers
2045
                ) ? true : false;
2046
2047
                if ($selected) {
2048
                    $option['selected'] = 'selected';
2049
                }
2050
2051
                if ($addOnlyItemsInSendTo) {
2052
                    if ($selected) {
2053
                        $options[] = $option;
2054
                    }
2055
                } else {
2056
                    $options[] = $option;
2057
                }
2058
            }
2059
2060
            $select->addOptGroup($options, get_lang('Users'));
2061
        }
2062
    }
2063
2064
    /**
2065
     * Separates the users and groups array
2066
     * users have a value USER:XXX (with XXX the user id
2067
     * groups have a value GROUP:YYY (with YYY the group id)
2068
     * use the 'everyone' key.
2069
     *
2070
     * @author Julio Montoya based in separate_users_groups in agenda.inc.php
2071
     *
2072
     * @param array $to
2073
     *
2074
     * @return array
2075
     */
2076
    public function parseSendToArray($to)
2077
    {
2078
        $groupList = [];
2079
        $userList = [];
2080
        $sendTo = null;
2081
2082
        $sendTo['everyone'] = false;
2083
        if (is_array($to) && count($to) > 0) {
2084
            foreach ($to as $item) {
2085
                if ('everyone' == $item) {
2086
                    $sendTo['everyone'] = true;
2087
                } else {
2088
                    [$type, $id] = explode(':', $item);
2089
                    switch ($type) {
2090
                        case 'GROUP':
2091
                            $groupList[] = $id;
2092
                            break;
2093
                        case 'USER':
2094
                            $userList[] = $id;
2095
                            break;
2096
                    }
2097
                }
2098
            }
2099
            $sendTo['groups'] = $groupList;
2100
            $sendTo['users'] = $userList;
2101
        }
2102
2103
        return $sendTo;
2104
    }
2105
2106
    /**
2107
     * @param array $params
2108
     *
2109
     * @return FormValidator
2110
     */
2111
    public function getForm($params = [])
2112
    {
2113
        $action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
2114
        $id = isset($params['id']) ? (int) $params['id'] : 0;
2115
2116
        $url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
2117
        if ('course' === $this->type) {
2118
            $url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
2119
        }
2120
2121
        $form = new FormValidator(
2122
            'add_event',
2123
            'post',
2124
            $url,
2125
            null,
2126
            ['enctype' => 'multipart/form-data']
2127
        );
2128
2129
        $idAttach = isset($params['id_attach']) ? (int) $params['id_attach'] : null;
2130
        $groupId = api_get_group_id();
2131
        $form_Title = get_lang('Add event to agenda');
2132
        if (!empty($id)) {
2133
            $form_Title = get_lang('Edit event');
2134
        }
2135
2136
        $form->addHeader($form_Title);
2137
        $form->addHidden('id', $id);
2138
        $form->addHidden('action', $action);
2139
        $form->addHidden('id_attach', $idAttach);
2140
2141
        $isSubEventEdition = false;
2142
        $isParentFromSerie = false;
2143
        $showAttachmentForm = true;
2144
2145
        if ('course' === $this->type) {
2146
            // Edition mode.
2147
            if (!empty($id)) {
2148
                $showAttachmentForm = false;
2149
                if (isset($params['parent_event_id']) && !empty($params['parent_event_id'])) {
2150
                    $isSubEventEdition = true;
2151
                }
2152
                if (!empty($params['repeat_info'])) {
2153
                    $isParentFromSerie = true;
2154
                }
2155
            }
2156
        }
2157
2158
        if ($isSubEventEdition) {
2159
            $form->addElement(
2160
                'label',
2161
                null,
2162
                Display::return_message(
2163
                    get_lang('Editing this event will remove it from the serie of events it is currently part of'),
2164
                    'warning'
2165
                )
2166
            );
2167
        }
2168
2169
        $form->addElement('text', 'title', get_lang('Event name'));
2170
2171
        if (isset($groupId) && !empty($groupId)) {
2172
            $form->addElement(
2173
                'hidden',
2174
                'users_to_send[]',
2175
                "GROUP:$groupId"
2176
            );
2177
            $form->addElement('hidden', 'to', 'true');
2178
        } else {
2179
            $sendTo = isset($params['send_to']) ? $params['send_to'] : ['everyone' => true];
2180
            if ('course' === $this->type) {
2181
                $this->showToForm($form, $sendTo, [], false, true);
2182
            }
2183
        }
2184
2185
        $form->addDateRangePicker(
2186
            'date_range',
2187
            get_lang('Date range'),
2188
            false,
2189
            ['id' => 'date_range']
2190
        );
2191
        $form->addElement('checkbox', 'all_day', null, get_lang('All day'));
2192
2193
        if ('course' === $this->type) {
2194
            $repeat = $form->addElement(
2195
                'checkbox',
2196
                'repeat',
2197
                null,
2198
                get_lang('Repeat event'),
2199
                ['onclick' => 'return plus_repeated_event();']
2200
            );
2201
            $form->addElement(
2202
                'html',
2203
                '<div id="options2" style="display:none">'
2204
            );
2205
            $form->addElement(
2206
                'select',
2207
                'repeat_type',
2208
                get_lang('Repeat type'),
2209
                self::getRepeatTypes()
2210
            );
2211
            $form->addElement(
2212
                'date_picker',
2213
                'repeat_end_day',
2214
                get_lang('Repeat end date'),
2215
                ['id' => 'repeat_end_date_form']
2216
            );
2217
2218
            if ($isSubEventEdition || $isParentFromSerie) {
2219
                $repeatInfo = $params['repeat_info'];
2220
                if ($isSubEventEdition) {
2221
                    $parentEvent = $params['parent_info'];
2222
                    $repeatInfo = $parentEvent['repeat_info'];
2223
                }
2224
                $params['repeat'] = 1;
2225
                $params['repeat_type'] = $repeatInfo['cal_type'];
2226
                $params['repeat_end_day'] = substr(
2227
                    api_get_local_time($repeatInfo['cal_end']),
2228
                    0,
2229
                    10
2230
                );
2231
2232
                $form->freeze(['repeat_type', 'repeat_end_day']);
2233
                $repeat->_attributes['disabled'] = 'disabled';
2234
            }
2235
            $form->addElement('html', '</div>');
2236
        }
2237
2238
        if (!empty($id)) {
2239
            if (empty($params['end_date'])) {
2240
                $params['date_range'] = $params['end_date'];
2241
            }
2242
2243
            $params['date_range'] =
2244
                substr(api_get_local_time($params['start_date']), 0, 16).' / '.
2245
                substr(api_get_local_time($params['end_date']), 0, 16);
2246
        }
2247
2248
        $toolbar = 'Agenda';
2249
        if (!api_is_allowed_to_edit(null, true)) {
2250
            $toolbar = 'AgendaStudent';
2251
        }
2252
2253
        $form->addHtmlEditor(
2254
            'content',
2255
            get_lang('Description'),
2256
            null,
2257
            [
2258
                'ToolbarSet' => $toolbar,
2259
                'Width' => '100%',
2260
                'Height' => '200',
2261
            ]
2262
        );
2263
2264
        if ('course' === $this->type) {
2265
            $form->addTextarea('comment', get_lang('Comment'));
2266
            $form->addLabel(
2267
                get_lang('Files attachments'),
2268
                '<div id="filepaths" class="file-upload-event">
2269
2270
                        <div id="filepath_1">
2271
                            <input type="file" name="attach_1"/>
2272
2273
                            <label>'.get_lang('Description').'</label>
2274
                            <input class="form-control" type="text" name="legend[]" />
2275
                        </div>
2276
2277
                    </div>'
2278
            );
2279
2280
            $form->addLabel(
2281
                '',
2282
                '<span id="link-more-attach">
2283
                    <a href="javascript://" onclick="return add_image_form()">'.
2284
                get_lang('Add one more file').'</a>
2285
                 </span>&nbsp;('.sprintf(
2286
                    get_lang('Maximun file size: %s'),
2287
                    format_file_size(
2288
                        api_get_setting('message_max_upload_filesize')
2289
                    )
2290
                ).')'
2291
            );
2292
2293
            if (isset($params['attachment']) && !empty($params['attachment'])) {
2294
                $attachmentList = $params['attachment'];
2295
                foreach ($attachmentList as $attachment) {
2296
                    $params['file_comment'] = $attachment['comment'];
2297
                    if (!empty($attachment['path'])) {
2298
                        $form->addElement(
2299
                            'checkbox',
2300
                            'delete_attachment['.$attachment['id'].']',
2301
                            null,
2302
                            get_lang(
2303
                                'DeleteAttachment'
2304
                            ).': '.$attachment['filename']
2305
                        );
2306
                    }
2307
                }
2308
            }
2309
2310
            $form->addElement(
2311
                'textarea',
2312
                'file_comment',
2313
                get_lang('File comment')
2314
            );
2315
        }
2316
2317
        if (empty($id)) {
2318
            $form->addElement(
2319
                'checkbox',
2320
                'add_announcement',
2321
                null,
2322
                get_lang('Add an announcement').'&nbsp('.get_lang('Send mail').')'
2323
            );
2324
        }
2325
2326
        if ($id) {
2327
            $form->addButtonUpdate(get_lang('Edit event'));
2328
        } else {
2329
            $form->addButtonSave(get_lang('Add event'));
2330
        }
2331
2332
        $form->setDefaults($params);
2333
        $form->addRule(
2334
            'date_range',
2335
            get_lang('Required field'),
2336
            'required'
2337
        );
2338
        $form->addRule('title', get_lang('Required field'), 'required');
2339
2340
        return $form;
2341
    }
2342
2343
    /**
2344
     * @param FormValidator $form
2345
     * @param array         $sendTo               array('everyone' => false, 'users' => [1, 2], 'groups' => [3, 4])
2346
     * @param array         $attributes
2347
     * @param bool          $addOnlyItemsInSendTo
2348
     * @param bool          $required
2349
     *
2350
     * @return bool
2351
     */
2352
    public function showToForm(
2353
        $form,
2354
        $sendTo = [],
2355
        $attributes = [],
2356
        $addOnlyItemsInSendTo = false,
2357
        $required = false
2358
    ) {
2359
        if ('course' !== $this->type) {
2360
            return false;
2361
        }
2362
2363
        $order = 'lastname';
2364
        if (api_is_western_name_order()) {
2365
            $order = 'firstname';
2366
        }
2367
2368
        $userList = CourseManager::get_user_list_from_course_code(
2369
            api_get_course_id(),
2370
            $this->sessionId,
2371
            null,
2372
            $order
2373
        );
2374
2375
        $groupList = CourseManager::get_group_list_of_course(
2376
            api_get_course_id(),
2377
            $this->sessionId
2378
        );
2379
2380
        $this->setSendToSelect(
2381
            $form,
2382
            $groupList,
2383
            $userList,
2384
            $sendTo,
2385
            $attributes,
2386
            $addOnlyItemsInSendTo,
2387
            $required
2388
        );
2389
2390
        return true;
2391
    }
2392
2393
    /**
2394
     * @param int   $id
2395
     * @param int   $visibility 0= invisible, 1 visible
2396
     * @param array $courseInfo
2397
     * @param int   $userId
2398
     */
2399
    public static function changeVisibility(
2400
        $id,
2401
        $visibility,
2402
        $courseInfo,
2403
        $userId = null
2404
    ) {
2405
        $id = (int) $id;
2406
2407
        $repo = Container::getCalendarEventRepository();
2408
        /** @var CCalendarEvent $event */
2409
        $event = $repo->find($id);
2410
        $visibility = (int) $visibility;
2411
2412
        if ($event) {
2413
            if (0 === $visibility) {
2414
                $repo->setVisibilityDraft($event);
2415
            } else {
2416
                $repo->setVisibilityPublished($event);
2417
            }
2418
        }
2419
2420
        return true;
2421
    }
2422
2423
    /**
2424
     * Get repeat types.
2425
     */
2426
    public static function getRepeatTypes(): array
2427
    {
2428
        return [
2429
            'daily' => get_lang('Daily'),
2430
            'weekly' => get_lang('Weekly'),
2431
            'monthlyByDate' => get_lang('Monthly, by date'),
2432
            //monthlyByDay"> get_lang('Monthly, by day');
2433
            //monthlyByDayR' => get_lang('Monthly, by dayR'),
2434
            'yearly' => get_lang('Yearly'),
2435
        ];
2436
    }
2437
2438
    /**
2439
     * Show a list with all the attachments according to the post's id.
2440
     *
2441
     * @param int   $attachmentId
2442
     * @param int   $eventId
2443
     * @param array $courseInfo
2444
     *
2445
     * @return array with the post info
2446
     */
2447
    public function getAttachment($attachmentId, $eventId, $courseInfo)
2448
    {
2449
        if (empty($courseInfo) || empty($attachmentId) || empty($eventId)) {
2450
            return [];
2451
        }
2452
2453
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
2454
        $courseId = (int) $courseInfo['real_id'];
2455
        $eventId = (int) $eventId;
2456
        $attachmentId = (int) $attachmentId;
2457
2458
        $row = [];
2459
        $sql = "SELECT iid, path, filename, comment
2460
                FROM $tableAttachment
2461
                WHERE
2462
                    c_id = $courseId AND
2463
                    agenda_id = $eventId AND
2464
                    iid = $attachmentId
2465
                ";
2466
        $result = Database::query($sql);
2467
        if (0 != Database::num_rows($result)) {
2468
            $row = Database::fetch_array($result, 'ASSOC');
2469
        }
2470
2471
        return $row;
2472
    }
2473
2474
    /**
2475
     * Add an attachment file into agenda.
2476
     *
2477
     * @param CCalendarEvent $event
2478
     * @param UploadedFile   $file
2479
     * @param string         $comment
2480
     * @param array          $courseInfo
2481
     *
2482
     * @return string
2483
     */
2484
    public function addAttachment(
2485
        $event,
2486
        $file,
2487
        $comment,
2488
        $courseInfo
2489
    ) {
2490
        // Storing the attachments
2491
        $valid = false;
2492
        if ($file) {
2493
            $valid = process_uploaded_file($file);
2494
        }
2495
2496
        if ($valid) {
2497
            /*$courseDir = $courseInfo['directory'].'/upload/calendar';
2498
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
2499
            $uploadDir = $sys_course_path.$courseDir;*/
2500
2501
            // Try to add an extension to the file if it hasn't one
2502
            /*$new_file_name = add_ext_on_mime(
2503
                stripslashes($fileUserUpload['name']),
2504
                $fileUserUpload['type']
2505
            );*/
2506
2507
            // user's file name
2508
            $fileName = $file->getClientOriginalName();
2509
            $courseId = api_get_course_int_id();
2510
            /*$new_file_name = uniqid('');
2511
            $new_path = $uploadDir.'/'.$new_file_name;
2512
            $result = @move_uploaded_file(
2513
                $fileUserUpload['tmp_name'],
2514
                $new_path
2515
            );
2516
            $courseId = api_get_course_int_id();
2517
            $size = intval($fileUserUpload['size']);*/
2518
            // Storing the attachments if any
2519
            //if ($result) {
2520
            $attachment = new CCalendarEventAttachment();
2521
            $attachment
2522
                ->setFilename($fileName)
2523
                ->setComment($comment)
2524
                ->setPath($fileName)
2525
                ->setEvent($event)
2526
                ->setSize($file->getSize())
2527
                ->setParent($event)
2528
                ->addCourseLink(
2529
                    api_get_course_entity(),
2530
                    api_get_session_entity(),
2531
                    api_get_group_entity()
2532
                );
2533
2534
            $repo = Container::getCalendarEventAttachmentRepository();
2535
            $repo->getEntityManager()->persist($attachment);
2536
            $repo->getEntityManager()->flush();
2537
2538
            $id = $attachment->getIid();
2539
            if ($id) {
2540
                /*api_item_property_update(
2541
                    $courseInfo,
2542
                    'calendar_event_attachment',
2543
                    $id,
2544
                    'AgendaAttachmentAdded',
2545
                    api_get_user_id()
2546
                );*/
2547
            }
2548
        }
2549
    }
2550
2551
    /**
2552
     * @param int    $attachmentId
2553
     * @param int    $eventId
2554
     * @param array  $fileUserUpload
2555
     * @param string $comment
2556
     * @param array  $courseInfo
2557
     */
2558
    public function updateAttachment(
2559
        $attachmentId,
2560
        $eventId,
2561
        $fileUserUpload,
2562
        $comment,
2563
        $courseInfo
2564
    ) {
2565
        $attachment = $this->getAttachment(
2566
            $attachmentId,
2567
            $eventId,
2568
            $courseInfo
2569
        );
2570
        if (!empty($attachment)) {
2571
            $this->deleteAttachmentFile($attachmentId);
2572
        }
2573
        $this->addAttachment($eventId, $fileUserUpload, $comment, $courseInfo);
2574
    }
2575
2576
    /**
2577
     * This function delete a attachment file by id.
2578
     *
2579
     * @param int $attachmentId
2580
     *
2581
     * @return string
2582
     */
2583
    public function deleteAttachmentFile($attachmentId)
2584
    {
2585
        $repo = Container::getCalendarEventAttachmentRepository();
2586
        /** @var CCalendarEventAttachment $attachment */
2587
        $attachment = $repo->find($attachmentId);
2588
2589
        if (empty($attachment)) {
2590
            return false;
2591
        }
2592
2593
        $repo->getEntityManager()->remove($attachment);
2594
        $repo->getEntityManager()->flush();
2595
2596
        return Display::return_message(
2597
            get_lang("The attached file has been deleted"),
2598
            'confirmation'
2599
        );
2600
    }
2601
2602
    /**
2603
     * @param int $eventId
2604
     *
2605
     * @return array
2606
     */
2607
    public function getAllRepeatEvents($eventId)
2608
    {
2609
        $events = [];
2610
        $eventId = (int) $eventId;
2611
2612
        switch ($this->type) {
2613
            case 'personal':
2614
                break;
2615
            case 'course':
2616
                if (!empty($this->course['real_id'])) {
2617
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
2618
                            WHERE
2619
                                c_id = ".$this->course['real_id']." AND
2620
                                parent_event_id = ".$eventId;
2621
                    $result = Database::query($sql);
2622
                    if (Database::num_rows($result)) {
2623
                        while ($row = Database::fetch_array($result, 'ASSOC')) {
2624
                            $events[] = $row;
2625
                        }
2626
                    }
2627
                }
2628
                break;
2629
        }
2630
2631
        return $events;
2632
    }
2633
2634
    /**
2635
     * @param int    $filter
2636
     * @param string $view
2637
     *
2638
     * @return string
2639
     */
2640
    public function displayActions($view, $filter = 0)
2641
    {
2642
        $groupInfo = GroupManager::get_group_properties(api_get_group_id());
2643
        $groupIid = isset($groupInfo['iid']) ? $groupInfo['iid'] : 0;
2644
2645
        $codePath = api_get_path(WEB_CODE_PATH);
2646
2647
        $currentUserId = api_get_user_id();
2648
        $cidReq = api_get_cidreq();
2649
2650
        $actionsLeft = '';
2651
        $actionsLeft .= Display::url(
2652
            Display::return_icon('calendar.png', get_lang('Calendar'), [], ICON_SIZE_MEDIUM),
2653
            $codePath."calendar/agenda_js.php?type={$this->type}&$cidReq"
2654
        );
2655
        $actionsLeft .= Display::url(
2656
            Display::return_icon('week.png', get_lang('Agenda list'), [], ICON_SIZE_MEDIUM),
2657
            $codePath."calendar/agenda_list.php?type={$this->type}&$cidReq"
2658
        );
2659
2660
        $form = '';
2661
        if (api_is_allowed_to_edit(false, true) ||
2662
            ('1' == api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous()) &&
2663
            api_is_allowed_to_session_edit(false, true)
2664
            || (
2665
                GroupManager::user_has_access($currentUserId, $groupIid, GroupManager::GROUP_TOOL_CALENDAR)
2666
                && GroupManager::is_tutor_of_group($currentUserId, $groupInfo)
2667
            )
2668
        ) {
2669
            $actionsLeft .= Display::url(
2670
                Display::return_icon('new_event.png', get_lang('Add event'), [], ICON_SIZE_MEDIUM),
2671
                $codePath."calendar/agenda.php?action=add&type={$this->type}&$cidReq"
2672
            );
2673
2674
            $actionsLeft .= Display::url(
2675
                Display::return_icon('import_calendar.png', get_lang('Outlook import'), [], ICON_SIZE_MEDIUM),
2676
                $codePath."calendar/agenda.php?action=importical&type={$this->type}&$cidReq"
2677
            );
2678
2679
            if ('course' === $this->type) {
2680
                if (!isset($_GET['action'])) {
2681
                    $form = new FormValidator(
2682
                        'form-search',
2683
                        'post',
2684
                        '',
2685
                        '',
2686
                        [],
2687
                        FormValidator::LAYOUT_INLINE
2688
                    );
2689
                    $attributes = [
2690
                        'multiple' => false,
2691
                        'id' => 'select_form_id_search',
2692
                    ];
2693
                    $selectedValues = $this->parseAgendaFilter($filter);
2694
                    $this->showToForm($form, $selectedValues, $attributes);
2695
                    $form = $form->returnForm();
2696
                }
2697
            }
2698
        }
2699
2700
        if ('personal' == $this->type && !api_is_anonymous()) {
2701
            $actionsLeft .= Display::url(
2702
                Display::return_icon('1day.png', get_lang('Sessions plan calendar'), [], ICON_SIZE_MEDIUM),
2703
                $codePath."calendar/planification.php"
2704
            );
2705
2706
            if (api_is_student_boss() || api_is_platform_admin()) {
2707
                $actionsLeft .= Display::url(
2708
                    Display::return_icon('calendar-user.png', get_lang('MyStudentsSchedule'), [], ICON_SIZE_MEDIUM),
2709
                    $codePath.'mySpace/calendar_plan.php'
2710
                );
2711
            }
2712
        }
2713
2714
        if (api_is_platform_admin() ||
2715
            api_is_teacher() ||
2716
            api_is_student_boss() ||
2717
            api_is_drh() ||
2718
            api_is_session_admin() ||
2719
            api_is_coach()
2720
        ) {
2721
            if ('personal' == $this->type) {
2722
                $form = null;
2723
                if (!isset($_GET['action'])) {
2724
                    $form = new FormValidator(
2725
                        'form-search',
2726
                        'get',
2727
                        api_get_self().'?type=personal&',
2728
                        '',
2729
                        [],
2730
                        FormValidator::LAYOUT_INLINE
2731
                    );
2732
2733
                    $sessions = [];
2734
2735
                    if (api_is_drh()) {
2736
                        $sessionList = SessionManager::get_sessions_followed_by_drh($currentUserId);
2737
                        if (!empty($sessionList)) {
2738
                            foreach ($sessionList as $sessionItem) {
2739
                                $sessions[$sessionItem['id']] = strip_tags($sessionItem['name']);
2740
                            }
2741
                        }
2742
                    } else {
2743
                        $sessions = SessionManager::get_sessions_by_user($currentUserId);
2744
                        $sessions = array_column($sessions, 'session_name', 'session_id');
2745
                    }
2746
2747
                    $form->addHidden('type', 'personal');
2748
                    $sessions = ['0' => get_lang('Please select an option')] + $sessions;
2749
2750
                    $form->addSelect(
2751
                        'session_id',
2752
                        get_lang('Session'),
2753
                        $sessions,
2754
                        ['id' => 'session_id', 'onchange' => 'submit();']
2755
                    );
2756
2757
                    $form->addButtonReset(get_lang('Reset'));
2758
                    $form = $form->returnForm();
2759
                }
2760
            }
2761
        }
2762
2763
        $actionsRight = '';
2764
        if ('calendar' == $view) {
2765
            $actionsRight .= $form;
2766
        }
2767
2768
        $toolbar = Display::toolbarAction(
2769
            'toolbar-agenda',
2770
            [$actionsLeft, $actionsRight]
2771
        );
2772
2773
        return $toolbar;
2774
    }
2775
2776
    /**
2777
     * @return FormValidator
2778
     */
2779
    public function getImportCalendarForm()
2780
    {
2781
        $form = new FormValidator(
2782
            'frm_import_ical',
2783
            'post',
2784
            api_get_self().'?action=importical&type='.$this->type,
2785
            ['enctype' => 'multipart/form-data']
2786
        );
2787
        $form->addHeader(get_lang('Outlook import'));
2788
        $form->addElement('file', 'ical_import', get_lang('Outlook import'));
2789
        $form->addRule(
2790
            'ical_import',
2791
            get_lang('Required field'),
2792
            'required'
2793
        );
2794
        $form->addButtonImport(get_lang('Import'), 'ical_submit');
2795
2796
        return $form;
2797
    }
2798
2799
    /**
2800
     * @param array $courseInfo
2801
     * @param $file
2802
     *
2803
     * @return false|string
2804
     */
2805
    public function importEventFile($courseInfo, $file)
2806
    {
2807
        $charset = api_get_system_encoding();
2808
        $filepath = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
2809
        $messages = [];
2810
2811
        if (!@move_uploaded_file($file['tmp_name'], $filepath)) {
2812
            error_log(
2813
                'Problem moving uploaded file: '.$file['error'].' in '.__FILE__.' line '.__LINE__
2814
            );
2815
2816
            return false;
2817
        }
2818
2819
        $data = file_get_contents($filepath);
2820
2821
        $trans = [
2822
            'DAILY' => 'daily',
2823
            'WEEKLY' => 'weekly',
2824
            'MONTHLY' => 'monthlyByDate',
2825
            'YEARLY' => 'yearly',
2826
        ];
2827
        $sentTo = ['everyone' => true];
2828
        $calendar = Sabre\VObject\Reader::read($data);
2829
        $currentTimeZone = api_get_timezone();
2830
        if (!empty($calendar->VEVENT)) {
2831
            foreach ($calendar->VEVENT as $event) {
2832
                $start = $event->DTSTART->getDateTime();
2833
                $end = $event->DTEND->getDateTime();
2834
                //Sabre\VObject\DateTimeParser::parseDateTime(string $dt, \Sabre\VObject\DateTimeZone $tz)
2835
2836
                $startDateTime = api_get_local_time(
2837
                    $start->format('Y-m-d H:i:s'),
2838
                    $currentTimeZone,
2839
                    $start->format('e')
2840
                );
2841
                $endDateTime = api_get_local_time(
2842
                    $end->format('Y-m-d H:i'),
2843
                    $currentTimeZone,
2844
                    $end->format('e')
2845
                );
2846
                $title = api_convert_encoding(
2847
                    (string) $event->summary,
2848
                    $charset,
2849
                    'UTF-8'
2850
                );
2851
                $description = api_convert_encoding(
2852
                    (string) $event->description,
2853
                    $charset,
2854
                    'UTF-8'
2855
                );
2856
2857
                $id = $this->addEvent(
2858
                    $startDateTime,
2859
                    $endDateTime,
2860
                    'false',
2861
                    $title,
2862
                    $description,
2863
                    $sentTo
2864
                );
2865
2866
                $messages[] = " $title - ".$startDateTime." - ".$endDateTime;
2867
2868
                //$attendee = (string)$event->attendee;
2869
                /** @var Sabre\VObject\Property\ICalendar\Recur $repeat */
2870
                $repeat = $event->RRULE;
2871
                if ($id && !empty($repeat)) {
2872
                    $repeat = $repeat->getParts();
2873
                    $freq = $trans[$repeat['FREQ']];
2874
2875
                    if (isset($repeat['UNTIL']) && !empty($repeat['UNTIL'])) {
2876
                        // Check if datetime or just date (strlen == 8)
2877
                        if (8 == strlen($repeat['UNTIL'])) {
2878
                            // Fix the datetime format to avoid exception in the next step
2879
                            $repeat['UNTIL'] .= 'T000000';
2880
                        }
2881
                        $until = Sabre\VObject\DateTimeParser::parseDateTime(
2882
                            $repeat['UNTIL'],
2883
                            new DateTimeZone($currentTimeZone)
2884
                        );
2885
                        $until = $until->format('Y-m-d H:i:s');
2886
                        $this->addRepeatedItem(
2887
                            $id,
2888
                            $freq,
2889
                            $until,
2890
                            $sentTo
2891
                        );
2892
                    }
2893
                }
2894
            }
2895
        }
2896
2897
        if (!empty($messages)) {
2898
            $messages = implode('<br /> ', $messages);
2899
        } else {
2900
            $messages = get_lang('There are no events');
2901
        }
2902
2903
        return $messages;
2904
    }
2905
2906
    /**
2907
     * Parse filter turns USER:12 to ['users' => [12])] or G:1 ['groups' => [1]].
2908
     *
2909
     * @param int $filter
2910
     *
2911
     * @return array
2912
     */
2913
    public function parseAgendaFilter($filter)
2914
    {
2915
        $everyone = false;
2916
        $groupId = null;
2917
        $userId = null;
2918
2919
        if ('everyone' === $filter) {
2920
            $everyone = true;
2921
        } else {
2922
            if ('G' === substr($filter, 0, 1)) {
2923
                $groupId = str_replace('GROUP:', '', $filter);
2924
            } else {
2925
                $userId = str_replace('USER:', '', $filter);
2926
            }
2927
        }
2928
        if (empty($userId) && empty($groupId)) {
2929
            $everyone = true;
2930
        }
2931
2932
        return [
2933
            'everyone' => $everyone,
2934
            'users' => [$userId],
2935
            'groups' => [$groupId],
2936
        ];
2937
    }
2938
2939
    /**
2940
     *    This function retrieves all the agenda items of all the courses the user is subscribed to.
2941
     */
2942
    public static function get_myagendaitems(
2943
        $user_id,
2944
        $courses_dbs,
2945
        $month,
2946
        $year
2947
    ) {
2948
        $user_id = (int) $user_id;
2949
2950
        $items = [];
2951
        $my_list = [];
2952
2953
        // get agenda-items for every course
2954
        foreach ($courses_dbs as $key => $array_course_info) {
2955
            //databases of the courses
2956
            $TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
2957
            $TABLE_ITEMPROPERTY = Database::get_course_table(
2958
                TABLE_ITEM_PROPERTY
2959
            );
2960
2961
            $group_memberships = GroupManager::get_group_ids(
2962
                $array_course_info['real_id'],
2963
                $user_id
2964
            );
2965
            $course_user_status = CourseManager::getUserInCourseStatus(
2966
                $user_id,
2967
                $array_course_info['real_id']
2968
            );
2969
            // if the user is administrator of that course we show all the agenda items
2970
            if ('1' == $course_user_status) {
2971
                //echo "course admin";
2972
                $sqlquery = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
2973
							FROM ".$TABLEAGENDA." agenda,
2974
								 ".$TABLE_ITEMPROPERTY." ip
2975
							WHERE agenda.id = ip.ref
2976
							AND MONTH(agenda.start_date)='".$month."'
2977
							AND YEAR(agenda.start_date)='".$year."'
2978
							AND ip.tool='".TOOL_CALENDAR_EVENT."'
2979
							AND ip.visibility='1'
2980
							GROUP BY agenda.id
2981
							ORDER BY start_date ";
2982
            } else {
2983
                // if the user is not an administrator of that course
2984
                if (is_array($group_memberships) && count(
2985
                        $group_memberships
2986
                    ) > 0
2987
                ) {
2988
                    $sqlquery = "SELECT	agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
2989
								FROM ".$TABLEAGENDA." agenda,
2990
									".$TABLE_ITEMPROPERTY." ip
2991
								WHERE agenda.id = ip.ref
2992
								AND MONTH(agenda.start_date)='".$month."'
2993
								AND YEAR(agenda.start_date)='".$year."'
2994
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
2995
								AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
2996
                            ", ",
2997
                            $group_memberships
2998
                        ).")) )
2999
								AND ip.visibility='1'
3000
								ORDER BY start_date ";
3001
                } else {
3002
                    $sqlquery = "SELECT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
3003
								FROM ".$TABLEAGENDA." agenda,
3004
									".$TABLE_ITEMPROPERTY." ip
3005
								WHERE agenda.id = ip.ref
3006
								AND MONTH(agenda.start_date)='".$month."'
3007
								AND YEAR(agenda.start_date)='".$year."'
3008
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
3009
								AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL)
3010
								AND ip.visibility='1'
3011
								ORDER BY start_date ";
3012
                }
3013
            }
3014
            $result = Database::query($sqlquery);
3015
3016
            while ($item = Database::fetch_array($result, 'ASSOC')) {
3017
                $agendaday = -1;
3018
                if (!empty($item['start_date'])) {
3019
                    $item['start_date'] = api_get_local_time(
3020
                        $item['start_date']
3021
                    );
3022
                    $item['start_date_tms'] = api_strtotime(
3023
                        $item['start_date']
3024
                    );
3025
                    $agendaday = date("j", $item['start_date_tms']);
3026
                }
3027
                if (!empty($item['end_date'])) {
3028
                    $item['end_date'] = api_get_local_time($item['end_date']);
3029
                }
3030
3031
                $url = api_get_path(
3032
                        WEB_CODE_PATH
3033
                    )."calendar/agenda.php?cidReq=".urlencode(
3034
                        $array_course_info["code"]
3035
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
3036
3037
                $item['url'] = $url;
3038
                $item['course_name'] = $array_course_info['title'];
3039
                $item['calendar_type'] = 'course';
3040
                $item['course_id'] = $array_course_info['course_id'];
3041
3042
                $my_list[$agendaday][] = $item;
3043
            }
3044
        }
3045
3046
        // sorting by hour for every day
3047
        $agendaitems = [];
3048
        foreach ($items as $agendaday => $tmpitems) {
3049
            if (!isset($agendaitems[$agendaday])) {
3050
                $agendaitems[$agendaday] = '';
3051
            }
3052
            sort($tmpitems);
3053
            foreach ($tmpitems as $val) {
3054
                $agendaitems[$agendaday] .= $val;
3055
            }
3056
        }
3057
3058
        return $my_list;
3059
    }
3060
3061
    /**
3062
     * This function retrieves one personal agenda item returns it.
3063
     *
3064
     * @param    array    The array containing existing events. We add to this array.
3065
     * @param    int        Day
3066
     * @param    int        Month
3067
     * @param    int        Year (4 digits)
3068
     * @param    int        Week number
3069
     * @param    string    Type of view (month_view, week_view, day_view)
3070
     *
3071
     * @return array The results of the database query, or null if not found
3072
     */
3073
    public static function get_global_agenda_items(
3074
        $agendaitems,
3075
        $day = "",
3076
        $month = "",
3077
        $year = "",
3078
        $week = "",
3079
        $type
3080
    ) {
3081
        $tbl_global_agenda = Database::get_main_table(
3082
            TABLE_MAIN_SYSTEM_CALENDAR
3083
        );
3084
        $month = intval($month);
3085
        $year = intval($year);
3086
        $week = intval($week);
3087
        $day = intval($day);
3088
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
3089
3090
        $current_access_url_id = api_get_current_access_url_id();
3091
3092
        if ("month_view" == $type or "" == $type) {
3093
            // We are in month view
3094
            $sql = "SELECT * FROM ".$tbl_global_agenda." WHERE MONTH(start_date) = ".$month." AND YEAR(start_date) = ".$year."  AND access_url_id = $current_access_url_id ORDER BY start_date ASC";
3095
        }
3096
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
3097
        if ("week_view" == $type) { // we are in week view
3098
            $start_end_day_of_week = self::calculate_start_end_of_week(
3099
                $week,
3100
                $year
3101
            );
3102
            $start_day = $start_end_day_of_week['start']['day'];
3103
            $start_month = $start_end_day_of_week['start']['month'];
3104
            $start_year = $start_end_day_of_week['start']['year'];
3105
            $end_day = $start_end_day_of_week['end']['day'];
3106
            $end_month = $start_end_day_of_week['end']['month'];
3107
            $end_year = $start_end_day_of_week['end']['year'];
3108
            // in sql statements you have to use year-month-day for date calculations
3109
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
3110
            $start_filter = api_get_utc_datetime($start_filter);
3111
3112
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
3113
            $end_filter = api_get_utc_datetime($end_filter);
3114
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."' AND  access_url_id = $current_access_url_id ";
3115
        }
3116
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
3117
        if ("day_view" == $type) { // we are in day view
3118
            // we could use mysql date() function but this is only available from 4.1 and higher
3119
            $start_filter = $year."-".$month."-".$day." 00:00:00";
3120
            $start_filter = api_get_utc_datetime($start_filter);
3121
3122
            $end_filter = $year."-".$month."-".$day." 23:59:59";
3123
            $end_filter = api_get_utc_datetime($end_filter);
3124
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."'  AND  access_url_id = $current_access_url_id";
3125
        }
3126
3127
        $result = Database::query($sql);
3128
3129
        while ($item = Database::fetch_array($result)) {
3130
            if (!empty($item['start_date'])) {
3131
                $item['start_date'] = api_get_local_time($item['start_date']);
3132
                $item['start_date_tms'] = api_strtotime($item['start_date']);
3133
            }
3134
            if (!empty($item['end_date'])) {
3135
                $item['end_date'] = api_get_local_time($item['end_date']);
3136
            }
3137
3138
            // we break the date field in the database into a date and a time part
3139
            $agenda_db_date = explode(" ", $item['start_date']);
3140
            $date = $agenda_db_date[0];
3141
            $time = $agenda_db_date[1];
3142
            // we divide the date part into a day, a month and a year
3143
            $agendadate = explode("-", $date);
3144
            $year = intval($agendadate[0]);
3145
            $month = intval($agendadate[1]);
3146
            $day = intval($agendadate[2]);
3147
            // we divide the time part into hour, minutes, seconds
3148
            $agendatime = explode(":", $time);
3149
            $hour = $agendatime[0];
3150
            $minute = $agendatime[1];
3151
            $second = $agendatime[2];
3152
3153
            if ('month_view' == $type) {
3154
                $item['calendar_type'] = 'global';
3155
                $agendaitems[$day][] = $item;
3156
                continue;
3157
            }
3158
3159
            $start_time = api_format_date(
3160
                $item['start_date'],
3161
                TIME_NO_SEC_FORMAT
3162
            );
3163
            $end_time = '';
3164
            if (!empty($item['end_date'])) {
3165
                $end_time = ' - '.api_format_date(
3166
                        $item['end_date'],
3167
                        DATE_TIME_FORMAT_LONG
3168
                    );
3169
            }
3170
3171
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
3172
            // if we have a day_view we use a half hour as index => key 33 = 16h30
3173
            if ("day_view" !== $type) {
3174
                // This is the array construction for the WEEK or MONTH view
3175
                //Display the Agenda global in the tab agenda (administrator)
3176
                $agendaitems[$day] .= "<i>$start_time $end_time</i>&nbsp;-&nbsp;";
3177
                $agendaitems[$day] .= "<b>".get_lang('Platform event')."</b>";
3178
                $agendaitems[$day] .= "<div>".$item['title']."</div><br>";
3179
            } else {
3180
                // this is the array construction for the DAY view
3181
                $halfhour = 2 * $agendatime['0'];
3182
                if ($agendatime['1'] >= '30') {
3183
                    $halfhour = $halfhour + 1;
3184
                }
3185
                if (!is_array($agendaitems[$halfhour])) {
3186
                    $content = $agendaitems[$halfhour];
3187
                }
3188
                $agendaitems[$halfhour] = $content."<div><i>$hour:$minute</i> <b>".get_lang(
3189
                        'Platform event'
3190
                    ).":  </b>".$item['title']."</div>";
3191
            }
3192
        }
3193
3194
        return $agendaitems;
3195
    }
3196
3197
    /**
3198
     * This function retrieves all the personal agenda items and add them to the agenda items found by the other
3199
     * functions.
3200
     */
3201
    public static function get_personal_agenda_items(
3202
        $user_id,
3203
        $agendaitems,
3204
        $day = "",
3205
        $month = "",
3206
        $year = "",
3207
        $week = "",
3208
        $type
3209
    ) {
3210
        $tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
3211
        $user_id = (int) $user_id;
3212
        $course_link = '';
3213
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
3214
        if ("month_view" === $type || "" == $type) {
3215
            // we are in month view
3216
            $sql = "SELECT * FROM ".$tbl_personal_agenda."
3217
                    WHERE user='".$user_id."' and MONTH(date)='".$month."' AND YEAR(date) = '".$year."'
3218
                    ORDER BY date ASC";
3219
        }
3220
3221
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
3222
        // we are in week view
3223
        if ("week_view" === $type) {
3224
            $start_end_day_of_week = self::calculate_start_end_of_week(
3225
                $week,
3226
                $year
3227
            );
3228
            $start_day = $start_end_day_of_week['start']['day'];
3229
            $start_month = $start_end_day_of_week['start']['month'];
3230
            $start_year = $start_end_day_of_week['start']['year'];
3231
            $end_day = $start_end_day_of_week['end']['day'];
3232
            $end_month = $start_end_day_of_week['end']['month'];
3233
            $end_year = $start_end_day_of_week['end']['year'];
3234
            // in sql statements you have to use year-month-day for date calculations
3235
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
3236
            $start_filter = api_get_utc_datetime($start_filter);
3237
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
3238
            $end_filter = api_get_utc_datetime($end_filter);
3239
            $sql = "SELECT * FROM ".$tbl_personal_agenda."
3240
                    WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
3241
        }
3242
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
3243
        if ("day_view" === $type) {
3244
            // we are in day view
3245
            // we could use mysql date() function but this is only available from 4.1 and higher
3246
            $start_filter = $year."-".$month."-".$day." 00:00:00";
3247
            $start_filter = api_get_utc_datetime($start_filter);
3248
            $end_filter = $year."-".$month."-".$day." 23:59:59";
3249
            $end_filter = api_get_utc_datetime($end_filter);
3250
            $sql = "SELECT * FROM ".$tbl_personal_agenda."
3251
                    WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
3252
        }
3253
3254
        $result = Database::query($sql);
3255
        while ($item = Database::fetch_array($result, 'ASSOC')) {
3256
            $time_minute = api_convert_and_format_date(
3257
                $item['date'],
3258
                TIME_NO_SEC_FORMAT
3259
            );
3260
            $item['date'] = api_get_local_time($item['date']);
3261
            $item['start_date_tms'] = api_strtotime($item['date']);
3262
            $item['content'] = $item['text'];
3263
3264
            // we break the date field in the database into a date and a time part
3265
            $agenda_db_date = explode(" ", $item['date']);
3266
            $date = $agenda_db_date[0];
3267
            $time = $agenda_db_date[1];
3268
            // we divide the date part into a day, a month and a year
3269
            $agendadate = explode("-", $item['date']);
3270
            $year = intval($agendadate[0]);
3271
            $month = intval($agendadate[1]);
3272
            $day = intval($agendadate[2]);
3273
            // we divide the time part into hour, minutes, seconds
3274
            $agendatime = explode(":", $time);
3275
3276
            $hour = $agendatime[0];
3277
            $minute = $agendatime[1];
3278
            $second = $agendatime[2];
3279
3280
            if ('month_view' === $type) {
3281
                $item['calendar_type'] = 'personal';
3282
                $item['start_date'] = $item['date'];
3283
                $agendaitems[$day][] = $item;
3284
                continue;
3285
            }
3286
3287
            // Creating the array that will be returned.
3288
            // If we have week or month view we have an array with the date as the key
3289
            // if we have a day_view we use a half hour as index => key 33 = 16h30
3290
            if ("day_view" !== $type) {
3291
                // This is the array construction for the WEEK or MONTH view
3292
3293
                //Display events in agenda
3294
                $agendaitems[$day] .= "<div>
3295
                     <i>$time_minute</i> $course_link
3296
                     <a href=\"myagenda.php?action=view&view=personal&day=$day&month=$month&year=$year&id=".$item['id']."#".$item['id']."\" class=\"personal_agenda\">".
3297
                    $item['title']."</a></div><br />";
3298
            } else {
3299
                // this is the array construction for the DAY view
3300
                $halfhour = 2 * $agendatime['0'];
3301
                if ($agendatime['1'] >= '30') {
3302
                    $halfhour = $halfhour + 1;
3303
                }
3304
3305
                //Display events by list
3306
                $agendaitems[$halfhour] .= "<div>
3307
                    <i>$time_minute</i> $course_link
3308
                    <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>";
3309
            }
3310
        }
3311
3312
        return $agendaitems;
3313
    }
3314
3315
    /**
3316
     * Show the month calendar of the given month.
3317
     *
3318
     * @param    array    Agendaitems
3319
     * @param    int    Month number
3320
     * @param    int    Year number
3321
     * @param    array    Array of strings containing long week day names (deprecated, you can send an empty array
3322
     *                          instead)
3323
     * @param    string    The month name
3324
     */
3325
    public static function display_mymonthcalendar(
3326
        $user_id,
3327
        $agendaitems,
3328
        $month,
3329
        $year,
3330
        $weekdaynames = [],
3331
        $monthName,
3332
        $show_content = true
3333
    ) {
3334
        global $DaysShort, $course_path;
3335
        //Handle leap year
3336
        $numberofdays = [
3337
            0,
3338
            31,
3339
            28,
3340
            31,
3341
            30,
3342
            31,
3343
            30,
3344
            31,
3345
            31,
3346
            30,
3347
            31,
3348
            30,
3349
            31,
3350
        ];
3351
        if ((0 == $year % 400) or (0 == $year % 4 and 0 != $year % 100)) {
3352
            $numberofdays[2] = 29;
3353
        }
3354
        //Get the first day of the month
3355
        $dayone = getdate(mktime(0, 0, 0, $month, 1, $year));
3356
        //Start the week on monday
3357
        $startdayofweek = 0 != $dayone['wday'] ? ($dayone['wday'] - 1) : 6;
3358
        $g_cc = (isset($_GET['courseCode']) ? $_GET['courseCode'] : '');
3359
3360
        $next_month = (1 == $month ? 12 : $month - 1);
3361
        $prev_month = (12 == $month ? 1 : $month + 1);
3362
3363
        $next_year = (1 == $month ? $year - 1 : $year);
3364
        $prev_year = (12 == $month ? $year + 1 : $year);
3365
3366
        if ($show_content) {
3367
            $back_url = Display::url(
3368
                get_lang('Previous'),
3369
                api_get_self()."?coursePath=".urlencode(
3370
                    $course_path
3371
                )."&courseCode=".Security::remove_XSS(
3372
                    $g_cc
3373
                )."&action=view&view=month&month=".$next_month."&year=".$next_year
3374
            );
3375
            $next_url = Display::url(
3376
                get_lang('Next'),
3377
                api_get_self()."?coursePath=".urlencode(
3378
                    $course_path
3379
                )."&courseCode=".Security::remove_XSS(
3380
                    $g_cc
3381
                )."&action=view&view=month&month=".$prev_month."&year=".$prev_year
3382
            );
3383
        } else {
3384
            $back_url = Display::url(
3385
                get_lang('Previous'),
3386
                '',
3387
                [
3388
                    'onclick' => "load_calendar('".$user_id."','".$next_month."', '".$next_year."'); ",
3389
                    'class' => 'btn ui-button ui-widget ui-state-default',
3390
                ]
3391
            );
3392
            $next_url = Display::url(
3393
                get_lang('Next'),
3394
                '',
3395
                [
3396
                    'onclick' => "load_calendar('".$user_id."','".$prev_month."', '".$prev_year."'); ",
3397
                    'class' => 'pull-right btn ui-button ui-widget ui-state-default',
3398
                ]
3399
            );
3400
        }
3401
        $html = '';
3402
        $html .= '<div class="actions">';
3403
        $html .= '<div class="row">';
3404
        $html .= '<div class="col-md-4">'.$back_url.'</div>';
3405
        $html .= '<div class="col-md-4"><p class="agenda-title text-center">'.$monthName." ".$year.'</p></div>';
3406
        $html .= '<div class="col-md-4">'.$next_url.'</div>';
3407
        $html .= '</div>';
3408
        $html .= '</div>';
3409
        $html .= '<table id="agenda_list2" class="table table-bordered">';
3410
        $html .= '<tr>';
3411
        for ($ii = 1; $ii < 8; $ii++) {
3412
            $html .= '<td class="weekdays">'.$DaysShort[$ii % 7].'</td>';
3413
        }
3414
        $html .= '</tr>';
3415
3416
        $curday = -1;
3417
        $today = getdate();
3418
        while ($curday <= $numberofdays[$month]) {
3419
            $html .= "<tr>";
3420
            for ($ii = 0; $ii < 7; $ii++) {
3421
                if ((-1 == $curday) && ($ii == $startdayofweek)) {
3422
                    $curday = 1;
3423
                }
3424
                if (($curday > 0) && ($curday <= $numberofdays[$month])) {
3425
                    $bgcolor = $class = 'class="days_week"';
3426
                    $dayheader = Display::div(
3427
                        $curday,
3428
                        ['class' => 'agenda_day']
3429
                    );
3430
                    if (($curday == $today['mday']) && ($year == $today['year']) && ($month == $today['mon'])) {
3431
                        $class = "class=\"days_today\" style=\"width:10%;\"";
3432
                    }
3433
3434
                    $html .= "<td ".$class.">".$dayheader;
3435
3436
                    if (!empty($agendaitems[$curday])) {
3437
                        $items = $agendaitems[$curday];
3438
                        $items = msort($items, 'start_date_tms');
3439
3440
                        foreach ($items as $value) {
3441
                            $value['title'] = Security::remove_XSS(
3442
                                $value['title']
3443
                            );
3444
                            $start_time = api_format_date(
3445
                                $value['start_date'],
3446
                                TIME_NO_SEC_FORMAT
3447
                            );
3448
                            $end_time = '';
3449
3450
                            if (!empty($value['end_date'])) {
3451
                                $end_time = '-&nbsp;<i>'.api_format_date(
3452
                                        $value['end_date'],
3453
                                        DATE_TIME_FORMAT_LONG
3454
                                    ).'</i>';
3455
                            }
3456
                            $complete_time = '<i>'.api_format_date(
3457
                                    $value['start_date'],
3458
                                    DATE_TIME_FORMAT_LONG
3459
                                ).'</i>&nbsp;'.$end_time;
3460
                            $time = '<i>'.$start_time.'</i>';
3461
3462
                            switch ($value['calendar_type']) {
3463
                                case 'personal':
3464
                                    $bg_color = '#D0E7F4';
3465
                                    $icon = Display::return_icon(
3466
                                        'user.png',
3467
                                        get_lang('Personal agenda'),
3468
                                        [],
3469
                                        ICON_SIZE_SMALL
3470
                                    );
3471
                                    break;
3472
                                case 'global':
3473
                                    $bg_color = '#FFBC89';
3474
                                    $icon = Display::return_icon(
3475
                                        'view_remove.png',
3476
                                        get_lang('Platform event'),
3477
                                        [],
3478
                                        ICON_SIZE_SMALL
3479
                                    );
3480
                                    break;
3481
                                case 'course':
3482
                                    $bg_color = '#CAFFAA';
3483
                                    $icon_name = 'course.png';
3484
                                    if (!empty($value['session_id'])) {
3485
                                        $icon_name = 'session.png';
3486
                                    }
3487
                                    if ($show_content) {
3488
                                        $icon = Display::url(
3489
                                            Display::return_icon(
3490
                                                $icon_name,
3491
                                                $value['course_name'].' '.get_lang(
3492
                                                    'Course'
3493
                                                ),
3494
                                                [],
3495
                                                ICON_SIZE_SMALL
3496
                                            ),
3497
                                            $value['url']
3498
                                        );
3499
                                    } else {
3500
                                        $icon = Display::return_icon(
3501
                                            $icon_name,
3502
                                            $value['course_name'].' '.get_lang(
3503
                                                'Course'
3504
                                            ),
3505
                                            [],
3506
                                            ICON_SIZE_SMALL
3507
                                        );
3508
                                    }
3509
                                    break;
3510
                                default:
3511
                                    break;
3512
                            }
3513
3514
                            $result = '<div class="rounded_div_agenda" style="background-color:'.$bg_color.';">';
3515
3516
                            if ($show_content) {
3517
                                //Setting a personal event to green
3518
                                $icon = Display::div(
3519
                                    $icon,
3520
                                    ['style' => 'float:right']
3521
                                );
3522
3523
                                $link = $value['calendar_type'].'_'.$value['id'].'_'.$value['course_id'].'_'.$value['session_id'];
3524
3525
                                //Link to bubble
3526
                                $url = Display::url(
3527
                                    cut($value['title'], 40),
3528
                                    '#',
3529
                                    ['id' => $link, 'class' => 'opener']
3530
                                );
3531
                                $result .= $time.' '.$icon.' '.Display::div(
3532
                                        $url
3533
                                    );
3534
3535
                                //Hidden content
3536
                                $content = Display::div(
3537
                                    $icon.Display::tag(
3538
                                        'h2',
3539
                                        $value['course_name']
3540
                                    ).'<hr />'.Display::tag(
3541
                                        'h3',
3542
                                        $value['title']
3543
                                    ).$complete_time.'<hr />'.Security::remove_XSS(
3544
                                        $value['content']
3545
                                    )
3546
                                );
3547
3548
                                //Main div
3549
                                $result .= Display::div(
3550
                                    $content,
3551
                                    [
3552
                                        'id' => 'main_'.$link,
3553
                                        'class' => 'dialog',
3554
                                        'style' => 'display:none',
3555
                                    ]
3556
                                );
3557
                                $result .= '</div>';
3558
                                $html .= $result;
3559
                            } else {
3560
                                $html .= $result .= $icon.'</div>';
3561
                            }
3562
                        }
3563
                    }
3564
                    $html .= "</td>";
3565
                    $curday++;
3566
                } else {
3567
                    $html .= "<td></td>";
3568
                }
3569
            }
3570
            $html .= "</tr>";
3571
        }
3572
        $html .= "</table>";
3573
        echo $html;
3574
    }
3575
3576
    /**
3577
     * Get personal agenda items between two dates (=all events from all registered courses).
3578
     *
3579
     * @param int $user_id user ID of the user
3580
     * @param    string    Optional start date in datetime format (if no start date is given, uses today)
3581
     * @param    string    Optional end date in datetime format (if no date is given, uses one year from now)
3582
     *
3583
     * @return array array of events ordered by start date, in
3584
     *               [0]('datestart','dateend','title'),[1]('datestart','dateend','title','link','coursetitle') format,
3585
     *               where datestart and dateend are in yyyyMMddhhmmss format
3586
     *
3587
     * @deprecated use agenda events
3588
     */
3589
    public static function get_personal_agenda_items_between_dates($user_id, $date_start = '', $date_end = '')
3590
    {
3591
        throw new Exception('fix get_personal_agenda_items_between_dates');
3592
        /*
3593
        $items = [];
3594
        if ($user_id != strval(intval($user_id))) {
3595
            return $items;
3596
        }
3597
        if (empty($date_start)) {
3598
            $date_start = date('Y-m-d H:i:s');
3599
        }
3600
        if (empty($date_end)) {
3601
            $date_end = date(
3602
                'Y-m-d H:i:s',
3603
                mktime(0, 0, 0, date("m"), date("d"), date("Y") + 1)
3604
            );
3605
        }
3606
        $expr = '/\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}/';
3607
        if (!preg_match($expr, $date_start)) {
3608
            return $items;
3609
        }
3610
        if (!preg_match($expr, $date_end)) {
3611
            return $items;
3612
        }
3613
3614
        // get agenda-items for every course
3615
        //$courses = api_get_user_courses($user_id, false);
3616
        $courses = CourseManager::get_courses_list_by_user_id($user_id, false);
3617
        foreach ($courses as $id => $course) {
3618
            $c = api_get_course_info_by_id($course['real_id']);
3619
            $t_a = Database::get_course_table(TABLE_AGENDA, $course['db']);
3620
            $t_ip = Database::get_course_table(
3621
                TABLE_ITEM_PROPERTY,
3622
                $course['db']
3623
            );
3624
            // get the groups to which the user belong
3625
            $group_memberships = GroupManager:: get_group_ids(
3626
                $course['db'],
3627
                $user_id
3628
            );
3629
            // if the user is administrator of that course we show all the agenda items
3630
            if ('1' == $course['status']) {
3631
                //echo "course admin";
3632
                $sqlquery = "SELECT ".
3633
                    " DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
3634
                    " FROM ".$t_a." agenda, ".
3635
                    $t_ip." ip ".
3636
                    " WHERE agenda.id = ip.ref ".
3637
                    " AND agenda.start_date>='$date_start' ".
3638
                    " AND agenda.end_date<='$date_end' ".
3639
                    " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
3640
                    " AND ip.visibility='1' ".
3641
                    " GROUP BY agenda.id ".
3642
                    " ORDER BY start_date ";
3643
            } else {
3644
                // if the user is not an administrator of that course, then...
3645
                if (is_array($group_memberships) && count(
3646
                        $group_memberships
3647
                    ) > 0
3648
                ) {
3649
                    $sqlquery = "SELECT ".
3650
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
3651
                        " FROM ".$t_a." agenda, ".
3652
                        $t_ip." ip ".
3653
                        " WHERE agenda.id = ip.ref ".
3654
                        " AND agenda.start_date>='$date_start' ".
3655
                        " AND agenda.end_date<='$date_end' ".
3656
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
3657
                        " AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
3658
                            ", ",
3659
                            $group_memberships
3660
                        ).")) ) ".
3661
                        " AND ip.visibility='1' ".
3662
                        " ORDER BY start_date ";
3663
                } else {
3664
                    $sqlquery = "SELECT ".
3665
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
3666
                        " FROM ".$t_a." agenda, ".
3667
                        $t_ip." ip ".
3668
                        " WHERE agenda.id = ip.ref ".
3669
                        " AND agenda.start_date>='$date_start' ".
3670
                        " AND agenda.end_date<='$date_end' ".
3671
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
3672
                        " AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL) ".
3673
                        " AND ip.visibility='1' ".
3674
                        " ORDER BY start_date ";
3675
                }
3676
            }
3677
3678
            $result = Database::query($sqlquery);
3679
            while ($item = Database::fetch_array($result)) {
3680
                $agendaday = date("j", strtotime($item['start_date']));
3681
                $month = date("n", strtotime($item['start_date']));
3682
                $year = date("Y", strtotime($item['start_date']));
3683
                $URL = api_get_path(
3684
                        WEB_PATH
3685
                    )."main/calendar/agenda.php?cidReq=".urlencode(
3686
                        $course["code"]
3687
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
3688
                [$year, $month, $day, $hour, $min, $sec] = explode(
3689
                    '[-: ]',
3690
                    $item['start_date']
3691
                );
3692
                $start_date = $year.$month.$day.$hour.$min;
3693
                [$year, $month, $day, $hour, $min, $sec] = explode(
3694
                    '[-: ]',
3695
                    $item['end_date']
3696
                );
3697
                $end_date = $year.$month.$day.$hour.$min;
3698
3699
                $items[] = [
3700
                    'datestart' => $start_date,
3701
                    'dateend' => $end_date,
3702
                    'title' => $item['title'],
3703
                    'link' => $URL,
3704
                    'coursetitle' => $c['name'],
3705
                ];
3706
            }
3707
        }
3708
3709
        return $items;*/
3710
    }
3711
3712
    /**
3713
     * This function calculates the startdate of the week (monday)
3714
     * and the enddate of the week (sunday)
3715
     * and returns it as an array.
3716
     */
3717
    public static function calculate_start_end_of_week($week_number, $year)
3718
    {
3719
        // determine the start and end date
3720
        // step 1: we calculate a timestamp for a day in this week
3721
        $random_day_in_week = mktime(
3722
                0,
3723
                0,
3724
                0,
3725
                1,
3726
                1,
3727
                $year
3728
            ) + ($week_number) * (7 * 24 * 60 * 60); // we calculate a random day in this week
3729
        // step 2: we which day this is (0=sunday, 1=monday, ...)
3730
        $number_day_in_week = date('w', $random_day_in_week);
3731
        // step 3: we calculate the timestamp of the monday of the week we are in
3732
        $start_timestamp = $random_day_in_week - (($number_day_in_week - 1) * 24 * 60 * 60);
3733
        // step 4: we calculate the timestamp of the sunday of the week we are in
3734
        $end_timestamp = $random_day_in_week + ((7 - $number_day_in_week + 1) * 24 * 60 * 60) - 3600;
3735
        // step 5: calculating the start_day, end_day, start_month, end_month, start_year, end_year
3736
        $start_day = date('j', $start_timestamp);
3737
        $start_month = date('n', $start_timestamp);
3738
        $start_year = date('Y', $start_timestamp);
3739
        $end_day = date('j', $end_timestamp);
3740
        $end_month = date('n', $end_timestamp);
3741
        $end_year = date('Y', $end_timestamp);
3742
        $start_end_array['start']['day'] = $start_day;
3743
        $start_end_array['start']['month'] = $start_month;
3744
        $start_end_array['start']['year'] = $start_year;
3745
        $start_end_array['end']['day'] = $end_day;
3746
        $start_end_array['end']['month'] = $end_month;
3747
        $start_end_array['end']['year'] = $end_year;
3748
3749
        return $start_end_array;
3750
    }
3751
3752
    /**
3753
     * @return bool
3754
     */
3755
    public function getIsAllowedToEdit()
3756
    {
3757
        return $this->isAllowedToEdit;
3758
    }
3759
3760
    /**
3761
     * @param bool $isAllowedToEdit
3762
     */
3763
    public function setIsAllowedToEdit($isAllowedToEdit)
3764
    {
3765
        $this->isAllowedToEdit = $isAllowedToEdit;
3766
    }
3767
3768
    /**
3769
     * Format needed for the Fullcalendar js lib.
3770
     *
3771
     * @param string $utcTime
3772
     *
3773
     * @return bool|string
3774
     */
3775
    public function formatEventDate($utcTime)
3776
    {
3777
        $utcTimeZone = new DateTimeZone('UTC');
3778
        $platformTimeZone = new DateTimeZone(api_get_timezone());
3779
3780
        $eventDate = new DateTime($utcTime, $utcTimeZone);
3781
        $eventDate->setTimezone($platformTimeZone);
3782
3783
        return $eventDate->format(DateTime::ISO8601);
3784
    }
3785
}
3786