MessageManager::send_message()   F
last analyzed

Complexity

Conditions 56
Paths > 20000

Size

Total Lines 327
Code Lines 205

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 205
c 0
b 0
f 0
dl 0
loc 327
rs 0
cc 56
nc 120062
nop 20

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Message;
6
use Chamilo\CoreBundle\Entity\Tag as TagEntity;
7
use Chamilo\UserBundle\Entity\User;
8
use ChamiloSession as Session;
9
10
/**
11
 * Class MessageManager.
12
 *
13
 * This class provides methods for messages management.
14
 * Include/require it in your code to use its features.
15
 */
16
class MessageManager
17
{
18
    public const MESSAGE_TYPE_INBOX = 1;
19
    public const MESSAGE_TYPE_OUTBOX = 2;
20
    public const MESSAGE_TYPE_PROMOTED = 3;
21
22
    /**
23
     * Get count new messages for the current user from the database.
24
     *
25
     * @return int
26
     */
27
    public static function getCountNewMessages()
28
    {
29
        $userId = api_get_user_id();
30
        if (empty($userId)) {
31
            return false;
32
        }
33
34
        static $count;
35
        if (!isset($count)) {
36
            $cacheAvailable = api_get_configuration_value('apc');
37
            if ($cacheAvailable === true) {
38
                $var = api_get_configuration_value('apc_prefix').'social_messages_unread_u_'.$userId;
39
                if (apcu_exists($var)) {
40
                    $count = apcu_fetch($var);
41
                } else {
42
                    $count = self::getCountNewMessagesFromDB($userId);
43
                    apcu_store($var, $count, 60);
44
                }
45
            } else {
46
                $count = self::getCountNewMessagesFromDB($userId);
47
            }
48
        }
49
50
        return $count;
51
    }
52
53
    /**
54
     * Gets the total number of messages, used for the inbox sortable table.
55
     *
56
     * @param array $params
57
     *
58
     * @return int
59
     */
60
    public static function getNumberOfMessages($params)
61
    {
62
        $table = Database::get_main_table(TABLE_MESSAGE);
63
        $conditions = self::getWhereConditions($params);
64
65
        $sql = "SELECT COUNT(DISTINCT m.id) as number_messages
66
                FROM $table m";
67
68
        if (true === api_get_configuration_value('enable_message_tags')) {
69
            $tblExtraFielRelTag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
70
            $tblExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
71
72
            $sql .= "
73
                LEFT JOIN $tblExtraFielRelTag efrt ON efrt.item_id = m.id
74
                LEFT JOIN $tblExtraField ef ON ef.id = efrt.field_id AND ef.variable = 'tags'";
75
        }
76
77
        $sql .= "
78
                WHERE
79
                    $conditions
80
                ";
81
        $result = Database::query($sql);
82
        $result = Database::fetch_array($result);
83
84
        if ($result) {
85
            return (int) $result['number_messages'];
86
        }
87
88
        return 0;
89
    }
90
91
    /**
92
     * @param array $extraParams
93
     *
94
     * @return string
95
     */
96
    public static function getWhereConditions($extraParams)
97
    {
98
        $userId = api_get_user_id();
99
100
        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
101
        $type = isset($extraParams['type']) && !empty($extraParams['type']) ? $extraParams['type'] : '';
102
        $tags = $extraParams['tags'] ?? [];
103
104
        if (empty($type)) {
105
            return '';
106
        }
107
108
        switch ($type) {
109
            case self::MESSAGE_TYPE_INBOX:
110
                $statusList = [MESSAGE_STATUS_NEW, MESSAGE_STATUS_UNREAD];
111
                $userCondition = " m.user_receiver_id = $userId AND";
112
                break;
113
            case self::MESSAGE_TYPE_OUTBOX:
114
                $statusList = [MESSAGE_STATUS_OUTBOX];
115
                $userCondition = " m.user_sender_id = $userId AND";
116
                break;
117
            case self::MESSAGE_TYPE_PROMOTED:
118
                $statusList = [MESSAGE_STATUS_PROMOTED];
119
                $userCondition = " m.user_receiver_id = $userId AND";
120
                break;
121
        }
122
123
        if (empty($statusList)) {
124
            return '';
125
        }
126
127
        $keywordCondition = '';
128
        if (!empty($keyword)) {
129
            $keyword = Database::escape_string($keyword);
130
            $keywordCondition = " AND (m.title like '%$keyword%' OR m.content LIKE '%$keyword%') ";
131
        }
132
        $messageStatusCondition = implode("','", $statusList);
133
134
        $tagsCondition = '';
135
136
        if (true === api_get_configuration_value('enable_message_tags') && !empty($tags)) {
137
            $tagsCondition = ' AND efrt.tag_id IN ('.implode(', ', $tags).") ";
138
        }
139
140
        return " $userCondition
141
                 m.msg_status IN ('$messageStatusCondition')
142
                 $keywordCondition
143
                 $tagsCondition";
144
    }
145
146
    /**
147
     * Gets information about some messages, used for the inbox sortable table.
148
     *
149
     * @param int    $from
150
     * @param int    $numberOfItems
151
     * @param int    $column
152
     * @param string $direction
153
     * @param array  $extraParams
154
     *
155
     * @return array
156
     */
157
    public static function getMessageData(
158
        $from,
159
        $numberOfItems,
160
        $column,
161
        $direction,
162
        $extraParams = []
163
    ) {
164
        $from = (int) $from;
165
        $numberOfItems = (int) $numberOfItems;
166
        // Forcing this order.
167
        if (!isset($direction)) {
168
            $column = 2;
169
            $direction = 'DESC';
170
        } else {
171
            $column = (int) $column;
172
            if (!in_array($direction, ['ASC', 'DESC'])) {
173
                $direction = 'ASC';
174
            }
175
        }
176
177
        if (!in_array($column, [0, 1, 2])) {
178
            $column = 2;
179
        }
180
181
        $type = isset($extraParams['type']) && !empty($extraParams['type']) ? $extraParams['type'] : '';
182
183
        if (empty($type)) {
184
            return [];
185
        }
186
187
        $viewUrl = '';
188
        switch ($type) {
189
            case self::MESSAGE_TYPE_OUTBOX:
190
            case self::MESSAGE_TYPE_INBOX:
191
                $viewUrl = api_get_path(WEB_CODE_PATH).'messages/view_message.php';
192
                break;
193
            case self::MESSAGE_TYPE_PROMOTED:
194
                $viewUrl = api_get_path(WEB_CODE_PATH).'social/view_promoted_message.php';
195
                break;
196
        }
197
        $viewUrl .= '?type='.$type;
198
199
        $whereConditions = self::getWhereConditions($extraParams);
200
201
        if (empty($whereConditions)) {
202
            return [];
203
        }
204
205
        $table = Database::get_main_table(TABLE_MESSAGE);
206
        $sql = "SELECT DISTINCT
207
                    m.id as col0,
208
                    m.title as col1,
209
                    m.send_date as col2,
210
                    m.msg_status as col3,
211
                    m.user_sender_id,
212
                    m.user_receiver_id
213
                FROM $table m";
214
215
        if (true === api_get_configuration_value('enable_message_tags')) {
216
            $tblExtraFielRelTag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
217
            $tblExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
218
219
            $sql .= "
220
                LEFT JOIN $tblExtraFielRelTag efrt ON efrt.item_id = m.id
221
                LEFT JOIN $tblExtraField ef ON ef.id = efrt.field_id AND ef.variable = 'tags'";
222
        }
223
224
        $sql .= "
225
                WHERE
226
                    $whereConditions
227
                ORDER BY col$column $direction
228
                LIMIT $from, $numberOfItems";
229
230
        $result = Database::query($sql);
231
        $messageList = [];
232
        $newMessageLink = api_get_path(WEB_CODE_PATH).'messages/new_message.php';
233
234
        $actions = $extraParams['actions'];
235
        $url = api_get_self();
236
237
        $objExtraField = new ExtraField('message');
238
        $extrafieldTags = $objExtraField->getHandlerEntityByFieldVariable('tags');
239
        $efrtRepo = Database::getManager()->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
240
241
        while ($row = Database::fetch_array($result, 'ASSOC')) {
242
            $messageId = $row['col0'];
243
            $title = $row['col1'];
244
            $sendDate = $row['col2'];
245
            $status = $row['col3'];
246
            $senderId = $row['user_sender_id'];
247
            $receiverId = $row['user_receiver_id'];
248
249
            $title = Security::remove_XSS($title, STUDENT, true);
250
            $title = cut($title, 80, true);
251
252
            $class = 'class = "read"';
253
            if (1 == $status) {
254
                $class = 'class = "unread"';
255
            }
256
257
            $userInfo = api_get_user_info($senderId);
258
            if ($type == self::MESSAGE_TYPE_OUTBOX) {
259
                $userInfo = api_get_user_info($receiverId);
260
            }
261
            $message[3] = '';
262
            if (!empty($senderId) && !empty($userInfo)) {
263
                $message[1] = '<a '.$class.' href="'.$viewUrl.'&id='.$messageId.'">'.$title.'</a><br />';
264
                $message[1] .= Display::tag('small', $userInfo['complete_name_with_username']);
265
                if (in_array('reply', $actions)) {
266
                    $message[3] =
267
                        Display::url(
268
                            Display::returnFontAwesomeIcon('reply', 2),
269
                            $newMessageLink.'?re_id='.$messageId,
270
                            ['title' => get_lang('ReplyToMessage')]
271
                        );
272
                }
273
            } else {
274
                $message[1] = '<a '.$class.' href="'.$viewUrl.'&id='.$messageId.'">'.$title.'</a><br />';
275
                $message[1] .= get_lang('UnknownUser');
276
                if (in_array('reply', $actions)) {
277
                    $message[3] =
278
                        Display::url(
279
                            Display::returnFontAwesomeIcon('reply', 2),
280
                            '#',
281
                            ['title' => get_lang('ReplyToMessage')]
282
                        );
283
                }
284
            }
285
286
            if (in_array($type, [self::MESSAGE_TYPE_INBOX, self::MESSAGE_TYPE_OUTBOX])
287
                && api_get_configuration_value('enable_message_tags')
288
                && $extrafieldTags
289
            ) {
290
                $tags = $efrtRepo->getTags($extrafieldTags, $messageId);
291
                $tagsBadges = array_map(
292
                    function (TagEntity $tag) {
293
                        return Display::badge($tag->getTag(), 'default');
294
                    },
295
                    $tags
296
                );
297
298
                $message[1] .= Display::badge_group($tagsBadges);
299
            }
300
301
            $message[0] = $messageId;
302
            $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
303
304
            // Actions
305
            if (in_array('edit', $actions)) {
306
                $message[3] .=
307
                    '&nbsp;&nbsp;'.
308
                    Display::url(
309
                        Display::returnFontAwesomeIcon('pencil', 2),
310
                        $newMessageLink.'?action=edit&id='.$messageId,
311
                        ['title' => get_lang('ForwardMessage')]
312
                    );
313
            }
314
315
            // Actions
316
            if (in_array('forward', $actions)) {
317
                $message[3] .=
318
                    '&nbsp;&nbsp;'.
319
                    Display::url(
320
                        Display::returnFontAwesomeIcon('share', 2),
321
                        $newMessageLink.'?forward_id='.$messageId,
322
                        ['title' => get_lang('ForwardMessage')]
323
                    );
324
            }
325
326
            if (in_array('delete', $actions)) {
327
                $message[3] .= '&nbsp;&nbsp;<a title="'.addslashes(
328
                    get_lang('DeleteMessage')
329
                ).'" onclick="javascript:if(!confirm('."'".addslashes(
330
                    api_htmlentities(get_lang('ConfirmDeleteMessage'))
331
                )."'".')) return false;" href="'.$url.'?action=deleteone&id='.$messageId.'">'.
332
                Display::returnFontAwesomeIcon('trash', 2).'</a>';
333
            }
334
335
            foreach ($message as $key => $value) {
336
                $message[$key] = api_xml_http_response_encode($value);
337
            }
338
            $messageList[] = $message;
339
        }
340
341
        return $messageList;
342
    }
343
344
    /**
345
     * @param array  $aboutUserInfo
346
     * @param array  $fromUserInfo
347
     * @param string $subject
348
     * @param string $content
349
     *
350
     * @return bool
351
     */
352
    public static function sendMessageAboutUser(
353
        $aboutUserInfo,
354
        $fromUserInfo,
355
        $subject,
356
        $content
357
    ) {
358
        if (empty($aboutUserInfo) || empty($fromUserInfo)) {
359
            return false;
360
        }
361
362
        if (empty($fromUserInfo['id']) || empty($aboutUserInfo['id'])) {
363
            return false;
364
        }
365
366
        $table = Database::get_main_table(TABLE_MESSAGE);
367
        $now = api_get_utc_datetime();
368
        $params = [
369
            'user_sender_id' => $fromUserInfo['id'],
370
            'user_receiver_id' => $aboutUserInfo['id'],
371
            'msg_status' => MESSAGE_STATUS_CONVERSATION,
372
            'send_date' => $now,
373
            'title' => $subject,
374
            'content' => $content,
375
            'group_id' => 0,
376
            'parent_id' => 0,
377
            'update_date' => $now,
378
        ];
379
        $id = Database::insert($table, $params);
380
381
        if ($id) {
382
            return true;
383
        }
384
385
        return false;
386
    }
387
388
    /**
389
     * @param array $aboutUserInfo
390
     *
391
     * @return array
392
     */
393
    public static function getMessagesAboutUser($aboutUserInfo)
394
    {
395
        if (!empty($aboutUserInfo)) {
396
            $table = Database::get_main_table(TABLE_MESSAGE);
397
            $sql = 'SELECT id FROM '.$table.'
398
                    WHERE
399
                      user_receiver_id = '.$aboutUserInfo['id'].' AND
400
                      msg_status = '.MESSAGE_STATUS_CONVERSATION.'
401
                    ';
402
            $result = Database::query($sql);
403
            $messages = [];
404
            $repo = Database::getManager()->getRepository('ChamiloCoreBundle:Message');
405
            while ($row = Database::fetch_array($result)) {
406
                $message = $repo->find($row['id']);
407
                $messages[] = $message;
408
            }
409
410
            return $messages;
411
        }
412
413
        return [];
414
    }
415
416
    /**
417
     * @param array $userInfo
418
     *
419
     * @return string
420
     */
421
    public static function getMessagesAboutUserToString($userInfo, $origin = null)
422
    {
423
        $messages = self::getMessagesAboutUser($userInfo);
424
        $html = '';
425
        if (!empty($messages)) {
426
            /** @var Message $message */
427
            foreach ($messages as $message) {
428
                $tag = 'message_'.$message->getId();
429
                $tagAccordion = 'accordion_'.$message->getId();
430
                $tagCollapse = 'collapse_'.$message->getId();
431
                $date = Display::dateToStringAgoAndLongDate(
432
                    $message->getSendDate()
433
                );
434
                $localTime = api_get_local_time(
435
                    $message->getSendDate(),
436
                    null,
437
                    null,
438
                    false,
439
                    false
440
                );
441
                $senderId = $message->getUserSenderId();
442
                $senderInfo = api_get_user_info($senderId);
443
                $deleteLink = '';
444
                if ('my_space' == $origin && api_get_user_id() == $senderId) {
445
                    $deleteLink = '<a title="'.addslashes(
446
                            get_lang('DeleteMessage')
447
                        ).'" href="'.api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.$userInfo['id'].'&action=delete_msg&msg_id='.$message->getId().'"  onclick="javascript:if(!confirm('."'".addslashes(
448
                            api_htmlentities(get_lang('ConfirmDeleteMessage'))
449
                        )."'".')) return false;" >&nbsp;&nbsp;&nbsp;&nbsp;'.
450
                        Display::returnFontAwesomeIcon('trash', 1).'</a>';
451
                }
452
                $html .= Display::panelCollapse(
453
                    $localTime.' '.$senderInfo['complete_name'].' '.$message->getTitle().$deleteLink,
454
                    $message->getContent().'<br />'.$date.'<br />'.get_lang(
455
                        'Author'
456
                    ).': '.$senderInfo['complete_name_with_message_link'],
457
                    $tag,
458
                    null,
459
                    $tagAccordion,
460
                    $tagCollapse,
461
                    false
462
                );
463
            }
464
        }
465
466
        return $html;
467
    }
468
469
    /**
470
     * @param int    $senderId
471
     * @param int    $receiverId
472
     * @param string $subject
473
     * @param string $message
474
     *
475
     * @return bool
476
     */
477
    public static function messageWasAlreadySent($senderId, $receiverId, $subject, $message)
478
    {
479
        $table = Database::get_main_table(TABLE_MESSAGE);
480
        $senderId = (int) $senderId;
481
        $receiverId = (int) $receiverId;
482
        $subject = Database::escape_string($subject);
483
        $message = Database::escape_string($message);
484
485
        $sql = "SELECT * FROM $table
486
                WHERE
487
                    user_sender_id = $senderId AND
488
                    user_receiver_id = $receiverId AND
489
                    title = '$subject' AND
490
                    content = '$message' AND
491
                    (msg_status = ".MESSAGE_STATUS_UNREAD." OR msg_status = ".MESSAGE_STATUS_NEW.")
492
                ";
493
        $result = Database::query($sql);
494
495
        return Database::num_rows($result) > 0;
496
    }
497
498
    /**
499
     * Sends a message to a user/group.
500
     *
501
     * @param int    $receiverUserId
502
     * @param string $subject
503
     * @param string $content
504
     * @param array  $attachments                files array($_FILES) (optional)
505
     * @param array  $fileCommentList            about attachment files (optional)
506
     * @param int    $group_id                   (optional)
507
     * @param int    $parent_id                  (optional)
508
     * @param int    $editMessageId              id for updating the message (optional)
509
     * @param int    $topic_id                   (optional) the default value is the current user_id
510
     * @param int    $sender_id
511
     * @param bool   $directMessage
512
     * @param int    $forwardId
513
     * @param array  $smsParameters
514
     * @param bool   $checkCurrentAudioId
515
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
516
     * @param int    $status                     Message status
517
     * @param bool   $checkUrls                  It checks access url of user when multiple_access_urls = true
518
     *
519
     * @return bool
520
     */
521
    public static function send_message(
522
        $receiverUserId,
523
        $subject,
524
        $content,
525
        array $attachments = [],
526
        array $fileCommentList = [],
527
        $group_id = 0,
528
        $parent_id = 0,
529
        $editMessageId = 0,
530
        $topic_id = 0,
531
        $sender_id = 0,
532
        $directMessage = false,
533
        $forwardId = 0,
534
        $smsParameters = [],
535
        $checkCurrentAudioId = false,
536
        $forceTitleWhenSendingEmail = false,
537
        $status = 0,
538
        array $extraParams = [],
539
        $checkUrls = false,
540
        $courseId = null,
541
        $only_local = false
542
    ) {
543
        $group_id = (int) $group_id;
544
        $receiverUserId = (int) $receiverUserId;
545
        $parent_id = (int) $parent_id;
546
        $editMessageId = (int) $editMessageId;
547
        $topic_id = (int) $topic_id;
548
        $status = empty($status) ? MESSAGE_STATUS_UNREAD : (int) $status;
549
550
        $sendEmail = !$only_local;
551
        if (!empty($receiverUserId)) {
552
            $receiverUserInfo = api_get_user_info($receiverUserId);
553
            if (empty($receiverUserInfo)) {
554
                return false;
555
            }
556
557
            // Disabling messages depending the pausetraining plugin.
558
            $allowPauseFormation =
559
                'true' === api_get_plugin_setting('pausetraining', 'tool_enable') &&
560
                'true' === api_get_plugin_setting('pausetraining', 'allow_users_to_edit_pause_formation');
561
562
            if ($allowPauseFormation && $sendEmail) {
563
                $extraFieldValue = new ExtraFieldValue('user');
564
                $disableEmails = $extraFieldValue->get_values_by_handler_and_field_variable(
565
                    $receiverUserId,
566
                    'disable_emails'
567
                );
568
569
                // User doesn't want email notifications but chamilo inbox still available.
570
                if (!empty($disableEmails) &&
571
                    isset($disableEmails['value']) && 1 === (int) $disableEmails['value']
572
                ) {
573
                    $sendEmail = false;
574
                }
575
576
                if ($sendEmail) {
577
                    // Check if user pause his formation.
578
                    $pause = $extraFieldValue->get_values_by_handler_and_field_variable(
579
                        $receiverUserId,
580
                        'pause_formation'
581
                    );
582
                    if (!empty($pause) && isset($pause['value']) && 1 === (int) $pause['value']) {
583
                        $startDate = $extraFieldValue->get_values_by_handler_and_field_variable(
584
                            $receiverUserInfo['user_id'],
585
                            'start_pause_date'
586
                        );
587
                        $endDate = $extraFieldValue->get_values_by_handler_and_field_variable(
588
                            $receiverUserInfo['user_id'],
589
                            'end_pause_date'
590
                        );
591
592
                        if (
593
                            !empty($startDate) && isset($startDate['value']) && !empty($startDate['value']) &&
594
                            !empty($endDate) && isset($endDate['value']) && !empty($endDate['value'])
595
                        ) {
596
                            $now = time();
597
                            $start = api_strtotime($startDate['value']);
598
                            $end = api_strtotime($endDate['value']);
599
600
                            if ($now > $start && $now < $end) {
601
                                $sendEmail = false;
602
                            }
603
                        }
604
                    }
605
                }
606
            }
607
        }
608
609
        $user_sender_id = empty($sender_id) ? api_get_user_id() : (int) $sender_id;
610
        if (empty($user_sender_id)) {
611
            Display::addFlash(Display::return_message(get_lang('UserDoesNotExist'), 'warning'));
612
613
            return false;
614
        }
615
616
        $totalFileSize = 0;
617
        $attachmentList = [];
618
        if (is_array($attachments)) {
619
            $counter = 0;
620
            foreach ($attachments as $attachment) {
621
                $attachment['comment'] = isset($fileCommentList[$counter]) ? $fileCommentList[$counter] : '';
622
                $fileSize = isset($attachment['size']) ? $attachment['size'] : 0;
623
                if (is_array($fileSize)) {
624
                    foreach ($fileSize as $size) {
625
                        $totalFileSize += $size;
626
                    }
627
                } else {
628
                    $totalFileSize += $fileSize;
629
                }
630
                $attachmentList[] = $attachment;
631
                $counter++;
632
            }
633
        }
634
635
        if ($checkCurrentAudioId) {
636
            // Add the audio file as an attachment
637
            $audioId = Session::read('current_audio_id');
638
            if (!empty($audioId)) {
639
                $file = api_get_uploaded_file('audio_message', api_get_user_id(), $audioId);
640
                if (!empty($file)) {
641
                    $audioAttachment = [
642
                        'name' => basename($file),
643
                        'comment' => 'audio_message',
644
                        'size' => filesize($file),
645
                        'tmp_name' => $file,
646
                        'error' => 0,
647
                        'type' => DocumentManager::file_get_mime_type(basename($file)),
648
                    ];
649
                    // create attachment from audio message
650
                    $attachmentList[] = $audioAttachment;
651
                }
652
            }
653
        }
654
655
        // Validating fields
656
        if (empty($subject) && empty($group_id)) {
657
            Display::addFlash(
658
                Display::return_message(
659
                    get_lang('YouShouldWriteASubject'),
660
                    'warning'
661
                )
662
            );
663
664
            return false;
665
        } elseif ($totalFileSize > (int) getIniMaxFileSizeInBytes(false, true)) {
666
            $warning = get_lang('FileSizeIsTooBig').' '.get_lang('MaxFileSize').' : '.getIniMaxFileSizeInBytes(true, true);
667
            Display::addFlash(Display::return_message($warning, 'error'));
668
669
            return false;
670
        }
671
672
        $now = api_get_utc_datetime();
673
        $table = Database::get_main_table(TABLE_MESSAGE);
674
675
        if (!empty($receiverUserId) || !empty($group_id)) {
676
            // message for user friend
677
            //@todo it's possible to edit a message? yes, only for groups
678
            if (!empty($editMessageId)) {
679
                $query = " UPDATE $table SET
680
                              update_date = '".$now."',
681
                              content = '".Database::escape_string($content)."'
682
                           WHERE id = '$editMessageId' ";
683
                Database::query($query);
684
                $messageId = $editMessageId;
685
            } else {
686
                $params = [
687
                    'user_sender_id' => $user_sender_id,
688
                    'user_receiver_id' => $receiverUserId,
689
                    'msg_status' => $status,
690
                    'send_date' => $now,
691
                    'title' => $subject,
692
                    'content' => $content,
693
                    'group_id' => $group_id,
694
                    'parent_id' => $parent_id,
695
                    'update_date' => $now,
696
                ];
697
                $messageId = Database::insert($table, $params);
698
            }
699
700
            // Forward also message attachments
701
            if (!empty($forwardId)) {
702
                $attachments = self::getAttachmentList($forwardId);
703
                foreach ($attachments as $attachment) {
704
                    if (!empty($attachment['file_source'])) {
705
                        $file = [
706
                            'name' => $attachment['filename'],
707
                            'tmp_name' => $attachment['file_source'],
708
                            'size' => $attachment['size'],
709
                            'error' => 0,
710
                            'comment' => $attachment['comment'],
711
                        ];
712
713
                        // Inject this array so files can be added when sending and email with the mailer
714
                        $attachmentList[] = $file;
715
                    }
716
                }
717
            }
718
719
            // Save attachment file for inbox messages
720
            if (is_array($attachmentList)) {
721
                foreach ($attachmentList as $attachment) {
722
                    if (0 == $attachment['error']) {
723
                        $comment = $attachment['comment'];
724
                        self::saveMessageAttachmentFile(
725
                            $attachment,
726
                            $comment,
727
                            $messageId,
728
                            null,
729
                            $receiverUserId,
730
                            $group_id
731
                        );
732
                    }
733
                }
734
            }
735
736
            // Save message in the outbox for user friend or group.
737
            if (empty($group_id) && MESSAGE_STATUS_UNREAD == $status) {
738
                $params = [
739
                    'user_sender_id' => $user_sender_id,
740
                    'user_receiver_id' => $receiverUserId,
741
                    'msg_status' => MESSAGE_STATUS_OUTBOX,
742
                    'send_date' => $now,
743
                    'title' => $subject,
744
                    'content' => $content,
745
                    'group_id' => $group_id,
746
                    'parent_id' => $parent_id,
747
                    'update_date' => $now,
748
                ];
749
                $outbox_last_id = Database::insert($table, $params);
750
751
                if ($extraParams) {
752
                    $extraParams['item_id'] = $outbox_last_id;
753
                    $extraFieldValues = new ExtraFieldValue('message');
754
                    $extraFieldValues->saveFieldValues($extraParams);
755
                }
756
757
                // save attachment file for outbox messages
758
                if (is_array($attachmentList)) {
759
                    foreach ($attachmentList as $attachment) {
760
                        if (0 == $attachment['error']) {
761
                            $comment = $attachment['comment'];
762
                            self::saveMessageAttachmentFile(
763
                                $attachment,
764
                                $comment,
765
                                $outbox_last_id,
766
                                $user_sender_id
767
                            );
768
                        }
769
                    }
770
                }
771
            }
772
773
            if ($sendEmail) {
774
                $notification = new Notification();
775
                $sender_info = api_get_user_info($user_sender_id);
776
777
                // add file attachment additional attributes
778
                $attachmentAddedByMail = [];
779
                foreach ($attachmentList as $attachment) {
780
                    $attachmentAddedByMail[] = [
781
                        'path' => $attachment['tmp_name'],
782
                        'filename' => $attachment['name'],
783
                    ];
784
                }
785
786
                if (empty($group_id)) {
787
                    $type = Notification::NOTIFICATION_TYPE_MESSAGE;
788
                    if ($directMessage) {
789
                        $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
790
                    }
791
                    $notification->saveNotification(
792
                        $messageId,
793
                        $type,
794
                        [$receiverUserId],
795
                        $subject,
796
                        $content,
797
                        $sender_info,
798
                        $attachmentAddedByMail,
799
                        $smsParameters,
800
                        $forceTitleWhenSendingEmail,
801
                        $checkUrls,
802
                        $courseId
803
                    );
804
                } else {
805
                    $usergroup = new UserGroup();
806
                    $group_info = $usergroup->get($group_id);
807
                    $group_info['topic_id'] = $topic_id;
808
                    $group_info['msg_id'] = $messageId;
809
810
                    $user_list = $usergroup->get_users_by_group(
811
                        $group_id,
812
                        false,
813
                        [],
814
                        0,
815
                        1000
816
                    );
817
818
                    // Adding more sense to the message group
819
                    $subject = sprintf(get_lang('ThereIsANewMessageInTheGroupX'), $group_info['name']);
820
                    $new_user_list = [];
821
                    foreach ($user_list as $user_data) {
822
                        $new_user_list[] = $user_data['id'];
823
                    }
824
                    $group_info = [
825
                        'group_info' => $group_info,
826
                        'user_info' => $sender_info,
827
                    ];
828
                    $notification->saveNotification(
829
                        $messageId,
830
                        Notification::NOTIFICATION_TYPE_GROUP,
831
                        $new_user_list,
832
                        $subject,
833
                        $content,
834
                        $group_info,
835
                        $attachmentAddedByMail,
836
                        $smsParameters,
837
                        false,
838
                        $checkUrls,
839
                        $courseId
840
                    );
841
                }
842
            }
843
844
            return $messageId;
845
        }
846
847
        return false;
848
    }
849
850
    /**
851
     * @param int    $receiverUserId
852
     * @param int    $subject
853
     * @param string $message
854
     * @param int    $sender_id
855
     * @param bool   $sendCopyToDrhUsers send copy to related DRH users
856
     * @param bool   $directMessage
857
     * @param array  $smsParameters
858
     * @param bool   $uploadFiles        Do not upload files using the MessageManager class
859
     * @param array  $attachmentList
860
     * @param bool   $checkUrls          It checks access url of user when multiple_access_urls = true
861
     *
862
     * @return bool
863
     */
864
    public static function send_message_simple(
865
        $receiverUserId,
866
        $subject,
867
        $message,
868
        $sender_id = 0,
869
        $sendCopyToDrhUsers = false,
870
        $directMessage = false,
871
        $smsParameters = [],
872
        $uploadFiles = true,
873
        $attachmentList = [],
874
        $checkUrls = false,
875
        $courseId = null
876
    ) {
877
        $files = $_FILES ? $_FILES : [];
878
        if (false === $uploadFiles) {
879
            $files = [];
880
        }
881
        // $attachmentList must have: tmp_name, name, size keys
882
        if (!empty($attachmentList)) {
883
            $files = $attachmentList;
884
        }
885
        $result = self::send_message(
886
            $receiverUserId,
887
            $subject,
888
            $message,
889
            $files,
890
            [],
891
            null,
892
            null,
893
            null,
894
            null,
895
            $sender_id,
896
            $directMessage,
897
            0,
898
            $smsParameters,
899
            false,
900
            false,
901
            0,
902
            [],
903
            $checkUrls,
904
            $courseId
905
        );
906
907
        if ($sendCopyToDrhUsers) {
908
            $userInfo = api_get_user_info($receiverUserId);
909
            $drhList = UserManager::getDrhListFromUser($receiverUserId);
910
            if (!empty($drhList)) {
911
                foreach ($drhList as $drhInfo) {
912
                    $message = sprintf(
913
                        get_lang('CopyOfMessageSentToXUser'),
914
                        $userInfo['complete_name']
915
                    ).' <br />'.$message;
916
917
                    self::send_message_simple(
918
                        $drhInfo['id'],
919
                        $subject,
920
                        $message,
921
                        $sender_id,
922
                        false,
923
                        $directMessage,
924
                        [],
925
                        true,
926
                        [],
927
                        $checkUrls,
928
                        $courseId
929
                    );
930
                }
931
            }
932
        }
933
934
        return $result;
935
    }
936
937
    /**
938
     * Delete (or just flag) a message (and its attachment) from the table and disk.
939
     *
940
     * @param int The owner (receiver) of the message
941
     * @param int The internal ID of the message
942
     * @param bool Whether to really delete the message (true) or just mark it deleted (default/false)
943
     *
944
     * @throws Exception if file cannot be deleted in delete_message_attachment_file()
945
     *
946
     * @return bool False on error, true otherwise
947
     */
948
    public static function delete_message_by_user_receiver(int $user_receiver_id, int $id, bool $realDelete = false)
949
    {
950
        $table = Database::get_main_table(TABLE_MESSAGE);
951
952
        if (empty($id) || empty($user_receiver_id)) {
953
            return false;
954
        }
955
956
        $sql = "SELECT * FROM $table
957
                WHERE
958
                    id = $id AND
959
                    user_receiver_id = $user_receiver_id AND
960
                    msg_status <> ".MESSAGE_STATUS_OUTBOX;
961
        $rs = Database::query($sql);
962
963
        if (Database::num_rows($rs) > 0) {
964
            // Delete attachment file.
965
            self::delete_message_attachment_file($id, $user_receiver_id, null, $realDelete);
966
            if (false !== $realDelete) {
967
                // Hard delete message.
968
                $query = "DELETE FROM $table WHERE id = $id";
969
            } else {
970
                // Soft delete message.
971
                $query = "UPDATE $table
972
                      SET msg_status = ".MESSAGE_STATUS_DELETED."
973
                      WHERE
974
                        id = $id AND
975
                        user_receiver_id = $user_receiver_id ";
976
            }
977
            Database::query($query);
978
979
            return true;
980
        }
981
982
        return false;
983
    }
984
985
    /**
986
     * Set status deleted or delete the message completely.
987
     *
988
     * @author Isaac FLores Paz <[email protected]>
989
     * @author Yannick Warnier <[email protected]> - Added realDelete option
990
     *
991
     * @param   int     The user's sender ID
992
     * @param   int     The message's ID
993
     * @param   bool    whether to really delete the message (true) or just mark it deleted (default/false)
994
     *
995
     * @throws Exception if file cannot be deleted in delete_message_attachment_file()
996
     *
997
     * @return bool
998
     */
999
    public static function delete_message_by_user_sender(int $user_sender_id, int $id, bool $realDelete = false)
1000
    {
1001
        if (empty($id) || empty($user_sender_id)) {
1002
            return false;
1003
        }
1004
1005
        $table = Database::get_main_table(TABLE_MESSAGE);
1006
1007
        $sql = "SELECT * FROM $table WHERE id = $id AND user_sender_id= $user_sender_id";
1008
        $rs = Database::query($sql);
1009
1010
        if (Database::num_rows($rs) > 0) {
1011
            // delete attachment file
1012
            self::delete_message_attachment_file($id, $user_sender_id, null, $realDelete);
1013
            if (false !== $realDelete) {
1014
                // hard delete message
1015
                $sql = "DELETE FROM $table WHERE id = $id";
1016
            } else {
1017
                // soft delete message
1018
                $sql = "UPDATE $table
1019
                    SET msg_status = '".MESSAGE_STATUS_DELETED."'
1020
                    WHERE user_sender_id = $user_sender_id AND id = $id";
1021
            }
1022
            Database::query($sql);
1023
1024
            return true;
1025
        }
1026
1027
        return false;
1028
    }
1029
1030
    /**
1031
     * Saves a message attachment files.
1032
     *
1033
     * @param array $file_attach $_FILES['name']
1034
     * @param  string    a comment about the uploaded file
1035
     * @param  int        message id
1036
     * @param  int        receiver user id (optional)
1037
     * @param  int        sender user id (optional)
1038
     * @param  int        group id (optional)
1039
     */
1040
    public static function saveMessageAttachmentFile(
1041
        $file_attach,
1042
        $file_comment,
1043
        $message_id,
1044
        $receiver_user_id = 0,
1045
        $sender_user_id = 0,
1046
        $group_id = 0
1047
    ) {
1048
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1049
1050
        // Try to add an extension to the file if it hasn't one
1051
        $type = isset($file_attach['type']) ? $file_attach['type'] : '';
1052
        if (empty($type)) {
1053
            $type = DocumentManager::file_get_mime_type($file_attach['name']);
1054
        }
1055
        $new_file_name = add_ext_on_mime(stripslashes($file_attach['name']), $type);
1056
1057
        // user's file name
1058
        $file_name = $file_attach['name'];
1059
        if (!filter_extension($new_file_name)) {
1060
            Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
1061
        } else {
1062
            $new_file_name = uniqid('');
1063
            if (!empty($receiver_user_id)) {
1064
                $message_user_id = $receiver_user_id;
1065
            } else {
1066
                $message_user_id = $sender_user_id;
1067
            }
1068
1069
            // User-reserved directory where photos have to be placed.*
1070
            $userGroup = new UserGroup();
1071
            if (!empty($group_id)) {
1072
                $path_user_info = $userGroup->get_group_picture_path_by_id(
1073
                    $group_id,
1074
                    'system',
1075
                    true
1076
                );
1077
            } else {
1078
                $path_user_info['dir'] = UserManager::getUserPathById($message_user_id, 'system');
1079
            }
1080
1081
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
1082
            // If this directory does not exist - we create it.
1083
            if (!file_exists($path_message_attach)) {
1084
                @mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);
1085
            }
1086
1087
            $new_path = $path_message_attach.$new_file_name;
1088
            $fileCopied = false;
1089
            if (isset($file_attach['tmp_name']) && !empty($file_attach['tmp_name'])) {
1090
                if (is_uploaded_file($file_attach['tmp_name'])) {
1091
                    @copy($file_attach['tmp_name'], $new_path);
1092
                    $fileCopied = true;
1093
                } else {
1094
                    // 'tmp_name' can be set by the ticket or when forwarding a message
1095
                    if (file_exists($file_attach['tmp_name'])) {
1096
                        @copy($file_attach['tmp_name'], $new_path);
1097
                        $fileCopied = true;
1098
                    }
1099
                }
1100
1101
                if ('image/svg+xml' === $type) {
1102
                    sanitizeSvgFile($new_path);
1103
                }
1104
            }
1105
1106
            if ($fileCopied) {
1107
                // Storing the attachments if any
1108
                $params = [
1109
                    'filename' => $file_name,
1110
                    'comment' => $file_comment,
1111
                    'path' => $new_file_name,
1112
                    'message_id' => $message_id,
1113
                    'size' => $file_attach['size'],
1114
                ];
1115
1116
                return Database::insert($table, $params);
1117
            }
1118
        }
1119
1120
        return false;
1121
    }
