Completed
Push — master ( 966b12...7d9ab3 )
by Julito
08:22
created

MessageManager::send_message()   F

Complexity

Conditions 55
Paths > 20000

Size

Total Lines 321
Code Lines 200

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 55
eloc 200
nc 72960
nop 16
dl 0
loc 321
rs 0
c 0
b 0
f 0

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