Passed
Push — master ( 954b89...f7e68c )
by Julito
07:20
created

MessageManager::generate_message_form()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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