1122
1123
    /**
1124
     * Delete message attachment files (logically updating the row with a suffix _DELETE_id).
1125
     *
1126
     * @param  int    message id
1127
     * @param  int    message user id (receiver user id or sender user id)
1128
     * @param  int|null   group id (optional)
1129
     * @param  bool   whether to really delete the file (true) or just mark it deleted (default/false)
1130
     *
1131
     * @throws Exception if file cannot be deleted
1132
     */
1133
    public static function delete_message_attachment_file(
1134
        int $message_id,
1135
        int $message_uid,
1136
        ?int $group_id = 0,
1137
        bool $realDelete = false
1138
    ): void {
1139
        $table_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1140
1141
        $sql = "SELECT * FROM $table_message_attach
1142
                WHERE message_id = $message_id";
1143
        $rs = Database::query($sql);
1144
        while ($row = Database::fetch_array($rs)) {
1145
            $path = $row['path'];
1146
            $attach_id = $row['id'];
1147
            $new_path = $path.'_DELETED_'.$attach_id;
1148
1149
            if (!empty($group_id)) {
1150
                $userGroup = new UserGroup();
1151
                $path_user_info = $userGroup->get_group_picture_path_by_id(
1152
                    $group_id,
1153
                    'system',
1154
                    true
1155
                );
1156
            } else {
1157
                $path_user_info['dir'] = UserManager::getUserPathById(
1158
                    $message_uid,
1159
                    'system'
1160
                );
1161
            }
1162
1163
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
1164
            if (is_file($path_message_attach.$path)) {
1165
                if ($realDelete) {
1166
                    $unlink = unlink($path_message_attach.$path);
1167
                    if (!$unlink) {
1168
                        throw new Exception('Could not delete file '.$path_message_attach.$path);
1169
                    }
1170
                    $sql = "DELETE FROM $table_message_attach
1171
                            WHERE id = $attach_id ";
1172
                } else {
1173
                    if (rename($path_message_attach.$path, $path_message_attach.$new_path)) {
1174
                        $sql = "UPDATE $table_message_attach
1175
                            SET path = '$new_path'
1176
                            WHERE id = $attach_id ";
1177
                    }
1178
                }
1179
                Database::query($sql);
1180
            }
1181
        }
1182
    }
