Passed
Push — 1.11.x ( 544dff...c8ebac )
by
unknown
10:59
created

Agenda::addEvent()   F

Complexity

Conditions 22
Paths 612

Size

Total Lines 211
Code Lines 145

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 145
nc 612
nop 12
dl 0
loc 211
rs 0.4311
c 0
b 0
f 0

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
/**
6
 * Class Agenda.
7
 *
8
 * @author: Julio Montoya <[email protected]>
9
 */
10
class Agenda
11
{
12
    public $events = [];
13
    /** @var string Current type */
14
    public $type = 'personal';
15
    public $types = ['personal', 'admin', 'course'];
16
    public $sessionId = 0;
17
    public $senderId;
18
    /** @var array */
19
    public $course;
20
    /** @var string */
21
    public $comment;
22
    public $eventStudentPublicationColor;
23
    /** @var array */
24
    private $sessionInfo;
25
    /** @var bool */
26
    private $isAllowedToEdit;
27
28
    /**
29
     * Constructor.
30
     *
31
     * @param string $type
32
     * @param int    $senderId  Optional The user sender ID
33
     * @param int    $courseId  Optional. The course ID
34
     * @param int    $sessionId Optional The session ID
35
     */
36
    public function __construct(
37
        $type,
38
        $senderId = 0,
39
        $courseId = 0,
40
        $sessionId = 0
41
    ) {
42
        // Table definitions
43
        $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
44
        $this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
45
        $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
46
        $this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
47
48
        $this->setType($type);
49
        $this->setSenderId($senderId ?: api_get_user_id());
50
        $isAllowToEdit = false;
51
52
        switch ($type) {
53
            case 'course':
54
                $sessionId = $sessionId ?: api_get_session_id();
55
                $sessionInfo = api_get_session_info($sessionId);
56
                $this->setSessionId($sessionId);
57
                $this->setSessionInfo($sessionInfo);
58
59
                // Setting the course object if we are in a course
60
                $courseInfo = api_get_course_info_by_id($courseId);
61
                if (!empty($courseInfo)) {
62
                    $this->set_course($courseInfo);
63
                }
64
65
                // Check if teacher/admin rights.
66
                $isAllowToEdit = api_is_allowed_to_edit(false, true);
67
                // Check course setting.
68
                if (api_get_course_setting('allow_user_edit_agenda') == '1'
69
                    && api_is_allowed_in_course()
70
                ) {
71
                    $isAllowToEdit = true;
72
                }
73
74
                $groupId = api_get_group_id();
75
                if (!empty($groupId)) {
76
                    $groupInfo = GroupManager::get_group_properties($groupId);
77
                    $userHasAccess = GroupManager::user_has_access(
78
                        api_get_user_id(),
79
                        $groupInfo['iid'],
80
                        GroupManager::GROUP_TOOL_CALENDAR
81
                    );
82
                    $isTutor = GroupManager::is_tutor_of_group(
83
                        api_get_user_id(),
84
                        $groupInfo
85
                    );
86
87
                    $isGroupAccess = $userHasAccess || $isTutor;
88
                    $isAllowToEdit = false;
89
                    if ($isGroupAccess) {
90
                        $isAllowToEdit = true;
91
                    }
92
                }
93
94
                if (false === $isAllowToEdit && !empty($sessionId)) {
95
                    $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
96
                    if ($allowDhrToEdit) {
97
                        $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
98
                        if ($isHrm) {
99
                            $isAllowToEdit = true;
100
                        }
101
                    }
102
                }
103
                break;
104
            case 'admin':
105
                $isAllowToEdit = api_is_platform_admin();
106
                break;
107
            case 'personal':
108
                $isAllowToEdit = !api_is_anonymous();
109
                break;
110
        }
111
112
        $this->setIsAllowedToEdit($isAllowToEdit);
113
        $this->events = [];
114
        $agendaColors = array_merge(
115
            [
116
                'platform' => 'red', //red
117
                'course' => '#458B00', //green
118
                'group' => '#A0522D', //siena
119
                'session' => '#00496D', // kind of green
120
                'other_session' => '#999', // kind of green
121
                'personal' => 'steel blue', //steel blue
122
                'student_publication' => '#FF8C00', //DarkOrange
123
            ],
124
            api_get_configuration_value('agenda_colors') ?: []
125
        );
126
127
        // Event colors
128
        $this->event_platform_color = $agendaColors['platform'];
129
        $this->event_course_color = $agendaColors['course'];
130
        $this->event_group_color = $agendaColors['group'];
131
        $this->event_session_color = $agendaColors['session'];
132
        $this->eventOtherSessionColor = $agendaColors['other_session'];
133
        $this->event_personal_color = $agendaColors['personal'];
134
        $this->eventStudentPublicationColor = $agendaColors['student_publication'];
135
    }
136
137
    /**
138
     * @param int $senderId
139
     */
140
    public function setSenderId($senderId)
141
    {
142
        $this->senderId = (int) $senderId;
143
    }
144
145
    /**
146
     * @return int
147
     */
148
    public function getSenderId()
149
    {
150
        return $this->senderId;
151
    }
152
153
    /**
154
     * @param string $type can be 'personal', 'admin'  or  'course'
155
     */
156
    public function setType($type)
157
    {
158
        $type = (string) trim($type);
159
        $typeList = $this->getTypes();
160
        if (in_array($type, $typeList, true)) {
161
            $this->type = $type;
162
        }
163
    }
164
165
    /**
166
     * Returns the type previously set (and filtered) through setType
167
     * If setType() was not called, then type defaults to "personal" as
168
     * set in the class definition.
169
     */
170
    public function getType()
171
    {
172
        if (isset($this->type)) {
173
            return $this->type;
174
        }
175
    }
176
177
    /**
178
     * @param int $id
179
     */
180
    public function setSessionId($id)
181
    {
182
        $this->sessionId = (int) $id;
183
    }
184
185
    /**
186
     * @param array $sessionInfo
187
     */
188
    public function setSessionInfo($sessionInfo)
189
    {
190
        $this->sessionInfo = $sessionInfo;
191
    }
192
193
    /**
194
     * @return int $id
195
     */
196
    public function getSessionId()
197
    {
198
        return $this->sessionId;
199
    }
200
201
    /**
202
     * @param array $courseInfo
203
     */
204
    public function set_course($courseInfo)
205
    {
206
        $this->course = $courseInfo;
207
    }
208
209
    /**
210
     * @return array
211
     */
212
    public function getTypes()
213
    {
214
        return $this->types;
215
    }
216
217
    /**
218
     * Adds an event to the calendar.
219
     *
220
     * @param string $start                 datetime format: 2012-06-14 09:00:00 in local time
221
     * @param string $end                   datetime format: 2012-06-14 09:00:00 in local time
222
     * @param string $allDay                (true, false)
223
     * @param string $title
224
     * @param string $content
225
     * @param array  $usersToSend           array('everyone') or a list of user/group ids
226
     * @param bool   $addAsAnnouncement     event as a *course* announcement
227
     * @param int    $parentEventId
228
     * @param array  $attachmentArray       array of $_FILES['']
229
     * @param array  $attachmentCommentList
230
     * @param string $eventComment
231
     * @param string $color
232
     *
233
     * @return int
234
     */
235
    public function addEvent(
236
        $start,
237
        $end,
238
        $allDay,
239
        $title,
240
        $content,
241
        $usersToSend = [],
242
        $addAsAnnouncement = false,
243
        $parentEventId = null,
244
        $attachmentArray = [],
245
        $attachmentCommentList = [],
246
        $eventComment = null,
247
        $color = ''
248
    ) {
249
        $start = api_get_utc_datetime($start);
250
        $end = api_get_utc_datetime($end);
251
        $allDay = isset($allDay) && ($allDay === 'true' || $allDay == 1) ? 1 : 0;
252
        $id = null;
253
254
        switch ($this->type) {
255
            case 'personal':
256
                $attributes = [
257
                    'user' => api_get_user_id(),
258
                    'title' => $title,
259
                    'text' => $content,
260
                    'date' => $start,
261
                    'enddate' => $end,
262
                    'all_day' => $allDay,
263
                    'color' => $color,
264
                ];
265
266
                $id = Database::insert(
267
                    $this->tbl_personal_agenda,
268
                    $attributes
269
                );
270
                break;
271
            case 'course':
272
                $attributes = [
273
                    'title' => $title,
274
                    'content' => $content,
275
                    'start_date' => $start,
276
                    'end_date' => $end,
277
                    'all_day' => $allDay,
278
                    'session_id' => $this->getSessionId(),
279
                    'c_id' => $this->course['real_id'],
280
                    'comment' => $eventComment,
281
                    'color' => $color,
282
                ];
283
284
                if (!empty($parentEventId)) {
285
                    $attributes['parent_event_id'] = $parentEventId;
286
                }
287
288
                $senderId = $this->getSenderId();
289
                $sessionId = $this->getSessionId();
290
291
                // Simple course event.
292
                $id = Database::insert($this->tbl_course_agenda, $attributes);
293
294
                if ($id) {
295
                    $sql = "UPDATE ".$this->tbl_course_agenda." SET id = iid WHERE iid = $id";
296
                    Database::query($sql);
297
298
                    $groupId = api_get_group_id();
299
                    $groupInfo = [];
300
                    if ($groupId) {
301
                        $groupInfo = GroupManager::get_group_properties(
302
                            $groupId
303
                        );
304
                    }
305
306
                    if (!empty($usersToSend)) {
307
                        $sendTo = $this->parseSendToArray($usersToSend);
308
                        if ($sendTo['everyone']) {
309
                            api_item_property_update(
310
                                $this->course,
311
                                TOOL_CALENDAR_EVENT,
312
                                $id,
313
                                'AgendaAdded',
314
                                $senderId,
315
                                $groupInfo,
316
                                '',
317
                                $start,
318
                                $end,
319
                                $sessionId
320
                            );
321
                            api_item_property_update(
322
                                $this->course,
323
                                TOOL_CALENDAR_EVENT,
324
                                $id,
325
                                'visible',
326
                                $senderId,
327
                                $groupInfo,
328
                                '',
329
                                $start,
330
                                $end,
331
                                $sessionId
332
                            );
333
                        } else {
334
                            // Storing the selected groups
335
                            if (!empty($sendTo['groups'])) {
336
                                foreach ($sendTo['groups'] as $group) {
337
                                    $groupInfoItem = [];
338
                                    if ($group) {
339
                                        $groupInfoItem = GroupManager::get_group_properties($group);
340
                                    }
341
342
                                    api_item_property_update(
343
                                        $this->course,
344
                                        TOOL_CALENDAR_EVENT,
345
                                        $id,
346
                                        'AgendaAdded',
347
                                        $senderId,
348
                                        $groupInfoItem,
349
                                        0,
350
                                        $start,
351
                                        $end,
352
                                        $sessionId
353
                                    );
354
355
                                    api_item_property_update(
356
                                        $this->course,
357
                                        TOOL_CALENDAR_EVENT,
358
                                        $id,
359
                                        'visible',
360
                                        $senderId,
361
                                        $groupInfoItem,
362
                                        0,
363
                                        $start,
364
                                        $end,
365
                                        $sessionId
366
                                    );
367
                                }
368
                            }
369
370
                            // storing the selected users
371
                            if (!empty($sendTo['users'])) {
372
                                foreach ($sendTo['users'] as $userId) {
373
                                    api_item_property_update(
374
                                        $this->course,
375
                                        TOOL_CALENDAR_EVENT,
376
                                        $id,
377
                                        'AgendaAdded',
378
                                        $senderId,
379
                                        $groupInfo,
380
                                        $userId,
381
                                        $start,
382
                                        $end,
383
                                        $sessionId
384
                                    );
385
386
                                    api_item_property_update(
387
                                        $this->course,
388
                                        TOOL_CALENDAR_EVENT,
389
                                        $id,
390
                                        'visible',
391
                                        $senderId,
392
                                        $groupInfo,
393
                                        $userId,
394
                                        $start,
395
                                        $end,
396
                                        $sessionId
397
                                    );
398
                                }
399
                            }
400
                        }
401
                    }
402
403
                    // Add announcement.
404
                    if ($addAsAnnouncement) {
405
                        $this->storeAgendaEventAsAnnouncement(
406
                            $id,
407
                            $usersToSend
408
                        );
409
                    }
410
411
                    // Add attachment.
412
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
413
                        $counter = 0;
414
                        foreach ($attachmentArray as $attachmentItem) {
415
                            $this->addAttachment(
416
                                $id,
417
                                $attachmentItem,
418
                                $attachmentCommentList[$counter],
419
                                $this->course
420
                            );
421
                            $counter++;
422
                        }
423
                    }
424
                }
425
                break;
426
            case 'admin':
427
                if (api_is_platform_admin()) {
428
                    $attributes = [
429
                        'title' => $title,
430
                        'content' => $content,
431
                        'start_date' => $start,
432
                        'end_date' => $end,
433
                        'all_day' => $allDay,
434
                        'access_url_id' => api_get_current_access_url_id(),
435
                    ];
436
437
                    $id = Database::insert(
438
                        $this->tbl_global_agenda,
439
                        $attributes
440
                    );
441
                }
442
                break;
443
        }
444
445
        return $id;
446
    }
447
448
    /**
449
     * @param int $eventId
450
     * @param int $courseId
451
     *
452
     * @return array
453
     */
454
    public function getRepeatedInfoByEvent($eventId, $courseId)
455
    {
456
        $repeatTable = Database::get_course_table(TABLE_AGENDA_REPEAT);
457
        $eventId = (int) $eventId;
458
        $courseId = (int) $courseId;
459
        $sql = "SELECT * FROM $repeatTable
460
                WHERE c_id = $courseId AND cal_id = $eventId";
461
        $res = Database::query($sql);
462
        $repeatInfo = [];
463
        if (Database::num_rows($res) > 0) {
464
            $repeatInfo = Database::fetch_array($res, 'ASSOC');
465
        }
466
467
        return $repeatInfo;
468
    }
469
470
    /**
471
     * @param string $type
472
     * @param string $startEvent      in UTC
473
     * @param string $endEvent        in UTC
474
     * @param string $repeatUntilDate in UTC
475
     *
476
     * @throws Exception
477
     *
478
     * @return array with local times
479
     */
480
    public function generateDatesByType($type, $startEvent, $endEvent, $repeatUntilDate)
481
    {
482
        $continue = true;
483
        $repeatUntilDate = new DateTime($repeatUntilDate, new DateTimeZone('UTC'));
484
        $loopMax = 365;
485
        $counter = 0;
486
        $list = [];
487
488
        switch ($type) {
489
            case 'daily':
490
                $interval = 'P1D';
491
                break;
492
            case 'weekly':
493
                $interval = 'P1W';
494
                break;
495
            case 'monthlyByDate':
496
                $interval = 'P1M';
497
                break;
498
            case 'monthlyByDay':
499
                // not yet implemented
500
                break;
501
            case 'monthlyByDayR':
502
                // not yet implemented
503
                break;
504
            case 'yearly':
505
                $interval = 'P1Y';
506
                break;
507
        }
508
509
        if (empty($interval)) {
510
            return [];
511
        }
512
        $timeZone = api_get_timezone();
513
514
        while ($continue) {
515
            $startDate = new DateTime($startEvent, new DateTimeZone('UTC'));
516
            $endDate = new DateTime($endEvent, new DateTimeZone('UTC'));
517
518
            $startDate->add(new DateInterval($interval));
519
            $endDate->add(new DateInterval($interval));
520
521
            $newStartDate = $startDate->format('Y-m-d H:i:s');
522
            $newEndDate = $endDate->format('Y-m-d H:i:s');
523
524
            $startEvent = $newStartDate;
525
            $endEvent = $newEndDate;
526
527
            if ($endDate > $repeatUntilDate) {
528
                break;
529
            }
530
531
	    // @todo remove comment code
532
	    // The code below was not adpating to saving light time but was doubling the difference with UTC time.
533
	    // Might be necessary to adapt to update saving light time difference.
534
/*            $startDateInLocal = new DateTime($newStartDate, new DateTimeZone($timeZone));
535
            if ($startDateInLocal->format('I') == 0) {
536
                // Is saving time? Then fix UTC time to add time
537
                $seconds = $startDateInLocal->getOffset();
538
                $startDate->add(new DateInterval("PT".$seconds."S"));
539
                //$startDateFixed = $startDate->format('Y-m-d H:i:s');
540
                //$startDateInLocalFixed = new DateTime($startDateFixed, new DateTimeZone($timeZone));
541
                //$newStartDate = $startDateInLocalFixed->format('Y-m-d H:i:s');
542
                //$newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
543
            }
544
545
            $endDateInLocal = new DateTime($newEndDate, new DateTimeZone($timeZone));
546
            if ($endDateInLocal->format('I') == 0) {
547
                // Is saving time? Then fix UTC time to add time
548
                $seconds = $endDateInLocal->getOffset();
549
                $endDate->add(new DateInterval("PT".$seconds."S"));
550
                //$endDateFixed = $endDate->format('Y-m-d H:i:s');
551
                //$endDateInLocalFixed = new DateTime($endDateFixed, new DateTimeZone($timeZone));
552
                //$newEndDate = $endDateInLocalFixed->format('Y-m-d H:i:s');
553
	    }
554
*/
555
	    $newStartDate = $startDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
556
            $newEndDate = $endDate->setTimezone(new DateTimeZone($timeZone))->format('Y-m-d H:i:s');
557
            $list[] = ['start' => $newStartDate, 'end' => $newEndDate];
558
            $counter++;
559
560
            // just in case stop if more than $loopMax
561
            if ($counter > $loopMax) {
562
                break;
563
            }
564
        }
565
566
        return $list;
567
    }
