Completed
Push — master ( b77cfe...000f93 )
by Julito
22:58 queued 11:19
created

MessageManager::inbox_display()   D

Complexity

Conditions 13
Paths 16

Size

Total Lines 94
Code Lines 66

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 66
nc 16
nop 1
dl 0
loc 94
rs 4.9922
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\UserBundle\Entity\User;
5
use ChamiloSession as Session;
6
7
/**
8
 * Class MessageManager.
9
 *
10
 * This class provides methods for messages management.
11
 * Include/require it in your code to use its features.
12
 *
13
 * @package chamilo.library
14
 */
15
class MessageManager
16
{
17
    /**
18
     * Get count new messages for the current user from the database.
19
     *
20
     * @return int
21
     */
22
    public static function getCountNewMessages()
23
    {
24
        $userId = api_get_user_id();
25
        if (empty($userId)) {
26
            return false;
27
        }
28
29
        static $count;
30
        if (!isset($count)) {
31
            $cacheAvailable = api_get_configuration_value('apc');
32
            if ($cacheAvailable === true) {
33
                $var = api_get_configuration_value('apc_prefix').'social_messages_unread_u_'.$userId;
34
                if (apcu_exists($var)) {
35
                    $count = apcu_fetch($var);
36
                } else {
37
                    $count = self::getCountNewMessagesFromDB($userId);
38
                    apcu_store($var, $count, 60);
39
                }
40
            } else {
41
                $count = self::getCountNewMessagesFromDB($userId);
42
            }
43
        }
44
45
        return $count;
46
    }
47
48
    /**
49
     * Gets the total number of messages, used for the inbox sortable table.
50
     *
51
     * @param bool $unread
52
     *
53
     * @return int
54
     */
55
    public static function getNumberOfMessages($unread = false)
56
    {
57
        $table = Database::get_main_table(TABLE_MESSAGE);
58
        if ($unread) {
59
            $condition_msg_status = ' msg_status = '.MESSAGE_STATUS_UNREAD.' ';
60
        } else {
61
            $condition_msg_status = ' msg_status IN('.MESSAGE_STATUS_NEW.','.MESSAGE_STATUS_UNREAD.') ';
62
        }
63
64
        $keyword = Session::read('message_search_keyword');
65
        $keywordCondition = '';
66
        if (!empty($keyword)) {
67
            $keyword = Database::escape_string($keyword);
68
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
69
        }
70
71
        $sql = "SELECT COUNT(id) as number_messages
72
                FROM $table
73
                WHERE $condition_msg_status AND
74
                    user_receiver_id=".api_get_user_id()."
75
                    $keywordCondition
76
                ";
77
        $result = Database::query($sql);
78
        $result = Database::fetch_array($result);
79
80
        return $result['number_messages'];
81
    }
82
83
    /**
84
     * Gets information about some messages, used for the inbox sortable table.
85
     *
86
     * @param int    $from
87
     * @param int    $number_of_items
88
     * @param string $column
89
     * @param string $direction
90
     *
91
     * @return array
92
     */
93
    public static function get_message_data(
94
        $from,
95
        $number_of_items,
96
        $column,
97
        $direction,
98
        $userId = 0
99
    ) {
100
        $from = (int) $from;
101
        $number_of_items = (int) $number_of_items;
102
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
103
104
        //forcing this order
105
        if (!isset($direction)) {
106
            $column = 2;
107
            $direction = 'DESC';
108
        } else {
109
            $column = intval($column);
110
            if (!in_array($direction, ['ASC', 'DESC'])) {
111
                $direction = 'ASC';
112
            }
113
        }
114
115
        if (!in_array($column, [0, 1, 2])) {
116
            $column = 2;
117
        }
118
119
        $keyword = Session::read('message_search_keyword');
120
        $keywordCondition = '';
121
        if (!empty($keyword)) {
122
            $keyword = Database::escape_string($keyword);
123
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
124
        }
125
126
        $table = Database::get_main_table(TABLE_MESSAGE);
127
        $sql = "SELECT 
128
                    id as col0, 
129
                    title as col1, 
130
                    send_date as col2, 
131
                    msg_status as col3,
132
                    user_sender_id
133
                FROM $table
134
                WHERE
135
                    user_receiver_id=".$userId." AND
136
                    msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
137
                    $keywordCondition
138
                ORDER BY col$column $direction
139
                LIMIT $from, $number_of_items";
140
141
        $result = Database::query($sql);
142
        $message_list = [];
143
        $newMessageLink = api_get_path(WEB_CODE_PATH).'messages/new_message.php';
144
        while ($row = Database::fetch_array($result, 'ASSOC')) {
145
            $messageId = $row['col0'];
146
            $title = $row['col1'];
147
            $sendDate = $row['col2'];
148
            $status = $row['col3'];
149
            $senderId = $row['user_sender_id'];
150
151
            $title = Security::remove_XSS($title, STUDENT, true);
152
            $title = cut($title, 80, true);
153
154
            if ($status == 1) {
155
                $class = 'class = "unread"';
156
            } else {
157
                $class = 'class = "read"';
158
            }
159
160
            $userInfo = api_get_user_info($senderId);
161
            if (!empty($senderId) && !empty($userInfo)) {
162
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
163
                $message[1] .= $userInfo['complete_name_with_username'];
164
                $message[3] =
165
                    Display::url(
166
                        Display::returnFontAwesomeIcon('reply', 2),
167
                        $newMessageLink.'?re_id='.$messageId,
168
                        ['title' => get_lang('ReplyToMessage')]
169
                    );
170
            } else {
171
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
172
                $message[1] .= get_lang('UnknownUser');
173
                $message[3] =
174
                    Display::url(
175
                        Display::returnFontAwesomeIcon('reply', 2),
176
                        '#',
177
                        ['title' => get_lang('ReplyToMessage')]
178
                    );
179
            }
180
181
            $message[0] = $messageId;
182
            $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
183
            $message[3] .=
184
                '&nbsp;&nbsp;'.
185
                Display::url(
186
                    Display::returnFontAwesomeIcon('share', 2),
187
                    $newMessageLink.'?forward_id='.$messageId,
188
                    ['title' => get_lang('ForwardMessage')]
189
                ).
190
                '&nbsp;&nbsp;<a title="'.addslashes(
191
                    get_lang('DeleteMessage')
192
                ).'" onclick="javascript:if(!confirm('."'".addslashes(
193
                    api_htmlentities(get_lang('ConfirmDeleteMessage'))
194
                )."'".')) return false;" href="inbox.php?action=deleteone&id='.$messageId.'">'.
195
                Display::returnFontAwesomeIcon('trash', 2).'</a>';
196
            foreach ($message as $key => $value) {
197
                $message[$key] = api_xml_http_response_encode($value);
198
            }
199
            $message_list[] = $message;
200
        }
201
202
        return $message_list;
203
    }
204
205
    /**
206
     * @param array  $aboutUserInfo
207
     * @param array  $fromUserInfo
208
     * @param string $subject
209
     * @param string $content
210
     *
211
     * @return bool
212
     */
213
    public static function sendMessageAboutUser(
214
        $aboutUserInfo,
215
        $fromUserInfo,
216
        $subject,
217
        $content
218
    ) {
219
        if (empty($aboutUserInfo) || empty($fromUserInfo)) {
220
            return false;
221
        }
222
223
        if (empty($fromUserInfo['id']) || empty($aboutUserInfo['id'])) {
224
            return false;
225
        }
226
227
        $table = Database::get_main_table(TABLE_MESSAGE);
228
        $now = api_get_utc_datetime();
229
        $params = [
230
            'user_sender_id' => $fromUserInfo['id'],
231
            'user_receiver_id' => $aboutUserInfo['id'],
232
            'msg_status' => MESSAGE_STATUS_CONVERSATION,
233
            'send_date' => $now,
234
            'title' => $subject,
235
            'content' => $content,
236
            'group_id' => 0,
237
            'parent_id' => 0,
238
            'update_date' => $now,
239
        ];
240
        $id = Database::insert($table, $params);
241
        if ($id) {
242
            return true;
243
        }
244
245
        return false;
246
    }
247
248
    /**
249
     * @param array $aboutUserInfo
250
     *
251
     * @return array
252
     */
253
    public static function getMessagesAboutUser($aboutUserInfo)
254
    {
255
        if (!empty($aboutUserInfo)) {
256
            $criteria = [
257
                'userReceiverId' => $aboutUserInfo['id'],
258
                'msgStatus' => MESSAGE_STATUS_CONVERSATION,
259
            ];
260
            $repo = Database::getManager()->getRepository('ChamiloCoreBundle:Message');
261
            $messages = $repo->findBy($criteria, ['sendDate' => 'DESC']);
262
263
            return $messages;
264
        }
265
266
        return [];
267
    }
268
269
    /**
270
     * Sends a message to a user/group.
271
     *
272
     * @param int    $receiver_user_id
273
     * @param string $subject
274
     * @param string $content
275
     * @param array  $attachments      files array($_FILES) (optional)
276
     * @param array  $fileCommentList  about attachment files (optional)
277
     * @param int    $group_id         (optional)
278
     * @param int    $parent_id        (optional)
279
     * @param int    $editMessageId    id for updating the message (optional)
280
     * @param int    $topic_id         (optional) the default value is the current user_id
281
     * @param int    $sender_id
282
     * @param bool   $directMessage
283
     * @param int    $forwardId
284
     * @param array  $smsParameters
285
     *
286
     * @return bool
287
     */
288
    public static function send_message(
289
        $receiver_user_id,
290
        $subject,
291
        $content,
292
        array $attachments = [],
293
        array $fileCommentList = [],
294
        $group_id = 0,
295
        $parent_id = 0,
296
        $editMessageId = 0,
297
        $topic_id = 0,
298
        $sender_id = 0,
299
        $directMessage = false,
300
        $forwardId = 0,
301
        $smsParameters = []
302
    ) {
303
        $table = Database::get_main_table(TABLE_MESSAGE);
304
        $group_id = (int) $group_id;
305
        $receiver_user_id = (int) $receiver_user_id;
306
        $parent_id = (int) $parent_id;
307
        $editMessageId = (int) $editMessageId;
308
        $topic_id = (int) $topic_id;
309
310
        if (!empty($receiver_user_id)) {
311
            $receiverUserInfo = api_get_user_info($receiver_user_id);
312
313
            // Disabling messages for inactive users.
314
            if ($receiverUserInfo['active'] == 0) {
315
                return false;
316
            }
317
        }
318
319
        $user_sender_id = empty($sender_id) ? api_get_user_id() : (int) $sender_id;
320
        if (empty($user_sender_id)) {
321
            Display::addFlash(Display::return_message(get_lang('UserDoesNotExist'), 'warning'));
322
323
            return false;
324
        }
325
326
        $totalFileSize = 0;
327
        $attachmentList = [];
328
        if (is_array($attachments)) {
329
            $counter = 0;
330
            foreach ($attachments as $attachment) {
331
                $attachment['comment'] = isset($fileCommentList[$counter]) ? $fileCommentList[$counter] : '';
332
                $fileSize = isset($attachment['size']) ? $attachment['size'] : 0;
333
                if (is_array($fileSize)) {
334
                    foreach ($fileSize as $size) {
335
                        $totalFileSize += $size;
336
                    }
337
                } else {
338
                    $totalFileSize += $fileSize;
339
                }
340
                $attachmentList[] = $attachment;
341
                $counter++;
342
            }
343
        }
344
345
        // Validating fields
346
        if (empty($subject) && empty($group_id)) {
347
            Display::addFlash(
348
                Display::return_message(
349
                    get_lang('YouShouldWriteASubject'),
350
                    'warning'
351
                )
352
            );
353
354
            return false;
355
        } elseif ($totalFileSize > intval(api_get_setting('message_max_upload_filesize'))) {
356
            $warning = sprintf(
357
                get_lang("FilesSizeExceedsX"),
358
                format_file_size(api_get_setting('message_max_upload_filesize'))
359
            );
360
361
            Display::addFlash(Display::return_message($warning, 'warning'));
362
363
            return false;
364
        }
365
366
        // Just in case we replace the and \n and \n\r while saving in the DB
367
        // $content = str_replace(array("\n", "\n\r"), '<br />', $content);
368
        $now = api_get_utc_datetime();
369
        if (!empty($receiver_user_id) || !empty($group_id)) {
370
            // message for user friend
371
            //@todo it's possible to edit a message? yes, only for groups
372
            if (!empty($editMessageId)) {
373
                $query = " UPDATE $table SET
374
                                update_date = '".$now."',
375
                                content = '".Database::escape_string($content)."'
376
                           WHERE id = '$editMessageId' ";
377
                Database::query($query);
378
                $messageId = $editMessageId;
379
            } else {
380
                $params = [
381
                    'user_sender_id' => $user_sender_id,
382
                    'user_receiver_id' => $receiver_user_id,
383
                    'msg_status' => MESSAGE_STATUS_UNREAD,
384
                    'send_date' => $now,
385
                    'title' => $subject,
386
                    'content' => $content,
387
                    'group_id' => $group_id,
388
                    'parent_id' => $parent_id,
389
                    'update_date' => $now,
390
                ];
391
                $messageId = Database::insert($table, $params);
392
            }
393
394
            // Forward also message attachments
395
            if (!empty($forwardId)) {
396
                $attachments = MessageManager::getAttachmentList($forwardId);
397
                foreach ($attachments as $attachment) {
398
                    if (!empty($attachment['file_source'])) {
399
                        $file = [
400
                            'name' => $attachment['filename'],
401
                            'tmp_name' => $attachment['file_source'],
402
                            'size' => $attachment['size'],
403
                            'error' => 0,
404
                            'comment' => $attachment['comment'],
405
                        ];
406
407
                        // Inject this array so files can be added when sending and email with the mailer
408
                        $attachmentList[] = $file;
409
                    }
410
                }
411
            }
412
413
            // Save attachment file for inbox messages
414
            if (is_array($attachmentList)) {
415
                foreach ($attachmentList as $attachment) {
416
                    if ($attachment['error'] == 0) {
417
                        $comment = $attachment['comment'];
418
                        self::saveMessageAttachmentFile(
419
                            $attachment,
420
                            $comment,
421
                            $messageId,
422
                            null,
423
                            $receiver_user_id,
424
                            $group_id
425
                        );
426
                    }
427
                }
428
            }
429
430
            if (empty($group_id)) {
431
                // message in outbox for user friend or group
432
                $params = [
433
                    'user_sender_id' => $user_sender_id,
434
                    'user_receiver_id' => $receiver_user_id,
435
                    'msg_status' => MESSAGE_STATUS_OUTBOX,
436
                    'send_date' => $now,
437
                    'title' => $subject,
438
                    'content' => $content,
439
                    'group_id' => $group_id,
440
                    'parent_id' => $parent_id,
441
                    'update_date' => $now,
442
                ];
443
                $outbox_last_id = Database::insert($table, $params);
444
445
                // save attachment file for outbox messages
446
                if (is_array($attachmentList)) {
447
                    foreach ($attachmentList as $attachment) {
448
                        if ($attachment['error'] == 0) {
449
                            $comment = $attachment['comment'];
450
                            self::saveMessageAttachmentFile(
451
                                $attachment,
452
                                $comment,
453
                                $outbox_last_id,
454
                                $user_sender_id
455
                            );
456
                        }
457
                    }
458
                }
459
            }
460
461
            // Load user settings.
462
            $notification = new Notification();
463
            $sender_info = api_get_user_info($user_sender_id);
464
465
            // add file attachment additional attributes
466
            $attachmentAddedByMail = [];
467
            foreach ($attachmentList as $attachment) {
468
                $attachmentAddedByMail[] = [
469
                    'path' => $attachment['tmp_name'],
470
                    'filename' => $attachment['name'],
471
                ];
472
            }
473
474
            if (empty($group_id)) {
475
                $type = Notification::NOTIFICATION_TYPE_MESSAGE;
476
                if ($directMessage) {
477
                    $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
478
                }
479
                $notification->saveNotification(
480
                    $messageId,
481
                    $type,
482
                    [$receiver_user_id],
483
                    $subject,
484
                    $content,
485
                    $sender_info,
486
                    $attachmentAddedByMail,
487
                    $smsParameters
488
                );
489
            } else {
490
                $usergroup = new UserGroup();
491
                $group_info = $usergroup->get($group_id);
492
                $group_info['topic_id'] = $topic_id;
493
                $group_info['msg_id'] = $messageId;
494
495
                $user_list = $usergroup->get_users_by_group(
496
                    $group_id,
497
                    false,
498
                    [],
499
                    0,
500
                    1000
501
                );
502
503
                // Adding more sense to the message group
504
                $subject = sprintf(get_lang('ThereIsANewMessageInTheGroupX'), $group_info['name']);
505
                $new_user_list = [];
506
                foreach ($user_list as $user_data) {
507
                    $new_user_list[] = $user_data['id'];
508
                }
509
                $group_info = [
510
                    'group_info' => $group_info,
511
                    'user_info' => $sender_info,
512
                ];
513
                $notification->saveNotification(
514
                    $messageId,
515
                    Notification::NOTIFICATION_TYPE_GROUP,
516
                    $new_user_list,
517
                    $subject,
518
                    $content,
519
                    $group_info,
520
                    $attachmentAddedByMail,
521
                    $smsParameters
522
                );
523
            }
524
525
            return $messageId;
526
        }
527
528
        return false;
529
    }
530
531
    /**
532
     * @param int    $receiver_user_id
533
     * @param int    $subject
534
     * @param string $message
535
     * @param int    $sender_id
536
     * @param bool   $sendCopyToDrhUsers send copy to related DRH users
537
     * @param bool   $directMessage
538
     * @param array  $smsParameters
539
     * @param bool   $uploadFiles        Do not upload files using the MessageManager class
540
     * @param array  $attachmentList
541
     *
542
     * @return bool
543
     */
544
    public static function send_message_simple(
545
        $receiver_user_id,
546
        $subject,
547
        $message,
548
        $sender_id = 0,
549
        $sendCopyToDrhUsers = false,
550
        $directMessage = false,
551
        $smsParameters = [],
552
        $uploadFiles = true,
553
        $attachmentList = []
554
    ) {
555
        $files = $_FILES ? $_FILES : [];
556
        if ($uploadFiles === false) {
557
            $files = [];
558
        }
559
        // $attachmentList must have: tmp_name, name, size keys
560
        if (!empty($attachmentList)) {
561
            $files = $attachmentList;
562
        }
563
        $result = self::send_message(
564
            $receiver_user_id,
565
            $subject,
566
            $message,
567
            $files,
568
            [],
569
            null,
570
            null,
571
            null,
572
            null,
573
            $sender_id,
574
            $directMessage,
575
            0,
576
            $smsParameters
577
        );
578
579
        if ($sendCopyToDrhUsers) {
580
            $userInfo = api_get_user_info($receiver_user_id);
581
            $drhList = UserManager::getDrhListFromUser($receiver_user_id);
582
            if (!empty($drhList)) {
583
                foreach ($drhList as $drhInfo) {
584
                    $message = sprintf(
585
                        get_lang('CopyOfMessageSentToXUser'),
586
                        $userInfo['complete_name']
587
                    ).' <br />'.$message;
588
589
                    self::send_message_simple(
590
                        $drhInfo['user_id'],
591
                        $subject,
592
                        $message,
593
                        $sender_id,
594
                        false,
595
                        $directMessage
596
                    );
597
                }
598
            }
599
        }
600
601
        return $result;
602
    }
603
604
    /**
605
     * Update parent ids for other receiver user from current message in groups.
606
     *
607
     * @author Christian Fasanando Flores
608
     *
609
     * @param int $parent_id
610
     * @param int $receiver_user_id
611
     * @param int $messageId
612
     */
613
    public static function update_parent_ids_from_reply(
614
        $parent_id,
615
        $receiver_user_id,
616
        $messageId
617
    ) {
618
        $table = Database::get_main_table(TABLE_MESSAGE);
619
        $parent_id = intval($parent_id);
620
        $receiver_user_id = intval($receiver_user_id);
621
        $messageId = intval($messageId);
622
623
        // first get data from message id (parent)
624
        $sql = "SELECT * FROM $table WHERE id = '$parent_id'";
625
        $rs_message = Database::query($sql);
626
        $row_message = Database::fetch_array($rs_message);
627
628
        // get message id from data found early for other receiver user
629
        $sql = "SELECT id FROM $table
630
                WHERE
631
                    user_sender_id ='{$row_message['user_sender_id']}' AND
632
                    title='{$row_message['title']}' AND
633
                    content='{$row_message['content']}' AND
634
                    group_id='{$row_message['group_id']}' AND
635
                    user_receiver_id='$receiver_user_id'";
636
        $result = Database::query($sql);
637
        $row = Database::fetch_array($result);
638
639
        // update parent_id for other user receiver
640
        $sql = "UPDATE $table SET parent_id = ".$row['id']."
641
                WHERE id = $messageId";
642
        Database::query($sql);
643
    }
644
645
    /**
646
     * @param int $user_receiver_id
647
     * @param int $id
648
     *
649
     * @return bool
650
     */
651
    public static function delete_message_by_user_receiver($user_receiver_id, $id)
652
    {
653
        $table = Database::get_main_table(TABLE_MESSAGE);
654
        if ($id != strval(intval($id))) {
655
            return false;
656
        }
657
        $user_receiver_id = intval($user_receiver_id);
658
        $id = intval($id);
659
        $sql = "SELECT * FROM $table
660
                WHERE id = ".$id." AND msg_status <>".MESSAGE_STATUS_OUTBOX;
661
        $rs = Database::query($sql);
662
663
        if (Database::num_rows($rs) > 0) {
664
            // delete attachment file
665
            self::delete_message_attachment_file($id, $user_receiver_id);
666
            // delete message
667
            $query = "UPDATE $table 
668
                      SET msg_status = ".MESSAGE_STATUS_DELETED."
669
                      WHERE 
670
                        user_receiver_id=".$user_receiver_id." AND 
671
                        id = ".$id;
672
            Database::query($query);
673
674
            return true;
675
        } else {
676
            return false;
677
        }
678
    }
679
680
    /**
681
     * Set status deleted.
682
     *
683
     * @author Isaac FLores Paz <[email protected]>
684
     *
685
     * @param  int
686
     * @param  int
687
     *
688
     * @return bool
689
     */
690
    public static function delete_message_by_user_sender($user_sender_id, $id)
691
    {
692
        if ($id != strval(intval($id))) {
693
            return false;
694
        }
695
696
        $table = Database::get_main_table(TABLE_MESSAGE);
697
698
        $id = intval($id);
699
        $user_sender_id = intval($user_sender_id);
700
701
        $sql = "SELECT * FROM $table WHERE id='$id'";
702
        $rs = Database::query($sql);
703
704
        if (Database::num_rows($rs) > 0) {
705
            // delete attachment file
706
            self::delete_message_attachment_file($id, $user_sender_id);
707
            // delete message
708
            $sql = "UPDATE $table 
709
                    SET msg_status = ".MESSAGE_STATUS_DELETED."
710
                    WHERE user_sender_id='$user_sender_id' AND id='$id'";
711
            Database::query($sql);
712
713
            return true;
714
        }
715
716
        return false;
717
    }
718
719
    /**
720
     * Saves a message attachment files.
721
     *
722
     * @param array $file_attach $_FILES['name']
723
     * @param  string    a comment about the uploaded file
724
     * @param  int        message id
725
     * @param  int        receiver user id (optional)
726
     * @param  int        sender user id (optional)
727
     * @param  int        group id (optional)
728
     */
729
    public static function saveMessageAttachmentFile(
730
        $file_attach,
731
        $file_comment,
732
        $message_id,
733
        $receiver_user_id = 0,
734
        $sender_user_id = 0,
735
        $group_id = 0
736
    ) {
737
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
738
739
        // Try to add an extension to the file if it hasn't one
740
        $type = isset($file_attach['type']) ? $file_attach['type'] : '';
741
        if (empty($type)) {
742
            $type = DocumentManager::file_get_mime_type($file_attach['name']);
743
        }
744
        $new_file_name = add_ext_on_mime(stripslashes($file_attach['name']), $type);
745
746
        // user's file name
747
        $file_name = $file_attach['name'];
748
        if (!filter_extension($new_file_name)) {
749
            Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
750
        } else {
751
            $new_file_name = uniqid('');
752
            if (!empty($receiver_user_id)) {
753
                $message_user_id = $receiver_user_id;
754
            } else {
755
                $message_user_id = $sender_user_id;
756
            }
757
758
            // User-reserved directory where photos have to be placed.*
759
            $userGroup = new UserGroup();
760
            if (!empty($group_id)) {
761
                $path_user_info = $userGroup->get_group_picture_path_by_id(
762
                    $group_id,
763
                    'system',
764
                    true
765
                );
766
            } else {
767
                $path_user_info['dir'] = UserManager::getUserPathById($message_user_id, 'system');
768
            }
769
770
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
771
            // If this directory does not exist - we create it.
772
            if (!file_exists($path_message_attach)) {
773
                @mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);
774
            }
775
776
            $new_path = $path_message_attach.$new_file_name;
777
            $fileCopied = false;
778
            if (isset($file_attach['tmp_name']) && !empty($file_attach['tmp_name'])) {
779
                if (is_uploaded_file($file_attach['tmp_name'])) {
780
                    @copy($file_attach['tmp_name'], $new_path);
781
                    $fileCopied = true;
782
                } else {
783
                    // 'tmp_name' can be set by the ticket or when forwarding a message
784
                    if (file_exists($file_attach['tmp_name'])) {
785
                        @copy($file_attach['tmp_name'], $new_path);
786
                        $fileCopied = true;
787
                    }
788
                }
789
            }
790
791
            if ($fileCopied) {
792
                // Storing the attachments if any
793
                $params = [
794
                    'filename' => $file_name,
795
                    'comment' => $file_comment,
796
                    'path' => $new_file_name,
797
                    'message_id' => $message_id,
798
                    'size' => $file_attach['size'],
799
                ];
800
                Database::insert($table, $params);
801
            }
802
        }
803
    }