1183
1184
    /**
1185
     * @param int $user_id
1186
     * @param int $message_id
1187
     * @param int $type
1188
     *
1189
     * @return bool
1190
     */
1191
    public static function update_message_status($user_id, $message_id, $type)
1192
    {
1193
        $user_id = (int) $user_id;
1194
        $message_id = (int) $message_id;
1195
        $type = (int) $type;
1196
1197
        if (empty($user_id) || empty($message_id)) {
1198
            return false;
1199
        }
1200
1201
        $table_message = Database::get_main_table(TABLE_MESSAGE);
1202
        $sql = "UPDATE $table_message SET
1203
                    msg_status = '$type'
1204
                WHERE
1205
                    user_receiver_id = ".$user_id." AND
1206
                    id = '".$message_id."'";
1207
        $result = Database::query($sql);
1208
1209
        return Database::affected_rows($result) > 0;
1210
    }
1211
1212
    /**
1213
     * get messages by group id.
1214
     *
1215
     * @param int $group_id group id
1216
     *
1217
     * @return array
1218
     */
1219
    public static function get_messages_by_group($group_id)
1220
    {
1221
        $group_id = (int) $group_id;
1222
1223
        if (empty($group_id)) {
1224
            return false;
1225
        }
1226
1227
        $table = Database::get_main_table(TABLE_MESSAGE);
1228
        $sql = "SELECT * FROM $table
1229
                WHERE
1230
                    group_id= $group_id AND
1231
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
1232
                ORDER BY id";
1233
        $rs = Database::query($sql);
1234
        $data = [];
1235
        if (Database::num_rows($rs) > 0) {
1236
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1237
                $data[] = $row;
1238
            }
1239
        }
1240
1241
        return $data;
1242
    }
1243
1244
    /**
1245
     * get messages by group id.
1246
     *
1247
     * @param int $group_id
1248
     * @param int $message_id
1249
     *
1250
     * @return array
1251
     */
1252
    public static function get_messages_by_group_by_message($group_id, $message_id)
1253
    {
1254
        $group_id = (int) $group_id;
1255
1256
        if (empty($group_id)) {
1257
            return false;
1258
        }
1259
1260
        $table = Database::get_main_table(TABLE_MESSAGE);
1261
        $sql = "SELECT * FROM $table
1262
                WHERE
1263
                    group_id = $group_id AND
1264
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
1265
                ORDER BY id ";
1266
1267
        $rs = Database::query($sql);
1268
        $data = [];
1269
        $parents = [];
1270
        if (Database::num_rows($rs) > 0) {
1271
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1272
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
1273
                    $parents[] = $row['id'];
1274
                    $data[] = $row;
1275
                }
1276
            }
1277
        }
1278
1279
        return $data;
1280
    }
1281
1282
    /**
1283
     * Get messages by parent id optionally with limit.
1284
     *
1285
     * @param  int        parent id
1286
     * @param  int        group id (optional)
1287
     * @param  int        offset (optional)
1288
     * @param  int        limit (optional)
1289
     *
1290
     * @return array
1291
     */
1292
    public static function getMessagesByParent($parentId, $groupId = 0, $offset = 0, $limit = 0)
