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

Agenda::editEvent()   F

Complexity

Conditions 56
Paths 8408

Size

Total Lines 377
Code Lines 227

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 227
c 1
b 0
f 0
dl 0
loc 377
rs 0
cc 56
nc 8408
nop 23

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
                $this->deleteEventIfAlreadyExists($start, $end, $allDay, $title);
330
                $senderId = $this->getSenderId();
331
                $sessionId = $this->getSessionId();
332
333
                // Simple course event.
334
                $id = Database::insert($this->tbl_course_agenda, $attributes);
335
336
                if ($id) {
337
                    $sql = "UPDATE ".$this->tbl_course_agenda." SET id = iid WHERE iid = $id";
338
                    Database::query($sql);
339
340
                    $groupId = api_get_group_id();
341
                    $groupInfo = [];
342
                    if ($groupId) {
343
                        $groupInfo = GroupManager::get_group_properties(
344
                            $groupId
345
                        );
346
                    }
347
348
                    if (!empty($usersToSend)) {
349
                        $sendTo = $this->parseSendToArray($usersToSend);
350
                        if ($sendTo['everyone']) {
351
                            api_item_property_update(
352
                                $this->course,
353
                                TOOL_CALENDAR_EVENT,
354
                                $id,
355
                                'AgendaAdded',
356
                                $senderId,
357
                                $groupInfo,
358
                                '',
359
                                $start,
360
                                $end,
361
                                $sessionId
362
                            );
363
                            api_item_property_update(
364
                                $this->course,
365
                                TOOL_CALENDAR_EVENT,
366
                                $id,
367
                                'visible',
368
                                $senderId,
369
                                $groupInfo,
370
                                '',
371
                                $start,
372
                                $end,
373
                                $sessionId
374
                            );
375
                        } else {
376
                            // Storing the selected groups
377
                            if (!empty($sendTo['groups'])) {
378
                                foreach ($sendTo['groups'] as $group) {
379
                                    $groupInfoItem = [];
380
                                    if ($group) {
381
                                        $groupInfoItem = GroupManager::get_group_properties($group);
382
                                    }
383
384
                                    api_item_property_update(
385
                                        $this->course,
386
                                        TOOL_CALENDAR_EVENT,
387
                                        $id,
388
                                        'AgendaAdded',
389
                                        $senderId,
390
                                        $groupInfoItem,
391
                                        0,
392
                                        $start,
393
                                        $end,
394
                                        $sessionId
395
                                    );
396
397
                                    api_item_property_update(
398
                                        $this->course,
399
                                        TOOL_CALENDAR_EVENT,
400
                                        $id,
401
                                        'visible',
402
                                        $senderId,
403
                                        $groupInfoItem,
404
                                        0,
405
                                        $start,
406
                                        $end,
407
                                        $sessionId
408
                                    );
409
                                }
410
                            }
411
412
                            // storing the selected users
413
                            if (!empty($sendTo['users'])) {
414
                                foreach ($sendTo['users'] as $userId) {
415
                                    api_item_property_update(
416
                                        $this->course,
417
                                        TOOL_CALENDAR_EVENT,
418
                                        $id,
419
                                        'AgendaAdded',
420
                                        $senderId,
421
                                        $groupInfo,
422
                                        $userId,
423
                                        $start,
424
                                        $end,
425
                                        $sessionId
426
                                    );
427
428
                                    api_item_property_update(
429
                                        $this->course,
430
                                        TOOL_CALENDAR_EVENT,
431
                                        $id,
432
                                        'visible',
433
                                        $senderId,
434
                                        $groupInfo,
435
                                        $userId,
436
                                        $start,
437
                                        $end,
438
                                        $sessionId
439
                                    );
440
                                }
441
                            }
442
                        }
443
                    }
444
445
                    // Add announcement.
446
                    if ($addAsAnnouncement) {
447
                        $this->storeAgendaEventAsAnnouncement(
448
                            $id,
449
                            $usersToSend
450
                        );
451
                    }
452
453
                    // Add attachment.
454
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
455
                        $counter = 0;
456
                        foreach ($attachmentArray as $attachmentItem) {
457
                            $this->addAttachment(
458
                                $id,
459
                                $attachmentItem,
460
                                $attachmentCommentList[$counter],
461
                                $this->course
462
                            );
463
                            $counter++;
464
                        }
465
                    }
466
                }
467
                break;
468
            case 'admin':
469
                if (api_is_platform_admin()) {
470
                    $attributes = [
471
                        'title' => $title,
472
                        'content' => $content,
473
                        'start_date' => $start,
474
                        'end_date' => $end,
475
                        'all_day' => $allDay,
476
                        'access_url_id' => api_get_current_access_url_id(),
477
                    ];
478
479
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
480
                        $attributes['career_id'] = $careerId;
481
                        $attributes['promotion_id'] = $promotionId;
482
                    }
483
484
                    $id = Database::insert(
485
                        $this->tbl_global_agenda,
486
                        $attributes
487
                    );
488
                }
489
                break;
490
        }
491
492
        if (api_get_configuration_value('agenda_reminders')) {
493
            foreach ($reminders as $reminder) {
494
                $this->addReminder($id, $reminder[0], $reminder[1]);
495
            }
496
        }
497
498
        return $id;
499
    }
