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