568
569
    /**
570
     * @param int    $eventId
571
     * @param string $type
572
     * @param string $end     in UTC
573
     * @param array  $sentTo
574
     *
575
     * @return bool
576
     */
577
    public function addRepeatedItem($eventId, $type, $end, $sentTo = [])
578
    {
579
        $t_agenda = Database::get_course_table(TABLE_AGENDA);
580
        $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT);
581
582
        if (empty($this->course)) {
583
            return false;
584
        }
585
586
        $courseId = $this->course['real_id'];
587
        $eventId = (int) $eventId;
588
589
        $sql = "SELECT title, content, start_date, end_date, all_day
590
                FROM $t_agenda
591
                WHERE c_id = $courseId AND id = $eventId";
592
        $res = Database::query($sql);
593
594
        if (Database::num_rows($res) !== 1) {
595
            return false;
596
        }
597
598
        $typeList = [
599
            'daily',
600
            'weekly',
601
            'monthlyByDate',
602
            'monthlyByDay',
603
            'monthlyByDayR',
604
            'yearly',
605
        ];
606
607
        if (!in_array($type, $typeList)) {
608
            return false;
609
        }
610
611
        $now = time();
612
613
        // The event has to repeat *in the future*. We don't allow repeated
614
        // events in the past.
615
        $endTimeStamp = api_strtotime($end, 'UTC');
616
617
        if ($endTimeStamp < $now) {
618
            return false;
619
        }
620
621
        $row = Database::fetch_array($res);
622
623
        $title = $row['title'];
624
        $content = $row['content'];
625
        $allDay = $row['all_day'];
626
627
        $type = Database::escape_string($type);
628
        $end = Database::escape_string($end);
629
630
        $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end)
631
                VALUES ($courseId, '$eventId', '$type', '$endTimeStamp')";
632
        Database::query($sql);
633
634
        $generatedDates = $this->generateDatesByType($type, $row['start_date'], $row['end_date'], $end);
635
636
        if (empty($generatedDates)) {
637
            return false;
638
        }
639
640
        foreach ($generatedDates as $dateInfo) {
641
//            $start = api_get_local_time($dateInfo['start']);
642
//            $end = api_get_local_time($dateInfo['end']);
643
            // On line 529 in function generateDatesByType there is a @todo remove comment code
644
            // just before the part updating the date in local time so keep both synchronised
645
            $start = $dateInfo['start'];
646
            $end = $dateInfo['end'];
647
648
            $this->addEvent(
649
                $start,
650
                $end,
651
                $allDay,
652
                $title,
653
                $content,
654
                $sentTo,
655
                false,
656
                $eventId
657
            );
658
        }
659
660
        return true;
661
    }
662
663
    /**
664
     * @param int   $item_id
665
     * @param array $sentTo
666
     *
667
     * @return int
668
     */
669
    public function storeAgendaEventAsAnnouncement($item_id, $sentTo = [])
670
    {
671
        $table_agenda = Database::get_course_table(TABLE_AGENDA);
672
        $courseId = api_get_course_int_id();
673
674
        // Check params
675
        if (empty($item_id) || $item_id != strval(intval($item_id))) {
676
            return -1;
677
        }
678
679
        // Get the agenda item.
680
        $item_id = intval($item_id);
681
        $sql = "SELECT * FROM $table_agenda
682
                WHERE c_id = $courseId AND id = ".$item_id;
683
        $res = Database::query($sql);
684
685
        if (Database::num_rows($res) > 0) {
686
            $row = Database::fetch_array($res, 'ASSOC');
687
688
            // Sending announcement
689
            if (!empty($sentTo)) {
690
                $id = AnnouncementManager::add_announcement(
691
                    api_get_course_info(),
692
                    api_get_session_id(),
693
                    $row['title'],
694
                    $row['content'],
695
                    $sentTo,
696
                    null,
697
                    null,
698
                    $row['end_date']
699
                );
700
701
                AnnouncementManager::sendEmail(
702
                    api_get_course_info(),
703
                    api_get_session_id(),
704
                    $id
705
                );
706
707
                return $id;
708
            }
709
        }
710
711
        return -1;
712
    }
713
714
    /**
715
     * Edits an event.
716
     *
717
     * @param int    $id
718
     * @param string $start                 datetime format: 2012-06-14 09:00:00
719
     * @param string $end                   datetime format: 2012-06-14 09:00:00
720
     * @param int    $allDay                is all day 'true' or 'false'
721
     * @param string $title
722
     * @param string $content
723
     * @param array  $usersToSend
724
     * @param array  $attachmentArray
725
     * @param array  $attachmentCommentList
726
     * @param string $comment
727
     * @param string $color
728
     * @param bool   $addAnnouncement
729
     * @param bool   $updateContent
730
     * @param int    $authorId
731
     *
732
     * @return bool
733
     */
734
    public function editEvent(
735
        $id,
736
        $start,
737
        $end,
738
        $allDay,
739
        $title,
740
        $content,
741
        $usersToSend = [],
742
        $attachmentArray = [],
743
        $attachmentCommentList = [],
744
        $comment = null,
745
        $color = '',
746
        $addAnnouncement = false,
747
        $updateContent = true,
748
        $authorId = 0
749
    ) {
750
        $start = api_get_utc_datetime($start);
751
        $end = api_get_utc_datetime($end);
752
        $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0;
753
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
754
755
        switch ($this->type) {
756
            case 'personal':
757
                $eventInfo = $this->get_event($id);
758
                if ($eventInfo['user'] != api_get_user_id()) {
759
                    break;
760
                }
761
                $attributes = [
762
                    'title' => $title,
763
                    'date' => $start,
764
                    'enddate' => $end,
765
                    'all_day' => $allDay,
766
                ];
767
768
                if ($updateContent) {
769
                    $attributes['text'] = $content;
770
                }
771
772
                if (!empty($color)) {
773
                    $attributes['color'] = $color;
774
                }
775
776
                Database::update(
777
                    $this->tbl_personal_agenda,
778
                    $attributes,
779
                    ['id = ?' => $id]
780
                );
781
                break;
782
            case 'course':
783
                $eventInfo = $this->get_event($id);
784
785
                if (empty($eventInfo)) {
786
                    return false;
787
                }
788
789
                $groupId = api_get_group_id();
790
                $groupIid = 0;
791
                $groupInfo = [];
792
                if ($groupId) {
793
                    $groupInfo = GroupManager::get_group_properties($groupId);
794
                    if ($groupInfo) {
795
                        $groupIid = $groupInfo['iid'];
796
                    }
797
                }
798
799
                $courseId = $this->course['real_id'];
800
801
                if (empty($courseId)) {
802
                    return false;
803
                }
804
805
                if ($this->getIsAllowedToEdit()) {
806
                    $attributes = [
807
                        'title' => $title,
808
                        'start_date' => $start,
809
                        'end_date' => $end,
810
                        'all_day' => $allDay,
811
                        'comment' => $comment,
812
                    ];
813
814
                    if ($updateContent) {
815
                        $attributes['content'] = $content;
816
                    }
817
818
                    if (!empty($color)) {
819
                        $attributes['color'] = $color;
820
                    }
821
822
                    Database::update(
823
                        $this->tbl_course_agenda,
824
                        $attributes,
825
                        [
826
                            'id = ? AND c_id = ? AND session_id = ? ' => [
827
                                $id,
828
                                $courseId,
829
                                $this->sessionId,
830
                            ],
831
                        ]
832
                    );
833
834
                    if (!empty($usersToSend)) {
835
                        $sendTo = $this->parseSendToArray($usersToSend);
836
837
                        $usersToDelete = array_diff(
838
                            $eventInfo['send_to']['users'],
839
                            $sendTo['users']
840
                        );
841
                        $usersToAdd = array_diff(
842
                            $sendTo['users'],
843
                            $eventInfo['send_to']['users']
844
                        );
845
846
                        $groupsToDelete = array_diff(
847
                            $eventInfo['send_to']['groups'],
848
                            $sendTo['groups']
849
                        );
850
                        $groupToAdd = array_diff(
851
                            $sendTo['groups'],
852
                            $eventInfo['send_to']['groups']
853
                        );
854
855
                        if ($sendTo['everyone']) {
856
                            // Delete all from group
857
                            if (isset($eventInfo['send_to']['groups']) &&
858
                                !empty($eventInfo['send_to']['groups'])
859
                            ) {
860
                                foreach ($eventInfo['send_to']['groups'] as $group) {
861
                                    $groupIidItem = 0;
862
                                    if ($group) {
863
                                        $groupInfoItem = GroupManager::get_group_properties(
864
                                            $group
865
                                        );
866
                                        if ($groupInfoItem) {
867
                                            $groupIidItem = $groupInfoItem['iid'];
868
                                        }
869
                                    }
870
871
                                    api_item_property_delete(
872
                                        $this->course,
873
                                        TOOL_CALENDAR_EVENT,
874
                                        $id,
875
                                        0,
876
                                        $groupIidItem,
877
                                        $this->sessionId
878
                                    );
879
                                }
880
                            }
881
882
                            // Storing the selected users.
883
                            if (isset($eventInfo['send_to']['users']) &&
884
                                !empty($eventInfo['send_to']['users'])
885
                            ) {
886
                                foreach ($eventInfo['send_to']['users'] as $userId) {
887
                                    api_item_property_delete(
888
                                        $this->course,
889
                                        TOOL_CALENDAR_EVENT,
890
                                        $id,
891
                                        $userId,
892
                                        $groupIid,
893
                                        $this->sessionId
894
                                    );
895
                                }
896
                            }
897
898
                            // Add to everyone only.
899
                            api_item_property_update(
900
                                $this->course,
901
                                TOOL_CALENDAR_EVENT,
902
                                $id,
903
                                'visible',
904
                                $authorId,
905
                                $groupInfo,
906
                                null,
907
                                $start,
908
                                $end,
909
                                $this->sessionId
910
                            );
911
                        } else {
912
                            // Delete "everyone".
913
                            api_item_property_delete(
914
                                $this->course,
915
                                TOOL_CALENDAR_EVENT,
916
                                $id,
917
                                0,
918
                                0,
919
                                $this->sessionId
920
                            );
921
922
                            // Add groups
923
                            if (!empty($groupToAdd)) {
924
                                foreach ($groupToAdd as $group) {
925
                                    $groupInfoItem = [];
926
                                    if ($group) {
927
                                        $groupInfoItem = GroupManager::get_group_properties(
928
                                            $group
929
                                        );
930
                                    }
931
932
                                    api_item_property_update(
933
                                        $this->course,
934
                                        TOOL_CALENDAR_EVENT,
935
                                        $id,
936
                                        'visible',
937
                                        $authorId,
938
                                        $groupInfoItem,
939
                                        0,
940
                                        $start,
941
                                        $end,
942
                                        $this->sessionId
943
                                    );
944
                                }
945
                            }
946
947
                            // Delete groups.
948
                            if (!empty($groupsToDelete)) {
949
                                foreach ($groupsToDelete as $group) {
950
                                    $groupIidItem = 0;
951
                                    $groupInfoItem = [];
952
                                    if ($group) {
953
                                        $groupInfoItem = GroupManager::get_group_properties(
954
                                            $group
955
                                        );
956
                                        if ($groupInfoItem) {
957
                                            $groupIidItem = $groupInfoItem['iid'];
958
                                        }
959
                                    }
960
961
                                    api_item_property_delete(
962
                                        $this->course,
963
                                        TOOL_CALENDAR_EVENT,
964
                                        $id,
965
                                        0,
966
                                        $groupIidItem,
967
                                        $this->sessionId
968
                                    );
969
                                }
970
                            }
971
972
                            // Add users.
973
                            if (!empty($usersToAdd)) {
974
                                foreach ($usersToAdd as $userId) {
975
                                    api_item_property_update(
976
                                        $this->course,
977
                                        TOOL_CALENDAR_EVENT,
978
                                        $id,
979
                                        'visible',
980
                                        $authorId,
981
                                        $groupInfo,
982
                                        $userId,
983
                                        $start,
984
                                        $end,
985
                                        $this->sessionId
986
                                    );
987
                                }
988
                            }
989
990
                            // Delete users.
991
                            if (!empty($usersToDelete)) {
992
                                foreach ($usersToDelete as $userId) {
993
                                    api_item_property_delete(
994
                                        $this->course,
995
                                        TOOL_CALENDAR_EVENT,
996
                                        $id,
997
                                        $userId,
998
                                        $groupInfo,
999
                                        $this->sessionId
1000
                                    );
1001
                                }
1002
                            }
1003
                        }
1004
                    }
1005
1006
                    // Add announcement.
1007
                    if (isset($addAnnouncement) && !empty($addAnnouncement)) {
1008
                        $this->storeAgendaEventAsAnnouncement(
1009
                            $id,
1010
                            $usersToSend
1011
                        );
1012
                    }
1013
1014
                    // Add attachment.
1015
                    if (isset($attachmentArray) && !empty($attachmentArray)) {
1016
                        $counter = 0;
1017
                        foreach ($attachmentArray as $attachmentItem) {
1018
                            $this->updateAttachment(
1019
                                $attachmentItem['id'],
1020
                                $id,
1021
                                $attachmentItem,
1022
                                $attachmentCommentList[$counter],
1023
                                $this->course
1024
                            );
1025
                            $counter++;
1026
                        }
1027
                    }
1028
1029
                    return true;
1030
                } else {
1031
                    return false;
1032
                }
1033
                break;
1034
            case 'admin':
1035
            case 'platform':
1036
                if (api_is_platform_admin()) {
1037
                    $attributes = [
1038
                        'title' => $title,
1039
                        'start_date' => $start,
1040
                        'end_date' => $end,
1041
                        'all_day' => $allDay,
1042
                    ];
1043
1044
                    if ($updateContent) {
1045
                        $attributes['content'] = $content;
1046
                    }
1047
                    Database::update(
1048
                        $this->tbl_global_agenda,
1049
                        $attributes,
1050
                        ['id = ?' => $id]
1051
                    );
1052
                }
1053
                break;
1054
        }
1055
    }
1056
1057
    /**
1058
     * @param int  $id
1059
     * @param bool $deleteAllItemsFromSerie
1060
     */
1061
    public function deleteEvent($id, $deleteAllItemsFromSerie = false)
1062
    {
1063
        switch ($this->type) {
1064
            case 'personal':
1065
                $eventInfo = $this->get_event($id);
1066
                if ($eventInfo['user'] == api_get_user_id()) {
1067
                    Database::delete(
1068
                        $this->tbl_personal_agenda,
1069
                        ['id = ?' => $id]
1070
                    );
1071
                }
1072
                break;
1073
            case 'course':
1074
                $courseId = api_get_course_int_id();
1075
                $isAllowToEdit = $this->getIsAllowedToEdit();
1076
1077
                if (!empty($courseId) && $isAllowToEdit) {
1078
                    $eventInfo = $this->get_event($id);
1079
                    if ($deleteAllItemsFromSerie) {
1080
                        /* This is one of the children.
1081
                           Getting siblings and delete 'Em all + the father! */
1082
                        if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) {
1083
                            // Removing items.
1084
                            $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']);
1085
                            if (!empty($events)) {
1086
                                foreach ($events as $event) {
1087
                                    $this->deleteEvent($event['id']);
1088
                                }
1089
                            }
1090
                            // Removing parent.
1091
                            $this->deleteEvent($eventInfo['parent_event_id']);
1092
                        } else {
1093
                            // This is the father looking for the children.
1094
                            $events = $this->getAllRepeatEvents($id);
1095
                            if (!empty($events)) {
1096
                                foreach ($events as $event) {
1097
                                    $this->deleteEvent($event['id']);
1098
                                }
1099
                            }
1100
                        }
1101
                    }
1102
1103
                    // Removing from events.
1104
                    Database::delete(
1105
                        $this->tbl_course_agenda,
1106
                        ['id = ? AND c_id = ?' => [$id, $courseId]]
1107
                    );
1108
1109
                    api_item_property_update(
1110
                        $this->course,
1111
                        TOOL_CALENDAR_EVENT,
1112
                        $id,
1113
                        'delete',
1114
                        api_get_user_id()
1115
                    );
1116
1117
                    // Removing from series.
1118
                    Database::delete(
1119
                        $this->table_repeat,
1120
                        [
1121
                            'cal_id = ? AND c_id = ?' => [
1122
                                $id,
1123
                                $courseId,
1124
                            ],
1125
                        ]
1126
                    );
1127
1128
                    if (isset($eventInfo['attachment']) && !empty($eventInfo['attachment'])) {
1129
                        foreach ($eventInfo['attachment'] as $attachment) {
1130
                            self::deleteAttachmentFile(
1131
                                $attachment['id'],
1132
                                $this->course
1133
                            );
1134
                        }
1135
                    }
1136
                }
1137
                break;
1138
            case 'admin':
1139
                if (api_is_platform_admin()) {
1140
                    Database::delete(
1141
                        $this->tbl_global_agenda,
1142
                        ['id = ?' => $id]
1143
                    );
1144
                }
1145
                break;
1146
        }
1147
    }
1148
1149
    /**
1150
     * Get agenda events.
1151
     *
1152
     * @param int    $start
1153
     * @param int    $end
1154
     * @param int    $courseId
1155
     * @param int    $groupId
1156
     * @param int    $user_id
1157
     * @param string $format
1158
     *
1159
     * @return array|string
1160
     */
