Passed
Push — master ( 44b866...954b89 )
by Julito
07:40
created

MessageManager::delete_message_by_user_receiver()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 42
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 19
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 42
rs 8.4444
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
    /**
22
     * @param array $extraParams
23
     *
24
     * @return string
25
     */
26
    public static function getWhereConditions($extraParams)
27
    {
28
        $userId = api_get_user_id();
29
30
        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
31
        $type = isset($extraParams['type']) && !empty($extraParams['type']) ? $extraParams['type'] : '';
32
33
        if (empty($type)) {
34
            return '';
35
        }
36
37
        switch ($type) {
38
            case Message::MESSAGE_TYPE_INBOX:
39
                $statusList = [MESSAGE_STATUS_NEW, MESSAGE_STATUS_UNREAD];
40
                $userCondition = " user_receiver_id = $userId AND";
41
                break;
42
            case Message::MESSAGE_TYPE_OUTBOX:
43
                $statusList = [MESSAGE_STATUS_OUTBOX];
44
                $userCondition = " user_sender_id = $userId AND";
45
                break;
46
            case Message::MESSAGE_TYPE_PROMOTED:
47
                $statusList = [MESSAGE_STATUS_PROMOTED];
48
                $userCondition = " user_receiver_id = $userId AND";
49
                break;
50
        }
51
52
        if (empty($statusList)) {
53
            return '';
54
        }
55
56
        $keywordCondition = '';
57
        if (!empty($keyword)) {
58
            $keyword = Database::escape_string($keyword);
59
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
60
        }
61
        $messageStatusCondition = implode("','", $statusList);
62
63
        return " $userCondition
64
                 msg_status IN ('$messageStatusCondition')
65
                 $keywordCondition";
66
    }
67
68
    /**
69
     * Gets information about some messages, used for the inbox sortable table.
70
     *
71
     * @param int    $from
72
     * @param int    $numberOfItems
73
     * @param string $column
74
     * @param string $direction
75
     * @param array  $extraParams
76
     *
77
     * @return array
78
     */
79
    public static function getMessageData(
80
        $from,
81
        $numberOfItems,
82
        $column,
83
        $direction,
84
        $extraParams = []
85
    ) {
86
        $from = (int) $from;
87
        $numberOfItems = (int) $numberOfItems;
88
        $column = (int) $column;
89
90
        // Forcing this order.
91
        if (!isset($direction)) {
92
            $column = 2;
93
            $direction = 'DESC';
94
        } else {
95
            if (!in_array($direction, ['ASC', 'DESC'])) {
96
                $direction = 'ASC';
97
            }
98
        }
99
100
        if (!in_array($column, [0, 1, 2])) {
101
            $column = 2;
102
        }
103
104
        $type = isset($extraParams['type']) && !empty($extraParams['type']) ? $extraParams['type'] : '';
105
106
        if (empty($type)) {
107
            return [];
108
        }
109
110
        $viewUrl = '';
111
        switch ($type) {
112
            case Message::MESSAGE_TYPE_OUTBOX:
113
            case Message::MESSAGE_TYPE_INBOX:
114
                $viewUrl = api_get_path(WEB_CODE_PATH).'messages/view_message.php';
115
                break;
116
            case Message::MESSAGE_TYPE_PROMOTED:
117
                $viewUrl = api_get_path(WEB_CODE_PATH).'social/view_promoted_message.php';
118
                break;
119
        }
120
        $viewUrl .= '?type='.$type;
121
122
        $whereConditions = self::getWhereConditions($extraParams);
123
124
        if (empty($whereConditions)) {
125
            return [];
126
        }
127
128
        $table = Database::get_main_table(TABLE_MESSAGE);
129
        $sql = "SELECT
130
                    id as col0,
131
                    title as col1,
132
                    send_date as col2,
133
                    msg_status as col3,
134
                    user_sender_id,
135
                    user_receiver_id
136
                FROM $table
137
                WHERE
138
                    $whereConditions
139
                ORDER BY col$column $direction
140
                LIMIT $from, $numberOfItems";
141
142
        $result = Database::query($sql);
143
        $messageList = [];
144
        $newMessageLink = api_get_path(WEB_CODE_PATH).'messages/new_message.php';
145
146
        $actions = $extraParams['actions'];
147
        $url = api_get_self();
148
        while ($row = Database::fetch_array($result, 'ASSOC')) {
149
            $messageId = $row['col0'];
150
            $title = $row['col1'];
151
            $sendDate = $row['col2'];
152
            $status = $row['col3'];
153
            $senderId = $row['user_sender_id'];
154
            $receiverId = $row['user_receiver_id'];
155
156
            $title = Security::remove_XSS($title, STUDENT, true);
157
            $title = cut($title, 80, true);
158
159
            $class = 'class = "read"';
160
            if (1 == $status) {
161
                $class = 'class = "unread"';
162
            }
163
164
            $userInfo = api_get_user_info($senderId);
165
            if (Message::MESSAGE_TYPE_OUTBOX == $type) {
166
                $userInfo = api_get_user_info($receiverId);
167
            }
168
            $message[3] = '';
169
            if (!empty($senderId) && !empty($userInfo)) {
170
                $message[1] = '<a '.$class.' href="'.$viewUrl.'&id='.$messageId.'">'.$title.'</a><br />';
171
                $message[1] .= $userInfo['complete_name_with_username'];
172
                if (in_array('reply', $actions)) {
173
                    $message[3] =
174
                        Display::url(
175
                            Display::returnFontAwesomeIcon('reply', 2),
176
                            $newMessageLink.'?re_id='.$messageId,
177
                            ['title' => get_lang('Reply to this message')]
178
                        );
179
                }
180
            } else {
181
                $message[1] = '<a '.$class.' href="'.$viewUrl.'&id='.$messageId.'">'.$title.'</a><br />';
182
                $message[1] .= get_lang('Unknown user');
183
                if (in_array('reply', $actions)) {
184
                    $message[3] =
185
                        Display::url(
186
                            Display::returnFontAwesomeIcon('reply', 2),
187
                            '#',
188
                            ['title' => get_lang('Reply to this message')]
189
                        );
190
                }
191
            }
192
193
            $message[0] = $messageId;
194
            $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
195
196
            // Actions
197
            if (in_array('edit', $actions)) {
198
                $message[3] .=
199
                    '&nbsp;&nbsp;'.
200
                    Display::url(
201
                        Display::returnFontAwesomeIcon('pencil', 2),
202
                        $newMessageLink.'?action=edit&id='.$messageId,
203
                        ['title' => get_lang('Forward message')]
204
                    );
205
            }
206
207
            // Actions
208
            if (in_array('forward', $actions)) {
209
                $message[3] .=
210
                    '&nbsp;&nbsp;'.
211
                    Display::url(
212
                        Display::returnFontAwesomeIcon('share', 2),
213
                        $newMessageLink.'?forward_id='.$messageId,
214
                        ['title' => get_lang('Forward message')]
215
                    );
216
            }
217
218
            if (in_array('delete', $actions)) {
219
                $message[3] .= '&nbsp;&nbsp;<a title="'.addslashes(
220
                    get_lang('Delete message')
221
                ).'" onclick="javascript:if(!confirm('."'".addslashes(
222
                    api_htmlentities(get_lang('ConfirmDelete message'))
223
                )."'".')) return false;" href="'.$url.'?action=deleteone&id='.$messageId.'">'.
224
                Display::returnFontAwesomeIcon('trash', 2).'</a>';
225
            }
226
227
            foreach ($message as $key => $value) {
228
                $message[$key] = api_xml_http_response_encode($value);
229
            }
230
            $messageList[] = $message;
231
        }
232
233
        return $messageList;
234
    }
235
236
    /**
237
     * @param array  $aboutUserInfo
238
     * @param array  $fromUserInfo
239
     * @param string $subject
240
     * @param string $content
241
     *
242
     * @return bool
243
     */
244
    public static function sendMessageAboutUser(
245
        $aboutUserInfo,
246
        $fromUserInfo,
247
        $subject,
248
        $content
249
    ) {
250
        if (empty($aboutUserInfo) || empty($fromUserInfo)) {
251
            return false;
252
        }
253
254
        if (empty($fromUserInfo['id']) || empty($aboutUserInfo['id'])) {
255
            return false;
256
        }
257
258
        $table = Database::get_main_table(TABLE_MESSAGE);
259
        $now = api_get_utc_datetime();
260
        $params = [
261
            'user_sender_id' => $fromUserInfo['id'],
262
            'user_receiver_id' => $aboutUserInfo['id'],
263
            'msg_status' => MESSAGE_STATUS_CONVERSATION,
264
            'send_date' => $now,
265
            'title' => $subject,
266
            'content' => $content,
267
            'group_id' => 0,
268
            'parent_id' => 0,
269
            'update_date' => $now,
270
        ];
271
        $id = Database::insert($table, $params);
272
273
        if ($id) {
274
            return true;
275
        }
276
277
        return false;
278
    }
279
280
    public static function getMessagesAboutUser(User $user): array
