Passed
Pull Request — master (#6079)
by
unknown
07:52
created

MessageManager::send_message()   F

Complexity

Conditions 53
Paths > 20000

Size

Total Lines 305
Code Lines 185

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 53
eloc 185
c 1
b 0
f 0
nc 102440
nop 16
dl 0
loc 305
rs 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\MessageRelUser;
9
use Chamilo\CoreBundle\Entity\SocialPost;
10
use Chamilo\CoreBundle\Entity\SocialPostFeedback;
11
use Chamilo\CoreBundle\Entity\User;
12
use Chamilo\CoreBundle\Framework\Container;
13
use ChamiloSession as Session;
14
use Doctrine\Common\Collections\Criteria;
15
use Symfony\Component\HttpFoundation\File\UploadedFile;
16
17
class MessageManager
18
{
19
    public static function getMessagesAboutUserToString(User $user, string $url = ''): string
20
    {
21
        $currentUserId = api_get_user_id();
22
        $messages = Container::getMessageRepository()->getMessageByUser($user, Message::MESSAGE_TYPE_CONVERSATION);
23
        $html = '';
24
        if (!empty($messages)) {
25
            foreach ($messages as $message) {
26
                $messageId = $message->getId();
27
                $tag = 'message_'.$messageId;
28
                $tagAccordion = 'accordion_'.$messageId;
29
                $tagCollapse = 'collapse_'.$messageId;
30
31
                $date = Display::dateToStringAgoAndLongDate($message->getSendDate());
32
                $localTime = api_get_local_time(
33
                    $message->getSendDate(),
34
                    null,
35
                    null,
36
                    false,
37
                    false
38
                );
39
                $sender = $message->getSender();
40
41
                $deleteLink = '';
42
                if (!empty($url) && $sender && $currentUserId === $sender->getId()) {
43
                    $deleteLink = '<button title="'.addslashes(get_lang('DeleteMessage')).'"
44
                       onclick="event.stopPropagation(); if(confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage'))).'\')) {
45
                       window.location.href=\''.$url.'&action=delete_message&message_id='.$messageId.'\';
46
                       } return false;"
47
                       class="ml-2 inline-flex items-center">'.
48
                        Display::returnPrimeIcon('trash', 'lg').'</button>';
49
                }
50
51
                $content = '<div class="custom-message">' . $message->getContent().'<br />'.$date.'<br />'.
52
                    get_lang('Author').': '.$sender->getUsername().
53
                    '<br /></div>';
54
55
                $html .= Display::panelCollapse(
56
                    $localTime.' '.UserManager::formatUserFullName($sender).' '.$message->getTitle().$deleteLink,
57
                    $content,
58
                    $tag,
59
                    null,
60
                    $tagAccordion,
61
                    $tagCollapse,
62
                    false
63
                );
64
            }
65
        }
66
67
        return $html;
68
    }
69
70
    /**
71
     * @param int    $senderId
72
     * @param int    $receiverId
73
     * @param string $subject
74
     * @param string $message
75
     *
76
     * @return bool
77
     */
78
    public static function messageWasAlreadySent($senderId, $receiverId, $subject, $message)
79
    {
80
        $tblMessage = Database::get_main_table(TABLE_MESSAGE);
81
        $senderId = (int) $senderId;
82
        $receiverId = (int) $receiverId;
83
        $subject = Database::escape_string($subject);
84
        $message = Database::escape_string($message);
85
86
        $sql = "SELECT m.id FROM $tblMessage m
87
                INNER JOIN message_rel_user mru on m.id = mru.message_id
88
                WHERE
89
                    m.user_sender_id = $senderId AND
90
                    mru.user_id = $receiverId AND
91
                    m.title = '$subject' AND
92
                    m.content = '$message' AND
93
                    m.msg_type = ".Message::MESSAGE_TYPE_INBOX."
94
                ";
95
        $result = Database::query($sql);
96
97
        return Database::num_rows($result) > 0;
98
    }
99
100
    /**
101
     * Sends a message to a user/group.
102
     *
103
     * @param int    $receiverUserId
104
     * @param string $subject
105
     * @param string $content
106
     * @param array  $attachments                files array($_FILES) (optional)
107
     * @param array  $fileCommentList            about attachment files (optional)
108
     * @param int    $group_id                   (optional)
109
     * @param int    $parent_id                  (optional)
110
     * @param int    $editMessageId              id for updating the message (optional)
111
     * @param int    $topic_id                   (optional) the default value is the current user_id
112
     * @param int    $sender_id
113
     * @param bool   $directMessage
114
     * @param int    $forwardId
115
     * @param bool   $checkCurrentAudioId
116
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
117
     *
118
     * @return bool
119
     */
120
    public static function send_message(
121
        $receiverUserId,
122
        $subject,
123
        $content,
124
        array $attachments = [],
125
        array $fileCommentList = [],
126
        $group_id = 0,
127
        $parent_id = 0,
128
        $editMessageId = 0,
129
        $topic_id = 0,
130
        $sender_id = 0,
131
        $directMessage = false,
132
        $forwardId = 0,
133
        $checkCurrentAudioId = false,
134
        $forceTitleWhenSendingEmail = false,
135
        $msgType = null,
136
        $baseUrl = null
137
    ) {
138
        $group_id = (int) $group_id;
139
        $receiverUserId = (int) $receiverUserId;
140
        $parent_id = (int) $parent_id;
141
        $editMessageId = (int) $editMessageId;
142
        $topic_id = (int) $topic_id;
143
        $user_sender_id = empty($sender_id) ? api_get_user_id() : (int) $sender_id;
144
145
        if (empty($user_sender_id) || empty($receiverUserId)) {
146
            return false;
147
        }
148
149
        $userSender = api_get_user_entity($user_sender_id);
150
        if (null === $userSender) {
151
            Display::addFlash(Display::return_message(get_lang('This user doesn\'t exist'), 'warning'));
152
153
            return false;
154
        }
155
156
        $userRecipient = api_get_user_entity($receiverUserId);
157
158
        if (null === $userRecipient) {
159
            return false;
160
        }
161
162
        // Disabling messages for inactive users.
163
        if (!$userRecipient->isActive()) {
164
            return false;
165
        }
166
167
        $sendEmail = true;
168
        // Disabling messages depending the pausetraining plugin.
169
        $allowPauseFormation =
170
            'true' === api_get_plugin_setting('pausetraining', 'tool_enable') &&
171
            'true' === api_get_plugin_setting('pausetraining', 'allow_users_to_edit_pause_formation');
172
173
        if ($allowPauseFormation) {
174
            $extraFieldValue = new ExtraFieldValue('user');
175
            $disableEmails = $extraFieldValue->get_values_by_handler_and_field_variable(
176
                $receiverUserId,
177
                'disable_emails'
178
            );
179
180
            // User doesn't want email notifications but chamilo inbox still available.
181
            if (!empty($disableEmails) &&
182
                isset($disableEmails['value']) && 1 === (int) $disableEmails['value']
183
            ) {
184
                $sendEmail = false;
185
            }
186
187
            if ($sendEmail) {
188
                // Check if user pause his formation.
189
                $pause = $extraFieldValue->get_values_by_handler_and_field_variable(
190
                    $receiverUserId,
191
                    'pause_formation'
192
                );
193
                if (!empty($pause) && isset($pause['value']) && 1 === (int) $pause['value']) {
194
                    $startDate = $extraFieldValue->get_values_by_handler_and_field_variable(
195
                        $receiverUserId,
196
                        'start_pause_date'
197
                    );
198
                    $endDate = $extraFieldValue->get_values_by_handler_and_field_variable(
199
                        $receiverUserId,
200
                        'end_pause_date'
201
                    );
202
203
                    if (!empty($startDate) && isset($startDate['value']) && !empty($startDate['value']) &&
204
                        !empty($endDate) && isset($endDate['value']) && !empty($endDate['value'])
205
                    ) {
206
                        $now = time();
207
                        $start = api_strtotime($startDate['value']);
208
                        $end = api_strtotime($endDate['value']);
209
210
                        if ($now > $start && $now < $end) {
211
                            $sendEmail = false;
212
                        }
213
                    }
214
                }
215
            }
216
        }
217
218
        $totalFileSize = 0;
219
        $attachmentList = [];
220
        if (is_array($attachments)) {
221
            $counter = 0;
222
            foreach ($attachments as $attachment) {
223
                $attachment['comment'] = $fileCommentList[$counter] ?? '';
224
                $fileSize = $attachment['size'] ?? 0;
225
                if (is_array($fileSize)) {
226
                    foreach ($fileSize as $size) {
227
                        $totalFileSize += $size;
228
                    }
229
                } else {
230
                    $totalFileSize += $fileSize;
231
                }
232
                $attachmentList[] = $attachment;
233
                $counter++;
234
            }
235
        }
236
237
        if ($checkCurrentAudioId) {
238
            // Add the audio file as an attachment
239
            $audio = Session::read('current_audio');
240
            if (!empty($audio) && isset($audio['name']) && !empty($audio['name'])) {
241
                $audio['comment'] = 'audio_message';
242
                // create attachment from audio message
243
                $attachmentList[] = $audio;
244
            }
245
        }
246
247
        // Validating fields
248
        if (empty($subject) && empty($group_id)) {
249
            Display::addFlash(
250
                Display::return_message(
251
                    get_lang('You should write a subject'),
252
                    'warning'
253
                )
254
            );
255
256
            return false;
257
        } elseif ($totalFileSize > (int) api_get_setting('message_max_upload_filesize')) {
258
            $warning = sprintf(
259
                get_lang('Files size exceeds'),
260
                format_file_size(api_get_setting('message_max_upload_filesize'))
261
            );
262
263
            Display::addFlash(Display::return_message($warning, 'warning'));
264
265
            return false;
266
        }
267
268
        $em = Database::getManager();
269
        $repo = $em->getRepository(Message::class);
270
        $parent = null;
271
        if (!empty($parent_id)) {
272
            $parent = $repo->find($parent_id);
273
        }
274
275
        // Just in case we replace the and \n and \n\r while saving in the DB
276
        if (!empty($receiverUserId) || !empty($group_id)) {
277
            // message for user friend
278
            //@todo it's possible to edit a message? yes, only for groups
279
            if (!empty($editMessageId)) {
280
                $message = $repo->find($editMessageId);
281
                if (null !== $message) {
282
                    $message->setTitle($subject);
283
                    $message->setContent($content);
284
                    $em->persist($message);
285
                    $em->flush();
286
                }
287
                $messageId = $editMessageId;
288
            } else {
289
                $group = Container::getUsergroupRepository()->find($group_id);
290
291
                $message = (new Message())
292
                    ->setSender($userSender)
293
                    ->addReceiverTo($userRecipient)
294
                    ->setTitle($subject)
295
                    ->setContent($content)
296
                    ->setGroup($group)
297
                    ->setParent($parent)
298
                ;
299
300
                if (isset($msgType)) {
301
                    $message->setMsgType($msgType);
302
                }
303
304
                $em->persist($message);
305
                $em->flush();
306
                $messageId = $message->getId();
307
            }
308
309
            // Forward also message attachments.
310
            if (!empty($forwardId)) {
311
                $forwardMessage = $repo->find($forwardId);
312
                if (null !== $forwardMessage) {
313
                    $forwardAttachments = $forwardMessage->getAttachments();
314
                    foreach ($forwardAttachments as $forwardAttachment) {
315
                        $message->addAttachment($forwardAttachment);
316
                    }
317
                    $em->persist($message);
318
                    $em->flush();
319
                }
320
            }
321
322
            // Save attachment file for inbox messages
323
            if (is_array($attachmentList)) {
324
                foreach ($attachmentList as $attachment) {
325
                    if (0 === $attachment['error']) {
326
                        self::saveMessageAttachmentFile(
327
                            $attachment,
328
                            $attachment['comment'] ?? '',
329
                            $message,
330
                        );
331
                    }
332
                }
333
            }
334
335
            // Add the sender as a receiver with TYPE_SENDER
336
            $messageRelUserRepository = $em->getRepository(MessageRelUser::class);
337
            $existingRelation = $messageRelUserRepository->findOneBy([
338
                'message' => $message,
339
                'receiver' => $userSender,
340
                'receiverType' => MessageRelUser::TYPE_SENDER
341
            ]);
342
343
            if (!$existingRelation) {
344
                $messageRelUserSender = new MessageRelUser();
345
                $messageRelUserSender->setMessage($message);
346
                $messageRelUserSender->setReceiver($userSender);
347
                $messageRelUserSender->setReceiverType(MessageRelUser::TYPE_SENDER);
348
                $em->persist($messageRelUserSender);
349
                $em->flush();
350
            }
351
352
            if ($sendEmail) {
353
                $notification = new Notification();
354
                $sender_info = api_get_user_info($user_sender_id);
355
                $baseUrl = $baseUrl ?? api_get_path(WEB_PATH);
356
                $content = self::processRelativeLinks($content, $baseUrl);
357
358
                // add file attachment additional attributes
359
                $attachmentAddedByMail = [];
360
                foreach ($attachmentList as $attachment) {
361
                    $attachmentAddedByMail[] = [
362
                        'path' => $attachment['tmp_name'],
363
                        'filename' => $attachment['name'],
364
                    ];
365
                }
366
367
                if (empty($group_id)) {
368
                    $type = Notification::NOTIFICATION_TYPE_MESSAGE;
369
                    if ($directMessage) {
370
                        $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
371
                    }
372
                    $notification->saveNotification(
373
                        $messageId,
374
                        $type,
375
                        [$receiverUserId],
376
                        $subject,
377
                        $content,
378
                        $sender_info,
379
                        $attachmentAddedByMail,
380
                        $forceTitleWhenSendingEmail,
381
                        $baseUrl
382
                    );
383
                } else {
384
                    $usergroup = new UserGroupModel();
385
                    $group_info = $usergroup->get($group_id);
386
                    $group_info['topic_id'] = $topic_id;
387
                    $group_info['msg_id'] = $messageId;
388
389
                    $user_list = $usergroup->get_users_by_group(
390
                        $group_id,
391
                        false,
392
                        [],
393
                        0,
394
                        1000
395
                    );
396
397
                    // Adding more sense to the message group
398
                    $subject = sprintf(get_lang('There is a new message in group %s'), $group_info['title']);
399
                    $new_user_list = [];
400
                    foreach ($user_list as $user_data) {
401
                        $new_user_list[] = $user_data['id'];
402
                    }
403
                    $group_info = [
404
                        'group_info' => $group_info,
405
                        'user_info' => $sender_info,
406
                    ];
407
                    $notification->saveNotification(
408
                        $messageId,
409
                        Notification::NOTIFICATION_TYPE_GROUP,
410
                        $new_user_list,
411
                        $subject,
412
                        $content,
413
                        $group_info,
414
                        $attachmentAddedByMail,
415
                        $forceTitleWhenSendingEmail,
416
                        $baseUrl
417
                    );
418
                }
419
            }
420
421
            return $messageId;
422
        }
423
424
        return false;
425
    }
426
427
    /**
428
     * Converts relative URLs in href and src attributes to absolute URLs.
429
     */
430
    private static function processRelativeLinks(string $content, string $baseUrl): string
431
    {
432
        return preg_replace_callback(
433
            '/(href|src)="(\/[^"]*)"/',
434
            function ($matches) use ($baseUrl) {
435
                return $matches[1] . '="' . rtrim($baseUrl, '/') . $matches[2] . '"';
436
            },
437
            $content
438
        );
439
    }
440
441
    /**
442
     * @param int    $receiverUserId
443
     * @param string $subject
444
     * @param string $message
445
     * @param int    $sender_id
446
     * @param bool   $sendCopyToDrhUsers send copy to related DRH users
447
     * @param bool   $directMessage
448
     * @param bool   $uploadFiles        Do not upload files using the MessageManager class
449
     * @param array  $attachmentList
450
     *
451
     * @return bool
452
     */
453
    public static function send_message_simple(
454
        $receiverUserId,
455
        $subject,
456
        $message,
457
        $sender_id = 0,
458
        $sendCopyToDrhUsers = false,
459
        $directMessage = false,
460
        $uploadFiles = true,
461
        $attachmentList = []
462
    ) {
463
        $files = $_FILES ? $_FILES : [];
464
        if (false === $uploadFiles) {
465
            $files = [];
466
        }
467
        // $attachmentList must have: tmp_name, name, size keys
468
        if (!empty($attachmentList)) {
469
            $files = $attachmentList;
470
        }
471
        $result = self::send_message(
472
            $receiverUserId,
473
            $subject,
474
            $message,
475
            $files,
476
            [],
477
            null,
478
            null,
479
            null,
480
            null,
481
            $sender_id,
482
            $directMessage
483
        );
484
485
        if ($sendCopyToDrhUsers) {
486
            $userInfo = api_get_user_info($receiverUserId);
487
            $drhList = UserManager::getDrhListFromUser($receiverUserId);
488
            if (!empty($drhList)) {
489
                foreach ($drhList as $drhInfo) {
490
                    $message = sprintf(
491
                        get_lang('Copy of message sent to %s'),
492
                        $userInfo['complete_name']
493
                    ).' <br />'.$message;
494
495
                    self::send_message_simple(
496
                        $drhInfo['id'],
497
                        $subject,
498
                        $message,
499
                        $sender_id,
500
                        false,
501
                        $directMessage
502
                    );
503
                }
504
            }
505
        }
506
507
        return $result;
508
    }
509
510
    /**
511
     * Saves a message attachment files.
512
     *
513
     * @param array  $file    $_FILES['name']
514
     * @param string $comment a comment about the uploaded file
515
     */
516
    public static function saveMessageAttachmentFile($file, $comment, Message $message)
517
    {
518
        // Try to add an extension to the file if it hasn't one
519
        $type = $file['type'] ?? '';
520
        if (empty($type)) {
521
            $type = DocumentManager::file_get_mime_type($file['name']);
522
        }
523
        $new_file_name = add_ext_on_mime(stripslashes($file['name']), $type);
524
525
        // user's file name
526
        $fileName = $file['name'];
527
        if (!filter_extension($new_file_name)) {
528
            Display::addFlash(
529
                Display::return_message(
530
                    get_lang('File upload failed: this file extension or file type is prohibited'),
531
                    'error'
532
                )
533
            );
534
535
            return false;
536
        }
537
538
        $em = Database::getManager();
539
        $attachmentRepo = Container::getMessageAttachmentRepository();
540
541
        $attachment = (new MessageAttachment())
542
            ->setSize($file['size'])
543
            ->setPath($fileName)
544
            ->setFilename($fileName)
545
            ->setComment($comment)
546
            ->setParent($message->getSender())
547
            ->setMessage($message)
548
        ;
549
550
        $request = Container::getRequest();
551
        $fileToUpload = null;
552
553
        // Search for files inside the $_FILES, when uploading several files from the form.
554
        if ($request->files->count()) {
555
            $allFiles = $request->files->all();
556
            $filesArray = array_key_exists('files', $allFiles) ? $allFiles['files'] : $allFiles;
557
            /** @var UploadedFile|null $fileRequest */
558
            foreach ($filesArray as $fileRequest) {
559
                if (null === $fileRequest) {
560
                    continue;
561
                }
562
                if ($fileRequest instanceof UploadedFile && $fileRequest->getClientOriginalName() === $file['name']) {
563
                    $fileToUpload = $fileRequest;
564
                    break;
565
                }
566
            }
567
        }
568
569
        // If no found file, try with $file['content'].
570
        if (null === $fileToUpload && isset($file['content'])) {
571
            $handle = tmpfile();
572
            fwrite($handle, $file['content']);
573
            $meta = stream_get_meta_data($handle);
574
            $fileToUpload = new UploadedFile($meta['uri'], $fileName, $file['type'], null, true);
575
        }
576
577
        if (null !== $fileToUpload) {
578
            $em->persist($attachment);
579
            $attachmentRepo->addFile($attachment, $fileToUpload);
580
            $attachment->addUserLink($message->getSender());
581
            $receivers = $message->getReceivers();
582
            foreach ($receivers as $receiver) {
583
                $attachment->addUserLink($receiver->getReceiver());
584
            }
585
            $em->flush();
586
587
            return true;
588
        }
589
590
        return false;
591
    }
592
593
    /**
594
     * get messages by group id.
595
     *
596
     * @param int $group_id group id
597
     *
598
     * @return array
599
     */
600
    public static function get_messages_by_group($group_id)
601
    {
602
        $group_id = (int) $group_id;
603
604
        if (empty($group_id)) {
605
            return false;
606
        }
607
608
        $table = Database::get_main_table(TABLE_MESSAGE);
609
        $sql = "SELECT * FROM $table
610
                WHERE
611
                    group_id= $group_id AND
612
                    msg_type = ".Message::MESSAGE_TYPE_GROUP."
613
                ORDER BY id";
614
        $rs = Database::query($sql);
615
        $data = [];
616
        if (Database::num_rows($rs) > 0) {
617
            while ($row = Database::fetch_assoc($rs)) {
618
                $data[] = $row;
619
            }
620
        }
621
622
        return $data;
623
    }
624
625
    /**
626
     * get messages by group id.
627
     *
628
     * @param int $group_id
629
     * @param int $message_id
630
     *
631
     * @return array
632
     */
633
    public static function get_messages_by_group_by_message($group_id, $message_id)
634
    {
635
        $group_id = (int) $group_id;
636
637
        if (empty($group_id)) {
638
            return false;
639
        }
640
641
        $table = Database::get_main_table(TABLE_MESSAGE);
642
        $sql = "SELECT * FROM $table
643
                WHERE
644
                    group_id = $group_id AND
645
                    msg_type = '".Message::MESSAGE_TYPE_GROUP."'
646
                ORDER BY id ";
647
648
        $rs = Database::query($sql);
649
        $data = [];
650
        $parents = [];
651
        if (Database::num_rows($rs) > 0) {
652
            while ($row = Database::fetch_assoc($rs)) {
653
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
654
                    $parents[] = $row['id'];
655
                    $data[] = $row;
656
                }
657
            }
658
        }
659
660
        return $data;
661
    }