1161
    public function getEvents(
1162
        $start,
1163
        $end,
1164
        $courseId = null,
1165
        $groupId = null,
1166
        $user_id = 0,
1167
        $format = 'json'
1168
    ) {
1169
        switch ($this->type) {
1170
            case 'admin':
1171
                $this->getPlatformEvents($start, $end);
1172
                break;
1173
            case 'course':
1174
                $courseInfo = api_get_course_info_by_id($courseId);
1175
1176
                // Session coach can see all events inside a session.
1177
                if (api_is_coach()) {
1178
                    // Own course
1179
                    $this->getCourseEvents(
1180
                        $start,
1181
                        $end,
1182
                        $courseInfo,
1183
                        $groupId,
1184
                        $this->sessionId,
1185
                        $user_id
1186
                    );
1187
1188
                    // Others
1189
                    $this->getSessionEvents(
1190
                        $start,
1191
                        $end,
1192
                        $this->sessionId,
1193
                        $user_id,
1194
                        $this->eventOtherSessionColor
1195
                    );
1196
                } else {
1197
                    $this->getCourseEvents(
1198
                        $start,
1199
                        $end,
1200
                        $courseInfo,
1201
                        $groupId,
1202
                        $this->sessionId,
1203
                        $user_id
1204
                    );
1205
                }
1206
                break;
1207
            case 'personal':
1208
            default:
1209
                $sessionFilterActive = false;
1210
                if (!empty($this->sessionId)) {
1211
                    $sessionFilterActive = true;
1212
                }
1213
1214
                if ($sessionFilterActive == false) {
1215
                    // Getting personal events
1216
                    $this->getPersonalEvents($start, $end);
1217
1218
                    // Getting platform/admin events
1219
                    $this->getPlatformEvents($start, $end);
1220
                }
1221
1222
                $ignoreVisibility = api_get_configuration_value('personal_agenda_show_all_session_events');
1223
1224
                // Getting course events
1225
                $my_course_list = [];
1226
                if (!api_is_anonymous()) {
1227
                    $session_list = SessionManager::get_sessions_by_user(
1228
                        api_get_user_id(),
1229
                        $ignoreVisibility
1230
                    );
1231
                    $my_course_list = CourseManager::get_courses_list_by_user_id(
1232
                        api_get_user_id(),
1233
                        false
1234
                    );
1235
                }
1236
1237
                if (api_is_drh()) {
1238
                    if (api_drh_can_access_all_session_content()) {
1239
                        $session_list = [];
1240
                        $sessionList = SessionManager::get_sessions_followed_by_drh(
1241
                            api_get_user_id(),
1242
                            null,
1243
                            null,
1244
                            null,
1245
                            true,
1246
                            false
1247
                        );
1248
1249
                        if (!empty($sessionList)) {
1250
                            foreach ($sessionList as $sessionItem) {
1251
                                $sessionId = $sessionItem['id'];
1252
                                $courses = SessionManager::get_course_list_by_session_id($sessionId);
1253
                                $sessionInfo = [
1254
                                    'session_id' => $sessionId,
1255
                                    'courses' => $courses,
1256
                                ];
1257
                                $session_list[] = $sessionInfo;
1258
                            }
1259
                        }
1260
                    }
1261
                }
1262
1263
                if (!empty($session_list)) {
1264
                    foreach ($session_list as $session_item) {
1265
                        if ($sessionFilterActive) {
1266
                            if ($this->sessionId != $session_item['session_id']) {
1267
                                continue;
1268
                            }
1269
                        }
1270
1271
                        $my_courses = $session_item['courses'];
1272
                        $my_session_id = $session_item['session_id'];
1273
1274
                        if (!empty($my_courses)) {
1275
                            foreach ($my_courses as $course_item) {
1276
                                $courseInfo = api_get_course_info_by_id(
1277
                                    $course_item['real_id']
1278
                                );
1279
                                $this->getCourseEvents(
1280
                                    $start,
1281
                                    $end,
1282
                                    $courseInfo,
1283
                                    0,
1284
                                    $my_session_id
1285
                                );
1286
                            }
1287
                        }
1288
                    }
1289
                }
1290
1291
                if (!empty($my_course_list) && $sessionFilterActive == false) {
1292
                    foreach ($my_course_list as $courseInfoItem) {
1293
                        $courseInfo = api_get_course_info_by_id(
1294
                            $courseInfoItem['real_id']
1295
                        );
1296
                        if (isset($courseId) && !empty($courseId)) {
1297
                            if ($courseInfo['real_id'] == $courseId) {
1298
                                $this->getCourseEvents(
1299
                                    $start,
1300
                                    $end,
1301
                                    $courseInfo,
1302
                                    0,
1303
                                    0,
1304
                                    $user_id
1305
                                );
1306
                            }
1307
                        } else {
1308
                            $this->getCourseEvents(
1309
                                $start,
1310
                                $end,
1311
                                $courseInfo,
1312
                                0,
1313
                                0,
1314
                                $user_id
1315
                            );
1316
                        }
1317
                    }
1318
                }
1319
                break;
1320
        }
1321
1322
        $this->cleanEvents();
1323
1324
        switch ($format) {
1325
            case 'json':
1326
                if (empty($this->events)) {
1327
                    return '[]';
1328
                }
1329
1330
                return json_encode($this->events);
1331
                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...
1332
            case 'array':
1333
                if (empty($this->events)) {
1334
                    return [];
1335
                }
1336
1337
                return $this->events;
1338
                break;
1339
        }
1340
    }
1341
1342
    /**
1343
     * Clean events.
1344
     *
1345
     * @return bool
1346
     */
1347
    public function cleanEvents()
1348
    {
1349
        if (empty($this->events)) {
1350
            return false;
1351
        }
1352
1353
        foreach ($this->events as &$event) {
1354
            $event['description'] = Security::remove_XSS($event['description']);
1355
            $event['title'] = Security::remove_XSS($event['title']);
1356
        }
1357
1358
        return true;
1359
    }
1360
1361
    /**
1362
     * @param int $id
1363
     * @param int $minute_delta
1364
     *
1365
     * @return int
1366
     */
1367
    public function resizeEvent($id, $minute_delta)
1368
    {
1369
        $id = (int) $id;
1370
        $delta = (int) $minute_delta;
1371
        $event = $this->get_event($id);
1372
        if (!empty($event)) {
1373
            switch ($this->type) {
1374
                case 'personal':
1375
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1376
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1377
							WHERE id = ".$id;
1378
                    Database::query($sql);
1379
                    break;
1380
                case 'course':
1381
                    $sql = "UPDATE $this->tbl_course_agenda SET
1382
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1383
							WHERE
1384
							    c_id = ".$this->course['real_id']." AND
1385
							    id = ".$id;
1386
                    Database::query($sql);
1387
                    break;
1388
                case 'admin':
1389
                    $sql = "UPDATE $this->tbl_global_agenda SET
1390
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1391
							WHERE id = ".$id;
1392
                    Database::query($sql);
1393
                    break;
1394
            }
1395
        }
1396
1397
        return 1;
1398
    }
1399
1400
    /**
1401
     * @param int $id
1402
     * @param int $minute_delta minutes
1403
     * @param int $allDay
1404
     *
1405
     * @return int
1406
     */
1407
    public function move_event($id, $minute_delta, $allDay)
1408
    {
1409
        $id = (int) $id;
1410
        $event = $this->get_event($id);
1411
1412
        if (empty($event)) {
1413
            return false;
1414
        }
1415
1416
        // we convert the hour delta into minutes and add the minute delta
1417
        $delta = (int) $minute_delta;
1418
        $allDay = (int) $allDay;
1419
1420
        if (!empty($event)) {
1421
            switch ($this->type) {
1422
                case 'personal':
1423
                    $sql = "UPDATE $this->tbl_personal_agenda SET
1424
                            all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE),
1425
                            enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
1426
							WHERE id=".$id;
1427
                    Database::query($sql);
1428
                    break;
1429
                case 'course':
1430
                    $sql = "UPDATE $this->tbl_course_agenda SET
1431
                            all_day = $allDay,
1432
                            start_date = DATE_ADD(start_date, INTERVAL $delta MINUTE),
1433
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1434
							WHERE
1435
							    c_id = ".$this->course['real_id']." AND
1436
							    id=".$id;
1437
                    Database::query($sql);
1438
                    break;
1439
                case 'admin':
1440
                    $sql = "UPDATE $this->tbl_global_agenda SET
1441
                            all_day = $allDay,
1442
                            start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
1443
                            end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
1444
							WHERE id=".$id;
1445
                    Database::query($sql);
1446
                    break;
1447
            }
1448
        }
1449
1450
        return 1;
1451
    }
1452
1453
    /**
1454
     * Gets a single event.
1455
     *
1456
     * @param int $id event id
1457
     *
1458
     * @return array
1459
     */
1460
    public function get_event($id)
1461
    {
1462
        // make sure events of the personal agenda can only be seen by the user himself
1463
        $id = (int) $id;
1464
        $event = null;
1465
        switch ($this->type) {
1466
            case 'personal':
1467
                $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1468
                        WHERE id = $id AND user = ".api_get_user_id();
1469
                $result = Database::query($sql);
1470
                if (Database::num_rows($result)) {
1471
                    $event = Database::fetch_array($result, 'ASSOC');
1472
                    $event['description'] = $event['text'];
1473
                    $event['content'] = $event['text'];
1474
                    $event['start_date'] = $event['date'];
1475
                    $event['end_date'] = $event['enddate'];
1476
                }
1477
                break;
1478
            case 'course':
1479
                if (!empty($this->course['real_id'])) {
1480
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
1481
                            WHERE c_id = ".$this->course['real_id']." AND id = ".$id;
1482
                    $result = Database::query($sql);
1483
                    if (Database::num_rows($result)) {
1484
                        $event = Database::fetch_array($result, 'ASSOC');
1485
                        $event['description'] = $event['content'];
1486
1487
                        // Getting send to array
1488
                        $event['send_to'] = $this->getUsersAndGroupSubscribedToEvent(
1489
                            $id,
1490
                            $this->course['real_id'],
1491
                            $this->sessionId
1492
                        );
1493
1494
                        // Getting repeat info
1495
                        $event['repeat_info'] = $this->getRepeatedInfoByEvent(
1496
                            $id,
1497
                            $this->course['real_id']
1498
                        );
1499
1500
                        if (!empty($event['parent_event_id'])) {
1501
                            $event['parent_info'] = $this->get_event($event['parent_event_id']);
1502
                        }
1503
1504
                        $event['attachment'] = $this->getAttachmentList(
1505
                            $id,
1506
                            $this->course
1507
                        );
1508
                    }
1509
                }
1510
                break;
1511
            case 'admin':
1512
            case 'platform':
1513
                $sql = "SELECT * FROM ".$this->tbl_global_agenda."
1514
                        WHERE id = $id";
1515
                $result = Database::query($sql);
1516
                if (Database::num_rows($result)) {
1517
                    $event = Database::fetch_array($result, 'ASSOC');
1518
                    $event['description'] = $event['content'];
1519
                }
1520
                break;
1521
        }
1522
1523
        return $event;
1524
    }
1525
1526
    /**
1527
     * Gets personal events.
1528
     *
1529
     * @param int $start
1530
     * @param int $end
1531
     *
1532
     * @return array
1533
     */
1534
    public function getPersonalEvents($start, $end)
1535
    {
1536
        $start = (int) $start;
1537
        $end = (int) $end;
1538
        $startCondition = '';
1539
        $endCondition = '';
1540
1541
        if ($start !== 0) {
1542
            $startCondition = "AND date >= '".api_get_utc_datetime($start)."'";
1543
        }
1544
        if ($start !== 0) {
1545
            $endCondition = "AND (enddate <= '".api_get_utc_datetime($end)."' OR enddate IS NULL)";
1546
        }
1547
        $user_id = api_get_user_id();
1548
1549
        $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
1550
                WHERE user = $user_id $startCondition $endCondition";
1551
1552
        $result = Database::query($sql);
1553
        $my_events = [];
1554
        if (Database::num_rows($result)) {
1555
            while ($row = Database::fetch_array($result, 'ASSOC')) {
1556
                $event = [];
1557
                $event['id'] = 'personal_'.$row['id'];
1558
                $event['title'] = $row['title'];
1559
                $event['className'] = 'personal';
1560
                $event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
1561
                $event['editable'] = true;
1562
                $event['sent_to'] = get_lang('Me');
1563
                $event['type'] = 'personal';
1564
1565
                if (!empty($row['date'])) {
1566
                    $event['start'] = $this->formatEventDate($row['date']);
1567
                    $event['start_date_localtime'] = api_get_local_time($row['date']);
1568
                }
1569
1570
                if (!empty($row['enddate'])) {
1571
                    $event['end'] = $this->formatEventDate($row['enddate']);
1572
                    $event['end_date_localtime'] = api_get_local_time($row['enddate']);
1573
                }
1574
1575
                $event['description'] = $row['text'];
1576
                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
1577
                $event['parent_event_id'] = 0;
1578
                $event['has_children'] = 0;
1579
1580
                $my_events[] = $event;
1581
                $this->events[] = $event;
1582
            }
1583
        }
1584
1585
        // Add plugin personal events
1586
1587
        $this->plugin = new AppPlugin();
1588
        $plugins = $this->plugin->getInstalledPluginListObject();
1589
        /** @var Plugin $plugin */
1590
        foreach ($plugins as $plugin) {
1591
            if ($plugin->hasPersonalEvents && method_exists($plugin, 'getPersonalEvents')) {
1592
                $pluginEvents = $plugin->getPersonalEvents($this, $start, $end);
1593
1594
                if (!empty($pluginEvents)) {
1595
                    $this->events = array_merge($this->events, $pluginEvents);
1596
                }
1597
            }
1598
        }
1599
1600
        return $my_events;
1601
    }
1602
1603
    /**
1604
     * Get user/group list per event.
1605
     *
1606
     * @param int $eventId
1607
     * @param int $courseId
1608
     * @param int $sessionId
1609
     * @paraù int $sessionId
1610
     *
1611
     * @return array
1612
     */
1613
    public function getUsersAndGroupSubscribedToEvent(
1614
        $eventId,
1615
        $courseId,
1616
        $sessionId
1617
    ) {
1618
        $eventId = (int) $eventId;
1619
        $courseId = (int) $courseId;
1620
        $sessionId = (int) $sessionId;
1621
1622
        $sessionCondition = "ip.session_id = $sessionId";
1623
        if (empty($sessionId)) {
1624
            $sessionCondition = " (ip.session_id = 0 OR ip.session_id IS NULL) ";
1625
        }
1626
1627
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
1628
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1629
1630
        // Get sent_tos
1631
        $sql = "SELECT DISTINCT to_user_id, to_group_id
1632
                FROM $tbl_property ip
1633
                INNER JOIN $tlb_course_agenda agenda
1634
                ON (
1635
                  ip.ref = agenda.id AND
1636
                  ip.c_id = agenda.c_id AND
1637
                  ip.tool = '".TOOL_CALENDAR_EVENT."'
1638
                )
1639
                WHERE
1640
                    ref = $eventId AND
1641
                    ip.visibility = '1' AND
1642
                    ip.c_id = $courseId AND
1643
                    $sessionCondition
1644
                ";
1645
1646
        $result = Database::query($sql);
1647
        $users = [];
1648
        $groups = [];
1649
        $everyone = false;
1650
1651
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1652
            if (!empty($row['to_group_id'])) {
1653
                $groups[] = $row['to_group_id'];
1654
            }
1655
            if (!empty($row['to_user_id'])) {
1656
                $users[] = $row['to_user_id'];
1657
            }
1658
1659
            if (empty($groups) && empty($users)) {
1660
                if ($row['to_group_id'] == 0) {
1661
                    $everyone = true;
1662
                }
1663
            }
1664
        }
1665
1666
        return [
1667
            'everyone' => $everyone,
1668
            'users' => $users,
1669
            'groups' => $groups,
1670
        ];
1671
    }
1672
1673
    /**
1674
     * @param int    $start
1675
     * @param int    $end
1676
     * @param int    $sessionId
1677
     * @param int    $userId
1678
     * @param string $color
1679
     *
1680
     * @return array
1681
     */
1682
    public function getSessionEvents(
1683
        $start,
1684
        $end,
1685
        $sessionId = 0,
1686
        $userId = 0,
1687
        $color = ''
1688
    ) {
1689
        $courses = SessionManager::get_course_list_by_session_id($sessionId);
1690
1691
        if (!empty($courses)) {
1692
            foreach ($courses as $course) {
1693
                $this->getCourseEvents(
1694
                    $start,
1695
                    $end,
1696
                    $course,
1697
                    0,
1698
                    $sessionId,
1699
                    0,
1700
                    $color
1701
                );
1702
            }
1703
        }
1704
    }
1705
1706
    /**
1707
     * @param int    $start
1708
     * @param int    $end
1709
     * @param array  $courseInfo
1710
     * @param int    $groupId
1711
     * @param int    $sessionId
1712
     * @param int    $user_id
1713
     * @param string $color
1714
     *
1715
     * @return array
1716
     */