281
    {
282
        if (!empty($user)) {
283
            $table = Database::get_main_table(TABLE_MESSAGE);
284
            $sql = 'SELECT id FROM '.$table.'
285
                    WHERE
286
                      user_receiver_id = '.$user->getId().' AND
287
                      msg_status = '.MESSAGE_STATUS_CONVERSATION.'
288
                    ';
289
            $result = Database::query($sql);
290
            $messages = [];
291
            $repo = Database::getManager()->getRepository(Message::class);
292
            while ($row = Database::fetch_array($result)) {
293
                $message = $repo->find($row['id']);
294
                $messages[] = $message;
295
            }
296
297
            return $messages;
298
        }
299
300
        return [];
301
    }
302
303
    public static function getMessagesAboutUserToString(User $user): string
304
    {
305
        $messages = self::getMessagesAboutUser($user);
306
        $html = '';
307
        if (!empty($messages)) {
308
            /** @var Message $message */
309
            foreach ($messages as $message) {
310
                $tag = 'message_'.$message->getId();
311
                $tagAccordion = 'accordion_'.$message->getId();
312
                $tagCollapse = 'collapse_'.$message->getId();
313
                $date = Display::dateToStringAgoAndLongDate(
314
                    $message->getSendDate()
315
                );
316
                $localTime = api_get_local_time(
317
                    $message->getSendDate(),
318
                    null,
319
                    null,
320
                    false,
321
                    false
322
                );
323
                $senderId = $message->getUserSender()->getId();
324
                $senderInfo = api_get_user_info($senderId);
325
                $html .= Display::panelCollapse(
326
                    $localTime.' '.$senderInfo['complete_name'].' '.$message->getTitle(),
327
                    $message->getContent().'<br />'.$date.'<br />'.get_lang(
328
                        'Author'
329
                    ).': '.$senderInfo['complete_name_with_message_link'],
330
                    $tag,
331
                    null,
332
                    $tagAccordion,
333
                    $tagCollapse,
334
                    false
335
                );
336
            }
337
        }
338
339
        return $html;
340
    }
341
342
    /**
343
     * @param int    $senderId
344
     * @param int    $receiverId
345
     * @param string $subject
346
     * @param string $message
347
     *
348
     * @return bool
349
     */
350
    public static function messageWasAlreadySent($senderId, $receiverId, $subject, $message)
351
    {
352
        $table = Database::get_main_table(TABLE_MESSAGE);
353
        $senderId = (int) $senderId;
354
        $receiverId = (int) $receiverId;
355
        $subject = Database::escape_string($subject);
356
        $message = Database::escape_string($message);
357
358
        $sql = "SELECT * FROM $table
359
                WHERE
360
                    user_sender_id = $senderId AND
361
                    user_receiver_id = $receiverId AND
362
                    title = '$subject' AND
363
                    content = '$message' AND
364
                    (msg_status = ".MESSAGE_STATUS_UNREAD." OR msg_status = ".MESSAGE_STATUS_NEW.")
365
                ";
366
        $result = Database::query($sql);
367
368
        return Database::num_rows($result) > 0;
369
    }
370
371
    /**
372
     * Sends a message to a user/group.
373
     *
374
     * @param int    $receiverUserId
375
     * @param string $subject
376
     * @param string $content
377
     * @param array  $attachments                files array($_FILES) (optional)
378
     * @param array  $fileCommentList            about attachment files (optional)
379
     * @param int    $group_id                   (optional)
380
     * @param int    $parent_id                  (optional)
381
     * @param int    $editMessageId              id for updating the message (optional)
382
     * @param int    $topic_id                   (optional) the default value is the current user_id
383
     * @param int    $sender_id
384
     * @param bool   $directMessage
385
     * @param int    $forwardId
386
     * @param array  $smsParameters
387
     * @param bool   $checkCurrentAudioId
388
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
389
     * @param int    $status                     Message status
390
     *
391
     * @return bool
392
     */
393
    public static function send_message(
394
        $receiverUserId,
395
        $subject,
396
        $content,
397
        array $attachments = [],
398
        array $fileCommentList = [],
399
        $group_id = 0,
400
        $parent_id = 0,
401
        $editMessageId = 0,
402
        $topic_id = 0,
403
        $sender_id = 0,
404
        $directMessage = false,
405
        $forwardId = 0,
406
        $smsParameters = [],
407
        $checkCurrentAudioId = false,
408
        $forceTitleWhenSendingEmail = false,
409
        $status = 0
410
    ) {
411
        $group_id = (int) $group_id;
412
        $receiverUserId = (int) $receiverUserId;
413
        $parent_id = (int) $parent_id;
414
        $editMessageId = (int) $editMessageId;
415
        $topic_id = (int) $topic_id;
416
        $status = empty($status) ? MESSAGE_STATUS_UNREAD : (int) $status;
417
        $user_sender_id = empty($sender_id) ? api_get_user_id() : (int) $sender_id;
418
419
        if (empty($user_sender_id) || empty($receiverUserId)) {
420
            return false;
421
        }
422
423
        $userSender = api_get_user_entity($user_sender_id);
424
        if (null === $userSender) {
425
            Display::addFlash(Display::return_message(get_lang('This user doesn\'t exist'), 'warning'));
426
427
            return false;
428
        }
429
430
        $userRecipient = api_get_user_entity($receiverUserId);
431
432
        if (null === $userRecipient) {
433
            return false;
434
        }
435
436
        // Disabling messages for inactive users.
437
        if (!$userRecipient->getActive()) {
438
            return false;
439
        }
440
441
        $sendEmail = true;
442
        // Disabling messages depending the pausetraining plugin.
443
        $allowPauseFormation =
444
            'true' === api_get_plugin_setting('pausetraining', 'tool_enable') &&
445
            'true' === api_get_plugin_setting('pausetraining', 'allow_users_to_edit_pause_formation');
446
447
        if ($allowPauseFormation) {
448
            $extraFieldValue = new ExtraFieldValue('user');
449
            $disableEmails = $extraFieldValue->get_values_by_handler_and_field_variable(
450
                $receiverUserId,
451
                'disable_emails'
452
            );
453
454
            // User doesn't want email notifications but chamilo inbox still available.
455
            if (!empty($disableEmails) &&
456
                isset($disableEmails['value']) && 1 === (int) $disableEmails['value']
457
            ) {
458
                $sendEmail = false;
459
            }
460
461
            if ($sendEmail) {
462
                // Check if user pause his formation.
463
                $pause = $extraFieldValue->get_values_by_handler_and_field_variable(
464
                    $receiverUserId,
465
                    'pause_formation'
466
                );
467
                if (!empty($pause) && isset($pause['value']) && 1 === (int) $pause['value']) {
468
                    $startDate = $extraFieldValue->get_values_by_handler_and_field_variable(
469
                        $receiverUserId,
470
                        'start_pause_date'
471
                    );
472
                    $endDate = $extraFieldValue->get_values_by_handler_and_field_variable(
473
                        $receiverUserId,
474
                        'end_pause_date'
475
                    );
476
477
                    if (!empty($startDate) && isset($startDate['value']) && !empty($startDate['value']) &&
478
                        !empty($endDate) && isset($endDate['value']) && !empty($endDate['value'])
479
                    ) {
480
                        $now = time();
481
                        $start = api_strtotime($startDate['value']);
482
                        $end = api_strtotime($endDate['value']);
483
484
                        if ($now > $start && $now < $end) {
485
                            $sendEmail = false;
486
                        }
487
                    }
488
                }
489
            }
490
        }
491
492
        $totalFileSize = 0;
493
        $attachmentList = [];
494
        if (is_array($attachments)) {
495
            $counter = 0;
496
            foreach ($attachments as $attachment) {
497
                $attachment['comment'] = $fileCommentList[$counter] ?? '';
498
                $fileSize = $attachment['size'] ?? 0;
499
                if (is_array($fileSize)) {
500
                    foreach ($fileSize as $size) {
501
                        $totalFileSize += $size;
502
                    }
503
                } else {
504
                    $totalFileSize += $fileSize;
505
                }
506
                $attachmentList[] = $attachment;
507
                $counter++;
508
            }
509
        }
510
511
        if ($checkCurrentAudioId) {
512
            // Add the audio file as an attachment
513
            $audio = Session::read('current_audio');
514
            if (!empty($audio) && isset($audio['name']) && !empty($audio['name'])) {
515
                $audio['comment'] = 'audio_message';
516
                // create attachment from audio message
517
                $attachmentList[] = $audio;
518
            }
519
        }
520
521
        // Validating fields
522
        if (empty($subject) && empty($group_id)) {
523
            Display::addFlash(
524
                Display::return_message(
525
                    get_lang('You should write a subject'),
526
                    'warning'
527
                )
528
            );
529
530
            return false;
531
        } elseif ($totalFileSize > (int) api_get_setting('message_max_upload_filesize')) {
532
            $warning = sprintf(
533
                get_lang('Files size exceeds'),
534
                format_file_size(api_get_setting('message_max_upload_filesize'))
535
            );
536
537
            Display::addFlash(Display::return_message($warning, 'warning'));
538
539
            return false;
540
        }
541
542
        $em = Database::getManager();
543
        $repo = $em->getRepository(Message::class);
544
        $parent = null;
545
        if (!empty($parent_id)) {
546
            $parent = $repo->find($parent_id);
547
        }
548
549
        $message = null;
550
        // Just in case we replace the and \n and \n\r while saving in the DB
551
        if (!empty($receiverUserId) || !empty($group_id)) {
552
            // message for user friend
553
            //@todo it's possible to edit a message? yes, only for groups
554
            if (!empty($editMessageId)) {
555
                $message = $repo->find($editMessageId);
556
                if (null !== $message) {
557
                    $message->setContent($content);
558
                    $em->persist($message);
559
                    $em->flush();
560
                }
561
                $messageId = $editMessageId;
562
            } else {
563
                $message = new Message();
564
                $message
565
                    ->setUserSender($userSender)
566
                    ->setUserReceiver($userRecipient)
567
                    ->setMsgType($status)
568
                    ->setTitle($subject)
569
                    ->setContent($content)
570
                    ->setGroup(api_get_group_entity($group_id))
571
                    ->setParent($parent)
572
                ;
573
                $em->persist($message);
574
                $em->flush();
575
                $messageId = $message->getId();
576
            }
577
578
            // Forward also message attachments.
579
            if (!empty($forwardId)) {
580
                $forwardMessage = $repo->find($forwardId);
581
                if (null !== $forwardMessage) {
582
                    $forwardAttachments = $forwardMessage->getAttachments();
583
                    foreach ($forwardAttachments as $forwardAttachment) {
584
                        $message->addAttachment($forwardAttachment);
585
                    }
586
                    $em->persist($message);
587
                    $em->flush();
588
                }
589
            }
590
591
            // Save attachment file for inbox messages
592
            if (is_array($attachmentList)) {
593
                foreach ($attachmentList as $attachment) {
594
                    if (0 === $attachment['error']) {
595
                        self::saveMessageAttachmentFile(
596
                            $attachment,
597
                            $attachment['comment'] ?? '',
598
                            $message,
599
                        );
600
                    }
601
                }
602
            }
603
604
            if ($sendEmail) {
605
                $notification = new Notification();
606
                $sender_info = api_get_user_info($user_sender_id);
607
608
                // add file attachment additional attributes
609
                $attachmentAddedByMail = [];
610
                foreach ($attachmentList as $attachment) {
611
                    $attachmentAddedByMail[] = [
612
                        'path' => $attachment['tmp_name'],
613
                        'filename' => $attachment['name'],
614
                    ];
615
                }
616
617
                if (empty($group_id)) {
618
                    $type = Notification::NOTIFICATION_TYPE_MESSAGE;
619
                    if ($directMessage) {
620
                        $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
621
                    }
622
                    $notification->saveNotification(
623
                        $messageId,
624
                        $type,
625
                        [$receiverUserId],
626
                        $subject,
627
                        $content,
628
                        $sender_info,
629
                        $attachmentAddedByMail,
630
                        $smsParameters,
631
                        $forceTitleWhenSendingEmail
632
                    );
633
                } else {
634
                    $usergroup = new UserGroupModel();
635
                    $group_info = $usergroup->get($group_id);
636
                    $group_info['topic_id'] = $topic_id;
637
                    $group_info['msg_id'] = $messageId;
638
639
                    $user_list = $usergroup->get_users_by_group(
640
                        $group_id,
641
                        false,
642
                        [],
643
                        0,
644
                        1000
645
                    );
646
647
                    // Adding more sense to the message group
648
                    $subject = sprintf(get_lang('There is a new message in group %s'), $group_info['name']);
649
                    $new_user_list = [];
650
                    foreach ($user_list as $user_data) {
651
                        $new_user_list[] = $user_data['id'];
652
                    }
653
                    $group_info = [
654
                        'group_info' => $group_info,
655
                        'user_info' => $sender_info,
656
                    ];
657
                    $notification->saveNotification(
658
                        $messageId,
659
                        Notification::NOTIFICATION_TYPE_GROUP,
660
                        $new_user_list,
661
                        $subject,
662
                        $content,
663
                        $group_info,
664
                        $attachmentAddedByMail,
665
                        $smsParameters
666
                    );
667
                }
668
            }
669
670
            return $messageId;
671
        }
672
673
        return false;
674
    }