804
805
    /**
806
     * Delete message attachment files (logically updating the row with a suffix _DELETE_id).
807
     *
808
     * @param  int    message id
809
     * @param  int    message user id (receiver user id or sender user id)
810
     * @param  int    group id (optional)
811
     */
812
    public static function delete_message_attachment_file(
813
        $message_id,
814
        $message_uid,
815
        $group_id = 0
816
    ) {
817
        $message_id = intval($message_id);
818
        $message_uid = intval($message_uid);
819
        $table_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
820
821
        $sql = "SELECT * FROM $table_message_attach 
822
                WHERE message_id = '$message_id'";
823
        $rs = Database::query($sql);
824
        while ($row = Database::fetch_array($rs)) {
825
            $path = $row['path'];
826
            $attach_id = $row['id'];
827
            $new_path = $path.'_DELETED_'.$attach_id;
828
829
            if (!empty($group_id)) {
830
                $userGroup = new UserGroup();
831
                $path_user_info = $userGroup->get_group_picture_path_by_id(
832
                    $group_id,
833
                    'system',
834
                    true
835
                );
836
            } else {
837
                $path_user_info['dir'] = UserManager::getUserPathById(
838
                    $message_uid,
839
                    'system'
840
                );
841
            }
842
843
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
844
            if (is_file($path_message_attach.$path)) {
845
                if (rename($path_message_attach.$path, $path_message_attach.$new_path)) {
846
                    $sql = "UPDATE $table_message_attach set path='$new_path'
847
                            WHERE id ='$attach_id'";
848
                    Database::query($sql);
849
                }
850
            }
851
        }
852
    }