1293
    {
1294
        $table = Database::get_main_table(TABLE_MESSAGE);
1295
        $parentId = (int) $parentId;
1296
1297
        if (empty($parentId)) {
1298
            return [];
1299
        }
1300
1301
        $condition_group_id = '';
1302
        if (!empty($groupId)) {
1303
            $groupId = (int) $groupId;
1304
            $condition_group_id = " AND group_id = '$groupId' ";
1305
        }
1306
1307
        $condition_limit = '';
1308
        if ($offset && $limit) {
1309
            $offset = (int) $offset;
1310
            $limit = (int) $limit;
1311
            $offset = ($offset - 1) * $limit;
1312
            $condition_limit = " LIMIT $offset,$limit ";
1313
        }
1314
1315
        $sql = "SELECT * FROM $table
1316
                WHERE
1317
                    parent_id='$parentId' AND
1318
                    msg_status NOT IN (".MESSAGE_STATUS_OUTBOX.", ".MESSAGE_STATUS_WALL_DELETE.")
1319
                    $condition_group_id
1320
                ORDER BY send_date DESC $condition_limit ";
1321
        $rs = Database::query($sql);
1322
        $data = [];
1323
        if (Database::num_rows($rs) > 0) {
1324
            while ($row = Database::fetch_array($rs)) {
1325
                $data[$row['id']] = $row;
1326
            }
1327
        }
1328
1329
        return $data;
1330
    }
1331
1332
    /**
1333
     * Gets information about messages sent.
1334
     *
1335
     * @param int
1336
     * @param int
1337
     * @param string
1338
     * @param string
1339
     *
1340
     * @return array
1341
     */
1342
    public static function get_message_data_sent(
1343
        $from,
1344
        $numberOfItems,
1345
        $column,
1346
        $direction,
1347
        $extraParams = []
1348
    ) {
1349
        $from = (int) $from;
1350
        $numberOfItems = (int) $numberOfItems;
1351
        if (!isset($direction)) {
1352
            $column = 2;
1353
            $direction = 'DESC';
1354
        } else {
1355
            $column = (int) $column;
1356
            if (!in_array($direction, ['ASC', 'DESC'])) {
1357
                $direction = 'ASC';
1358
            }
1359
        }
1360
1361
        if (!in_array($column, [0, 1, 2])) {
1362
            $column = 2;
1363
        }
1364
        $table = Database::get_main_table(TABLE_MESSAGE);
1365
        $request = api_is_xml_http_request();
1366
        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
1367
        $keywordCondition = '';
1368
        if (!empty($keyword)) {
1369
            $keyword = Database::escape_string($keyword);
1370
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1371
        }
1372
1373
        $sql = "SELECT
1374
                    id as col0,
1375
                    title as col1,
1376
                    send_date as col2,
1377
                    user_receiver_id,
1378
                    msg_status,
1379
                    user_sender_id
1380
                FROM $table
1381
                WHERE
1382
                    user_sender_id = ".api_get_user_id()." AND
1383
                    msg_status = ".MESSAGE_STATUS_OUTBOX."
1384
                    $keywordCondition
1385
                ORDER BY col$column $direction
1386
                LIMIT $from, $numberOfItems";
1387
        $result = Database::query($sql);
1388
1389
        $message_list = [];
1390
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1391
            $messageId = $row['col0'];
1392
            $title = $row['col1'];
1393
            $sendDate = $row['col2'];
1394
            $senderId = $row['user_sender_id'];
1395
1396
            if ($request === true) {
1397
                $message[0] = '<input type="checkbox" value='.$messageId.' name="out[]">';
1398
            } else {
1399
                $message[0] = $messageId;
1400
            }
1401
1402
            $class = 'class = "read"';
1403
            $title = Security::remove_XSS($title);
1404
            $userInfo = api_get_user_info($senderId);
1405
            if ($request === true) {
1406
                $message[1] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.
1407
                    $userInfo['complete_name_with_username'].'</a>';
1408
                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace(
1409
                        "\\",
1410
                        "",
1411
                        $title
1412
                    ).'</a>';
1413
                //date stays the same
1414
                $message[3] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1415
                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(
1416
                        get_lang('DeleteMessage')
1417
                    ).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
1418
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1419
            } else {
1420
                $message[1] = '<a '.$class.' onclick="show_sent_message('.$messageId.')" href="../messages/view_message.php?id_send='.$messageId.'">'.$title.'</a><br />'.$userInfo['complete_name_with_username'];
1421
                $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1422
                $message[3] = '<a title="'.addslashes(
1423
                        get_lang('DeleteMessage')
1424
                    ).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(
1425
                        api_htmlentities(get_lang('ConfirmDeleteMessage'))
1426
                    )."'".')) return false;" >'.
1427
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1428
            }
1429
1430
            $message_list[] = $message;
1431
        }
1432
1433
        return $message_list;
1434
    }
1435
1436
    /**
1437
     * display message box in the inbox.
1438
     *
1439
     * @param int $messageId
1440
     * @param int $type
1441
     *
1442
     * @todo replace numbers with letters in the $row array pff...
1443
     *
1444
     * @return string html with the message content
1445
     */
1446
    public static function showMessageBox($messageId, $type)
1447
    {
1448
        $messageId = (int) $messageId;
1449
1450
        if (empty($messageId) || empty($type)) {
1451
            return '';
1452
        }
1453
        $currentUserId = api_get_user_id();
1454
1455
        $table = Database::get_main_table(TABLE_MESSAGE);
1456
1457
        if (empty($type)) {
1458
            return '';
1459
        }
1460
1461
        switch ($type) {
1462
            case self::MESSAGE_TYPE_OUTBOX:
1463
                $status = MESSAGE_STATUS_OUTBOX;
1464
                $userCondition = " user_sender_id = $currentUserId AND ";
1465
                break;
1466
            case self::MESSAGE_TYPE_INBOX:
1467
                $status = MESSAGE_STATUS_NEW;
1468
                $userCondition = " user_receiver_id = $currentUserId AND ";
1469
1470
                $query = "UPDATE $table SET
1471
                          msg_status = '".MESSAGE_STATUS_NEW."'
1472
                          WHERE id = $messageId ";
1473
                Database::query($query);
1474
                break;
1475
            case self::MESSAGE_TYPE_PROMOTED:
1476
                $status = MESSAGE_STATUS_PROMOTED;
1477
                $userCondition = " user_receiver_id = $currentUserId AND ";
1478
                break;
1479
        }
1480
1481
        if (empty($userCondition)) {
1482
            return '';
1483
        }
1484
1485
        $query = "SELECT * FROM $table
1486
                  WHERE
1487
                    id = $messageId AND
1488
                    $userCondition
1489
                    msg_status = $status";
1490
        $result = Database::query($query);
1491
        $row = Database::fetch_array($result, 'ASSOC');
1492
1493
        if (empty($row)) {
1494
            return '';
1495
        }
1496
1497
        /* get previous message */
1498
        $query = "SELECT id FROM $table
1499
                  WHERE
1500
                  $userCondition
1501
                       id < $messageId
1502
                     order by id DESC limit 1 ";
1503
        $result = Database::query($query);
1504
        $rowPrevMessage = Database::fetch_array($result, 'ASSOC');
1505
        $idPrevMessage = (int) isset($rowPrevMessage['id']) ? $rowPrevMessage['id'] : 0;
1506
1507
        /* get next message */
1508
        $query = "SELECT id FROM $table
1509
                  WHERE
1510
                  $userCondition
1511
                       id > $messageId
1512
                     order by id ASC limit 1 ";
1513
        $result = Database::query($query);
1514
        $rowNextMessage = Database::fetch_array($result, 'ASSOC');
1515
        $idNextMessage = (int) isset($rowNextMessage['id']) ? $rowNextMessage['id'] : 0;
1516
1517
        $user_sender_id = $row['user_sender_id'];
1518
1519
        // get file attachments by message id
1520
        $files_attachments = self::getAttachmentLinkList($messageId, $type);
1521
1522
        $row['content'] = str_replace('</br>', '<br />', $row['content']);
1523
        $title = Security::remove_XSS($row['title'], STUDENT, true);
1524
        $content = Security::remove_XSS($row['content'], STUDENT, true);
1525
1526
        $name = get_lang('UnknownUser');
1527
        $fromUser = api_get_user_info($user_sender_id);
1528
        $userImage = '';
1529
        if (!empty($user_sender_id) && !empty($fromUser)) {
1530
            $name = $fromUser['complete_name_with_username'];
1531
            $userImage = Display::img(
1532
                $fromUser['avatar_small'],
1533
                $name,
1534
                ['title' => $name, 'class' => 'img-responsive img-circle', 'style' => 'max-width:35px'],
1535
                false
1536
            );
1537
        }
1538
1539
        $message_content = Display::page_subheader(str_replace("\\", '', $title));
1540
1541
        $receiverUserInfo = [];
1542
        if (!empty($row['user_receiver_id'])) {
1543
            $receiverUserInfo = api_get_user_info($row['user_receiver_id']);
1544
        }
1545
1546
        if ('true' === api_get_setting('allow_social_tool')) {
1547
            $message_content .= '<ul class="list-message">';
1548
1549
            if (!empty($user_sender_id)) {
1550
                $message_content .= '<li>'.$userImage.'</li>';
1551
                $message_content .= '<li>';
1552
                $message_content .= Display::url(
1553
                    $name,
1554
                    api_get_path(WEB_PATH).'main/social/profile.php?u='.$user_sender_id
1555
                );
1556
            } else {
1557
                $message_content .= '<li>'.$name;
1558
            }
1559
1560
            switch ($type) {
1561
                case self::MESSAGE_TYPE_INBOX:
1562
                    $message_content .= '&nbsp;'.api_strtolower(get_lang('To')).'&nbsp;'.get_lang('Me');
1563
                    break;
1564
                case self::MESSAGE_TYPE_OUTBOX:
1565
                    if (!empty($receiverUserInfo)) {
1566
                        $message_content .= '&nbsp;'.api_strtolower(
1567
                                get_lang('To')
1568
                            ).'&nbsp;<b>'.$receiverUserInfo['complete_name_with_username'].'</b></li>';
1569
                    }
1570
                    break;
1571
                case self::MESSAGE_TYPE_PROMOTED:
1572
                    break;
1573
            }
1574
1575
            $message_content .= '&nbsp;<li>'.Display::dateToStringAgoAndLongDate($row['send_date']).'</li>';
1576
            $message_content .= '</ul>';
1577
        } else {
1578
            switch ($type) {
1579
                case self::MESSAGE_TYPE_INBOX:
1580
                    $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1581
                        get_lang('Me').'</b>';
1582
                    break;
1583
                case self::MESSAGE_TYPE_OUTBOX:
1584
                    $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1585
                        $receiverUserInfo['complete_name_with_username'].'</b>';
1586
                    break;
1587
            }
1588
        }
1589
1590
        $message_content .= '
1591
		        <hr>
1592
		        <table width="100%">
1593
		            <tr>
1594
		              <td valign=top class="view-message-content">'.str_replace("\\", "", $content).'</td>
1595
		            </tr>
1596
		        </table>
1597
		        <div id="message-attach">'.(!empty($files_attachments) ? implode('<br />', $files_attachments) : '').'</div>
1598
		        <hr>';
1599
1600
        if (api_get_configuration_value('enable_message_tags')) {
1601
            $message_content .= self::addTagsForm($messageId, $type);
1602
        }
1603
1604
        $message_content .= '<div style="padding: 15px 0 5px 0;">';
1605
1606
        $social_link = '';
1607
        if (isset($_GET['f']) && $_GET['f'] == 'social') {
1608
            $social_link = 'f=social';
1609
        }
1610
1611
        $eventLink = Display::url(
1612
            Display::return_icon('new_event.png', get_lang('New event')),
1613
            api_get_path(WEB_CODE_PATH).'calendar/agenda.php?action=add&type=personal&m='.$messageId
1614
        ).PHP_EOL;
1615
1616
        switch ($type) {
1617
            case self::MESSAGE_TYPE_OUTBOX:
1618
                $message_content .= '<a href="outbox.php?'.$social_link.'">'.
1619
                    Display::return_icon('back.png', get_lang('ReturnToOutbox')).'</a> &nbsp';
1620
                $message_content .= $eventLink;
1621
                $message_content .= '<a href="outbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1622
                    Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp';
1623
                break;
1624
            case self::MESSAGE_TYPE_INBOX:
1625
                $message_content .= '<a href="inbox.php?'.$social_link.'">'.
1626
                    Display::return_icon('icons/22/arrow_up.png', get_lang('ReturnToInbox')).'</a>&nbsp;';
1627
                $message_content .= '<a href="new_message.php?re_id='.$messageId.'&'.$social_link.'">'.
1628
                    Display::return_icon('message_reply.png', get_lang('ReplyToMessage')).'</a>&nbsp;';
1629
                $message_content .= $eventLink;
1630
                $message_content .= '<a href="inbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1631
                    Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp;';
1632
                if ($idPrevMessage != 0) {
1633
                    $message_content .= '<a title="'.get_lang('PrevMessage').'" href="view_message.php?type='.$type.'&id='.$idPrevMessage.'" ">'.Display::return_icon('icons/22/back.png', get_lang('ScormPrevious')).'</a> &nbsp';
1634
                }
1635
                if ($idNextMessage != 0) {
1636
                    $message_content .= '<a title="'.get_lang('NextMessage').'" href="view_message.php?type='.$type.'&id='.$idNextMessage.'">'.Display::return_icon('icons/22/move.png', get_lang('ScormNext')).'</a> &nbsp';
1637
                }
1638
                break;
1639
        }
1640
1641
        $message_content .= '</div>';
1642
1643
        return $message_content;
1644
    }
1645
1646
    /**
1647
     * get user id by user email.
1648
     *
1649
     * @param string $user_email
1650
     *
1651
     * @return int user id
1652
     */
1653
    public static function get_user_id_by_email($user_email)
1654
    {
1655
        $table = Database::get_main_table(TABLE_MAIN_USER);
1656
        $sql = 'SELECT user_id
1657
                FROM '.$table.'
1658
                WHERE email="'.Database::escape_string($user_email).'";';
1659
        $rs = Database::query($sql);
1660
        $row = Database::fetch_array($rs, 'ASSOC');
1661
        if (isset($row['user_id'])) {
1662
            return $row['user_id'];
1663
        }
1664
1665
        return null;
1666
    }
1667
1668
    /**
1669
     * Displays messages of a group with nested view.
1670
     *
1671
     * @param int $groupId
1672
     *
1673
     * @return string
1674
     */
1675
    public static function display_messages_for_group($groupId)