675
676
    /**
677
     * @param int    $receiverUserId
678
     * @param string $subject
679
     * @param string $message
680
     * @param int    $sender_id
681
     * @param bool   $sendCopyToDrhUsers send copy to related DRH users
682
     * @param bool   $directMessage
683
     * @param array  $smsParameters
684
     * @param bool   $uploadFiles        Do not upload files using the MessageManager class
685
     * @param array  $attachmentList
686
     *
687
     * @return bool
688
     */
689
    public static function send_message_simple(
690
        $receiverUserId,
691
        $subject,
692
        $message,
693
        $sender_id = 0,
694
        $sendCopyToDrhUsers = false,
695
        $directMessage = false,
696
        $smsParameters = [],
697
        $uploadFiles = true,
698
        $attachmentList = []
699
    ) {
700
        $files = $_FILES ? $_FILES : [];
701
        if (false === $uploadFiles) {
702
            $files = [];
703
        }
704
        // $attachmentList must have: tmp_name, name, size keys
705
        if (!empty($attachmentList)) {
706
            $files = $attachmentList;
707
        }
708
        $result = self::send_message(
709
            $receiverUserId,
710
            $subject,
711
            $message,
712
            $files,
713
            [],
714
            null,
715
            null,
716
            null,
717
            null,
718
            $sender_id,
719
            $directMessage,
720
            0,
721
            $smsParameters
722
        );
723
724
        if ($sendCopyToDrhUsers) {
725
            $userInfo = api_get_user_info($receiverUserId);
726
            $drhList = UserManager::getDrhListFromUser($receiverUserId);
727
            if (!empty($drhList)) {
728
                foreach ($drhList as $drhInfo) {
729
                    $message = sprintf(
730
                        get_lang('Copy of message sent to %s'),
731
                        $userInfo['complete_name']
732
                    ).' <br />'.$message;
733
734
                    self::send_message_simple(
735
                        $drhInfo['id'],
736
                        $subject,
737
                        $message,
738
                        $sender_id,
739
                        false,
740
                        $directMessage
741
                    );
742
                }
743
            }
744
        }
745
746
        return $result;
747
    }
748
749
    public static function softDeleteAttachments(Message $message): void
750
    {
751
        $attachments = $message->getAttachments();
752
        if (!empty($attachments)) {
753
            $repo = Container::getMessageAttachmentRepository();
754
            foreach ($attachments as $file) {
755
                $repo->softDelete($file);
756
            }
757
        }
758
    }
759
760
    /**
761
     * Saves a message attachment files.
762
     *
763
     * @param array  $file    $_FILES['name']
764
     * @param string $comment a comment about the uploaded file
765
     */
766
    public static function saveMessageAttachmentFile($file, $comment, Message $message)
767
    {
768
        // Try to add an extension to the file if it hasn't one
769
        $type = $file['type'] ?? '';
770
        if (empty($type)) {
771
            $type = DocumentManager::file_get_mime_type($file['name']);
772
        }
773
        $new_file_name = add_ext_on_mime(stripslashes($file['name']), $type);
774
775
        // user's file name
776
        $fileName = $file['name'];
777
        if (!filter_extension($new_file_name)) {
778
            Display::addFlash(
779
                Display::return_message(
780
                    get_lang('File upload failed: this file extension or file type is prohibited'),
781
                    'error'
782
                )
783
            );
784
785
            return false;
786
        }
787
788
        $em = Database::getManager();
789
        $attachmentRepo = Container::getMessageAttachmentRepository();
790
791
        $attachment = new MessageAttachment();
792
        $attachment
793
            ->setSize($file['size'])
794
            ->setPath($fileName)
795
            ->setFilename($fileName)
796
            ->setComment($comment)
797
            ->setParent($message->getUserSender())
798
            ->setMessage($message)
799
        ;
800
801
        $request = Container::getRequest();
802
        $fileToUpload = null;
803
804
        // Search for files inside the $_FILES, when uploading several files from the form.
805
        if ($request->files->count()) {
806
            /** @var UploadedFile|null $fileRequest */
807
            foreach ($request->files->all() as $fileRequest) {
808
                if (null === $fileRequest) {
809
                    continue;
810
                }
811
                if ($fileRequest->getClientOriginalName() === $file['name']) {
812
                    $fileToUpload = $fileRequest;
813
                    break;
814
                }
815
            }
816
        }
817
818
        // If no found file, try with $file['content'].
819
        if (null === $fileToUpload && isset($file['content'])) {
820
            $handle = tmpfile();
821
            fwrite($handle, $file['content']);
822
            $meta = stream_get_meta_data($handle);
823
            $fileToUpload = new UploadedFile($meta['uri'], $fileName, $file['type'], null, true);
824
        }
825
826
        if (null !== $fileToUpload) {
827
            $em->persist($attachment);
828
            $attachmentRepo->addFile($attachment, $fileToUpload);
829
            $attachment->addUserLink($message->getUserSender());
830
            $attachment->addUserLink($message->getUserReceiver());
831
            $em->flush();
832
833
            return true;
834
        }
835
836
        return false;
837
    }
