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

Agenda::addEvent()   F

Complexity

Conditions 30
Paths 1272

Size

Total Lines 256
Code Lines 166

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 166
c 0
b 0
f 0
dl 0
loc 256
rs 0
cc 30
nop 20
nc 1272

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
        array $subscribers = []
901
    ) {
902
        $id = (int) $id;
903
        $start = api_get_utc_datetime($start);
904
        $end = api_get_utc_datetime($end);
905
        $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0;
906
        $currentUserId = api_get_user_id();
907
        $authorId = empty($authorId) ? $currentUserId : (int) $authorId;
908
909
        $em = Database::getManager();
910
911
        switch ($this->type) {
912
            case 'personal':
913
                $eventInfo = $this->get_event($id);
914
                if ($eventInfo['user'] != $currentUserId
915
                    && (
916
                        api_get_configuration_value('agenda_collective_invitations')
917
                            && !self::isUserInvitedInEvent($id, $currentUserId)
918
                    )
919
                ) {
920
                    break;
921
                }
922
                $attributes = [
923
                    'title' => $title,
924
                    'date' => $start,
925
                    'enddate' => $end,
926
                    'all_day' => $allDay,
927
                ];
928
929
                if ($updateContent) {
930
                    $attributes['text'] = $content;
931
                }
932
933
                if (!empty($color)) {
934
                    $attributes['color'] = $color;
935
                }
936
937
                Database::update(
938
                    $this->tbl_personal_agenda,
939
                    $attributes,
940
                    ['id = ?' => $id]
941
                );
942
943
                if (api_get_configuration_value('agenda_collective_invitations')) {
944
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
945
                }
946
947
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
948
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
949
                    $personalEvent->setSubscriptionVisibility($subscriptionVisibility);
950
951
                    /** @var AgendaEventSubscription $subscription */
952
                    $subscription = $personalEvent->getInvitation();
953
                    $subscription->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0);
954
955
                    if ($personalEvent->getSubscriptionItemId() != $subscriptionItemId) {
956
                        $personalEvent->setSubscriptionItemId($subscriptionItemId ?: null);
957
                        $subscription->removeInvitees();
958
                    } else {
959
                        $subscription->removeInviteesNotInIdList($subscribers);
960
                    }
961
962
                    $em->flush();
963
                }
964
                break;
965
            case 'course':
966
                $eventInfo = $this->get_event($id);
967
968
                if (empty($eventInfo)) {
969
                    return false;
970
                }
971
972
                $groupId = api_get_group_id();
973
                $groupIid = 0;
974
                $groupInfo = [];
975
                if ($groupId) {
976
                    $groupInfo = GroupManager::get_group_properties($groupId);
977
                    if ($groupInfo) {
978
                        $groupIid = $groupInfo['iid'];
979
                    }
980
                }
981
982
                $courseId = $this->course['real_id'];
983
984
                if (empty($courseId)) {
985
                    return false;
986
                }
987
988
                if (!$this->getIsAllowedToEdit()) {
989
                    return false;
990
                }
991
992
                $attributes = [
993
                    'title' => $title,
994
                    'start_date' => $start,
995
                    'end_date' => $end,
996
                    'all_day' => $allDay,
997
                    'comment' => $comment,
998
                ];
999
1000
                if ($updateContent) {
1001
                    $attributes['content'] = $content;
1002
                }
1003
1004
                if (!empty($color)) {
1005
                    $attributes['color'] = $color;
1006
                }
1007
1008
                Database::update(
1009
                    $this->tbl_course_agenda,
1010
                    $attributes,
1011
                    [
1012
                        'id = ? AND c_id = ? AND session_id = ? ' => [
1013
                            $id,
1014
                            $courseId,
1015
                            $this->sessionId,
1016
                        ],
1017
                    ]
1018
                );