1676
    {
1677
        global $my_group_role;
1678
1679
        $rows = self::get_messages_by_group($groupId);
1680
        $topics_per_page = 10;
1681
        $html_messages = '';
1682
        $query_vars = ['id' => $groupId, 'topics_page_nr' => 0];
1683
1684
        if (is_array($rows) && count($rows) > 0) {
1685
            // prepare array for topics with its items
1686
            $topics = [];
1687
            $x = 0;
1688
            foreach ($rows as $index => $value) {
1689
                if (empty($value['parent_id'])) {
1690
                    $topics[$value['id']] = $value;
1691
                }
1692
            }
1693
1694
            $new_topics = [];
1695
1696
            foreach ($topics as $id => $value) {
1697
                $rows = null;
1698
                $rows = self::get_messages_by_group_by_message($groupId, $value['id']);
1699
                if (!empty($rows)) {
1700
                    $count = count(self::calculate_children($rows, $value['id']));
1701
                } else {
1702
                    $count = 0;
1703
                }
1704
                $value['count'] = $count;
1705
                $new_topics[$id] = $value;
1706
            }
1707
1708
            $array_html = [];
1709
            foreach ($new_topics as $index => $topic) {
1710
                $html = '';
1711
                // topics
1712
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1713
                $name = $user_sender_info['complete_name'];
1714
                $html .= '<div class="groups-messages">';
1715
                $html .= '<div class="row">';
1716
1717
                $items = $topic['count'];
1718
                $reply_label = ($items == 1) ? get_lang('GroupReply') : get_lang('GroupReplies');
1719
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
1720
                $topic['title'] = trim($topic['title']);
1721
1722
                if (empty($topic['title'])) {
1723
                    $topic['title'] = get_lang('Untitled');
1724
                }
1725
1726
                $html .= '<div class="col-xs-8 col-md-10">';
1727
                $html .= Display::tag(
1728
                    'h4',
1729
                    Display::url(
1730
                        Security::remove_XSS($topic['title'], STUDENT, true),
1731
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$groupId.'&topic_id='.$topic['id']
1732
                    ),
1733
                    ['class' => 'title']
1734
                );
1735
                $actions = '';
1736
                if ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1737
                    $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1738
                ) {
1739
                    $actions = '<br />'.Display::url(
1740
                            get_lang('Delete'),
1741
                            api_get_path(
1742
                                WEB_CODE_PATH
1743
                            ).'social/group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic['id'],
1744
                            ['class' => 'btn btn-default']
1745
                        );
1746
                }
1747
1748
                $date = '';
1749
                if ($topic['send_date'] != $topic['update_date']) {
1750
                    if (!empty($topic['update_date'])) {
1751
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1752
                                'LastUpdate'
1753
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
1754
                    }
1755
                } else {
1756
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1757
                            'Created'
1758
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
1759
                }
1760
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
1761
                $html .= '</div>';
1762
1763
                $image = $user_sender_info['avatar'];
1764
1765
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
1766
                $user_info .= '<div class="name"><a href="'.api_get_path(
1767
                        WEB_PATH
1768
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
1769
1770
                $html .= '<div class="col-xs-4 col-md-2">';
1771
                $html .= $user_info;
1772
                $html .= '</div>';
1773
                $html .= '</div>';
1774
                $html .= '</div>';
1775
1776
                $array_html[] = [$html];
1777
            }
1778
1779
            // grids for items and topics  with paginations
1780
            $html_messages .= Display::return_sortable_grid(
1781
                'topics',
1782
                [],
1783
                $array_html,
1784
                [
1785
                    'hide_navigation' => false,
1786
                    'per_page' => $topics_per_page,
1787
                ],
1788
                $query_vars,
1789
                false,
1790
                [true, true, true, false],
1791
                false
1792
            );
1793
        }
1794
1795
        return $html_messages;
1796
    }
1797
1798
    /**
1799
     * Displays messages of a group with nested view.
1800
     *
1801
     * @param $groupId
1802
     * @param $topic_id
1803
     *
1804
     * @return string
1805
     */
1806
    public static function display_message_for_group($groupId, $topic_id)
1807
    {
1808
        global $my_group_role;
1809
        $main_message = self::get_message_by_id($topic_id);
1810
        if (empty($main_message)) {
1811
            return false;
1812
        }
1813
1814
        $webCodePath = api_get_path(WEB_CODE_PATH);
1815
        $iconCalendar = Display::returnFontAwesomeIcon('calendar');
1816
1817
        $langEdit = get_lang('Edit');
1818
        $langReply = get_lang('Reply');
1819
        $langLastUpdated = get_lang('LastUpdated');
1820
        $langCreated = get_lang('Created');
1821
1822
        $rows = self::get_messages_by_group_by_message($groupId, $topic_id);
1823
        $rows = self::calculate_children($rows, $topic_id);
1824
        $current_user_id = api_get_user_id();
1825
1826
        $items_per_page = 50;
1827
        $query_vars = ['id' => $groupId, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
1828
1829
        // Main message
1830
        $links = '';
1831
        $main_content = '';
1832
        $html = '';
1833
        $items_page_nr = null;
1834
1835
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1836
        $files_attachments = self::getAttachmentLinkList($main_message['id'], 0);
1837
        $name = $user_sender_info['complete_name'];
1838
1839
        $topic_page_nr = isset($_GET['topics_page_nr']) ? (int) $_GET['topics_page_nr'] : null;
1840
1841
        $links .= '<div class="pull-right">';
1842
        $links .= '<div class="btn-group btn-group-sm">';
1843
1844
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1845
            $main_message['user_sender_id'] == $current_user_id
1846
        ) {
1847
            $urlEdit = $webCodePath.'social/message_for_group_form.inc.php?'
1848
                .http_build_query(
1849
                    [
1850
                        'user_friend' => $current_user_id,
1851
                        'group_id' => $groupId,
1852
                        'message_id' => $main_message['id'],
1853
                        'action' => 'edit_message_group',
1854
                        'anchor_topic' => 'topic_'.$main_message['id'],
1855
                        'topics_page_nr' => $topic_page_nr,
1856
                        'items_page_nr' => $items_page_nr,
1857
                        'topic_id' => $main_message['id'],
1858
                    ]
1859
                );
1860
1861
            $links .= Display::toolbarButton(
1862
                $langEdit,
1863
                $urlEdit,
1864
                'pencil',
1865
                'default',
1866
                ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1867
                false
1868
            );
1869
        }
1870
1871
        $links .= self::getLikesButton($main_message['id'], $current_user_id, $groupId);
1872
1873
        $urlReply = $webCodePath.'social/message_for_group_form.inc.php?'
1874
            .http_build_query(
1875
                [
1876
                    'user_friend' => $current_user_id,
1877
                    'group_id' => $groupId,
1878
                    'message_id' => $main_message['id'],
1879
                    'action' => 'reply_message_group',
1880
                    'anchor_topic' => 'topic_'.$main_message['id'],
1881
                    'topics_page_nr' => $topic_page_nr,
1882
                    'topic_id' => $main_message['id'],
1883
                ]
1884
            );
1885
1886
        $links .= Display::toolbarButton(
1887
            $langReply,
1888
            $urlReply,
1889
            'commenting',
1890
            'default',
1891
            ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1892
            false
1893
        );
1894
1895
        if (api_is_platform_admin()) {
1896
            $links .= Display::toolbarButton(
1897
                get_lang('Delete'),
1898
                'group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic_id,
1899
                'trash',
1900
                'default',
1901
                [],
1902
                false
1903
            );
1904
        }
1905
1906
        $links .= '</div>';
1907
        $links .= '</div>';
1908
1909
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
1910
1911
        $userPicture = $user_sender_info['avatar'];
1912
        $main_content .= '<div class="row">';
1913
        $main_content .= '<div class="col-md-2">';
1914
        $main_content .= '<div class="avatar-author">';
1915
        $main_content .= Display::img(
1916
            $userPicture,
1917
            $name,
1918
            ['width' => '60px', 'class' => 'img-responsive img-circle'],
1919
            false
1920
        );
1921
        $main_content .= '</div>';
1922
        $main_content .= '</div>';
1923
1924
        $date = '';
1925
        if ($main_message['send_date'] != $main_message['update_date']) {
1926
            if (!empty($main_message['update_date'])) {
1927
                $date = '<div class="date"> '
1928
                    ."$iconCalendar $langLastUpdated "
1929
                    .Display::dateToStringAgoAndLongDate($main_message['update_date'])
1930
                    .'</div>';
1931
            }
1932
        } else {
1933
            $date = '<div class="date"> '
1934
                ."$iconCalendar $langCreated "
1935
                .Display::dateToStringAgoAndLongDate($main_message['send_date'])
1936
                .'</div>';
1937
        }
1938
        $attachment = '<div class="message-attach">'
1939
            .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
1940
            .'</div>';
1941
        $main_content .= '<div class="col-md-10">';
1942
        $user_link = Display::url(
1943
            $name,
1944
            $webCodePath.'social/profile.php?u='.$main_message['user_sender_id']
1945
        );
1946
        $main_content .= '<div class="message-content"> ';
1947
        $main_content .= '<div class="username">'.$user_link.'</div>';
1948
        $main_content .= $date;
1949
        $main_content .= '<div class="message">'
1950
            .Security::remove_XSS($main_message['content'], STUDENT, true)
1951
            .$attachment.'</div></div>';
1952
        $main_content .= '</div>';
1953
        $main_content .= '</div>';
1954
1955
        $html .= Display::div(
1956
            Display::div(
1957
                $title.$main_content,
1958
                ['class' => 'message-topic']
1959
            ),
1960
            ['class' => 'sm-groups-message']
1961
        );
1962
1963
        $topic_id = $main_message['id'];
1964
1965
        if (is_array($rows) && count($rows) > 0) {
1966
            $topics = $rows;
1967
            $array_html_items = [];
1968
1969
            foreach ($topics as $index => $topic) {
1970
                if (empty($topic['id'])) {
1971
                    continue;
1972
                }
1973
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr'])
1974
                    ? (int) $_GET['items_'.$topic['id'].'_page_nr']
1975
                    : null;
1976
                $links = '';
1977
                $links .= '<div class="pull-right">';
1978
                $html_items = '';
1979
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1980
                $files_attachments = self::getAttachmentLinkList($topic['id'], 0);
1981
                $name = $user_sender_info['complete_name'];
1982
1983
                $links .= '<div class="btn-group btn-group-sm">';
1984
                if (
1985
                    ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1986
                        $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1987
                    ) ||
1988
                    $topic['user_sender_id'] == $current_user_id
1989
                ) {
1990
                    $links .= Display::toolbarButton(
1991
                        $langEdit,
1992
                        $webCodePath.'social/message_for_group_form.inc.php?'
1993
                            .http_build_query(
1994
                                [
1995
                                    'user_friend' => $current_user_id,
1996
                                    'group_id' => $groupId,
1997
                                    'message_id' => $topic['id'],
1998
                                    'action' => 'edit_message_group',
1999
                                    'anchor_topic' => 'topic_'.$topic_id,
2000
                                    'topics_page_nr' => $topic_page_nr,
2001
                                    'items_page_nr' => $items_page_nr,
2002
                                    'topic_id' => $topic_id,
2003
                                ]
2004
                            ),
2005
                        'pencil',
2006
                        'default',
2007
                        ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
2008
                        false
2009
                    );
2010
                }
2011
2012
                $links .= self::getLikesButton($topic['id'], $current_user_id, $groupId);
2013
2014
                $links .= Display::toolbarButton(
2015
                    $langReply,
2016
                    $webCodePath.'social/message_for_group_form.inc.php?'
2017
                        .http_build_query(
2018
                            [
2019
                                'user_friend' => $current_user_id,
2020
                                'group_id' => $groupId,
2021
                                'message_id' => $topic['id'],
2022
                                'action' => 'reply_message_group',
2023
                                'anchor_topic' => 'topic_'.$topic_id,
2024
                                'topics_page_nr' => $topic_page_nr,
2025
                                'items_page_nr' => $items_page_nr,
2026
                                'topic_id' => $topic_id,
2027
                            ]
2028
                        ),
2029
                    'commenting',
2030
                    'default',
2031
                    ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
2032
                    false
2033
                );
2034
                $links .= '</div>';
2035
                $links .= '</div>';
2036
2037
                $userPicture = $user_sender_info['avatar'];
2038
                $user_link = Display::url(
2039
                    $name,
2040
                    $webCodePath.'social/profile.php?u='.$topic['user_sender_id']
2041
                );
2042
                $html_items .= '<div class="row">';
2043
                $html_items .= '<div class="col-md-2">';
2044
                $html_items .= '<div class="avatar-author">';
2045
                $html_items .= Display::img(
2046
                    $userPicture,
2047
                    $name,
2048
                    ['width' => '60px', 'class' => 'img-responsive img-circle'],
2049
                    false
2050
                );
2051
                $html_items .= '</div>';
2052
                $html_items .= '</div>';
2053
2054
                $date = '';
2055
                if ($topic['send_date'] != $topic['update_date']) {
2056
                    if (!empty($topic['update_date'])) {
2057
                        $date = '<div class="date"> '
2058
                            ."$iconCalendar $langLastUpdated "
2059
                            .Display::dateToStringAgoAndLongDate($topic['update_date'])
2060
                            .'</div>';
2061
                    }
2062
                } else {
2063
                    $date = '<div class="date"> '
2064
                        ."$iconCalendar $langCreated "
2065
                        .Display::dateToStringAgoAndLongDate($topic['send_date'])
2066
                        .'</div>';
2067
                }
2068
                $attachment = '<div class="message-attach">'
2069
                    .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
2070
                    .'</div>';
2071
                $html_items .= '<div class="col-md-10">'
2072
                    .'<div class="message-content">'
2073
                    .$links
2074
                    .'<div class="username">'.$user_link.'</div>'
2075
                    .$date
2076
                    .'<div class="message">'
2077
                    .Security::remove_XSS($topic['content'], STUDENT, true)
2078
                    .'</div>'.$attachment.'</div>'
2079
                    .'</div>'
2080
                    .'</div>';
2081
2082
                $base_padding = 20;
2083
2084
                if (0 == $topic['indent_cnt']) {
2085
                    $indent = $base_padding;
2086
                } else {
2087
                    $indent = (int) $topic['indent_cnt'] * $base_padding + $base_padding;
2088
                }
2089
2090
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
2091
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
2092
                $array_html_items[] = [$html_items];
2093
            }
2094
2095
            // grids for items with paginations
2096
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
2097
            $visibility = [true, true, true, false];
2098
2099
            $style_class = [
2100
                'item' => ['class' => 'user-post'],
2101
                'main' => ['class' => 'user-list'],
2102
            ];
2103
            if (!empty($array_html_items)) {
2104
                $html .= Display::return_sortable_grid(
2105
                    'items_'.$topic['id'],
2106
                    [],
2107
                    $array_html_items,
2108
                    $options,
2109
                    $query_vars,
2110
                    null,
2111
                    $visibility,
2112
                    false,
2113
                    $style_class
2114
                );
2115
            }
2116
        }
2117
2118
        return $html;
2119
    }
2120
2121
    /**
2122
     * Add children to messages by id is used for nested view messages.
2123
     *
2124
     * @param array $rows rows of messages
2125
     *
2126
     * @return array $first_seed new list adding the item children
2127
     */
2128
    public static function calculate_children($rows, $first_seed)
2129
    {
2130
        $rows_with_children = [];
2131
        foreach ($rows as $row) {
2132
            $rows_with_children[$row["id"]] = $row;
2133
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
2134
        }
2135
        $rows = $rows_with_children;
2136
        $sorted_rows = [0 => []];
2137
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
2138
        unset($sorted_rows[0]);
2139
2140
        return $sorted_rows;
2141
    }
2142
2143
    /**
2144
     * Sort recursively the messages, is used for for nested view messages.
2145
     *
2146
     * @param array  original rows of messages
2147
     * @param array  list recursive of messages
2148
     * @param int   seed for calculate the indent
2149
     * @param int   indent for nested view
2150
     */