838
839
    /**
840
     * @param int $user_id
841
     * @param int $message_id
842
     * @param int $type
843
     *
844
     * @return bool
845
     */
846
    public static function update_message_status($user_id, $message_id, $type)
847
    {
848
        $user_id = (int) $user_id;
849
        $message_id = (int) $message_id;
850
        $type = (int) $type;
851
852
        if (empty($user_id) || empty($message_id)) {
853
            return false;
854
        }
855
856
        $table_message = Database::get_main_table(TABLE_MESSAGE);
857
        $sql = "UPDATE $table_message SET
858
                    msg_status = '$type'
859
                WHERE
860
                    user_receiver_id = ".$user_id." AND
861
                    id = '".$message_id."'";
862
        $result = Database::query($sql);
863
864
        return Database::affected_rows($result) > 0;
865
    }
866
867
    /**
868
     * get messages by group id.
869
     *
870
     * @param int $group_id group id
871
     *
872
     * @return array
873
     */
874
    public static function get_messages_by_group($group_id)
875
    {
876
        $group_id = (int) $group_id;
877
878
        if (empty($group_id)) {
879
            return false;
880
        }
881
882
        $table = Database::get_main_table(TABLE_MESSAGE);
883
        $sql = "SELECT * FROM $table
884
                WHERE
885
                    group_id= $group_id AND
886
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
887
                ORDER BY id";
888
        $rs = Database::query($sql);
889
        $data = [];
890
        if (Database::num_rows($rs) > 0) {
891
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
892
                $data[] = $row;
893
            }
894
        }
895
896
        return $data;
897
    }
898
899
    /**
900
     * get messages by group id.
901
     *
902
     * @param int $group_id
903
     * @param int $message_id
904
     *
905
     * @return array
906
     */
907
    public static function get_messages_by_group_by_message($group_id, $message_id)
908
    {
909
        $group_id = (int) $group_id;
910
911
        if (empty($group_id)) {
912
            return false;
913
        }
914
915
        $table = Database::get_main_table(TABLE_MESSAGE);
916
        $sql = "SELECT * FROM $table
917
                WHERE
918
                    group_id = $group_id AND
919
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
920
                ORDER BY id ";
921
922
        $rs = Database::query($sql);
923
        $data = [];
924
        $parents = [];
925
        if (Database::num_rows($rs) > 0) {
926
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
927
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
928
                    $parents[] = $row['id'];
929
                    $data[] = $row;
930
                }
931
            }
932
        }
933
934
        return $data;
935
    }
936
937
    /**
938
     * Get messages by parent id optionally with limit.
939
     *
940
     * @param  int        parent id
941
     * @param  int        group id (optional)
942
     * @param  int        offset (optional)
943
     * @param  int        limit (optional)
944
     *
945
     * @return array
946
     */
947
    public static function getMessagesByParent($parentId, $groupId = 0, $offset = 0, $limit = 0)
948
    {
949
        $table = Database::get_main_table(TABLE_MESSAGE);
950
        $parentId = (int) $parentId;
951
952
        if (empty($parentId)) {
953
            return [];
954
        }
955
956
        $condition_group_id = '';
957
        if (!empty($groupId)) {
958
            $groupId = (int) $groupId;
959
            $condition_group_id = " AND group_id = '$groupId' ";
960
        }
961
962
        $condition_limit = '';
963
        if ($offset && $limit) {
964
            $offset = (int) $offset;
965
            $limit = (int) $limit;
966
            $offset = ($offset - 1) * $limit;
967
            $condition_limit = " LIMIT $offset,$limit ";
968
        }
969
970
        $sql = "SELECT * FROM $table
971
                WHERE
972
                    parent_id='$parentId' AND
973
                    msg_status NOT IN (".MESSAGE_STATUS_OUTBOX.", ".MESSAGE_STATUS_WALL_DELETE.")
974
                    $condition_group_id
975
                ORDER BY send_date DESC $condition_limit ";
976
        $rs = Database::query($sql);
977
        $data = [];
978
        if (Database::num_rows($rs) > 0) {
979
            while ($row = Database::fetch_array($rs)) {
980
                $data[$row['id']] = $row;
981
            }
982
        }
983
984
        return $data;
985
    }
986
987
    /**
988
     * Gets information about messages sent.
989
     *
990
     * @param int
991
     * @param int
992
     * @param string
993
     * @param string
994
     *
995
     * @return array
996
     */
997
    public static function get_message_data_sent(
998
        $from,
999
        $numberOfItems,
1000
        $column,
1001
        $direction,
1002
        $extraParams = []
1003
    ) {
1004
        $from = (int) $from;
1005
        $numberOfItems = (int) $numberOfItems;
1006
        if (!isset($direction)) {
1007
            $column = 2;
1008
            $direction = 'DESC';
1009
        } else {
1010
            $column = (int) $column;
1011
            if (!in_array($direction, ['ASC', 'DESC'])) {
1012
                $direction = 'ASC';
1013
            }
1014
        }
1015
1016
        if (!in_array($column, [0, 1, 2])) {
1017
            $column = 2;
1018
        }
1019
        $table = Database::get_main_table(TABLE_MESSAGE);
1020
        $request = api_is_xml_http_request();
1021
        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
1022
        $keywordCondition = '';
1023
        if (!empty($keyword)) {
1024
            $keyword = Database::escape_string($keyword);
1025
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1026
        }
1027
1028
        $sql = "SELECT
1029
                    id as col0,
1030
                    title as col1,
1031
                    send_date as col2,
1032
                    user_receiver_id,
1033
                    msg_status,
1034
                    user_sender_id
1035
                FROM $table
1036
                WHERE
1037
                    user_sender_id = ".api_get_user_id()." AND
1038
                    msg_status = ".MESSAGE_STATUS_OUTBOX."
1039
                    $keywordCondition
1040
                ORDER BY col$column $direction
1041
                LIMIT $from, $numberOfItems";
1042
        $result = Database::query($sql);
1043
1044
        $message_list = [];
1045
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1046
            $messageId = $row['col0'];
1047
            $title = $row['col1'];
1048
            $sendDate = $row['col2'];
1049
            $senderId = $row['user_sender_id'];
1050
1051
            if (true === $request) {
1052
                $message[0] = '<input type="checkbox" value='.$messageId.' name="out[]">';
1053
            } else {
1054
                $message[0] = $messageId;
1055
            }
1056
1057
            $class = 'class = "read"';
1058
            $title = Security::remove_XSS($title);
1059
            $userInfo = api_get_user_info($senderId);
1060
            if (true === $request) {
1061
                $message[1] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.
1062
                    $userInfo['complete_name_with_username'].'</a>';
1063
                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace(
1064
                        "\\",
1065
                        "",
1066
                        $title
1067
                    ).'</a>';
1068
                //date stays the same
1069
                $message[3] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1070
                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(
1071
                        get_lang('Delete message')
1072
                    ).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
1073
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1074
            } else {
1075
                $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'];
1076
                $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1077
                $message[3] = '<a title="'.addslashes(
1078
                        get_lang('Delete message')
1079
                    ).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(
1080
                        api_htmlentities(get_lang('ConfirmDelete message'))
1081
                    )."'".')) return false;" >'.
1082
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1083
            }
1084
1085
            $message_list[] = $message;
1086
        }
1087
1088
        return $message_list;
1089
    }
1090
1091
    /**
1092
     * Displays messages of a group with nested view.
1093
     *
1094
     * @param int $groupId
1095
     *
1096
     * @return string
1097
     */
1098
    public static function display_messages_for_group($groupId)