1717
    public function getCourseEvents(
1718
        $start,
1719
        $end,
1720
        $courseInfo,
1721
        $groupId = 0,
1722
        $sessionId = 0,
1723
        $user_id = 0,
1724
        $color = ''
1725
    ) {
1726
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
1727
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
1728
1729
        if (empty($courseInfo)) {
1730
            return [];
1731
        }
1732
        $courseId = $courseInfo['real_id'];
1733
1734
        if (empty($courseId)) {
1735
            return [];
1736
        }
1737
1738
        $sessionId = (int) $sessionId;
1739
        $user_id = (int) $user_id;
1740
1741
        $groupList = GroupManager::get_group_list(
1742
            null,
1743
            $courseInfo,
1744
            null,
1745
            $sessionId
1746
        );
1747
1748
        $groupNameList = [];
1749
        if (!empty($groupList)) {
1750
            foreach ($groupList as $group) {
1751
                $groupNameList[$group['iid']] = $group['name'];
1752
            }
1753
        }
1754
1755
        if (api_is_platform_admin() || api_is_allowed_to_edit()) {
1756
            $isAllowToEdit = true;
1757
        } else {
1758
            $isAllowToEdit = CourseManager::is_course_teacher(
1759
                api_get_user_id(),
1760
                $courseInfo['code']
1761
            );
1762
        }
1763
1764
        $isAllowToEditByHrm = false;
1765
        if (!empty($sessionId)) {
1766
            $allowDhrToEdit = api_get_configuration_value('allow_agenda_edit_for_hrm');
1767
            if ($allowDhrToEdit) {
1768
                $isHrm = SessionManager::isUserSubscribedAsHRM($sessionId, api_get_user_id());
1769
                if ($isHrm) {
1770
                    $isAllowToEdit = $isAllowToEditByHrm = true;
1771
                }
1772
            }
1773
        }
1774
1775
        $groupMemberships = [];
1776
        if (!empty($groupId)) {
1777
            $groupMemberships = [$groupId];
1778
        } else {
1779
            if ($isAllowToEdit) {
1780
                if (!empty($groupList)) {
1781
                    // c_item_property.to_group_id field was migrated to use
1782
                    // c_group_info.iid
1783
                    $groupMemberships = array_column($groupList, 'iid');
1784
                }
1785
            } else {
1786
                // get only related groups from user
1787
                $groupMemberships = GroupManager::get_group_ids(
1788
                    $courseId,
1789
                    api_get_user_id()
1790
                );
1791
            }
1792
        }
1793
1794
        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
1795
        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1796
1797
        if (empty($sessionId)) {
1798
            $sessionCondition = "
1799
            (
1800
                agenda.session_id = 0 AND (ip.session_id IS NULL OR ip.session_id = 0)
1801
            ) ";
1802
        } else {
1803
            $sessionCondition = "
1804
            (
1805
                agenda.session_id = $sessionId AND
1806
                ip.session_id = $sessionId
1807
            ) ";
1808
        }
1809
1810
        if ($isAllowToEdit) {
1811
            // No group filter was asked
1812
            if (empty($groupId)) {
1813
                if (empty($user_id)) {
1814
                    // Show all events not added in group
1815
                    $userCondition = ' (ip.to_group_id IS NULL OR ip.to_group_id = 0) ';
1816
                    // admin see only his stuff
1817
                    if ($this->type === 'personal') {
1818
                        $userCondition = " (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0) ) ";
1819
                        $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) ) ";
1820
                    }
1821
1822
                    if (!empty($groupMemberships)) {
1823
                        // Show events sent to selected groups
1824
                        $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1825
                    }
1826
                } else {
1827
                    // Show events of requested user in no group
1828
                    $userCondition = " (ip.to_user_id = $user_id AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
1829
                    // Show events sent to selected groups
1830
                    if (!empty($groupMemberships)) {
1831
                        $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1832
                    }
1833
                }
1834
            } else {
1835
                // Show only selected groups (depending of user status)
1836
                $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1837
1838
                if (!empty($groupMemberships)) {
1839
                    // Show send to $user_id in selected groups
1840
                    $userCondition .= " OR (ip.to_user_id = $user_id) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1841
                }
1842
            }
1843
        } else {
1844
            // No group filter was asked
1845
            if (empty($groupId)) {
1846
                // Show events sent to everyone and no group
1847
                $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) ';
1848
1849
                // Show events sent to selected groups
1850
                if (!empty($groupMemberships)) {
1851
                    $userCondition .= " OR (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships)."))) ";
1852
                } else {
1853
                    $userCondition .= " ) ";
1854
                }
1855
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id()." AND (ip.to_group_id IS NULL OR ip.to_group_id = 0)) ";
1856
            } else {
1857
                if (!empty($groupMemberships)) {
1858
                    // Show send to everyone - and only selected groups
1859
                    $userCondition = " (ip.to_user_id = 0 OR ip.to_user_id is NULL) AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1860
                }
1861
            }
1862
1863
            // Show sent to only me and no group
1864
            if (!empty($groupMemberships)) {
1865
                $userCondition .= " OR (ip.to_user_id = ".api_get_user_id().") AND (ip.to_group_id IN (".implode(", ", $groupMemberships).")) ";
1866
            } else {
1867
                // Show sent to only me and selected groups
1868
            }
1869
        }
1870
1871
        if (api_is_allowed_to_edit()) {
1872
            $visibilityCondition = " (ip.visibility IN ('1', '0'))  ";
1873
        } else {
1874
            $visibilityCondition = " (ip.visibility = '1') ";
1875
        }
1876
1877
        $sql = "SELECT DISTINCT
1878
                    agenda.*,
1879
                    ip.visibility,
1880
                    ip.to_group_id,
1881
                    ip.insert_user_id,
1882
                    ip.ref,
1883
                    to_user_id
1884
                FROM $tlb_course_agenda agenda
1885
                INNER JOIN $tbl_property ip
1886
                ON (
1887
                    agenda.id = ip.ref AND
1888
                    agenda.c_id = ip.c_id AND
1889
                    ip.tool = '".TOOL_CALENDAR_EVENT."'
1890
                )
1891
                WHERE
1892
                    $sessionCondition AND
1893
                    ($userCondition) AND
1894
                    $visibilityCondition AND
1895
                    agenda.c_id = $courseId
1896
        ";
1897
        $dateCondition = '';
1898
        if (!empty($start) && !empty($end)) {
1899
            $dateCondition .= "AND (
1900
                 agenda.start_date BETWEEN '".$start."' AND '".$end."' OR
1901
                 agenda.end_date BETWEEN '".$start."' AND '".$end."' OR
1902
                 (
1903
                     agenda.start_date IS NOT NULL AND agenda.end_date IS NOT NULL AND
1904
                     YEAR(agenda.start_date) = YEAR(agenda.end_date) AND
1905
                     MONTH('$start') BETWEEN MONTH(agenda.start_date) AND MONTH(agenda.end_date)
1906
                 )
1907
            )";
1908
        }
1909
1910
        $sql .= $dateCondition;
1911
        $result = Database::query($sql);
1912
1913
        $coachCanEdit = false;
1914
        if (!empty($sessionId)) {
1915
            $coachCanEdit = api_is_coach($sessionId, $courseId) || api_is_platform_admin();
1916
        }
1917
1918
        if (Database::num_rows($result)) {
1919
            $eventsAdded = array_column($this->events, 'unique_id');
1920
            while ($row = Database::fetch_array($result, 'ASSOC')) {
1921
                $event = [];
1922
                $event['id'] = 'course_'.$row['id'];
1923
                $event['unique_id'] = $row['iid'];
1924
                // To avoid doubles
1925
                if (in_array($event['unique_id'], $eventsAdded)) {
1926
                    continue;
1927
                }
1928
1929
                $eventsAdded[] = $event['unique_id'];
1930
                $eventId = $row['ref'];
1931
                $items = $this->getUsersAndGroupSubscribedToEvent(
1932
                    $eventId,
1933
                    $courseId,
1934
                    $this->sessionId
1935
                );
1936
                $group_to_array = $items['groups'];
1937
                $user_to_array = $items['users'];
1938
                $attachmentList = $this->getAttachmentList(
1939
                    $row['id'],
1940
                    $courseInfo
1941
                );
1942
                $event['attachment'] = '';
1943
                if (!empty($attachmentList)) {
1944
                    foreach ($attachmentList as $attachment) {
1945
                        $has_attachment = Display::return_icon(
1946
                            'attachment.gif',
1947
                            get_lang('Attachment')
1948
                        );
1949
                        $user_filename = $attachment['filename'];
1950
                        $url = api_get_path(WEB_CODE_PATH).'calendar/download.php?file='.$attachment['path'].'&course_id='.$courseId.'&'.api_get_cidreq();
1951
                        $event['attachment'] .= $has_attachment.
1952
                            Display::url(
1953
                                $user_filename,
1954
                                $url
1955
                            ).'<br />';
1956
                    }
1957
                }
1958
1959
                $event['title'] = $row['title'];
1960
                $event['className'] = 'course';
1961
                $event['allDay'] = 'false';
1962
                $event['course_id'] = $courseId;
1963
                $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color;
1964
1965
                $sessionInfo = [];
1966
                if (isset($row['session_id']) && !empty($row['session_id'])) {
1967
                    $sessionInfo = api_get_session_info($sessionId);
1968
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_session_color;
1969
                }
1970
1971
                $event['session_name'] = isset($sessionInfo['name']) ? $sessionInfo['name'] : '';
1972
                $event['course_name'] = isset($courseInfo['title']) ? $courseInfo['title'] : '';
1973
1974
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
1975
                    $event['borderColor'] = $event['backgroundColor'] = $this->event_group_color;
1976
                }
1977
1978
                if (!empty($color)) {
1979
                    $event['borderColor'] = $event['backgroundColor'] = $color;
1980
                }
1981
1982
                if (isset($row['color']) && !empty($row['color'])) {
1983
                    $event['borderColor'] = $event['backgroundColor'] = $row['color'];
1984
                }
1985
1986
                $event['editable'] = false;
1987
                if ($this->getIsAllowedToEdit() && $this->type == 'course') {
1988
                    $event['editable'] = true;
1989
                    if (!empty($sessionId)) {
1990
                        if ($coachCanEdit == false) {
1991
                            $event['editable'] = false;
1992
                        }
1993
                        if ($isAllowToEditByHrm) {
1994
                            $event['editable'] = true;
1995
                        }
1996
                    }
1997
                    // if user is author then he can edit the item
1998
                    if (api_get_user_id() == $row['insert_user_id']) {
1999
                        $event['editable'] = true;
2000
                    }
2001
                }
2002
2003
                if (!empty($row['start_date'])) {
2004
                    $event['start'] = $this->formatEventDate($row['start_date']);
2005
                    $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2006
                }
2007
                if (!empty($row['end_date'])) {
2008
                    $event['end'] = $this->formatEventDate($row['end_date']);
2009
                    $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2010
                }
2011
2012
                $event['sent_to'] = '';
2013
                $event['type'] = 'course';
2014
                if ($row['session_id'] != 0) {
2015
                    $event['type'] = 'session';
2016
                }
2017
2018
                // Event Sent to a group?
2019
                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
2020
                    $sent_to = [];
2021
                    if (!empty($group_to_array)) {
2022
                        foreach ($group_to_array as $group_item) {
2023
                            $sent_to[] = $groupNameList[$group_item];
2024
                        }
2025
                    }
2026
                    $sent_to = implode('@@', $sent_to);
2027
                    $sent_to = str_replace(
2028
                        '@@',
2029
                        '</div><div class="label_tag notice">',
2030
                        $sent_to
2031
                    );
2032
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2033
                    $event['type'] = 'group';
2034
                }
2035
2036
                // Event sent to a user?
2037
                if (isset($row['to_user_id'])) {
2038
                    $sent_to = [];
2039
                    if (!empty($user_to_array)) {
2040
                        foreach ($user_to_array as $item) {
2041
                            $user_info = api_get_user_info($item);
2042
                            // Add username as tooltip for $event['sent_to'] - ref #4226
2043
                            $username = api_htmlentities(
2044
                                sprintf(
2045
                                    get_lang('LoginX'),
2046
                                    $user_info['username']
2047
                                ),
2048
                                ENT_QUOTES
2049
                            );
2050
                            $sent_to[] = "<span title='".$username."'>".$user_info['complete_name']."</span>";
2051
                        }
2052
                    }
2053
                    $sent_to = implode('@@', $sent_to);
2054
                    $sent_to = str_replace(
2055
                        '@@',
2056
                        '</div><div class="label_tag notice">',
2057
                        $sent_to
2058
                    );
2059
                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
2060
                }
2061
2062
                //Event sent to everyone!
2063
                if (empty($event['sent_to'])) {
2064
                    $event['sent_to'] = '<div class="label_tag notice">'.get_lang('Everyone').'</div>';
2065
                }
2066
2067
                $event['description'] = Security::remove_XSS($row['content']);
2068
                $event['visibility'] = $row['visibility'];
2069
                $event['real_id'] = $row['id'];
2070
                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2071
                $event['parent_event_id'] = $row['parent_event_id'];
2072
                $event['has_children'] = $this->hasChildren($row['id'], $courseId) ? 1 : 0;
2073
                $event['comment'] = Security::remove_XSS($row['comment']);
2074
                $this->events[] = $event;
2075
            }
2076
        }
2077
2078
        return $this->events;
2079
    }
2080
2081
    /**
2082
     * @param int $start tms
2083
     * @param int $end   tms
2084
     *
2085
     * @return array
2086
     */
2087
    public function getPlatformEvents($start, $end)
2088
    {
2089
        $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
2090
        $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
2091
        $dateCondition = '';
2092
2093
        if (!empty($start) && !empty($end)) {
2094
            $dateCondition .= "AND (
2095
                 start_date BETWEEN '".$start."' AND '".$end."' OR
2096
                 end_date BETWEEN '".$start."' AND '".$end."' OR
2097
                 (
2098
                     start_date IS NOT NULL AND end_date IS NOT NULL AND
2099
                     YEAR(start_date) = YEAR(end_date) AND
2100
                     MONTH('$start') BETWEEN MONTH(start_date) AND MONTH(end_date)
2101
                 )
2102
            )";
2103
        }
2104
2105
        $access_url_id = api_get_current_access_url_id();
2106
2107
        $sql = "SELECT *
2108
                FROM ".$this->tbl_global_agenda."
2109
                WHERE access_url_id = $access_url_id
2110
                $dateCondition";
2111
        $result = Database::query($sql);
2112
        $my_events = [];
2113
        if (Database::num_rows($result)) {
2114
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2115
                $event = [];
2116
                $event['id'] = 'platform_'.$row['id'];
2117
                $event['title'] = $row['title'];
2118
                $event['className'] = 'platform';
2119
                $event['allDay'] = 'false';
2120
                $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color;
2121
                $event['editable'] = false;
2122
                $event['type'] = 'admin';
2123
2124
                if (api_is_platform_admin() && $this->type === 'admin') {
2125
                    $event['editable'] = true;
2126
                }
2127
2128
                if (!empty($row['start_date'])) {
2129
                    $event['start'] = $this->formatEventDate($row['start_date']);
2130
                    $event['start_date_localtime'] = api_get_local_time($row['start_date']);
2131
                }
2132
2133
                if (!empty($row['end_date'])) {
2134
                    $event['end'] = $this->formatEventDate($row['end_date']);
2135
                    $event['end_date_localtime'] = api_get_local_time($row['end_date']);
2136
                }
2137
                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
2138
                $event['parent_event_id'] = 0;
2139
                $event['has_children'] = 0;
2140
                $event['description'] = $row['content'];
2141
2142
                $my_events[] = $event;
2143
                $this->events[] = $event;
2144
            }
2145
        }
2146
2147
        return $my_events;
2148
    }
2149
2150
    /**
2151
     * @param FormValidator $form
2152
     * @param array         $groupList
2153
     * @param array         $userList
2154
     * @param array         $sendTo               array('users' => [1, 2], 'groups' => [3, 4])
2155
     * @param array         $attributes
2156
     * @param bool          $addOnlyItemsInSendTo
2157
     * @param bool          $required
2158
     */
