Passed
Pull Request — 1.11.x (#4097)
by Angel Fernando Quiroz
10:12
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
        $eventLink = Display::url(
1500
            Display::return_icon('new_event.png', get_lang('New event')),
1501
            api_get_path(WEB_CODE_PATH).'calendar/agenda.php?action=add&type=personal&m='.$messageId
1502
        ).PHP_EOL;
1503
1504
        switch ($type) {
1505
            case self::MESSAGE_TYPE_OUTBOX:
1506
                $message_content .= '<a href="outbox.php?'.$social_link.'">'.
1507
                    Display::return_icon('back.png', get_lang('ReturnToOutbox')).'</a> &nbsp';
1508
                $message_content .= $eventLink;
1509
                $message_content .= '<a href="outbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1510
                    Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp';
1511
                break;
1512
            case self::MESSAGE_TYPE_INBOX:
1513
                $message_content .= '<a href="inbox.php?'.$social_link.'">'.
1514
                    Display::return_icon('icons/22/arrow_up.png', get_lang('ReturnToInbox')).'</a>&nbsp;';
1515
                $message_content .= '<a href="new_message.php?re_id='.$messageId.'&'.$social_link.'">'.
1516
                    Display::return_icon('message_reply.png', get_lang('ReplyToMessage')).'</a>&nbsp;';
1517
                $message_content .= $eventLink;
1518
                $message_content .= '<a href="inbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1519
                    Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp;';
1520
                if ($idPrevMessage != 0) {
1521
                    $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';
1522
                }
1523
                if ($idNextMessage != 0) {
1524
                    $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';
1525
                }
1526
                break;
1527
        }
1528
1529
        $message_content .= '</div></td>
1530
		      <td width="10"></td>
1531
		    </tr>
1532
		</table>';
1533
1534
        return $message_content;
1535
    }
1536
1537
    /**
1538
     * get user id by user email.
1539
     *
1540
     * @param string $user_email
1541
     *
1542
     * @return int user id
1543
     */
1544
    public static function get_user_id_by_email($user_email)
1545
    {
1546
        $table = Database::get_main_table(TABLE_MAIN_USER);
1547
        $sql = 'SELECT user_id
1548
                FROM '.$table.'
1549
                WHERE email="'.Database::escape_string($user_email).'";';
1550
        $rs = Database::query($sql);
1551
        $row = Database::fetch_array($rs, 'ASSOC');
1552
        if (isset($row['user_id'])) {
1553
            return $row['user_id'];
1554
        }
1555
1556
        return null;
1557
    }
1558
1559
    /**
1560
     * Displays messages of a group with nested view.
1561
     *
1562
     * @param int $groupId
1563
     *
1564
     * @return string
1565
     */
1566
    public static function display_messages_for_group($groupId)
1567
    {
1568
        global $my_group_role;
1569
1570
        $rows = self::get_messages_by_group($groupId);
1571
        $topics_per_page = 10;
1572
        $html_messages = '';
1573
        $query_vars = ['id' => $groupId, 'topics_page_nr' => 0];
1574
1575
        if (is_array($rows) && count($rows) > 0) {
1576
            // prepare array for topics with its items
1577
            $topics = [];
1578
            $x = 0;
1579
            foreach ($rows as $index => $value) {
1580
                if (empty($value['parent_id'])) {
1581
                    $topics[$value['id']] = $value;
1582
                }
1583
            }
1584
1585
            $new_topics = [];
1586
1587
            foreach ($topics as $id => $value) {
1588
                $rows = null;
1589
                $rows = self::get_messages_by_group_by_message($groupId, $value['id']);
1590
                if (!empty($rows)) {
1591
                    $count = count(self::calculate_children($rows, $value['id']));
1592
                } else {
1593
                    $count = 0;
1594
                }
1595
                $value['count'] = $count;
1596
                $new_topics[$id] = $value;
1597
            }
1598
1599
            $array_html = [];
1600
            foreach ($new_topics as $index => $topic) {
1601
                $html = '';
1602
                // topics
1603
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1604
                $name = $user_sender_info['complete_name'];
1605
                $html .= '<div class="groups-messages">';
1606
                $html .= '<div class="row">';
1607
1608
                $items = $topic['count'];
1609
                $reply_label = ($items == 1) ? get_lang('GroupReply') : get_lang('GroupReplies');
1610
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
1611
                $topic['title'] = trim($topic['title']);
1612
1613
                if (empty($topic['title'])) {
1614
                    $topic['title'] = get_lang('Untitled');
1615
                }
1616
1617
                $html .= '<div class="col-xs-8 col-md-10">';
1618
                $html .= Display::tag(
1619
                    'h4',
1620
                    Display::url(
1621
                        Security::remove_XSS($topic['title'], STUDENT, true),
1622
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$groupId.'&topic_id='.$topic['id']
1623
                    ),
1624
                    ['class' => 'title']
1625
                );
1626
                $actions = '';
1627
                if ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1628
                    $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1629
                ) {
1630
                    $actions = '<br />'.Display::url(
1631
                            get_lang('Delete'),
1632
                            api_get_path(
1633
                                WEB_CODE_PATH
1634
                            ).'social/group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic['id'],
1635
                            ['class' => 'btn btn-default']
1636
                        );
1637
                }
1638
1639
                $date = '';
1640
                if ($topic['send_date'] != $topic['update_date']) {
1641
                    if (!empty($topic['update_date'])) {
1642
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1643
                                'LastUpdate'
1644
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
1645
                    }
1646
                } else {
1647
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1648
                            'Created'
1649
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
1650
                }
1651
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
1652
                $html .= '</div>';
1653
1654
                $image = $user_sender_info['avatar'];
1655
1656
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
1657
                $user_info .= '<div class="name"><a href="'.api_get_path(
1658
                        WEB_PATH
1659
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
1660
1661
                $html .= '<div class="col-xs-4 col-md-2">';
1662
                $html .= $user_info;
1663
                $html .= '</div>';
1664
                $html .= '</div>';
1665
                $html .= '</div>';
1666
1667
                $array_html[] = [$html];
1668
            }
1669
1670
            // grids for items and topics  with paginations
1671
            $html_messages .= Display::return_sortable_grid(
1672
                'topics',
1673
                [],
1674
                $array_html,
1675
                [
1676
                    'hide_navigation' => false,
1677
                    'per_page' => $topics_per_page,
1678
                ],
1679
                $query_vars,
1680
                false,
1681
                [true, true, true, false],
1682
                false
1683
            );
1684
        }
1685
1686
        return $html_messages;
1687
    }
1688
1689
    /**
1690
     * Displays messages of a group with nested view.
1691
     *
1692
     * @param $groupId
1693
     * @param $topic_id
1694
     *
1695
     * @return string
1696
     */
1697
    public static function display_message_for_group($groupId, $topic_id)