1019
1020
                if (!empty($usersToSend)) {
1021
                    $sendTo = $this->parseSendToArray($usersToSend);
1022
1023
                    $usersToDelete = array_diff(
1024
                        $eventInfo['send_to']['users'],
1025
                        $sendTo['users']
1026
                    );
1027
                    $usersToAdd = array_diff(
1028
                        $sendTo['users'],
1029
                        $eventInfo['send_to']['users']
1030
                    );
1031
1032
                    $groupsToDelete = array_diff(
1033
                        $eventInfo['send_to']['groups'],
1034
                        $sendTo['groups']
1035
                    );
1036
                    $groupToAdd = array_diff(
1037
                        $sendTo['groups'],
1038
                        $eventInfo['send_to']['groups']
1039
                    );
1040
1041
                    if ($sendTo['everyone']) {
1042
                        // Delete all from group
1043
                        if (isset($eventInfo['send_to']['groups']) &&
1044
                            !empty($eventInfo['send_to']['groups'])
1045
                        ) {
1046
                            foreach ($eventInfo['send_to']['groups'] as $group) {
1047
                                $groupIidItem = 0;
1048
                                if ($group) {
1049
                                    $groupInfoItem = GroupManager::get_group_properties(
1050
                                        $group
1051
                                    );
1052
                                    if ($groupInfoItem) {
1053
                                        $groupIidItem = $groupInfoItem['iid'];
1054
                                    }
1055
                                }
1056
1057
                                api_item_property_delete(
1058
                                    $this->course,
1059
                                    TOOL_CALENDAR_EVENT,
1060
                                    $id,
1061
                                    0,
1062
                                    $groupIidItem,
1063
                                    $this->sessionId
1064
                                );
1065
                            }
1066
                        }
1067
1068
                        // Storing the selected users.
1069
                        if (isset($eventInfo['send_to']['users']) &&
1070
                            !empty($eventInfo['send_to']['users'])
1071
                        ) {
1072
                            foreach ($eventInfo['send_to']['users'] as $userId) {
1073
                                api_item_property_delete(
1074
                                    $this->course,
1075
                                    TOOL_CALENDAR_EVENT,
1076
                                    $id,
1077
                                    $userId,
1078
                                    $groupIid,
1079
                                    $this->sessionId
1080
                                );
1081
                            }
1082
                        }
1083
1084
                        // Add to everyone only.
1085
                        api_item_property_update(
1086
                            $this->course,
1087
                            TOOL_CALENDAR_EVENT,
1088
                            $id,
1089
                            'visible',
1090
                            $authorId,
1091
                            $groupInfo,
1092
                            null,
1093
                            $start,
1094
                            $end,
1095
                            $this->sessionId
1096
                        );
1097
                    } else {
1098
                        // Delete "everyone".
1099
                        api_item_property_delete(
1100
                            $this->course,
1101
                            TOOL_CALENDAR_EVENT,
1102
                            $id,
1103
                            0,
1104
                            0,
1105
                            $this->sessionId
1106
                        );
1107
1108
                        // Add groups
1109
                        if (!empty($groupToAdd)) {
1110
                            foreach ($groupToAdd as $group) {
1111
                                $groupInfoItem = [];
1112
                                if ($group) {
1113
                                    $groupInfoItem = GroupManager::get_group_properties(
1114
                                        $group
1115
                                    );
1116
                                }
1117
1118
                                api_item_property_update(
1119
                                    $this->course,
1120
                                    TOOL_CALENDAR_EVENT,
1121
                                    $id,
1122
                                    'visible',
1123
                                    $authorId,
1124
                                    $groupInfoItem,
1125
                                    0,
1126
                                    $start,
1127
                                    $end,
1128
                                    $this->sessionId
1129
                                );
1130
                            }
1131
                        }
1132
1133
                        // Delete groups.
1134
                        if (!empty($groupsToDelete)) {
1135
                            foreach ($groupsToDelete as $group) {
1136
                                $groupIidItem = 0;
1137
                                $groupInfoItem = [];
1138
                                if ($group) {
1139
                                    $groupInfoItem = GroupManager::get_group_properties(
1140
                                        $group
1141
                                    );
1142
                                    if ($groupInfoItem) {
1143
                                        $groupIidItem = $groupInfoItem['iid'];
1144
                                    }
1145
                                }
1146
1147
                                api_item_property_delete(
1148
                                    $this->course,
1149
                                    TOOL_CALENDAR_EVENT,
1150
                                    $id,
1151
                                    0,
1152
                                    $groupIidItem,
1153
                                    $this->sessionId
1154
                                );
1155
                            }
1156
                        }
1157
1158
                        // Add users.
1159
                        if (!empty($usersToAdd)) {
1160
                            foreach ($usersToAdd as $userId) {
1161
                                api_item_property_update(
1162
                                    $this->course,
1163
                                    TOOL_CALENDAR_EVENT,
1164
                                    $id,
1165
                                    'visible',
1166
                                    $authorId,
1167
                                    $groupInfo,
1168
                                    $userId,
1169
                                    $start,
1170
                                    $end,
1171
                                    $this->sessionId
1172
                                );
1173
                            }
1174
                        }
1175
1176
                        // Delete users.
1177
                        if (!empty($usersToDelete)) {
1178
                            foreach ($usersToDelete as $userId) {
1179
                                api_item_property_delete(
1180
                                    $this->course,
1181
                                    TOOL_CALENDAR_EVENT,
1182
                                    $id,
1183
                                    $userId,
1184
                                    $groupInfo,
1185
                                    $this->sessionId
1186
                                );
1187
                            }
1188
                        }
1189
                    }
1190
                }