1099
    {
1100
        global $my_group_role;
1101
1102
        $rows = self::get_messages_by_group($groupId);
1103
        $topics_per_page = 10;
1104
        $html_messages = '';
1105
        $query_vars = ['id' => $groupId, 'topics_page_nr' => 0];
1106
1107
        if (is_array($rows) && count($rows) > 0) {
1108
            // prepare array for topics with its items
1109
            $topics = [];
1110
            $x = 0;
1111
            foreach ($rows as $index => $value) {
1112
                if (empty($value['parent_id'])) {
1113
                    $topics[$value['id']] = $value;
1114
                }
1115
            }
1116
1117
            $new_topics = [];
1118
1119
            foreach ($topics as $id => $value) {
1120
                $rows = null;
1121
                $rows = self::get_messages_by_group_by_message($groupId, $value['id']);
1122
                if (!empty($rows)) {
1123
                    $count = count(self::calculate_children($rows, $value['id']));
1124
                } else {
1125
                    $count = 0;
1126
                }
1127
                $value['count'] = $count;
1128
                $new_topics[$id] = $value;
1129
            }
1130
1131
            $array_html = [];
1132
            foreach ($new_topics as $index => $topic) {
1133
                $html = '';
1134
                // topics
1135
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1136
                $name = $user_sender_info['complete_name'];
1137
                $html .= '<div class="groups-messages">';
1138
                $html .= '<div class="row">';
1139
1140
                $items = $topic['count'];
1141
                $reply_label = (1 == $items) ? get_lang('Reply') : get_lang('Replies');
1142
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
1143
                $topic['title'] = trim($topic['title']);
1144
1145
                if (empty($topic['title'])) {
1146
                    $topic['title'] = get_lang('Untitled');
1147
                }
1148
1149
                $html .= '<div class="col-xs-8 col-md-10">';
1150
                $html .= Display::tag(
1151
                    'h4',
1152
                    Display::url(
1153
                        Security::remove_XSS($topic['title'], STUDENT, true),
1154
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$groupId.'&topic_id='.$topic['id']
1155
                    ),
1156
                    ['class' => 'title']
1157
                );
1158
                $actions = '';
1159
                if (GROUP_USER_PERMISSION_ADMIN == $my_group_role ||
1160
                    GROUP_USER_PERMISSION_MODERATOR == $my_group_role
1161
                ) {
1162
                    $actions = '<br />'.Display::url(
1163
                            get_lang('Delete'),
1164
                            api_get_path(
1165
                                WEB_CODE_PATH
1166
                            ).'social/group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic['id'],
1167
                            ['class' => 'btn btn-default']
1168
                        );
1169
                }
1170
1171
                $date = '';
1172
                if ($topic['send_date'] != $topic['update_date']) {
1173
                    if (!empty($topic['update_date'])) {
1174
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1175
                                'LastUpdate'
1176
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
1177
                    }
1178
                } else {
1179
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1180
                            'Created'
1181
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
1182
                }
1183
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
1184
                $html .= '</div>';
1185
1186
                $image = $user_sender_info['avatar'];
1187
1188
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
1189
                $user_info .= '<div class="name"><a href="'.api_get_path(
1190
                        WEB_PATH
1191
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
1192
1193
                $html .= '<div class="col-xs-4 col-md-2">';
1194
                $html .= $user_info;
1195
                $html .= '</div>';
1196
                $html .= '</div>';
1197
                $html .= '</div>';
1198
1199
                $array_html[] = [$html];
1200
            }
1201
1202
            // grids for items and topics  with paginations
1203
            $html_messages .= Display::return_sortable_grid(
1204
                'topics',
1205
                [],
1206
                $array_html,
1207
                [
1208
                    'hide_navigation' => false,
1209
                    'per_page' => $topics_per_page,
1210
                ],
1211
                $query_vars,
1212
                false,
1213
                [true, true, true, false],
1214
                false
1215
            );
1216
        }
1217
1218
        return $html_messages;
1219
    }
1220
1221
    /**
1222
     * Displays messages of a group with nested view.
1223
     *
1224
     * @param $groupId
1225
     * @param $topic_id
1226
     *
1227
     * @return string
1228
     */
1229
    public static function display_message_for_group($groupId, $topic_id)
1230
    {
1231
        global $my_group_role;
1232
        $main_message = self::get_message_by_id($topic_id);
1233
        if (empty($main_message)) {
1234
            return false;
1235
        }
1236
1237
        $webCodePath = api_get_path(WEB_CODE_PATH);
1238
        $iconCalendar = Display::returnFontAwesomeIcon('calendar');
1239
1240
        $langEdit = get_lang('Edit');
1241
        $langReply = get_lang('Reply');
1242
        $langLastUpdated = get_lang('LastUpdated');
1243
        $langCreated = get_lang('Created');
1244
1245
        $rows = self::get_messages_by_group_by_message($groupId, $topic_id);
1246
        $rows = self::calculate_children($rows, $topic_id);
1247
        $current_user_id = api_get_user_id();
1248
1249
        $items_per_page = 50;
1250
        $query_vars = ['id' => $groupId, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
1251
1252
        // Main message
1253
        $links = '';
1254
        $main_content = '';
1255
        $html = '';
1256
        $items_page_nr = null;
1257
1258
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1259
        $filesAttachments = self::getAttachmentLinkList($main_message['id'], 0);
1260
        $name = $user_sender_info['complete_name'];
1261
1262
        $topic_page_nr = isset($_GET['topics_page_nr']) ? (int) $_GET['topics_page_nr'] : null;
1263
1264
        $links .= '<div class="pull-right">';
1265
        $links .= '<div class="btn-group btn-group-sm">';
1266
1267
        if ((GROUP_USER_PERMISSION_ADMIN == $my_group_role || GROUP_USER_PERMISSION_MODERATOR == $my_group_role) ||
1268
            $main_message['user_sender_id'] == $current_user_id
1269
        ) {
1270
            $urlEdit = $webCodePath.'social/message_for_group_form.inc.php?'
1271
                .http_build_query(
1272
                    [
1273
                        'user_friend' => $current_user_id,
1274
                        'group_id' => $groupId,
1275
                        'message_id' => $main_message['id'],
1276
                        'action' => 'edit_message_group',
1277
                        'anchor_topic' => 'topic_'.$main_message['id'],
1278
                        'topics_page_nr' => $topic_page_nr,
1279
                        'items_page_nr' => $items_page_nr,
1280
                        'topic_id' => $main_message['id'],
1281
                    ]
1282
                );
1283
1284
            $links .= Display::toolbarButton(
1285
                $langEdit,
1286
                $urlEdit,
1287
                'pencil',
1288
                'default',
1289
                ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1290
                false
1291
            );
1292
        }
1293
1294
        $links .= self::getLikesButton($main_message['id'], $current_user_id, $groupId);
1295
1296
        $urlReply = $webCodePath.'social/message_for_group_form.inc.php?'
1297
            .http_build_query(
1298
                [
1299
                    'user_friend' => $current_user_id,
1300
                    'group_id' => $groupId,
1301
                    'message_id' => $main_message['id'],
1302
                    'action' => 'reply_message_group',
1303
                    'anchor_topic' => 'topic_'.$main_message['id'],
1304
                    'topics_page_nr' => $topic_page_nr,
1305
                    'topic_id' => $main_message['id'],
1306
                ]
1307
            );
1308
1309
        $links .= Display::toolbarButton(
1310
            $langReply,
1311
            $urlReply,
1312
            'commenting',
1313
            'default',
1314
            ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1315
            false
1316
        );
1317
1318
        if (api_is_platform_admin()) {
1319
            $links .= Display::toolbarButton(
1320
                get_lang('Delete'),
1321
                'group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic_id,
1322
                'trash',
1323
                'default',
1324
                [],
1325
                false
1326
            );
1327
        }
1328
1329
        $links .= '</div>';
1330
        $links .= '</div>';
1331
1332
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
1333
1334
        $userPicture = $user_sender_info['avatar'];
1335
        $main_content .= '<div class="row">';
1336
        $main_content .= '<div class="col-md-2">';
1337
        $main_content .= '<div class="avatar-author">';
1338
        $main_content .= Display::img(
1339
            $userPicture,
1340
            $name,
1341
            ['width' => '60px', 'class' => 'img-responsive img-circle'],
1342
            false
1343
        );
1344
        $main_content .= '</div>';
1345
        $main_content .= '</div>';
1346
1347
        $date = '';
1348
        if ($main_message['send_date'] != $main_message['update_date']) {
1349
            if (!empty($main_message['update_date'])) {
1350
                $date = '<div class="date"> '
1351
                    ."$iconCalendar $langLastUpdated "
1352
                    .Display::dateToStringAgoAndLongDate($main_message['update_date'])
1353
                    .'</div>';
1354
            }
1355
        } else {
1356
            $date = '<div class="date"> '
1357
                ."$iconCalendar $langCreated "
1358
                .Display::dateToStringAgoAndLongDate($main_message['send_date'])
1359
                .'</div>';
1360
        }
1361
        $attachment = '<div class="message-attach">'
1362
            .(!empty($filesAttachments) ? implode('<br />', $filesAttachments) : '')
1363
            .'</div>';
1364
        $main_content .= '<div class="col-md-10">';
1365
        $user_link = Display::url(
1366
            $name,
1367
            $webCodePath.'social/profile.php?u='.$main_message['user_sender_id']
1368
        );
1369
        $main_content .= '<div class="message-content"> ';
1370
        $main_content .= '<div class="username">'.$user_link.'</div>';
1371
        $main_content .= $date;
1372
        $main_content .= '<div class="message">'.$main_message['content'].$attachment.'</div></div>';
1373
        $main_content .= '</div>';
1374
        $main_content .= '</div>';
1375
1376
        $html .= Display::div(
1377
            Display::div(
1378
                $title.$main_content,
1379
                ['class' => 'message-topic']
1380
            ),
1381
            ['class' => 'sm-groups-message']
1382
        );
1383
1384
        $topic_id = $main_message['id'];
1385
1386
        if (is_array($rows) && count($rows) > 0) {
1387
            $topics = $rows;
1388
            $array_html_items = [];
1389
1390
            foreach ($topics as $index => $topic) {
1391
                if (empty($topic['id'])) {
1392
                    continue;
1393
                }
1394
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr'])
1395
                    ? (int) $_GET['items_'.$topic['id'].'_page_nr']
1396
                    : null;
1397
                $links = '';
1398
                $links .= '<div class="pull-right">';
1399
                $html_items = '';
1400
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1401
                $filesAttachments = self::getAttachmentLinkList($topic['id'], 0);
1402
                $name = $user_sender_info['complete_name'];
1403
1404
                $links .= '<div class="btn-group btn-group-sm">';
1405
                if (
1406
                    (GROUP_USER_PERMISSION_ADMIN == $my_group_role ||
1407
                        GROUP_USER_PERMISSION_MODERATOR == $my_group_role
1408
                    ) ||
1409
                    $topic['user_sender_id'] == $current_user_id
1410
                ) {
1411
                    $links .= Display::toolbarButton(
1412
                        $langEdit,
1413
                        $webCodePath.'social/message_for_group_form.inc.php?'
1414
                            .http_build_query(
1415
                                [
1416
                                    'user_friend' => $current_user_id,
1417
                                    'group_id' => $groupId,
1418
                                    'message_id' => $topic['id'],
1419
                                    'action' => 'edit_message_group',
1420
                                    'anchor_topic' => 'topic_'.$topic_id,
1421
                                    'topics_page_nr' => $topic_page_nr,
1422
                                    'items_page_nr' => $items_page_nr,
1423
                                    'topic_id' => $topic_id,
1424
                                ]
1425
                            ),
1426
                        'pencil',
1427
                        'default',
1428
                        ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1429
                        false
1430
                    );
1431
                }
1432
1433
                $links .= self::getLikesButton($topic['id'], $current_user_id, $groupId);
1434
1435
                $links .= Display::toolbarButton(
1436
                    $langReply,
1437
                    $webCodePath.'social/message_for_group_form.inc.php?'
1438
                        .http_build_query(
1439
                            [
1440
                                'user_friend' => $current_user_id,
1441
                                'group_id' => $groupId,
1442
                                'message_id' => $topic['id'],
1443
                                'action' => 'reply_message_group',
1444
                                'anchor_topic' => 'topic_'.$topic_id,
1445
                                'topics_page_nr' => $topic_page_nr,
1446
                                'items_page_nr' => $items_page_nr,
1447
                                'topic_id' => $topic_id,
1448
                            ]
1449
                        ),
1450
                    'commenting',
1451
                    'default',
1452
                    ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1453
                    false
1454
                );
1455
                $links .= '</div>';
1456
                $links .= '</div>';
1457
1458
                $userPicture = $user_sender_info['avatar'];
1459
                $user_link = Display::url(
1460
                    $name,
1461
                    $webCodePath.'social/profile.php?u='.$topic['user_sender_id']
1462
                );
1463
                $html_items .= '<div class="row">';
1464
                $html_items .= '<div class="col-md-2">';
1465
                $html_items .= '<div class="avatar-author">';
1466
                $html_items .= Display::img(
1467
                    $userPicture,
1468
                    $name,
1469
                    ['width' => '60px', 'class' => 'img-responsive img-circle'],
1470
                    false
1471
                );
1472
                $html_items .= '</div>';
1473
                $html_items .= '</div>';
1474
1475
                $date = '';
1476
                if ($topic['send_date'] != $topic['update_date']) {
1477
                    if (!empty($topic['update_date'])) {
1478
                        $date = '<div class="date"> '
1479
                            ."$iconCalendar $langLastUpdated "
1480
                            .Display::dateToStringAgoAndLongDate($topic['update_date'])
1481
                            .'</div>';
1482
                    }
1483
                } else {
1484
                    $date = '<div class="date"> '
1485
                        ."$iconCalendar $langCreated "
1486
                        .Display::dateToStringAgoAndLongDate($topic['send_date'])
1487
                        .'</div>';
1488
                }
1489
                $attachment = '<div class="message-attach">'
1490
                    .(!empty($filesAttachments) ? implode('<br />', $filesAttachments) : '')
1491
                    .'</div>';
1492
                $html_items .= '<div class="col-md-10">'
1493
                    .'<div class="message-content">'
1494
                    .$links
1495
                    .'<div class="username">'.$user_link.'</div>'
1496
                    .$date
1497
                    .'<div class="message">'
1498
                    .Security::remove_XSS($topic['content'], STUDENT, true)
1499
                    .'</div>'.$attachment.'</div>'
1500
                    .'</div>'
1501
                    .'</div>';
1502
1503
                $base_padding = 20;
1504
1505
                if (0 == $topic['indent_cnt']) {
1506
                    $indent = $base_padding;
1507
                } else {
1508
                    $indent = (int) $topic['indent_cnt'] * $base_padding + $base_padding;
1509
                }
1510
1511
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
1512
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
1513
                $array_html_items[] = [$html_items];
1514
            }
1515
1516
            // grids for items with paginations
1517
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
1518
            $visibility = [true, true, true, false];
1519
1520
            $style_class = [
1521
                'item' => ['class' => 'user-post'],
1522
                'main' => ['class' => 'user-list'],
1523
            ];
1524
            if (!empty($array_html_items)) {
1525
                $html .= Display::return_sortable_grid(
1526
                    'items_'.$topic['id'],
1527
                    [],
1528
                    $array_html_items,
1529
                    $options,
1530
                    $query_vars,
1531
                    null,
1532
                    $visibility,
1533
                    false,
1534
                    $style_class
1535
                );
1536
            }
1537
        }
1538
1539
        return $html;
1540
    }
1541
1542
    /**
1543
     * Add children to messages by id is used for nested view messages.
1544
     *
1545
     * @param array $rows rows of messages
1546
     *
1547
     * @return array $first_seed new list adding the item children
1548
     */
1549
    public static function calculate_children($rows, $first_seed)
1550
    {
1551
        $rows_with_children = [];
1552
        foreach ($rows as $row) {
1553
            $rows_with_children[$row["id"]] = $row;
1554
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
1555
        }
1556
        $rows = $rows_with_children;
1557
        $sorted_rows = [0 => []];
1558
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
1559
        unset($sorted_rows[0]);
1560
1561
        return $sorted_rows;
1562
    }
1563
1564
    /**
1565
     * Sort recursively the messages, is used for for nested view messages.
1566
     *
1567
     * @param array  original rows of messages
1568
     * @param array  list recursive of messages
1569
     * @param int   seed for calculate the indent
1570
     * @param int   indent for nested view
1571
     */
1572
    public static function message_recursive_sort(
1573
        $rows,
1574
        &$messages,
1575
        $seed = 0,
1576
        $indent = 0
1577
    ) {
1578
        if ($seed > 0 && isset($rows[$seed]["id"])) {
1579
            $messages[$rows[$seed]["id"]] = $rows[$seed];
1580
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
1581
            $indent++;
1582
        }
1583
1584
        if (isset($rows[$seed]["children"])) {
1585
            foreach ($rows[$seed]["children"] as $child) {
1586
                self::message_recursive_sort($rows, $messages, $child, $indent);
1587
            }
1588
        }
1589
    }
1590
1591
    /**
1592
     * Get array of links (download) for message attachment files.
1593
     *
1594
     * @return array
1595
     */
1596
    public static function getAttachmentLinkList(Message $message)
1597
    {
1598
        $files = $message->getAttachments();
1599
        // get file attachments by message id
1600
        $list = [];
1601
        if ($files) {
0 ignored issues
show
introduced by
$files is of type Doctrine\Common\Collections\Collection, thus it always evaluated to true.
Loading history...
1602
            $attachIcon = Display::returnFontAwesomeIcon('paperclip');
1603
            $repo = Container::getMessageAttachmentRepository();
1604
            foreach ($files as $file) {
1605
                $size = format_file_size($file->getSize());
1606
                $comment = Security::remove_XSS($file->getComment());
1607
                $filename = Security::remove_XSS($file->getFilename());
1608
                $url = $repo->getResourceFileUrl($file);
1609
                $link = Display::url($filename, $url);
1610
                $comment = !empty($comment) ? '&nbsp;-&nbsp;<i>'.$comment.'</i>' : '';
1611
1612
                $attachmentLine = $attachIcon.'&nbsp;'.$link.'&nbsp;('.$size.')'.$comment;
1613
                /*if ('audio_message' === $file['comment']) {
1614
                    $attachmentLine = '<audio src="'.$archiveURL.$archiveFile.'"/>';
1615
                }*/
1616
                $list[] = $attachmentLine;
1617
            }
1618
        }
1619
1620
        return $list;
1621
    }
1622
1623
    /**
1624
     * Get message list by id.
1625
     *
1626
     * @param int $messageId
1627
     *
1628
     * @return array
1629
     */
1630
    public static function get_message_by_id($messageId)
1631
    {
1632
        $table = Database::get_main_table(TABLE_MESSAGE);
1633
        $messageId = (int) $messageId;
1634
        $sql = "SELECT * FROM $table
1635
                WHERE
1636
                    id = '$messageId' AND
1637
                    msg_status <> '".MESSAGE_STATUS_DELETED."' ";
1638
        $res = Database::query($sql);
1639
        $item = [];
1640
        if (Database::num_rows($res) > 0) {
1641
            $item = Database::fetch_array($res, 'ASSOC');
1642
        }
1643
1644
        return $item;
1645
    }
1646
1647
    /**
1648
     * @return string
1649
     */
1650
    public static function generate_message_form()
1651
    {
1652
        $form = new FormValidator('send_message');
1653
        $form->addText(
1654
            'subject',
1655
            get_lang('Subject'),
1656
            false,
1657
            ['id' => 'subject_id']
1658
        );
1659
        $form->addTextarea(
1660
            'content',
1661
            get_lang('Message'),
1662
            ['id' => 'content_id', 'rows' => '5']
1663
        );
1664
1665
        return $form->returnForm();
1666
    }
1667
1668
    /**
1669
     * @return string
1670
     */
1671
    public static function generate_invitation_form()
1672
    {
1673
        $form = new FormValidator('send_invitation');
1674
        $form->addTextarea(
1675
            'content',
1676
            get_lang('Add a personal message'),
1677
            ['id' => 'content_invitation_id', 'rows' => 5]
1678
        );
1679
1680
        return $form->returnForm();
1681
    }
1682
1683
    /**
1684
     * @param string $type
1685
     * @param string $keyword
1686
     * @param array  $actions
1687
     *
1688
     * @return string
1689
     */
1690
    public static function getMessageGrid($type, $keyword, $actions = [])
1691
    {
1692
        $html = '';
1693
        // display sortable table with messages of the current user
1694
        $table = new SortableTable(
1695
            'message_inbox',
1696
            ['MessageManager', 'getNumberOfMessages'],
1697
            ['MessageManager', 'getMessageData'],
1698
            2,
1699
            20,
1700
            'DESC'
1701
        );
1702
        $table->setDataFunctionParams(
1703
            ['keyword' => $keyword, 'type' => $type, 'actions' => $actions]
1704
        );
1705
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
1706
        $table->set_header(1, get_lang('Messages'), false);
1707
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
1708
        $table->set_header(3, get_lang('Edit'), false, ['style' => 'width:120px;']);
1709
1710
        if (isset($_REQUEST['f']) && 'social' === $_REQUEST['f']) {
1711
            $parameters['f'] = 'social';
1712
            $table->set_additional_parameters($parameters);
1713
        }
1714
1715
        $defaultActions = [
1716
            'delete' => get_lang('Delete selected messages'),
1717
            'mark_as_unread' => get_lang('Mark as unread'),
1718
            'mark_as_read' => get_lang('Mark as read'),
1719
        ];
1720
1721
        if (!in_array('delete', $actions)) {
1722
            unset($defaultActions['delete']);
1723
        }
1724
        if (!in_array('mark_as_unread', $actions)) {
1725
            unset($defaultActions['mark_as_unread']);
1726
        }
1727
        if (!in_array('mark_as_read', $actions)) {
1728
            unset($defaultActions['mark_as_read']);
1729
        }
1730
1731
        $table->set_form_actions($defaultActions);
1732
1733
        $html .= $table->return_table();
1734
1735
        return $html;
1736
    }
1737
1738
    /**
1739
     * Check whether a message has attachments.
1740
     *
1741
     * @param int $messageId The message id
1742
     *
1743
     * @return bool Whether the message has attachments return true. Otherwise return false
1744
     */
1745
    public static function hasAttachments($messageId)
1746
    {
1747
        $messageId = (int) $messageId;
1748
1749
        if (empty($messageId)) {
1750
            return false;
1751
        }
1752
1753
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1754
1755
        $conditions = [
1756
            'where' => [
1757
                'message_id = ?' => $messageId,
1758
            ],
1759
        ];
1760
1761
        $result = Database::select(
1762
            'COUNT(1) AS qty',
1763
            $messageAttachmentTable,
1764
            $conditions,
1765
            'first'
1766
        );
1767
1768
        if (!empty($result)) {
1769
            if ($result['qty'] > 0) {
1770
                return true;
1771
            }
1772
        }
1773
1774
        return false;
1775
    }
1776
1777
    /**
1778
     * @param int $messageId
1779
     *
1780
     * @return array|bool
1781
     */
1782
    public static function getAttachment($messageId)
1783
    {
1784
        $messageId = (int) $messageId;
1785
1786
        if (empty($messageId)) {
1787
            return false;
1788
        }
1789
1790
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1791
1792
        $conditions = [
1793
            'where' => [
1794
                'id = ?' => $messageId,
1795
            ],
1796
        ];
1797
1798
        $result = Database::select(
1799
            '*',
1800
            $table,
1801
            $conditions,
1802
            'first'
1803
        );
1804
1805
        if (!empty($result)) {
1806
            return $result;
1807
        }
1808
1809
        return false;
1810
    }
1811
1812
    /**
1813
     * @param string $url
1814
     *
1815
     * @return FormValidator
1816
     */
1817
    public static function getSearchForm($url)
1818
    {
1819
        $form = new FormValidator(
1820
            'search',
1821
            'post',
1822
            $url,
1823
            null,
1824
            [],
1825
            FormValidator::LAYOUT_INLINE
1826
        );
1827
1828
        $form->addElement(
1829
            'text',
1830
            'keyword',
1831
            false,
1832
            [
1833
                'aria-label' => get_lang('Search'),
1834
            ]
1835
        );
1836
        $form->addButtonSearch(get_lang('Search'));
1837
1838
        return $form;
1839
    }
1840
1841
    /**
1842
     * Send a notification to all admins when a new user is registered.
1843
     */
1844
    public static function sendNotificationOfNewRegisteredUser(User $user)
1845
    {
1846
        $tplMailBody = new Template(
1847
            null,
1848
            false,
1849
            false,
1850
            false,
1851
            false,
1852
            false,
1853
            false
1854
        );
1855
        $tplMailBody->assign('user', $user);
1856
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
1857
        $tplMailBody->assign(
1858
            'manageUrl',
1859
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
1860
        );
1861
1862
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
1863
1864
        $emailsubject = '['.get_lang('The user has been registered').'] '.$user->getUsername();
1865
        $emailbody = $tplMailBody->fetch($layoutContent);
1866
1867
        $admins = UserManager::get_all_administrators();
1868
1869
        foreach ($admins as $admin_info) {
1870
            self::send_message(
1871
                $admin_info['user_id'],
1872
                $emailsubject,
1873
                $emailbody,
1874
                [],
1875
                [],
1876
                null,
1877
                null,
1878
                null,
1879
                null,
1880
                $user->getId()
1881
            );
1882
        }
1883
    }
1884
1885
    /**
1886
     * Send a notification to all admins when a new user is registered
1887
     * while the approval method is used for users registration.
1888
     */
1889
    public static function sendNotificationOfNewRegisteredUserApproval(User $user)
1890
    {
1891
        $tplMailBody = new Template(
1892
            null,
1893
            false,
1894
            false,
1895
            false,
1896
            false,
1897
            false,
1898
            false
1899
        );
1900
        $tplMailBody->assign('user', $user);
1901
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
1902
        $userId = $user->getId();
1903
        $url_edit = Display::url(
1904
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId,
1905
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId
1906
        );
1907
        $tplMailBody->assign(
1908
            'manageUrl',
1909
            $url_edit
1910
        );
1911
        // Get extra field values for this user and reformat the array
1912
        $extraFieldValues = new ExtraFieldValue('user');
1913
        $userExtraFields = $extraFieldValues->getAllValuesByItem($userId);
1914
        $values = [];
1915
        foreach ($userExtraFields as $field => $value) {
1916
            $values[$value['variable']] = $value['value'];
1917
        }
1918
        $tplMailBody->assign(
1919
            'extra',
1920
            $values
1921
        );
1922
        $layoutContent = '';
1923
        $emailbody = '';
1924
        if (true == api_get_configuration_value('mail_template_system')) {
1925
            $mailTemplateManager = new MailTemplateManager();
1926
            $templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl');
1927
            if (empty($templateText)) {
1928
            } else {
1929
                // custom procedure to load a template as a string (doesn't use cache so may slow down)
1930
                $template = $tplMailBody->twig->createTemplate($templateText);
1931
                $emailbody = $template->render($tplMailBody->params);
1932
            }
1933
        }
1934
        if (empty($emailbody)) {
1935
            $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl');
1936
            $emailbody = $tplMailBody->fetch($layoutContent);
1937
        }
1938
1939
        $emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername();
1940
1941
        if (api_get_configuration_value('send_inscription_notification_to_general_admin_only')) {
1942
            $email = api_get_setting('emailAdministrator');
1943
            $firstname = api_get_setting('administratorSurname');
1944
            $lastname = api_get_setting('administratorName');
1945
            api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody);
1946
        } else {
1947
            $admins = UserManager::get_all_administrators();
1948
            foreach ($admins as $admin_info) {
1949
                self::send_message(
1950
                    $admin_info['user_id'],
1951
                    $emailsubject,
1952
                    $emailbody,
1953
                    [],
1954
                    [],
1955
                    null,
1956
                    null,
1957
                    null,
1958
                    null,
1959
                    $userId
1960
                );
1961
            }
1962
        }
1963
    }
1964
1965
    /**
1966
     * Get the error log from failed mailing
1967
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
1968
     * into app/cache/mail/mailq.
1969
     * This can be done with a cron command like (check the location of your mail log file first):.
1970
     *
1971
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
1972
     *
1973
     * @return array|bool
1974
     */
1975
    public static function failedSentMailErrors()
1976
    {
1977
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
1978
        $mailq = $base.'mailq';
1979
1980
        if (!file_exists($mailq) || !is_readable($mailq)) {
1981
            return false;
1982
        }
1983
1984
        $file = fopen($mailq, 'r');
1985
        $i = 1;
1986
        while (!feof($file)) {
1987
            $line = fgets($file);
1988
1989
            if ('' == trim($line)) {
1990
                continue;
1991
            }
1992
1993
            // Get the mail code, something like 1WBumL-0002xg-FF
1994
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
1995
                $mail_queue[$i]['code'] = $codeMatches[2];
1996
            }
1997
1998
            $fullMail = $base.$mail_queue[$i]['code'];
1999
            $mailFile = fopen($fullMail, 'r');
2000
2001
            // Get the reason of mail fail
2002
            $iX = 1;
2003
            while (!feof($mailFile)) {
2004
                $mailLine = fgets($mailFile);
2005
                //if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2006
                if (2 == $iX &&
2007
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2008
                ) {
2009
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2010
                }
2011
                $iX++;
2012
            }
2013
2014
            fclose($mailFile);
2015
2016
            // Get the time of mail fail
2017
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
2018
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
2019
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
2020
                $mail_queue[$i]['mail'] = $emailMatches[2];
2021
                $i++;
2022
            }
2023
        }