1698
    {
1699
        global $my_group_role;
1700
        $main_message = self::get_message_by_id($topic_id);
1701
        if (empty($main_message)) {
1702
            return false;
1703
        }
1704
1705
        $webCodePath = api_get_path(WEB_CODE_PATH);
1706
        $iconCalendar = Display::returnFontAwesomeIcon('calendar');
1707
1708
        $langEdit = get_lang('Edit');
1709
        $langReply = get_lang('Reply');
1710
        $langLastUpdated = get_lang('LastUpdated');
1711
        $langCreated = get_lang('Created');
1712
1713
        $rows = self::get_messages_by_group_by_message($groupId, $topic_id);
1714
        $rows = self::calculate_children($rows, $topic_id);
1715
        $current_user_id = api_get_user_id();
1716
1717
        $items_per_page = 50;
1718
        $query_vars = ['id' => $groupId, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
1719
1720
        // Main message
1721
        $links = '';
1722
        $main_content = '';
1723
        $html = '';
1724
        $items_page_nr = null;
1725
1726
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1727
        $files_attachments = self::getAttachmentLinkList($main_message['id'], 0);
1728
        $name = $user_sender_info['complete_name'];
1729
1730
        $topic_page_nr = isset($_GET['topics_page_nr']) ? (int) $_GET['topics_page_nr'] : null;
1731
1732
        $links .= '<div class="pull-right">';
1733
        $links .= '<div class="btn-group btn-group-sm">';
1734
1735
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1736
            $main_message['user_sender_id'] == $current_user_id
1737
        ) {
1738
            $urlEdit = $webCodePath.'social/message_for_group_form.inc.php?'
1739
                .http_build_query(
1740
                    [
1741
                        'user_friend' => $current_user_id,
1742
                        'group_id' => $groupId,
1743
                        'message_id' => $main_message['id'],
1744
                        'action' => 'edit_message_group',
1745
                        'anchor_topic' => 'topic_'.$main_message['id'],
1746
                        'topics_page_nr' => $topic_page_nr,
1747
                        'items_page_nr' => $items_page_nr,
1748
                        'topic_id' => $main_message['id'],
1749
                    ]
1750
                );
1751
1752
            $links .= Display::toolbarButton(
1753
                $langEdit,
1754
                $urlEdit,
1755
                'pencil',
1756
                'default',
1757
                ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1758
                false
1759
            );
1760
        }
1761
1762
        $links .= self::getLikesButton($main_message['id'], $current_user_id, $groupId);
1763
1764
        $urlReply = $webCodePath.'social/message_for_group_form.inc.php?'
1765
            .http_build_query(
1766
                [
1767
                    'user_friend' => $current_user_id,
1768
                    'group_id' => $groupId,
1769
                    'message_id' => $main_message['id'],
1770
                    'action' => 'reply_message_group',
1771
                    'anchor_topic' => 'topic_'.$main_message['id'],
1772
                    'topics_page_nr' => $topic_page_nr,
1773
                    'topic_id' => $main_message['id'],
1774
                ]
1775
            );
1776
1777
        $links .= Display::toolbarButton(
1778
            $langReply,
1779
            $urlReply,
1780
            'commenting',
1781
            'default',
1782
            ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1783
            false
1784
        );
1785
1786
        if (api_is_platform_admin()) {
1787
            $links .= Display::toolbarButton(
1788
                get_lang('Delete'),
1789
                'group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic_id,
1790
                'trash',
1791
                'default',
1792
                [],
1793
                false
1794
            );
1795
        }
1796
1797
        $links .= '</div>';
1798
        $links .= '</div>';
1799
1800
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
1801
1802
        $userPicture = $user_sender_info['avatar'];
1803
        $main_content .= '<div class="row">';
1804
        $main_content .= '<div class="col-md-2">';
1805
        $main_content .= '<div class="avatar-author">';
1806
        $main_content .= Display::img(
1807
            $userPicture,
1808
            $name,
1809
            ['width' => '60px', 'class' => 'img-responsive img-circle'],
1810
            false
1811
        );
1812
        $main_content .= '</div>';
1813
        $main_content .= '</div>';
1814
1815
        $date = '';
1816
        if ($main_message['send_date'] != $main_message['update_date']) {
1817
            if (!empty($main_message['update_date'])) {
1818
                $date = '<div class="date"> '
1819
                    ."$iconCalendar $langLastUpdated "
1820
                    .Display::dateToStringAgoAndLongDate($main_message['update_date'])
1821
                    .'</div>';
1822
            }
1823
        } else {
1824
            $date = '<div class="date"> '
1825
                ."$iconCalendar $langCreated "
1826
                .Display::dateToStringAgoAndLongDate($main_message['send_date'])
1827
                .'</div>';
1828
        }
1829
        $attachment = '<div class="message-attach">'
1830
            .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
1831
            .'</div>';
1832
        $main_content .= '<div class="col-md-10">';
1833
        $user_link = Display::url(
1834
            $name,
1835
            $webCodePath.'social/profile.php?u='.$main_message['user_sender_id']
1836
        );
1837
        $main_content .= '<div class="message-content"> ';
1838
        $main_content .= '<div class="username">'.$user_link.'</div>';
1839
        $main_content .= $date;
1840
        $main_content .= '<div class="message">'.$main_message['content'].$attachment.'</div></div>';
1841
        $main_content .= '</div>';
1842
        $main_content .= '</div>';
1843
1844
        $html .= Display::div(
1845
            Display::div(
1846
                $title.$main_content,
1847
                ['class' => 'message-topic']
1848
            ),
1849
            ['class' => 'sm-groups-message']
1850
        );
1851
1852
        $topic_id = $main_message['id'];
1853
1854
        if (is_array($rows) && count($rows) > 0) {
1855
            $topics = $rows;
1856
            $array_html_items = [];
1857
1858
            foreach ($topics as $index => $topic) {
1859
                if (empty($topic['id'])) {
1860
                    continue;
1861
                }
1862
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr'])
1863
                    ? (int) $_GET['items_'.$topic['id'].'_page_nr']
1864
                    : null;
1865
                $links = '';
1866
                $links .= '<div class="pull-right">';
1867
                $html_items = '';
1868
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1869
                $files_attachments = self::getAttachmentLinkList($topic['id'], 0);
1870
                $name = $user_sender_info['complete_name'];
1871
1872
                $links .= '<div class="btn-group btn-group-sm">';
1873
                if (
1874
                    ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1875
                        $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1876
                    ) ||
1877
                    $topic['user_sender_id'] == $current_user_id
1878
                ) {
1879
                    $links .= Display::toolbarButton(
1880
                        $langEdit,
1881
                        $webCodePath.'social/message_for_group_form.inc.php?'
1882
                            .http_build_query(
1883
                                [
1884
                                    'user_friend' => $current_user_id,
1885
                                    'group_id' => $groupId,
1886
                                    'message_id' => $topic['id'],
1887
                                    'action' => 'edit_message_group',
1888
                                    'anchor_topic' => 'topic_'.$topic_id,
1889
                                    'topics_page_nr' => $topic_page_nr,
1890
                                    'items_page_nr' => $items_page_nr,
1891
                                    'topic_id' => $topic_id,
1892
                                ]
1893
                            ),
1894
                        'pencil',
1895
                        'default',
1896
                        ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1897
                        false
1898
                    );
1899
                }
1900
1901
                $links .= self::getLikesButton($topic['id'], $current_user_id, $groupId);
1902
1903
                $links .= Display::toolbarButton(
1904
                    $langReply,
1905
                    $webCodePath.'social/message_for_group_form.inc.php?'
1906
                        .http_build_query(
1907
                            [
1908
                                'user_friend' => $current_user_id,
1909
                                'group_id' => $groupId,
1910
                                'message_id' => $topic['id'],
1911
                                'action' => 'reply_message_group',
1912
                                'anchor_topic' => 'topic_'.$topic_id,
1913
                                'topics_page_nr' => $topic_page_nr,
1914
                                'items_page_nr' => $items_page_nr,
1915
                                'topic_id' => $topic_id,
1916
                            ]
1917
                        ),
1918
                    'commenting',
1919
                    'default',
1920
                    ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1921
                    false
1922
                );
1923
                $links .= '</div>';
1924
                $links .= '</div>';
1925
1926
                $userPicture = $user_sender_info['avatar'];
1927
                $user_link = Display::url(
1928
                    $name,
1929
                    $webCodePath.'social/profile.php?u='.$topic['user_sender_id']
1930
                );
1931
                $html_items .= '<div class="row">';
1932
                $html_items .= '<div class="col-md-2">';
1933
                $html_items .= '<div class="avatar-author">';
1934
                $html_items .= Display::img(
1935
                    $userPicture,
1936
                    $name,
1937
                    ['width' => '60px', 'class' => 'img-responsive img-circle'],
1938
                    false
1939
                );
1940
                $html_items .= '</div>';
1941
                $html_items .= '</div>';
1942
1943
                $date = '';
1944
                if ($topic['send_date'] != $topic['update_date']) {
1945
                    if (!empty($topic['update_date'])) {
1946
                        $date = '<div class="date"> '
1947
                            ."$iconCalendar $langLastUpdated "
1948
                            .Display::dateToStringAgoAndLongDate($topic['update_date'])
1949
                            .'</div>';
1950
                    }
1951
                } else {
1952
                    $date = '<div class="date"> '
1953
                        ."$iconCalendar $langCreated "
1954
                        .Display::dateToStringAgoAndLongDate($topic['send_date'])
1955
                        .'</div>';
1956
                }
1957
                $attachment = '<div class="message-attach">'
1958
                    .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
1959
                    .'</div>';
1960
                $html_items .= '<div class="col-md-10">'
1961
                    .'<div class="message-content">'
1962
                    .$links
1963
                    .'<div class="username">'.$user_link.'</div>'
1964
                    .$date
1965
                    .'<div class="message">'
1966
                    .Security::remove_XSS($topic['content'], STUDENT, true)
1967
                    .'</div>'.$attachment.'</div>'
1968
                    .'</div>'
1969
                    .'</div>';
1970
1971
                $base_padding = 20;
1972
1973
                if (0 == $topic['indent_cnt']) {
1974
                    $indent = $base_padding;
1975
                } else {
1976
                    $indent = (int) $topic['indent_cnt'] * $base_padding + $base_padding;
1977
                }
1978
1979
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
1980
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
1981
                $array_html_items[] = [$html_items];
1982
            }
1983
1984
            // grids for items with paginations
1985
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
1986
            $visibility = [true, true, true, false];
1987
1988
            $style_class = [
1989
                'item' => ['class' => 'user-post'],
1990
                'main' => ['class' => 'user-list'],
1991
            ];
1992
            if (!empty($array_html_items)) {
1993
                $html .= Display::return_sortable_grid(
1994
                    'items_'.$topic['id'],
1995
                    [],
1996
                    $array_html_items,
1997
                    $options,
1998
                    $query_vars,
1999
                    null,
2000
                    $visibility,
2001
                    false,
2002
                    $style_class
2003
                );
2004
            }
2005
        }