1191
1192
                // Add announcement.
1193
                if (isset($addAnnouncement) && !empty($addAnnouncement)) {
1194
                    $this->storeAgendaEventAsAnnouncement(
1195
                        $id,
1196
                        $usersToSend
1197
                    );
1198
                }
1199
1200
                // Add attachment.
1201
                if (isset($attachmentArray) && !empty($attachmentArray)) {
1202
                    $counter = 0;
1203
                    foreach ($attachmentArray as $attachmentItem) {
1204
                        if (empty($attachmentItems['id'])) {
1205
                            continue;
1206
                        }
1207
1208
                        $this->updateAttachment(
1209
                            $attachmentItem['id'],
1210
                            $id,
1211
                            $attachmentItem,
1212
                            $attachmentCommentList[$counter],
1213
                            $this->course
1214
                        );
1215
                        $counter++;
1216
                    }
1217
                }
1218
                break;
1219
            case 'admin':
1220
            case 'platform':
1221
                if (api_is_platform_admin()) {
1222
                    $attributes = [
1223
                        'title' => $title,
1224
                        'start_date' => $start,
1225
                        'end_date' => $end,
1226
                        'all_day' => $allDay,
1227
                    ];
1228
1229
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
1230
                        $attributes['career_id'] = $careerId;
1231
                        $attributes['promotion_id'] = $promotionId;
1232
                    }
1233
1234
                    if ($updateContent) {
1235
                        $attributes['content'] = $content;
1236
                    }
1237
                    Database::update(
1238
                        $this->tbl_global_agenda,
1239
                        $attributes,
1240
                        ['id = ?' => $id]
1241
                    );
1242
                }
1243
                break;
1244
        }
1245
1246
        $this->editReminders($id, $remindersList);
1247
1248
        return true;
1249
    }
1250
1251
    /**
1252
     * @param int  $id
1253
     * @param bool $deleteAllItemsFromSerie
1254
     *
1255
     * @throws \Doctrine\ORM\ORMException
1256
     * @throws \Doctrine\ORM\OptimisticLockException
1257
     */