853
854
    /**
855
     * update messages by user id and message id.
856
     *
857
     * @param int $user_id
858
     * @param int $message_id
859
     *
860
     * @return bool
861
     */
862
    public static function update_message($user_id, $message_id)
863
    {
864
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
865
            return false;
866
        }
867
868
        $table = Database::get_main_table(TABLE_MESSAGE);
869
        $sql = "UPDATE $table SET 
870
                    msg_status = '".MESSAGE_STATUS_NEW."'
871
                WHERE
872
                    msg_status <> ".MESSAGE_STATUS_OUTBOX." AND
873
                    user_receiver_id = ".intval($user_id)." AND
874
                    id = '".intval($message_id)."'";
875
        Database::query($sql);
876
877
        return true;
878
    }
879
880
    /**
881
     * @param int    $user_id
882
     * @param int    $message_id
883
     * @param string $type
884
     *
885
     * @return bool
886
     */
887
    public static function update_message_status($user_id, $message_id, $type)
888
    {
889
        $type = intval($type);
890
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
891
            return false;
892
        }
893
        $table_message = Database::get_main_table(TABLE_MESSAGE);
894
        $sql = "UPDATE $table_message SET
895
                    msg_status = '$type'
896
                WHERE
897
                    user_receiver_id = ".intval($user_id)." AND
898
                    id = '".intval($message_id)."'";
899
        Database::query($sql);
900
    }
901
902
    /**
903
     * get messages by user id and message id.
904
     *
905
     * @param int $user_id
906
     * @param int $message_id
907
     *
908
     * @return array
909
     */
910
    public static function get_message_by_user($user_id, $message_id)
911
    {
912
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
913
            return false;
914
        }
915
        $table = Database::get_main_table(TABLE_MESSAGE);
916
        $query = "SELECT * FROM $table
917
                  WHERE user_receiver_id=".intval($user_id)." AND id='".intval($message_id)."'";
918
        $result = Database::query($query);
919
920
        return $row = Database::fetch_array($result);
921
    }
922
923
    /**
924
     * get messages by group id.
925
     *
926
     * @param int $group_id group id
927
     *
928
     * @return array
929
     */
930
    public static function get_messages_by_group($group_id)
931
    {
932
        if ($group_id != strval(intval($group_id))) {
933
            return false;
934
        }
935
936
        $table = Database::get_main_table(TABLE_MESSAGE);
937
        $group_id = intval($group_id);
938
        $sql = "SELECT * FROM $table
939
                WHERE
940
                    group_id= $group_id AND
941
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
942
                ORDER BY id";
943
        $rs = Database::query($sql);
944
        $data = [];
945
        if (Database::num_rows($rs) > 0) {
946
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
947
                $data[] = $row;
948
            }
949
        }
950
951
        return $data;
952
    }
953
954
    /**
955
     * get messages by group id.
956
     *
957
     * @param int $group_id
958
     * @param int $message_id
959
     *
960
     * @return array
961
     */
962
    public static function get_messages_by_group_by_message($group_id, $message_id)