2024
2025
        fclose($file);
2026
2027
        return array_reverse($mail_queue);
2028
    }
2029
2030
    /**
2031
     * @param int $userId
2032
     *
2033
     * @return array
2034
     */
2035
    public static function getUsersThatHadConversationWithUser($userId)
2036
    {
2037
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2038
        $userId = (int) $userId;
2039
2040
        $sql = "SELECT DISTINCT
2041
                    user_sender_id
2042
                FROM $messagesTable
2043
                WHERE
2044
                    user_receiver_id = ".$userId;
2045
        $result = Database::query($sql);
2046
        $users = Database::store_result($result);
2047
        $userList = [];
2048
        foreach ($users as $userData) {
2049
            $userId = $userData['user_sender_id'];
2050
            if (empty($userId)) {
2051
                continue;
2052
            }
2053
            $userInfo = api_get_user_info($userId);
2054
            if ($userInfo) {
2055
                $userList[$userId] = $userInfo;
2056
            }
2057
        }
2058
2059
        return $userList;
2060
    }
2061
2062
    /**
2063
     * @param int $userId
2064
     * @param int $otherUserId
2065
     *
2066
     * @return array
2067
     */
2068
    public static function getAllMessagesBetweenStudents($userId, $otherUserId)
2069
    {
2070
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2071
        $userId = (int) $userId;
2072
        $otherUserId = (int) $otherUserId;
2073
2074
        if (empty($otherUserId) || empty($userId)) {
2075
            return [];
2076
        }
2077
2078
        $sql = "SELECT DISTINCT *
2079
                FROM $messagesTable
2080
                WHERE
2081
                    (user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
2082
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId)
2083
                ORDER BY send_date DESC
2084
            ";
2085
        $result = Database::query($sql);
2086
        $messages = Database::store_result($result);
2087
        $list = [];
2088
        foreach ($messages as $message) {
2089
            $list[] = $message;
2090
        }
2091
2092
        return $list;
2093
    }