2006
2007
        return $html;
2008
    }
2009
2010
    /**
2011
     * Add children to messages by id is used for nested view messages.
2012
     *
2013
     * @param array $rows rows of messages
2014
     *
2015
     * @return array $first_seed new list adding the item children
2016
     */
2017
    public static function calculate_children($rows, $first_seed)
2018
    {
2019
        $rows_with_children = [];
2020
        foreach ($rows as $row) {
2021
            $rows_with_children[$row["id"]] = $row;
2022
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
2023
        }
2024
        $rows = $rows_with_children;
2025
        $sorted_rows = [0 => []];
2026
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
2027
        unset($sorted_rows[0]);
2028
2029
        return $sorted_rows;
2030
    }
2031
2032
    /**
2033
     * Sort recursively the messages, is used for for nested view messages.
2034
     *
2035
     * @param array  original rows of messages
2036
     * @param array  list recursive of messages
2037
     * @param int   seed for calculate the indent
2038
     * @param int   indent for nested view
2039
     */
2040
    public static function message_recursive_sort(
2041
        $rows,
2042
        &$messages,
2043
        $seed = 0,
2044
        $indent = 0
2045
    ) {
2046
        if ($seed > 0 && isset($rows[$seed]["id"])) {
2047
            $messages[$rows[$seed]["id"]] = $rows[$seed];
2048
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
2049
            $indent++;
2050
        }
2051
2052
        if (isset($rows[$seed]["children"])) {
2053
            foreach ($rows[$seed]["children"] as $child) {
2054
                self::message_recursive_sort($rows, $messages, $child, $indent);
2055
            }
2056
        }
2057
    }
2058
2059
    /**
2060
     * @param int $messageId
2061
     *
2062
     * @return array
2063
     */
2064
    public static function getAttachmentList($messageId)
2065
    {
2066
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2067
        $messageId = (int) $messageId;
2068
2069
        if (empty($messageId)) {
2070
            return [];
2071
        }
2072
2073
        $messageInfo = self::get_message_by_id($messageId);
2074
2075
        if (empty($messageInfo)) {
2076
            return [];
2077
        }
2078
2079
        $attachmentDir = UserManager::getUserPathById($messageInfo['user_receiver_id'], 'system');
2080
        $attachmentDir .= 'message_attachments/';
2081
2082
        $sql = "SELECT * FROM $table
2083
                WHERE message_id = '$messageId'";
2084
        $result = Database::query($sql);
2085
        $files = [];
2086
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2087
            $row['file_source'] = '';
2088
            if (file_exists($attachmentDir.$row['path'])) {
2089
                $row['file_source'] = $attachmentDir.$row['path'];
2090
            }
2091
            $files[] = $row;
2092
        }
2093
2094
        return $files;
2095
    }
2096
2097
    /**
2098
     * Get array of links (download) for message attachment files.
2099
     *
2100
     * @param int $messageId
2101
     * @param int $type
2102
     *
2103
     * @return array
2104
     */
2105
    public static function getAttachmentLinkList($messageId, $type)
2106
    {
2107
        $files = self::getAttachmentList($messageId);
2108
        // get file attachments by message id
2109
        $list = [];
2110
        if ($files) {
2111
            $attachIcon = Display::return_icon('attachment.gif', '');
2112
            $archiveURL = api_get_path(WEB_CODE_PATH).'messages/download.php?type='.$type.'&file=';
2113
            foreach ($files as $row_file) {
2114
                $archiveFile = $row_file['path'];
2115
                $filename = $row_file['filename'];
2116
                $size = format_file_size($row_file['size']);
2117
                $comment = Security::remove_XSS($row_file['comment']);
2118
                $filename = Security::remove_XSS($filename);
2119
                $link = Display::url($filename, $archiveURL.$archiveFile);
2120
                $comment = !empty($comment) ? '&nbsp;-&nbsp;<i>'.$comment.'</i>' : '';
2121
2122
                $attachmentLine = $attachIcon.'&nbsp;'.$link.'&nbsp;('.$size.')'.$comment;
2123
                if ($row_file['comment'] === 'audio_message') {
2124
                    $attachmentLine = '<audio src="'.$archiveURL.$archiveFile.'"/>';
2125
                }
2126
                $list[] = $attachmentLine;
2127
            }
2128
        }
2129
2130
        return $list;
2131
    }