1258
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
1259
    {
1260
        $em = Database::getManager();
1261
1262
        switch ($this->type) {
1263
            case 'personal':
1264
                $eventInfo = $this->get_event($id);
1265
                if ($eventInfo['user'] == api_get_user_id()) {
1266
                    Database::delete(
1267
                        $this->tbl_personal_agenda,
1268
                        ['id = ?' => $id]
1269
                    );
1270
                } elseif (api_get_configuration_value('agenda_collective_invitations')) {
1271
                    $currentUser = api_get_user_entity(api_get_user_id());
1272
1273
                    $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
1274
                    $event = $eventRepo->findOneByIdAndInvitee($id, $currentUser);
1275
                    $invitation = $event ? $event->getInvitation() : null;
1276
1277
                    if ($invitation) {
1278
                        $invitation->removeInviteeUser($currentUser);
1279
1280
                        $em->persist($invitation);
1281
                        $em->flush();
1282
                    }
1283
                }
1284
                break;
1285
            case 'course':
1286
                $courseId = api_get_course_int_id();
1287
                $isAllowToEdit = $this->getIsAllowedToEdit();
1288
1289
                if (!empty($courseId) && $isAllowToEdit) {
1290
                    $eventInfo = $this->get_event($id);
1291
                    if ($deleteAllItemsFromSerie) {
1292
                        /* This is one of the children.
1293
                           Getting siblings and delete 'Em all + the father! */
1294
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
1295
                            // Removing items.
1296
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
1297
                            if (!empty($events)) {
1298
                                foreach ($events as $event) {
1299
                                    $this->deleteEvent($event['id']);
1300
                                }
1301
                            }
1302
                            // Removing parent.
1303
                            $this->deleteEvent($eventInfo['parent_event_id']);
1304
                        } else {
1305
                            // This is the father looking for the children.
1306
                            $events = $this->getAllRepeatEvents($id);
1307
                            if (!empty($events)) {
1308
                                foreach ($events as $event) {
1309
                                    $this->deleteEvent($event['id']);
1310
                                }
1311
                            }
1312
                        }
1313
                    }
1314
1315
                    // Removing from events.
1316
                    Database::delete(
1317
                        $this->tbl_course_agenda,
1318
                        ['id = ? AND c_id = ?' => [$id, $courseId]]
1319
                    );
1320
1321
                    api_item_property_update(
1322
                        $this->course,
1323
                        TOOL_CALENDAR_EVENT,
1324
                        $id,
1325
                        'delete',
1326
                        api_get_user_id()
1327
                    );
1328
1329
                    // Removing from series.
1330
                    Database::delete(
1331
                        $this->table_repeat,
1332
                        [
1333
                            'cal_id = ? AND c_id = ?' => [
1334
                                $id,
1335
                                $courseId,
1336
                            ],
1337
                        ]
1338
                    );
1339
1340
                    if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
1341
                        foreach ($eventInfo['attachment'] as $attachment) {
1342
                            self::deleteAttachmentFile(
1343
                                $attachment['id'],
1344
                                $this->course
1345
                            );
1346
                        }
1347
                    }
1348
                }
1349
                break;
1350
            case 'admin':
1351
                if (api_is_platform_admin()) {
1352
                    Database::delete(
1353
                        $this->tbl_global_agenda,
1354
                        ['id = ?' => $id]
1355
                    );
1356
                }
1357
                break;
1358
        }
1359
    }
1360
1361
    public function subscribeCurrentUserToEvent(int $id)
1362
    {
1363
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1364
            return;
1365
        }
1366
1367
        if ('personal' !== $this->type) {
1368
            return;
1369
        }
1370
1371
        $em = Database::getManager();
1372
1373
        $currentUser = api_get_user_entity(api_get_user_id());
1374
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1375
1376
        /** @var AgendaEventSubscription $subscription */
1377
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1378
1379
        if (!$subscription) {
1380
            return;
1381
        }
