Passed
Push — 1.11.x ( 73095b...3fbd99 )
by Angel Fernando Quiroz
09:40
created

Agenda::addEvent()   F

Complexity

Conditions 32
Paths 1296

Size

Total Lines 263
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\AgendaEventInvitation;
6
use Chamilo\CoreBundle\Entity\AgendaEventInvitee;
7
use Chamilo\CoreBundle\Entity\AgendaEventSubscriber;
8
use Chamilo\CoreBundle\Entity\AgendaEventSubscription;
9
use Chamilo\CoreBundle\Entity\AgendaReminder;
10
use Chamilo\CoreBundle\Entity\PersonalAgenda;
11
use Chamilo\UserBundle\Entity\User;
12
13
/**
14
 * Class Agenda.
15
 *
16
 * @author: Julio Montoya <[email protected]>
17
 */
18
class Agenda
19
{
20
    public $events = [];
21
    /** @var string Current type */
22
    public $type = 'personal';
23
    public $types = ['personal', 'admin', 'course'];
24
    public $sessionId = 0;
25
    public $senderId;
26
    /** @var array */
27
    public $course;
28
    /** @var string */
29
    public $comment;
30
    public $eventStudentPublicationColor;
31
    /** @var array */
32
    private $sessionInfo;
33
    /** @var bool */
34
    private $isAllowedToEdit;
35
36
    /**
37
     * Constructor.
38
     *
39
     * @param string $type
40
     * @param int    $senderId  Optional The user sender ID
41
     * @param int    $courseId  Optional. The course ID
42
     * @param int    $sessionId Optional The session ID
43
     */
44
    public function __construct(
45
        $type,
46
        $senderId = 0,
47
        $courseId = 0,
48
        $sessionId = 0
49
    ) {
50
        // Table definitions
51
        $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
52
        $this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
53
        $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
54
        $this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
55
56
        $this->setType($type);
57
        $this->setSenderId($senderId ?: api_get_user_id());
58
        $isAllowToEdit = false;
59
60
        switch ($type) {
61
            case 'course':
62
                $sessionId = $sessionId ?: api_get_session_id();
63
                $sessionInfo = api_get_session_info($sessionId);
64
                $this->setSessionId($sessionId);
65
                $this->setSessionInfo($sessionInfo);
66
67
                // Setting the course object if we are in a course
68
                $courseInfo = api_get_course_info_by_id($courseId);
69
                if (!empty($courseInfo)) {
70
                    $this->set_course($courseInfo);
71
                }
72
73
                // Check if teacher/admin rights.
74
                $isAllowToEdit = api_is_allowed_to_edit(false, true);
75
                // Check course setting.
76
                if (api_get_course_setting('allow_user_edit_agenda') == '1'
77
                    && api_is_allowed_in_course()
78
                ) {
79
                    $isAllowToEdit = true;
80
                }
81
82
                $groupId = api_get_group_id();
83
                if (!empty($groupId)) {
84
                    $groupInfo = GroupManager::get_group_properties($groupId);
85
                    $userHasAccess = GroupManager::user_has_access(
86
                        api_get_user_id(),
87
                        $groupInfo['iid'],
88
                        GroupManager::GROUP_TOOL_CALENDAR
89
                    );
90
                    $isTutor = GroupManager::is_tutor_of_group(
91
                        api_get_user_id(),
92
                        $groupInfo
93
                    );
94
95
                    $isGroupAccess = $userHasAccess || $isTutor;
96
                    $isAllowToEdit = false;
97
                    if ($isGroupAccess) {
98
                        $isAllowToEdit = true;
99
                    }
100
                }
101
102
                if (false === $isAllowToEdit && !empty($sessionId)) {
103
                    $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
104
                    if ($allowDhrToEdit) {
105
                        $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
106
                        if ($isHrm) {
107
                            $isAllowToEdit = true;
108
                        }
109
                    }
110
                }
111
                break;
112
            case 'admin':
113
                $isAllowToEdit = api_is_platform_admin();
114
                break;
115
            case 'personal':
116
                $isAllowToEdit = !api_is_anonymous();
117
                break;
118
        }
119
120
        $this->setIsAllowedToEdit($isAllowToEdit);
121
        $this->events = [];
122
        $agendaColors = array_merge(
123
            [
124
                'platform' => 'red', //red
125
                'course' => '#458B00', //green
126
                'group' => '#A0522D', //siena
127
                'session' => '#00496D', // kind of green
128
                'other_session' => '#999', // kind of green
129
                'personal' => 'steel blue', //steel blue
130
                'student_publication' => '#FF8C00', //DarkOrange
131
            ],
132
            api_get_configuration_value('agenda_colors') ?: []
133
        );
134
135
        // Event colors
136
        $this->event_platform_color = $agendaColors['platform'];
137
        $this->event_course_color = $agendaColors['course'];
138
        $this->event_group_color = $agendaColors['group'];
139
        $this->event_session_color = $agendaColors['session'];
140
        $this->eventOtherSessionColor = $agendaColors['other_session'];
141
        $this->event_personal_color = $agendaColors['personal'];
142
        $this->eventStudentPublicationColor = $agendaColors['student_publication'];
143
    }
144
145
    /**
146
     * @param int $senderId
147
     */
148
    public function setSenderId($senderId)
149
    {
150
        $this->senderId = (int) $senderId;
151
    }
152
153
    /**
154
     * @return int
155
     */
156
    public function getSenderId()
157
    {
158
        return $this->senderId;
159
    }
160
161
    /**
162
     * @param string $type can be 'personal', 'admin'  or  'course'
163
     */
164
    public function setType($type)
165
    {
166
        $type = (string) trim($type);
167
        $typeList = $this->getTypes();
168
        if (in_array($type, $typeList, true)) {
169
            $this->type = $type;
170
        }
171
    }
172
173
    /**
174
     * Returns the type previously set (and filtered) through setType
175
     * If setType() was not called, then type defaults to "personal" as
176
     * set in the class definition.
177
     */
178
    public function getType()
179
    {
180
        if (isset($this->type)) {
181
            return $this->type;
182
        }
183
    }
184
185
    /**
186
     * @param int $id
187
     */
188
    public function setSessionId($id)
189
    {
190
        $this->sessionId = (int) $id;
191
    }
192
193
    /**
194
     * @param array $sessionInfo
195
     */
196
    public function setSessionInfo($sessionInfo)
197
    {
198
        $this->sessionInfo = $sessionInfo;
199
    }
200
201
    /**
202
     * @return int $id
203
     */
204
    public function getSessionId()
205
    {
206
        return $this->sessionId;
207
    }
208
209
    /**
210
     * @param array $courseInfo
211
     */
212
    public function set_course($courseInfo)
213
    {
214
        $this->course = $courseInfo;
215
    }
216
217
    /**
218
     * @return array
219
     */
220
    public function getTypes()
221
    {
222
        return $this->types;
223
    }
224
225
    /**
226
     * Adds an event to the calendar.
227
     *
228
     * @param string $start                 datetime format: 2012-06-14 09:00:00 in local time
229
     * @param string $end                   datetime format: 2012-06-14 09:00:00 in local time
230
     * @param string $allDay                (true, false)
231
     * @param string $title
232
     * @param string $content
233
     * @param array  $usersToSend           array('everyone') or a list of user/group ids
234
     * @param bool   $addAsAnnouncement     event as a *course* announcement
235
     * @param int    $parentEventId
236
     * @param array  $attachmentArray       array of $_FILES['']
237
     * @param array  $attachmentCommentList
238
     * @param string $eventComment
239
     * @param string $color
240
     *
241
     * @return int
242
     */
243
    public function addEvent(
244
        $start,
245
        $end,
246
        $allDay,
247
        $title,
248
        $content,
249
        $usersToSend = [],
250
        $addAsAnnouncement = false,
251
        $parentEventId = null,
252
        $attachmentArray = [],
253
        $attachmentCommentList = [],
254
        $eventComment = null,
255
        $color = '',
256
        array $inviteesList = [],
257
        bool $isCollective = false,
258
        array $reminders = [],
259
        int $careerId = 0,
260
        int $promotionId = 0,
261
        int $subscriptionVisibility = 0,
262
        ?int $subscriptionItemId = null,
263
        int $maxSubscriptions = 0
264
    ) {
265
        $start = api_get_utc_datetime($start);
266
        $end = api_get_utc_datetime($end);
267
        $allDay = isset($allDay) && ($allDay === 'true' || $allDay == 1) ? 1 : 0;
268
        $id = null;
269
270
        $em = Database::getManager();
271
272
        switch ($this->type) {
273
            case 'personal':
274
                $attributes = [
275
                    'user' => api_get_user_id(),
276
                    'title' => $title,
277
                    'text' => $content,
278
                    'date' => $start,
279
                    'enddate' => $end,
280
                    'all_day' => $allDay,
281
                    'color' => $color,
282
                ];
283
284
                $id = Database::insert(
285
                    $this->tbl_personal_agenda,
286
                    $attributes
287
                );
288
289
                if (api_get_configuration_value('agenda_collective_invitations')) {
290
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
291
                }
292
293
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
294
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
295
296
                    if ($personalEvent->hasInvitation()
297
                        && !($personalEvent->getInvitation() instanceof AgendaEventSubscription)
298
                    ) {
299
                        break;
300
                    }
301
302
                    $personalEvent
303
                        ->setSubscriptionVisibility($subscriptionVisibility)
304
                        ->setSubscriptionItemId($subscriptionItemId ?: null)
305
                    ;
306
307
                    $subscription = (new AgendaEventSubscription())
308
                        ->setCreator(api_get_user_entity(api_get_user_id()))
309
                        ->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0)
310
                    ;
311
312
                    $personalEvent
313
                        ->setCollective(false)
314
                        ->setInvitation($subscription)
315
                    ;
316
317
                    $em->flush();
318
                }
319
                break;
320
            case 'course':
321
                $attributes = [
322
                    'title' => $title,
323
                    'content' => $content,
324
                    'start_date' => $start,
325
                    'end_date' => $end,
326
                    'all_day' => $allDay,
327
                    'session_id' => $this->getSessionId(),
328
                    'c_id' => $this->course['real_id'],
329
                    'comment' => $eventComment,
330
                    'color' => $color,
331
                ];
332
333
                if (!empty($parentEventId)) {
334
                    $attributes['parent_event_id'] = $parentEventId;
335
                }
336
                $this->deleteEventIfAlreadyExists($start, $end, $allDay, $title);
337
                $senderId = $this->getSenderId();
338
                $sessionId = $this->getSessionId();
339
340
                // Simple course event.
341
                $id = Database::insert($this->tbl_course_agenda, $attributes);
342
343
                if ($id) {
344
                    $sql = "UPDATE ".$this->tbl_course_agenda." SET id = iid WHERE iid = $id";
345
                    Database::query($sql);
346
347
                    $groupId = api_get_group_id();
348
                    $groupInfo = [];
349
                    if ($groupId) {
350
                        $groupInfo = GroupManager::get_group_properties(
351
                            $groupId
352
                        );
353
                    }
354
355
                    if (!empty($usersToSend)) {
356
                        $sendTo = $this->parseSendToArray($usersToSend);
357
                        if ($sendTo['everyone']) {
358
                            api_item_property_update(
359
                                $this->course,
360
                                TOOL_CALENDAR_EVENT,
361
                                $id,
362
                                'AgendaAdded',
363
                                $senderId,
364
                                $groupInfo,
365
                                '',
366
                                $start,
367
                                $end,
368
                                $sessionId
369
                            );
370
                            api_item_property_update(
371
                                $this->course,
372
                                TOOL_CALENDAR_EVENT,
373
                                $id,
374
                                'visible',
375
                                $senderId,
376
                                $groupInfo,
377
                                '',
378
                                $start,
379
                                $end,
380
                                $sessionId
381
                            );
382
                        } else {
383
                            // Storing the selected groups
384
                            if (!empty($sendTo['groups'])) {
385
                                foreach ($sendTo['groups'] as $group) {
386
                                    $groupInfoItem = [];
387
                                    if ($group) {
388
                                        $groupInfoItem = GroupManager::get_group_properties($group);
389
                                    }
390
391
                                    api_item_property_update(
392
                                        $this->course,
393
                                        TOOL_CALENDAR_EVENT,
394
                                        $id,
395
                                        'AgendaAdded',
396
                                        $senderId,
397
                                        $groupInfoItem,
398
                                        0,
399
                                        $start,
400
                                        $end,
401
                                        $sessionId
402
                                    );
403
404
                                    api_item_property_update(
405
                                        $this->course,
406
                                        TOOL_CALENDAR_EVENT,
407
                                        $id,
408
                                        'visible',
409
                                        $senderId,
410
                                        $groupInfoItem,
411
                                        0,
412
                                        $start,
413
                                        $end,
414
                                        $sessionId
415
                                    );
416
                                }
417
                            }
418
419
                            // storing the selected users
420
                            if (!empty($sendTo['users'])) {
421
                                foreach ($sendTo['users'] as $userId) {
422
                                    api_item_property_update(
423
                                        $this->course,
424
                                        TOOL_CALENDAR_EVENT,
425
                                        $id,
426
                                        'AgendaAdded',
427
                                        $senderId,
428
                                        $groupInfo,
429
                                        $userId,
430
                                        $start,
431
                                        $end,
432
                                        $sessionId
433
                                    );
434
435
                                    api_item_property_update(
436
                                        $this->course,
437
                                        TOOL_CALENDAR_EVENT,
438
                                        $id,
439
                                        'visible',
440
                                        $senderId,
441
                                        $groupInfo,
442
                                        $userId,
443
                                        $start,
444
                                        $end,
445
                                        $sessionId
446
                                    );
447
                                }
448
                            }
449
                        }
450
                    }
451
452
                    // Add announcement.
453
                    if ($addAsAnnouncement) {
454
                        $this->storeAgendaEventAsAnnouncement(
455
                            $id,
456
                            $usersToSend
457
                        );
458
                    }
459
460
                    // Add attachment.
461
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
462
                        $counter = 0;
463
                        foreach ($attachmentArray as $attachmentItem) {
464
                            $this->addAttachment(
465
                                $id,
466
                                $attachmentItem,
467
                                $attachmentCommentList[$counter],
468
                                $this->course
469
                            );
470
                            $counter++;
471
                        }
472
                    }
473
                }