500
501
    /**
502
     * Checks if an event exists and delete it (right before inserting a modified version in addEvent())
503
     * @param string $start datetime format: 2012-06-14 09:00:00 in local time
504
     * @param string $end   datetime format: 2012-06-14 09:00:00 in local time
505
     * @param int $allDay   (true = 1, false = 0)
506
     * @param string $title
507
     *
508
     * @return bool
509
     * @throws Exception
510
     */
511
    public function deleteEventIfAlreadyExists(
512
        string $start,
513
        string $end,
514
        int $allDay,
515
        string $title
516
    ): bool {
517
        $courseId = $this->course['real_id'];
518
        $start = Database::escape_string($start);
519
        $end = Database::escape_string($end);
520
        $title = Database::escape_string($title);
521
        $sql = "SELECT id FROM ".$this->tbl_course_agenda."
522
                WHERE c_id = $courseId
523
                AND session_id = ".$this->sessionId."
524
                AND start_date = '$start'
525
                AND end_date = '$end'
526
                AND all_day = $allDay
527
                AND title = '$title'";
528
        $res = Database::query($sql);
529
        if (Database::num_rows($res) > 0) {
530
            $row = Database::fetch_array($res, 'ASSOC');
531
            $id = $row['id'];
532
            $this->deleteEvent($id);
533
534
            return true;
535
        }
536
537
        return false;
538
    }
539
540
    /**
541
     * @throws Exception
542
     */
543
    public function addReminder($eventId, $count, $period)
544
    {
545
        switch ($period) {
546
            case 'i':
547
                $dateInterval = DateInterval::createFromDateString("$count minutes");
548
                break;
549
            case 'h':
550
                $dateInterval = DateInterval::createFromDateString("$count hours");
551
                break;
552
            case 'd':
553
                $dateInterval = DateInterval::createFromDateString("$count days");
554
                break;
555
            default:
556
                return null;
557
        }
558
559
        $agendaReminder = new AgendaReminder();
560
        $agendaReminder
561
            ->setType($this->type)
562
            ->setEventId($eventId)
563
            ->setDateInterval($dateInterval)
564
        ;
565
566
        $em = Database::getManager();
567
        $em->persist($agendaReminder);
568
        $em->flush();
569
    }
570
571
    public function removeReminders(int $eventId, int $count, string $period)
572
    {
573
        switch ($period) {
574
            case 'i':
575
                $dateInterval = DateInterval::createFromDateString("$count minutes");
576
                break;
577
            case 'h':
578
                $dateInterval = DateInterval::createFromDateString("$count hours");
579
                break;
580
            case 'd':
581
                $dateInterval = DateInterval::createFromDateString("$count days");
582
                break;
583
            default:
584
                return null;
585
        }
586
587
        Database::getManager()
588
            ->createQuery(
589
                'DELETE FROM ChamiloCoreBundle:AgendaReminder ar
590
                WHERE ar.eventId = :eventId AND ar.type = :type AND ar.dateInterval = :dateInterval'
591
            )
592
            ->setParameters(
593
                [
594
                    'eventId' => $eventId,
595
                    'type' => $this->type,
596
                    'dateInterval' => $dateInterval,
597
                ]
598
            )
599
            ->execute();
600
    }
601
602
    public function getReminder(int $eventId, int $count, string $period)
603
    {
604
        switch ($period) {
605
            case 'i':
606
                $dateInterval = DateInterval::createFromDateString("$count minutes");
607
                break;
608
            case 'h':
609
                $dateInterval = DateInterval::createFromDateString("$count hours");
610
                break;
611
            case 'd':
612
                $dateInterval = DateInterval::createFromDateString("$count days");
613
                break;
614
            default:
615
                return null;
616
        }
617
618
        $em = Database::getManager();
619
        $remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
620
621
        return $remindersRepo->findOneBy(
622
            [
623
                'type' => $this->type,
624
                'dateInterval' => $dateInterval,
625
                'eventId' => $eventId,
626
            ]
627
        );
628
    }
629
630
    /**
631
     * @param int $eventId
632
     * @param int $courseId
633
     *
634
     * @return array
635
     */
636
    public function getRepeatedInfoByEvent($eventId, $courseId)
637
    {
638
        $repeatTable = Database::get_course_table(TABLE_AGENDA_REPEAT);
639
        $eventId = (int) $eventId;
640
        $courseId = (int) $courseId;
641
        $sql = "SELECT * FROM $repeatTable
642
                WHERE c_id = $courseId AND cal_id = $eventId";
643
        $res = Database::query($sql);
644
        $repeatInfo = [];
645
        if (Database::num_rows($res) > 0) {
646
            $repeatInfo = Database::fetch_array($res, 'ASSOC');
647
        }
648
649
        return $repeatInfo;
650
    }
651
652
    /**
653
     * @param string $type
654
     * @param string $startEvent      in UTC
655
     * @param string $endEvent        in UTC
656
     * @param string $repeatUntilDate in UTC
657
     *
658
     * @throws Exception
659
     *
660
     * @return array with local times
661
     */
662
    public function generateDatesByType($type, $startEvent, $endEvent, $repeatUntilDate)