2151
    public static function message_recursive_sort(
2152
        $rows,
2153
        &$messages,
2154
        $seed = 0,
2155
        $indent = 0
2156
    ) {
2157
        if ($seed > 0 && isset($rows[$seed]["id"])) {
2158
            $messages[$rows[$seed]["id"]] = $rows[$seed];
2159
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
2160
            $indent++;
2161
        }
2162
2163
        if (isset($rows[$seed]["children"])) {
2164
            foreach ($rows[$seed]["children"] as $child) {
2165
                self::message_recursive_sort($rows, $messages, $child, $indent);
2166
            }
2167
        }
2168
    }
2169
2170
    /**
2171
     * @param int $messageId
2172
     *
2173
     * @return array
2174
     */
2175
    public static function getAttachmentList($messageId)
2176
    {
2177
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2178
        $messageId = (int) $messageId;
2179
2180
        if (empty($messageId)) {
2181
            return [];
2182
        }
2183
2184
        $messageInfo = self::get_message_by_id($messageId);
2185
2186
        if (empty($messageInfo)) {
2187
            return [];
2188
        }
2189
2190
        $attachmentDir = UserManager::getUserPathById($messageInfo['user_receiver_id'], 'system');
2191
        $attachmentDir .= 'message_attachments/';
2192
2193
        $sql = "SELECT * FROM $table
2194
                WHERE message_id = '$messageId'";
2195
        $result = Database::query($sql);
2196
        $files = [];
2197
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2198
            $row['file_source'] = '';
2199
            if (file_exists($attachmentDir.$row['path'])) {
2200
                $row['file_source'] = $attachmentDir.$row['path'];
2201
            }
2202
            $files[] = $row;
2203
        }
2204
2205
        return $files;
2206
    }
2207
2208
    /**
2209
     * Get array of links (download) for message attachment files.
2210
     *
2211
     * @param int $messageId
2212
     * @param int $type
2213
     *
2214
     * @return array
2215
     */
2216
    public static function getAttachmentLinkList($messageId, $type)
2217
    {
2218
        $files = self::getAttachmentList($messageId);
2219
        // get file attachments by message id
2220
        $list = [];
2221
        if ($files) {
2222
            $attachIcon = Display::return_icon('attachment.gif', '');
2223
            $archiveURL = api_get_path(WEB_CODE_PATH).'messages/download.php?type='.$type.'&file=';
2224
            foreach ($files as $row_file) {
2225
                $archiveFile = $row_file['path'];
2226
                $filename = $row_file['filename'];
2227
                $size = format_file_size($row_file['size']);
2228
                $comment = Security::remove_XSS($row_file['comment']);
2229
                $filename = Security::remove_XSS($filename);
2230
                $link = Display::url($filename, $archiveURL.$archiveFile);
2231
                $comment = !empty($comment) ? '&nbsp;-&nbsp;<i>'.$comment.'</i>' : '';
2232
2233
                $attachmentLine = $attachIcon.'&nbsp;'.$link.'&nbsp;('.$size.')'.$comment;
2234
                if ($row_file['comment'] === 'audio_message') {
2235
                    $attachmentLine = '<audio src="'.$archiveURL.$archiveFile.'"/>';
2236
                }
2237
                $list[] = $attachmentLine;
2238
            }
2239
        }
2240
2241
        return $list;
2242
    }
2243
2244
    /**
2245
     * Get message list by id.
2246
     *
2247
     * @param int $messageId
2248
     *
2249
     * @return array
2250
     */
2251
    public static function get_message_by_id($messageId)
2252
    {
2253
        $table = Database::get_main_table(TABLE_MESSAGE);
2254
        $messageId = (int) $messageId;
2255
        $sql = "SELECT * FROM $table
2256
                WHERE
2257
                    id = '$messageId' AND
2258
                    msg_status <> '".MESSAGE_STATUS_DELETED."' ";
2259
        $res = Database::query($sql);
2260
        $item = [];
2261
        if (Database::num_rows($res) > 0) {
2262
            $item = Database::fetch_array($res, 'ASSOC');
2263
        }
2264
2265
        return $item;
2266
    }
2267
2268
    /**
2269
     * @return string
2270
     */
2271
    public static function generate_message_form()
2272
    {
2273
        $form = new FormValidator('send_message');
2274
        $form->addText(
2275
            'subject',
2276
            get_lang('Subject'),
2277
            false,
2278
            ['id' => 'subject_id']
2279
        );
2280
        $form->addTextarea(
2281
            'content',
2282
            get_lang('Message'),
2283
            ['id' => 'content_id', 'rows' => '5']
2284
        );
2285
2286
        return $form->returnForm();
2287
    }
2288
2289
    /**
2290
     * @return string
2291
     */
2292
    public static function generate_invitation_form()
2293
    {
2294
        $form = new FormValidator('send_invitation');
2295
        $form->addTextarea(
2296
            'content',
2297
            get_lang('AddPersonalMessage'),
2298
            ['id' => 'content_invitation_id', 'rows' => 5]
2299
        );
2300
2301
        return $form->returnForm();
2302
    }
2303
2304
    /**
2305
     * @param string $type
2306
     * @param string $keyword
2307
     * @param array  $actions
2308
     *
2309
     * @return string
2310
     */
2311
    public static function getMessageGrid($type, $keyword, $actions = [], array $searchTags = [])
2312
    {
2313
        $html = '';
2314
        // display sortable table with messages of the current user
2315
        $table = new SortableTable(
2316
            'message_inbox',
2317
            ['MessageManager', 'getNumberOfMessages'],
2318
            ['MessageManager', 'getMessageData'],
2319
            2,
2320
            20,
2321
            'DESC'
2322
        );
2323
        $table->setDataFunctionParams(
2324
            ['keyword' => $keyword, 'type' => $type, 'actions' => $actions, 'tags' => $searchTags]
2325
        );
2326
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2327
        $table->set_header(1, get_lang('Messages'), false);
2328
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2329
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:120px;']);
2330
2331
        if (isset($_REQUEST['f']) && $_REQUEST['f'] === 'social') {
2332
            $parameters['f'] = 'social';
2333
            $table->set_additional_parameters($parameters);
2334
        }
2335
2336
        $defaultActions = [
2337
            'delete' => get_lang('DeleteSelectedMessages'),
2338
            'mark_as_unread' => get_lang('MailMarkSelectedAsUnread'),
2339
            'mark_as_read' => get_lang('MailMarkSelectedAsRead'),
2340
        ];
2341
2342
        if (!in_array('delete', $actions)) {
2343
            unset($defaultActions['delete']);
2344
        }
2345
        if (!in_array('mark_as_unread', $actions)) {
2346
            unset($defaultActions['mark_as_unread']);
2347
        }
2348
        if (!in_array('mark_as_read', $actions)) {
2349
            unset($defaultActions['mark_as_read']);
2350
        }
2351
2352
        $table->set_form_actions($defaultActions);
2353
2354
        $html .= $table->return_table();
2355
2356
        return $html;
2357
    }
2358
2359
    /**
2360
     * @param string $keyword
2361
     *
2362
     * @return string
2363
     */
2364
    public static function inboxDisplay($keyword = '', array $searchTags = [])
2365
    {
2366
        $success = get_lang('SelectedMessagesDeleted');
2367
        $success_read = get_lang('SelectedMessagesRead');
2368
        $success_unread = get_lang('SelectedMessagesUnRead');
2369
        $currentUserId = api_get_user_id();
2370
2371
        if (isset($_REQUEST['action'])) {
2372
            switch ($_REQUEST['action']) {
2373
                case 'mark_as_unread':
2374
                    if (is_array($_POST['id'])) {
2375
                        foreach ($_POST['id'] as $index => $messageId) {
2376
                            self::update_message_status(
2377
                                $currentUserId,
2378
                                $messageId,
2379
                                MESSAGE_STATUS_UNREAD
2380
                            );
2381
                        }
2382
                    }
2383
                    Display::addFlash(Display::return_message(
2384
                        $success_unread,
2385
                        'normal',
2386
                        false
2387
                    ));
2388
                    break;
2389
                case 'mark_as_read':
2390
                    if (is_array($_POST['id'])) {
2391
                        foreach ($_POST['id'] as $index => $messageId) {
2392
                            self::update_message_status(
2393
                                $currentUserId,
2394
                                $messageId,
2395
                                MESSAGE_STATUS_NEW
2396
                            );
2397
                        }
2398
                    }
2399
                    Display::addFlash(Display::return_message(
2400
                        $success_read,
2401
                        'normal',
2402
                        false
2403
                    ));
2404
                    break;
2405
                case 'delete':
2406
                    foreach ($_POST['id'] as $index => $messageId) {
2407
                        self::delete_message_by_user_receiver($currentUserId, $messageId);
2408
                    }
2409
                    Display::addFlash(Display::return_message(
2410
                        $success,
2411
                        'normal',
2412
                        false
2413
                    ));
2414
                    break;
2415
                case 'deleteone':
2416
                    $result = self::delete_message_by_user_receiver($currentUserId, $_GET['id']);
2417
                    if ($result) {
2418
                        Display::addFlash(
2419
                            Display::return_message(
2420
                                $success,
2421
                                'confirmation',
2422
                                false
2423
                            )
2424
                        );
2425
                    }
2426
                    break;
2427
            }
2428
            header('Location: '.api_get_self());
2429
            exit;
2430
        }
2431
2432
        $actions = ['reply', 'mark_as_unread', 'mark_as_read', 'forward', 'delete'];
2433
2434
        $html = self::getMessageGrid(self::MESSAGE_TYPE_INBOX, $keyword, $actions, $searchTags);
2435
2436
        if (!empty($html)) {
2437
            $html .= self::addTagsFormToInbox();
2438
        }
2439
2440
        return $html;
2441
    }
2442
2443
    /**
2444
     * @param string $keyword
2445
     *
2446
     * @return string
2447
     */
2448
    public static function getPromotedMessagesGrid($keyword)
2449
    {
2450
        $actions = ['delete'];
2451
        $currentUserId = api_get_user_id();
2452
2453
        $success = get_lang('SelectedMessagesDeleted');
2454
        if (isset($_REQUEST['action'])) {
2455
            switch ($_REQUEST['action']) {
2456
                case 'delete':
2457
                    foreach ($_POST['id'] as $index => $messageId) {
2458
                        self::delete_message_by_user_receiver($currentUserId, $messageId);
2459
                    }
2460
                    Display::addFlash(Display::return_message(
2461
                        $success,
2462
                        'normal',
2463
                        false
2464
                    ));
2465
                    break;
2466
                case 'deleteone':
2467
                    self::delete_message_by_user_receiver($currentUserId, $_GET['id']);
2468
                    Display::addFlash(Display::return_message(
2469
                        $success,
2470
                        'confirmation',
2471
                        false
2472
                    ));
2473
                    break;
2474
            }
2475
2476
            header('Location: '.api_get_self());
2477
            exit;
2478
        }
2479
2480
        $html = self::getMessageGrid(self::MESSAGE_TYPE_PROMOTED, $keyword, $actions);
2481
2482
        return $html;
2483
    }
2484
2485
    /**
2486
     * @param string $keyword
2487
     *
2488
     * @return string
2489
     */
2490
    public static function outBoxDisplay($keyword, array $searchTags = [])
2491
    {
2492
        $actions = ['delete'];
2493
2494
        $success = get_lang('SelectedMessagesDeleted');
2495
        $currentUserId = api_get_user_id();
2496
        if (isset($_REQUEST['action'])) {
2497
            switch ($_REQUEST['action']) {
2498
                case 'delete':
2499
                    foreach ($_POST['id'] as $index => $messageId) {
2500
                        self::delete_message_by_user_sender($currentUserId, $messageId);
2501
                    }
2502
                    Display::addFlash(Display::return_message(
2503
                        $success,
2504
                        'normal',
2505
                        false
2506
                    ));
2507
2508
                    break;
2509
                case 'deleteone':
2510
                    self::delete_message_by_user_sender($currentUserId, $_GET['id']);
2511
                    Display::addFlash(Display::return_message(
2512
                        $success,
2513
                        'confirmation',
2514
                        false
2515
                    ));
2516
                    break;
2517
            }
2518
2519
            header('Location: '.api_get_self());
2520
            exit;
2521
        }
2522
2523
        $html = self::getMessageGrid(self::MESSAGE_TYPE_OUTBOX, $keyword, $actions, $searchTags);
2524
2525
        if (!empty($html)) {
2526
            $html .= self::addTagsFormToInbox();
2527
        }
2528
2529
        return $html;
2530
    }
2531
2532
    /**
2533
     * @param string $keyword
2534
     *
2535
     * @return string
2536
     */
2537
    public static function outbox_display($keyword = '')
2538
    {
2539
        Session::write('message_sent_search_keyword', $keyword);
2540
        $success = get_lang('SelectedMessagesDeleted').'&nbsp</b><br />
2541
                    <a href="outbox.php">'.get_lang('BackToOutbox').'</a>';
2542
2543
        $html = '';
2544
        if (isset($_REQUEST['action'])) {
2545
            switch ($_REQUEST['action']) {
2546
                case 'delete':
2547
                    $count = count($_POST['id']);
2548
                    if ($count != 0) {
2549
                        foreach ($_POST['id'] as $index => $messageId) {
2550
                            self::delete_message_by_user_receiver(
2551
                                api_get_user_id(),
2552
                                $messageId
2553
                            );
2554
                        }
2555
                    }
2556
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2557
                    break;
2558
                case 'deleteone':
2559
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
2560
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2561
                    $html .= '<br/>';
2562
                    break;
2563
            }
2564
        }
2565
2566
        // display sortable table with messages of the current user
2567
        $table = new SortableTable(
2568
            'message_outbox',
2569
            ['MessageManager', 'getNumberOfMessages'],
2570
            ['MessageManager', 'getMessageData'],
2571
            2,
2572
            20,
2573
            'DESC'
2574
        );
2575
        $table->setDataFunctionParams(
2576
            ['keyword' => $keyword, 'type' => self::MESSAGE_TYPE_OUTBOX]
2577
        );
2578
2579
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2580
        $table->set_header(1, get_lang('Messages'), false);
2581
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2582
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:70px;']);
2583
2584
        $table->set_form_actions(['delete' => get_lang('DeleteSelectedMessages')]);
2585
        $html .= $table->return_table();
2586
2587
        return $html;
2588
    }
2589
2590
    /**
2591
     * Get the data of the last received messages for a user.
2592
     *
2593
     * @param int $userId The user id
2594
     * @param int $lastId The id of the last received message
2595
     *
2596
     * @return array
2597
     */
2598
    public static function getMessagesFromLastReceivedMessage($userId, $lastId = 0)
