Passed
Push — 1.11.x ( 0d8106...9cc1fc )
by Julito
13:44 queued 14s
created

MessageManager::send_message()   F

Complexity

Conditions 53
Paths > 20000

Size

Total Lines 319
Code Lines 198

Duplication

Lines 0
Ratio 0 %

Importance

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