2132
2133
    /**
2134
     * Get message list by id.
2135
     *
2136
     * @param int $messageId
2137
     *
2138
     * @return array
2139
     */
2140
    public static function get_message_by_id($messageId)
2141
    {
2142
        $table = Database::get_main_table(TABLE_MESSAGE);
2143
        $messageId = (int) $messageId;
2144
        $sql = "SELECT * FROM $table
2145
                WHERE
2146
                    id = '$messageId' AND
2147
                    msg_status <> '".MESSAGE_STATUS_DELETED."' ";
2148
        $res = Database::query($sql);
2149
        $item = [];
2150
        if (Database::num_rows($res) > 0) {
2151
            $item = Database::fetch_array($res, 'ASSOC');
2152
        }
2153
2154
        return $item;
2155
    }
2156
2157
    /**
2158
     * @return string
2159
     */
2160
    public static function generate_message_form()
2161
    {
2162
        $form = new FormValidator('send_message');
2163
        $form->addText(
2164
            'subject',
2165
            get_lang('Subject'),
2166
            false,
2167
            ['id' => 'subject_id']
2168
        );
2169
        $form->addTextarea(
2170
            'content',
2171
            get_lang('Message'),
2172
            ['id' => 'content_id', 'rows' => '5']
2173
        );
2174
2175
        return $form->returnForm();
2176
    }
2177
2178
    /**
2179
     * @return string
2180
     */
2181
    public static function generate_invitation_form()
2182
    {
2183
        $form = new FormValidator('send_invitation');
2184
        $form->addTextarea(
2185
            'content',
2186
            get_lang('AddPersonalMessage'),
2187
            ['id' => 'content_invitation_id', 'rows' => 5]
2188
        );
2189
2190
        return $form->returnForm();
2191
    }
2192
2193
    /**
2194
     * @param string $type
2195
     * @param string $keyword
2196
     * @param array  $actions
2197
     *
2198
     * @return string
2199
     */
2200
    public static function getMessageGrid($type, $keyword, $actions = [])
2201
    {
2202
        $html = '';
2203
        // display sortable table with messages of the current user
2204
        $table = new SortableTable(
2205
            'message_inbox',
2206
            ['MessageManager', 'getNumberOfMessages'],
2207
            ['MessageManager', 'getMessageData'],
2208
            2,
2209
            20,
2210
            'DESC'
2211
        );
2212
        $table->setDataFunctionParams(
2213
            ['keyword' => $keyword, 'type' => $type, 'actions' => $actions]
2214
        );
2215
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2216
        $table->set_header(1, get_lang('Messages'), false);
2217
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2218
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:120px;']);
2219
2220
        if (isset($_REQUEST['f']) && $_REQUEST['f'] === 'social') {
2221
            $parameters['f'] = 'social';
2222
            $table->set_additional_parameters($parameters);
2223
        }
2224
2225
        $defaultActions = [
2226
            'delete' => get_lang('DeleteSelectedMessages'),
2227
            'mark_as_unread' => get_lang('MailMarkSelectedAsUnread'),
2228
            'mark_as_read' => get_lang('MailMarkSelectedAsRead'),
2229
        ];
2230
2231
        if (!in_array('delete', $actions)) {
2232
            unset($defaultActions['delete']);
2233
        }
2234
        if (!in_array('mark_as_unread', $actions)) {
2235
            unset($defaultActions['mark_as_unread']);
2236
        }
2237
        if (!in_array('mark_as_read', $actions)) {
2238
            unset($defaultActions['mark_as_read']);
2239
        }
2240
2241
        $table->set_form_actions($defaultActions);
2242
2243
        $html .= $table->return_table();
2244
2245
        return $html;
2246
    }
2247
2248
    /**
2249
     * @param string $keyword
2250
     *
2251
     * @return string
2252
     */
2253
    public static function inboxDisplay($keyword = '')
2254
    {
2255
        $success = get_lang('SelectedMessagesDeleted');
2256
        $success_read = get_lang('SelectedMessagesRead');
2257
        $success_unread = get_lang('SelectedMessagesUnRead');
2258
        $currentUserId = api_get_user_id();
2259
2260
        if (isset($_REQUEST['action'])) {
2261
            switch ($_REQUEST['action']) {
2262
                case 'mark_as_unread':
2263
                    if (is_array($_POST['id'])) {
2264
                        foreach ($_POST['id'] as $index => $messageId) {
2265
                            self::update_message_status(
2266
                                $currentUserId,
2267
                                $messageId,
2268
                                MESSAGE_STATUS_UNREAD
2269
                            );
2270
                        }
2271
                    }
2272
                    Display::addFlash(Display::return_message(
2273
                        $success_unread,
2274
                        'normal',
2275
                        false
2276
                    ));
2277
                    break;
2278
                case 'mark_as_read':
2279
                    if (is_array($_POST['id'])) {
2280
                        foreach ($_POST['id'] as $index => $messageId) {
2281
                            self::update_message_status(
2282
                                $currentUserId,
2283
                                $messageId,
2284
                                MESSAGE_STATUS_NEW
2285
                            );
2286
                        }
2287
                    }
2288
                    Display::addFlash(Display::return_message(
2289
                        $success_read,
2290
                        'normal',
2291
                        false
2292
                    ));
2293
                    break;
2294
                case 'delete':
2295
                    foreach ($_POST['id'] as $index => $messageId) {
2296
                        self::delete_message_by_user_receiver($currentUserId, $messageId);
2297
                    }
2298
                    Display::addFlash(Display::return_message(
2299
                        $success,
2300
                        'normal',
2301
                        false
2302
                    ));
2303
                    break;
2304
                case 'deleteone':
2305
                    $result = self::delete_message_by_user_receiver($currentUserId, $_GET['id']);
2306
                    if ($result) {
2307
                        Display::addFlash(
2308
                            Display::return_message(
2309
                                $success,
2310
                                'confirmation',
2311
                                false
2312
                            )
2313
                        );
2314
                    }
2315
                    break;
2316
            }
2317
            header('Location: '.api_get_self());
2318
            exit;
2319
        }
2320
2321
        $actions = ['reply', 'mark_as_unread', 'mark_as_read', 'forward', 'delete'];
2322
2323
        return self::getMessageGrid(self::MESSAGE_TYPE_INBOX, $keyword, $actions);
2324
    }
2325
2326
    /**
2327
     * @param string $keyword
2328
     *
2329
     * @return string
2330
     */
2331
    public static function getPromotedMessagesGrid($keyword)
