Passed
Pull Request — master (#5005)
by Yannick
12:54 queued 06:05
created

MessageManager::send_message_simple()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 55
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 33
c 0
b 0
f 0
nc 24
nop 8
dl 0
loc 55
rs 8.4586

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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