Passed
Push — master ( 0e8800...0cdc5b )
by Julito
11:59
created

MessageManager::send_message()   F

Complexity

Conditions 54
Paths > 20000

Size

Total Lines 313
Code Lines 183

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 54
eloc 183
nc 154192
nop 16
dl 0
loc 313
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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