Passed
Push — 1.11.x ( 4fb383...20ec8e )
by Yannick
10:46 queued 01:32
created

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 71
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 41
c 0
b 0
f 0
dl 0
loc 71
rs 8.3306
cc 7
nc 24
nop 11

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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