2159
    public function setSendToSelect(
2160
        $form,
2161
        $groupList = [],
2162
        $userList = [],
2163
        $sendTo = [],
2164
        $attributes = [],
2165
        $addOnlyItemsInSendTo = false,
2166
        $required = false
2167
    ) {
2168
        $params = [
2169
            'id' => 'users_to_send_id',
2170
            'data-placeholder' => get_lang('Select'),
2171
            'multiple' => 'multiple',
2172
            'class' => 'multiple-select',
2173
        ];
2174
2175
        if (!empty($attributes)) {
2176
            $params = array_merge($params, $attributes);
2177
            if (empty($params['multiple'])) {
2178
                unset($params['multiple']);
2179
            }
2180
        }
2181
2182
        $sendToGroups = isset($sendTo['groups']) ? $sendTo['groups'] : [];
2183
        $sendToUsers = isset($sendTo['users']) ? $sendTo['users'] : [];
2184
2185
        /** @var HTML_QuickForm_select $select */
2186
        $select = $form->addSelect(
2187
            'users_to_send',
2188
            get_lang('To'),
2189
            null,
2190
            $params
2191
        );
2192
2193
        if ($required) {
2194
            $form->setRequired($select);
2195
        }
2196
2197
        $selectedEveryoneOptions = [];
2198
        if (isset($sendTo['everyone']) && $sendTo['everyone']) {
2199
            $selectedEveryoneOptions = ['selected'];
2200
            $sendToUsers = [];
2201
        }
2202
2203
        $select->addOption(
2204
            get_lang('Everyone'),
2205
            'everyone',
2206
            $selectedEveryoneOptions
2207
        );
2208
2209
        $options = [];
2210
        if (is_array($groupList)) {
2211
            foreach ($groupList as $group) {
2212
                $count_users = isset($group['count_users']) ? $group['count_users'] : $group['userNb'];
2213
                $count_users = " &ndash; $count_users ".get_lang('Users');
2214
                $option = [
2215
                    'text' => $group['name'].$count_users,
2216
                    'value' => "GROUP:".$group['id'],
2217
                ];
2218
                $selected = in_array(
2219
                    $group['id'],
2220
                    $sendToGroups
2221
                ) ? true : false;
2222
                if ($selected) {
2223
                    $option['selected'] = 'selected';
2224
                }
2225
2226
                if ($addOnlyItemsInSendTo) {
2227
                    if ($selected) {
2228
                        $options[] = $option;
2229
                    }
2230
                } else {
2231
                    $options[] = $option;
2232
                }
2233
            }
2234
            $select->addOptGroup($options, get_lang('Groups'));
2235
        }
2236
2237
        // adding the individual users to the select form
2238
        if (is_array($userList)) {
2239
            $options = [];
2240
            foreach ($userList as $user) {
2241
                if ($user['status'] == ANONYMOUS) {
2242
                    continue;
2243
                }
2244
                $option = [
2245
                    'text' => api_get_person_name(
2246
                            $user['firstname'],
2247
                            $user['lastname']
2248
                        ).' ('.$user['username'].')',
2249
                    'value' => "USER:".$user['user_id'],
2250
                ];
2251
2252
                $selected = in_array(
2253
                    $user['user_id'],
2254
                    $sendToUsers
2255
                ) ? true : false;
2256
2257
                if ($selected) {
2258
                    $option['selected'] = 'selected';
2259
                }
2260
2261
                if ($addOnlyItemsInSendTo) {
2262
                    if ($selected) {
2263
                        $options[] = $option;
2264
                    }
2265
                } else {
2266
                    $options[] = $option;
2267
                }
2268
            }
2269
2270
            $select->addOptGroup($options, get_lang('Users'));
2271
        }
2272
    }
2273
2274
    /**
2275
     * Separates the users and groups array
2276
     * users have a value USER:XXX (with XXX the user id
2277
     * groups have a value GROUP:YYY (with YYY the group id)
2278
     * use the 'everyone' key.
2279
     *
2280
     * @author Julio Montoya based in separate_users_groups in agenda.inc.php
2281
     *
2282
     * @param array $to
2283
     *
2284
     * @return array
2285
     */
2286
    public function parseSendToArray($to)
2287
    {
2288
        $groupList = [];
2289
        $userList = [];
2290
        $sendTo = null;
2291
2292
        $sendTo['everyone'] = false;
2293
        if (is_array($to) && count($to) > 0) {
2294
            foreach ($to as $item) {
2295
                if ($item == 'everyone') {
2296
                    $sendTo['everyone'] = true;
2297
                } else {
2298
                    list($type, $id) = explode(':', $item);
2299
                    switch ($type) {
2300
                        case 'GROUP':
2301
                            $groupList[] = $id;
2302
                            break;
2303
                        case 'USER':
2304
                            $userList[] = $id;
2305
                            break;
2306
                    }
2307
                }
2308
            }
2309
            $sendTo['groups'] = $groupList;
2310
            $sendTo['users'] = $userList;
2311
        }
2312
2313
        return $sendTo;
2314
    }
2315
2316
    /**
2317
     * @param array $params
2318
     *
2319
     * @return FormValidator
2320
     */
2321
    public function getForm($params = [])
2322
    {
2323
        $action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
2324
        $id = isset($params['id']) ? (int) $params['id'] : 0;
2325
2326
        $url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
2327
        if ($this->type == 'course') {
2328
            $url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
2329
        }
2330
2331
        $form = new FormValidator(
2332
            'add_event',
2333
            'post',
2334
            $url,
2335
            null,
2336
            ['enctype' => 'multipart/form-data']
2337
        );
2338
2339
        $idAttach = isset($params['id_attach']) ? (int) $params['id_attach'] : null;
2340
        $groupId = api_get_group_id();
2341
        $form_Title = get_lang('AddCalendarItem');
2342
        if (!empty($id)) {
2343
            $form_Title = get_lang('ModifyCalendarItem');
2344
        }
2345
2346
        $form->addHeader($form_Title);
2347
        $form->addElement('hidden', 'id', $id);
2348
        $form->addElement('hidden', 'action', $action);
2349
        $form->addElement('hidden', 'id_attach', $idAttach);
2350
2351
        $isSubEventEdition = false;
2352
        $isParentFromSerie = false;
2353
        $showAttachmentForm = true;
2354
2355
        if ($this->type == 'course') {
2356
            // Edition mode.
2357
            if (!empty($id)) {
2358
                $showAttachmentForm = false;
2359
                if (isset($params['parent_event_id']) && !empty($params['parent_event_id'])) {
2360
                    $isSubEventEdition = true;
2361
                }
2362
                if (!empty($params['repeat_info'])) {
2363
                    $isParentFromSerie = true;
2364
                }
2365
            }
2366
        }
2367
2368
        if ($isSubEventEdition) {
2369
            $form->addElement(
2370
                'label',
2371
                null,
2372
                Display::return_message(
2373
                    get_lang('EditingThisEventWillRemoveItFromTheSerie'),
2374
                    'warning'
2375
                )
2376
            );
2377
        }
2378
2379
        $form->addElement('text', 'title', get_lang('ItemTitle'));
2380
2381
        if (isset($groupId) && !empty($groupId)) {
2382
            $form->addElement(
2383
                'hidden',
2384
                'users_to_send[]',
2385
                "GROUP:$groupId"
2386
            );
2387
            $form->addElement('hidden', 'to', 'true');
2388
        } else {
2389
            $sendTo = isset($params['send_to']) ? $params['send_to'] : ['everyone' => true];
2390
            if ($this->type == 'course') {
2391
                $this->showToForm($form, $sendTo, [], false, true);
2392
            }
2393
        }
2394
2395
        $form->addDateRangePicker(
2396
            'date_range',
2397
            get_lang('DateRange'),
2398
            false,
2399
            ['id' => 'date_range']
2400
        );
2401
        $form->addElement('checkbox', 'all_day', null, get_lang('AllDay'));
2402
2403
        if ($this->type == 'course') {
2404
            $repeat = $form->addElement(
2405
                'checkbox',
2406
                'repeat',
2407
                null,
2408
                get_lang('RepeatEvent'),
2409
                ['onclick' => 'return plus_repeated_event();']
2410
            );
2411
            $form->addElement(
2412
                'html',
2413
                '<div id="options2" style="display:none">'
2414
            );
2415
            $form->addElement(
2416
                'select',
2417
                'repeat_type',
2418
                get_lang('RepeatType'),
2419
                self::getRepeatTypes()
2420
            );
2421
            $form->addElement(
2422
                'date_picker',
2423
                'repeat_end_day',
2424
                get_lang('RepeatEnd'),
2425
                ['id' => 'repeat_end_date_form']
2426
            );
2427
2428
            if ($isSubEventEdition || $isParentFromSerie) {
2429
                $repeatInfo = $params['repeat_info'];
2430
                if ($isSubEventEdition) {
2431
                    $parentEvent = $params['parent_info'];
2432
                    $repeatInfo = $parentEvent['repeat_info'];
2433
                }
2434
                $params['repeat'] = 1;
2435
                $params['repeat_type'] = $repeatInfo['cal_type'];
2436
                $params['repeat_end_day'] = substr(
2437
                    api_get_local_time($repeatInfo['cal_end']),
2438
                    0,
2439
                    10
2440
                );
2441
2442
                $form->freeze(['repeat_type', 'repeat_end_day']);
2443
                $repeat->_attributes['disabled'] = 'disabled';
2444
            }
2445
            $form->addElement('html', '</div>');
2446
        }
2447
2448
        if (!empty($id)) {
2449
            if (empty($params['end_date'])) {
2450
                $params['date_range'] = $params['end_date'];
2451
            }
2452
2453
            $params['date_range'] =
2454
                substr(api_get_local_time($params['start_date']), 0, 16).' / '.
2455
                substr(api_get_local_time($params['end_date']), 0, 16);
2456
        }
2457
2458
        $toolbar = 'Agenda';
2459
        if (!api_is_allowed_to_edit(null, true)) {
2460
            $toolbar = 'AgendaStudent';
2461
        }
2462
2463
        $form->addElement(
2464
            'html_editor',
2465
            'content',
2466
            get_lang('Description'),
2467
            null,
2468
            [
2469
                'ToolbarSet' => $toolbar,
2470
                'Width' => '100%',
2471
                'Height' => '200',
2472
            ]
2473
        );
2474
2475
        if ($this->type == 'course') {
2476
            $form->addElement('textarea', 'comment', get_lang('Comment'));
2477
            $form->addLabel(
2478
                get_lang('FilesAttachment'),
2479
                '<div id="filepaths" class="file-upload-event">
2480
2481
                        <div id="filepath_1">
2482
                            <input type="file" name="attach_1"/>
2483
2484
                            <label>'.get_lang('Description').'</label>
2485
                            <input class="form-control" type="text" name="legend[]" />
2486
                        </div>
2487
2488
                    </div>'
2489
            );
2490
2491
            $form->addLabel(
2492
                '',
2493
                '<span id="link-more-attach">
2494
                    <a href="javascript://" onclick="return add_image_form()">'.
2495
                get_lang('AddOneMoreFile').'</a>
2496
                 </span>&nbsp;('.sprintf(
2497
                    get_lang('MaximunFileSizeX'),
2498
                    format_file_size(
2499
                        api_get_setting('message_max_upload_filesize')
2500
                    )
2501
                ).')'
2502
            );
2503
2504
            if (isset($params['attachment']) && !empty($params['attachment'])) {
2505
                $attachmentList = $params['attachment'];
2506
                foreach ($attachmentList as $attachment) {
2507
                    $params['file_comment'] = $attachment['comment'];
2508
                    if (!empty($attachment['path'])) {
2509
                        $form->addElement(
2510
                            'checkbox',
2511
                            'delete_attachment['.$attachment['id'].']',
2512
                            null,
2513
                            get_lang(
2514
                                'DeleteAttachment'
2515
                            ).': '.$attachment['filename']
2516
                        );
2517
                    }
2518
                }
2519
            }
2520
2521
            $form->addElement(
2522
                'textarea',
2523
                'file_comment',
2524
                get_lang('FileComment')
2525
            );
2526
        }
2527
2528
        if (empty($id)) {
2529
            $form->addElement(
2530
                'checkbox',
2531
                'add_announcement',
2532
                null,
2533
                get_lang('AddAnnouncement').'&nbsp('.get_lang('SendMail').')'
2534
            );
2535
        }
2536
2537
        if ($id) {
2538
            $form->addButtonUpdate(get_lang('ModifyEvent'));
2539
        } else {
2540
            $form->addButtonSave(get_lang('AgendaAdd'));
2541
        }
2542
2543
        $form->setDefaults($params);
2544
        $form->addRule(
2545
            'date_range',
2546
            get_lang('ThisFieldIsRequired'),
2547
            'required'
2548
        );
2549
        $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
2550
2551
        return $form;
2552
    }
2553
2554
    /**
2555
     * @param FormValidator $form
2556
     * @param array         $sendTo               array('everyone' => false, 'users' => [1, 2], 'groups' => [3, 4])
2557
     * @param array         $attributes
2558
     * @param bool          $addOnlyItemsInSendTo
2559
     * @param bool          $required
2560
     *
2561
     * @return bool
2562
     */
2563
    public function showToForm(
2564
        $form,
2565
        $sendTo = [],
2566
        $attributes = [],
2567
        $addOnlyItemsInSendTo = false,
2568
        $required = false
2569
    ) {
2570
        if ($this->type != 'course') {
2571
            return false;
2572
        }
2573
2574
        $order = 'lastname';
2575
        if (api_is_western_name_order()) {
2576
            $order = 'firstname';
2577
        }
2578
2579
        $userList = CourseManager::get_user_list_from_course_code(
2580
            api_get_course_id(),
2581
            $this->sessionId,
2582
            null,
2583
            $order
2584
        );
2585
2586
        $groupList = CourseManager::get_group_list_of_course(
2587
            api_get_course_id(),
2588
            $this->sessionId
2589
        );
2590
2591
        $this->setSendToSelect(
2592
            $form,
2593
            $groupList,
2594
            $userList,
2595
            $sendTo,
2596
            $attributes,
2597
            $addOnlyItemsInSendTo,
2598
            $required
2599
        );
2600
2601
        return true;
2602
    }
2603
2604
    /**
2605
     * @param int   $id
2606
     * @param int   $visibility 0= invisible, 1 visible
2607
     * @param array $courseInfo
2608
     * @param int   $userId
2609
     */
2610
    public static function changeVisibility(
2611
        $id,
2612
        $visibility,
2613
        $courseInfo,
2614
        $userId = null
2615
    ) {
2616
        $id = intval($id);
2617
        if (empty($userId)) {
2618
            $userId = api_get_user_id();
2619
        } else {
2620
            $userId = intval($userId);
2621
        }
2622
2623
        if ($visibility == 0) {
2624
            api_item_property_update(
2625
                $courseInfo,
2626
                TOOL_CALENDAR_EVENT,
2627
                $id,
2628
                'invisible',
2629
                $userId
2630
            );
2631
        } else {
2632
            api_item_property_update(
2633
                $courseInfo,
2634
                TOOL_CALENDAR_EVENT,
2635
                $id,
2636
                'visible',
2637
                $userId
2638
            );
2639
        }
2640
    }
2641
2642
    /**
2643
     * Get repeat types.
2644
     *
2645
     * @return array
2646
     */
2647
    public static function getRepeatTypes()
2648
    {
2649
        return [
2650
            'daily' => get_lang('RepeatDaily'),
2651
            'weekly' => get_lang('RepeatWeekly'),
2652
            'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
2653
            //monthlyByDay"> get_lang('RepeatMonthlyByDay');
2654
            //monthlyByDayR' => get_lang('RepeatMonthlyByDayR'),
2655
            'yearly' => get_lang('RepeatYearly'),
2656
        ];
2657
    }
2658
2659
    /**
2660
     * Show a list with all the attachments according to the post's id.
2661
     *
2662
     * @param int   $eventId
2663
     * @param array $courseInfo
2664
     *
2665
     * @return array with the post info
2666
     */
2667
    public function getAttachmentList($eventId, $courseInfo)
2668
    {
2669
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
2670
        $courseId = (int) $courseInfo['real_id'];
2671
        $eventId = (int) $eventId;
2672
2673
        $sql = "SELECT id, path, filename, comment
2674
                FROM $tableAttachment
2675
                WHERE
2676
                    c_id = $courseId AND
2677
                    agenda_id = $eventId";
2678
        $result = Database::query($sql);
2679
        $list = [];
2680
        if (Database::num_rows($result) != 0) {
2681
            $list = Database::store_result($result, 'ASSOC');
2682
        }
2683
2684
        return $list;
2685
    }
2686
2687
    /**
2688
     * Show a list with all the attachments according to the post's id.
2689
     *
2690
     * @param int   $attachmentId
2691
     * @param int   $eventId
2692
     * @param array $courseInfo
2693
     *
2694
     * @return array with the post info
2695
     */
2696
    public function getAttachment($attachmentId, $eventId, $courseInfo)
2697
    {
2698
        if (empty($courseInfo) || empty($attachmentId) || empty($eventId)) {
2699
            return [];
2700
        }
2701
2702
        $tableAttachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
2703
        $courseId = (int) $courseInfo['real_id'];
2704
        $eventId = (int) $eventId;
2705
        $attachmentId = (int) $attachmentId;
2706
2707
        $row = [];
2708
        $sql = "SELECT id, path, filename, comment
2709
                FROM $tableAttachment
2710
                WHERE
2711
                    c_id = $courseId AND
2712
                    agenda_id = $eventId AND
2713
                    id = $attachmentId
2714
                ";
2715
        $result = Database::query($sql);
2716
        if (Database::num_rows($result) != 0) {
2717
            $row = Database::fetch_array($result, 'ASSOC');
2718
        }
2719
2720
        return $row;
2721
    }
2722
2723
    /**
2724
     * Add an attachment file into agenda.
2725
     *
2726
     * @param int    $eventId
2727
     * @param array  $fileUserUpload ($_FILES['user_upload'])
2728
     * @param string $comment        about file
2729
     * @param array  $courseInfo
2730
     *
2731
     * @return string
2732
     */