2599
    {
2600
        $userId = (int) $userId;
2601
        $lastId = (int) $lastId;
2602
2603
        if (empty($userId)) {
2604
            return [];
2605
        }
2606
2607
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2608
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2609
2610
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname
2611
                FROM $messagesTable as m
2612
                INNER JOIN $userTable as u
2613
                ON m.user_sender_id = u.user_id
2614
                WHERE
2615
                    m.user_receiver_id = $userId AND
2616
                    m.msg_status = ".MESSAGE_STATUS_UNREAD."
2617
                    AND m.id > $lastId
2618
                ORDER BY m.send_date DESC";
2619
2620
        $result = Database::query($sql);
2621
2622
        $messages = [];
2623
        if ($result !== false) {
2624
            while ($row = Database::fetch_assoc($result)) {
2625
                $messages[] = $row;
2626
            }
2627
        }
2628
2629
        return $messages;
2630
    }
2631
2632
    /**
2633
     * Get the data of the last received messages for a user.
2634
     *
2635
     * @param int $userId The user id
2636
     * @param int $lastId The id of the last received message
2637
     *
2638
     * @return array
2639
     */
2640
    public static function getReceivedMessages($userId, $lastId = 0)
2641
    {
2642
        $userId = intval($userId);
2643
        $lastId = intval($lastId);
2644
2645
        if (empty($userId)) {
2646
            return [];
2647
        }
2648
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2649
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2650
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
2651
                FROM $messagesTable as m
2652
                INNER JOIN $userTable as u
2653
                ON m.user_sender_id = u.user_id
2654
                WHERE
2655
                    m.user_receiver_id = $userId AND
2656
                    m.msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
2657
                    AND m.id > $lastId
2658
                ORDER BY m.send_date DESC";
2659
2660
        $result = Database::query($sql);
2661
2662
        $messages = [];
2663
        if ($result !== false) {
2664
            while ($row = Database::fetch_assoc($result)) {
2665
                $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
2666
                $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
2667
                $messages[] = $row;
2668
            }
2669
        }
2670
2671
        return $messages;
2672
    }
2673
2674
    /**
2675
     * Get the data of the last received messages for a user.
2676
     *
2677
     * @param int $userId The user id
2678
     * @param int $lastId The id of the last received message
2679
     *
2680
     * @return array
2681
     */
2682
    public static function getSentMessages($userId, $lastId = 0)
2683
    {
2684
        $userId = intval($userId);
2685
        $lastId = intval($lastId);
2686
2687
        if (empty($userId)) {
2688
            return [];
2689
        }
2690
2691
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2692
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2693
2694
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
2695
                FROM $messagesTable as m
2696
                INNER JOIN $userTable as u
2697
                ON m.user_receiver_id = u.user_id
2698
                WHERE
2699
                    m.user_sender_id = $userId
2700
                    AND m.msg_status = ".MESSAGE_STATUS_OUTBOX."
2701
                    AND m.id > $lastId
2702
                ORDER BY m.send_date DESC";
2703
2704
        $result = Database::query($sql);
2705
2706
        $messages = [];
2707
        if ($result !== false) {
2708
            while ($row = Database::fetch_assoc($result)) {
2709
                $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
2710
                $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
2711
                $messages[] = $row;
2712
            }
2713
        }
2714
2715
        return $messages;
2716
    }
2717
2718
    /**
2719
     * Check whether a message has attachments.
2720
     *
2721
     * @param int $messageId The message id
2722
     *
2723
     * @return bool Whether the message has attachments return true. Otherwise return false
2724
     */
2725
    public static function hasAttachments($messageId)
2726
    {
2727
        $messageId = (int) $messageId;
2728
2729
        if (empty($messageId)) {
2730
            return false;
2731
        }
2732
2733
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2734
2735
        $conditions = [
2736
            'where' => [
2737
                'message_id = ?' => $messageId,
2738
            ],
2739
        ];
2740
2741
        $result = Database::select(
2742
            'COUNT(1) AS qty',
2743
            $messageAttachmentTable,
2744
            $conditions,
2745
            'first'
2746
        );
2747
2748
        if (!empty($result)) {
2749
            if ($result['qty'] > 0) {
2750
                return true;
2751
            }
2752
        }
2753
2754
        return false;
2755
    }
2756
2757
    /**
2758
     * @param int $messageId
2759
     *
2760
     * @return array|bool
2761
     */
2762
    public static function getAttachment($messageId)
2763
    {
2764
        $messageId = (int) $messageId;
2765
2766
        if (empty($messageId)) {
2767
            return false;
2768
        }
2769
2770
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2771
2772
        $conditions = [
2773
            'where' => [
2774
                'id = ?' => $messageId,
2775
            ],
2776
        ];
2777
2778
        $result = Database::select(
2779
            '*',
2780
            $table,
2781
            $conditions,
2782
            'first'
2783
        );
2784
2785
        if (!empty($result)) {
2786
            return $result;
2787
        }
2788
2789
        return false;
2790
    }
2791
2792
    /**
2793
     * @param string $url
2794
     *
2795
     * @return FormValidator
2796
     */
2797
    public static function getSearchForm($url)
2798
    {
2799
        $form = new FormValidator(
2800
            'search',
2801
            'post',
2802
            $url,
2803
            null,
2804
            [],
2805
            FormValidator::LAYOUT_INLINE
2806
        );
2807
2808
        self::addTagsFormToSearch($form);
2809
2810
        $form->addElement(
2811
            'text',
2812
            'keyword',
2813
            false,
2814
            [
2815
                'aria-label' => get_lang('Search'),
2816
            ]
2817
        );
2818
        $form->addButtonSearch(get_lang('Search'));
2819
2820
        return $form;
2821
    }
2822
2823
    /**
2824
     * Send a notification to all admins when a new user is registered.
2825
     */
2826
    public static function sendNotificationOfNewRegisteredUser(User $user)
2827
    {
2828
        $tplMailBody = new Template(
2829
            null,
2830
            false,
2831
            false,
2832
            false,
2833
            false,
2834
            false,
2835
            false
2836
        );
2837
        $tplMailBody->assign('user', $user);
2838
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2839
        $tplMailBody->assign(
2840
            'manageUrl',
2841
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
2842
        );
2843
2844
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
2845
2846
        $emailsubject = '['.get_lang('UserRegistered').'] '.$user->getUsername();
2847
        $emailbody = $tplMailBody->fetch($layoutContent);
2848
2849
        $admins = UserManager::get_all_administrators();
2850
2851
        foreach ($admins as $admin_info) {
2852
            self::send_message(
2853
                $admin_info['user_id'],
2854
                $emailsubject,
2855
                $emailbody,
2856
                [],
2857
                [],
2858
                null,
2859
                null,
2860
                null,
2861
                null,
2862
                $user->getId()
2863
            );
2864
        }
2865
    }
2866
2867
    /**
2868
     * Send a notification to all admins when a new user is registered
2869
     * while the approval method is used for users registration.
2870
     */
2871
    public static function sendNotificationOfNewRegisteredUserApproval(User $user)
2872
    {
2873
        $tplMailBody = new Template(
2874
            null,
2875
            false,
2876
            false,
2877
            false,
2878
            false,
2879
            false,
2880
            false
2881
        );
2882
        $tplMailBody->assign('user', $user);
2883
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2884
        $userId = $user->getId();
2885
        $url_edit = Display::url(
2886
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId,
2887
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId
2888
        );
2889
        $tplMailBody->assign(
2890
            'manageUrl',
2891
            $url_edit
2892
        );
2893
        // Get extra field values for this user and reformat the array
2894
        $extraFieldValues = new ExtraFieldValue('user');
2895
        $userExtraFields = $extraFieldValues->getAllValuesByItem($userId);
2896
        $values = [];
2897
        foreach ($userExtraFields as $field => $value) {
2898
            $values[$value['variable']] = $value['value'];
2899
        }
2900
        $tplMailBody->assign(
2901
            'extra',
2902
            $values
2903
        );
2904
        $layoutContent = '';
2905
        $emailbody = '';
2906
        if (api_get_configuration_value('mail_template_system') == true) {
2907
            $mailTemplateManager = new MailTemplateManager();
2908
            $templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl');
2909
            if (empty($templateText)) {
2910
            } else {
2911
                // custom procedure to load a template as a string (doesn't use cache so may slow down)
2912
                $template = $tplMailBody->twig->createTemplate($templateText);
2913
                $emailbody = $template->render($tplMailBody->params);
2914
            }
2915
        }
2916
        if (empty($emailbody)) {
2917
            $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl');
2918
            $emailbody = $tplMailBody->fetch($layoutContent);
2919
        }
2920
2921
        $emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername();
2922
2923
        if (api_get_configuration_value('send_inscription_notification_to_general_admin_only')) {
2924
            $email = api_get_setting('emailAdministrator');
2925
            $firstname = api_get_setting('administratorSurname');
2926
            $lastname = api_get_setting('administratorName');
2927
            api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody);
2928
        } else {
2929
            $admins = UserManager::get_all_administrators();
2930
            foreach ($admins as $admin_info) {
2931
                self::send_message(
2932
                    $admin_info['user_id'],
2933
                    $emailsubject,
2934
                    $emailbody,
2935
                    [],
2936
                    [],
2937
                    null,
2938
                    null,
2939
                    null,
2940
                    null,
2941
                    $userId
2942
                );
2943
            }
2944
        }
2945
    }
2946
2947
    /**
2948
     * Get the error log from failed mailing
2949
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
2950
     * into app/cache/mail/mailq.
2951
     * This can be done with a cron command like (check the location of your mail log file first):.
2952
     *
2953
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
2954
     *
2955
     * @return array|bool
2956
     */
2957
    public static function failedSentMailErrors()
2958
    {
2959
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
2960
        $mailq = $base.'mailq';
2961
2962
        if (!file_exists($mailq) || !is_readable($mailq)) {
2963
            return false;
2964
        }
2965
2966
        $file = fopen($mailq, 'r');
2967
        $i = 1;
2968
        while (!feof($file)) {
2969
            $line = fgets($file);
2970
2971
            if (trim($line) == '') {
2972
                continue;
2973
            }
2974
2975
            // Get the mail code, something like 1WBumL-0002xg-FF
2976
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
2977
                $mail_queue[$i]['code'] = $codeMatches[2];
2978
            }
2979
2980
            $fullMail = $base.$mail_queue[$i]['code'];
2981
            $mailFile = fopen($fullMail, 'r');
2982
2983
            // Get the reason of mail fail
2984
            $iX = 1;
2985
            while (!feof($mailFile)) {
2986
                $mailLine = fgets($mailFile);
2987
                //if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2988
                if ($iX == 2 &&
2989
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2990
                ) {
2991
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2992
                }
2993
                $iX++;
2994
            }
2995
2996
            fclose($mailFile);
2997
2998
            // Get the time of mail fail
2999
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
3000
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
3001
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
3002
                $mail_queue[$i]['mail'] = $emailMatches[2];
3003
                $i++;
3004
            }
3005
        }
3006
3007
        fclose($file);
3008
3009
        return array_reverse($mail_queue);
3010
    }
3011
3012
    /**
3013
     * @param int      $userId
3014
     * @param datetime $startDate
3015
     * @param datetime $endDate
3016
     *
3017
     * @return array
3018
     */
3019
    public static function getUsersThatHadConversationWithUser($userId, $startDate = null, $endDate = null)
3020
    {
3021
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
3022
        $userId = (int) $userId;
3023
3024
        $sql = "SELECT DISTINCT
3025
                    user_sender_id
3026
                FROM $messagesTable
3027
                WHERE
3028
                    user_receiver_id = ".$userId;
3029
3030
        if ($startDate != null) {
3031
            $startDate = Database::escape_string($startDate);
3032
            $sql .= " AND send_date >= '".$startDate."'";
3033
        }
3034
3035
        if ($endDate != null) {
3036
            $endDate = Database::escape_string($endDate);
3037
            $sql .= " AND send_date <= '".$endDate."'";
3038
        }
3039
3040
        $result = Database::query($sql);
3041
        $users = Database::store_result($result);
3042
        $userList = [];
3043
        foreach ($users as $userData) {
3044
            $userId = $userData['user_sender_id'];
3045
            if (empty($userId)) {
3046
                continue;
3047
            }
3048
            $userInfo = api_get_user_info($userId);
3049
            if ($userInfo) {
3050
                $userList[$userId] = $userInfo;
3051
            }
3052
        }
3053
3054
        return $userList;
3055
    }
3056
3057
    /**
3058
     * Retrieves a list of users with whom the specified user has exchanged messages within an optional date range.
3059
     *
3060
     * @param int         $userId    The user ID for whom to retrieve message exchange.
3061
     * @param string|null $startDate Start date to filter the messages (optional).
3062
     * @param string|null $endDate   End date to filter the messages (optional).
3063
     *
3064
     * @return array Array of user information for each user with whom the specified user has exchanged messages.
3065
     */
3066
    public static function getMessageExchangeWithUser($userId, $startDate = null, $endDate = null)
3067
    {
3068
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
3069
        $userId = (int) $userId;
3070
3071
        if ($startDate !== null) {
3072
            $startDate = Database::escape_string($startDate);
3073
        }
3074
        if ($endDate !== null) {
3075
            $endDate = Database::escape_string($endDate);
3076
        }
3077
3078
        $sql = "SELECT DISTINCT user_sender_id AS user_id
3079
                 FROM $messagesTable
3080
                 WHERE user_receiver_id = $userId".
3081
                 ($startDate ? " AND send_date >= '$startDate'" : "").
3082
                 ($endDate ? " AND send_date <= '$endDate'" : "").
3083
               " UNION
3084
               SELECT DISTINCT user_receiver_id
3085
                 FROM $messagesTable
3086
                 WHERE user_sender_id = $userId".
3087
                 ($startDate ? " AND send_date >= '$startDate'" : "").
3088
                 ($endDate ? " AND send_date <= '$endDate'" : "");
3089
3090
        $result = Database::query($sql);
3091
        $users = Database::store_result($result);
3092
3093
        $userList = [];
3094
        foreach ($users as $userData) {
3095
            $userId = $userData['user_id'];
3096
            if (empty($userId)) {
3097
                continue;
3098
            }
3099
            $userInfo = api_get_user_info($userId);
3100
            if ($userInfo) {
3101
                $userList[$userId] = $userInfo;
3102
            }
3103
        }
3104
3105
        return $userList;
3106
    }
3107
3108
    /**
3109
     * @param int      $userId
3110
     * @param int      $otherUserId
3111
     * @param datetime $startDate
3112
     * @param datetime $endDate
3113
     *
3114
     * @return array
3115
     */
3116
    public static function getAllMessagesBetweenStudents($userId, $otherUserId, $startDate = null, $endDate = null)