963
    {
964
        if ($group_id != strval(intval($group_id))) {
965
            return false;
966
        }
967
        $table = Database::get_main_table(TABLE_MESSAGE);
968
        $group_id = intval($group_id);
969
        $sql = "SELECT * FROM $table
970
                WHERE
971
                    group_id = $group_id AND
972
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
973
                ORDER BY id ";
974
975
        $rs = Database::query($sql);
976
        $data = [];
977
        $parents = [];
978
        if (Database::num_rows($rs) > 0) {
979
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
980
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
981
                    $parents[] = $row['id'];
982
                    $data[] = $row;
983
                }
984
            }
985
        }
986
987
        return $data;
988
    }
989
990
    /**
991
     * Get messages by parent id optionally with limit.
992
     *
993
     * @param  int        parent id
994
     * @param  int        group id (optional)
995
     * @param  int        offset (optional)
996
     * @param  int        limit (optional)
997
     *
998
     * @return array
999
     */
1000
    public static function get_messages_by_parent($parent_id, $group_id = 0, $offset = 0, $limit = 0)
1001
    {
1002
        if ($parent_id != strval(intval($parent_id))) {
1003
            return false;
1004
        }
1005
        $table = Database::get_main_table(TABLE_MESSAGE);
1006
        $parent_id = intval($parent_id);
1007
        $condition_group_id = '';
1008
        if (!empty($group_id)) {
1009
            $group_id = intval($group_id);
1010
            $condition_group_id = " AND group_id = '$group_id' ";
1011
        }
1012
1013
        $condition_limit = '';
1014
        if ($offset && $limit) {
1015
            $offset = ($offset - 1) * $limit;
1016
            $condition_limit = " LIMIT $offset,$limit ";
1017
        }
1018
1019
        $sql = "SELECT * FROM $table
1020
                WHERE
1021
                    parent_id='$parent_id' AND
1022
                    msg_status <> ".MESSAGE_STATUS_OUTBOX."
1023
                    $condition_group_id
1024
                ORDER BY send_date DESC $condition_limit ";
1025
        $rs = Database::query($sql);
1026
        $data = [];
1027
        if (Database::num_rows($rs) > 0) {
1028
            while ($row = Database::fetch_array($rs)) {
1029
                $data[$row['id']] = $row;
1030
            }
1031
        }
1032
1033
        return $data;
1034
    }
1035
1036
    /**
1037
     * Gets information about messages sent.
1038
     *
1039
     * @param  int
1040
     * @param  int
1041
     * @param  string
1042
     *
1043
     * @return array
1044
     */
1045
    public static function get_message_data_sent(
1046
        $from,
1047
        $number_of_items,
1048
        $column,
1049
        $direction
1050
    ) {
1051
        $from = intval($from);
1052
        $number_of_items = intval($number_of_items);
1053
        if (!isset($direction)) {
1054
            $column = 2;
1055
            $direction = 'DESC';
1056
        } else {
1057
            $column = intval($column);
1058
            if (!in_array($direction, ['ASC', 'DESC'])) {
1059
                $direction = 'ASC';
1060
            }
1061
        }
1062
1063
        if (!in_array($column, [0, 1, 2])) {
1064
            $column = 2;
1065
        }
1066
        $table = Database::get_main_table(TABLE_MESSAGE);
1067
        $request = api_is_xml_http_request();
1068
        $keyword = Session::read('message_sent_search_keyword');
1069
        $keywordCondition = '';
1070
        if (!empty($keyword)) {
1071
            $keyword = Database::escape_string($keyword);
1072
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1073
        }
1074
1075
        $sql = "SELECT
1076
                    id as col0, 
1077
                    title as col1, 
1078
                    send_date as col2, 
1079
                    user_receiver_id, 
1080
                    msg_status,
1081
                    user_sender_id
1082
                FROM $table
1083
                WHERE
1084
                    user_sender_id = ".api_get_user_id()." AND
1085
                    msg_status = ".MESSAGE_STATUS_OUTBOX."
1086
                    $keywordCondition
1087
                ORDER BY col$column $direction
1088
                LIMIT $from, $number_of_items";
1089
        $result = Database::query($sql);
1090
        $i = 0;
1091
        $message_list = [];
1092
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1093
            $messageId = $row['col0'];
1094
            $title = $row['col1'];
1095
            $sendDate = $row['col2'];
1096
            $status = $row['msg_status'];
1097
            $senderId = $row['user_sender_id'];
1098
1099
            if ($request === true) {
1100
                $message[0] = '<input type="checkbox" value='.$messageId.' name="out[]">';
1101
            } else {
1102
                $message[0] = $messageId;
1103
            }
1104
1105
            $class = 'class = "read"';
1106
            $title = Security::remove_XSS($title);
1107
            $userInfo = api_get_user_info($senderId);
1108
            if ($request === true) {
1109
                $message[1] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.$userInfo['complete_name_with_username'].'</a>';
1110
                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace(
1111
                        "\\",
1112
                        "",
1113
                        $title
1114
                    ).'</a>';
1115
                //date stays the same
1116
                $message[3] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1117
                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(
1118
                        get_lang('DeleteMessage')
1119
                    ).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
1120
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1121
            } else {
1122
                $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'];
1123
                $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1124
                $message[3] = '<a title="'.addslashes(
1125
                        get_lang('DeleteMessage')
1126
                    ).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(
1127
                        api_htmlentities(get_lang('ConfirmDeleteMessage'))
1128
                    )."'".')) return false;" >'.
1129
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1130
            }
1131
1132
            $message_list[] = $message;
1133
            $i++;
1134
        }
1135
1136
        return $message_list;
1137
    }
1138
1139
    /**
1140
     * Gets information about number messages sent.
1141
     *
1142
     * @author Isaac FLores Paz <[email protected]>
1143
     *
1144
     * @param void
1145
     *
1146
     * @return int
1147
     */
1148
    public static function getNumberOfMessagesSent()
1149
    {
1150
        $table = Database::get_main_table(TABLE_MESSAGE);
1151
        $keyword = Session::read('message_sent_search_keyword');
1152
        $keywordCondition = '';
1153
        if (!empty($keyword)) {
1154
            $keyword = Database::escape_string($keyword);
1155
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1156
        }
1157
1158
        $sql = "SELECT COUNT(id) as number_messages 
1159
                FROM $table
1160
                WHERE
1161
                  msg_status = ".MESSAGE_STATUS_OUTBOX." AND
1162
                  user_sender_id = ".api_get_user_id()."
1163
                  $keywordCondition
1164
                ";
1165
        $result = Database::query($sql);
1166
        $result = Database::fetch_array($result);
1167
1168
        return $result['number_messages'];
1169
    }
1170
1171
    /**
1172
     * display message box in the inbox.
1173
     *
1174
     * @param int the message id
1175
     * @param string inbox or outbox strings are available
1176
     *
1177
     * @todo replace numbers with letters in the $row array pff...
1178
     *
1179
     * @return string html with the message content
1180
     */
1181
    public static function showMessageBox($messageId, $source = 'inbox')
1182
    {
1183
        $table = Database::get_main_table(TABLE_MESSAGE);
1184
        $messageId = intval($messageId);
1185
1186
        if ($source == 'outbox') {
1187
            if (isset($messageId) && is_numeric($messageId)) {
1188
                $query = "SELECT * FROM $table
1189
                          WHERE
1190
                            user_sender_id = ".api_get_user_id()." AND
1191
                            id = ".$messageId." AND
1192
                            msg_status = ".MESSAGE_STATUS_OUTBOX;
1193
                $result = Database::query($query);
1194
            }
1195
        } else {
1196
            if (is_numeric($messageId) && !empty($messageId)) {
1197
                $query = "UPDATE $table SET
1198
                          msg_status = '".MESSAGE_STATUS_NEW."'
1199
                          WHERE
1200
                            user_receiver_id=".api_get_user_id()." AND
1201
                            id='".$messageId."'";
1202
                Database::query($query);
1203
1204
                $query = "SELECT * FROM $table
1205
                          WHERE
1206
                            msg_status<> ".MESSAGE_STATUS_OUTBOX." AND
1207
                            user_receiver_id=".api_get_user_id()." AND
1208
                            id='".$messageId."'";
1209
                $result = Database::query($query);
1210
            }
1211
        }
1212
        $row = Database::fetch_array($result, 'ASSOC');
1213
        $user_sender_id = $row['user_sender_id'];
1214
1215
        // get file attachments by message id
1216
        $files_attachments = self::getAttachmentLinkList(
1217
            $messageId,
1218
            $source
1219
        );
1220
1221
        $row['content'] = str_replace('</br>', '<br />', $row['content']);
1222
        $title = Security::remove_XSS($row['title'], STUDENT, true);
1223
        $content = Security::remove_XSS($row['content'], STUDENT, true);
1224
1225
        $name = get_lang('UnknownUser');
1226
        $fromUser = api_get_user_info($user_sender_id);
1227
        $userImage = '';
1228
        if (!empty($user_sender_id) && !empty($fromUser)) {
1229
            $name = $fromUser['complete_name_with_username'];
1230
            $userImage = Display::img(
1231
                $fromUser['avatar_small'],
1232
                $name,
1233
                ['title' => $name, 'class' => 'img-responsive img-circle', 'style' => 'max-width:35px'],
1234
                false
1235
            );
1236
        }
1237
1238
        $message_content = Display::page_subheader(str_replace("\\", "", $title));
1239
1240
        $receiverUserInfo = [];
1241
        if (!empty($row['user_receiver_id'])) {
1242
            $receiverUserInfo = api_get_user_info($row['user_receiver_id']);
1243
        }
1244
1245
        $message_content .= '<tr>';
1246
        if (api_get_setting('allow_social_tool') == 'true') {
1247
            $message_content .= '<div class="row">';
1248
            if ($source == 'outbox') {
1249
                $message_content .= '<div class="col-md-12">';
1250
                $message_content .= '<ul class="list-message">';
1251
                $message_content .= '<li>'.$userImage.'</li>';
1252
                $message_content .= '<li>'.$name.'&nbsp;';
1253
                if (!empty($receiverUserInfo)) {
1254
                    $message_content .= api_strtolower(
1255
                            get_lang('To')
1256
                        ).'&nbsp;<b>'.$receiverUserInfo['complete_name_with_username'].'</b></li>';
1257
                } else {
1258
                    $message_content .= api_strtolower(get_lang('To')).'&nbsp;<b>-</b></li>';
1259
                }
1260
1261
                $message_content .= '<li>'.Display::dateToStringAgoAndLongDate($row['send_date']).'</li>';
1262
                $message_content .= '</ul>';
1263
                $message_content .= '</div>';
1264
            } else {
1265
                $message_content .= '<div class="col-md-12">';
1266
                $message_content .= '<ul class="list-message">';
1267
                if (!empty($user_sender_id)) {
1268
                    $message_content .= '<li>'.$userImage.'</li>';
1269
                    $message_content .= '<li><a href="'.api_get_path(
1270
                            WEB_PATH
1271
                        ).'main/social/profile.php?u='.$user_sender_id.'">'.$name.'</a>';
1272
                } else {
1273
                    $message_content .= '<li>'.$name;
1274
                }
1275
1276
                $message_content .= '&nbsp;'.api_strtolower(get_lang('To')).'&nbsp;'.get_lang('Me');
1277
                $message_content .= '<li>'.Display::dateToStringAgoAndLongDate($row['send_date']).'</li>';
1278
                $message_content .= '</ul>';
1279
                $message_content .= '</div>';
1280
            }
1281
            $message_content .= '</div>';
1282
        } else {
1283
            if ($source == 'outbox') {
1284
                $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1285
                    $receiverUserInfo['complete_name_with_username'].'</b>';
1286
            } else {
1287
                $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1288
                    get_lang('Me').'</b>';
1289
            }
1290
        }
1291
1292
        $message_content .= '		        
1293
		        <hr style="color:#ddd" />
1294
		        <table width="100%">
1295
		            <tr>
1296
		              <td valign=top class="view-message-content">'.str_replace("\\", "", $content).'</td>
1297
		            </tr>
1298
		        </table>
1299
		        <div id="message-attach">'.(!empty($files_attachments) ? implode('<br />', $files_attachments) : '').'</div>
1300
		        <div style="padding: 15px 0px 5px 0px">';
1301
        $social_link = '';
1302
        if (isset($_GET['f']) && $_GET['f'] == 'social') {
1303
            $social_link = 'f=social';
1304
        }
1305
        if ($source == 'outbox') {
1306
            $message_content .= '<a href="outbox.php?'.$social_link.'">'.
1307
                Display::return_icon('back.png', get_lang('ReturnToOutbox')).'</a> &nbsp';
1308
        } else {
1309
            $message_content .= '<a href="inbox.php?'.$social_link.'">'.
1310
                Display::return_icon('back.png', get_lang('ReturnToInbox')).'</a> &nbsp';
1311
            $message_content .= '<a href="new_message.php?re_id='.$messageId.'&'.$social_link.'">'.
1312
                Display::return_icon('message_reply.png', get_lang('ReplyToMessage')).'</a> &nbsp';
1313
        }
1314
        $message_content .= '<a href="inbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1315
            Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp';
1316
1317
        $message_content .= '</div></td>
1318
		      <td width=10></td>
1319
		    </tr>
1320
		</table>';
1321
1322
        return $message_content;
1323
    }