2733
    public function addAttachment(
2734
        $eventId,
2735
        $fileUserUpload,
2736
        $comment,
2737
        $courseInfo
2738
    ) {
2739
        $agenda_table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
2740
        $eventId = (int) $eventId;
2741
2742
        // Storing the attachments
2743
        $upload_ok = false;
2744
        if (!empty($fileUserUpload['name'])) {
2745
            $upload_ok = process_uploaded_file($fileUserUpload);
2746
        }
2747
2748
        if (!empty($upload_ok)) {
2749
            $courseDir = $courseInfo['directory'].'/upload/calendar';
2750
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
2751
            $uploadDir = $sys_course_path.$courseDir;
2752
2753
            // Try to add an extension to the file if it hasn't one
2754
            $new_file_name = add_ext_on_mime(
2755
                stripslashes($fileUserUpload['name']),
2756
                $fileUserUpload['type']
2757
            );
2758
2759
            // user's file name
2760
            $file_name = $fileUserUpload['name'];
2761
2762
            if (!filter_extension($new_file_name)) {
2763
                return Display::return_message(
2764
                    get_lang('UplUnableToSaveFileFilteredExtension'),
2765
                    'error'
2766
                );
2767
            } else {
2768
                $new_file_name = uniqid('');
2769
                $new_path = $uploadDir.'/'.$new_file_name;
2770
                $result = @move_uploaded_file(
2771
                    $fileUserUpload['tmp_name'],
2772
                    $new_path
2773
                );
2774
                $courseId = api_get_course_int_id();
2775
                $size = intval($fileUserUpload['size']);
2776
                // Storing the attachments if any
2777
                if ($result) {
2778
                    $params = [
2779
                        'c_id' => $courseId,
2780
                        'filename' => $file_name,
2781
                        'comment' => $comment,
2782
                        'path' => $new_file_name,
2783
                        'agenda_id' => $eventId,
2784
                        'size' => $size,
2785
                    ];
2786
                    $id = Database::insert($agenda_table_attachment, $params);
2787
                    if ($id) {
2788
                        $sql = "UPDATE $agenda_table_attachment
2789
                                SET id = iid WHERE iid = $id";
2790
                        Database::query($sql);
2791
2792
                        api_item_property_update(
2793
                            $courseInfo,
2794
                            'calendar_event_attachment',
2795
                            $id,
2796
                            'AgendaAttachmentAdded',
2797
                            api_get_user_id()
2798
                        );
2799
                    }
2800
                }
2801
            }
2802
        }
2803
    }
2804
2805
    /**
2806
     * @param int    $attachmentId
2807
     * @param int    $eventId
2808
     * @param array  $fileUserUpload
2809
     * @param string $comment
2810
     * @param array  $courseInfo
2811
     */
2812
    public function updateAttachment(
2813
        $attachmentId,
2814
        $eventId,
2815
        $fileUserUpload,
2816
        $comment,
2817
        $courseInfo
2818
    ) {
2819
        $attachment = $this->getAttachment(
2820
            $attachmentId,
2821
            $eventId,
2822
            $courseInfo
2823
        );
2824
        if (!empty($attachment)) {
2825
            $this->deleteAttachmentFile($attachmentId, $courseInfo);
2826
        }
2827
        $this->addAttachment($eventId, $fileUserUpload, $comment, $courseInfo);
2828
    }
2829
2830
    /**
2831
     * This function delete a attachment file by id.
2832
     *
2833
     * @param int   $attachmentId
2834
     * @param array $courseInfo
2835
     *
2836
     * @return string
2837
     */
2838
    public function deleteAttachmentFile($attachmentId, $courseInfo)
2839
    {
2840
        $table = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
2841
        $attachmentId = (int) $attachmentId;
2842
        $courseId = $courseInfo['real_id'];
2843
2844
        if (empty($courseId) || empty($attachmentId)) {
2845
            return false;
2846
        }
2847
2848
        $sql = "DELETE FROM $table
2849
                WHERE c_id = $courseId AND id = ".$attachmentId;
2850
        $result = Database::query($sql);
2851
2852
        // update item_property
2853
        api_item_property_update(
2854
            $courseInfo,
2855
            'calendar_event_attachment',
2856
            $attachmentId,
2857
            'AgendaAttachmentDeleted',
2858
            api_get_user_id()
2859
        );
2860
2861
        if (!empty($result)) {
2862
            return Display::return_message(
2863
                get_lang("AttachmentFileDeleteSuccess"),
2864
                'confirmation'
2865
            );
2866
        }
2867
    }
2868
2869
    /**
2870
     * @param int $eventId
2871
     *
2872
     * @return array
2873
     */
2874
    public function getAllRepeatEvents($eventId)
2875
    {
2876
        $events = [];
2877
        $eventId = (int) $eventId;
2878
2879
        switch ($this->type) {
2880
            case 'personal':
2881
                break;
2882
            case 'course':
2883
                if (!empty($this->course['real_id'])) {
2884
                    $sql = "SELECT * FROM ".$this->tbl_course_agenda."
2885
                            WHERE
2886
                                c_id = ".$this->course['real_id']." AND
2887
                                parent_event_id = ".$eventId;
2888
                    $result = Database::query($sql);
2889
                    if (Database::num_rows($result)) {
2890
                        while ($row = Database::fetch_array($result, 'ASSOC')) {
2891
                            $events[] = $row;
2892
                        }
2893
                    }
2894
                }
2895
                break;
2896
        }
2897
2898
        return $events;
2899
    }
2900
2901
    /**
2902
     * @param int $eventId
2903
     * @param int $courseId
2904
     *
2905
     * @return bool
2906
     */
2907
    public function hasChildren($eventId, $courseId)
2908
    {
2909
        $eventId = (int) $eventId;
2910
        $courseId = (int) $courseId;
2911
2912
        $sql = "SELECT count(DISTINCT(id)) as count
2913
                FROM ".$this->tbl_course_agenda."
2914
                WHERE
2915
                    c_id = $courseId AND
2916
                    parent_event_id = $eventId";
2917
        $result = Database::query($sql);
2918
        if (Database::num_rows($result)) {
2919
            $row = Database::fetch_array($result, 'ASSOC');
2920
2921
            return $row['count'] > 0;
2922
        }
2923
2924
        return false;
2925
    }
2926
2927
    /**
2928
     * @param int    $filter
2929
     * @param string $view
2930
     *
2931
     * @return string
2932
     */
2933
    public function displayActions($view, $filter = 0)
2934
    {
2935
        $groupInfo = GroupManager::get_group_properties(api_get_group_id());
2936
        $groupIid = isset($groupInfo['iid']) ? $groupInfo['iid'] : 0;
2937
2938
        $codePath = api_get_path(WEB_CODE_PATH);
2939
2940
        $currentUserId = api_get_user_id();
2941
        $cidReq = api_get_cidreq();
2942
2943
        $actionsLeft = '';
2944
        $actionsLeft .= Display::url(
2945
            Display::return_icon('calendar.png', get_lang('Calendar'), [], ICON_SIZE_MEDIUM),
2946
            $codePath."calendar/agenda_js.php?type={$this->type}&$cidReq"
2947
        );
2948
        $actionsLeft .= Display::url(
2949
            Display::return_icon('week.png', get_lang('AgendaList'), [], ICON_SIZE_MEDIUM),
2950
            $codePath."calendar/agenda_list.php?type={$this->type}&$cidReq"
2951
        );
2952
2953
        $form = '';
2954
        if (api_is_allowed_to_edit(false, true) ||
2955
            ('personal' === $this->type && !api_is_anonymous() && 'true' === api_get_setting('allow_personal_agenda')) ||
2956
            (
2957
                '1' === api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous() &&
2958
                api_is_allowed_to_session_edit(false, true))
2959
            || (
2960
                GroupManager::user_has_access($currentUserId, $groupIid, GroupManager::GROUP_TOOL_CALENDAR)
2961
                && GroupManager::is_tutor_of_group($currentUserId, $groupInfo)
2962
            )
2963
        ) {
2964
            $actionsLeft .= Display::url(
2965
                Display::return_icon('new_event.png', get_lang('AgendaAdd'), [], ICON_SIZE_MEDIUM),
2966
                $codePath."calendar/agenda.php?action=add&type={$this->type}&$cidReq"
2967
            );
2968
2969
            $actionsLeft .= Display::url(
2970
                Display::return_icon('import_calendar.png', get_lang('ICalFileImport'), [], ICON_SIZE_MEDIUM),
2971
                $codePath."calendar/agenda.php?action=importical&type={$this->type}&$cidReq"
2972
            );
2973
2974
            if ($this->type === 'course') {
2975
                if (!isset($_GET['action'])) {
2976
                    $form = new FormValidator(
2977
                        'form-search',
2978
                        'post',
2979
                        '',
2980
                        '',
2981
                        [],
2982
                        FormValidator::LAYOUT_INLINE
2983
                    );
2984
                    $attributes = [
2985
                        'multiple' => false,
2986
                        'id' => 'select_form_id_search',
2987
                    ];
2988
                    $selectedValues = $this->parseAgendaFilter($filter);
2989
                    $this->showToForm($form, $selectedValues, $attributes);
2990
                    $form = $form->returnForm();
2991
                }
2992
            }
2993
        }
2994
2995
        if ($this->type === 'personal' && !api_is_anonymous()) {
2996
            $actionsLeft .= Display::url(
2997
                Display::return_icon('1day.png', get_lang('SessionsPlanCalendar'), [], ICON_SIZE_MEDIUM),
2998
                $codePath.'calendar/planification.php'
2999
            );
3000
3001
            if (api_is_student_boss() || api_is_platform_admin()) {
3002
                $actionsLeft .= Display::url(
3003
                    Display::return_icon('calendar-user.png', get_lang('MyStudentsSchedule'), [], ICON_SIZE_MEDIUM),
3004
                    $codePath.'mySpace/calendar_plan.php'
3005
                );
3006
            }
3007
        }
3008
3009
        if (api_is_platform_admin() ||
3010
            api_is_teacher() ||
3011
            api_is_student_boss() ||
3012
            api_is_drh() ||
3013
            api_is_session_admin() ||
3014
            api_is_coach()
3015
        ) {
3016
            if ($this->type == 'personal') {
3017
                $form = null;
3018
                if (!isset($_GET['action'])) {
3019
                    $form = new FormValidator(
3020
                        'form-search',
3021
                        'get',
3022
                        api_get_self().'?type=personal&',
3023
                        '',
3024
                        [],
3025
                        FormValidator::LAYOUT_INLINE
3026
                    );
3027
3028
                    $sessions = [];
3029
3030
                    if (api_is_drh()) {
3031
                        $sessionList = SessionManager::get_sessions_followed_by_drh($currentUserId);
3032
                        if (!empty($sessionList)) {
3033
                            foreach ($sessionList as $sessionItem) {
3034
                                $sessions[$sessionItem['id']] = strip_tags($sessionItem['name']);
3035
                            }
3036
                        }
3037
                    } else {
3038
                        $sessions = SessionManager::get_sessions_by_user($currentUserId);
3039
                        $sessions = array_column($sessions, 'session_name', 'session_id');
3040
                    }
3041
3042
                    $form->addHidden('type', 'personal');
3043
                    $sessions = ['0' => get_lang('SelectAnOption')] + $sessions;
3044
3045
                    $form->addSelect(
3046
                        'session_id',
3047
                        get_lang('Session'),
3048
                        $sessions,
3049
                        ['id' => 'session_id', 'onchange' => 'submit();']
3050
                    );
3051
3052
                    $form->addButtonReset(get_lang('Reset'));
3053
                    $form = $form->returnForm();
3054
                }
3055
            }
3056
        }
3057
3058
        $actionsRight = '';
3059
        if ($view == 'calendar') {
3060
            $actionsRight .= $form;
3061
        }
3062
3063
        $toolbar = Display::toolbarAction(
3064
            'toolbar-agenda',
3065
            [$actionsLeft, $actionsRight]
3066
        );
3067
3068
        return $toolbar;
3069
    }
3070
3071
    /**
3072
     * @return FormValidator
3073
     */
3074
    public function getImportCalendarForm()
3075
    {
3076
        $form = new FormValidator(
3077
            'frm_import_ical',
3078
            'post',
3079
            api_get_self().'?action=importical&type='.$this->type,
3080
            ['enctype' => 'multipart/form-data']
3081
        );
3082
        $form->addHeader(get_lang('ICalFileImport'));
3083
        $form->addElement('file', 'ical_import', get_lang('ICalFileImport'));
3084
        $form->addRule(
3085
            'ical_import',
3086
            get_lang('ThisFieldIsRequired'),
3087
            'required'
3088
        );
3089
        $form->addButtonImport(get_lang('Import'), 'ical_submit');
3090
3091
        return $form;
3092
    }
3093
3094
    /**
3095
     * @param array $courseInfo
3096
     * @param $file
3097
     *
3098
     * @return false|string
3099
     */
3100
    public function importEventFile($courseInfo, $file)
3101
    {
3102
        $charset = api_get_system_encoding();
3103
        $filepath = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
3104
        $messages = [];
3105
3106
        if (!@move_uploaded_file($file['tmp_name'], $filepath)) {
3107
            error_log(
3108
                'Problem moving uploaded file: '.$file['error'].' in '.__FILE__.' line '.__LINE__
3109
            );
3110
3111
            return false;
3112
        }
3113
3114
        $data = file_get_contents($filepath);
3115
3116
        $trans = [
3117
            'DAILY' => 'daily',
3118
            'WEEKLY' => 'weekly',
3119
            'MONTHLY' => 'monthlyByDate',
3120
            'YEARLY' => 'yearly',
3121
        ];
3122
        $sentTo = ['everyone' => true];
3123
        $calendar = Sabre\VObject\Reader::read($data);
3124
        $currentTimeZone = api_get_timezone();
3125
        if (!empty($calendar->VEVENT)) {
3126
            /** @var Sabre\VObject\Component\VEvent $event */
3127
            foreach ($calendar->VEVENT as $event) {
3128
                $tempDate = $event->DTSTART->getValue();
3129
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3130
                    $event->DTSTART->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3131
                }
3132
                $tempDate = $event->DTEND->getValue();
3133
                if ('Z' == substr($tempDate, -1) && 'UTC' != date('e', strtotime($tempDate))) {
3134
                    $event->DTEND->setValue(gmdate('Ymd\THis\Z', strtotime($tempDate)));
3135
                }
3136
                $start = $event->DTSTART->getDateTime();
3137
                $end = $event->DTEND->getDateTime();
3138
                //Sabre\VObject\DateTimeParser::parseDateTime(string $dt, \Sabre\VObject\DateTimeZone $tz)
3139
3140
                $startDateTime = api_get_local_time(
3141
                    $start->format('Y-m-d H:i:s'),
3142
                    $currentTimeZone,
3143
                    $start->format('e')
3144
                );
3145
                $endDateTime = api_get_local_time(
3146
                    $end->format('Y-m-d H:i'),
3147
                    $currentTimeZone,
3148
                    $end->format('e')
3149
                );
3150
                $title = api_convert_encoding(
3151
                    (string) $event->summary,
3152
                    $charset,
3153
                    'UTF-8'
3154
                );
3155
                $description = api_convert_encoding(
3156
                    (string) $event->description,
3157
                    $charset,
3158
                    'UTF-8'
3159
                );
3160
3161
                $id = $this->addEvent(
3162
                    $startDateTime,
3163
                    $endDateTime,
3164
                    'false',
3165
                    $title,
3166
                    $description,
3167
                    $sentTo
3168
                );
3169
3170
                $messages[] = " $title - ".$startDateTime." - ".$endDateTime;
3171
3172
                //$attendee = (string)$event->attendee;
3173
                /** @var Sabre\VObject\Property\ICalendar\Recur $repeat */
3174
                $repeat = $event->RRULE;
3175
                if ($id && !empty($repeat)) {
3176
                    $repeat = $repeat->getParts();
3177
                    $freq = $trans[$repeat['FREQ']];
3178
3179
                    if (isset($repeat['UNTIL']) && !empty($repeat['UNTIL'])) {
3180
                        // Check if datetime or just date (strlen == 8)
3181
                        if (strlen($repeat['UNTIL']) == 8) {
3182
                            // Fix the datetime format to avoid exception in the next step
3183
                            $repeat['UNTIL'] .= 'T000000';
3184
                        }
3185
                        $until = Sabre\VObject\DateTimeParser::parseDateTime(
3186
                            $repeat['UNTIL'],
3187
                            new DateTimeZone($currentTimeZone)
3188
                        );
3189
                        $until = $until->format('Y-m-d H:i:s');
3190
                        $this->addRepeatedItem(
3191
                            $id,
3192
                            $freq,
3193
                            $until,
3194
                            $sentTo
3195
                        );
3196
                    }
3197
3198
                    if (!empty($repeat['COUNT'])) {
3199
                        /*$count = $repeat['COUNT'];
3200
                        $interval = $repeat['INTERVAL'];
3201
                        $endDate = null;
3202
                        switch($freq) {
3203
                            case 'daily':
3204
                                $start = api_strtotime($startDateTime);
3205
                                $date = new DateTime($startDateTime);
3206
                                $days = $count * $interval;
3207
                                var_dump($days);
3208
                                $date->add(new DateInterval("P".$days."D"));
3209
                                $endDate = $date->format('Y-m-d H:i');
3210
                                //$endDate = $count *
3211
                                for ($i = 0; $i < $count; $i++) {
3212
                                    $days = 86400 * 7
3213
                                }
3214
                            }
3215
                        }*/
3216
                        //$res = agenda_add_repeat_item($courseInfo, $id, $freq, $count, $attendee);
3217
                        /*$this->addRepeatedItem(
3218
                            $id,
3219
                            $freq,
3220
                            $endDate,
3221
                            $sentTo
3222
                        );*/
3223
                    }
3224
                }
3225
            }
3226
        }
3227
3228
        if (!empty($messages)) {
3229
            $messages = implode('<br /> ', $messages);
3230
        } else {
3231
            $messages = get_lang('NoAgendaItems');
3232
        }
3233
3234
        return $messages;
3235
    }
3236
3237
    /**
3238
     * Parse filter turns USER:12 to ['users' => [12])] or G:1 ['groups' => [1]].
3239
     *
3240
     * @param int $filter
3241
     *
3242
     * @return array
3243
     */
3244
    public function parseAgendaFilter($filter)
