Passed
Push — master ( 760dff...ab8d81 )
by Julito
07:06
created

MessageManager::send_message()   F

Complexity

Conditions 52
Paths > 20000

Size

Total Lines 281
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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