2094
2095
    /**
2096
     * @param string $subject
2097
     * @param string $message
2098
     * @param Course $course
2099
     * @param int    $sessionId
2100
     *
2101
     * @return bool
2102
     */
2103
    public static function sendMessageToAllUsersInCourse($subject, $message, Course $course, $sessionId = 0)
2104
    {
2105
        $senderId = api_get_user_id();
2106
        if (empty($senderId)) {
2107
            return false;
2108
        }
2109
        if (empty($sessionId)) {
2110
            // Course students and teachers
2111
            $users = CourseManager::get_user_list_from_course_code($course->getCode());
2112
        } else {
2113
            // Course-session students and course session coaches
2114
            $users = CourseManager::get_user_list_from_course_code($course->getCode(), $sessionId);
2115
        }
2116
2117
        if (empty($users)) {
2118
            return false;
2119
        }
2120
2121
        foreach ($users as $userInfo) {
2122
            self::send_message_simple(
2123
                $userInfo['user_id'],
2124
                $subject,
2125
                $message,
2126
                $senderId,
2127
                false,
2128
                false,
2129
                [],
2130
                false
2131
            );
2132
        }
2133
    }
2134
2135
    /**
2136
     * Clean audio messages already added in the message tool.
2137
     */
2138
    public static function cleanAudioMessage()