1324
1325
    /**
1326
     * get user id by user email.
1327
     *
1328
     * @param string $user_email
1329
     *
1330
     * @return int user id
1331
     */
1332
    public static function get_user_id_by_email($user_email)
1333
    {
1334
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1335
        $sql = 'SELECT user_id FROM '.$tbl_user.'
1336
                WHERE email="'.Database::escape_string($user_email).'";';
1337
        $rs = Database::query($sql);
1338
        $row = Database::fetch_array($rs, 'ASSOC');
1339
        if (isset($row['user_id'])) {
1340
            return $row['user_id'];
1341
        } else {
1342
            return null;
1343
        }
1344
    }
1345
1346
    /**
1347
     * Displays messages of a group with nested view.
1348
     *
1349
     * @param int $group_id
1350
     *
1351
     * @return string
1352
     */
1353
    public static function display_messages_for_group($group_id)
1354
    {
1355
        global $my_group_role;
1356
1357
        $rows = self::get_messages_by_group($group_id);
1358
        $topics_per_page = 10;
1359
        $html_messages = '';
1360
        $query_vars = ['id' => $group_id, 'topics_page_nr' => 0];
1361
1362
        if (is_array($rows) && count($rows) > 0) {
1363
            // prepare array for topics with its items
1364
            $topics = [];
1365
            $x = 0;
1366
            foreach ($rows as $index => $value) {
1367
                if (empty($value['parent_id'])) {
1368
                    $topics[$value['id']] = $value;
1369
                }
1370
            }
1371
1372
            $new_topics = [];
1373
1374
            foreach ($topics as $id => $value) {
1375
                $rows = null;
1376
                $rows = self::get_messages_by_group_by_message($group_id, $value['id']);
1377
                if (!empty($rows)) {
1378
                    $count = count(self::calculate_children($rows, $value['id']));
1379
                } else {
1380
                    $count = 0;
1381
                }
1382
                $value['count'] = $count;
1383
                $new_topics[$id] = $value;
1384
            }
1385
1386
            $array_html = [];
1387
            foreach ($new_topics as $index => $topic) {
1388
                $html = '';
1389
                // topics
1390
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1391
                $name = $user_sender_info['complete_name'];
1392
                $html .= '<div class="groups-messages">';
1393
                $html .= '<div class="row">';
1394
1395
                $items = $topic['count'];
1396
                $reply_label = ($items == 1) ? get_lang('GroupReply') : get_lang('GroupReplies');
1397
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
1398
                $topic['title'] = trim($topic['title']);
1399
1400
                if (empty($topic['title'])) {
1401
                    $topic['title'] = get_lang('Untitled');
1402
                }
1403
1404
                $html .= '<div class="col-xs-8 col-md-10">';
1405
                $html .= Display::tag(
1406
                    'h4',
1407
                    Display::url(
1408
                        Security::remove_XSS($topic['title'], STUDENT, true),
1409
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$group_id.'&topic_id='.$topic['id']
1410
                    ),
1411
                    ['class' => 'title']
1412
                );
1413
                $actions = '';
1414
                if ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1415
                    $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1416
                ) {
1417
                    $actions = '<br />'.Display::url(
1418
                            get_lang('Delete'),
1419
                            api_get_path(
1420
                                WEB_CODE_PATH
1421
                            ).'social/group_topics.php?action=delete&id='.$group_id.'&topic_id='.$topic['id'],
1422
                            ['class' => 'btn btn-default']
1423
                        );
1424
                }
1425
1426
                $date = '';
1427
                if ($topic['send_date'] != $topic['update_date']) {
1428
                    if (!empty($topic['update_date'])) {
1429
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1430
                                'LastUpdate'
1431
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
1432
                    }
1433
                } else {
1434
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1435
                            'Created'
1436
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
1437
                }
1438
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
1439
                $html .= '</div>';
1440
1441
                $image = $user_sender_info['avatar'];
1442
1443
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
1444
                $user_info .= '<div class="name"><a href="'.api_get_path(
1445
                        WEB_PATH
1446
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
1447
1448
                $html .= '<div class="col-xs-4 col-md-2">';
1449
                $html .= $user_info;
1450
                $html .= '</div>';
1451
                $html .= '</div>';
1452
                $html .= '</div>';
1453
1454
                $array_html[] = [$html];
1455
            }
1456
1457
            // grids for items and topics  with paginations
1458
            $html_messages .= Display::return_sortable_grid(
1459
                'topics',
1460
                [],
1461
                $array_html,
1462
                [
1463
                    'hide_navigation' => false,
1464
                    'per_page' => $topics_per_page,
1465
                ],
1466
                $query_vars,
1467
                false,
1468
                [true, true, true, false],
1469
                false
1470
            );
1471
        }
1472
1473
        return $html_messages;
1474
    }
1475
1476
    /**
1477
     * Displays messages of a group with nested view.
1478
     *
1479
     * @param $group_id
1480
     * @param $topic_id
1481
     * @param $is_member
1482
     * @param $messageId
1483
     *
1484
     * @return string
1485
     */
1486
    public static function display_message_for_group($group_id, $topic_id, $is_member, $messageId)