663
    {
664
        $continue = true;
665
        $repeatUntilDate = new DateTime($repeatUntilDate, new DateTimeZone('UTC'));
666
        $loopMax = 365;
667
        $counter = 0;
668
        $list = [];
669
670
        switch ($type) {
671
            case 'daily':
672
                $interval = 'P1D';
673
                break;
674
            case 'weekly':
675
                $interval = 'P1W';
676
                break;
677
            case 'monthlyByDate':
678
                $interval = 'P1M';
679
                break;
680
            case 'monthlyByDay':
681
                // not yet implemented
682
                break;
683
            case 'monthlyByDayR':
684
                // not yet implemented
685
                break;
686
            case 'yearly':
687
                $interval = 'P1Y';
688
                break;
689
        }
690
691
        if (empty($interval)) {
692
            return [];
693
        }
694
        $timeZone = api_get_timezone();
695
696
        while ($continue) {
697
            $startDate = new DateTime($startEvent, new DateTimeZone('UTC'));
698
            $endDate = new DateTime($endEvent, new DateTimeZone('UTC'));
699
700
            $startDate->add(new DateInterval($interval));
701
            $endDate->add(new DateInterval($interval));
702
703
            $newStartDate = $startDate->format('Y-m-d H:i:s');
704
            $newEndDate = $endDate->format('Y-m-d H:i:s');
705
706
            $startEvent = $newStartDate;
707
            $endEvent = $newEndDate;
708
709
            if ($endDate > $repeatUntilDate) {
710
                break;
711
            }
712
713
            // @todo remove comment code
714
            // The code below was not adpating to saving light time but was doubling the difference with UTC time.
715
            // Might be necessary to adapt to update saving light time difference.
716
            /*            $startDateInLocal = new DateTime($newStartDate, new DateTimeZone($timeZone));
717
                        if ($startDateInLocal->format('I') == 0) {
718
                            // Is saving time? Then fix UTC time to add time
719
                            $seconds = $startDateInLocal->getOffset();
720
                            $startDate->add(new DateInterval("PT".$seconds."S"));
721
                            //$startDateFixed = $startDate->format('Y-m-d H:i:s');
722
                            //$startDateInLocalFixed = new DateTime($startDateFixed, new DateTimeZone($timeZone));
723
                            //$newStartDate = $startDateInLocalFixed->format('Y-m-d H:i:s');
724
                            //$newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
725
                        }
726
727
                        $endDateInLocal = new DateTime($newEndDate, new DateTimeZone($timeZone));
728
                        if ($endDateInLocal->format('I') == 0) {
729
                            // Is saving time? Then fix UTC time to add time
730
                            $seconds = $endDateInLocal->getOffset();
731
                            $endDate->add(new DateInterval("PT".$seconds."S"));
732
                            //$endDateFixed = $endDate->format('Y-m-d H:i:s');
733
                            //$endDateInLocalFixed = new DateTime($endDateFixed, new DateTimeZone($timeZone));
734
                            //$newEndDate = $endDateInLocalFixed->format('Y-m-d H:i:s');
735
                    }
736
            */
737
            $newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
738
            $newEndDate = $endDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
739
            $list[] = ['start' => $newStartDate, 'end' => $newEndDate];
740
            $counter++;
741
742
            // just in case stop if more than $loopMax
743
            if ($counter > $loopMax) {
744
                break;
745
            }
746
        }
747
748
        return $list;
749
    }
750
751
    /**
752
     * @param int    $eventId
753
     * @param string $type
754
     * @param string $end     in UTC
755
     * @param array  $sentTo
756
     *
757
     * @return bool
758
     */
759
    public function addRepeatedItem($eventId, $type, $end, $sentTo = [])
760
    {
761
        $t_agenda = Database::get_course_table(TABLE_AGENDA);
762
        $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT);
763
764
        if (empty($this->course)) {
765
            return false;
766
        }
767
768
        $courseId = $this->course['real_id'];
769
        $eventId = (int) $eventId;
770
771
        $sql = "SELECT title, content, start_date, end_date, all_day
772
                FROM $t_agenda
773
                WHERE c_id = $courseId AND id = $eventId";
774
        $res = Database::query($sql);
775
776
        if (Database::num_rows($res) !== 1) {
777
            return false;
778
        }
779
780
        $typeList = [
781
            'daily',
782
            'weekly',
783
            'monthlyByDate',
784
            'monthlyByDay',
785
            'monthlyByDayR',
786
            'yearly',
787
        ];
788
789
        if (!in_array($type, $typeList)) {
790
            return false;
791
        }
792
793
        $now = time();
794
795
        // The event has to repeat *in the future*. We don't allow repeated
796
        // events in the past.
797
        $endTimeStamp = api_strtotime($end, 'UTC');
798
799
        if ($endTimeStamp < $now) {
800
            return false;
801
        }
802
803
        $row = Database::fetch_array($res);
804
805
        $title = $row['title'];
806
        $content = $row['content'];
807
        $allDay = $row['all_day'];
808
809
        $type = Database::escape_string($type);
810
        $end = Database::escape_string($end);
811
812
        $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end)
813
                VALUES ($courseId, '$eventId', '$type', '$endTimeStamp')";
814
        Database::query($sql);
815
816
        $generatedDates = $this->generateDatesByType($type, $row['start_date'], $row['end_date'], $end);
817
818
        if (empty($generatedDates)) {
819
            return false;
820
        }
821
822
        foreach ($generatedDates as $dateInfo) {
823
//            $start = api_get_local_time($dateInfo['start']);
824
//            $end = api_get_local_time($dateInfo['end']);
825
            // On line 529 in function generateDatesByType there is a @todo remove comment code
826
            // just before the part updating the date in local time so keep both synchronised
827
            $start = $dateInfo['start'];
828
            $end = $dateInfo['end'];
829
830
            $this->addEvent(
831
                $start,
832
                $end,
833
                $allDay,
834
                $title,
835
                $content,
836
                $sentTo,
837
                false,
838
                $eventId
839
            );
840
        }