2139
    {
2140
        Session::erase('current_audio');
2141
    }
2142
2143
    /**
2144
     * @param int    $senderId
2145
     * @param string $subject
2146
     * @param string $message
2147
     */
2148
    public static function sendMessageToAllAdminUsers(
2149
        $senderId,
2150
        $subject,
2151
        $message
2152
    ) {
2153
        $admins = UserManager::get_all_administrators();
2154
        foreach ($admins as $admin) {
2155
            self::send_message_simple($admin['user_id'], $subject, $message, $senderId);
2156
        }
2157
    }
2158
2159
    /**
2160
     * @param int $messageId
2161
     * @param int $userId
2162
     *
2163
     * @return array
2164
     */
2165
    public static function countLikesAndDislikes($messageId, $userId)
2166
    {
2167
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
2168
            return [];
2169
        }
2170
2171
        $messageId = (int) $messageId;
2172
        $userId = (int) $userId;
2173
2174
        $em = Database::getManager();
2175
        $query = $em
2176
            ->createQuery('
2177
                SELECT SUM(l.liked) AS likes, SUM(l.disliked) AS dislikes FROM ChamiloCoreBundle:MessageFeedback l
2178
                WHERE l.message = :message
2179
            ')
2180
            ->setParameters(['message' => $messageId]);
2181
2182
        try {
2183
            $counts = $query->getSingleResult();
2184
        } catch (Exception $e) {
2185
            $counts = ['likes' => 0, 'dislikes' => 0];
2186
        }
2187
2188
        $userLike = $em
2189
            ->getRepository(MessageFeedback::class)
2190
            ->findOneBy(['message' => $messageId, 'user' => $userId]);
2191
2192
        return [
2193
            'likes' => (int) $counts['likes'],
2194
            'dislikes' => (int) $counts['dislikes'],
2195
            'user_liked' => $userLike ? $userLike->isLiked() : false,
2196
            'user_disliked' => $userLike ? $userLike->isDisliked() : false,
2197
        ];
2198
    }
2199
2200
    /**
2201
     * @param int $messageId
2202
     * @param int $userId
2203
     * @param int $groupId   Optional.
2204
     *
2205
     * @return string
2206
     */
2207
    public static function getLikesButton($messageId, $userId, $groupId = 0)
2208
    {
2209
        if (!api_get_configuration_value('social_enable_messages_feedback')) {
2210
            return '';
2211
        }
2212
2213
        $countLikes = self::countLikesAndDislikes($messageId, $userId);
2214
2215
        $class = $countLikes['user_liked'] ? 'btn-primary' : 'btn-default';
2216
2217
        $btnLike = Display::button(
2218
            'like',
2219
            Display::returnFontAwesomeIcon('thumbs-up', '', true)
2220
                .PHP_EOL.'<span>'.$countLikes['likes'].'</span>',
2221
            [
2222
                'title' => get_lang('Like'),
2223
                'class' => 'btn  social-like '.$class,
2224
                'data-status' => 'like',
2225
                'data-message' => $messageId,
2226
                'data-group' => $groupId,
2227
            ]
2228
        );
2229
2230
        $btnDislike = '';
2231
        if (false === api_get_configuration_value('disable_dislike_option')) {
2232
            $disabled = $countLikes['user_disliked'] ? 'btn-danger' : 'btn-default';
2233
2234
            $btnDislike = Display::button(
2235
                'like',
2236
                Display::returnFontAwesomeIcon('thumbs-down', '', true)
2237
                .PHP_EOL.'<span>'.$countLikes['dislikes'].'</span>',
2238
                [
2239
                    'title' => get_lang('Dislike'),
2240
                    'class' => 'btn social-like '.$disabled,
2241
                    'data-status' => 'dislike',
2242
                    'data-message' => $messageId,
2243
                    'data-group' => $groupId,
2244
                ]
2245
            );
2246
        }
2247
2248
        return $btnLike.PHP_EOL.$btnDislike;
2249
    }
2250
}
2251