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

Agenda::editEvent()   F

Complexity

Conditions 55
Paths 8344

Size

Total Lines 367
Code Lines 219

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 219
c 0
b 0
f 0
dl 0
loc 367
rs 0
cc 55
nop 22
nc 8344

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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