Passed
Push — 1.11.x ( 36c06b...0359bd )
by Yannick
09:42 queued 13s
created

Agenda::addAttachment()   B

Complexity

Conditions 6

Size

Total Lines 65
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 44
nop 4
dl 0
loc 65
rs 8.5937
c 0
b 0
f 0

How to fix   Long Method   

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:

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