841
842
        return true;
843
    }
844
845
    /**
846
     * @param int   $item_id
847
     * @param array $sentTo
848
     *
849
     * @return int
850
     */
851
    public function storeAgendaEventAsAnnouncement($item_id, $sentTo = [])
852
    {
853
        $table_agenda = Database::get_course_table(TABLE_AGENDA);
854
        $courseId = api_get_course_int_id();
855
856
        // Check params
857
        if (empty($item_id) || $item_id != strval(intval($item_id))) {
858
            return -1;
859
        }
860
861
        // Get the agenda item.
862
        $item_id = intval($item_id);
863
        $sql = "SELECT * FROM $table_agenda
864
                WHERE c_id = $courseId AND id = ".$item_id;
865
        $res = Database::query($sql);
866
867
        if (Database::num_rows($res) > 0) {
868
            $row = Database::fetch_array($res, 'ASSOC');
869
870
            // Sending announcement
871
            if (!empty($sentTo)) {
872
                $id = AnnouncementManager::add_announcement(
873
                    api_get_course_info(),
874
                    api_get_session_id(),
875
                    $row['title'],
876
                    $row['content'],
877
                    $sentTo,
878
                    null,
879
                    null,
880
                    $row['end_date']
881
                );
882
883
                AnnouncementManager::sendEmail(
884
                    api_get_course_info(),
885
                    api_get_session_id(),
886
                    $id
887
                );
888
889
                return $id;
890
            }
891
        }
892
893
        return -1;
894
    }
895
896
    /**
897
     * Edits an event.
898
     *
899
     * @param int    $id
900
     * @param string $start                 datetime format: 2012-06-14 09:00:00
901
     * @param string $end                   datetime format: 2012-06-14 09:00:00
902
     * @param int    $allDay                is all day 'true' or 'false'
903
     * @param string $title
904
     * @param string $content
905
     * @param array  $usersToSend
906
     * @param array  $attachmentArray
907
     * @param array  $attachmentCommentList
908
     * @param string $comment
909
     * @param string $color
910
     * @param bool   $addAnnouncement
911
     * @param bool   $updateContent
912
     * @param int    $authorId
913
     *
914
     * @return bool
915
     */
