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

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\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