Passed
Push — 1.11.x ( 6c626e...925e49 )
by Yannick
10:39 queued 15s
created

Agenda::addEvent()   F

Complexity

Conditions 32
Paths 1296

Size

Total Lines 263
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 170
c 0
b 0
f 0
dl 0
loc 263
rs 0
cc 32
nop 20
nc 1296

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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