916
    public function editEvent(
917
        $id,
918
        $start,
919
        $end,
920
        $allDay,
921
        $title,
922
        $content,
923
        $usersToSend = [],
924
        $attachmentArray = [],
925
        $attachmentCommentList = [],
926
        $comment = null,
927
        $color = '',
928
        $addAnnouncement = false,
929
        $updateContent = true,
930
        $authorId = 0,
931
        array $inviteesList = [],
932
        bool $isCollective = false,
933
        array $remindersList = [],
934
        int $careerId = 0,
935
        int $promotionId = 0,
936
        int $subscriptionVisibility = 0,
937
        ?int $subscriptionItemId = null,
938
        int $maxSubscriptions = 0,
939
        array $subscribers = []
940
    ) {
941
        $id = (int) $id;
942
        $start = api_get_utc_datetime($start);
943
        $end = api_get_utc_datetime($end);
944
        $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0;
945
        $currentUserId = api_get_user_id();
946
        $authorId = empty($authorId) ? $currentUserId : (int) $authorId;
947
948
        $em = Database::getManager();
949
950
        switch ($this->type) {
951
            case 'personal':
952
                $eventInfo = $this->get_event($id);
953
                if ($eventInfo['user'] != $currentUserId
954
                    && (
955
                        api_get_configuration_value('agenda_collective_invitations')
956
                            && !self::isUserInvitedInEvent($id, $currentUserId)
957
                    )
958
                ) {
959
                    break;
960
                }
961
                $attributes = [
962
                    'title' => $title,
963
                    'date' => $start,
964
                    'enddate' => $end,
965
                    'all_day' => $allDay,
966
                ];
967
968
                if ($updateContent) {
969
                    $attributes['text'] = $content;
970
                }
971
972
                if (!empty($color)) {
973
                    $attributes['color'] = $color;
974
                }
975
976
                Database::update(
977
                    $this->tbl_personal_agenda,
978
                    $attributes,
979
                    ['id = ?' => $id]
980
                );
981
982
                if (api_get_configuration_value('agenda_collective_invitations')) {
983
                    Agenda::saveCollectiveProperties($inviteesList, $isCollective, $id);
984
                }
985
986
                if (api_get_configuration_value('agenda_event_subscriptions') && api_is_platform_admin()) {
987
                    $personalEvent = $em->find(PersonalAgenda::class, $id);
988
                    $personalEvent->setSubscriptionVisibility($subscriptionVisibility);
989
990
                    /** @var AgendaEventSubscription $subscription */
991
                    $subscription = $personalEvent->getInvitation();
992
                    $subscription->setMaxAttendees($subscriptionVisibility > 0 ? $maxSubscriptions : 0);
993
994
                    if ($personalEvent->getSubscriptionItemId() != $subscriptionItemId) {
995
                        $personalEvent->setSubscriptionItemId($subscriptionItemId ?: null);
996
                        $subscription->removeInvitees();
997
                    } else {
998
                        $subscription->removeInviteesNotInIdList($subscribers);
999
                    }
1000
1001
                    $em->flush();
1002
                }
1003
                break;
1004
            case 'course':
1005
                $eventInfo = $this->get_event($id);
1006
1007
                if (empty($eventInfo)) {
1008
                    return false;
1009
                }
1010
1011
                $groupId = api_get_group_id();
1012
                $groupIid = 0;
1013
                $groupInfo = [];
1014
                if ($groupId) {
1015
                    $groupInfo = GroupManager::get_group_properties($groupId);
1016
                    if ($groupInfo) {
1017
                        $groupIid = $groupInfo['iid'];
1018
                    }
1019
                }
1020
1021
                $courseId = $this->course['real_id'];
1022
1023
                if (empty($courseId)) {
1024
                    return false;
1025
                }
1026
1027
                if (!$this->getIsAllowedToEdit()) {
1028
                    return false;
1029
                }
1030
1031
                $attributes = [
1032
                    'title' => $title,
1033
                    'start_date' => $start,
1034
                    'end_date' => $end,
1035
                    'all_day' => $allDay,
1036
                    'comment' => $comment,
1037
                ];
1038
1039
                if ($updateContent) {
1040
                    $attributes['content'] = $content;
1041
                }
1042
1043
                if (!empty($color)) {
1044
                    $attributes['color'] = $color;
1045
                }
1046
1047
                Database::update(
1048
                    $this->tbl_course_agenda,
1049
                    $attributes,
1050
                    [
1051
                        'id = ? AND c_id = ? AND session_id = ? ' => [
1052
                            $id,
1053
                            $courseId,
1054
                            $this->sessionId,
1055
                        ],
1056
                    ]
1057
                );
1058
1059
                if (!empty($usersToSend)) {
1060
                    $sendTo = $this->parseSendToArray($usersToSend);
1061
1062
                    $usersToDelete = array_diff(
1063
                        $eventInfo['send_to']['users'],
1064
                        $sendTo['users']
1065
                    );
1066
                    $usersToAdd = array_diff(
1067
                        $sendTo['users'],
1068
                        $eventInfo['send_to']['users']
1069
                    );
1070
1071
                    $groupsToDelete = array_diff(
1072
                        $eventInfo['send_to']['groups'],
1073
                        $sendTo['groups']
1074
                    );
1075
                    $groupToAdd = array_diff(
1076
                        $sendTo['groups'],
1077
                        $eventInfo['send_to']['groups']
1078
                    );
1079
1080
                    if ($sendTo['everyone']) {
1081
                        // Delete all from group
1082
                        if (isset($eventInfo['send_to']['groups']) &&
1083
                            !empty($eventInfo['send_to']['groups'])
1084
                        ) {
1085
                            foreach ($eventInfo['send_to']['groups'] as $group) {
1086
                                $groupIidItem = 0;
1087
                                if ($group) {
1088
                                    $groupInfoItem = GroupManager::get_group_properties(
1089
                                        $group
1090
                                    );
1091
                                    if ($groupInfoItem) {
1092
                                        $groupIidItem = $groupInfoItem['iid'];
1093
                                    }
1094
                                }
1095
1096
                                api_item_property_delete(
1097
                                    $this->course,
1098
                                    TOOL_CALENDAR_EVENT,
1099
                                    $id,
1100
                                    0,
1101
                                    $groupIidItem,
1102
                                    $this->sessionId
1103
                                );
1104
                            }
1105
                        }
1106
1107
                        // Storing the selected users.
1108
                        if (isset($eventInfo['send_to']['users']) &&
1109
                            !empty($eventInfo['send_to']['users'])
1110
                        ) {
1111
                            foreach ($eventInfo['send_to']['users'] as $userId) {
1112
                                api_item_property_delete(
1113
                                    $this->course,
1114
                                    TOOL_CALENDAR_EVENT,
1115
                                    $id,
1116
                                    $userId,
1117
                                    $groupIid,
1118
                                    $this->sessionId
1119
                                );
1120
                            }
1121
                        }
1122
1123
                        // Add to everyone only.
1124
                        api_item_property_update(
1125
                            $this->course,
1126
                            TOOL_CALENDAR_EVENT,
1127
                            $id,
1128
                            'visible',
1129
                            $authorId,
1130
                            $groupInfo,
1131
                            null,
1132
                            $start,
1133
                            $end,
1134
                            $this->sessionId
1135
                        );
1136
                    } else {
1137
                        // Delete "everyone".
1138
                        api_item_property_delete(
1139
                            $this->course,
1140
                            TOOL_CALENDAR_EVENT,
1141
                            $id,
1142
                            0,
1143
                            0,
1144
                            $this->sessionId
1145
                        );
1146
1147
                        // Add groups
1148
                        if (!empty($groupToAdd)) {
1149
                            foreach ($groupToAdd as $group) {
1150
                                $groupInfoItem = [];
1151
                                if ($group) {
1152
                                    $groupInfoItem = GroupManager::get_group_properties(
1153
                                        $group
1154
                                    );
1155
                                }
1156
1157
                                api_item_property_update(
1158
                                    $this->course,
1159
                                    TOOL_CALENDAR_EVENT,
1160
                                    $id,
1161
                                    'visible',
1162
                                    $authorId,
1163
                                    $groupInfoItem,
1164
                                    0,
1165
                                    $start,
1166
                                    $end,
1167
                                    $this->sessionId
1168
                                );
1169
                            }
1170
                        }
1171
1172
                        // Delete groups.
1173
                        if (!empty($groupsToDelete)) {
1174
                            foreach ($groupsToDelete as $group) {
1175
                                $groupIidItem = 0;
1176
                                $groupInfoItem = [];
1177
                                if ($group) {
1178
                                    $groupInfoItem = GroupManager::get_group_properties(
1179
                                        $group
1180
                                    );
1181
                                    if ($groupInfoItem) {
1182
                                        $groupIidItem = $groupInfoItem['iid'];
1183
                                    }
1184
                                }
1185
1186
                                api_item_property_delete(
1187
                                    $this->course,
1188
                                    TOOL_CALENDAR_EVENT,
1189
                                    $id,
1190
                                    0,
1191
                                    $groupIidItem,
1192
                                    $this->sessionId
1193
                                );
1194
                            }
1195
                        }
1196
1197
                        // Add users.
1198
                        if (!empty($usersToAdd)) {
1199
                            foreach ($usersToAdd as $userId) {
1200
                                api_item_property_update(
1201
                                    $this->course,
1202
                                    TOOL_CALENDAR_EVENT,
1203
                                    $id,
1204
                                    'visible',
1205
                                    $authorId,
1206
                                    $groupInfo,
1207
                                    $userId,
1208
                                    $start,
1209
                                    $end,
1210
                                    $this->sessionId
1211
                                );
1212
                            }
1213
                        }
1214
1215
                        // Delete users.
1216
                        if (!empty($usersToDelete)) {
1217
                            foreach ($usersToDelete as $userId) {
1218
                                api_item_property_delete(
1219
                                    $this->course,
1220
                                    TOOL_CALENDAR_EVENT,
1221
                                    $id,
1222
                                    $userId,
1223
                                    $groupInfo,
1224
                                    $this->sessionId
1225
                                );
1226
                            }
1227
                        }
1228
                    }
1229
                }
1230
1231
                // Add announcement.
1232
                if (isset($addAnnouncement) && !empty($addAnnouncement)) {
1233
                    $this->storeAgendaEventAsAnnouncement(
1234
                        $id,
1235
                        $usersToSend
1236
                    );
1237
                }
1238
1239
                // Add attachment.
1240
                if (isset($attachmentArray) && !empty($attachmentArray)) {
1241
                    $counter = 0;
1242
                    foreach ($attachmentArray as $attachmentItem) {
1243
                        if (empty($attachmentItem['id'])) {
1244
                            $this->addAttachment(
1245
                                $id,
1246
                                $attachmentItem,
1247
                                $attachmentCommentList[$counter],
1248
                                $this->course
1249
                            );
1250
                        } else {
1251
                            $this->updateAttachment(
1252
                                $attachmentItem['id'],
1253
                                $id,
1254
                                $attachmentItem,
1255
                                $attachmentCommentList[$counter],
1256
                                $this->course
1257
                            );
1258
                        }
1259
                        $counter++;
1260
                    }
1261
                }
1262
                break;
1263
            case 'admin':
1264
            case 'platform':
1265
                if (api_is_platform_admin()) {
1266
                    $attributes = [
1267
                        'title' => $title,
1268
                        'start_date' => $start,
1269
                        'end_date' => $end,
1270
                        'all_day' => $allDay,
1271
                    ];
1272
1273
                    if (api_get_configuration_value('allow_careers_in_global_agenda')) {
1274
                        $attributes['career_id'] = $careerId;
1275
                        $attributes['promotion_id'] = $promotionId;
1276
                    }
1277
1278
                    if ($updateContent) {
1279
                        $attributes['content'] = $content;
1280
                    }
1281
                    Database::update(
1282
                        $this->tbl_global_agenda,
1283
                        $attributes,
1284
                        ['id = ?' => $id]
1285
                    );
1286
                }
1287
                break;
1288
        }
1289
1290
        $this->editReminders($id, $remindersList);
1291
1292
        return true;
1293
    }