662
663
    /**
664
     * Get messages by parent id optionally with limit.
665
     *
666
     * @param  int        parent id
667
     * @param  int        group id (optional)
668
     * @param  int        offset (optional)
669
     * @param  int        limit (optional)
670
     *
671
     * @return array
672
     */
673
    public static function getMessagesByParent($parentId, $groupId = 0, $offset = 0, $limit = 0)
674
    {
675
        $table = Database::get_main_table(TABLE_MESSAGE);
676
        $parentId = (int) $parentId;
677
678
        if (empty($parentId)) {
679
            return [];
680
        }
681
682
        $condition_group_id = '';
683
        if (!empty($groupId)) {
684
            $groupId = (int) $groupId;
685
            $condition_group_id = " AND group_id = '$groupId' ";
686
        }
687
688
        $condition_limit = '';
689
        if ($offset && $limit) {
690
            $offset = (int) $offset;
691
            $limit = (int) $limit;
692
            $offset = ($offset - 1) * $limit;
693
            $condition_limit = " LIMIT $offset,$limit ";
694
        }
695
696
        $sql = "SELECT * FROM $table
697
                WHERE
698
                    parent_id='$parentId' AND
699
                    msg_type = '".Message::MESSAGE_TYPE_GROUP."'
700
                    $condition_group_id
701
                ORDER BY send_date DESC $condition_limit ";
702
        $rs = Database::query($sql);
703
        $data = [];
704
        if (Database::num_rows($rs) > 0) {
705
            while ($row = Database::fetch_array($rs)) {
706
                $data[$row['id']] = $row;
707
            }
708
        }
709
710
        return $data;
711
    }
