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

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 34
nc 24
nop 9
dl 0
loc 58
rs 8.4426
c 0
b 0
f 0

How to fix   Long Method    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
    /**
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