2332
    {
2333
        $actions = ['delete'];
2334
        $currentUserId = api_get_user_id();
2335
2336
        $success = get_lang('SelectedMessagesDeleted');
2337
        if (isset($_REQUEST['action'])) {
2338
            switch ($_REQUEST['action']) {
2339
                case 'delete':
2340
                    foreach ($_POST['id'] as $index => $messageId) {
2341
                        self::delete_message_by_user_receiver($currentUserId, $messageId);
2342
                    }
2343
                    Display::addFlash(Display::return_message(
2344
                        $success,
2345
                        'normal',
2346
                        false
2347
                    ));
2348
                    break;
2349
                case 'deleteone':
2350
                    self::delete_message_by_user_receiver($currentUserId, $_GET['id']);
2351
                    Display::addFlash(Display::return_message(
2352
                        $success,
2353
                        'confirmation',
2354
                        false
2355
                    ));
2356
                    break;
2357
            }
2358
2359
            header('Location: '.api_get_self());
2360
            exit;
2361
        }
2362
2363
        $html = self::getMessageGrid(self::MESSAGE_TYPE_PROMOTED, $keyword, $actions);
2364
2365
        return $html;
2366
    }
2367
2368
    /**
2369
     * @param string $keyword
2370
     *
2371
     * @return string
2372
     */
2373
    public static function outBoxDisplay($keyword)
2374
    {
2375
        $actions = ['delete'];
2376
2377
        $success = get_lang('SelectedMessagesDeleted');
2378
        $currentUserId = api_get_user_id();
2379
        if (isset($_REQUEST['action'])) {
2380
            switch ($_REQUEST['action']) {
2381
                case 'delete':
2382
                    foreach ($_POST['id'] as $index => $messageId) {
2383
                        self::delete_message_by_user_sender($currentUserId, $messageId);
2384
                    }
2385
                    Display::addFlash(Display::return_message(
2386
                        $success,
2387
                        'normal',
2388
                        false
2389
                    ));
2390
2391
                    break;
2392
                case 'deleteone':
2393
                    self::delete_message_by_user_sender($currentUserId, $_GET['id']);
2394
                    Display::addFlash(Display::return_message(
2395
                        $success,
2396
                        'confirmation',
2397
                        false
2398
                    ));
2399
                    break;
2400
            }
2401
2402
            header('Location: '.api_get_self());
2403
            exit;
2404
        }
2405
2406
        $html = self::getMessageGrid(self::MESSAGE_TYPE_OUTBOX, $keyword, $actions);
2407
2408
        return $html;
2409
    }
2410
2411
    /**
2412
     * @param string $keyword
2413
     *
2414
     * @return string
2415
     */
2416
    public static function outbox_display($keyword = '')
2417
    {
2418
        Session::write('message_sent_search_keyword', $keyword);
2419
        $success = get_lang('SelectedMessagesDeleted').'&nbsp</b><br />
2420
                    <a href="outbox.php">'.get_lang('BackToOutbox').'</a>';
2421
2422
        $html = '';
2423
        if (isset($_REQUEST['action'])) {
2424
            switch ($_REQUEST['action']) {
2425
                case 'delete':
2426
                    $count = count($_POST['id']);
2427
                    if ($count != 0) {
2428
                        foreach ($_POST['id'] as $index => $messageId) {
2429
                            self::delete_message_by_user_receiver(
2430
                                api_get_user_id(),
2431
                                $messageId
2432
                            );
2433
                        }
2434
                    }
2435
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2436
                    break;
2437
                case 'deleteone':
2438
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
2439
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
2440
                    $html .= '<br/>';
2441
                    break;
2442
            }
2443
        }
2444
2445
        // display sortable table with messages of the current user
2446
        $table = new SortableTable(
2447
            'message_outbox',
2448
            ['MessageManager', 'getNumberOfMessages'],
2449
            ['MessageManager', 'getMessageData'],
2450
            2,
2451
            20,
2452
            'DESC'
2453
        );
2454
        $table->setDataFunctionParams(
2455
            ['keyword' => $keyword, 'type' => self::MESSAGE_TYPE_OUTBOX]
2456
        );
2457
2458
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
2459
        $table->set_header(1, get_lang('Messages'), false);
2460
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
2461
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:70px;']);
2462
2463
        $table->set_form_actions(['delete' => get_lang('DeleteSelectedMessages')]);
2464
        $html .= $table->return_table();
2465
2466
        return $html;
2467
    }
2468
2469
    /**
2470
     * Get the data of the last received messages for a user.
2471
     *
2472
     * @param int $userId The user id
2473
     * @param int $lastId The id of the last received message
2474
     *
2475
     * @return array
2476
     */
2477
    public static function getMessagesFromLastReceivedMessage($userId, $lastId = 0)
2478
    {
2479
        $userId = (int) $userId;
2480
        $lastId = (int) $lastId;
2481
2482
        if (empty($userId)) {
2483
            return [];
2484
        }
2485
2486
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2487
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2488
2489
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname
2490
                FROM $messagesTable as m
2491
                INNER JOIN $userTable as u
2492
                ON m.user_sender_id = u.user_id
2493
                WHERE
2494
                    m.user_receiver_id = $userId AND
2495
                    m.msg_status = ".MESSAGE_STATUS_UNREAD."
2496
                    AND m.id > $lastId
2497
                ORDER BY m.send_date DESC";
2498
2499
        $result = Database::query($sql);
2500
2501
        $messages = [];
2502
        if ($result !== false) {
2503
            while ($row = Database::fetch_assoc($result)) {
2504
                $messages[] = $row;
2505
            }
2506
        }
2507
2508
        return $messages;
2509
    }
2510
2511
    /**
2512
     * Get the data of the last received messages for a user.
2513
     *
2514
     * @param int $userId The user id
2515
     * @param int $lastId The id of the last received message
2516
     *
2517
     * @return array
2518
     */
2519
    public static function getReceivedMessages($userId, $lastId = 0)
2520
    {
2521
        $userId = intval($userId);
2522
        $lastId = intval($lastId);
2523
2524
        if (empty($userId)) {
2525
            return [];
2526
        }
2527
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2528
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2529
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
2530
                FROM $messagesTable as m
2531
                INNER JOIN $userTable as u
2532
                ON m.user_sender_id = u.user_id
2533
                WHERE
2534
                    m.user_receiver_id = $userId AND
2535
                    m.msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
2536
                    AND m.id > $lastId
2537
                ORDER BY m.send_date DESC";
2538
2539
        $result = Database::query($sql);
2540
2541
        $messages = [];
2542
        if ($result !== false) {
2543
            while ($row = Database::fetch_assoc($result)) {
2544
                $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
2545
                $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
2546
                $messages[] = $row;
2547
            }
2548
        }
2549
2550
        return $messages;
2551
    }
2552
2553
    /**
2554
     * Get the data of the last received messages for a user.
2555
     *
2556
     * @param int $userId The user id
2557
     * @param int $lastId The id of the last received message
2558
     *
2559
     * @return array
2560
     */
2561
    public static function getSentMessages($userId, $lastId = 0)