1294
1295
    /**
1296
     * @param int  $id
1297
     * @param bool $deleteAllItemsFromSerie
1298
     *
1299
     * @throws \Doctrine\ORM\ORMException
1300
     * @throws \Doctrine\ORM\OptimisticLockException
1301
     */
1302
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
1303
    {
1304
        $em = Database::getManager();
1305
1306
        switch ($this->type) {
1307
            case 'personal':
1308
                $eventInfo = $this->get_event($id);
1309
                if ($eventInfo['user'] == api_get_user_id()) {
1310
                    Database::delete(
1311
                        $this->tbl_personal_agenda,
1312
                        ['id = ?' => $id]
1313
                    );
1314
                } elseif (api_get_configuration_value('agenda_collective_invitations')) {
1315
                    $currentUser = api_get_user_entity(api_get_user_id());
1316
1317
                    $eventRepo = $em->getRepository('ChamiloCoreBundle:PersonalAgenda');
1318
                    $event = $eventRepo->findOneByIdAndInvitee($id, $currentUser);
1319
                    $invitation = $event ? $event->getInvitation() : null;
1320
1321
                    if ($invitation) {
1322
                        $invitation->removeInviteeUser($currentUser);
1323
1324
                        $em->persist($invitation);
1325
                        $em->flush();
1326
                    }
1327
                }
1328
                break;
1329
            case 'course':
1330
                $courseId = api_get_course_int_id();
1331
                $isAllowToEdit = $this->getIsAllowedToEdit();
1332
1333
                if (!empty($courseId) && $isAllowToEdit) {
1334
                    $eventInfo = $this->get_event($id);
1335
                    if ($deleteAllItemsFromSerie) {
1336
                        /* This is one of the children.
1337
                           Getting siblings and delete 'Em all + the father! */
1338
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
1339
                            // Removing items.
1340
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
1341
                            if (!empty($events)) {
1342
                                foreach ($events as $event) {
1343
                                    $this->deleteEvent($event['id']);
1344
                                }
1345
                            }
1346
                            // Removing parent.
1347
                            $this->deleteEvent($eventInfo['parent_event_id']);
1348
                        } else {
1349
                            // This is the father looking for the children.
1350
                            $events = $this->getAllRepeatEvents($id);
1351
                            if (!empty($events)) {
1352
                                foreach ($events as $event) {
1353
                                    $this->deleteEvent($event['id']);
1354
                                }
1355
                            }
1356
                        }
1357
                    }
1358
1359
                    // Removing from events.
1360
                    Database::delete(
1361
                        $this->tbl_course_agenda,
1362
                        ['id = ? AND c_id = ?' => [$id, $courseId]]
1363
                    );
1364
1365
                    api_item_property_update(
1366
                        $this->course,
1367
                        TOOL_CALENDAR_EVENT,
1368
                        $id,
1369
                        'delete',
1370
                        api_get_user_id()
1371
                    );
1372
1373
                    // Removing from series.
1374
                    Database::delete(
1375
                        $this->table_repeat,
1376
                        [
1377
                            'cal_id = ? AND c_id = ?' => [
1378
                                $id,
1379
                                $courseId,
1380
                            ],
1381
                        ]
1382
                    );
1383
1384
                    if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
1385
                        foreach ($eventInfo['attachment'] as $attachment) {
1386
                            self::deleteAttachmentFile(
1387
                                $attachment['id'],
1388
                                $this->course
1389
                            );
1390
                        }
1391
                    }
1392
                }
