Passed
Push — 1.11.x ( 220ec2...a18d33 )
by Angel Fernando Quiroz
10:53
created

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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