1487
    {
1488
        global $my_group_role;
1489
        $main_message = self::get_message_by_id($topic_id);
1490
        if (empty($main_message)) {
1491
            return false;
1492
        }
1493
        $rows = self::get_messages_by_group_by_message($group_id, $topic_id);
1494
        $rows = self::calculate_children($rows, $topic_id);
1495
        $current_user_id = api_get_user_id();
1496
1497
        $items_per_page = 50;
1498
        $query_vars = ['id' => $group_id, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
1499
1500
        // Main message
1501
        $links = '';
1502
        $main_content = '';
1503
        $html = '';
1504
        $items_page_nr = null;
1505
1506
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1507
        $files_attachments = self::getAttachmentLinkList($main_message['id']);
1508
        $name = $user_sender_info['complete_name'];
1509
1510
        $topic_page_nr = isset($_GET['topics_page_nr']) ? intval($_GET['topics_page_nr']) : null;
1511
1512
        $links .= '<div class="pull-right">';
1513
        $links .= '<div class="btn-group btn-group-sm">';
1514
1515
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1516
                $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1517
            $main_message['user_sender_id'] == $current_user_id
1518
        ) {
1519
            $urlEdit = api_get_path(WEB_CODE_PATH);
1520
            $urlEdit .= 'social/message_for_group_form.inc.php?';
1521
            $urlEdit .= http_build_query(
1522
                [
1523
                    'user_friend' => $current_user_id,
1524
                    'group_id' => $group_id,
1525
                    'message_id' => $main_message['id'],
1526
                    'action' => 'edit_message_group',
1527
                    'anchor_topic' => 'topic_'.$main_message['id'],
1528
                    'topics_page_nr' => $topic_page_nr,
1529
                    'items_page_nr' => $items_page_nr,
1530
                    'topic_id' => $main_message['id'],
1531
                ]
1532
            );
1533
1534
            $links .= Display::url(
1535
                Display::returnFontAwesomeIcon('pencil'),
1536
                $urlEdit,
1537
                [
1538
                    'class' => 'btn btn-default ajax',
1539
                    'title' => get_lang('Edit'),
1540
                    'data-title' => get_lang('Edit'),
1541
                    'data-size' => 'lg',
1542
                ]
1543
            );
1544
        }
1545
1546
        $urlReply = api_get_path(WEB_CODE_PATH);
1547
        $urlReply .= 'social/message_for_group_form.inc.php?';
1548
        $urlReply .= http_build_query(
1549
            [
1550
                'user_friend' => api_get_user_id(),
1551
                'group_id' => $group_id,
1552
                'message_id' => $main_message['id'],
1553
                'action' => 'reply_message_group',
1554
                'anchor_topic' => 'topic_'.$main_message['id'],
1555
                'topics_page_nr' => $topic_page_nr,
1556
                'topic_id' => $main_message['id'],
1557
            ]
1558
        );
1559
1560
        $links .= Display::url(
1561
            Display::returnFontAwesomeIcon('commenting'),
1562
            $urlReply,
1563
            [
1564
                'class' => 'btn btn-default ajax',
1565
                'title' => get_lang('Reply'),
1566
                'data-title' => get_lang('Reply'),
1567
                'data-size' => 'lg',
1568
            ]
1569
        );
1570
1571
        if (api_is_platform_admin()) {
1572
            $links .= Display::url(
1573
                Display::returnFontAwesomeIcon('trash'),
1574
                'group_topics.php?action=delete&id='.$group_id.'&topic_id='.$topic_id,
1575
                [
1576
                    'class' => 'btn btn-default',
1577
                ]
1578
            );
1579
        }
1580
1581
        $links .= '</div>';
1582
        $links .= '</div>';
1583
1584
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
1585
1586
        $userPicture = $user_sender_info['avatar'];
1587
        $main_content .= '<div class="row">';
1588
        $main_content .= '<div class="col-md-2">';
1589
        $main_content .= '<div class="avatar-author">';
1590
        $main_content .= '<img width="60px" src="'.$userPicture.'" alt="'.$name.'" class="img-responsive img-circle" title="'.$name.'" />';
1591
        $main_content .= '</div>';
1592
        $main_content .= '</div>';
1593
1594
        $date = '';
1595
        if ($main_message['send_date'] != $main_message['update_date']) {
1596
            if (!empty($main_message['update_date'])) {
1597
                $date = '<div class="date"> '.
1598
                    Display::returnFontAwesomeIcon('calendar').' '.get_lang('LastUpdate').' '.
1599
                    Display::dateToStringAgoAndLongDate($main_message['update_date']).
1600
                    '</div>';
1601
            }
1602
        } else {
1603
            $date = '<div class="date"> '.
1604
                Display::returnFontAwesomeIcon('calendar').' '.get_lang('Created').' '.
1605
                Display::dateToStringAgoAndLongDate($main_message['send_date']).
1606
                '</div>';
1607
        }
1608
        $attachment = '<div class="message-attach">'.(!empty($files_attachments) ? implode(
1609
                '<br />',
1610
                $files_attachments
1611
            ) : '').'</div>';
1612
        $main_content .= '<div class="col-md-10">';
1613
        $user_link = '<a href="'.api_get_path(
1614
                WEB_PATH
1615
            ).'main/social/profile.php?u='.$main_message['user_sender_id'].'">'.$name.'</a>';
1616
        $main_content .= '<div class="message-content"> ';
1617
        $main_content .= '<div class="username">'.$user_link.'</div>';
1618
        $main_content .= $date;
1619
        $main_content .= '<div class="message">'.$main_message['content'].$attachment.'</div></div>';
1620
        $main_content .= '</div>';
1621
        $main_content .= '</div>';
1622
1623
        $html .= Display::div(
1624
            Display::div(
1625
                $title.$main_content,
1626
                ['class' => 'message-topic']
1627
            ),
1628
            ['class' => 'sm-groups-message']
1629
        );
1630
1631
        $topic_id = $main_message['id'];
1632
1633
        if (is_array($rows) && count($rows) > 0) {
1634
            $topics = $rows;
1635
            $array_html_items = [];
1636
            foreach ($topics as $index => $topic) {
1637
                if (empty($topic['id'])) {
1638
                    continue;
1639
                }
1640
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr']) ? intval(
1641
                    $_GET['items_'.$topic['id'].'_page_nr']
1642
                ) : null;
1643
                $links = '';
1644
                $links .= '<div class="pull-right">';
1645
                $html_items = '';
1646
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1647
                $files_attachments = self::getAttachmentLinkList($topic['id']);
1648
                $name = $user_sender_info['complete_name'];
1649
1650
                $links .= '<div class="btn-group btn-group-sm">';
1651
                if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1652
                    $topic['user_sender_id'] == $current_user_id
1653
                ) {
1654
                    $links .= '<a href="'.api_get_path(
1655
                            WEB_CODE_PATH
1656
                        ).'social/message_for_group_form.inc.php?height=400&width=800&&user_friend='.$current_user_id.'&group_id='.$group_id.'&message_id='.$topic['id'].'&action=edit_message_group&anchor_topic=topic_'.$topic_id.'&topics_page_nr='.$topic_page_nr.'&items_page_nr='.$items_page_nr.'&topic_id='.$topic_id.'" class="ajax btn btn-default" data-size="lg" data-title="'.get_lang(
1657
                            'Edit'
1658
                        ).'" title="'.get_lang('Edit').'">'.
1659
                        Display::returnFontAwesomeIcon('pencil').'</a>';
1660
                }
1661
                $links .= '<a href="'.api_get_path(
1662
                        WEB_CODE_PATH
1663
                    ).'social/message_for_group_form.inc.php?height=400&width=800&&user_friend='.api_get_user_id(
1664
                    ).'&group_id='.$group_id.'&message_id='.$topic['id'].'&action=reply_message_group&anchor_topic=topic_'.$topic_id.'&topics_page_nr='.$topic_page_nr.'&items_page_nr='.$items_page_nr.'&topic_id='.$topic_id.'" class="ajax btn btn-default" data-size="lg" data-title="'.get_lang(
1665
                        'Reply'
1666
                    ).'" title="'.get_lang('Reply').'">';
1667
                $links .= Display::returnFontAwesomeIcon('commenting').'</a>';
1668
                $links .= '</div>';
1669
                $links .= '</div>';
1670
1671
                $userPicture = $user_sender_info['avatar'];
1672
                $user_link = '<a href="'.api_get_path(
1673
                        WEB_PATH
1674
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp</a>';
1675
                $html_items .= '<div class="row">';
1676
                $html_items .= '<div class="col-md-2">';
1677
                $html_items .= '<div class="avatar-author">';
1678
                $html_items .= '<img width="60px" src="'.$userPicture.'" alt="'.$name.'" class="img-responsive img-circle" title="'.$name.'" /></div>';
1679
                $html_items .= '</div>';
1680
1681
                $date = '';
1682
                if ($topic['send_date'] != $topic['update_date']) {
1683
                    if (!empty($topic['update_date'])) {
1684
                        $date = '<div class="date"> '.
1685
                            Display::returnFontAwesomeIcon('calendar').' '.
1686
                            get_lang('LastUpdate').' '.Display::dateToStringAgoAndLongDate($topic['update_date']).
1687
                            '</div>';
1688
                    }
1689
                } else {
1690
                    $date = '<div class="date"> '.
1691
                        Display::returnFontAwesomeIcon('calendar').
1692
                        get_lang('Created').' '.Display::dateToStringAgoAndLongDate($topic['send_date']).
1693
                        '</div>';
1694
                }
1695
                $attachment = '<div class="message-attach">'.(!empty($files_attachments) ? implode(
1696
                        '<br />',
1697
                        $files_attachments
1698
                    ) : '').'</div>';
1699
                $html_items .= '<div class="col-md-10">';
1700
                $html_items .= '<div class="message-content">';
1701
                $html_items .= $links;
1702
                $html_items .= '<div class="username">'.$user_link.'</div>';
1703
                $html_items .= $date;
1704
                $html_items .= '<div class="message">'.
1705
                    Security::remove_XSS($topic['content'], STUDENT, true).
1706
                    '</div>'.$attachment.'</div>';
1707
                $html_items .= '</div>';
1708
                $html_items .= '</div>';
1709
1710
                $base_padding = 20;
1711
1712
                if ($topic['indent_cnt'] == 0) {
1713
                    $indent = $base_padding;
1714
                } else {
1715
                    $indent = intval($topic['indent_cnt']) * $base_padding + $base_padding;
1716
                }
1717
1718
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
1719
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
1720
                $array_html_items[] = [$html_items];
1721
            }
1722
1723
            // grids for items with paginations
1724
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
1725
            $visibility = [true, true, true, false];
1726
1727
            $style_class = [
1728
                'item' => ['class' => 'user-post'],
1729
                'main' => ['class' => 'user-list'],
1730
            ];
1731
            if (!empty($array_html_items)) {
1732
                $html .= Display::return_sortable_grid(
1733
                    'items_'.$topic['id'],
1734
                    [],
1735
                    $array_html_items,
1736
                    $options,
1737
                    $query_vars,
1738
                    null,
1739
                    $visibility,
1740
                    false,
1741
                    $style_class
1742
                );
1743
            }
1744
        }
1745
1746
        return $html;
1747
    }
1748
1749
    /**
1750
     * Add children to messages by id is used for nested view messages.
1751
     *
1752
     * @param array $rows rows of messages
1753
     *
1754
     * @return array $first_seed new list adding the item children
1755
     */
1756
    public static function calculate_children($rows, $first_seed)
1757
    {
1758
        $rows_with_children = [];
1759
        foreach ($rows as $row) {
1760
            $rows_with_children[$row["id"]] = $row;
1761
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
1762
        }
1763
        $rows = $rows_with_children;
1764
        $sorted_rows = [0 => []];
1765
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
1766
        unset($sorted_rows[0]);
1767
1768
        return $sorted_rows;
1769
    }
1770
1771
    /**
1772
     * Sort recursively the messages, is used for for nested view messages.
1773
     *
1774
     * @param array  original rows of messages
1775
     * @param array  list recursive of messages
1776
     * @param int   seed for calculate the indent
1777
     * @param int   indent for nested view
1778
     */
1779
    public static function message_recursive_sort(
1780
        $rows,
1781
        &$messages,
1782
        $seed = 0,
1783
        $indent = 0
1784
    ) {
1785
        if ($seed > 0 && isset($rows[$seed]["id"])) {
1786
            $messages[$rows[$seed]["id"]] = $rows[$seed];
1787
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
1788
            $indent++;
1789
        }
1790
1791
        if (isset($rows[$seed]["children"])) {
1792
            foreach ($rows[$seed]["children"] as $child) {
1793
                self::message_recursive_sort($rows, $messages, $child, $indent);
1794
            }
1795
        }
1796
    }