474
                break;
475
            case 'admin':
476
                if (api_is_platform_admin()) {
477
                    $attributes = [
478
                        'title' => $title,
479
                        'content' => $content,
480
                        'start_date' => $start,
481
                        'end_date' => $end,
482
                        'all_day' => $allDay,
483
                        'access_url_id' => api_get_current_access_url_id(),
484
                    ];
485
486
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
487
                        $attributes['career_id'] = $careerId;
488
                        $attributes['promotion_id'] = $promotionId;
489
                    }
490
491
                    $id = Database::insert(
492
                        $this->tbl_global_agenda,
493
                        $attributes
494
                    );
495
                }
496
                break;
497
        }
498
499
        if (api_get_configuration_value('agenda_reminders')) {
500
            foreach ($reminders as $reminder) {
501
                $this->addReminder($id, $reminder[0], $reminder[1]);
502
            }
503
        }
504
505
        return $id;
506
    }
507
508
    /**
509
     * Checks if an event exists and delete it (right before inserting a modified version in addEvent())
510
     * @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) {
3148
            $form->addRadio(
3149
                'invitation_type',
3150
                get_lang('Allowed'),
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
            $this->addCollectiveInvitationsFields($form, $personalEvent);
3163
        }
3164
3165
        if ($agendaEventSubscriptions) {
3166
            $this->addSubscriptionFields($form, $personalEvent);
3167
        }
3168
3169
        if (api_get_configuration_value('agenda_reminders')) {
3170
            $form->addHtml('<div id="notification_list">');
3171
3172
            if ($id) {
3173
                $this->addFieldsForRemindersToForm($id, $form);
3174
            }
3175
3176
            $form->addHtml('</div>');
3177
            $form->addButton('add_notification', get_lang('AddNotification'), 'bell-o')->setType('button');
3178
            $form->addHtml('<hr>');
3179
        }
3180
3181
        if (api_get_configuration_value('allow_careers_in_global_agenda') && 'admin' === $this->type) {
3182
            Career::addCareerFieldsToForm($form);
3183
            $form->addHtml('<hr>');
3184
        }
3185
3186
        if ($id) {
3187
            $form->addButtonUpdate(get_lang('ModifyEvent'));
3188
        } else {
3189
            $form->addButtonSave(get_lang('AgendaAdd'));
3190
        }
3191
3192
        $form->setDefaults($params);
3193
        $form->addRule(
3194
            'date_range',
3195
            get_lang('ThisFieldIsRequired'),
3196
            'required'
3197
        );
3198
        $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
3199
3200
        return $form;
3201
    }
3202
3203
    private function addCollectiveInvitationsFields(FormValidator $form, ?PersonalAgenda $personalEvent)
3204
    {
3205
        $invitees = [];
3206
        $isCollective = false;
3207
        $withInvitation = false;
3208
3209
        if ($personalEvent) {
3210
            $eventInvitation = $personalEvent->getInvitation();
3211
            $withInvitation = !($eventInvitation instanceof AgendaEventSubscription);
3212
3213
            if ($withInvitation) {
3214
                foreach ($eventInvitation->getInvitees() as $invitee) {
3215
                    $inviteeUser = $invitee->getUser();
3216
3217
                    $invitees[$inviteeUser->getId()] = $inviteeUser->getCompleteNameWithUsername();
3218
                }
3219
            }
3220
3221
            $isCollective = $personalEvent->isCollective();
3222
        }
3223
3224
        $form->addHtml(
3225
            '<div id="invitations-block" style="display: '.($withInvitation ? 'block;' : 'none;').'">'
3226
        );
3227
        $form->addHeader(get_lang('Invitations'));
3228
        $form->addSelectAjax(
3229
            'invitees',
3230
            get_lang('Invitees'),
3231
            $invitees,
3232
            [
3233
                'multiple' => 'multiple',
3234
                'url' => api_get_path(WEB_AJAX_PATH).'message.ajax.php?a=find_users',
3235
            ]
3236
        );
3237
        $form->addCheckBox('collective', '', get_lang('IsItEditableByTheInvitees'));
3238
        $form->addHtml('<hr>');
3239
        $form->addHtml('</div>');
3240
3241
        $form->setDefaults([
3242
            'invitees' => array_keys($invitees),
3243
            'collective' => $isCollective
3244
        ]);
3245
    }
3246
3247
    private function addSubscriptionFields(FormValidator $form, ?PersonalAgenda $personalEvent)
3248
    {
3249
        $subscribers = [];
3250
        $withSubscription = false;
3251
        $maxSubscriptions = 0;
3252
        $groupId = null;
3253
3254
        if ($personalEvent) {
3255
            $eventInvitation = $personalEvent->getInvitation();
3256
            $withSubscription = $eventInvitation instanceof AgendaEventSubscription;
3257
            $maxSubscriptions = $withSubscription ? $eventInvitation->getMaxAttendees() : 0;
3258
            $groupId = $personalEvent->getSubscriptionItemId();
3259
3260
            $subscribers = self::getInviteesForPersonalEvent($personalEvent->getId(), AgendaEventSubscriber::class);
3261
            $subscribers = array_combine(
3262
                array_column($subscribers, 'id'),
3263
                array_column($subscribers, 'name')
3264
            );
3265
        }
3266
3267
        $form->addHtml(
3268
            '<div id="subscriptions-block" style="display: '.($withSubscription ? 'block;' : 'none;').'">'
3269
        );
3270
        $form->addHeader(get_lang('Subscriptions'));
3271
        $form->addSelect(
3272
            'subscription_visibility',
3273
            get_lang('AllowSubscriptions'),
3274
            [
3275
                AgendaEventSubscription::SUBSCRIPTION_NO => get_lang('No'),
3276
                AgendaEventSubscription::SUBSCRIPTION_ALL => get_lang('AllUsersOfThePlatform'),
3277
                AgendaEventSubscription::SUBSCRIPTION_CLASS => get_lang('UsersInsideClass'),
3278
            ]
3279
        );
3280
        $slctItem = $form->addSelectAjax(
3281
            'subscription_item',
3282
            get_lang('SocialGroup').' / '.get_lang('Class'),
3283
            [],
3284
            [
3285
                'url' => api_get_path(WEB_AJAX_PATH).'usergroup.ajax.php?a=get_class_by_keyword',
3286
                'disabled' => 'disabled',
3287
            ]
3288
        );
3289
3290
        $form->addNumeric(
3291
            'max_subscriptions',
3292
            ['', get_lang('MaxSubscriptionsLeaveEmptyToNotLimit')],
3293
            [
3294
                'disabled' => 'disabled',
3295
                'step' => 1,
3296
                'min' => 0,
3297
                'value' => 0,
3298
            ]
3299
        );
3300
        $form->addHtml("<script>
3301
            $(function () {
3302
                $('#add_event_subscription_visibility')
3303
                    .on('change', function () {
3304
                        $('#max_subscriptions').prop('disabled', this.value == 0);
3305
                        $('#add_event_subscription_item').prop('disabled', this.value != 2);
3306
                    })
3307
                    .trigger('change');
3308
            })
3309
            </script>
3310
        ");
3311
3312
        $form->addSelect(
3313
            'subscribers',
3314
            get_lang('Subscribers'),
3315
            $subscribers,
3316
            ['multiple' => 'multiple']
3317
        );
3318
3319
        $form->setDefaults([
3320
            'subscribers' => array_keys($subscribers),
3321
            'max_subscriptions' => $maxSubscriptions,
3322
        ]);
3323
3324
        if ($groupId) {
3325
            $objUserGroup = new UserGroup();
3326
3327
            $groupInfo = $objUserGroup->get($groupId);
3328
3329
            $slctItem->addOption($groupInfo['name'], $groupId);
3330
        }
3331
3332
        $form->addHtml('</div>');
3333
    }
3334
3335
    public function addFieldsForRemindersToForm(int $eventId, FormValidator $form)
3336
    {
3337
        $remindersList = $this->parseEventReminders(
3338
            $this->getEventReminders($eventId)
3339
        );
3340
3341
        foreach ($remindersList as $reminderInfo) {
3342
            $form->addHtml('<div class="form-group">');
3343
            $form
3344
                ->addNumeric('notification_count[]', '', ['step' => 1, 'min' => 0])
3345
                ->setValue($reminderInfo['date_interval'][0])
3346
            ;
3347
            $form
3348
                ->addSelect(
3349
                'notification_period[]',
3350
                '',
3351
                    [
3352
                        'i' => get_lang('Minutes'),
3353
                        'h' => get_lang('Hours'),
3354
                        'd' => get_lang('Days'),
3355
                    ]
3356
                )
3357
                ->setValue($reminderInfo['date_interval'][1])
3358
            ;
3359
            $form->addHtml('<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>');
3360
            $form->addHtml(
3361
                '<div class="text-right col-sm-2">'
3362
                .'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>'
3363
                .'</div>'
3364
            );
3365
            $form->addHtml('</div>');
3366
        }
3367
3368
        $renderer = $form->defaultRenderer();
3369
        $renderer->setElementTemplate(
3370
            '<div class="col-sm-offset-2 col-sm-3">{element}</div>',
3371
            'notification_count[]'
3372
        );
3373
        $renderer->setElementTemplate(
3374
            '<div class="col-sm-3">{element}</div>',
3375
            'notification_period[]'
3376
        );
3377
    }
3378
3379
    /**
3380
     * @param FormValidator $form
3381
     * @param array         $sendTo               array('everyone' => false, 'users' => [1, 2], 'groups' => [3, 4])
3382
     * @param array         $attributes
3383
     * @param bool          $addOnlyItemsInSendTo
3384
     * @param bool          $required
3385
     *
3386
     * @return bool
3387
     */
