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

Agenda::unsubscribeCurrentUserToEvent()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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