712
713
    /**
714
     * Displays messages of a group with nested view.
715
     *
716
     * @param int $groupId
717
     *
718
     * @return string
719
     */
720
    public static function display_messages_for_group($groupId)
721
    {
722
        global $my_group_role;
723
724
        $rows = self::get_messages_by_group($groupId);
725
        $topics_per_page = 10;
726
        $html_messages = '';
727
        $query_vars = ['id' => $groupId, 'topics_page_nr' => 0];
728
729
        if (is_array($rows) && count($rows) > 0) {
730
            // prepare array for topics with its items
731
            $topics = [];
732
            $x = 0;
733
            foreach ($rows as $index => $value) {
734
                if (empty($value['parent_id'])) {
735
                    $topics[$value['id']] = $value;
736
                }
737
            }
738
739
            $new_topics = [];
740
741
            foreach ($topics as $id => $value) {
742
                $rows = self::get_messages_by_group_by_message($groupId, $value['id']);
743
                if (!empty($rows)) {
744
                    $count = count(self::calculate_children($rows, $value['id']));
745
                } else {
746
                    $count = 0;
747
                }
748
                $value['count'] = $count;
749
                $new_topics[$id] = $value;
750
            }
751
752
            $array_html = [];
753
            foreach ($new_topics as $index => $topic) {
754
                $html = '';
755
                // topics
756
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
757
                $name = $user_sender_info['complete_name'];
758
                $html .= '<div class="groups-messages">';
759
                $html .= '<div class="row">';
760
761
                $items = $topic['count'];
762
                $reply_label = (1 == $items) ? get_lang('Reply') : get_lang('Replies');
763
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
764
                $topic['title'] = trim($topic['title']);
765
766
                if (empty($topic['title'])) {
767
                    $topic['title'] = get_lang('Untitled');
768
                }
769
770
                $html .= '<div class="col-xs-8 col-md-10">';
771
                $html .= Display::tag(
772
                    'h4',
773
                    Display::url(
774
                        Security::remove_XSS($topic['title'], STUDENT, true),
775
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$groupId.'&topic_id='.$topic['id']
776
                    ),
777
                    ['class' => 'title']
778
                );
779
                $actions = '';
780
                if (GROUP_USER_PERMISSION_ADMIN == $my_group_role ||
781
                    GROUP_USER_PERMISSION_MODERATOR == $my_group_role
782
                ) {
783
                    $actions = '<br />'.Display::url(
784
                            get_lang('Delete'),
785
                            api_get_path(
786
                                WEB_CODE_PATH
787
                            ).'social/group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic['id'],
788
                            ['class' => 'btn btn--plain']
789
                        );
790
                }
791
792
                $date = '';
793
                if ($topic['send_date'] != $topic['update_date']) {
794
                    if (!empty($topic['update_date'])) {
795
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
796
                                'LastUpdate'
797
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
798
                    }
799
                } else {
800
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
801
                            'Created'
802
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
803
                }
804
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
805
                $html .= '</div>';
806
807
                $image = $user_sender_info['avatar'];
808
809
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
810
                $user_info .= '<div class="name"><a href="'.api_get_path(
811
                        WEB_PATH
812
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
813
814
                $html .= '<div class="col-xs-4 col-md-2">';
815
                $html .= $user_info;
816
                $html .= '</div>';
817
                $html .= '</div>';
818
                $html .= '</div>';
819
820
                $array_html[] = [$html];
821
            }
822
823
            // grids for items and topics  with paginations
824
            $html_messages .= Display::return_sortable_grid(
825
                'topics',
826
                [],
827
                $array_html,
828
                [
829
                    'hide_navigation' => false,
830
                    'per_page' => $topics_per_page,
831
                ],
832
                $query_vars,
833
                false,
834
                [true, true, true, false],
835
                false
836
            );
837
        }
838
839
        return $html_messages;
840
    }
841
842
    /**
843
     * Get message list by id.
844
     *
845
     * @param int $messageId
846
     *
847
     * @return array
848
     */
849
    public static function get_message_by_id($messageId)
850
    {
851
        $table = Database::get_main_table(TABLE_MESSAGE);
852
        $messageId = (int) $messageId;
853
        $sql = "SELECT * FROM $table
854
                WHERE
855
                    id = '$messageId' AND
856
                    msg_type <> 3";
857
858
        echo $sql;
859
860
        $res = Database::query($sql);
861
        $item = [];
862
        if (Database::num_rows($res) > 0) {
863
            $item = Database::fetch_assoc($res);
864
        }
865
866
        return $item;
867
    }
868
869
    /**
870
     * Displays messages of a group with nested view.
871
     *
872
     * @param $groupId
873
     * @param $topic_id
874
     *
875
     * @return string
876
     */
877
    public static function display_message_for_group($groupId, $topic_id)
878
    {
879
        global $my_group_role;
880
        $main_message = self::get_message_by_id($topic_id);
881
        if (empty($main_message)) {
882
            return false;
883
        }
884
885
        $webCodePath = api_get_path(WEB_CODE_PATH);
886
        $iconCalendar = Display::returnFontAwesomeIcon('calendar');
887
888
        $langEdit = get_lang('Edit');
889
        $langReply = get_lang('Reply');
890
        $langLastUpdated = get_lang('LastUpdated');
891
        $langCreated = get_lang('Created');
892
893
        $rows = self::get_messages_by_group_by_message($groupId, $topic_id);
894
        $rows = self::calculate_children($rows, $topic_id);
895
        $current_user_id = api_get_user_id();
896
897
        $items_per_page = 50;
898
        $query_vars = ['id' => $groupId, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
899
900
        // Main message
901
        $links = '';
902
        $main_content = '';
903
        $html = '';
904
        $items_page_nr = null;
905
906
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
907
        $files_attachments = self::getAttachmentLinkList($main_message['id'], 0);
908
        $name = $user_sender_info['complete_name'];
909
910
        $topic_page_nr = isset($_GET['topics_page_nr']) ? (int) $_GET['topics_page_nr'] : null;
911
912
        $links .= '<div class="pull-right">';
913
        $links .= '<div class="btn-group btn-group-sm">';
914
915
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
916
            $main_message['user_sender_id'] == $current_user_id
917
        ) {
918
            $urlEdit = $webCodePath.'social/message_for_group_form.inc.php?'
919
                .http_build_query(
920
                    [
921
                        'user_friend' => $current_user_id,
922
                        'group_id' => $groupId,
923
                        'message_id' => $main_message['id'],
924
                        'action' => 'edit_message_group',
925
                        'anchor_topic' => 'topic_'.$main_message['id'],
926
                        'topics_page_nr' => $topic_page_nr,
927
                        'items_page_nr' => $items_page_nr,
928
                        'topic_id' => $main_message['id'],
929
                    ]
930
                );
931
932
            $links .= Display::toolbarButton(
933
                $langEdit,
934
                $urlEdit,
935
                'pencil',
936
                'default',
937
                ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
938
                false
939
            );
940
        }
941
942
        $links .= self::getLikesButton($main_message['id'], $current_user_id, $groupId);
943
944
        $urlReply = $webCodePath.'social/message_for_group_form.inc.php?'
945
            .http_build_query(
946
                [
947
                    'user_friend' => $current_user_id,
948
                    'group_id' => $groupId,
949
                    'message_id' => $main_message['id'],
950
                    'action' => 'reply_message_group',
951
                    'anchor_topic' => 'topic_'.$main_message['id'],
952
                    'topics_page_nr' => $topic_page_nr,
953
                    'topic_id' => $main_message['id'],
954
                ]
955
            );
956
957
        $links .= Display::toolbarButton(
958
            $langReply,
959
            $urlReply,
960
            'commenting',
961
            'default',
962
            ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
963
            false
964
        );
965
966
        if (api_is_platform_admin()) {
967
            $links .= Display::toolbarButton(
968
                get_lang('Delete'),
969
                'group_topics.php?action=delete&id='.$groupId.'&topic_id='.$topic_id,
970
                'trash',
971
                'default',
972
                [],
973
                false
974
            );
975
        }
976
977
        $links .= '</div>';
978
        $links .= '</div>';
979
980
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
981
982
        $userPicture = $user_sender_info['avatar'];
983
        $main_content .= '<div class="row">';
984
        $main_content .= '<div class="col-md-2">';
985
        $main_content .= '<div class="avatar-author">';
986
        $main_content .= Display::img(
987
            $userPicture,
988
            $name,
989
            ['width' => '60px', 'class' => 'img-responsive img-circle'],
990
            false
991
        );
992
        $main_content .= '</div>';
993
        $main_content .= '</div>';
994
995
        $date = '';
996
        if ($main_message['send_date'] != $main_message['update_date']) {
997
            if (!empty($main_message['update_date'])) {
998
                $date = '<div class="date"> '
999
                    ."$iconCalendar $langLastUpdated "
1000
                    .Display::dateToStringAgoAndLongDate($main_message['update_date'])
1001
                    .'</div>';
1002
            }
1003
        } else {
1004
            $date = '<div class="date"> '
1005
                ."$iconCalendar $langCreated "
1006
                .Display::dateToStringAgoAndLongDate($main_message['send_date'])
1007
                .'</div>';
1008
        }
1009
        $attachment = '<div class="message-attach">'
1010
            .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
1011
            .'</div>';
1012
        $main_content .= '<div class="col-md-10">';
1013
        $user_link = Display::url(
1014
            $name,
1015
            $webCodePath.'social/profile.php?u='.$main_message['user_sender_id']
1016
        );
1017
        $main_content .= '<div class="message-content"> ';
1018
        $main_content .= '<div class="username">'.$user_link.'</div>';
1019
        $main_content .= $date;
1020
        $main_content .= '<div class="message">'
1021
            .Security::remove_XSS($main_message['content'], STUDENT, true)
1022
            .$attachment.'</div></div>';
1023
        $main_content .= '</div>';
1024
        $main_content .= '</div>';
1025
1026
        $html .= Display::div(
1027
            Display::div(
1028
                $title.$main_content,
1029
                ['class' => 'message-topic']
1030
            ),
1031
            ['class' => 'sm-groups-message']
1032
        );
1033
1034
        $topic_id = $main_message['id'];
1035
1036
        if (is_array($rows) && count($rows) > 0) {
1037
            $topics = $rows;
1038
            $array_html_items = [];
1039
1040
            foreach ($topics as $index => $topic) {
1041
                if (empty($topic['id'])) {
1042
                    continue;
1043
                }
1044
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr'])
1045
                    ? (int) $_GET['items_'.$topic['id'].'_page_nr']
1046
                    : null;
1047
                $links = '';
1048
                $links .= '<div class="pull-right">';
1049
                $html_items = '';
1050
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1051
                $files_attachments = self::getAttachmentLinkList($topic['id'], 0);
1052
                $name = $user_sender_info['complete_name'];
1053
1054
                $links .= '<div class="btn-group btn-group-sm">';
1055
                if (
1056
                    ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1057
                        $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1058
                    ) ||
1059
                    $topic['user_sender_id'] == $current_user_id
1060
                ) {
1061
                    $links .= Display::toolbarButton(
1062
                        $langEdit,
1063
                        $webCodePath.'social/message_for_group_form.inc.php?'
1064
                        .http_build_query(
1065
                            [
1066
                                'user_friend' => $current_user_id,
1067
                                'group_id' => $groupId,
1068
                                'message_id' => $topic['id'],
1069
                                'action' => 'edit_message_group',
1070
                                'anchor_topic' => 'topic_'.$topic_id,
1071
                                'topics_page_nr' => $topic_page_nr,
1072
                                'items_page_nr' => $items_page_nr,
1073
                                'topic_id' => $topic_id,
1074
                            ]
1075
                        ),
1076
                        'pencil',
1077
                        'default',
1078
                        ['class' => 'ajax', 'data-title' => $langEdit, 'data-size' => 'lg'],
1079
                        false
1080
                    );
1081
                }
1082
1083
                $links .= self::getLikesButton($topic['id'], $current_user_id, $groupId);
1084
1085
                $links .= Display::toolbarButton(
1086
                    $langReply,
1087
                    $webCodePath.'social/message_for_group_form.inc.php?'
1088
                    .http_build_query(
1089
                        [
1090
                            'user_friend' => $current_user_id,
1091
                            'group_id' => $groupId,
1092
                            'message_id' => $topic['id'],
1093
                            'action' => 'reply_message_group',
1094
                            'anchor_topic' => 'topic_'.$topic_id,
1095
                            'topics_page_nr' => $topic_page_nr,
1096
                            'items_page_nr' => $items_page_nr,
1097
                            'topic_id' => $topic_id,
1098
                        ]
1099
                    ),
1100
                    'commenting',
1101
                    'default',
1102
                    ['class' => 'ajax', 'data-title' => $langReply, 'data-size' => 'lg'],
1103
                    false
1104
                );
1105
                $links .= '</div>';
1106
                $links .= '</div>';
1107
1108
                $userPicture = $user_sender_info['avatar'];
1109
                $user_link = Display::url(
1110
                    $name,
1111
                    $webCodePath.'social/profile.php?u='.$topic['user_sender_id']
1112
                );
1113
                $html_items .= '<div class="row">';
1114
                $html_items .= '<div class="col-md-2">';
1115
                $html_items .= '<div class="avatar-author">';
1116
                $html_items .= Display::img(
1117
                    $userPicture,
1118
                    $name,
1119
                    ['width' => '60px', 'class' => 'img-responsive img-circle'],
1120
                    false
1121
                );
1122
                $html_items .= '</div>';
1123
                $html_items .= '</div>';
1124
1125
                $date = '';
1126
                if ($topic['send_date'] != $topic['update_date']) {
1127
                    if (!empty($topic['update_date'])) {
1128
                        $date = '<div class="date"> '
1129
                            ."$iconCalendar $langLastUpdated "
1130
                            .Display::dateToStringAgoAndLongDate($topic['update_date'])
1131
                            .'</div>';
1132
                    }
1133
                } else {
1134
                    $date = '<div class="date"> '
1135
                        ."$iconCalendar $langCreated "
1136
                        .Display::dateToStringAgoAndLongDate($topic['send_date'])
1137
                        .'</div>';
1138
                }
1139
                $attachment = '<div class="message-attach">'
1140
                    .(!empty($files_attachments) ? implode('<br />', $files_attachments) : '')
1141
                    .'</div>';
1142
                $html_items .= '<div class="col-md-10">'
1143
                    .'<div class="message-content">'
1144
                    .$links
1145
                    .'<div class="username">'.$user_link.'</div>'
1146
                    .$date
1147
                    .'<div class="message">'
1148
                    .Security::remove_XSS($topic['content'], STUDENT, true)
1149
                    .'</div>'.$attachment.'</div>'
1150
                    .'</div>'
1151
                    .'</div>';
1152
1153
                $base_padding = 20;
1154
1155
                if ($topic['indent_cnt'] == 0) {
1156
                    $indent = $base_padding;
1157
                } else {
1158
                    $indent = (int) $topic['indent_cnt'] * $base_padding + $base_padding;
1159
                }
1160
1161
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
1162
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
1163
                $array_html_items[] = [$html_items];
1164
            }
1165
1166
            // grids for items with paginations
1167
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
1168
            $visibility = [true, true, true, false];
1169
1170
            $style_class = [
1171
                'item' => ['class' => 'user-post'],
1172
                'main' => ['class' => 'user-list'],
1173
            ];
1174
            if (!empty($array_html_items)) {
1175
                $html .= Display::return_sortable_grid(
1176
                    'items_'.$topic['id'],
1177
                    [],
1178
                    $array_html_items,
1179
                    $options,
1180
                    $query_vars,
1181
                    null,
1182
                    $visibility,
1183
                    false,
1184
                    $style_class
1185
                );
1186
            }
1187
        }
1188
1189
1190
        return $html;
1191
    }