3388
    public function showToForm(
3389
        $form,
3390
        $sendTo = [],
3391
        $attributes = [],
3392
        $addOnlyItemsInSendTo = false,
3393
        $required = false
3394
    ) {
3395
        if ($this->type != 'course') {
3396
            return false;
3397
        }
3398
3399
        $order = 'lastname';
3400
        if (api_is_western_name_order()) {
3401
            $order = 'firstname';
3402
        }
3403
3404
        $userList = CourseManager::get_user_list_from_course_code(
3405
            api_get_course_id(),
3406
            $this->sessionId,
3407
            null,
3408
            $order
3409
        );
3410
3411
        $groupList = CourseManager::get_group_list_of_course(
3412
            api_get_course_id(),
3413
            $this->sessionId
3414
        );
3415
3416
        $this->setSendToSelect(
3417
            $form,
3418
            $groupList,
3419
            $userList,
3420
            $sendTo,
3421
            $attributes,
3422
            $addOnlyItemsInSendTo,
3423
            $required
3424
        );
3425
3426
        return true;
3427
    }
3428
3429
    /**
3430
     * @param int   $id
3431
     * @param int   $visibility 0= invisible, 1 visible
3432
     * @param array $courseInfo
3433
     * @param int   $userId
3434
     */
3435
    public static function changeVisibility(
3436
        $id,
3437
        $visibility,
3438
        $courseInfo,
3439
        $userId = null
3440
    ) {
3441
        $id = intval($id);
3442
        if (empty($userId)) {
3443
            $userId = api_get_user_id();
3444
        } else {
3445
            $userId = intval($userId);
3446
        }
3447
3448
        if ($visibility == 0) {
3449
            api_item_property_update(
3450
                $courseInfo,
3451
                TOOL_CALENDAR_EVENT,
3452
                $id,
3453
                'invisible',
3454
                $userId
3455
            );
3456
        } else {
3457
            api_item_property_update(
3458
                $courseInfo,
3459
                TOOL_CALENDAR_EVENT,
3460
                $id,
3461
                'visible',
3462
                $userId
3463
            );
3464
        }
3465
    }
3466
3467
    /**
3468
     * Get repeat types.
3469
     *
3470
     * @return array
3471
     */
3472
    public static function getRepeatTypes()
3473
    {
3474
        return [
3475
            'daily' => get_lang('RepeatDaily'),
3476
            'weekly' => get_lang('RepeatWeekly'),
3477
            'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
3478
            //monthlyByDay"> get_lang('RepeatMonthlyByDay');
3479
            //monthlyByDayR' => get_lang('RepeatMonthlyByDayR'),
3480
            'yearly' => get_lang('RepeatYearly'),
3481
        ];
3482
    }
3483
3484
    /**
3485
     * Show a list with all the attachments according to the post's id.
3486
     *
3487
     * @param int   $eventId
3488
     * @param array $courseInfo
3489
     *
3490
     * @return array with the post info
3491
     */
3492
    public function getAttachmentList($eventId, $courseInfo)
3493
    {
3494
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3495
        $courseId = (int) $courseInfo['real_id'];
3496
        $eventId = (int) $eventId;
3497
3498
        $sql = "SELECT id, path, filename, comment
3499
                FROM $tableAttachment
3500
                WHERE
3501
                    c_id = $courseId AND
3502
                    agenda_id = $eventId";
3503
        $result = Database::query($sql);
3504
        $list = [];
3505
        if (Database::num_rows($result) != 0) {
3506
            $list = Database::store_result($result, 'ASSOC');
3507
        }
3508
3509
        return $list;
3510
    }
3511
3512
    /**
3513
     * Show a list with all the attachments according to the post's id.
3514
     *
3515
     * @param int   $attachmentId
3516
     * @param int   $eventId
3517
     * @param array $courseInfo
3518
     *
3519
     * @return array with the post info
3520
     */
3521
    public function getAttachment($attachmentId, $eventId, $courseInfo)
3522
    {
3523
        if (empty($courseInfo) || empty($attachmentId) || empty($eventId)) {
3524
            return [];
3525
        }
3526
3527
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3528
        $courseId = (int) $courseInfo['real_id'];
3529
        $eventId = (int) $eventId;
3530
        $attachmentId = (int) $attachmentId;
3531
3532
        $row = [];
3533
        $sql = "SELECT id, path, filename, comment
3534
                FROM $tableAttachment
3535
                WHERE
3536
                    c_id = $courseId AND
3537
                    agenda_id = $eventId AND
3538
                    id = $attachmentId
3539
                ";
3540
        $result = Database::query($sql);
3541
        if (Database::num_rows($result) != 0) {
3542
            $row = Database::fetch_array($result, 'ASSOC');
3543
        }
3544
3545
        return $row;
3546
    }
3547
3548
    /**
3549
     * Add an attachment file into agenda.
3550
     *
3551
     * @param int    $eventId
3552
     * @param array  $fileUserUpload ($_FILES['user_upload'])
3553
     * @param string $comment        about file
3554
     * @param array  $courseInfo
3555
     *
3556
     * @return string
3557
     */
3558
    public function addAttachment(
3559
        $eventId,
3560
        $fileUserUpload,
3561
        $comment,
3562
        $courseInfo
3563
    ) {
3564
        $agenda_table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3565
        $eventId = (int) $eventId;
3566
3567
        // Storing the attachments
3568
        $upload_ok = false;
3569
        if (!empty($fileUserUpload['name'])) {
3570
            $upload_ok = process_uploaded_file($fileUserUpload);
3571
        }
3572
3573
        if (!empty($upload_ok)) {
3574
            $courseDir = $courseInfo['directory'].'/upload/calendar';
3575
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
3576
            $uploadDir = $sys_course_path.$courseDir;
3577
3578
            // Try to add an extension to the file if it hasn't one
3579
            $new_file_name = add_ext_on_mime(
3580
                stripslashes($fileUserUpload['name']),
3581
                $fileUserUpload['type']
3582
            );
3583
3584
            // user's file name
3585
            $file_name = $fileUserUpload['name'];
3586
3587
            if (!filter_extension($new_file_name)) {
3588
                return Display::return_message(
3589
                    get_lang('UplUnableToSaveFileFilteredExtension'),
3590
                    'error'
3591
                );
3592
            } else {
3593
                $new_file_name = uniqid('');
3594
                $new_path = $uploadDir.'/'.$new_file_name;
3595
                $result = @move_uploaded_file(
3596
                    $fileUserUpload['tmp_name'],
3597
                    $new_path
3598
                );
3599
                $courseId = api_get_course_int_id();
3600
                $size = intval($fileUserUpload['size']);
3601
                // Storing the attachments if any
3602
                if ($result) {
3603
                    $params = [
3604
                        'c_id' => $courseId,
3605
                        'filename' => $file_name,
3606
                        'comment' => $comment,
3607
                        'path' => $new_file_name,
3608
                        'agenda_id' => $eventId,
3609
                        'size' => $size,
3610
                    ];
3611
                    $id = Database::insert($agenda_table_attachment, $params);
3612
                    if ($id) {
3613
                        $sql = "UPDATE $agenda_table_attachment
3614
                                SET id = iid WHERE iid = $id";
3615
                        Database::query($sql);
3616
3617
                        api_item_property_update(
3618
                            $courseInfo,
3619
                            'calendar_event_attachment',
3620
                            $id,
3621
                            'AgendaAttachmentAdded',
3622
                            api_get_user_id()
3623
                        );
3624
                    }
3625
                }
3626
            }
3627
        }
3628
    }
3629
3630
    /**
3631
     * @param int    $attachmentId
3632
     * @param int    $eventId
3633
     * @param array  $fileUserUpload
3634
     * @param string $comment
3635
     * @param array  $courseInfo
3636
     */
3637
    public function updateAttachment(
3638
        $attachmentId,
3639
        $eventId,
3640
        $fileUserUpload,
3641
        $comment,
3642
        $courseInfo
3643
    ) {
3644
        $attachment = $this->getAttachment(
3645
            $attachmentId,
3646
            $eventId,
3647
            $courseInfo
3648
        );
3649
        if (!empty($attachment)) {
3650
            $this->deleteAttachmentFile($attachmentId, $courseInfo);
3651
        }
3652
        $this->addAttachment($eventId, $fileUserUpload, $comment, $courseInfo);
3653
    }
3654
3655
    /**
3656
     * This function delete a attachment file by id.
3657
     *
3658
     * @param int   $attachmentId
3659
     * @param array $courseInfo
3660
     *
3661
     * @return string
3662
     */
3663
    public function deleteAttachmentFile($attachmentId, $courseInfo)
3664
    {
3665
        $table = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
3666
        $attachmentId = (int) $attachmentId;
3667
        $courseId = $courseInfo['real_id'];
3668
3669
        if (empty($courseId) || empty($attachmentId)) {
3670
            return false;
3671
        }
3672
3673
        $sql = "DELETE FROM $table
3674
                WHERE c_id = $courseId AND id = ".$attachmentId;
3675
        $result = Database::query($sql);
3676
3677
        // update item_property
3678
        api_item_property_update(
3679
            $courseInfo,
3680
            'calendar_event_attachment',
3681
            $attachmentId,
3682
            'AgendaAttachmentDeleted',
3683
            api_get_user_id()
3684
        );
3685
3686
        if (!empty($result)) {
3687
            return Display::return_message(
3688
                get_lang("AttachmentFileDeleteSuccess"),
3689
                'confirmation'
3690
            );
3691
        }
3692
    }
3693
3694
    /**
3695
     * @param int $eventId
3696
     *
3697
     * @return array
3698
     */
3699
    public function getAllRepeatEvents($eventId)
3700
    {
3701
        $events = [];
3702
        $eventId = (int) $eventId;
3703
3704
        switch ($this->type) {
3705
            case 'personal':
3706
                break;
3707
            case 'course':
3708
                if (!empty($this->course['real_id'])) {
3709
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
3710
                            WHERE
3711
                                c_id = ".$this->course['real_id']." AND
3712
                                parent_event_id = ".$eventId;
3713
                    $result = Database::query($sql);
3714
                    if (Database::num_rows($result)) {
3715
                        while ($row = Database::fetch_array($result, 'ASSOC')) {
3716
                            $events[] = $row;
3717
                        }
3718
                    }
3719
                }
3720
                break;
3721
        }
3722
3723
        return $events;
3724
    }
3725
3726
    /**
3727
     * @param int $eventId
3728
     * @param int $courseId
3729
     *
3730
     * @return bool
3731
     */
3732
    public function hasChildren($eventId, $courseId)
3733
    {
3734
        $eventId = (int) $eventId;
3735
        $courseId = (int) $courseId;
3736
3737
        $sql = "SELECT count(DISTINCT(id)) as count
3738
                FROM ".$this->tbl_course_agenda."
3739
                WHERE
3740
                    c_id = $courseId AND
3741
                    parent_event_id = $eventId";
3742
        $result = Database::query($sql);
3743
        if (Database::num_rows($result)) {
3744
            $row = Database::fetch_array($result, 'ASSOC');
3745
3746
            return $row['count'] > 0;
3747
        }
3748
3749
        return false;
3750
    }
3751
3752
    public function displayActions(string $view, ?string $filter = ''): string