2562
    {
2563
        $userId = intval($userId);
2564
        $lastId = intval($lastId);
2565
2566
        if (empty($userId)) {
2567
            return [];
2568
        }
2569
2570
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2571
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2572
2573
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
2574
                FROM $messagesTable as m
2575
                INNER JOIN $userTable as u
2576
                ON m.user_receiver_id = u.user_id
2577
                WHERE
2578
                    m.user_sender_id = $userId
2579
                    AND m.msg_status = ".MESSAGE_STATUS_OUTBOX."
2580
                    AND m.id > $lastId
2581
                ORDER BY m.send_date DESC";
2582
2583
        $result = Database::query($sql);
2584
2585
        $messages = [];
2586
        if ($result !== false) {
2587
            while ($row = Database::fetch_assoc($result)) {
2588
                $pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
2589
                $row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
2590
                $messages[] = $row;
2591
            }
2592
        }
2593
2594
        return $messages;
2595
    }
2596
2597
    /**
2598
     * Check whether a message has attachments.
2599
     *
2600
     * @param int $messageId The message id
2601
     *
2602
     * @return bool Whether the message has attachments return true. Otherwise return false
2603
     */
2604
    public static function hasAttachments($messageId)
2605
    {
2606
        $messageId = (int) $messageId;
2607
2608
        if (empty($messageId)) {
2609
            return false;
2610
        }
2611
2612
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2613
2614
        $conditions = [
2615
            'where' => [
2616
                'message_id = ?' => $messageId,
2617
            ],
2618
        ];
2619
2620
        $result = Database::select(
2621
            'COUNT(1) AS qty',
2622
            $messageAttachmentTable,
2623
            $conditions,
2624
            'first'
2625
        );
2626
2627
        if (!empty($result)) {
2628
            if ($result['qty'] > 0) {
2629
                return true;
2630
            }
2631
        }
2632
2633
        return false;
2634
    }
2635
2636
    /**
2637
     * @param int $messageId
2638
     *
2639
     * @return array|bool
2640
     */
2641
    public static function getAttachment($messageId)
2642
    {
2643
        $messageId = (int) $messageId;
2644
2645
        if (empty($messageId)) {
2646
            return false;
2647
        }
2648
2649
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2650
2651
        $conditions = [
2652
            'where' => [
2653
                'id = ?' => $messageId,
2654
            ],
2655
        ];
2656
2657
        $result = Database::select(
2658
            '*',
2659
            $table,
2660
            $conditions,
2661
            'first'
2662
        );
2663
2664
        if (!empty($result)) {
2665
            return $result;
2666
        }
2667
2668
        return false;
2669
    }
2670
2671
    /**
2672
     * @param string $url
2673
     *
2674
     * @return FormValidator
2675
     */
2676
    public static function getSearchForm($url)
2677
    {
2678
        $form = new FormValidator(
2679
            'search',
2680
            'post',
2681
            $url,
2682
            null,
2683
            [],
2684
            FormValidator::LAYOUT_INLINE
2685
        );
2686
2687
        $form->addElement(
2688
            'text',
2689
            'keyword',
2690
            false,
2691
            [
2692
                'aria-label' => get_lang('Search'),
2693
            ]
2694
        );
2695
        $form->addButtonSearch(get_lang('Search'));
2696
2697
        return $form;
2698
    }
2699
2700
    /**
2701
     * Send a notification to all admins when a new user is registered.
2702
     */
2703
    public static function sendNotificationOfNewRegisteredUser(User $user)
2704
    {
2705
        $tplMailBody = new Template(
2706
            null,
2707
            false,
2708
            false,
2709
            false,
2710
            false,
2711
            false,
2712
            false
2713
        );
2714
        $tplMailBody->assign('user', $user);
2715
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2716
        $tplMailBody->assign(
2717
            'manageUrl',
2718
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
2719
        );
2720
2721
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
2722
2723
        $emailsubject = '['.get_lang('UserRegistered').'] '.$user->getUsername();
2724
        $emailbody = $tplMailBody->fetch($layoutContent);
2725
2726
        $admins = UserManager::get_all_administrators();
2727
2728
        foreach ($admins as $admin_info) {
2729
            self::send_message(
2730
                $admin_info['user_id'],
2731
                $emailsubject,
2732
                $emailbody,
2733
                [],
2734
                [],
2735
                null,
2736
                null,
2737
                null,
2738
                null,
2739
                $user->getId()
2740
            );
2741
        }
2742
    }
2743
2744
    /**
2745
     * Send a notification to all admins when a new user is registered
2746
     * while the approval method is used for users registration.
2747
     */
2748
    public static function sendNotificationOfNewRegisteredUserApproval(User $user)
2749
    {
2750
        $tplMailBody = new Template(
2751
            null,
2752
            false,
2753
            false,
2754
            false,
2755
            false,
2756
            false,
2757
            false
2758
        );
2759
        $tplMailBody->assign('user', $user);
2760
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2761
        $userId = $user->getId();
2762
        $url_edit = Display::url(
2763
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId,
2764
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId
2765
        );
2766
        $tplMailBody->assign(
2767
            'manageUrl',
2768
            $url_edit
2769
        );
2770
        // Get extra field values for this user and reformat the array
2771
        $extraFieldValues = new ExtraFieldValue('user');
2772
        $userExtraFields = $extraFieldValues->getAllValuesByItem($userId);
2773
        $values = [];
2774
        foreach ($userExtraFields as $field => $value) {
2775
            $values[$value['variable']] = $value['value'];
2776
        }
2777
        $tplMailBody->assign(
2778
            'extra',
2779
            $values
2780
        );
2781
        $layoutContent = '';
2782
        $emailbody = '';
2783
        if (api_get_configuration_value('mail_template_system') == true) {
2784
            $mailTemplateManager = new MailTemplateManager();
2785
            $templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl');
2786
            if (empty($templateText)) {
2787
            } else {
2788
                // custom procedure to load a template as a string (doesn't use cache so may slow down)
2789
                $template = $tplMailBody->twig->createTemplate($templateText);
2790
                $emailbody = $template->render($tplMailBody->params);
2791
            }
2792
        }
2793
        if (empty($emailbody)) {
2794
            $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl');
2795
            $emailbody = $tplMailBody->fetch($layoutContent);
2796
        }
2797
2798
        $emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername();
2799
2800
        if (api_get_configuration_value('send_inscription_notification_to_general_admin_only')) {
2801
            $email = api_get_setting('emailAdministrator');
2802
            $firstname = api_get_setting('administratorSurname');
2803
            $lastname = api_get_setting('administratorName');
2804
            api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody);
2805
        } else {
2806
            $admins = UserManager::get_all_administrators();
2807
            foreach ($admins as $admin_info) {
2808
                self::send_message(
2809
                    $admin_info['user_id'],
2810
                    $emailsubject,
2811
                    $emailbody,
2812
                    [],
2813
                    [],
2814
                    null,
2815
                    null,
2816
                    null,
2817
                    null,
2818
                    $userId
2819
                );
2820
            }
2821
        }
2822
    }
2823
2824
    /**
2825
     * Get the error log from failed mailing
2826
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
2827
     * into app/cache/mail/mailq.
2828
     * This can be done with a cron command like (check the location of your mail log file first):.
2829
     *
2830
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
2831
     *
2832
     * @return array|bool
2833
     */
2834
    public static function failedSentMailErrors()
