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