Passed
Push — 1.11.x ( 063b4a...73095b )
by Angel Fernando Quiroz
08:41
created

Agenda::editEvent()   F

Complexity

Conditions 56
Paths 8408

Size

Total Lines 377
Code Lines 227

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 227
c 1
b 0
f 0
dl 0
loc 377
rs 0
cc 56
nc 8408
nop 23

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