3245
    {
3246
        $everyone = false;
3247
        $groupId = null;
3248
        $userId = null;
3249
3250
        if ($filter == 'everyone') {
3251
            $everyone = true;
3252
        } else {
3253
            if (substr($filter, 0, 1) == 'G') {
3254
                $groupId = str_replace('GROUP:', '', $filter);
3255
            } else {
3256
                $userId = str_replace('USER:', '', $filter);
3257
            }
3258
        }
3259
        if (empty($userId) && empty($groupId)) {
3260
            $everyone = true;
3261
        }
3262
3263
        return [
3264
            'everyone' => $everyone,
3265
            'users' => [$userId],
3266
            'groups' => [$groupId],
3267
        ];
3268
    }
3269
3270
    /**
3271
     *    This function retrieves all the agenda items of all the courses the user is subscribed to.
3272
     */
3273
    public static function get_myagendaitems(
3274
        $user_id,
3275
        $courses_dbs,
3276
        $month,
3277
        $year
3278
    ) {
3279
        $user_id = intval($user_id);
3280
3281
        $items = [];
3282
        $my_list = [];
3283
3284
        // get agenda-items for every course
3285
        foreach ($courses_dbs as $key => $array_course_info) {
3286
            //databases of the courses
3287
            $TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
3288
            $TABLE_ITEMPROPERTY = Database::get_course_table(
3289
                TABLE_ITEM_PROPERTY
3290
            );
3291
3292
            $group_memberships = GroupManager::get_group_ids(
3293
                $array_course_info['real_id'],
3294
                $user_id
3295
            );
3296
            $course_user_status = CourseManager::getUserInCourseStatus(
3297
                $user_id,
3298
                $array_course_info['real_id']
3299
            );
3300
            // if the user is administrator of that course we show all the agenda items
3301
            if ($course_user_status == '1') {
3302
                //echo "course admin";
3303
                $sqlquery = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
3304
							FROM ".$TABLEAGENDA." agenda,
3305
								 ".$TABLE_ITEMPROPERTY." ip
3306
							WHERE agenda.id = ip.ref
3307
							AND MONTH(agenda.start_date)='".$month."'
3308
							AND YEAR(agenda.start_date)='".$year."'
3309
							AND ip.tool='".TOOL_CALENDAR_EVENT."'
3310
							AND ip.visibility='1'
3311
							GROUP BY agenda.id
3312
							ORDER BY start_date ";
3313
            } else {
3314
                // if the user is not an administrator of that course
3315
                if (is_array($group_memberships) && count(
3316
                        $group_memberships
3317
                    ) > 0
3318
                ) {
3319
                    $sqlquery = "SELECT	agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
3320
								FROM ".$TABLEAGENDA." agenda,
3321
									".$TABLE_ITEMPROPERTY." ip
3322
								WHERE agenda.id = ip.ref
3323
								AND MONTH(agenda.start_date)='".$month."'
3324
								AND YEAR(agenda.start_date)='".$year."'
3325
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
3326
								AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
3327
                            ", ",
3328
                            $group_memberships
3329
                        ).")) )
3330
								AND ip.visibility='1'
3331
								ORDER BY start_date ";
3332
                } else {
3333
                    $sqlquery = "SELECT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref
3334
								FROM ".$TABLEAGENDA." agenda,
3335
									".$TABLE_ITEMPROPERTY." ip
3336
								WHERE agenda.id = ip.ref
3337
								AND MONTH(agenda.start_date)='".$month."'
3338
								AND YEAR(agenda.start_date)='".$year."'
3339
								AND ip.tool='".TOOL_CALENDAR_EVENT."'
3340
								AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL)
3341
								AND ip.visibility='1'
3342
								ORDER BY start_date ";
3343
                }
3344
            }
3345
            $result = Database::query($sqlquery);
3346
3347
            while ($item = Database::fetch_array($result, 'ASSOC')) {
3348
                $agendaday = -1;
3349
                if (!empty($item['start_date'])) {
3350
                    $item['start_date'] = api_get_local_time(
3351
                        $item['start_date']
3352
                    );
3353
                    $item['start_date_tms'] = api_strtotime(
3354
                        $item['start_date']
3355
                    );
3356
                    $agendaday = date("j", $item['start_date_tms']);
3357
                }
3358
                if (!empty($item['end_date'])) {
3359
                    $item['end_date'] = api_get_local_time($item['end_date']);
3360
                }
3361
3362
                $url = api_get_path(
3363
                        WEB_CODE_PATH
3364
                    )."calendar/agenda.php?cidReq=".urlencode(
3365
                        $array_course_info["code"]
3366
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
3367
3368
                $item['url'] = $url;
3369
                $item['course_name'] = $array_course_info['title'];
3370
                $item['calendar_type'] = 'course';
3371
                $item['course_id'] = $array_course_info['course_id'];
3372
3373
                $my_list[$agendaday][] = $item;
3374
            }
3375
        }
3376
3377
        // sorting by hour for every day
3378
        $agendaitems = [];
3379
        foreach ($items as $agendaday => $tmpitems) {
3380
            if (!isset($agendaitems[$agendaday])) {
3381
                $agendaitems[$agendaday] = '';
3382
            }
3383
            sort($tmpitems);
3384
            foreach ($tmpitems as $val) {
3385
                $agendaitems[$agendaday] .= $val;
3386
            }
3387
        }
3388
3389
        return $my_list;
3390
    }
3391
3392
    /**
3393
     * This function retrieves one personal agenda item returns it.
3394
     *
3395
     * @param    array    The array containing existing events. We add to this array.
3396
     * @param    int        Day
3397
     * @param    int        Month
3398
     * @param    int        Year (4 digits)
3399
     * @param    int        Week number
3400
     * @param    string    Type of view (month_view, week_view, day_view)
3401
     *
3402
     * @return array The results of the database query, or null if not found
3403
     */