2835
    {
2836
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
2837
        $mailq = $base.'mailq';
2838
2839
        if (!file_exists($mailq) || !is_readable($mailq)) {
2840
            return false;
2841
        }
2842
2843
        $file = fopen($mailq, 'r');
2844
        $i = 1;
2845
        while (!feof($file)) {
2846
            $line = fgets($file);
2847
2848
            if (trim($line) == '') {
2849
                continue;
2850
            }
2851
2852
            // Get the mail code, something like 1WBumL-0002xg-FF
2853
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
2854
                $mail_queue[$i]['code'] = $codeMatches[2];
2855
            }
2856
2857
            $fullMail = $base.$mail_queue[$i]['code'];
2858
            $mailFile = fopen($fullMail, 'r');
2859
2860
            // Get the reason of mail fail
2861
            $iX = 1;
2862
            while (!feof($mailFile)) {
2863
                $mailLine = fgets($mailFile);
2864
                //if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2865
                if ($iX == 2 &&
2866
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2867
                ) {
2868
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2869
                }
2870
                $iX++;
2871
            }
2872
2873
            fclose($mailFile);
2874
2875
            // Get the time of mail fail
2876
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
2877
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
2878
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
2879
                $mail_queue[$i]['mail'] = $emailMatches[2];
2880
                $i++;
2881
            }
2882
        }
2883
2884
        fclose($file);
2885
2886
        return array_reverse($mail_queue);
2887
    }
2888
2889
    /**
2890
     * @param int      $userId
2891
     * @param datetime $startDate
2892
     * @param datetime $endDate
2893
     *
2894
     * @return array
2895
     */
2896
    public static function getUsersThatHadConversationWithUser($userId, $startDate = null, $endDate = null)
2897
    {
2898
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2899
        $userId = (int) $userId;
2900
2901
        $sql = "SELECT DISTINCT
2902
                    user_sender_id
2903
                FROM $messagesTable
2904
                WHERE
2905
                    user_receiver_id = ".$userId;
2906
2907
        if ($startDate != null) {
2908
            $startDate = Database::escape_string($startDate);
2909
            $sql .= " AND send_date >= '".$startDate."'";
2910
        }
2911
2912
        if ($endDate != null) {
2913
            $endDate = Database::escape_string($endDate);
2914
            $sql .= " AND send_date <= '".$endDate."'";
2915
        }
2916
2917
        $result = Database::query($sql);
2918
        $users = Database::store_result($result);
2919
        $userList = [];
2920
        foreach ($users as $userData) {
2921
            $userId = $userData['user_sender_id'];
2922
            if (empty($userId)) {
2923
                continue;
2924
            }
2925
            $userInfo = api_get_user_info($userId);
2926
            if ($userInfo) {
2927
                $userList[$userId] = $userInfo;
2928
            }
2929
        }
2930
2931
        return $userList;
2932
    }
2933
2934
    /**
2935
     * @param int      $userId
2936
     * @param int      $otherUserId
2937
     * @param datetime $startDate
2938
     * @param datetime $endDate
2939
     *
2940
     * @return array
2941
     */
2942
    public static function getAllMessagesBetweenStudents($userId, $otherUserId, $startDate = null, $endDate = null)
2943
    {
2944
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2945
        $userId = (int) $userId;
2946
        $otherUserId = (int) $otherUserId;
2947
2948
        if (empty($otherUserId) || empty($userId)) {
2949
            return [];
2950
        }
2951
2952
        $sql = "SELECT DISTINCT *
2953
                FROM $messagesTable
2954
                WHERE
2955
                    ((user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
2956
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId))
2957
            ";
2958
        if ($startDate != null) {
2959
            $startDate = Database::escape_string($startDate);
2960
            $sql .= " AND send_date >= '".$startDate."'";
2961
        }
2962
        if ($endDate != null) {
2963
            $endDate = Database::escape_string($endDate);
2964
            $sql .= " AND send_date <= '".$endDate."'";
2965
        }
2966
        $sql .= " ORDER BY send_date DESC";
2967
        $result = Database::query($sql);
2968
        $messages = Database::store_result($result);
2969
        $list = [];
2970
        foreach ($messages as $message) {
2971
            $list[] = $message;
2972
        }
2973
2974
        return $list;
2975
    }
2976
2977
    /**
2978
     * @param string $subject
2979
     * @param string $message
2980
     * @param array  $courseInfo
2981
     * @param int    $sessionId
2982
     *
2983
     * @return bool
2984
     */
2985
    public static function sendMessageToAllUsersInCourse($subject, $message, $courseInfo, $sessionId = 0)
2986
    {
2987
        if (empty($courseInfo)) {
2988
            return false;
2989
        }
2990
2991
        $senderId = api_get_user_id();
2992
        if (empty($senderId)) {
2993
            return false;
2994
        }
2995
        if (empty($sessionId)) {
2996
            // Course students and teachers
2997
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code']);
2998
        } else {
2999
            // Course-session students and course session coaches
3000
            $users = CourseManager::get_user_list_from_course_code($courseInfo['code'], $sessionId);
3001
        }
3002
3003
        if (empty($users)) {
3004
            return false;
3005
        }
3006
3007
        foreach ($users as $userInfo) {
3008
            self::send_message_simple(
3009
                $userInfo['user_id'],
3010
                $subject,
3011
                $message,
3012
                $senderId,
3013
                false,
3014
                false,
3015
                [],
3016
                false
3017
            );
3018
        }
3019
    }
3020
3021
    /**
3022
     * Clean audio messages already added in the message tool.
3023
     */
3024
    public static function cleanAudioMessage()
3025
    {
3026
        $audioId = Session::read('current_audio_id');
3027
        if (!empty($audioId)) {
3028
            api_remove_uploaded_file_by_id('audio_message', api_get_user_id(), $audioId);
3029
            Session::erase('current_audio_id');
3030
        }
3031
    }
3032
3033
    /**
3034
     * @param int    $senderId
3035
     * @param string $subject
3036
     * @param string $message
3037
     */
3038
    public static function sendMessageToAllAdminUsers(
3039
        $senderId,
3040
        $subject,
3041
        $message
3042
    ) {
3043
        $admins = UserManager::get_all_administrators();
3044
        foreach ($admins as $admin) {
3045
            self::send_message_simple($admin['user_id'], $subject, $message, $senderId);
3046
        }
3047
    }
3048
3049
    /**
3050
     * @param int $messageId
3051
     * @param int $userId
3052
     *
3053
     * @return array
3054
     */
3055
    public static function countLikesAndDislikes($messageId, $userId)
3056
    {
3057
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
3058
            return [];
3059
        }
3060
3061
        $messageId = (int) $messageId;
3062
        $userId = (int) $userId;
3063
3064
        $em = Database::getManager();
3065
        $query = $em
3066
            ->createQuery('
3067
                SELECT SUM(l.liked) AS likes, SUM(l.disliked) AS dislikes FROM ChamiloCoreBundle:MessageFeedback l
3068
                WHERE l.message = :message
3069
            ')
3070
            ->setParameters(['message' => $messageId]);
3071
3072
        try {
3073
            $counts = $query->getSingleResult();
3074
        } catch (Exception $e) {
3075
            $counts = ['likes' => 0, 'dislikes' => 0];
3076
        }
3077
3078
        $userLike = $em
3079
            ->getRepository('ChamiloCoreBundle:MessageFeedback')
3080
            ->findOneBy(['message' => $messageId, 'user' => $userId]);
3081
3082
        return [
3083
            'likes' => (int) $counts['likes'],
3084
            'dislikes' => (int) $counts['dislikes'],
3085
            'user_liked' => $userLike ? $userLike->isLiked() : false,
3086
            'user_disliked' => $userLike ? $userLike->isDisliked() : false,
3087
        ];
3088
    }