1192
1193
    /**
1194
     * Add children to messages by id is used for nested view messages.
1195
     *
1196
     * @param array $rows rows of messages
1197
     *
1198
     * @return array $first_seed new list adding the item children
1199
     */
1200
    public static function calculate_children($rows, $first_seed)
1201
    {
1202
        $rows_with_children = [];
1203
        foreach ($rows as $row) {
1204
            $rows_with_children[$row["id"]] = $row;
1205
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
1206
        }
1207
        $rows = $rows_with_children;
1208
        $sorted_rows = [0 => []];
1209
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
1210
        unset($sorted_rows[0]);
1211
1212
        return $sorted_rows;
1213
    }
1214
1215
    /**
1216
     * Sort recursively the messages, is used for for nested view messages.
1217
     *
1218
     * @param array  original rows of messages
1219
     * @param array  list recursive of messages
1220
     * @param int   seed for calculate the indent
1221
     * @param int   indent for nested view
1222
     */
1223
    public static function message_recursive_sort(
1224
        $rows,
1225
        &$messages,
1226
        $seed = 0,
1227
        $indent = 0
1228
    ) {
1229
        if ($seed > 0 && isset($rows[$seed]["id"])) {
1230
            $messages[$rows[$seed]["id"]] = $rows[$seed];
1231
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
1232
            $indent++;
1233
        }
1234
1235
        if (isset($rows[$seed]["children"])) {
1236
            foreach ($rows[$seed]["children"] as $child) {
1237
                self::message_recursive_sort($rows, $messages, $child, $indent);
1238
            }
1239
        }
1240
    }
