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

Agenda::isUserInvitedInEvent()   A

Complexity

Conditions 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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