Passed
Push — master ( ab8dec...906584 )
by Julito
09:36
created

MessageManager::send_message()   F

Complexity

Conditions 53
Paths > 20000

Size

Total Lines 327
Code Lines 196

Duplication

Lines 0
Ratio 0 %

Importance

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