1241
1242
    /**
1243
     * Get array of links (download) for message attachment files.
1244
     *
1245
     * @return array
1246
     */
1247
    public static function getAttachmentLinkList(Message $message)
1248
    {
1249
        $files = $message->getAttachments();
1250
        // get file attachments by message id
1251
        $list = [];
1252
        if ($files) {
0 ignored issues
show
introduced by
$files is of type Doctrine\Common\Collections\Collection, thus it always evaluated to true.
Loading history...
1253
            $attachIcon = Display::getMdiIcon('paperclip');
1254
            $repo = Container::getMessageAttachmentRepository();
1255
            foreach ($files as $file) {
1256
                $size = format_file_size($file->getSize());
1257
                $comment = Security::remove_XSS($file->getComment());
1258
                $filename = Security::remove_XSS($file->getFilename());
1259
                $url = $repo->getResourceFileUrl($file);
1260
                $link = Display::url($filename, $url);
1261
                $comment = !empty($comment) ? '&nbsp;-&nbsp;<i>'.$comment.'</i>' : '';
1262
1263
                $attachmentLine = $attachIcon.'&nbsp;'.$link.'&nbsp;('.$size.')'.$comment;
1264
                /*if ('audio_message' === $file['comment']) {
1265
                    $attachmentLine = '<audio src="'.$archiveURL.$archiveFile.'"/>';
1266
                }*/
1267
                $list[] = $attachmentLine;
1268
            }
1269
        }
1270
1271
        return $list;
1272
    }