1393
                break;
1394
            case 'admin':
1395
                if (api_is_platform_admin()) {
1396
                    Database::delete(
1397
                        $this->tbl_global_agenda,
1398
                        ['id = ?' => $id]
1399
                    );
1400
                }
1401
                break;
1402
        }
1403
    }
1404
1405
    public function subscribeCurrentUserToEvent(int $id)
1406
    {
1407
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1408
            return;
1409
        }
1410
1411
        if ('personal' !== $this->type) {
1412
            return;
1413
        }
1414
1415
        $em = Database::getManager();
1416
1417
        $currentUser = api_get_user_entity(api_get_user_id());
1418
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1419
1420
        /** @var AgendaEventSubscription $subscription */
1421
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1422
1423
        if (!$subscription) {
1424
            return;
1425
        }
1426
1427
        if ($subscription->getInvitees()->count() >= $subscription->getMaxAttendees()
1428
            && $subscription->getMaxAttendees() > 0
1429
        ) {
1430
            return;
1431
        }
1432
1433
        if (AgendaEventSubscription::SUBSCRIPTION_CLASS === $personalEvent->getSubscriptionVisibility()) {
1434
            $objGroup = new UserGroup();
1435
            $groupList = $objGroup->getUserGroupListByUser($currentUser->getId(), UserGroup::NORMAL_CLASS);
1436
            $groupIdList = array_column($groupList, 'id');
1437
1438
            if (!in_array($personalEvent->getSubscriptionItemId(), $groupIdList)) {
1439
                return;
1440
            }
1441
        }
1442
1443
        $subscriber = (new AgendaEventSubscriber())
1444
            ->setUser($currentUser)
1445
        ;
1446
1447
        $subscription->addInvitee($subscriber);
1448
1449
        $em->flush();
1450
    }
1451
1452
    public function unsubscribeCurrentUserToEvent(int $id)
1453
    {
1454
        if (false === api_get_configuration_value('agenda_event_subscriptions')) {
1455
            return;
1456
        }
1457
1458
        if ('personal' !== $this->type) {
1459
            return;
1460
        }
1461
1462
        $em = Database::getManager();
1463
1464
        $currentUser = api_get_user_entity(api_get_user_id());
1465
        $personalEvent = $em->find(PersonalAgenda::class, $id);
1466
1467
        /** @var AgendaEventSubscription $subscription */
1468
        $subscription = $personalEvent ? $personalEvent->getInvitation() : null;
1469
1470
        if (!$subscription) {
1471
            return;
1472
        }
1473
1474
        $subscription->removeInviteeUser($currentUser);
1475
1476
        $em->flush();
1477
    }
1478
1479
    /**
1480
     * Get agenda events.
1481
     *
1482
     * @param int    $start
1483
     * @param int    $end
1484
     * @param int    $courseId
1485
     * @param int    $groupId
1486
     * @param int    $user_id
1487
     * @param string $format
1488
     *
1489
     * @return array|string
1490
     */