3753
    {
3754
        $groupInfo = GroupManager::get_group_properties(api_get_group_id());
3755
        $groupIid = $groupInfo['iid'] ?? 0;
3756
3757
        $codePath = api_get_path(WEB_CODE_PATH);
3758
3759
        $currentUserId = api_get_user_id();
3760
        $cidReq = api_get_cidreq();
3761
3762
        $actionsLeft = Display::url(
3763
            Display::return_icon('calendar.png', get_lang('Calendar'), [], ICON_SIZE_MEDIUM),
3764
            $codePath."calendar/agenda_js.php?type={$this->type}&$cidReq"
3765
        );
3766
        $actionsLeft .= Display::url(
3767
            Display::return_icon('week.png', get_lang('AgendaList'), [], ICON_SIZE_MEDIUM),
3768
            $codePath."calendar/agenda_list.php?type={$this->type}&$cidReq"
3769
        );
3770
3771
        $isAllowedToEdit = api_is_allowed_to_edit(false, true);
3772
3773
        $form = '';
3774
        if ($isAllowedToEdit
3775
            || ('personal' === $this->type && !api_is_anonymous() && 'true' === api_get_setting('allow_personal_agenda'))
3776
            || (
3777
                '1' === api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous() &&
3778
                api_is_allowed_to_session_edit(false, true))
3779
            || (
3780
                GroupManager::user_has_access($currentUserId, $groupIid, GroupManager::GROUP_TOOL_CALENDAR)
3781
                && GroupManager::is_tutor_of_group($currentUserId, $groupInfo)
3782
            )
3783
        ) {
3784
            $actionsLeft .= Display::url(
3785
                Display::return_icon('new_event.png', get_lang('AgendaAdd'), [], ICON_SIZE_MEDIUM),
3786
                $codePath."calendar/agenda.php?action=add&type={$this->type}&$cidReq"
3787
            );
3788
3789
            $actionsLeft .= Display::url(
3790
                Display::return_icon('import_calendar.png', get_lang('ICalFileImport'), [], ICON_SIZE_MEDIUM),
3791
                $codePath."calendar/agenda.php?action=importical&type={$this->type}&$cidReq"
3792
            );
3793
3794
            if ($this->type === 'course') {
3795
                if (!isset($_GET['action'])) {
3796
                    $form = new FormValidator(
3797
                        'form-search',
3798
                        'post',
3799
                        '',
3800
                        '',
3801
                        [],
3802
                        FormValidator::LAYOUT_INLINE
3803
                    );
3804
                    $attributes = [
3805
                        'multiple' => false,
3806
                        'id' => 'select_form_id_search',
3807
                    ];
3808
                    $selectedValues = $this->parseAgendaFilter($filter);
3809
                    $this->showToForm($form, $selectedValues, $attributes);
3810
                    $form = $form->returnForm();
3811
                }
3812
3813
                if (true === api_get_configuration_value('agenda_reminders') && $isAllowedToEdit) {
3814
                    $actionsLeft .= Display::url(
3815
                        Display::return_icon(
3816
                            'course_request_pending.png',
3817
                            get_lang('ImportCourseEvents'),
3818
                            [],
3819
                            ICON_SIZE_MEDIUM
3820
                        ),
3821
                        $codePath."calendar/agenda.php?action=import_course_agenda_reminders&type={$this->type}&$cidReq"
3822
                    );
3823
                }
3824
            }
3825
        }
3826
3827
        if ($this->type === 'personal' && !api_is_anonymous()) {
3828
            $actionsLeft .= Display::url(
3829
                Display::return_icon('1day.png', get_lang('SessionsPlanCalendar'), [], ICON_SIZE_MEDIUM),
3830
                $codePath.'calendar/planification.php'
3831
            );
3832
3833
            if (api_is_student_boss() || api_is_platform_admin()) {
3834
                $actionsLeft .= Display::url(
3835
                    Display::return_icon('calendar-user.png', get_lang('MyStudentsSchedule'), [], ICON_SIZE_MEDIUM),
3836
                    $codePath.'mySpace/calendar_plan.php'
3837
                );
3838
            }
3839
        }
3840
3841
        if (api_is_platform_admin()
3842
            || api_is_teacher()
3843
            || api_is_student_boss()
3844
            || api_is_drh()
3845
            || api_is_session_admin()
3846
            || api_is_coach()
3847
        ) {
3848
            if ($this->type == 'personal') {
3849
                $form = '';
3850
                if (!isset($_GET['action'])) {
3851
                    $form = new FormValidator(
3852
                        'form-search',
3853
                        'get',
3854
                        api_get_self().'?type=personal&',
3855
                        '',
3856
                        [],
3857
                        FormValidator::LAYOUT_INLINE
3858
                    );
3859
3860
                    $sessions = [];
3861
3862
                    if (api_is_drh()) {
3863
                        $sessionList = SessionManager::get_sessions_followed_by_drh($currentUserId);
3864
                        if (!empty($sessionList)) {
3865
                            foreach ($sessionList as $sessionItem) {
3866
                                $sessions[$sessionItem['id']] = strip_tags($sessionItem['name']);
3867
                            }
3868
                        }
3869
                    } else {
3870
                        $sessions = SessionManager::get_sessions_by_user($currentUserId);
3871
                        $sessions = array_column($sessions, 'session_name', 'session_id');
3872
                    }
3873
3874
                    $form->addHidden('type', 'personal');
3875
                    $sessions = ['0' => get_lang('SelectAnOption')] + $sessions;
3876
3877
                    $form->addSelect(
3878
                        'session_id',
3879
                        get_lang('Session'),
3880
                        $sessions,
3881
                        ['id' => 'session_id', 'onchange' => 'submit();']
3882
                    );
3883
3884
                    $form->addButton('reset', get_lang('Reset'), 'eraser');
3885
                    $form = $form->returnForm();
3886
                }
3887
            }
3888
        }
3889
3890
        $actionsRight = '';
3891
        if ($view == 'calendar') {
3892
            $actionsRight .= $form;
3893
        }
3894
3895
        return Display::toolbarAction(
3896
            'toolbar-agenda',
3897
            [$actionsLeft, $actionsRight]
3898
        );
3899
    }
3900
3901
    /**
3902
     * @return FormValidator
3903
     */
3904
    public function getImportCalendarForm()
3905
    {
3906
        $form = new FormValidator(
3907
            'frm_import_ical',
3908
            'post',
3909
            api_get_self().'?action=importical&type='.$this->type,
3910
            ['enctype' => 'multipart/form-data']
3911
        );
3912
        $form->addHeader(get_lang('ICalFileImport'));
3913
        $form->addElement('file', 'ical_import', get_lang('ICalFileImport'));
3914
        $form->addRule(
3915
            'ical_import',
3916
            get_lang('ThisFieldIsRequired'),
3917
            'required'
3918
        );
3919
        $form->addButtonImport(get_lang('Import'), 'ical_submit');
3920
3921
        return $form;
3922
    }
3923
3924
    /**
3925
     * @param array $courseInfo
3926
     * @param $file
3927
     *
3928
     * @return false|string
3929
     */
3930
    public function importEventFile($courseInfo, $file)
3931
    {
3932
        $charset = api_get_system_encoding();
3933
        $filepath = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
3934
        $messages = [];
3935
3936
        if (!@move_uploaded_file($file['tmp_name'], $filepath)) {
3937
            error_log(
3938
                'Problem moving uploaded file: '.$file['error'].' in '.__FILE__.' line '.__LINE__
3939
            );
3940
3941
            return false;
3942
        }
3943
3944
        $data = file_get_contents($filepath);
3945
3946
        $trans = [
3947
            'DAILY' => 'daily',
3948
            'WEEKLY' => 'weekly',
3949
            'MONTHLY' => 'monthlyByDate',
3950
            'YEARLY' => 'yearly',
3951
        ];
3952
        $sentTo = ['everyone' => true];
3953
        $calendar = Sabre\VObject\Reader::read($data);
3954
        $currentTimeZone = api_get_timezone();
3955
        if (!empty($calendar->VEVENT)) {
3956
            /** @var Sabre\VObject\Component\VEvent $event */
3957
            foreach ($calendar->VEVENT as $event) {
3958
                $tempDate = $event->DTSTART->getValue();
3959
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3960
                    $event->DTSTART->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3961
                }
3962
                $tempDate = $event->DTEND->getValue();
3963
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3964
                    $event->DTEND->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3965
                }
3966
                $start = $event->DTSTART->getDateTime();
3967
                $end = $event->DTEND->getDateTime();
3968
                //Sabre\VObject\DateTimeParser::parseDateTime(string $dt, \Sabre\VObject\DateTimeZone $tz)
3969
3970
                $startDateTime = api_get_local_time(
3971
                    $start->format('Y-m-d H:i:s'),
3972
                    $currentTimeZone,
3973
                    $start->format('e')
3974
                );
3975
                $endDateTime = api_get_local_time(
3976
                    $end->format('Y-m-d H:i'),
3977
                    $currentTimeZone,
3978
                    $end->format('e')
3979
                );
3980
                $title = api_convert_encoding(
3981
                    (string) $event->summary,
3982
                    $charset,
3983
                    'UTF-8'
3984
                );
3985
                $description = api_convert_encoding(
3986
                    (string) $event->description,
3987
                    $charset,
3988
                    'UTF-8'
3989
                );
3990
3991
                $id = $this->addEvent(
3992
                    $startDateTime,
3993
                    $endDateTime,
3994
                    'false',
3995
                    $title,
3996
                    $description,
3997
                    $sentTo
3998
                );
3999
4000
                $messages[] = " $title - ".$startDateTime." - ".$endDateTime;
4001
4002
                //$attendee = (string)$event->attendee;
4003
                /** @var Sabre\VObject\Property\ICalendar\Recur $repeat */
4004
                $repeat = $event->RRULE;
4005
                if ($id && !empty($repeat)) {
4006
                    $repeat = $repeat->getParts();
4007
                    $freq = $trans[$repeat['FREQ']];
4008
4009
                    if (isset($repeat['UNTIL']) && !empty($repeat['UNTIL'])) {
4010
                        // Check if datetime or just date (strlen == 8)
4011
                        if (strlen($repeat['UNTIL']) == 8) {
4012
                            // Fix the datetime format to avoid exception in the next step
4013
                            $repeat['UNTIL'] .= 'T000000';
4014
                        }
4015
                        $until = Sabre\VObject\DateTimeParser::parseDateTime(
4016
                            $repeat['UNTIL'],
4017
                            new DateTimeZone($currentTimeZone)
4018
                        );
4019
                        $until = $until->format('Y-m-d H:i:s');
4020
                        $this->addRepeatedItem(
4021
                            $id,
4022
                            $freq,
4023
                            $until,
4024
                            $sentTo
4025
                        );
4026
                    }
4027
4028
                    if (!empty($repeat['COUNT'])) {
4029
                        /*$count = $repeat['COUNT'];
4030
                        $interval = $repeat['INTERVAL'];
4031
                        $endDate = null;
4032
                        switch($freq) {
4033
                            case 'daily':
4034
                                $start = api_strtotime($startDateTime);
4035
                                $date = new DateTime($startDateTime);
4036
                                $days = $count * $interval;
4037
                                var_dump($days);
4038
                                $date->add(new DateInterval("P".$days."D"));
4039
                                $endDate = $date->format('Y-m-d H:i');
4040
                                //$endDate = $count *
4041
                                for ($i = 0; $i < $count; $i++) {
4042
                                    $days = 86400 * 7
4043
                                }
4044
                            }
4045
                        }*/
4046
                        //$res = agenda_add_repeat_item($courseInfo, $id, $freq, $count, $attendee);
4047
                        /*$this->addRepeatedItem(
4048
                            $id,
4049
                            $freq,
4050
                            $endDate,
4051
                            $sentTo
4052
                        );*/
4053
                    }
4054
                }
4055
            }
4056
        }
4057
4058
        if (!empty($messages)) {
4059
            $messages = implode('<br /> ', $messages);
4060
        } else {
4061
            $messages = get_lang('NoAgendaItems');
4062
        }
