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

Agenda::addEvent()   F

Complexity

Conditions 29
Paths 1272

Size

Total Lines 254
Code Lines 165

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 165
dl 0
loc 254
rs 0
c 0
b 0
f 0
cc 29
nc 1272
nop 19

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