1273
1274
    /**
1275
     * @return string
1276
     */
1277
    public static function generate_message_form()
1278
    {
1279
        $form = new FormValidator('send_message');
1280
        $form->addText(
1281
            'subject',
1282
            get_lang('Subject'),
1283
            false,
1284
            ['id' => 'subject_id']
1285
        );
1286
        $form->addTextarea(
1287
            'content',
1288
            get_lang('Message'),
1289
            ['id' => 'content_id', 'rows' => '5']
1290
        );
1291
1292
        return $form->returnForm();
1293
    }
1294
1295
    /**
1296
     * @return string
1297
     */
1298
    public static function generate_invitation_form()
1299
    {
1300
        $form = new FormValidator('send_invitation');
1301
        $form->addTextarea(
1302
            'content',
1303
            get_lang('Add a personal message'),
1304
            ['id' => 'content_invitation_id', 'rows' => 5]
1305
        );
1306
1307
        return $form->returnForm();
1308
    }
1309
1310
    /**
1311
     * @param string $type
1312
     * @param string $keyword
1313
     * @param array  $actions
1314
     *
1315
     * @return string
1316
     */
1317
    public static function getMessageGrid($type, $keyword, $actions = [])
1318
    {
1319
        $html = '';
1320
        // display sortable table with messages of the current user
1321
        $table = new SortableTable(
1322
            'message_inbox',
1323
            ['MessageManager', 'getNumberOfMessages'],
1324
            ['MessageManager', 'getMessageData'],
1325
            2,
1326
            20,
1327
            'DESC'
1328
        );
1329
        $table->setDataFunctionParams(
1330
            ['keyword' => $keyword, 'type' => $type, 'actions' => $actions]
1331
        );
1332
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
1333
        $table->set_header(1, get_lang('Messages'), false);
1334
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
1335
        $table->set_header(3, get_lang('Edit'), false, ['style' => 'width:120px;']);
1336
1337
        if (isset($_REQUEST['f']) && 'social' === $_REQUEST['f']) {
1338
            $parameters['f'] = 'social';
1339
            $table->set_additional_parameters($parameters);
1340
        }
1341
1342
        $defaultActions = [
1343
            'delete' => get_lang('Delete selected messages'),
1344
            'mark_as_unread' => get_lang('Mark as unread'),
1345
            'mark_as_read' => get_lang('Mark as read'),
1346
        ];
1347
1348
        if (!in_array('delete', $actions)) {
1349
            unset($defaultActions['delete']);
1350
        }
1351
        if (!in_array('mark_as_unread', $actions)) {
1352
            unset($defaultActions['mark_as_unread']);
1353
        }
1354
        if (!in_array('mark_as_read', $actions)) {
1355
            unset($defaultActions['mark_as_read']);
1356
        }
1357
1358
        $table->set_form_actions($defaultActions);
1359
1360
        $html .= $table->return_table();
1361
1362
        return $html;
1363
    }