4063
4064
        return $messages;
4065
    }
4066
4067
    /**
4068
     * Parse filter turns USER:12 to ['users' => [12])] or G:1 ['groups' => [1]].
4069
     *
4070
     * @param int $filter
4071
     *
4072
     * @return array
4073
     */
4074
    public function parseAgendaFilter($filter)
4075
    {
4076
        $everyone = false;
4077
        $groupId = null;
4078
        $userId = null;
4079
4080
        if ($filter == 'everyone') {
4081
            $everyone = true;
4082
        } else {
4083
            if (substr($filter, 0, 1) == 'G') {
4084
                $groupId = str_replace('GROUP:', '', $filter);
4085
            } else {
4086
                $userId = str_replace('USER:', '', $filter);
4087
            }
4088
        }
4089
        if (empty($userId) && empty($groupId)) {
4090
            $everyone = true;
4091
        }
4092
4093
        return [
4094
            'everyone' => $everyone,
4095
            'users' => [$userId],
4096
            'groups' => [$groupId],
4097
        ];
4098
    }
4099
4100
    /**
4101
     *    This function retrieves all the agenda items of all the courses the user is subscribed to.
4102
     */
4103
    public static function get_myagendaitems(
4104
        $user_id,
4105
        $courses_dbs,
4106
        $month,
4107
        $year
4108
    ) {
4109
        $user_id = intval($user_id);
4110
4111
        $items = [];
4112
        $my_list = [];
4113
4114
        // get agenda-items for every course
4115
        foreach ($courses_dbs as $key => $array_course_info) {
4116
            //databases of the courses
4117
            $TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
4118
            $TABLE_ITEMPROPERTY = Database::get_course_table(
4119
                TABLE_ITEM_PROPERTY
4120
            );
4121
4122
            $group_memberships = GroupManager::get_group_ids(
4123
                $array_course_info['real_id'],
4124
                $user_id
4125
            );
4126
            $course_user_status = CourseManager::getUserInCourseStatus(
4127
                $user_id,
4128
                $array_course_info['real_id']
4129
            );
4130
            // if the user is administrator of that course we show all the agenda items
4131
            if ($course_user_status == '1') {
4132
                //echo "course admin";
4133
                $sqlquery = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4134
							FROM ".$TABLEAGENDA." agenda,
4135
								 ".$TABLE_ITEMPROPERTY." ip
4136
							WHERE agenda.id = ip.ref
4137
							AND MONTH(agenda.start_date)='".$month."'
4138
							AND YEAR(agenda.start_date)='".$year."'
4139
							AND ip.tool='".TOOL_CALENDAR_EVENT."'
4140
							AND ip.visibility='1'
4141
							GROUP BY agenda.id
4142
							ORDER BY start_date ";
4143
            } else {
4144
                // if the user is not an administrator of that course
4145
                if (is_array($group_memberships) && count(
4146
                        $group_memberships
4147
                    ) > 0
4148
                ) {
4149
                    $sqlquery = "SELECT	agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4150
								FROM ".$TABLEAGENDA." agenda,
4151
									".$TABLE_ITEMPROPERTY." ip
4152
								WHERE agenda.id = ip.ref
4153
								AND MONTH(agenda.start_date)='".$month."'
4154
								AND YEAR(agenda.start_date)='".$year."'
4155
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4156
								AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4157
                            ", ",
4158
                            $group_memberships
4159
                        ).")) )
4160
								AND ip.visibility='1'
4161
								ORDER BY start_date ";
4162
                } else {
4163
                    $sqlquery = "SELECT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
4164
								FROM ".$TABLEAGENDA." agenda,
4165
									".$TABLE_ITEMPROPERTY." ip
4166
								WHERE agenda.id = ip.ref
4167
								AND MONTH(agenda.start_date)='".$month."'
4168
								AND YEAR(agenda.start_date)='".$year."'
4169
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
4170
								AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL)
4171
								AND ip.visibility='1'
4172
								ORDER BY start_date ";
4173
                }
4174
            }
4175
            $result = Database::query($sqlquery);
4176
4177
            while ($item = Database::fetch_array($result, 'ASSOC')) {
4178
                $agendaday = -1;
4179
                if (!empty($item['start_date'])) {
4180
                    $item['start_date'] = api_get_local_time(
4181
                        $item['start_date']
4182
                    );
4183
                    $item['start_date_tms'] = api_strtotime(
4184
                        $item['start_date']
4185
                    );
4186
                    $agendaday = date("j", $item['start_date_tms']);
4187
                }
4188
                if (!empty($item['end_date'])) {
4189
                    $item['end_date'] = api_get_local_time($item['end_date']);
4190
                }
4191
4192
                $url = api_get_path(
4193
                        WEB_CODE_PATH
4194
                    )."calendar/agenda.php?cidReq=".urlencode(
4195
                        $array_course_info["code"]
4196
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4197
4198
                $item['url'] = $url;
4199
                $item['course_name'] = $array_course_info['title'];
4200
                $item['calendar_type'] = 'course';
4201
                $item['course_id'] = $array_course_info['course_id'];
4202
4203
                $my_list[$agendaday][] = $item;
4204
            }
4205
        }
4206
4207
        // sorting by hour for every day
4208
        $agendaitems = [];
4209
        foreach ($items as $agendaday => $tmpitems) {
4210
            if (!isset($agendaitems[$agendaday])) {
4211
                $agendaitems[$agendaday] = '';
4212
            }
4213
            sort($tmpitems);
4214
            foreach ($tmpitems as $val) {
4215
                $agendaitems[$agendaday] .= $val;
4216
            }
4217
        }
4218
4219
        return $my_list;
4220
    }
4221
4222
    /**
4223
     * This function retrieves one personal agenda item returns it.
4224
     *
4225
     * @param    array    The array containing existing events. We add to this array.
4226
     * @param    int        Day
4227
     * @param    int        Month
4228
     * @param    int        Year (4 digits)
4229
     * @param    int        Week number
4230
     * @param    string    Type of view (month_view, week_view, day_view)
4231
     *
4232
     * @return array The results of the database query, or null if not found
4233
     */
