Passed
Push — preprodparkur ( 16ed43...b173f4 )
by Angel Fernando Quiroz
13:51 queued 03:13
created

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 34
nc 24
nop 9
dl 0
loc 58
rs 8.4426
c 0
b 0
f 0

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