1382
1383
        if ($subscription->getInvitees()->count() >= $subscription->getMaxAttendees()
1384
            && $subscription->getMaxAttendees() > 0
1385
        ) {
1386
            return;
1387
        }
1388
1389
        if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $personalEvent->getSubscriptionVisibility()) {
1390
            $objGroup = new UserGroup();
1391
            $groupList = $objGroup->getUserGroupListByUser($currentUser->getId(), UserGroup::NORMAL_CLASS);
1392
            $groupIdList = array_column($groupList, 'id');
1393
1394
            if (!in_array($personalEvent->getSubscriptionItemId(), $groupIdList)) {
1395
                return;
1396
            }
1397
        }
1398
1399
        $subscriber = (new AgendaEventSubscriber())
1400
            ->setUser($currentUser)
1401
        ;
1402
1403
        $subscription->addInvitee($subscriber);
1404
1405
        $em->flush();
1406
    }
1407
1408
    public function unsubscribeCurrentUserToEvent(int $id)
1409
    {
1410
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1411
            return;
1412
        }
1413
1414
        if ('personal' !== $this->type) {
1415
            return;
1416
        }
1417
1418
        $em = Database::getManager();
1419
1420
        $currentUser = api_get_user_entity(api_get_user_id());
1421
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1422
1423
        /** @var AgendaEventSubscription $subscription */
1424
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1425
1426
        if (!$subscription) {
1427
            return;
1428
        }
1429
1430
        $subscription->removeInviteeUser($currentUser);
1431
1432
        $em->flush();
1433
    }
1434
1435
    /**
1436
     * Get agenda events.
1437
     *
1438
     * @param int    $start
1439
     * @param int    $end
1440
     * @param int    $courseId
1441
     * @param int    $groupId
1442
     * @param int    $user_id
1443
     * @param string $format
1444
     *
1445
     * @return array|string
1446
     */
1447
    public function getEvents(
1448
        $start,
1449
        $end,
1450
        $courseId = null,
1451
        $groupId = null,
1452
        $user_id = 0,
1453
        $format = 'json'
1454
    ) {
1455
        switch ($this->type) {
1456
            case 'admin':
1457
                $this->getPlatformEvents($start, $end);
1458
                break;
1459
            case 'course':
1460
                $courseInfo = api_get_course_info_by_id($courseId);
1461
1462
                // Session coach can see all events inside a session.
1463
                if (api_is_coach()) {
1464
                    // Own course
1465
                    $this->getCourseEvents(
1466
                        $start,
1467
                        $end,
1468
                        $courseInfo,
1469
                        $groupId,
1470
                        $this->sessionId,
1471
                        $user_id
1472
                    );
1473
1474
                    // Others
1475
                    $this->getSessionEvents(
1476
                        $start,
1477
                        $end,
1478
                        $this->sessionId,
1479
                        $user_id,
1480
                        $this->eventOtherSessionColor
1481
                    );
1482
                } else {
1483
                    $this->getCourseEvents(
1484
                        $start,
1485
                        $end,
1486
                        $courseInfo,
1487
                        $groupId,
1488
                        $this->sessionId,
1489
                        $user_id
1490
                    );
1491
                }
1492
                break;
1493
            case 'personal':
1494
            default:
1495
                $sessionFilterActive = false;
1496
                if (!empty($this->sessionId)) {
1497
                    $sessionFilterActive = true;
1498
                }
1499
1500
                if ($sessionFilterActive == false) {
1501
                    // Getting personal events
1502
                    $this->getPersonalEvents($start, $end);
1503
1504
                    // Getting platform/admin events
1505
                    $this->getPlatformEvents($start, $end);
1506
                }
1507
1508
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1509
1510
                $session_list = [];
1511
                // Getting course events
1512
                $my_course_list = [];
1513
                if (!api_is_anonymous()) {
1514
                    $session_list = SessionManager::get_sessions_by_user(
1515
                        api_get_user_id(),
1516
                        $ignoreVisibility
1517
                    );
1518
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1519
                        api_get_user_id(),
1520
                        false
1521
                    );
1522
                }
1523
1524
                if (api_is_drh()) {
1525
                    if (api_drh_can_access_all_session_content()) {
1526
                        $session_list = [];
1527
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1528
                            api_get_user_id(),
1529
                            null,
1530
                            null,
1531
                            null,
1532
                            true,
1533
                            false
1534
                        );
1535
1536
                        if (!empty($sessionList)) {
1537
                            foreach ($sessionList as $sessionItem) {
1538
                                $sessionId = $sessionItem['id'];
1539
                                $courses = SessionManager::get_course_list_by_session_id($sessionId);
1540
                                $sessionInfo = [
1541
                                    'session_id' => $sessionId,
1542
                                    'courses' => $courses,
1543
                                ];
1544
                                $session_list[] = $sessionInfo;
1545
                            }
1546
                        }
1547
                    }
1548
                }
