Passed
Push — master ( e157d2...b7d807 )
by Julito
12:22
created

MessageManager::send_message()   F

Complexity

Conditions 52
Paths > 20000

Size

Total Lines 281
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 52
eloc 170
nc 78160
nop 16
dl 0
loc 281
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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