3404
    public static function get_global_agenda_items(
3405
        $agendaitems,
3406
        $day,
3407
        $month,
3408
        $year,
3409
        $week,
3410
        $type
3411
    ) {
3412
        $tbl_global_agenda = Database::get_main_table(
3413
            TABLE_MAIN_SYSTEM_CALENDAR
3414
        );
3415
        $month = intval($month);
3416
        $year = intval($year);
3417
        $week = intval($week);
3418
        $day = intval($day);
3419
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
3420
3421
        $current_access_url_id = api_get_current_access_url_id();
3422
3423
        if ($type == "month_view" || $type == "") {
3424
            // We are in month view
3425
            $sql = "SELECT * FROM ".$tbl_global_agenda."
3426
                    WHERE
3427
                        MONTH(start_date) = ".$month." AND
3428
                        YEAR(start_date) = ".$year."  AND
3429
                        access_url_id = $current_access_url_id
3430
                    ORDER BY start_date ASC";
3431
        }
3432
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
3433
        if ($type == "week_view") { // we are in week view
3434
            $start_end_day_of_week = self::calculate_start_end_of_week(
3435
                $week,
3436
                $year
3437
            );
3438
            $start_day = $start_end_day_of_week['start']['day'];
3439
            $start_month = $start_end_day_of_week['start']['month'];
3440
            $start_year = $start_end_day_of_week['start']['year'];
3441
            $end_day = $start_end_day_of_week['end']['day'];
3442
            $end_month = $start_end_day_of_week['end']['month'];
3443
            $end_year = $start_end_day_of_week['end']['year'];
3444
            // in sql statements you have to use year-month-day for date calculations
3445
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
3446
            $start_filter = api_get_utc_datetime($start_filter);
3447
3448
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
3449
            $end_filter = api_get_utc_datetime($end_filter);
3450
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."' AND  access_url_id = $current_access_url_id ";
3451
        }
3452
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
3453
        if ($type == "day_view") { // we are in day view
3454
            // we could use mysql date() function but this is only available from 4.1 and higher
3455
            $start_filter = $year."-".$month."-".$day." 00:00:00";
3456
            $start_filter = api_get_utc_datetime($start_filter);
3457
3458
            $end_filter = $year."-".$month."-".$day." 23:59:59";
3459
            $end_filter = api_get_utc_datetime($end_filter);
3460
            $sql = " SELECT * FROM ".$tbl_global_agenda." WHERE start_date>='".$start_filter."' AND start_date<='".$end_filter."'  AND  access_url_id = $current_access_url_id";
3461
        }
3462
3463
        $result = Database::query($sql);
3464
3465
        while ($item = Database::fetch_array($result)) {
3466
            if (!empty($item['start_date'])) {
3467
                $item['start_date'] = api_get_local_time($item['start_date']);
3468
                $item['start_date_tms'] = api_strtotime($item['start_date']);
3469
            }
3470
            if (!empty($item['end_date'])) {
3471
                $item['end_date'] = api_get_local_time($item['end_date']);
3472
            }
3473
3474
            // we break the date field in the database into a date and a time part
3475
            $agenda_db_date = explode(" ", $item['start_date']);
3476
            $date = $agenda_db_date[0];
3477
            $time = $agenda_db_date[1];
3478
            // we divide the date part into a day, a month and a year
3479
            $agendadate = explode("-", $date);
3480
            $year = intval($agendadate[0]);
3481
            $month = intval($agendadate[1]);
3482
            $day = intval($agendadate[2]);
3483
            // we divide the time part into hour, minutes, seconds
3484
            $agendatime = explode(":", $time);
3485
            $hour = $agendatime[0];
3486
            $minute = $agendatime[1];
3487
            $second = $agendatime[2];
3488
3489
            if ($type == 'month_view') {
3490
                $item['calendar_type'] = 'global';
3491
                $agendaitems[$day][] = $item;
3492
                continue;
3493
            }
3494
3495
            $start_time = api_format_date(
3496
                $item['start_date'],
3497
                TIME_NO_SEC_FORMAT
3498
            );
3499
            $end_time = '';
3500
            if (!empty($item['end_date'])) {
3501
                $end_time = ' - '.api_format_date(
3502
                        $item['end_date'],
3503
                        DATE_TIME_FORMAT_LONG
3504
                    );
3505
            }
3506
3507
            // if the student has specified a course we a add a link to that course
3508
            if ($item['course'] != "") {
3509
                $url = api_get_path(
3510
                        WEB_CODE_PATH
3511
                    )."admin/agenda.php?cidReq=".urlencode(
3512
                        $item['course']
3513
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
3514
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
3515
            } else {
3516
                $course_link = "";
3517
            }
3518
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
3519
            // if we have a day_view we use a half hour as index => key 33 = 16h30
3520
            if ($type !== "day_view") {
3521
                // This is the array construction for the WEEK or MONTH view
3522
                //Display the Agenda global in the tab agenda (administrator)
3523
                $agendaitems[$day] .= "<i>$start_time $end_time</i>&nbsp;-&nbsp;";
3524
                $agendaitems[$day] .= "<b>".get_lang('GlobalEvent')."</b>";
3525
                $agendaitems[$day] .= "<div>".$item['title']."</div><br>";
3526
            } else {
3527
                // this is the array construction for the DAY view
3528
                $halfhour = 2 * $agendatime['0'];
3529
                if ($agendatime['1'] >= '30') {
3530
                    $halfhour = $halfhour + 1;
3531
                }
3532
                if (!is_array($agendaitems[$halfhour])) {
3533
                    $content = $agendaitems[$halfhour];
3534
                }
3535
                $agendaitems[$halfhour] = $content."<div><i>$hour:$minute</i> <b>".get_lang(
3536
                        'GlobalEvent'
3537
                    ).":  </b>".$item['title']."</div>";
3538
            }
3539
        }
3540
3541
        return $agendaitems;
3542
    }
3543
3544
    /**
3545
     * This function retrieves all the personal agenda items and add them to the agenda items found by the other
3546
     * functions.
3547
     */
3548
    public static function get_personal_agenda_items(
3549
        $user_id,
3550
        $agendaitems,
3551
        $day,
3552
        $month,
3553
        $year,
3554
        $week,
3555
        $type
3556
    ) {
3557
        $tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
3558
        $user_id = intval($user_id);
3559
3560
        // 1. creating the SQL statement for getting the personal agenda items in MONTH view
3561
        if ($type === "month_view" || $type === "") {
3562
            // we are in month view
3563
            $sql = "SELECT * FROM $tbl_personal_agenda
3564
                    WHERE
3565
                        user='".$user_id."' AND
3566
                        MONTH(date)='".$month."' AND
3567
                        YEAR(date) = '".$year."'
3568
                     ORDER BY date ASC";
3569
        }
3570
3571
        // 2. creating the SQL statement for getting the personal agenda items in WEEK view
3572
        // we are in week view
3573
        if ($type == "week_view") {
3574
            $start_end_day_of_week = self::calculate_start_end_of_week(
3575
                $week,
3576
                $year
3577
            );
3578
            $start_day = $start_end_day_of_week['start']['day'];
3579
            $start_month = $start_end_day_of_week['start']['month'];
3580
            $start_year = $start_end_day_of_week['start']['year'];
3581
            $end_day = $start_end_day_of_week['end']['day'];
3582
            $end_month = $start_end_day_of_week['end']['month'];
3583
            $end_year = $start_end_day_of_week['end']['year'];
3584
            // in sql statements you have to use year-month-day for date calculations
3585
            $start_filter = $start_year."-".$start_month."-".$start_day." 00:00:00";
3586
            $start_filter = api_get_utc_datetime($start_filter);
3587
            $end_filter = $end_year."-".$end_month."-".$end_day." 23:59:59";
3588
            $end_filter = api_get_utc_datetime($end_filter);
3589
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
3590
        }
3591
        // 3. creating the SQL statement for getting the personal agenda items in DAY view
3592
        if ($type == "day_view") {
3593
            // we are in day view
3594
            // we could use mysql date() function but this is only available from 4.1 and higher
3595
            $start_filter = $year."-".$month."-".$day." 00:00:00";
3596
            $start_filter = api_get_utc_datetime($start_filter);
3597
            $end_filter = $year."-".$month."-".$day." 23:59:59";
3598
            $end_filter = api_get_utc_datetime($end_filter);
3599
            $sql = " SELECT * FROM ".$tbl_personal_agenda." WHERE user='".$user_id."' AND date>='".$start_filter."' AND date<='".$end_filter."'";
3600
        }
3601
3602
        $result = Database::query($sql);
3603
        while ($item = Database::fetch_array($result, 'ASSOC')) {
3604
            $time_minute = api_convert_and_format_date(
3605
                $item['date'],
3606
                TIME_NO_SEC_FORMAT
3607
            );
3608
            $item['date'] = api_get_local_time($item['date']);
3609
            $item['start_date_tms'] = api_strtotime($item['date']);
3610
            $item['content'] = $item['text'];
3611
3612
            // we break the date field in the database into a date and a time part
3613
            $agenda_db_date = explode(" ", $item['date']);
3614
            $date = $agenda_db_date[0];
3615
            $time = $agenda_db_date[1];
3616
            // we divide the date part into a day, a month and a year
3617
            $agendadate = explode("-", $item['date']);
3618
            $year = intval($agendadate[0]);
3619
            $month = intval($agendadate[1]);
3620
            $day = intval($agendadate[2]);
3621
            // we divide the time part into hour, minutes, seconds
3622
            $agendatime = explode(":", $time);
3623
3624
            $hour = $agendatime[0];
3625
            $minute = $agendatime[1];
3626
            $second = $agendatime[2];
3627
3628
            if ($type == 'month_view') {
3629
                $item['calendar_type'] = 'personal';
3630
                $item['start_date'] = $item['date'];
3631
                $agendaitems[$day][] = $item;
3632
                continue;
3633
            }
3634
3635
            // if the student has specified a course we a add a link to that course
3636
            if ($item['course'] != "") {
3637
                $url = api_get_path(
3638
                        WEB_CODE_PATH
3639
                    )."calendar/agenda.php?cidReq=".urlencode(
3640
                        $item['course']
3641
                    )."&day=$day&month=$month&year=$year#$day"; // RH  //Patrick Cool: to highlight the relevant agenda item
3642
                $course_link = "<a href=\"$url\" title=\"".$item['course']."\">".$item['course']."</a>";
3643
            } else {
3644
                $course_link = "";
3645
            }
3646
            // Creating the array that will be returned. If we have week or month view we have an array with the date as the key
3647
            // if we have a day_view we use a half hour as index => key 33 = 16h30
3648
            if ($type !== "day_view") {
3649
                // This is the array construction for the WEEK or MONTH view
3650
3651
                //Display events in agenda
3652
                $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 />";
3653
            } else {
3654
                // this is the array construction for the DAY view
3655
                $halfhour = 2 * $agendatime['0'];
3656
                if ($agendatime['1'] >= '30') {
3657
                    $halfhour = $halfhour + 1;
3658
                }
3659
3660
                //Display events by list
3661
                $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>";
3662
            }
3663
        }
3664
3665
        return $agendaitems;
3666
    }
3667
3668
    /**
3669
     * Show the monthcalender of the given month.
3670
     *
3671
     * @param    array    Agendaitems
3672
     * @param    int    Month number
3673
     * @param    int    Year number
3674
     * @param    array    Array of strings containing long week day names (deprecated, you can send an empty array
3675
     *                          instead)
3676
     * @param    string    The month name
3677
     */
3678
    public static function display_mymonthcalendar(
3679
        $user_id,
3680
        $agendaitems,
3681
        $month,
3682
        $year,
3683
        $weekdaynames,
3684
        $monthName,
3685
        $show_content = true
3686
    ) {
3687
        global $DaysShort, $course_path;
3688
        //Handle leap year
3689
        $numberofdays = [
3690
            0,
3691
            31,
3692
            28,
3693
            31,
3694
            30,
3695
            31,
3696
            30,
3697
            31,
3698
            31,
3699
            30,
3700
            31,
3701
            30,
3702
            31,
3703
        ];
3704
        if (($year % 400 == 0) or ($year % 4 == 0 and $year % 100 != 0)) {
3705
            $numberofdays[2] = 29;
3706
        }
3707
        //Get the first day of the month
3708
        $dayone = getdate(mktime(0, 0, 0, $month, 1, $year));
3709
        //Start the week on monday
3710
        $startdayofweek = $dayone['wday'] != 0 ? ($dayone['wday'] - 1) : 6;
3711
        $g_cc = (isset($_GET['courseCode']) ? $_GET['courseCode'] : '');
3712
3713
        $next_month = ($month == 1 ? 12 : $month - 1);
3714
        $prev_month = ($month == 12 ? 1 : $month + 1);
3715
3716
        $next_year = ($month == 1 ? $year - 1 : $year);
3717
        $prev_year = ($month == 12 ? $year + 1 : $year);
3718
3719
        if ($show_content) {
3720
            $back_url = Display::url(
3721
                get_lang('Previous'),
3722
                api_get_self()."?coursePath=".urlencode(
3723
                    $course_path
3724
                )."&courseCode=".Security::remove_XSS(
3725
                    $g_cc
3726
                )."&action=view&view=month&month=".$next_month."&year=".$next_year
3727
            );
3728
            $next_url = Display::url(
3729
                get_lang('Next'),
3730
                api_get_self()."?coursePath=".urlencode(
3731
                    $course_path
3732
                )."&courseCode=".Security::remove_XSS(
3733
                    $g_cc
3734
                )."&action=view&view=month&month=".$prev_month."&year=".$prev_year
3735
            );
3736
        } else {
3737
            $back_url = Display::url(
3738
                get_lang('Previous'),
3739
                '',
3740
                [
3741
                    'onclick' => "load_calendar('".$user_id."','".$next_month."', '".$next_year."'); ",
3742
                    'class' => 'btn ui-button ui-widget ui-state-default',
3743
                ]
3744
            );
3745
            $next_url = Display::url(
3746
                get_lang('Next'),
3747
                '',
3748
                [
3749
                    'onclick' => "load_calendar('".$user_id."','".$prev_month."', '".$prev_year."'); ",
3750
                    'class' => 'pull-right btn ui-button ui-widget ui-state-default',
3751
                ]
3752
            );
3753
        }
3754
        $html = '';
3755
        $html .= '<div class="actions">';
3756
        $html .= '<div class="row">';
3757
        $html .= '<div class="col-md-4">'.$back_url.'</div>';
3758
        $html .= '<div class="col-md-4"><p class="agenda-title text-center">'.$monthName." ".$year.'</p></div>';
3759
        $html .= '<div class="col-md-4">'.$next_url.'</div>';
3760
        $html .= '</div>';
3761
        $html .= '</div>';
3762
        $html .= '<table id="agenda_list2" class="table table-bordered">';
3763
        $html .= '<tr>';
3764
        for ($ii = 1; $ii < 8; $ii++) {
3765
            $html .= '<td class="weekdays">'.$DaysShort[$ii % 7].'</td>';
3766
        }
3767
        $html .= '</tr>';
3768
3769
        $curday = -1;
3770
        $today = getdate();
3771
        while ($curday <= $numberofdays[$month]) {
3772
            $html .= "<tr>";
3773
            for ($ii = 0; $ii < 7; $ii++) {
3774
                if (($curday == -1) && ($ii == $startdayofweek)) {
3775
                    $curday = 1;
3776
                }
3777
                if (($curday > 0) && ($curday <= $numberofdays[$month])) {
3778
                    $bgcolor = $class = 'class="days_week"';
3779
                    $dayheader = Display::div(
3780
                        $curday,
3781
                        ['class' => 'agenda_day']
3782
                    );
3783
                    if (($curday == $today['mday']) && ($year == $today['year']) && ($month == $today['mon'])) {
3784
                        $class = "class=\"days_today\" style=\"width:10%;\"";
3785
                    }
3786
3787
                    $html .= "<td ".$class.">".$dayheader;
3788
3789
                    if (!empty($agendaitems[$curday])) {
3790
                        $items = $agendaitems[$curday];
3791
                        $items = msort($items, 'start_date_tms');
3792
3793
                        foreach ($items as $value) {
3794
                            $value['title'] = Security::remove_XSS(
3795
                                $value['title']
3796
                            );
3797
                            $start_time = api_format_date(
3798
                                $value['start_date'],
3799
                                TIME_NO_SEC_FORMAT
3800
                            );
3801
                            $end_time = '';
3802
3803
                            if (!empty($value['end_date'])) {
3804
                                $end_time = '-&nbsp;<i>'.api_format_date(
3805
                                        $value['end_date'],
3806
                                        DATE_TIME_FORMAT_LONG
3807
                                    ).'</i>';
3808
                            }
3809
                            $complete_time = '<i>'.api_format_date(
3810
                                    $value['start_date'],
3811
                                    DATE_TIME_FORMAT_LONG
3812
                                ).'</i>&nbsp;'.$end_time;
3813
                            $time = '<i>'.$start_time.'</i>';
3814
3815
                            switch ($value['calendar_type']) {
3816
                                case 'personal':
3817
                                    $bg_color = '#D0E7F4';
3818
                                    $icon = Display::return_icon(
3819
                                        'user.png',
3820
                                        get_lang('MyAgenda'),
3821
                                        [],
3822
                                        ICON_SIZE_SMALL
3823
                                    );
3824
                                    break;
3825
                                case 'global':
3826
                                    $bg_color = '#FFBC89';
3827
                                    $icon = Display::return_icon(
3828
                                        'view_remove.png',
3829
                                        get_lang('GlobalEvent'),
3830
                                        [],
3831
                                        ICON_SIZE_SMALL
3832
                                    );
3833
                                    break;
3834
                                case 'course':
3835
                                    $bg_color = '#CAFFAA';
3836
                                    $icon_name = 'course.png';
3837
                                    if (!empty($value['session_id'])) {
3838
                                        $icon_name = 'session.png';
3839
                                    }
3840
                                    if ($show_content) {
3841
                                        $icon = Display::url(
3842
                                            Display::return_icon(
3843
                                                $icon_name,
3844
                                                $value['course_name'].' '.get_lang(
3845
                                                    'Course'
3846
                                                ),
3847
                                                [],
3848
                                                ICON_SIZE_SMALL
3849
                                            ),
3850
                                            $value['url']
3851
                                        );
3852
                                    } else {
3853
                                        $icon = Display::return_icon(
3854
                                            $icon_name,
3855
                                            $value['course_name'].' '.get_lang(
3856
                                                'Course'
3857
                                            ),
3858
                                            [],
3859
                                            ICON_SIZE_SMALL
3860
                                        );
3861
                                    }
3862
                                    break;
3863
                                default:
3864
                                    break;
3865
                            }
3866
3867
                            $result = '<div class="rounded_div_agenda" style="background-color:'.$bg_color.';">';
3868
3869
                            if ($show_content) {
3870
                                //Setting a personal event to green
3871
                                $icon = Display::div(
3872
                                    $icon,
3873
                                    ['style' => 'float:right']
3874
                                );
3875
3876
                                $link = $value['calendar_type'].'_'.$value['id'].'_'.$value['course_id'].'_'.$value['session_id'];
3877
3878
                                //Link to bubble
3879
                                $url = Display::url(
3880
                                    cut($value['title'], 40),
3881
                                    '#',
3882
                                    ['id' => $link, 'class' => 'opener']
3883
                                );
3884
                                $result .= $time.' '.$icon.' '.Display::div(
3885
                                        $url
3886
                                    );
3887
3888
                                //Hidden content
3889
                                $content = Display::div(
3890
                                    $icon.Display::tag(
3891
                                        'h2',
3892
                                        $value['course_name']
3893
                                    ).'<hr />'.Display::tag(
3894
                                        'h3',
3895
                                        $value['title']
3896
                                    ).$complete_time.'<hr />'.Security::remove_XSS(
3897
                                        $value['content']
3898
                                    )
3899
                                );
3900
3901
                                //Main div
3902
                                $result .= Display::div(
3903
                                    $content,
3904
                                    [
3905
                                        'id' => 'main_'.$link,
3906
                                        'class' => 'dialog',
3907
                                        'style' => 'display:none',
3908
                                    ]
3909
                                );
3910
                                $result .= '</div>';
3911
                                $html .= $result;
3912
                            } else {
3913
                                $html .= $result .= $icon.'</div>';
3914
                            }
3915
                        }
3916
                    }
3917
                    $html .= "</td>";
3918
                    $curday++;
3919
                } else {
3920
                    $html .= "<td></td>";
3921
                }
3922
            }
3923
            $html .= "</tr>";
3924
        }
3925
        $html .= "</table>";
3926
        echo $html;
3927
    }
3928
3929
    /**
3930
     * Get personal agenda items between two dates (=all events from all registered courses).
3931
     *
3932
     * @param int $user_id user ID of the user
3933
     * @param    string    Optional start date in datetime format (if no start date is given, uses today)
3934
     * @param    string    Optional end date in datetime format (if no date is given, uses one year from now)
3935
     *
3936
     * @return array array of events ordered by start date, in
3937
     *               [0]('datestart','dateend','title'),[1]('datestart','dateend','title','link','coursetitle') format,
3938
     *               where datestart and dateend are in yyyyMMddhhmmss format
3939
     *
3940
     * @deprecated use agenda events
3941
     */
3942
    public static function get_personal_agenda_items_between_dates(
3943
        $user_id,
3944
        $date_start = '',
3945
        $date_end = ''
3946
    ) {
3947
        $items = [];
3948
        if ($user_id != strval(intval($user_id))) {
3949
            return $items;
3950
        }
3951
        if (empty($date_start)) {
3952
            $date_start = date('Y-m-d H:i:s');
3953
        }
3954
        if (empty($date_end)) {
3955
            $date_end = date(
3956
                'Y-m-d H:i:s',
3957
                mktime(0, 0, 0, date("m"), date("d"), date("Y") + 1)
3958
            );
3959
        }
3960
        $expr = '/\d{4}-\d{2}-\d{2}\ \d{2}:\d{2}:\d{2}/';
3961
        if (!preg_match($expr, $date_start)) {
3962
            return $items;
3963
        }
3964
        if (!preg_match($expr, $date_end)) {
3965
            return $items;
3966
        }
3967
3968
        // get agenda-items for every course
3969
        $courses = api_get_user_courses($user_id, false);
3970
        foreach ($courses as $id => $course) {
3971
            $c = api_get_course_info_by_id($course['real_id']);
3972
            //databases of the courses
3973
            $t_a = Database::get_course_table(TABLE_AGENDA, $course['db']);
3974
            $t_ip = Database::get_course_table(
3975
                TABLE_ITEM_PROPERTY,
3976
                $course['db']
3977
            );
3978
            // get the groups to which the user belong
3979
            $group_memberships = GroupManager:: get_group_ids(
3980
                $course['db'],
3981
                $user_id
3982
            );
3983
            // if the user is administrator of that course we show all the agenda items
3984
            if ($course['status'] == '1') {
3985
                //echo "course admin";
3986
                $sqlquery = "SELECT ".
3987
                    " DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
3988
                    " FROM ".$t_a." agenda, ".
3989
                    $t_ip." ip ".
3990
                    " WHERE agenda.id = ip.ref ".
3991
                    " AND agenda.start_date>='$date_start' ".
3992
                    " AND agenda.end_date<='$date_end' ".
3993
                    " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
3994
                    " AND ip.visibility='1' ".
3995
                    " GROUP BY agenda.id ".
3996
                    " ORDER BY start_date ";
3997
            } else {
3998
                // if the user is not an administrator of that course, then...
3999
                if (is_array($group_memberships) && count(
4000
                        $group_memberships
4001
                    ) > 0
4002
                ) {
4003
                    $sqlquery = "SELECT ".
4004
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4005
                        " FROM ".$t_a." agenda, ".
4006
                        $t_ip." ip ".
4007
                        " WHERE agenda.id = ip.ref ".
4008
                        " AND agenda.start_date>='$date_start' ".
4009
                        " AND agenda.end_date<='$date_end' ".
4010
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4011
                        " AND	( ip.to_user_id='".$user_id."' OR (ip.to_group_id IS NULL OR ip.to_group_id IN (0, ".implode(
4012
                            ", ",
4013
                            $group_memberships
4014
                        ).")) ) ".
4015
                        " AND ip.visibility='1' ".
4016
                        " ORDER BY start_date ";
4017
                } else {
4018
                    $sqlquery = "SELECT ".
4019
                        "DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref ".
4020
                        " FROM ".$t_a." agenda, ".
4021
                        $t_ip." ip ".
4022
                        " WHERE agenda.id = ip.ref ".
4023
                        " AND agenda.start_date>='$date_start' ".
4024
                        " AND agenda.end_date<='$date_end' ".
4025
                        " AND ip.tool='".TOOL_CALENDAR_EVENT."' ".
4026
                        " AND ( ip.to_user_id='".$user_id."' OR ip.to_group_id='0' OR ip.to_group_id IS NULL) ".
4027
                        " AND ip.visibility='1' ".
4028
                        " ORDER BY start_date ";
4029
                }
4030
            }
4031
4032
            $result = Database::query($sqlquery);
4033
            while ($item = Database::fetch_array($result)) {
4034
                $agendaday = date("j", strtotime($item['start_date']));
4035
                $month = date("n", strtotime($item['start_date']));
4036
                $year = date("Y", strtotime($item['start_date']));
4037
                $URL = api_get_path(
4038
                        WEB_PATH
4039
                    )."main/calendar/agenda.php?cidReq=".urlencode(
4040
                        $course["code"]
4041
                    )."&day=$agendaday&month=$month&year=$year#$agendaday";
4042
                list($year, $month, $day, $hour, $min, $sec) = explode(
4043
                    '[-: ]',
4044
                    $item['start_date']
4045
                );
4046
                $start_date = $year.$month.$day.$hour.$min;
4047
                list($year, $month, $day, $hour, $min, $sec) = explode(
4048
                    '[-: ]',
4049
                    $item['end_date']
4050
                );
4051
                $end_date = $year.$month.$day.$hour.$min;
4052
4053
                $items[] = [
4054
                    'datestart' => $start_date,
4055
                    'dateend' => $end_date,
4056
                    'title' => $item['title'],
4057
                    'link' => $URL,
4058
                    'coursetitle' => $c['name'],
4059
                ];
4060
            }
4061
        }
4062
4063
        return $items;
4064
    }
4065
4066
    /**
4067
     * This function calculates the startdate of the week (monday)
4068
     * and the enddate of the week (sunday)
4069
     * and returns it as an array.
4070
     */
4071
    public static function calculate_start_end_of_week($week_number, $year)
4072
    {
4073
        // determine the start and end date
4074
        // step 1: we calculate a timestamp for a day in this week
4075
        $random_day_in_week = mktime(
4076
                0,
4077
                0,
4078
                0,
4079
                1,
4080
                1,
4081
                $year
4082
            ) + ($week_number) * (7 * 24 * 60 * 60); // we calculate a random day in this week
4083
        // step 2: we which day this is (0=sunday, 1=monday, ...)
4084
        $number_day_in_week = date('w', $random_day_in_week);
4085
        // step 3: we calculate the timestamp of the monday of the week we are in
4086
        $start_timestamp = $random_day_in_week - (($number_day_in_week - 1) * 24 * 60 * 60);
4087
        // step 4: we calculate the timestamp of the sunday of the week we are in
4088
        $end_timestamp = $random_day_in_week + ((7 - $number_day_in_week + 1) * 24 * 60 * 60) - 3600;
4089
        // step 5: calculating the start_day, end_day, start_month, end_month, start_year, end_year
4090
        $start_day = date('j', $start_timestamp);
4091
        $start_month = date('n', $start_timestamp);
4092
        $start_year = date('Y', $start_timestamp);
4093
        $end_day = date('j', $end_timestamp);
4094
        $end_month = date('n', $end_timestamp);
4095
        $end_year = date('Y', $end_timestamp);
4096
        $start_end_array['start']['day'] = $start_day;
4097
        $start_end_array['start']['month'] = $start_month;
4098
        $start_end_array['start']['year'] = $start_year;
4099
        $start_end_array['end']['day'] = $end_day;
4100
        $start_end_array['end']['month'] = $end_month;
4101
        $start_end_array['end']['year'] = $end_year;
4102
4103
        return $start_end_array;
4104
    }
4105
4106
    /**
4107
     * @return bool
4108
     */
4109
    public function getIsAllowedToEdit()
4110
    {
4111
        return $this->isAllowedToEdit;
4112
    }
4113
4114
    /**
4115
     * @param bool $isAllowedToEdit
4116
     */
4117
    public function setIsAllowedToEdit($isAllowedToEdit)
4118
    {
4119
        $this->isAllowedToEdit = $isAllowedToEdit;
4120
    }
4121
4122
    /**
4123
     * Format needed for the Fullcalendar js lib.
4124
     *
4125
     * @param string $utcTime
4126
     *
4127
     * @return bool|string
4128
     */
4129
    public function formatEventDate($utcTime)
4130
    {
4131
        $utcTimeZone = new DateTimeZone('UTC');
4132
        $platformTimeZone = new DateTimeZone(api_get_timezone());
4133
4134
        $eventDate = new DateTime($utcTime, $utcTimeZone);
4135
        $eventDate->setTimezone($platformTimeZone);
4136
4137
        return $eventDate->format(DateTime::ISO8601);
4138
    }
4139
}
4140