Passed
Push — 1.11.x ( 0d8106...9cc1fc )
by Julito
13:44 queued 14s
created

sendNotificationOfNewRegisteredUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 37
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

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