1491
    public function getEvents(
1492
        $start,
1493
        $end,
1494
        $courseId = null,
1495
        $groupId = null,
1496
        $user_id = 0,
1497
        $format = 'json'
1498
    ) {
1499
        switch ($this->type) {
1500
            case 'admin':
1501
                $this->getPlatformEvents($start, $end);
1502
                break;
1503
            case 'course':
1504
                $courseInfo = api_get_course_info_by_id($courseId);
1505
1506
                // Session coach can see all events inside a session.
1507
                if (api_is_coach()) {
1508
                    // Own course
1509
                    $this->getCourseEvents(
1510
                        $start,
1511
                        $end,
1512
                        $courseInfo,
1513
                        $groupId,
1514
                        $this->sessionId,
1515
                        $user_id
1516
                    );
1517
1518
                    // Others
1519
                    $this->getSessionEvents(
1520
                        $start,
1521
                        $end,
1522
                        $this->sessionId,
1523
                        $user_id,
1524
                        $this->eventOtherSessionColor
1525
                    );
1526
                } else {
1527
                    $this->getCourseEvents(
1528
                        $start,
1529
                        $end,
1530
                        $courseInfo,
1531
                        $groupId,
1532
                        $this->sessionId,
1533
                        $user_id
1534
                    );
1535
                }
1536
                break;
1537
            case 'personal':
1538
            default:
1539
                $sessionFilterActive = false;
1540
                if (!empty($this->sessionId)) {
1541
                    $sessionFilterActive = true;
1542
                }
1543
1544
                if ($sessionFilterActive == false) {
1545
                    // Getting personal events
1546
                    $this->getPersonalEvents($start, $end);
1547
1548
                    // Getting platform/admin events
1549
                    $this->getPlatformEvents($start, $end);
1550
                }
1551
1552
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1553
1554
                $session_list = [];
1555
                // Getting course events
1556
                $my_course_list = [];
1557
                if (!api_is_anonymous()) {
1558
                    $session_list = SessionManager::get_sessions_by_user(
1559
                        api_get_user_id(),
1560
                        $ignoreVisibility
1561
                    );
1562
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1563
                        api_get_user_id(),
1564
                        false
1565
                    );
1566
                }
1567
1568
                if (api_is_drh()) {
1569
                    if (api_drh_can_access_all_session_content()) {
1570
                        $session_list = [];
1571
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1572
                            api_get_user_id(),
1573
                            null,
1574
                            null,
1575
                            null,
1576
                            true,
1577
                            false
1578
                        );
1579
1580
                        if (!empty($sessionList)) {
1581
                            foreach ($sessionList as $sessionItem) {
1582
                                $sessionId = $sessionItem['id'];
1583
                                $courses = SessionManager::get_course_list_by_session_id($sessionId);
1584
                                $sessionInfo = [
1585
                                    'session_id' => $sessionId,
1586
                                    'courses' => $courses,
1587
                                ];
1588
                                $session_list[] = $sessionInfo;
1589
                            }
1590
                        }
1591
                    }
1592
                }
1593
1594
                if (!empty($session_list)) {
1595
                    foreach ($session_list as $session_item) {
1596
                        if ($sessionFilterActive) {
1597
                            if ($this->sessionId != $session_item['session_id']) {
1598
                                continue;
1599
                            }
1600
                        }
1601
1602
                        $my_courses = $session_item['courses'];
1603
                        $my_session_id = $session_item['session_id'];
1604
1605
                        if (!empty($my_courses)) {
1606
                            foreach ($my_courses as $course_item) {
1607
                                $courseInfo = api_get_course_info_by_id(
1608
                                    $course_item['real_id']
1609
                                );
1610
                                $this->getCourseEvents(
1611
                                    $start,
1612
                                    $end,
1613
                                    $courseInfo,
1614
                                    0,
1615
                                    $my_session_id
1616
                                );
1617
                            }
1618
                        }
1619
                    }
1620
                }
1621
1622
                if (!empty($my_course_list) && $sessionFilterActive == false) {
1623
                    foreach ($my_course_list as $courseInfoItem) {
1624
                        $courseInfo = api_get_course_info_by_id(
1625
                            $courseInfoItem['real_id']
1626
                        );
1627
                        if (isset($courseId) && !empty($courseId)) {
1628
                            if ($courseInfo['real_id'] == $courseId) {
1629
                                $this->getCourseEvents(
1630
                                    $start,
1631
                                    $end,
1632
                                    $courseInfo,
1633
                                    0,
1634
                                    0,
1635
                                    $user_id
1636
                                );
1637
                            }
1638
                        } else {
1639
                            $this->getCourseEvents(
1640
                                $start,
1641
                                $end,
1642
                                $courseInfo,
1643
                                0,
1644
                                0,
1645
                                $user_id
1646
                            );
1647
                        }
1648
                    }
1649
                }
1650
1651
                if ($start && $end) {
1652
                    $this->loadSessionsAsEvents($start, $end);
1653
                }
1654
1655
                break;
1656
        }
1657
1658
        if (api_get_configuration_value('agenda_reminders')) {
1659
            $this->events = array_map(
1660
                function (array $eventInfo) {
1661
                    $id = str_replace(['personal_', 'course_', 'session_'], '', $eventInfo['id']);
1662
1663
                    $eventInfo['reminders'] = $this->parseEventReminders(
1664
                        $this->getEventReminders(
1665
                            $id,
1666
                            'session' === $eventInfo['type'] ? 'course' : $eventInfo['type']
1667
                        )
1668
                    );
1669
1670
                    return $eventInfo;
1671
                },
1672
                $this->events
1673
            );
1674
        }
1675
1676
        $this->cleanEvents();
1677
1678
        switch ($format) {
1679
            case 'json':
1680
                if (empty($this->events)) {
1681
                    return '[]';
1682
                }
1683
1684
                return json_encode($this->events);
1685
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

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