3089
3090
    /**
3091
     * @param int $messageId
3092
     * @param int $userId
3093
     * @param int $groupId   Optional.
3094
     *
3095
     * @return string
3096
     */
3097
    public static function getLikesButton($messageId, $userId, $groupId = 0)
3098
    {
3099
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
3100
            return '';
3101
        }
3102
3103
        $countLikes = self::countLikesAndDislikes($messageId, $userId);
3104
3105
        $class = $countLikes['user_liked'] ? 'btn-primary' : 'btn-default';
3106
3107
        $btnLike = Display::button(
3108
            'like',
3109
            Display::returnFontAwesomeIcon('thumbs-up', '', true)
3110
                .PHP_EOL.'<span>'.$countLikes['likes'].'</span>',
3111
            [
3112
                'title' => get_lang('VoteLike'),
3113
                'class' => 'btn  social-like '.$class,
3114
                'data-status' => 'like',
3115
                'data-message' => $messageId,
3116
                'data-group' => $groupId,
3117
            ]
3118
        );
3119
3120
        $btnDislike = '';
3121
        if (api_get_configuration_value('disable_dislike_option') === false) {
3122
            $disabled = $countLikes['user_disliked'] ? 'btn-danger' : 'btn-default';
3123
3124
            $btnDislike = Display::button(
3125
                'like',
3126
                Display::returnFontAwesomeIcon('thumbs-down', '', true)
3127
                .PHP_EOL.'<span>'.$countLikes['dislikes'].'</span>',
3128
                [
3129
                    'title' => get_lang('VoteDislike'),
3130
                    'class' => 'btn social-like '.$disabled,
3131
                    'data-status' => 'dislike',
3132
                    'data-message' => $messageId,
3133
                    'data-group' => $groupId,
3134
                ]
3135
            );
3136
        }
3137
3138
        return $btnLike.PHP_EOL.$btnDislike;
3139
    }
3140
3141
    /**
3142
     * Execute the SQL necessary to know the number of messages in the database.
3143
     *
3144
     * @param int $userId The user for which we need the unread messages count
3145
     *
3146
     * @return int The number of unread messages in the database for the given user
3147
     */
3148
    public static function getCountNewMessagesFromDB($userId)
3149
    {
3150
        $userId = (int) $userId;
3151
3152
        if (empty($userId)) {
3153
            return 0;
3154
        }
3155
3156
        $table = Database::get_main_table(TABLE_MESSAGE);
3157
        $sql = "SELECT COUNT(id) as count
3158
                FROM $table
3159
                WHERE
3160
                    user_receiver_id = $userId AND
3161
                    msg_status = ".MESSAGE_STATUS_UNREAD;
3162
        $result = Database::query($sql);
3163
        $row = Database::fetch_assoc($result);
3164
3165
        return (int) $row['count'];
3166
    }
3167
3168
    public static function getMessagesCountForUser(int $userId): array
3169
    {
3170
        // Setting notifications
3171
        $countUnreadMessage = 0;
3172
3173
        if (api_get_setting('allow_message_tool') === 'true') {
3174
            // get count unread message and total invitations
3175
            $countUnreadMessage = MessageManager::getCountNewMessagesFromDB($userId);
3176
        }
3177
3178
        if (api_get_setting('allow_social_tool') === 'true') {
3179
            $numberOfNewMessagesOfFriend = SocialManager::get_message_number_invitation_by_user_id(
3180
                $userId
3181
            );
3182
            $usergroup = new UserGroup();
3183
            $groupPendingInvitations = $usergroup->get_groups_by_user(
3184
                $userId,
3185
                GROUP_USER_PERMISSION_PENDING_INVITATION
3186
            );
3187
3188
            if (!empty($groupPendingInvitations)) {
3189
                $groupPendingInvitations = count($groupPendingInvitations);
3190
            } else {
3191
                $groupPendingInvitations = 0;
3192
            }
3193
3194
            return [
3195
                'ms_friends' => $numberOfNewMessagesOfFriend,
3196
                'ms_groups' => $groupPendingInvitations,
3197
                'ms_inbox' => $countUnreadMessage,
3198
            ];
3199
        }
3200
3201
        return [];
3202
    }
3203
3204
    /**
3205
     * @throws Exception
3206
     */
3207
    public static function setDefaultValuesInFormFromMessageInfo(array $messageInfo, FormValidator $form)
3208
    {
3209
        $currentUserId = api_get_user_id();
3210
        $contentMatch = [];
3211
        preg_match('/<body>(.*?)<\/body>/s', $messageInfo['content'], $contentMatch);
3212
3213
        $defaults = [
3214
            'title' => $messageInfo['title'],
3215
            'content' => $contentMatch[1] ?? '',
3216
        ];
3217
3218
        if (api_get_configuration_value('agenda_collective_invitations')) {
3219
            $defaults['invitees'] = [];
3220
3221
            if ($currentUserId != $messageInfo['user_sender_id']) {
3222
                $senderInfo = api_get_user_info($messageInfo['user_sender_id']);
3223
                $form->getElement('invitees')->addOption(
3224
                    $senderInfo['complete_name_with_username'],
3225
                    $senderInfo['id']
3226
                );
3227
                $defaults['invitees'][] = $senderInfo['id'];
3228
            }
3229
3230
            $messageCopies = MessageManager::getCopiesFromMessageInfo($messageInfo);
3231
3232
            foreach ($messageCopies as $messageCopy) {
3233
                if ($currentUserId == $messageCopy->getUserReceiverId()) {
3234
                    continue;
3235
                }
3236
3237
                $receiverInfo = api_get_user_info($messageCopy->getUserReceiverId());
3238
                $form->getElement('invitees')->addOption(
3239
                    $receiverInfo['complete_name_with_username'],
3240
                    $receiverInfo['id']
3241
                );
3242
3243
                $defaults['invitees'][] = $receiverInfo['id'];
3244
            }
3245
        }
3246
3247
        $form->setDefaults($defaults);
3248
    }
3249
3250
    /**
3251
     * @throws Exception
3252
     *
3253
     * @return array<Message>
3254
     */
3255
    public static function getCopiesFromMessageInfo(array $messageInfo): array
3256
    {
3257
        $em = Database::getManager();
3258
        $messageRepo = $em->getRepository('ChamiloCoreBundle:Message');
3259
3260
        return $messageRepo->findBy(
3261
            [
3262
                'userSenderId' => $messageInfo['user_sender_id'],
3263
                'msgStatus' => MESSAGE_STATUS_OUTBOX,
3264
                'sendDate' => new DateTime($messageInfo['send_date'], new DateTimeZone('UTC')),
3265
                'title' => $messageInfo['title'],
3266
                'content' => $messageInfo['content'],
3267
                'groupId' => $messageInfo['group_id'],
3268
                'parentId' => $messageInfo['parent_id'],
3269
            ]
3270
        );
3271
    }
3272
}
3273