1364
1365
    /**
1366
     * @param string $url
1367
     *
1368
     * @return FormValidator
1369
     */
1370
    public static function getSearchForm($url)
1371
    {
1372
        $form = new FormValidator(
1373
            'search',
1374
            'post',
1375
            $url,
1376
            null,
1377
            [],
1378
            FormValidator::LAYOUT_INLINE
1379
        );
1380
1381
        $form->addElement(
1382
            'text',
1383
            'keyword',
1384
            false,
1385
            [
1386
                'aria-label' => get_lang('Search'),
1387
            ]
1388
        );
1389
        $form->addButtonSearch(get_lang('Search'));
1390
1391
        return $form;
1392
    }
1393
1394
    /**
1395
     * Send a notification to all admins when a new user is registered.
1396
     */
1397
    public static function sendNotificationOfNewRegisteredUser(User $user)
1398
    {
1399
        $tplMailBody = new Template(
1400
            null,
1401
            false,
1402
            false,
1403
            false,
1404
            false,
1405
            false,
1406
            false
1407
        );
1408
        $tplMailBody->assign('user', $user);
1409
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
1410
        $tplMailBody->assign(
1411
            'manageUrl',
1412
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
1413
        );
1414
1415
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
1416
1417
        $emailsubject = '['.get_lang('The user has been registered').'] '.$user->getUsername();
1418
        $emailbody = $tplMailBody->fetch($layoutContent);
1419
1420
        $admins = UserManager::get_all_administrators();
1421
1422
        foreach ($admins as $admin_info) {
1423
            self::send_message(
1424
                $admin_info['user_id'],
1425
                $emailsubject,
1426
                $emailbody,
1427
                [],
1428
                [],
1429
                null,
1430
                null,
1431
                null,
1432
                null,
1433
                $user->getId()
1434
            );
1435
        }
1436
    }
1437
1438
    /**
1439
     * Send a notification to all admins when a new user is registered
1440
     * while the approval method is used for users registration.
1441
     */
1442
    public static function sendNotificationOfNewRegisteredUserApproval(User $user)
1443
    {
1444
        $tplMailBody = new Template(
1445
            null,
1446
            false,
1447
            false,
1448
            false,
1449
            false,
1450
            false,
1451
            false
1452
        );
1453
        $tplMailBody->assign('user', $user);
1454
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
1455
        $userId = $user->getId();
1456
        $url_edit = Display::url(
1457
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId,
1458
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId
1459
        );
1460
        $tplMailBody->assign(
1461
            'manageUrl',
1462
            $url_edit
1463
        );
1464
        // Get extra field values for this user and reformat the array
1465
        $extraFieldValues = new ExtraFieldValue('user');
1466
        $userExtraFields = $extraFieldValues->getAllValuesByItem($userId);
1467
        $values = [];
1468
        foreach ($userExtraFields as $field => $value) {
1469
            $values[$value['variable']] = $value['value'];
1470
        }
1471
        $tplMailBody->assign(
1472
            'extra',
1473
            $values
1474
        );
1475
        $layoutContent = '';
1476
        $emailbody = '';
1477
        $mailTemplateManager = new MailTemplateManager();
1478
        $templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl');
1479
        if (empty($templateText)) {
1480
        } else {
1481
            // custom procedure to load a template as a string (doesn't use cache so may slow down)
1482
            $template = $tplMailBody->twig->createTemplate($templateText);
1483
            $emailbody = $template->render($tplMailBody->params);
1484
        }
1485
        if (empty($emailbody)) {
1486
            $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl');
1487
            $emailbody = $tplMailBody->fetch($layoutContent);
1488
        }
1489
1490
        $emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername();
1491
1492
        if ('true' === api_get_setting('admin.send_inscription_notification_to_general_admin_only')) {
1493
            $email = api_get_setting('emailAdministrator');
1494
            $firstname = api_get_setting('administratorSurname');
1495
            $lastname = api_get_setting('administratorName');
1496
            api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody);
1497
        } else {
1498
            $admins = UserManager::get_all_administrators();
1499
            foreach ($admins as $admin_info) {
1500
                self::send_message(
1501
                    $admin_info['user_id'],
1502
                    $emailsubject,
1503
                    $emailbody,
1504
                    [],
1505
                    [],
1506
                    null,
1507
                    null,
1508
                    null,
1509
                    null,
1510
                    $userId
1511
                );
1512
            }
1513
        }
1514
    }
1515
1516
    /**
1517
     * Get the error log from failed mailing
1518
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
1519
     * into app/cache/mail/mailq.
1520
     * This can be done with a cron command like (check the location of your mail log file first):.
1521
     *
1522
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
1523
     *
1524
     * @return array|bool
1525
     */
1526
    public static function failedSentMailErrors()
1527
    {
1528
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
1529
        $mailq = $base.'mailq';
1530
1531
        if (!file_exists($mailq) || !is_readable($mailq)) {
1532
            return false;
1533
        }
1534
1535
        $file = fopen($mailq, 'r');
1536
        $i = 1;
1537
        while (!feof($file)) {
1538
            $line = fgets($file);
1539
1540
            if ('' == trim($line)) {
1541
                continue;
1542
            }
1543
1544
            // Get the mail code, something like 1WBumL-0002xg-FF
1545
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
1546
                $mail_queue[$i]['code'] = $codeMatches[2];
1547
            }
1548
1549
            $fullMail = $base.$mail_queue[$i]['code'];
1550
            $mailFile = fopen($fullMail, 'r');
1551
1552
            // Get the reason of mail fail
1553
            $iX = 1;
1554
            while (!feof($mailFile)) {
1555
                $mailLine = fgets($mailFile);
1556
                //if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
1557
                if (2 == $iX &&
1558
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
1559
                ) {
1560
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
1561
                }
1562
                $iX++;
1563
            }
1564
1565
            fclose($mailFile);
1566
1567
            // Get the time of mail fail
1568
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
1569
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
1570
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
1571
                $mail_queue[$i]['mail'] = $emailMatches[2];
1572
                $i++;
1573
            }
