Passed
Push — master ( 0e8800...0cdc5b )
by Julito
11:59
created

MessageManager   F

Complexity

Total Complexity 345

Size/Duplication

Total Lines 3035
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1629
dl 0
loc 3035
rs 0.8
c 0
b 0
f 0
wmc 345

51 Methods

Rating   Name   Duplication   Size   Complexity  
A getMessagesAboutUser() 0 21 3
A sendNotificationOfNewRegisteredUser() 0 37 2
A getSearchForm() 0 22 1
B failedSentMailErrors() 0 53 11
A hasAttachments() 0 30 4
A getAttachment() 0 28 3
A getAllMessagesBetweenStudents() 0 25 4
B sendNotificationOfNewRegisteredUserApproval() 0 71 7
A getUsersThatHadConversationWithUser() 0 25 4
B getMessagesByParent() 0 38 7
A generate_message_form() 0 16 1
B getMessageGrid() 0 46 6
A calculate_children() 0 13 2
A getMessagesAboutUserToString() 0 37 3
A generate_invitation_form() 0 10 1
A cleanAudioMessage() 0 3 1
A getSentMessages() 0 22 3
A outBoxDisplay() 0 36 5
B sendMessageAboutUser() 0 34 6
F send_message() 0 313 54
F getMessageData() 0 155 22
A get_message_by_id() 0 15 2
C display_messages_for_group() 0 121 14
A delete_message_by_user_sender() 0 29 4
B send_message_simple() 0 58 7
A get_messages_by_group() 0 23 4
C get_message_data_sent() 0 92 10
A countLikesAndDislikes() 0 32 5
A sendMessageToAllUsersInCourse() 0 28 5
B saveMessageAttachmentFile() 0 71 10
A getAttachmentLinkList() 0 25 4
A get_messages_by_group_by_message() 0 28 6
F showMessageBox() 0 180 25
A sendMessageToAllAdminUsers() 0 8 2
C getWhereConditions() 0 40 11
A getReceivedMessages() 0 18 2
A messageWasAlreadySent() 0 19 1
A update_message_status() 0 19 3
A getNumberOfMessages() 0 18 2
A getPromotedMessagesGrid() 0 35 5
F display_message_for_group() 0 311 23
A getLikesButton() 0 42 5
C inboxDisplay() 0 70 12
A getMessagesFromLastReceivedMessage() 0 18 2
A get_user_id_by_email() 0 13 2
A getCountNewMessages() 0 24 5
B delete_message_by_user_receiver() 0 41 8
A softDeleteAttachments() 0 7 3
A getCountNewMessagesFromDB() 0 18 2
B outbox_display() 0 51 6
A message_recursive_sort() 0 15 5

How to fix   Complexity   

Complex Class

Complex classes like MessageManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MessageManager, and based on these observations, apply Extract Interface, too.

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