3117
    {
3118
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
3119
        $userId = (int) $userId;
3120
        $otherUserId = (int) $otherUserId;
3121
3122
        if (empty($otherUserId) || empty($userId)) {
3123
            return [];
3124
        }
3125
3126
        $sql = "SELECT DISTINCT *
3127
                FROM $messagesTable
3128
                WHERE
3129
                    ((user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
3130
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId))
3131
            ";
3132
        if ($startDate != null) {
3133
            $startDate = Database::escape_string($startDate);
3134
            $sql .= " AND send_date >= '".$startDate."'";
3135
        }
3136
        if ($endDate != null) {
3137
            $endDate = Database::escape_string($endDate);
3138
            $sql .= " AND send_date <= '".$endDate."'";
3139
        }
3140
        $sql .= " ORDER BY send_date DESC";
3141
        $result = Database::query($sql);
3142
        $messages = Database::store_result($result);
3143
        $list = [];
3144
        foreach ($messages as $message) {
3145
            $list[] = $message;
3146
        }
3147
3148
        return $list;
3149
    }
3150
3151
    /**
3152
     * @param string $subject
3153
     * @param string $message
3154
     * @param array  $courseInfo
3155
     * @param int    $sessionId
3156
     *
3157
     * @return bool
3158
     */
3159
    public static function sendMessageToAllUsersInCourse($subject, $message, $courseInfo, $sessionId = 0)
3160
    {
3161
        if (empty($courseInfo)) {
3162
            return false;
3163
        }
3164
3165
        $senderId = api_get_user_id();
3166
        if (empty($senderId)) {
3167
            return false;
3168
        }
3169
        if (empty($sessionId)) {
3170
            // Course students and teachers
3171
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code']);
3172
        } else {
3173
            // Course-session students and course session coaches
3174
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code'], $sessionId);
3175
        }
3176
3177
        if (empty($users)) {
3178
            return false;
3179
        }
3180
3181
        foreach ($users as $userInfo) {
3182
            self::send_message_simple(
3183
                $userInfo['user_id'],
3184
                $subject,
3185
                $message,
3186
                $senderId,
3187
                false,
3188
                false,
3189
                [],
3190
                false
3191
            );
3192
        }
3193
    }
3194
3195
    /**
3196
     * Clean audio messages already added in the message tool.
3197
     */
3198
    public static function cleanAudioMessage()
3199
    {
3200
        $audioId = Session::read('current_audio_id');
3201
        if (!empty($audioId)) {
3202
            api_remove_uploaded_file_by_id('audio_message', api_get_user_id(), $audioId);
3203
            Session::erase('current_audio_id');
3204
        }
3205
    }
3206
3207
    /**
3208
     * @param int    $senderId
3209
     * @param string $subject
3210
     * @param string $message
3211
     */
3212
    public static function sendMessageToAllAdminUsers(
3213
        $senderId,
3214
        $subject,
3215
        $message
3216
    ) {
3217
        $admins = UserManager::get_all_administrators();
3218
        foreach ($admins as $admin) {
3219
            self::send_message_simple($admin['user_id'], $subject, $message, $senderId);
3220
        }
3221
    }
3222
3223
    /**
3224
     * @param int $messageId
3225
     * @param int $userId
3226
     *
3227
     * @return array
3228
     */
3229
    public static function countLikesAndDislikes($messageId, $userId)
3230
    {
3231
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
3232
            return [];
3233
        }
3234
3235
        $messageId = (int) $messageId;
3236
        $userId = (int) $userId;
3237
3238
        $em = Database::getManager();
3239
        $query = $em
3240
            ->createQuery('
3241
                SELECT SUM(l.liked) AS likes, SUM(l.disliked) AS dislikes FROM ChamiloCoreBundle:MessageFeedback l
3242
                WHERE l.message = :message
3243
            ')
3244
            ->setParameters(['message' => $messageId]);
3245
3246
        try {
3247
            $counts = $query->getSingleResult();
3248
        } catch (Exception $e) {
3249
            $counts = ['likes' => 0, 'dislikes' => 0];
3250
        }
3251
3252
        $userLike = $em
3253
            ->getRepository('ChamiloCoreBundle:MessageFeedback')
3254
            ->findOneBy(['message' => $messageId, 'user' => $userId]);
3255
3256
        return [
3257
            'likes' => (int) $counts['likes'],
3258
            'dislikes' => (int) $counts['dislikes'],
3259
            'user_liked' => $userLike ? $userLike->isLiked() : false,
3260
            'user_disliked' => $userLike ? $userLike->isDisliked() : false,
3261
        ];
3262
    }
3263
3264
    /**
3265
     * @param int $messageId
3266
     * @param int $userId
3267
     * @param int $groupId   Optional.
3268
     *
3269
     * @return string
3270
     */
3271
    public static function getLikesButton($messageId, $userId, $groupId = 0)
3272
    {
3273
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
3274
            return '';
3275
        }
3276
3277
        $countLikes = self::countLikesAndDislikes($messageId, $userId);
3278
3279
        $class = $countLikes['user_liked'] ? 'btn-primary' : 'btn-default';
3280
3281
        $btnLike = Display::button(
3282
            'like',
3283
            Display::returnFontAwesomeIcon('thumbs-up', '', true)
3284
                .PHP_EOL.'<span>'.$countLikes['likes'].'</span>',
3285
            [
3286
                'title' => get_lang('VoteLike'),
3287
                'class' => 'btn  social-like '.$class,
3288
                'data-status' => 'like',
3289
                'data-message' => $messageId,
3290
                'data-group' => $groupId,
3291
            ]
3292
        );
3293
3294
        $btnDislike = '';
3295
        if (api_get_configuration_value('disable_dislike_option') === false) {
3296
            $disabled = $countLikes['user_disliked'] ? 'btn-danger' : 'btn-default';
3297
3298
            $btnDislike = Display::button(
3299
                'like',
3300
                Display::returnFontAwesomeIcon('thumbs-down', '', true)
3301
                .PHP_EOL.'<span>'.$countLikes['dislikes'].'</span>',
3302
                [
3303
                    'title' => get_lang('VoteDislike'),
3304
                    'class' => 'btn social-like '.$disabled,
3305
                    'data-status' => 'dislike',
3306
                    'data-message' => $messageId,
3307
                    'data-group' => $groupId,
3308
                ]
3309
            );
3310
        }
3311
3312
        return $btnLike.PHP_EOL.$btnDislike;
3313
    }
3314
3315
    /**
3316
     * Execute the SQL necessary to know the number of messages in the database.
3317
     *
3318
     * @param int $userId The user for which we need the unread messages count
3319
     *
3320
     * @return int The number of unread messages in the database for the given user
3321
     */
3322
    public static function getCountNewMessagesFromDB($userId)
3323
    {
3324
        $userId = (int) $userId;
3325
3326
        if (empty($userId)) {
3327
            return 0;
3328
        }
3329
3330
        $table = Database::get_main_table(TABLE_MESSAGE);
3331
        $sql = "SELECT COUNT(id) as count
3332
                FROM $table
3333
                WHERE
3334
                    user_receiver_id = $userId AND
3335
                    msg_status = ".MESSAGE_STATUS_UNREAD;
3336
        $result = Database::query($sql);
3337
        $row = Database::fetch_assoc($result);
3338
3339
        return (int) $row['count'];
3340
    }
3341
3342
    public static function getMessagesCountForUser(int $userId): array
3343
    {
3344
        // Setting notifications
3345
        $countUnreadMessage = 0;
3346
3347
        if (api_get_setting('allow_message_tool') === 'true') {
3348
            // get count unread message and total invitations
3349
            $countUnreadMessage = MessageManager::getCountNewMessagesFromDB($userId);
3350
        }
3351
3352
        if (api_get_setting('allow_social_tool') === 'true') {
3353
            $numberOfNewMessagesOfFriend = SocialManager::get_message_number_invitation_by_user_id(
3354
                $userId
3355
            );
3356
            $usergroup = new UserGroup();
3357
            $groupPendingInvitations = $usergroup->get_groups_by_user(
3358
                $userId,
3359
                GROUP_USER_PERMISSION_PENDING_INVITATION
3360
            );
3361
3362
            if (!empty($groupPendingInvitations)) {
3363
                $groupPendingInvitations = count($groupPendingInvitations);
3364
            } else {
3365
                $groupPendingInvitations = 0;
3366
            }
3367
3368
            return [
3369
                'ms_friends' => $numberOfNewMessagesOfFriend,
3370
                'ms_groups' => $groupPendingInvitations,
3371
                'ms_inbox' => $countUnreadMessage,
3372
            ];
3373
        }
3374
3375
        return [
3376
            'ms_friends' => 0,
3377
            'ms_groups' => 0,
3378
            'ms_inbox' => $countUnreadMessage,
3379
        ];
3380
    }
3381
3382
    /**
3383
     * @throws Exception
3384
     */
3385
    public static function setDefaultValuesInFormFromMessageInfo(array $messageInfo, FormValidator $form)
3386
    {
3387
        $currentUserId = api_get_user_id();
3388
        $contentMatch = [];
3389
        preg_match('/<body>(.*?)<\/body>/s', $messageInfo['content'], $contentMatch);
3390
3391
        $defaults = [
3392
            'title' => $messageInfo['title'],
3393
        ];
3394
3395
        if (empty($contentMatch[1])) {
3396
            $defaults['content'] = strip_tags_blacklist(
3397
                $messageInfo['content'],
3398
                ['link', 'script', 'title', 'head', 'body']
3399
            );
3400
            $defaults['content'] = preg_replace('#(<link(.*?)>)#msi', '', $defaults['content']);
3401
        } else {
3402
            $defaults['content'] = $contentMatch[1];
3403
        }
3404
3405
        if (api_get_configuration_value('agenda_collective_invitations')) {
3406
            $defaults['invitees'] = [];
3407
3408
            if ($currentUserId != $messageInfo['user_sender_id']) {
3409
                $senderInfo = api_get_user_info($messageInfo['user_sender_id']);
3410
                $form->getElement('invitees')->addOption(
3411
                    $senderInfo['complete_name_with_username'],
3412
                    $senderInfo['id']
3413
                );
3414
                $defaults['invitees'][] = $senderInfo['id'];
3415
            }
3416
3417
            $messageCopies = MessageManager::getCopiesFromMessageInfo($messageInfo);
3418
3419
            foreach ($messageCopies as $messageCopy) {
3420
                if ($currentUserId == $messageCopy->getUserReceiverId()) {
3421
                    continue;
3422
                }
3423
3424
                $receiverInfo = api_get_user_info($messageCopy->getUserReceiverId());
3425
                $form->getElement('invitees')->addOption(
3426
                    $receiverInfo['complete_name_with_username'],
3427
                    $receiverInfo['id']
3428
                );
3429
3430
                $defaults['invitees'][] = $receiverInfo['id'];
3431
            }
3432
        }
3433
3434
        $form->setDefaults($defaults);
3435
    }
3436
3437
    /**
3438
     * @throws Exception
3439
     *
3440
     * @return array<Message>
3441
     */
3442
    public static function getCopiesFromMessageInfo(array $messageInfo): array
3443
    {
3444
        $em = Database::getManager();
3445
        $messageRepo = $em->getRepository('ChamiloCoreBundle:Message');
3446
3447
        return $messageRepo->findBy(
3448
            [
3449
                'userSenderId' => $messageInfo['user_sender_id'],
3450
                'msgStatus' => MESSAGE_STATUS_OUTBOX,
3451
                'sendDate' => new DateTime($messageInfo['send_date'], new DateTimeZone('UTC')),
3452
                'title' => $messageInfo['title'],
3453
                'content' => $messageInfo['content'],
3454
                'groupId' => $messageInfo['group_id'],
3455
                'parentId' => $messageInfo['parent_id'],
3456
            ]
3457
        );
3458
    }
3459
3460
    /**
3461
     * Reports whether the given user is sender or receiver of the given message.
3462
     *
3463
     * @return bool
3464
     */
3465
    public static function isUserOwner(int $userId, int $messageId)
3466
    {
3467
        $table = Database::get_main_table(TABLE_MESSAGE);
3468
        $sql = "SELECT id FROM $table
3469
          WHERE id = $messageId
3470
            AND (user_receiver_id = $userId OR user_sender_id = $userId)";
3471
        $res = Database::query($sql);
3472
        if (Database::num_rows($res) === 1) {
3473
            return true;
3474
        }
3475
3476
        return false;
3477
    }
3478
3479
    private static function addTagsFormToInbox(): string
3480
    {
3481
        if (false === api_get_configuration_value('enable_message_tags')) {
3482
            return '';
3483
        }
3484
3485
        $form = new FormValidator('frm_inbox_tags', 'post');
3486
3487
        $extrafield = new ExtraField('message');
3488
        $extraHtml = $extrafield->addElements($form, 0, [], true, false, ['tags']);
3489
3490
        $form->addButton('submit', get_lang('AddTags'), 'plus', 'primary');
3491
        $form->protect();
3492
3493
        $html = $form->returnForm();
3494
        $html .= '<script>$(function () { '.$extraHtml['jquery_ready_content'].' });</script>';
3495
3496
        return $html;
3497
    }
3498
3499
    private static function addTagsForm(int $messageId, string $type): string
3500
    {
3501
        $url = api_get_self()."?id=$messageId&type=$type";
3502
        $form = new FormValidator('frm_tags', 'post', $url);
3503
3504
        $extrafield = new ExtraField('message');
3505
        $extraHtml = $extrafield->addElements($form, $messageId, [], true, false, ['tags']);
3506
3507
        $form->addButtonSave(get_lang('Save'));
3508
        $form->protect();
3509
3510
        if ($form->validate()) {
3511
            $values = $form->getSubmitValues();
3512
            $values['item_id'] = $messageId;
3513
3514
            $extraFieldValues = new ExtraFieldValue('message');
3515
            $extraFieldValues->saveFieldValues($values);
3516
3517
            Display::addFlash(
3518
                Display::return_message(get_lang('ItemUpdated'), 'success')
3519
            );
3520
3521
            header("Location: $url");
3522
            exit;
3523
        }
3524
3525
        $messageContent = $form->returnForm();
3526
        $messageContent .= '<script>$(function () { '.$extraHtml['jquery_ready_content'].' });</script>';
3527
3528
        return $messageContent;
3529
    }
3530
3531
    private static function addTagsFormToSearch(FormValidator $form)
3532
    {
3533
        if (false === api_get_configuration_value('enable_message_tags')) {
3534
            return;
3535
        }
3536
3537
        $userId = api_get_user_id();
3538
3539
        $em = Database::getManager();
3540
        $tags = $em
3541
            ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
3542
            ->getTagsByUserMessages($userId)
3543
        ;
3544
3545
        $tagsOptions = [];
3546
3547
        foreach ($tags as $tag) {
3548
            $tagsOptions[$tag->getId()] = $tag->getTag();
3549
        }
3550
3551
        $form
3552
            ->addSelect(
3553
                'tags',
3554
                get_lang('Tags'),
3555
                $tagsOptions,
3556
                ['class' => 'inbox-search-tags', 'title' => get_lang('FilterByTags')]
3557
            )
3558
            ->setMultiple(true)
3559
        ;
3560
    }
3561
}
3562