1797
1798
    /**
1799
     * Sort date by desc from a multi-dimensional array.
1800
     *
1801
     * @param array $array1 first array to compare
1802
     * @param array $array2 second array to compare
1803
     *
1804
     * @return bool
1805
     */
1806
    public function order_desc_date($array1, $array2)
1807
    {
1808
        return strcmp($array2['send_date'], $array1['send_date']);
1809
    }
1810
1811
    /**
1812
     * @param int $messageId
1813
     *
1814
     * @return array
1815
     */
1816
    public static function getAttachmentList($messageId)
1817
    {
1818
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1819
        $messageId = (int) $messageId;
1820
1821
        if (empty($messageId)) {
1822
            return [];
1823
        }
1824
1825
        $messageInfo = MessageManager::get_message_by_id($messageId);
1826
1827
        if (empty($messageInfo)) {
1828
            return [];
1829
        }
1830
1831
        $attachmentDir = UserManager::getUserPathById($messageInfo['user_receiver_id'], 'system');
1832
        $attachmentDir .= 'message_attachments/';
1833
1834
        $sql = "SELECT * FROM $table
1835
                WHERE message_id = '$messageId'";
1836
        $result = Database::query($sql);
1837
        $files = [];
1838
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1839
            $row['file_source'] = '';
1840
            if (file_exists($attachmentDir.$row['path'])) {
1841
                $row['file_source'] = $attachmentDir.$row['path'];
1842
            }
1843
            $files[] = $row;
1844
        }
1845
1846
        return $files;
1847
    }
1848
1849
    /**
1850
     * Get array of links (download) for message attachment files.
1851
     *
1852
     * @param int    $messageId
1853
     * @param string $type      message list (inbox/outbox)
1854
     *
1855
     * @return array
1856
     */
1857
    public static function get_links_message_attachment_files($messageId, $type = '')
1858
    {
1859
        $files = self::getAttachmentList($messageId);
1860
        // get file attachments by message id
1861
        $list = [];
1862
        if ($files) {
1863
            $attach_icon = Display::return_icon('attachment.gif', '');
1864
            $archiveURL = api_get_path(WEB_CODE_PATH).'messages/download.php?type='.$type.'&file=';
1865
            foreach ($files as $row_file) {
1866
                $archiveFile = $row_file['path'];
1867
                $filename = $row_file['filename'];
1868
                $filesize = format_file_size($row_file['size']);
1869
                $filecomment = Security::remove_XSS($row_file['comment']);
1870
                $filename = Security::remove_XSS($filename);
1871
                $list[] = $attach_icon.'&nbsp;<a href="'.$archiveURL.$archiveFile.'">'.$filename.'</a>
1872
                    &nbsp;('.$filesize.')'.(!empty($filecomment) ? '&nbsp;-&nbsp;<i>'.$filecomment.'</i>' : '');
1873
            }
1874
        }
1875
1876
        return $list;
1877
    }
1878
1879
    /**
1880
     * Get message list by id.
1881
     *
1882
     * @param int $messageId
1883
     *
1884
     * @return array
1885
     */
1886
    public static function get_message_by_id($messageId)
1887
    {
1888
        $table = Database::get_main_table(TABLE_MESSAGE);
1889
        $messageId = intval($messageId);
1890
        $sql = "SELECT * FROM $table
1891
                WHERE 
1892
                    id = '$messageId' AND 
1893
                    msg_status <> '".MESSAGE_STATUS_DELETED."' ";
1894
        $res = Database::query($sql);
1895
        $item = [];
1896
        if (Database::num_rows($res) > 0) {
1897
            $item = Database::fetch_array($res, 'ASSOC');
1898
        }
1899
1900
        return $item;
1901
    }
1902
1903
    /**
1904
     * @return string
1905
     */
1906
    public static function generate_message_form()
1907
    {
1908
        $form = new FormValidator('send_message');
1909
        $form->addText(
1910
            'subject',
1911
            get_lang('Subject'),
1912
            false,
1913
            ['id' => 'subject_id']
1914
        );
1915
        $form->addTextarea(
1916
            'content',
1917
            get_lang('Message'),
1918
            ['id' => 'content_id', 'rows' => '5']
1919
        );
1920
1921
        return $form->returnForm();
1922
    }
1923
1924
    /**
1925
     * @param $id
1926
     * @param array $params
1927
     *
1928
     * @return string
1929
     */
1930
    public static function generate_invitation_form($id, $params = [])
1931
    {
1932
        $form = new FormValidator('send_invitation');
1933
        $form->addTextarea(
1934
            'content',
1935
            get_lang('AddPersonalMessage'),
1936
            ['id' => 'content_invitation_id', 'rows' => 5]
1937
        );
1938
1939
        return $form->returnForm();
1940
    }
1941
1942
    //@todo this functions should be in the message class
1943
1944
    /**
1945
     * @param string $keyword
1946
     *
1947
     * @return string
1948
     */
1949
    public static function inbox_display($keyword = '')
1950
    {
1951
        $success = get_lang('SelectedMessagesDeleted');
1952
        $success_read = get_lang('SelectedMessagesRead');
1953
        $success_unread = get_lang('SelectedMessagesUnRead');
1954
        $html = '';
1955
1956
        Session::write('message_search_keyword', $keyword);
1957
1958
        if (isset($_REQUEST['action'])) {
1959
            switch ($_REQUEST['action']) {
1960
                case 'mark_as_unread':
1961
                    if (is_array($_POST['id'])) {
1962
                        foreach ($_POST['id'] as $index => $message_id) {
1963
                            self::update_message_status(
1964
                                api_get_user_id(),
1965
                                $message_id,
1966
                                MESSAGE_STATUS_UNREAD
1967
                            );
1968
                        }
1969
                    }
1970
                    $html .= Display::return_message(
1971
                        api_xml_http_response_encode($success_unread),
1972
                        'normal',
1973
                        false
1974
                    );
1975
                    break;
1976
                case 'mark_as_read':
1977
                    if (is_array($_POST['id'])) {
1978
                        foreach ($_POST['id'] as $index => $message_id) {
1979
                            self::update_message_status(
1980
                                api_get_user_id(),
1981
                                $message_id,
1982
                                MESSAGE_STATUS_NEW
1983
                            );
1984
                        }
1985
                    }
1986
                    $html .= Display::return_message(
1987
                        api_xml_http_response_encode($success_read),
1988
                        'normal',
1989
                        false
1990
                    );
1991
                    break;
1992
                case 'delete':
1993
                    foreach ($_POST['id'] as $index => $message_id) {
1994
                        self::delete_message_by_user_receiver(api_get_user_id(), $message_id);
1995
                    }
1996
                    $html .= Display::return_message(
1997
                        api_xml_http_response_encode($success),
1998
                        'normal',
1999
                        false
2000
                    );
2001
                    break;
2002
                case 'deleteone':
2003
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
2004
                    $html .= Display::return_message(
2005
                        api_xml_http_response_encode($success),
2006
                        'confirmation',
2007
                        false
2008
                    );
2009
                    break;
2010
            }
2011
        }
2012
2013
        // display sortable table with messages of the current user
2014
        $table = new SortableTable(
2015
            'message_inbox',
2016
            ['MessageManager', 'getNumberOfMessages'],
2017
            ['MessageManager', 'get_message_data'],
2018
            2,
2019
            20,
2020
            'DESC'
2021
        );
2022
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2023
        $table->set_header(1, get_lang('Messages'), false);
2024
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2025
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:120px;']);
2026
2027
        if (isset($_REQUEST['f']) && $_REQUEST['f'] == 'social') {
2028
            $parameters['f'] = 'social';
2029
            $table->set_additional_parameters($parameters);
2030
        }
2031
        $table->set_form_actions(
2032
            [
2033
                'delete' => get_lang('DeleteSelectedMessages'),
2034
                'mark_as_unread' => get_lang('MailMarkSelectedAsUnread'),
2035
                'mark_as_read' => get_lang('MailMarkSelectedAsRead'),
2036
            ]
2037
        );
2038
        $html .= $table->return_table();
2039
2040
        Session::erase('message_search_keyword');
2041
2042
        return $html;
2043
    }
2044
2045
    /**
2046
     * @param string $keyword
2047
     *
2048
     * @return string
2049
     */
2050
    public static function outbox_display($keyword = '')
2051
    {
2052
        Session::write('message_sent_search_keyword', $keyword);
2053
        $success = get_lang('SelectedMessagesDeleted').'&nbsp</b><br />
2054
                    <a href="outbox.php">'.get_lang('BackToOutbox').'</a>';
2055
2056
        $html = '';
2057
        if (isset($_REQUEST['action'])) {
2058
            switch ($_REQUEST['action']) {
2059
                case 'delete':
2060
                    $number_of_selected_messages = count($_POST['id']);
2061
                    if ($number_of_selected_messages != 0) {
2062
                        foreach ($_POST['id'] as $index => $message_id) {
2063
                            self::delete_message_by_user_receiver(
2064
                                api_get_user_id(),
2065
                                $message_id
2066
                            );
2067
                        }
2068
                    }
2069
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2070
                    break;
2071
                case 'deleteone':
2072
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
2073
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2074
                    $html .= '<br/>';
2075
                    break;
2076
            }
2077
        }
2078
2079
        // display sortable table with messages of the current user
2080
        $table = new SortableTable(
2081
            'message_outbox',
2082
            ['MessageManager', 'getNumberOfMessagesSent'],
2083
            ['MessageManager', 'get_message_data_sent'],
2084
            2,
2085
            20,
2086
            'DESC'
2087
        );
2088
2089
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2090
        $table->set_header(1, get_lang('Messages'), false);
2091
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2092
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:70px;']);
2093
2094
        $table->set_form_actions(['delete' => get_lang('DeleteSelectedMessages')]);
2095
        $html .= $table->return_table();
2096
2097
        Session::erase('message_sent_search_keyword');
2098
2099
        return $html;
2100
    }
2101
2102
    /**
2103
     * Get the count of the last received messages for a user.
2104
     *
2105
     * @param int $userId The user id
2106
     * @param int $lastId The id of the last received message
2107
     *
2108
     * @return int The count of new messages
2109
     */
2110
    public static function countMessagesFromLastReceivedMessage($userId, $lastId = 0)