4234
    public static function get_global_agenda_items(
4235
        $agendaitems,
4236
        $day,
4237
        $month,
4238
        $year,
4239
        $week,
4240
        $type
4241
    ) {
4242
        $tbl_global_agenda = Database::get_main_table(
4243
            TABLE_MAIN_SYSTEM_CALENDAR
4244
        );
4245
        $month = intval($month);
4246
        $year = intval($year);
4247
        $week = intval($week);
4248
        $day = intval($day);
4249
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4250
4251
        $current_access_url_id = api_get_current_access_url_id();
4252
4253
        if ($type == "month_view" || $type == "") {
4254
            // We are in month view
4255
            $sql = "SELECT * FROM ".$tbl_global_agenda."
4256
                    WHERE
4257
                        MONTH(start_date) = ".$month." AND
4258
                        YEAR(start_date) = ".$year."  AND
4259
                        access_url_id = $current_access_url_id
4260
                    ORDER BY start_date ASC";
4261
        }
4262
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4263
        if ($type == "week_view") { // we are in week view
4264
            $start_end_day_of_week = self::calculate_start_end_of_week(
4265
                $week,
4266
                $year
4267
            );
4268
            $start_day = $start_end_day_of_week['start']['day'];
4269
            $start_month = $start_end_day_of_week['start']['month'];
4270
            $start_year = $start_end_day_of_week['start']['year'];
4271
            $end_day = $start_end_day_of_week['end']['day'];
4272
            $end_month = $start_end_day_of_week['end']['month'];
4273
            $end_year = $start_end_day_of_week['end']['year'];
4274
            // in sql statements you have to use year-month-day for date calculations
4275
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4276
            $start_filter = api_get_utc_datetime($start_filter);
4277
4278
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4279
            $end_filter = api_get_utc_datetime($end_filter);
4280
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."' AND  access_url_id = $current_access_url_id ";
4281
        }
4282
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4283
        if ($type == "day_view") { // we are in day view
4284
            // we could use mysql date() function but this is only available from 4.1 and higher
4285
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4286
            $start_filter = api_get_utc_datetime($start_filter);
4287
4288
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4289
            $end_filter = api_get_utc_datetime($end_filter);
4290
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."'  AND  access_url_id = $current_access_url_id";
4291
        }
4292
4293
        $result = Database::query($sql);
4294
4295
        while ($item = Database::fetch_array($result)) {
4296
            if (!empty($item['start_date'])) {
4297
                $item['start_date'] = api_get_local_time($item['start_date']);
4298
                $item['start_date_tms'] = api_strtotime($item['start_date']);
4299
            }
4300
            if (!empty($item['end_date'])) {
4301
                $item['end_date'] = api_get_local_time($item['end_date']);
4302
            }
4303
4304
            // we break the date field in the database into a date and a time part
4305
            $agenda_db_date = explode(" ", $item['start_date']);
4306
            $date = $agenda_db_date[0];
4307
            $time = $agenda_db_date[1];
4308
            // we divide the date part into a day, a month and a year
4309
            $agendadate = explode("-", $date);
4310
            $year = intval($agendadate[0]);
4311
            $month = intval($agendadate[1]);
4312
            $day = intval($agendadate[2]);
4313
            // we divide the time part into hour, minutes, seconds
4314
            $agendatime = explode(":", $time);
4315
            $hour = $agendatime[0];
4316
            $minute = $agendatime[1];
4317
            $second = $agendatime[2];
4318
4319
            if ($type == 'month_view') {
4320
                $item['calendar_type'] = 'global';
4321
                $agendaitems[$day][] = $item;
4322
                continue;
4323
            }
4324
4325
            $start_time = api_format_date(
4326
                $item['start_date'],
4327
                TIME_NO_SEC_FORMAT
4328
            );
4329
            $end_time = '';
4330
            if (!empty($item['end_date'])) {
4331
                $end_time = ' - '.api_format_date(
4332
                        $item['end_date'],
4333
                        DATE_TIME_FORMAT_LONG
4334
                    );
4335
            }
4336
4337
            // if the student has specified a course we a add a link to that course
4338
            if ($item['course'] != "") {
4339
                $url = api_get_path(
4340
                        WEB_CODE_PATH
4341
                    )."admin/agenda.php?cidReq=".urlencode(
4342
                        $item['course']
4343
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4344
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4345
            } else {
4346
                $course_link = "";
4347
            }
4348
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4349
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4350
            if ($type !== "day_view") {
4351
                // This is the array construction for the WEEK or MONTH view
4352
                //Display the Agenda global in the tab agenda (administrator)
4353
                $agendaitems[$day] .= "<i>$start_time $end_time</i>&nbsp;-&nbsp;";
4354
                $agendaitems[$day] .= "<b>".get_lang('GlobalEvent')."</b>";
4355
                $agendaitems[$day] .= "<div>".$item['title']."</div><br>";
4356
            } else {
4357
                // this is the array construction for the DAY view
4358
                $halfhour = 2 * $agendatime['0'];
4359
                if ($agendatime['1'] >= '30') {
4360
                    $halfhour = $halfhour + 1;
4361
                }
4362
                if (!is_array($agendaitems[$halfhour])) {
4363
                    $content = $agendaitems[$halfhour];
4364
                }
4365
                $agendaitems[$halfhour] = $content."<div><i>$hour:$minute</i> <b>".get_lang(
4366
                        'GlobalEvent'
4367
                    ).":  </b>".$item['title']."</div>";
4368
            }
4369
        }
4370
4371
        return $agendaitems;
4372
    }
4373
4374
    /**
4375
     * This function retrieves all the personal agenda items and add them to the agenda items found by the other
4376
     * functions.
4377
     */
4378
    public static function get_personal_agenda_items(
4379
        $user_id,
4380
        $agendaitems,
4381
        $day,
4382
        $month,
4383
        $year,
4384
        $week,
4385
        $type
4386
    ) {
4387
        $tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
4388
        $user_id = intval($user_id);
4389
4390
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
4391
        if ($type === "month_view" || $type === "") {
4392
            // we are in month view
4393
            $sql = "SELECT * FROM $tbl_personal_agenda
4394
                    WHERE
4395
                        user='".$user_id."' AND
4396
                        MONTH(date)='".$month."' AND
4397
                        YEAR(date) = '".$year."'
4398
                     ORDER BY date ASC";
4399
        }
4400
4401
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
4402
        // we are in week view
4403
        if ($type == "week_view") {
4404
            $start_end_day_of_week = self::calculate_start_end_of_week(
4405
                $week,
4406
                $year
4407
            );
4408
            $start_day = $start_end_day_of_week['start']['day'];
4409
            $start_month = $start_end_day_of_week['start']['month'];
4410
            $start_year = $start_end_day_of_week['start']['year'];
4411
            $end_day = $start_end_day_of_week['end']['day'];
4412
            $end_month = $start_end_day_of_week['end']['month'];
4413
            $end_year = $start_end_day_of_week['end']['year'];
4414
            // in sql statements you have to use year-month-day for date calculations
4415
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
4416
            $start_filter = api_get_utc_datetime($start_filter);
4417
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
4418
            $end_filter = api_get_utc_datetime($end_filter);
4419
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4420
        }
4421
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
4422
        if ($type == "day_view") {
4423
            // we are in day view
4424
            // we could use mysql date() function but this is only available from 4.1 and higher
4425
            $start_filter = $year."-".$month."-".$day." 00:00:00";
4426
            $start_filter = api_get_utc_datetime($start_filter);
4427
            $end_filter = $year."-".$month."-".$day." 23:59:59";
4428
            $end_filter = api_get_utc_datetime($end_filter);
4429
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
4430
        }
4431
4432
        $result = Database::query($sql);
4433
        while ($item = Database::fetch_array($result, 'ASSOC')) {
4434
            $time_minute = api_convert_and_format_date(
4435
                $item['date'],
4436
                TIME_NO_SEC_FORMAT
4437
            );
4438
            $item['date'] = api_get_local_time($item['date']);
4439
            $item['start_date_tms'] = api_strtotime($item['date']);
4440
            $item['content'] = $item['text'];
4441
4442
            // we break the date field in the database into a date and a time part
4443
            $agenda_db_date = explode(" ", $item['date']);
4444
            $date = $agenda_db_date[0];
4445
            $time = $agenda_db_date[1];
4446
            // we divide the date part into a day, a month and a year
4447
            $agendadate = explode("-", $item['date']);
4448
            $year = intval($agendadate[0]);
4449
            $month = intval($agendadate[1]);
4450
            $day = intval($agendadate[2]);
4451
            // we divide the time part into hour, minutes, seconds
4452
            $agendatime = explode(":", $time);
4453
4454
            $hour = $agendatime[0];
4455
            $minute = $agendatime[1];
4456
            $second = $agendatime[2];
4457
4458
            if ($type == 'month_view') {
4459
                $item['calendar_type'] = 'personal';
4460
                $item['start_date'] = $item['date'];
4461
                $agendaitems[$day][] = $item;
4462
                continue;
4463
            }
4464
4465
            // if the student has specified a course we a add a link to that course
4466
            if ($item['course'] != "") {
4467
                $url = api_get_path(
4468
                        WEB_CODE_PATH
4469
                    )."calendar/agenda.php?cidReq=".urlencode(
4470
                        $item['course']
4471
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
4472
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
4473
            } else {
4474
                $course_link = "";
4475
            }
4476
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
4477
            // if we have a day_view we use a half hour as index => key 33 = 16h30
4478
            if ($type !== "day_view") {
4479
                // This is the array construction for the WEEK or MONTH view
4480
4481
                //Display events in agenda
4482
                $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 />";
4483
            } else {
4484
                // this is the array construction for the DAY view
4485
                $halfhour = 2 * $agendatime['0'];
4486
                if ($agendatime['1'] >= '30') {
4487
                    $halfhour = $halfhour + 1;
4488
                }
4489
4490
                //Display events by list
4491
                $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>";
4492
            }
4493
        }
4494
4495
        return $agendaitems;
4496
    }
4497
4498
    /**
4499
     * Show the monthcalender of the given month.
4500
     *
4501
     * @param    array    Agendaitems
4502
     * @param    int    Month number
4503
     * @param    int    Year number
4504
     * @param    array    Array of strings containing long week day names (deprecated, you can send an empty array
4505
     *                          instead)
4506
     * @param    string    The month name
4507
     */
4508
    public static function display_mymonthcalendar(
4509
        $user_id,
4510
        $agendaitems,
4511
        $month,
4512
        $year,
4513
        $weekdaynames,
4514
        $monthName,
4515
        $show_content = true
4516
    ) {
4517
        global $DaysShort, $course_path;
4518
        //Handle leap year
4519
        $numberofdays = [
4520
            0,
4521
            31,
4522
            28,
4523
            31,
4524
            30,
4525
            31,
4526
            30,
4527
            31,
4528
            31,
4529
            30,
4530
            31,
4531
            30,
4532
            31,
4533
        ];
4534
        if (($year % 400 == 0) or ($year % 4 == 0 and $year % 100 != 0)) {
4535
            $numberofdays[2] = 29;
4536
        }
4537
        //Get the first day of the month
4538
        $dayone = getdate(mktime(0, 0, 0, $month, 1, $year));
4539
        //Start the week on monday
4540
        $startdayofweek = $dayone['wday'] != 0 ? ($dayone['wday'] - 1) : 6;
4541
        $g_cc = (isset($_GET['courseCode']) ? $_GET['courseCode'] : '');
4542
4543
        $next_month = ($month == 1 ? 12 : $month - 1);
4544
        $prev_month = ($month == 12 ? 1 : $month + 1);
4545
4546
        $next_year = ($month == 1 ? $year - 1 : $year);
4547
        $prev_year = ($month == 12 ? $year + 1 : $year);
4548
4549
        if ($show_content) {
4550
            $back_url = Display::url(
4551
                get_lang('Previous'),
4552
                api_get_self()."?coursePath=".urlencode(
4553
                    $course_path
4554
                )."&courseCode=".Security::remove_XSS(
4555
                    $g_cc
4556
                )."&action=view&view=month&month=".$next_month."&year=".$next_year
4557
            );
4558
            $next_url = Display::url(
4559
                get_lang('Next'),
4560
                api_get_self()."?coursePath=".urlencode(
4561
                    $course_path
4562
                )."&courseCode=".Security::remove_XSS(
4563
                    $g_cc
4564
                )."&action=view&view=month&month=".$prev_month."&year=".$prev_year
4565
            );
4566
        } else {
4567
            $back_url = Display::url(
4568
                get_lang('Previous'),
4569
                '',
4570
                [
4571
                    'onclick' => "load_calendar('".$user_id."','".$next_month."', '".$next_year."'); ",
4572
                    'class' => 'btn ui-button ui-widget ui-state-default',
4573
                ]
4574
            );
4575
            $next_url = Display::url(
4576
                get_lang('Next'),
4577
                '',
4578
                [
4579
                    'onclick' => "load_calendar('".$user_id."','".$prev_month."', '".$prev_year."'); ",
4580
                    'class' => 'pull-right btn ui-button ui-widget ui-state-default',
4581
                ]
4582
            );
4583
        }
4584
        $html = '';
4585
        $html .= '<div class="actions">';
4586
        $html .= '<div class="row">';
4587
        $html .= '<div class="col-md-4">'.$back_url.'</div>';
4588
        $html .= '<div class="col-md-4"><p class="agenda-title text-center">'.$monthName." ".$year.'</p></div>';
4589
        $html .= '<div class="col-md-4">'.$next_url.'</div>';
4590
        $html .= '</div>';
4591
        $html .= '</div>';
4592
        $html .= '<table id="agenda_list2" class="table table-bordered">';
4593
        $html .= '<tr>';
4594
        for ($ii = 1; $ii < 8; $ii++) {
4595
            $html .= '<td class="weekdays">'.$DaysShort[$ii % 7].'</td>';
4596
        }
4597
        $html .= '</tr>';
4598
4599
        $curday = -1;
4600
        $today = getdate();
4601
        while ($curday <= $numberofdays[$month]) {
4602
            $html .= "<tr>";
4603
            for ($ii = 0; $ii < 7; $ii++) {
4604
                if (($curday == -1) && ($ii == $startdayofweek)) {
4605
                    $curday = 1;
4606
                }
4607
                if (($curday > 0) && ($curday <= $numberofdays[$month])) {
4608
                    $bgcolor = $class = 'class="days_week"';
4609
                    $dayheader = Display::div(
4610
                        $curday,
4611
                        ['class' => 'agenda_day']
4612
                    );
4613
                    if (($curday == $today['mday']) && ($year == $today['year']) && ($month == $today['mon'])) {
4614
                        $class = "class=\"days_today\" style=\"width:10%;\"";
4615
                    }
4616
4617
                    $html .= "<td ".$class.">".$dayheader;
4618
4619
                    if (!empty($agendaitems[$curday])) {
4620
                        $items = $agendaitems[$curday];
4621
                        $items = msort($items, 'start_date_tms');
4622
4623
                        foreach ($items as $value) {
4624
                            $value['title'] = Security::remove_XSS(
4625
                                $value['title']
4626
                            );
4627
                            $start_time = api_format_date(
4628
                                $value['start_date'],
4629
                                TIME_NO_SEC_FORMAT
4630
                            );
4631
                            $end_time = '';
4632
4633
                            if (!empty($value['end_date'])) {
4634
                                $end_time = '-&nbsp;<i>'.api_format_date(
4635
                                        $value['end_date'],
4636
                                        DATE_TIME_FORMAT_LONG
4637
                                    ).'</i>';
4638
                            }
4639
                            $complete_time = '<i>'.api_format_date(
4640
                                    $value['start_date'],
4641
                                    DATE_TIME_FORMAT_LONG
4642
                                ).'</i>&nbsp;'.$end_time;
4643
                            $time = '<i>'.$start_time.'</i>';
4644
4645
                            switch ($value['calendar_type']) {
4646
                                case 'personal':
4647
                                    $bg_color = '#D0E7F4';
4648
                                    $icon = Display::return_icon(
4649
                                        'user.png',
4650
                                        get_lang('MyAgenda'),
4651
                                        [],
4652
                                        ICON_SIZE_SMALL
4653
                                    );
4654
                                    break;
4655
                                case 'global':
4656
                                    $bg_color = '#FFBC89';
4657
                                    $icon = Display::return_icon(
4658
                                        'view_remove.png',
4659
                                        get_lang('GlobalEvent'),
4660
                                        [],
4661
                                        ICON_SIZE_SMALL
4662
                                    );
4663
                                    break;
4664
                                case 'course':
4665
                                    $bg_color = '#CAFFAA';
4666
                                    $icon_name = 'course.png';
4667
                                    if (!empty($value['session_id'])) {
4668
                                        $icon_name = 'session.png';
4669
                                    }
4670
                                    if ($show_content) {
4671
                                        $icon = Display::url(
4672
                                            Display::return_icon(
4673
                                                $icon_name,
4674
                                                $value['course_name'].' '.get_lang(
4675
                                                    'Course'
4676
                                                ),
4677
                                                [],
4678
                                                ICON_SIZE_SMALL
4679
                                            ),
4680
                                            $value['url']
4681
                                        );
4682
                                    } else {
4683
                                        $icon = Display::return_icon(
4684
                                            $icon_name,
4685
                                            $value['course_name'].' '.get_lang(
4686
                                                'Course'
4687
                                            ),
4688
                                            [],
4689
                                            ICON_SIZE_SMALL
4690
                                        );
4691
                                    }
4692
                                    break;
4693
                                default:
4694
                                    break;
4695
                            }
4696
4697
                            $result = '<div class="rounded_div_agenda" style="background-color:'.$bg_color.';">';
4698
4699
                            if ($show_content) {
4700
                                //Setting a personal event to green
4701
                                $icon = Display::div(
4702
                                    $icon,
4703
                                    ['style' => 'float:right']
4704
                                );
4705
4706
                                $link = $value['calendar_type'].'_'.$value['id'].'_'.$value['course_id'].'_'.$value['session_id'];
4707
4708
                                //Link to bubble
4709
                                $url = Display::url(
4710
                                    cut($value['title'], 40),
4711
                                    '#',
4712
                                    ['id' => $link, 'class' => 'opener']
4713
                                );
4714
                                $result .= $time.' '.$icon.' '.Display::div(
4715
                                        $url
4716
                                    );
4717
4718
                                //Hidden content
4719
                                $content = Display::div(
4720
                                    $icon.Display::tag(
4721
                                        'h2',
4722
                                        $value['course_name']
4723
                                    ).'<hr />'.Display::tag(
4724
                                        'h3',
4725
                                        $value['title']
4726
                                    ).$complete_time.'<hr />'.Security::remove_XSS(
4727
                                        $value['content']
4728
                                    )
4729
                                );
4730
4731
                                //Main div
4732
                                $result .= Display::div(
4733
                                    $content,
4734
                                    [
4735
                                        'id' => 'main_'.$link,
4736
                                        'class' => 'dialog',
4737
                                        'style' => 'display:none',
4738
                                    ]
4739
                                );
4740
                                $result .= '</div>';
4741
                                $html .= $result;
4742
                            } else {
4743
                                $html .= $result .= $icon.'</div>';
4744
                            }
4745
                        }
4746
                    }
4747
                    $html .= "</td>";
4748
                    $curday++;
4749
                } else {
4750
                    $html .= "<td></td>";
4751
                }
4752
            }
4753
            $html .= "</tr>";
4754
        }
4755
        $html .= "</table>";
4756
        echo $html;
4757
    }
4758
4759
    /**
4760
     * Get personal agenda items between two dates (=all events from all registered courses).
4761
     *
4762
     * @param int $user_id user ID of the user
4763
     * @param    string    Optional start date in datetime format (if no start date is given, uses today)
4764
     * @param    string    Optional end date in datetime format (if no date is given, uses one year from now)
4765
     *
4766
     * @return array array of events ordered by start date, in
4767
     *               [0]('datestart','dateend','title'),[1]('datestart','dateend','title','link','coursetitle') format,
4768
     *               where datestart and dateend are in yyyyMMddhhmmss format
4769
     *
4770
     * @deprecated use agenda events
4771
     */
4772
    public static function get_personal_agenda_items_between_dates(
4773
        $user_id,
4774
        $date_start = '',
4775
        $date_end = ''
4776
    ) {
4777
        $items = [];
4778
        if ($user_id != strval(intval($user_id))) {
4779
            return $items;
4780
        }
4781
        if (empty($date_start)) {
4782
            $date_start = date('Y-m-d H:i:s');
4783
        }
4784
        if (empty($date_end)) {
4785
            $date_end = date(
4786
                'Y-m-d H:i:s',
4787
                mktime(0, 0, 0, date("m"), date("d"), date("Y") + 1)
4788
            );
4789
        }
4790
        $expr = '/\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}/';
4791
        if (!preg_match($expr, $date_start)) {
4792
            return $items;
4793
        }
4794
        if (!preg_match($expr, $date_end)) {
4795
            return $items;
4796
        }
4797
4798
        // get agenda-items for every course
4799
        $courses = api_get_user_courses($user_id, false);
4800
        foreach ($courses as $id => $course) {
4801
            $c = api_get_course_info_by_id($course['real_id']);
4802
            //databases of the courses
4803
            $t_a = Database::get_course_table(TABLE_AGENDA, $course['db']);
4804
            $t_ip = Database::get_course_table(
4805
                TABLE_ITEM_PROPERTY,
4806
                $course['db']
4807
            );
4808
            // get the groups to which the user belong
4809
            $group_memberships = GroupManager::get_group_ids(
4810
                $course['db'],
4811
                $user_id
4812
            );
4813
            // if the user is administrator of that course we show all the agenda items
4814
            if ($course['status'] == '1') {
4815
                //echo "course admin";
4816
                $sqlquery = "SELECT ".
4817
                    " DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4818
                    " FROM ".$t_a." agenda, ".
4819
                    $t_ip." ip ".
4820
                    " WHERE agenda.id = ip.ref ".
4821
                    " AND agenda.start_date>='$date_start' ".
4822
                    " AND agenda.end_date<='$date_end' ".
4823
                    " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4824
                    " AND ip.visibility='1' ".
4825
                    " GROUP BY agenda.id ".
4826
                    " ORDER BY start_date ";
4827
            } else {
4828
                // if the user is not an administrator of that course, then...
4829
                if (is_array($group_memberships) && count(
4830
                        $group_memberships
4831
                    ) > 0
4832
                ) {
4833
                    $sqlquery = "SELECT ".
4834
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4835
                        " FROM ".$t_a." agenda, ".
4836
                        $t_ip." ip ".
4837
                        " WHERE agenda.id = ip.ref ".
4838
                        " AND agenda.start_date>='$date_start' ".
4839
                        " AND agenda.end_date<='$date_end' ".
4840
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4841
                        " AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4842
                            ", ",
4843
                            $group_memberships
4844
                        ).")) ) ".
4845
                        " AND ip.visibility='1' ".
4846
                        " ORDER BY start_date ";
4847
                } else {
4848
                    $sqlquery = "SELECT ".
4849
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4850
                        " FROM ".$t_a." agenda, ".
4851
                        $t_ip." ip ".
4852
                        " WHERE agenda.id = ip.ref ".
4853
                        " AND agenda.start_date>='$date_start' ".
4854
                        " AND agenda.end_date<='$date_end' ".
4855
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4856
                        " AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL) ".
4857
                        " AND ip.visibility='1' ".
4858
                        " ORDER BY start_date ";
4859
                }
4860
            }
4861
4862
            $result = Database::query($sqlquery);
4863
            while ($item = Database::fetch_array($result)) {
4864
                $agendaday = date("j", strtotime($item['start_date']));
4865
                $month = date("n", strtotime($item['start_date']));
4866
                $year = date("Y", strtotime($item['start_date']));
4867
                $URL = api_get_path(
4868
                        WEB_PATH
4869
                    )."main/calendar/agenda.php?cidReq=".urlencode(
4870
                        $course["code"]
4871
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4872
                list($year, $month, $day, $hour, $min, $sec) = explode(
4873
                    '[-: ]',
4874
                    $item['start_date']
4875
                );
4876
                $start_date = $year.$month.$day.$hour.$min;
4877
                list($year, $month, $day, $hour, $min, $sec) = explode(
4878
                    '[-: ]',
4879
                    $item['end_date']
4880
                );
4881
                $end_date = $year.$month.$day.$hour.$min;
4882
4883
                $items[] = [
4884
                    'datestart' => $start_date,
4885
                    'dateend' => $end_date,
4886
                    'title' => $item['title'],
4887
                    'link' => $URL,
4888
                    'coursetitle' => $c['name'],
4889
                ];
4890
            }
4891
        }
4892
4893
        return $items;
4894
    }
4895
4896
    /**
4897
     * This function calculates the startdate of the week (monday)
4898
     * and the enddate of the week (sunday)
4899
     * and returns it as an array.
4900
     */
4901
    public static function calculate_start_end_of_week($week_number, $year)
4902
    {
4903
        // determine the start and end date
4904
        // step 1: we calculate a timestamp for a day in this week
4905
        $random_day_in_week = mktime(
4906
                0,
4907
                0,
4908
                0,
4909
                1,
4910
                1,
4911
                $year
4912
            ) + ($week_number) * (7 * 24 * 60 * 60); // we calculate a random day in this week
4913
        // step 2: we which day this is (0=sunday, 1=monday, ...)
4914
        $number_day_in_week = date('w', $random_day_in_week);
4915
        // step 3: we calculate the timestamp of the monday of the week we are in
4916
        $start_timestamp = $random_day_in_week - (($number_day_in_week - 1) * 24 * 60 * 60);
4917
        // step 4: we calculate the timestamp of the sunday of the week we are in
4918
        $end_timestamp = $random_day_in_week + ((7 - $number_day_in_week + 1) * 24 * 60 * 60) - 3600;
4919
        // step 5: calculating the start_day, end_day, start_month, end_month, start_year, end_year
4920
        $start_day = date('j', $start_timestamp);
4921
        $start_month = date('n', $start_timestamp);
4922
        $start_year = date('Y', $start_timestamp);
4923
        $end_day = date('j', $end_timestamp);
4924
        $end_month = date('n', $end_timestamp);
4925
        $end_year = date('Y', $end_timestamp);
4926
        $start_end_array['start']['day'] = $start_day;
4927
        $start_end_array['start']['month'] = $start_month;
4928
        $start_end_array['start']['year'] = $start_year;
4929
        $start_end_array['end']['day'] = $end_day;
4930
        $start_end_array['end']['month'] = $end_month;
4931
        $start_end_array['end']['year'] = $end_year;
4932
4933
        return $start_end_array;
4934
    }
4935
4936
    /**
4937
     * @return bool
4938
     */
4939
    public function getIsAllowedToEdit()
4940
    {
4941
        return $this->isAllowedToEdit;
4942
    }
4943
4944
    /**
4945
     * @param bool $isAllowedToEdit
4946
     */
4947
    public function setIsAllowedToEdit($isAllowedToEdit)
4948
    {
4949
        $this->isAllowedToEdit = $isAllowedToEdit;
4950
    }
4951
4952
    /**
4953
     * Format needed for the Fullcalendar js lib.
4954
     *
4955
     * @param string $utcTime
4956
     *
4957
     * @return bool|string
4958
     */
4959
    public function formatEventDate($utcTime)
4960
    {
4961
        if ($utcTime instanceof DateTime) {
4962
            $eventDate = $utcTime;
4963
        } else {
4964
            $utcTimeZone = new DateTimeZone('UTC');
4965
            $eventDate = new DateTime($utcTime, $utcTimeZone);
4966
        }
4967
4968
        $platformTimeZone = new DateTimeZone(api_get_timezone());
4969
4970
        $eventDate->setTimezone($platformTimeZone);
4971
4972
        return $eventDate->format(DateTime::ISO8601);
4973
    }
4974
4975
    /**
4976
     * @throws \Doctrine\ORM\OptimisticLockException
4977
     * @throws \Doctrine\ORM\ORMException
4978
     * @throws \Doctrine\ORM\TransactionRequiredException
4979
     */
4980
    public static function saveCollectiveProperties(array $inviteeUserList, bool $isCollective, int $eventId)
4981
    {
4982
        if (empty($inviteeUserList)) {
4983
            return;
4984
        }
4985
4986
        $em = Database::getManager();
4987
4988
        $event = $em->find('ChamiloCoreBundle:PersonalAgenda', $eventId);
4989
4990
        $invitation = $event->getInvitation();
4991
4992
        if ($invitation instanceof AgendaEventSubscription) {
4993
            return;
4994
        }
4995
4996
        if (!$invitation) {
4997
            $invitation = new AgendaEventInvitation();
4998
            $invitation->setCreator(api_get_user_entity(api_get_user_id()));
4999
5000
            $event->setInvitation($invitation);
5001
        }
5002
5003
        $event->setCollective($isCollective);
5004
5005
        foreach ($inviteeUserList as $inviteeId) {
5006
            $userInvitee = api_get_user_entity($inviteeId);
5007
5008
            if (!$invitation->hasUserAsInvitee($userInvitee)) {
5009
                $invitee = new AgendaEventInvitee();
5010
                $invitee
5011
                    ->setUser($userInvitee)
5012
                    ->setInvitation($invitation)
5013
                ;
5014
5015
                $em->persist($invitee);
5016
            }
5017
        }
5018
5019
        $em->flush();
5020
    }
5021
5022
    public static function getJsForReminders(string $cssSelectorBtnAdd): string
5023
    {
5024
        return '
5025
            var template = \'<div class="form-group">\' +
5026
                \'<div class="col-sm-offset-2 col-sm-3">\' +
5027
                \'<input min="0" step="1" id="notification_count[]" type="number" class=" form-control" name="notification_count[]">\' +
5028
                \'</div>\' +
5029
                \'<div class="col-sm-3">\' +
5030
                \'<select class="form-control" name="notification_period[]" id="form_notification_period[]">\' +
5031
                \'<option value="i">'.get_lang('Minutes').'</option>\' +
5032
                \'<option value="h">'.get_lang('Hours').'</option>\' +
5033
                \'<option value="d">'.get_lang('Days').'</option>\' +
5034
                \'</select>\' +
5035
                \'</div>\' +
5036
                \'<div class="col-sm-2"><p class="form-control-static">'.get_lang('Before').'</p></div>\' +
5037
                \'<div class="text-right col-sm-2">\' +
5038
                \'<button class="btn btn-default delete-notification" type="button" aria-label="'.get_lang('Delete').'"><em class="fa fa-times"></em></button>\' +
5039
                \'</div>\' +
5040
                \'</div>\';
5041
5042
            $("'.$cssSelectorBtnAdd.'").on("click", function (e) {
5043
                e.preventDefault();
5044
5045
                $(template).appendTo("#notification_list");
5046
                $("#notification_list select").selectpicker("refresh");
5047
            });
5048
5049
            $("#notification_list").on("click", ".delete-notification", function (e) {
5050
                e.preventDefault();
5051
5052
                $(this).parents(".form-group").remove();
5053
            });';
5054
    }
5055
5056
    public static function returnGoogleCalendarUrl(int $userId): ?string
5057
    {
5058
        $extraFieldInfo = UserManager::get_extra_user_data_by_field($userId, 'google_calendar_url');
5059
5060
        if (empty($extraFieldInfo) || empty($extraFieldInfo['google_calendar_url'])) {
5061
            return null;
5062
        }
5063
5064
        return $extraFieldInfo['google_calendar_url'];
5065
    }
5066
5067
    public static function returnFullCalendarExtraSettings(): ?string
5068
    {
5069
        $settings = api_get_configuration_value('fullcalendar_settings');
5070
5071
        if (empty($settings) || empty($settings['settings'])) {
5072
            return null;
5073
        }
5074
5075
        $encoded = json_encode($settings['settings']);
5076
5077
        return substr($encoded, 1, -1).',';
5078
    }
5079
5080
    public static function returnOnHoverInfo()
5081
    {
5082
        $onHoverInfo = api_get_configuration_value('agenda_on_hover_info');
5083
5084
        if (!empty($onHoverInfo)) {
5085
            return $onHoverInfo['options'];
5086
        }
5087
5088
        return [
5089
            'comment' => true,
5090
            'description' => true,
5091
        ];
5092
    }
5093
5094
    private function editReminders(int $eventId, array $reminderList = [])
5095
    {
5096
        if (false === api_get_configuration_value('agenda_reminders')) {
5097
            return;
5098
        }
5099
5100
        $eventReminders = $this->parseEventReminders(
5101
            $this->getEventReminders($eventId)
5102
        );
5103
        $eventIntervalList = array_column($eventReminders, 'date_interval');
5104
5105
        foreach ($eventIntervalList as $eventIntervalInfo) {
5106
            if (!in_array($eventIntervalInfo, $reminderList)) {
5107
                $this->removeReminders($eventId, $eventIntervalInfo[0], $eventIntervalInfo[1]);
5108
            }
5109
        }
5110
5111
        foreach ($reminderList as $reminderInfo) {
5112
            if (!in_array($reminderInfo, $eventIntervalList)) {
5113
                $this->addReminder($eventId, $reminderInfo[0], $reminderInfo[1]);
5114
            }
5115
        }
5116
    }
5117
5118
    private static function isUserInvitedInEvent(int $id, int $userId): bool
5119
    {
5120
        $user = api_get_user_entity($userId);
5121
5122
        $event = Database::getManager()
5123
            ->getRepository('ChamiloCoreBundle:PersonalAgenda')
5124
            ->findOneByIdAndInvitee($id, $user)
5125
        ;
5126
5127
        return null !== $event;
5128
    }
5129
5130
    private function loadEventsAsInvitee(User $user, ?DateTime $startDate, ?DateTime $endDate)
5131
    {
5132
        $em = Database::getManager();
5133
        $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
5134
        $events = $eventRepo->getEventsForInvitee($user, $startDate, $endDate);
5135
5136
        foreach ($events as $event) {
5137
            $eventInfo = [];
5138
            $eventInfo['id'] = 'personal_'.$event->getId();
5139
            $eventInfo['title'] = $event->getTitle();
5140
            $eventInfo['className'] = 'personal';
5141
            $eventInfo['borderColor'] = $eventInfo['backgroundColor'] = $this->event_personal_color;
5142
            $eventInfo['editable'] = $event->isCollective();
5143
            $eventInfo['sent_to'] = get_lang('Me');
5144
            $eventInfo['type'] = 'personal';
5145
5146
            if ($event->getDate()) {
5147
                $eventInfo['start'] = $this->formatEventDate($event->getDate()->format('Y-m-d H:i:s'));
5148
                $eventInfo['start_date_localtime'] = api_get_local_time($event->getDate());
5149
            }
5150
5151
            if ($event->getEnddate()) {
5152
                $eventInfo['end'] = $this->formatEventDate($event->getEnddate()->format('Y-m-d H:i:s'));
5153
                $eventInfo['end_date_localtime'] = api_get_local_time($event->getEnddate());
5154
            }
5155
5156
            $eventInfo['description'] = $event->getText();
5157
            $eventInfo['allDay'] = $event->getAllDay();
5158
            $eventInfo['parent_event_id'] = 0;
5159
            $eventInfo['has_children'] = 0;
5160
            $eventInfo['collective'] = $event->isCollective();
5161
            $eventInfo['invitees'] = [];
5162
5163
            $invitation = $event->getInvitation();
5164
5165
            if ($invitation) {
5166
                foreach ($invitation->getInvitees() as $invitee) {
5167
                    $inviteeUser = $invitee->getUser();
5168
5169
                    $eventInfo['invitees'][] = [
5170
                        'id' => $inviteeUser->getId(),
5171
                        'name' => $inviteeUser->getCompleteNameWithUsername(),
5172
                    ];
5173
                }
5174
            }
5175
5176
            $this->events[] = $eventInfo;
5177
        }
5178
    }
5179
5180
    /**
5181
     * @throws Exception
5182
     */
5183
    private function convertSessionWithDuration(int $userId, array $sessionInfo, DateTime $start, DateTime $end): array
5184
    {
5185
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
5186
            $sessionInfo['session_id'],
5187
            $userId
5188
        );
5189
5190
        if (empty($courseAccess)) {
5191
            throw new Exception();
5192
        }
5193
5194
        $firstAccessDate = new DateTime($courseAccess['login_course_date'], new DateTimeZone('UTC'));
5195
        $lastAccessDate = clone $firstAccessDate;
5196
        $lastAccessDate->modify('+'.$sessionInfo['duration'].' days');
5197
5198
        if ($firstAccessDate->format('Y-m-d H:i:s') > $start
5199
            && $lastAccessDate->format('Y-m-d H:i:s') < $end
5200
        ) {
5201
            throw new Exception();
5202
        }
5203
5204
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5205
        $firstCourse = current($courseList);
5206
5207
        return [
5208
            'id' => 'session_'.$sessionInfo['id'],
5209
            'session_id' => $sessionInfo['id'],
5210
            'title' => $sessionInfo['name'],
5211
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5212
            'className' => 'personal',
5213
            'borderColor' => $this->event_personal_color,
5214
            'backgroundColor' => $this->event_personal_color,
5215
            'editable' => false,
5216
            'sent_to' => get_lang('Me'),
5217
            'type' => 'session',
5218
            'start' => $firstAccessDate->format(DateTime::ISO8601),
5219
            'start_date_localtime' => api_get_local_time($firstAccessDate),
5220
            'end' => $lastAccessDate->format(DateTime::ISO8601),
5221
            'end_date_localtime' => api_get_local_time($lastAccessDate),
5222
            'allDay' => 0,
5223
            'parent_event_id' => 0,
5224
            'has_children' => 0,
5225
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5226
        ];
5227
    }
5228
5229
    /**
5230
     * @throws Exception
5231
     */
5232
    private function convertSessionWithDates(array $sessionInfo, DateTime $start, DateTime $end): array
5233
    {
5234
        if ($sessionInfo['display_start_date'] < $start
5235
            && $sessionInfo['display_end_date'] > $end
5236
        ) {
5237
            throw new Exception();
5238
        }
5239
5240
        $courseList = SessionManager::get_course_list_by_session_id($sessionInfo['id']);
5241
        $firstCourse = current($courseList);
5242
5243
        return [
5244
            'id' => 'session_'.$sessionInfo['id'],
5245
            'session_id' => $sessionInfo['id'],
5246
            'title' => $sessionInfo['name'],
5247
            'description' => $sessionInfo['show_description'] ? $sessionInfo['description'] : '',
5248
            'className' => 'personal',
5249
            'borderColor' => $this->event_personal_color,
5250
            'backgroundColor' => $this->event_personal_color,
5251
            'editable' => false,
5252
            'sent_to' => get_lang('Me'),
5253
            'type' => 'session_subscription',
5254
            'start' => $sessionInfo['display_start_date'],
5255
            'start_date_localtime' => $sessionInfo['display_start_date']
5256
                ? $this->formatEventDate($sessionInfo['display_start_date'])
5257
                : '',
5258
            'end' => $sessionInfo['display_end_date'],
5259
            'end_date_localtime' => $sessionInfo['display_end_date']
5260
                ? $this->formatEventDate($sessionInfo['display_end_date'])
5261
                : '',
5262
            'allDay' => 0,
5263
            'parent_event_id' => 0,
5264
            'has_children' => 0,
5265
            'course_url' => api_get_course_url($firstCourse['code'], $sessionInfo['id']),
5266
        ];
5267
    }
5268
5269
    private function loadSessionsAsEvents(int $start, int $end)
5270
    {
5271
        if (false === api_get_configuration_value('personal_calendar_show_sessions_occupation')) {
5272
            return;
5273
        }
5274
5275
        $start = api_get_utc_datetime($start, false, true);
5276
        $end = api_get_utc_datetime($end, false, true);
5277
        $userInfo = api_get_user_info();
5278
        $sessionList = SessionManager::getSessionsFollowedByUser($userInfo['id'], $userInfo['status']);
5279
5280
        foreach ($sessionList as $sessionInfo) {
5281
            if (!empty($sessionInfo['duration'])) {
5282
                try {
5283
                    $this->events[] = $this->convertSessionWithDuration($userInfo['id'], $sessionInfo, $start, $end);
5284
                } catch (Exception $e) {
5285
                    continue;
5286
                }
5287
5288
                continue;
5289
            }
5290
5291
            if (empty($sessionInfo['display_start_date']) || empty($sessionInfo['display_end_date'])) {
5292
                continue;
5293
            }
5294
5295
            try {
5296
                $this->events[] = $this->convertSessionWithDates($sessionInfo, $start, $end);
5297
            } catch (Exception $e) {
5298
                continue;
5299
            }
5300
        }
5301
    }
5302
}
5303