1574
        }
1575
1576
        fclose($file);
1577
1578
        return array_reverse($mail_queue);
1579
    }
1580
1581
    /**
1582
     * @param int $userId
1583
     *
1584
     * @return array
1585
     */
1586
    public static function getUsersThatHadConversationWithUser($userId)
1587
    {
1588
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
1589
        $userId = (int) $userId;
1590
1591
        $sql = "SELECT DISTINCT
1592
                    user_sender_id
1593
                FROM $messagesTable
1594
                WHERE
1595
                    user_receiver_id = ".$userId;
1596
        $result = Database::query($sql);
1597
        $users = Database::store_result($result);
1598
        $userList = [];
1599
        foreach ($users as $userData) {
1600
            $userId = $userData['user_sender_id'];
1601
            if (empty($userId)) {
1602
                continue;
1603
            }
1604
            $userInfo = api_get_user_info($userId);
1605
            if ($userInfo) {
1606
                $userList[$userId] = $userInfo;
1607
            }
1608
        }
1609
1610
        return $userList;
1611
    }
1612
1613
    /**
1614
     * @param int $userId
1615
     * @param int $otherUserId
1616
     *
1617
     * @return array
1618
     */
1619
    public static function getAllMessagesBetweenStudents($userId, $otherUserId)
1620
    {
1621
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
1622
        $userId = (int) $userId;
1623
        $otherUserId = (int) $otherUserId;
1624
1625
        if (empty($otherUserId) || empty($userId)) {
1626
            return [];
1627
        }
1628
1629
        $sql = "SELECT DISTINCT *
1630
                FROM $messagesTable
1631
                WHERE
1632
                    (user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
1633
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId)
1634
                ORDER BY send_date DESC
1635
            ";
1636
        $result = Database::query($sql);
1637
        $messages = Database::store_result($result);
1638
        $list = [];
1639
        foreach ($messages as $message) {
1640
            $list[] = $message;
1641
        }
1642
1643
        return $list;
1644
    }
1645
1646
    /**
1647
     * @param string $subject
1648
     * @param string $message
1649
     * @param Course $course
1650
     * @param int    $sessionId
1651
     *
1652
     * @return bool
1653
     */
1654
    public static function sendMessageToAllUsersInCourse($subject, $message, Course $course, $sessionId = 0)
1655
    {
1656
        $senderId = api_get_user_id();
1657
        if (empty($senderId)) {
1658
            return false;
1659
        }
1660
        if (empty($sessionId)) {
1661
            // Course students and teachers
1662
            $users = CourseManager::get_user_list_from_course_code($course->getCode());
1663
        } else {
1664
            // Course-session students and course session coaches
1665
            $users = CourseManager::get_user_list_from_course_code($course->getCode(), $sessionId);
1666
        }
1667
1668
        if (empty($users)) {
1669
            return false;
1670
        }
1671
1672
        foreach ($users as $userInfo) {
1673
            self::send_message_simple(
1674
                $userInfo['user_id'],
1675
                $subject,
1676
                $message,
1677
                $senderId,
1678
                false,
1679
                false,
1680
                false
1681
            );
1682
        }
1683
    }
1684
1685
    /**
1686
     * Clean audio messages already added in the message tool.
1687
     */
1688
    public static function cleanAudioMessage()
1689
    {
1690
        Session::erase('current_audio');
1691
    }
1692
1693
    /**
1694
     * @param int    $senderId
1695
     * @param string $subject
1696
     * @param string $message
1697
     */
1698
    public static function sendMessageToAllAdminUsers(
1699
        $senderId,
1700
        $subject,
1701
        $message
1702
    ) {
1703
        $admins = UserManager::get_all_administrators();
1704
        foreach ($admins as $admin) {
1705
            self::send_message_simple($admin['user_id'], $subject, $message, $senderId);
1706
        }
1707
    }
1708
1709
    /**
1710
     * @param int $messageId
1711
     * @param int $userId
1712
     *
1713
     * @return array
1714
     */
1715
    public static function countLikesAndDislikes($messageId, $userId): array
1716
    {
1717
        if ('true' !== api_get_setting('social.social_enable_messages_feedback')) {
1718
            return [];
1719
        }
1720
1721
        $user = Container::getUserRepository()->find($userId);
1722
        $socialPost = Container::getSocialPostRepository()->find($messageId);
1723
1724
        $userLike = $user->getSocialPostFeedbackBySocialPost($socialPost);
1725
1726
        return [
1727
            'likes' => $socialPost->getCountFeedbackLikes(),
1728
            'dislikes' => $socialPost->getCountFeedbackDislikes(),
1729
            'user_liked' => $userLike ? $userLike->isLiked() : false,
1730
            'user_disliked' => $userLike ? $userLike->isDisliked() : false,
1731
        ];
1732
    }
1733
1734
    /**
1735
     * @param int $messageId
1736
     * @param int $userId
1737
     * @param int $groupId   Optional.
1738
     *
1739
     * @return string
1740
     */
1741
    public static function getLikesButton($messageId, $userId, $groupId = 0)
1742
    {
1743
        if ('true' !== api_get_setting('social.social_enable_messages_feedback')) {
1744
            return '';
1745
        }
1746
1747
        $countLikes = self::countLikesAndDislikes($messageId, $userId);
1748
1749
        $class = $countLikes['user_liked'] ? 'btn--primary' : 'btn--plain';
1750
1751
        $btnLike = Display::button(
1752
            'like',
1753
            Display::getMdiIcon('thumb-up')
1754
                .PHP_EOL.'<span>'.$countLikes['likes'].'</span>',
1755
            [
1756
                'title' => get_lang('Like'),
1757
                'class' => 'btn  social-like '.$class,
1758
                'data-status' => 'like',
1759
                'data-message' => $messageId,
1760
                'data-group' => $groupId,
1761
            ]
1762
        );
1763
1764
        $btnDislike = '';
1765
        if ('true' !== api_get_setting('social.disable_dislike_option')) {
1766
            $disabled = $countLikes['user_disliked'] ? 'btn--danger' : 'btn--plain';
1767
1768
            $btnDislike = Display::button(
1769
                'like',
1770
                Display::getMdiIcon('thumb-down')
1771
                .PHP_EOL.'<span>'.$countLikes['dislikes'].'</span>',
1772
                [
1773
                    'title' => get_lang('Dislike'),
1774
                    'class' => 'btn social-like '.$disabled,
1775
                    'data-status' => 'dislike',
1776
                    'data-message' => $messageId,
1777
                    'data-group' => $groupId,
1778
                ]
1779
            );
1780
        }
1781
1782
        return $btnLike.PHP_EOL.$btnDislike;
1783
    }
1784
1785
    /**
1786
     * Reports whether the given user is sender or receiver of the given message
1787
     */
1788
    public static function isUserOwner(int $userId, int $messageId): bool
1789
    {
1790
        $table = Database::get_main_table(TABLE_MESSAGE);
1791
        $sql = "SELECT id FROM $table
1792
          WHERE id = $messageId
1793
            AND (user_receiver_id = $userId OR user_sender_id = $userId)";
1794
        $res = Database::query($sql);
1795
        if (Database::num_rows($res) === 1) {
1796
            return true;
1797
        }
1798
        return false;
1799
    }
1800
}
1801