1549
1550
                if (!empty($session_list)) {
1551
                    foreach ($session_list as $session_item) {
1552
                        if ($sessionFilterActive) {
1553
                            if ($this->sessionId != $session_item['session_id']) {
1554
                                continue;
1555
                            }
1556
                        }
1557
1558
                        $my_courses = $session_item['courses'];
1559
                        $my_session_id = $session_item['session_id'];
1560
1561
                        if (!empty($my_courses)) {
1562
                            foreach ($my_courses as $course_item) {
1563
                                $courseInfo = api_get_course_info_by_id(
1564
                                    $course_item['real_id']
1565
                                );
1566
                                $this->getCourseEvents(
1567
                                    $start,
1568
                                    $end,
1569
                                    $courseInfo,
1570
                                    0,
1571
                                    $my_session_id
1572
                                );
1573
                            }
1574
                        }
1575
                    }
1576
                }
1577
1578
                if (!empty($my_course_list) && $sessionFilterActive == false) {
1579
                    foreach ($my_course_list as $courseInfoItem) {
1580
                        $courseInfo = api_get_course_info_by_id(
1581
                            $courseInfoItem['real_id']
1582
                        );
1583
                        if (isset($courseId) && !empty($courseId)) {
1584
                            if ($courseInfo['real_id'] == $courseId) {
1585
                                $this->getCourseEvents(
1586
                                    $start,
1587
                                    $end,
1588
                                    $courseInfo,
1589
                                    0,
1590
                                    0,
1591
                                    $user_id
1592
                                );
1593
                            }
1594
                        } else {
1595
                            $this->getCourseEvents(
1596
                                $start,
1597
                                $end,
1598
                                $courseInfo,
1599
                                0,
1600
                                0,
1601
                                $user_id
1602
                            );
1603
                        }
1604
                    }
1605
                }
1606
1607
                if ($start && $end) {
1608
                    $this->loadSessionsAsEvents($start, $end);
1609
                }
1610
1611
                break;
1612
        }
1613
1614
        if (api_get_configuration_value('agenda_reminders')) {
1615
            $this->events = array_map(
1616
                function (array $eventInfo) {
1617
                    $id = str_replace(['personal_', 'course_', 'session_'], '', $eventInfo['id']);
1618
1619
                    $eventInfo['reminders'] = $this->parseEventReminders(
1620
                        $this->getEventReminders(
1621
                            $id,
1622
                            'session' === $eventInfo['type'] ? 'course' : $eventInfo['type']
1623
                        )
1624
                    );
1625
1626
                    return $eventInfo;
1627
                },
1628
                $this->events
1629
            );
1630
        }
1631
1632
        $this->cleanEvents();
1633
1634
        switch ($format) {
1635
            case 'json':
1636
                if (empty($this->events)) {
1637
                    return '[]';
1638
                }
1639
1640
                return json_encode($this->events);
1641
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

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