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

MessageManager::sendMessageToAllAdminUsers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 8
rs 10
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