2111
    {
2112
        $userId = intval($userId);
2113
        $lastId = intval($lastId);
2114
2115
        if (empty($userId)) {
2116
            return 0;
2117
        }
2118
2119
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2120
2121
        $conditions = [
2122
            'where' => [
2123
                'user_receiver_id = ?' => $userId,
2124
                'AND msg_status = ?' => MESSAGE_STATUS_UNREAD,
2125
                'AND id > ?' => $lastId,
2126
            ],
2127
        ];
2128
2129
        $result = Database::select('COUNT(1) AS qty', $messagesTable, $conditions);
2130
2131
        if (!empty($result)) {
2132
            $row = current($result);
2133
2134
            return $row['qty'];
2135
        }
2136
2137
        return 0;
2138
    }
2139
2140
    /**
2141
     * Get the data of the last received messages for a user.
2142
     *
2143
     * @param int $userId The user id
2144
     * @param int $lastId The id of the last received message
2145
     *
2146
     * @return array
2147
     */
2148
    public static function getMessagesFromLastReceivedMessage($userId, $lastId = 0)
2149
    {
2150
        $userId = intval($userId);
2151
        $lastId = intval($lastId);
2152
2153
        if (empty($userId)) {
2154
            return [];
2155
        }
2156
2157
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2158
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2159
2160
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname
2161
                FROM $messagesTable as m
2162
                INNER JOIN $userTable as u
2163
                ON m.user_sender_id = u.user_id
2164
                WHERE
2165
                    m.user_receiver_id = $userId AND
2166
                    m.msg_status = ".MESSAGE_STATUS_UNREAD."
2167
                    AND m.id > $lastId
2168
                ORDER BY m.send_date DESC";
2169
2170
        $result = Database::query($sql);
2171
2172
        $messages = [];
2173
        if ($result !== false) {
2174
            while ($row = Database::fetch_assoc($result)) {
2175
                $messages[] = $row;
2176
            }
2177
        }
2178
2179
        return $messages;
2180
    }
2181
2182
    /**
2183
     * Check whether a message has attachments.
2184
     *
2185
     * @param int $messageId The message id
2186
     *
2187
     * @return bool Whether the message has attachments return true. Otherwise return false
2188
     */
2189
    public static function hasAttachments($messageId)
2190
    {
2191
        $messageId = intval($messageId);
2192
2193
        if (empty($messageId)) {
2194
            return false;
2195
        }
2196
2197
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2198
2199
        $conditions = [
2200
            'where' => [
2201
                'message_id = ?' => $messageId,
2202
            ],
2203
        ];
2204
2205
        $result = Database::select(
2206
            'COUNT(1) AS qty',
2207
            $messageAttachmentTable,
2208
            $conditions,
2209
            'first'
2210
        );
2211
2212
        if (!empty($result)) {
2213
            if ($result['qty'] > 0) {
2214
                return true;
2215
            }
2216
        }
2217
2218
        return false;
2219
    }
2220
2221
    /**
2222
     * @param string $url
2223
     *
2224
     * @return FormValidator
2225
     */
2226
    public static function getSearchForm($url)
2227
    {
2228
        $form = new FormValidator(
2229
            'search',
2230
            'post',
2231
            $url,
2232
            null,
2233
            [],
2234
            FormValidator::LAYOUT_INLINE
2235
        );
2236
2237
        $form->addElement(
2238
            'text',
2239
            'keyword',
2240
            false,
2241
            [
2242
                'aria-label' => get_lang('Search'),
2243
            ]
2244
        );
2245
        $form->addButtonSearch(get_lang('Search'));
2246
2247
        return $form;
2248
    }
2249
2250
    /**
2251
     * Send a notification to all admins when a new user is registered.
2252
     *
2253
     * @param User $user
2254
     */
2255
    public static function sendNotificationByRegisteredUser(User $user)
2256
    {
2257
        $tplMailBody = new Template(
2258
            null,
2259
            false,
2260
            false,
2261
            false,
2262
            false,
2263
            false,
2264
            false
2265
        );
2266
        $tplMailBody->assign('user', $user);
2267
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2268
        $tplMailBody->assign(
2269
            'manageUrl',
2270
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
2271
        );
2272
2273
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
2274
2275
        $emailsubject = '['.get_lang('UserRegistered').'] '.$user->getUsername();
2276
        $emailbody = $tplMailBody->fetch($layoutContent);
2277
2278
        $admins = UserManager::get_all_administrators();
2279
2280
        foreach ($admins as $admin_info) {
2281
            self::send_message(
2282
                $admin_info['user_id'],
2283
                $emailsubject,
2284
                $emailbody,
2285
                [],
2286
                [],
2287
                null,
2288
                null,
2289
                null,
2290
                null,
2291
                $user->getId()
2292
            );
2293
        }
2294
    }
2295
2296
    /**
2297
     * Get the error log from failed mailing
2298
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
2299
     * into app/cache/mail/mailq.
2300
     * This can be done with a cron command like (check the location of your mail log file first):.
2301
     *
2302
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
2303
     *
2304
     * @return array|bool
2305
     */
2306
    public static function failedSentMailErrors()
2307
    {
2308
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
2309
        $mailq = $base.'mailq';
2310
2311
        if (!file_exists($mailq) || !is_readable($mailq)) {
2312
            return false;
2313
        }
2314
2315
        $file = fopen($mailq, 'r');
2316
        $i = 1;
2317
        while (!feof($file)) {
2318
            $line = fgets($file);
2319
            //$line = trim($line);
2320
2321
            if (trim($line) == '') {
2322
                continue;
2323
            }
2324
2325
            //Get the mail code, something like 1WBumL-0002xg-FF
2326
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
2327
                $mail_queue[$i]['code'] = $codeMatches[2];
2328
            }
2329
2330
            $fullMail = $base.$mail_queue[$i]['code'];
2331
            $mailFile = fopen($fullMail, 'r');
2332
2333
            //Get the reason of mail fail
2334
            $iX = 1;
2335
2336
            while (!feof($mailFile)) {
2337
                $mailLine = fgets($mailFile);
2338
                //if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2339
                if ($iX == 2 &&
2340
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2341
                ) {
2342
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2343
                }
2344
2345
                $iX++;
2346
            }
2347
2348
            fclose($mailFile);
2349
2350
            //Get the time of mail fail
2351
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
2352
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
2353
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
2354
                $mail_queue[$i]['mail'] = $emailMatches[2];
2355
                $i++;
2356
            }
2357
        }
2358
2359
        fclose($file);
2360
2361
        return array_reverse($mail_queue);
2362
    }
2363
2364
    /**
2365
     * @param int $userId
2366
     *
2367
     * @return array
2368
     */
2369
    public static function getUsersThatHadConversationWithUser($userId)
2370
    {
2371
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2372
        $userId = (int) $userId;
2373
2374
        $sql = "SELECT DISTINCT
2375
                    user_sender_id
2376
                FROM $messagesTable
2377
                WHERE
2378
                    user_receiver_id = ".$userId;
2379
        $result = Database::query($sql);
2380
        $users = Database::store_result($result);
2381
        $userList = [];
2382
        foreach ($users as $userData) {
2383
            $userId = $userData['user_sender_id'];
2384
            if (empty($userId)) {
2385
                continue;
2386
            }
2387
            $userInfo = api_get_user_info($userId);
2388
            if ($userInfo) {
2389
                $userList[$userId] = $userInfo;
2390
            }
2391
        }
2392
2393
        return $userList;
2394
    }
2395
2396
    /**
2397
     * @param int $userId
2398
     * @param int $otherUserId
2399
     *
2400
     * @return array
2401
     */
2402
    public static function getAllMessagesBetweenStudents($userId, $otherUserId)
2403
    {
2404
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2405
        $userId = (int) $userId;
2406
        $otherUserId = (int) $otherUserId;
2407
2408
        if (empty($otherUserId) || empty($userId)) {
2409
            return [];
2410
        }
2411
2412
        $sql = "SELECT DISTINCT * 
2413
                FROM $messagesTable
2414
                WHERE
2415
                    (user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
2416
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId)
2417
                ORDER BY send_date DESC
2418
            ";
2419
        $result = Database::query($sql);
2420
        $messages = Database::store_result($result);
2421
        $list = [];
2422
        foreach ($messages as $message) {
2423
            $list[] = $message;
2424
        }
2425
2426
        return $list;
2427
    }
2428
2429
    /**
2430
     * @param string $subject
2431
     * @param string $message
2432
     * @param array  $courseInfo
2433
     * @param int    $sessionId
2434
     *
2435
     * @return bool
2436
     */
2437
    public static function sendMessageToAllUsersInCourse($subject, $message, $courseInfo, $sessionId = 0)
2438
    {
2439
        if (empty($courseInfo)) {
2440
            return false;
2441
        }
2442
        $senderId = api_get_user_id();
2443
        if (empty($senderId)) {
2444
            return false;
2445
        }
2446
        if (empty($sessionId)) {
2447
            // Course students and teachers
2448
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code']);
2449
        } else {
2450
            // Course-session students and course session coaches
2451
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code'], $sessionId);
2452
        }
2453
2454
        if (empty($users)) {
2455
            return false;
2456
        }
2457
2458
        foreach ($users as $userInfo) {
2459
            self::send_message_simple(
2460
                $userInfo['user_id'],
2461
                $subject,
2462
                $message,
2463
                $senderId,
2464
                false,
2465
                false,
2466
                [],
2467
                false
2468
            );
2469
        }
2470
    }
2471
2472
    /**
2473
     * Execute the SQL necessary to know the number of messages in the database.
2474
     *
2475
     * @param int $userId The user for which we need the unread messages count
2476
     *
2477
     * @return int The number of unread messages in the database for the given user
2478
     */
2479
    private static function getCountNewMessagesFromDB($userId)
2480
    {
2481
        if (empty($userId)) {
2482
            return 0;
2483
        }
2484
        $table = Database::get_main_table(TABLE_MESSAGE);
2485
        $sql = "SELECT COUNT(id) as count 
2486
                FROM $table
2487
                WHERE
2488
                    user_receiver_id=".api_get_user_id()." AND
2489
                    msg_status = ".MESSAGE_STATUS_UNREAD;
2490
        $result = Database::query($sql);
2491
        $row = Database::fetch_assoc($result);
2492
2493
        return $row['count'];
2494
    }
2495
}
2496