Completed
Push — master ( d5b39b...ee3fd0 )
by Julito
27:10
created

getUsersThatHadConversationWithUser()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 16
nc 4
nop 1
dl 0
loc 25
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
7
/**
8
 * Class MessageManager
9
 *
10
 * This class provides methods for messages management.
11
 * Include/require it in your code to use its features.
12
 *
13
 * @package chamilo.library
14
 */
15
class MessageManager
16
{
17
    /**
18
     * Get count new messages for the current user from the database.
19
     * @return int
20
     */
21
    public static function getCountNewMessages()
22
    {
23
        $userId = api_get_user_id();
24
        if (empty($userId)) {
25
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
26
        }
27
28
        static $count;
29
        if (!isset($count)) {
30
            $cacheAvailable = api_get_configuration_value('apc');
31
            if ($cacheAvailable === true) {
32
                $var = api_get_configuration_value('apc_prefix').'social_messages_unread_u_'.$userId;
0 ignored issues
show
Bug introduced by
Are you sure api_get_configuration_value('apc_prefix') of type mixed|false can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

32
                $var = /** @scrutinizer ignore-type */ api_get_configuration_value('apc_prefix').'social_messages_unread_u_'.$userId;
Loading history...
33
                if (apcu_exists($var)) {
34
                    $count = apcu_fetch($var);
35
                } else {
36
                    $count = self::getCountNewMessagesFromDB($userId);
37
                    apcu_store($var, $count, 60);
38
                }
39
            } else {
40
                $count = self::getCountNewMessagesFromDB($userId);
41
            }
42
        }
43
44
        return $count;
45
    }
46
47
    /**
48
     * Execute the SQL necessary to know the number of messages in the database
49
     * @param   int $userId The user for which we need the unread messages count
50
     * @return  int The number of unread messages in the database for the given user
51
     */
52
    private static function getCountNewMessagesFromDB($userId)
53
    {
54
        if (empty($userId)) {
55
            return 0;
56
        }
57
        $table = Database::get_main_table(TABLE_MESSAGE);
58
        $sql = "SELECT COUNT(id) as count 
59
                FROM $table
60
                WHERE
61
                    user_receiver_id=".api_get_user_id()." AND
62
                    msg_status = ".MESSAGE_STATUS_UNREAD;
63
        $result = Database::query($sql);
64
        $row = Database::fetch_assoc($result);
65
66
        return $row['count'];
67
    }
68
69
    /**
70
     * Gets the total number of messages, used for the inbox sortable table
71
     * @param bool $unread
72
     * @return int
73
     */
74
    public static function getNumberOfMessages($unread = false)
75
    {
76
        $table = Database::get_main_table(TABLE_MESSAGE);
77
        if ($unread) {
78
            $condition_msg_status = ' msg_status = '.MESSAGE_STATUS_UNREAD.' ';
79
        } else {
80
            $condition_msg_status = ' msg_status IN('.MESSAGE_STATUS_NEW.','.MESSAGE_STATUS_UNREAD.') ';
81
        }
82
83
        $keyword = Session::read('message_search_keyword');
84
        $keywordCondition = '';
85
        if (!empty($keyword)) {
86
            $keyword = Database::escape_string($keyword);
87
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
88
        }
89
90
        $sql = "SELECT COUNT(id) as number_messages
91
                FROM $table
92
                WHERE $condition_msg_status AND
93
                    user_receiver_id=".api_get_user_id()."
94
                    $keywordCondition
95
                ";
96
        $result = Database::query($sql);
97
        $result = Database::fetch_array($result);
98
99
        return $result['number_messages'];
100
    }
101
102
    /**
103
     * Gets information about some messages, used for the inbox sortable table
104
     * @param int $from
105
     * @param int $number_of_items
106
     * @param string $column
107
     * @param string $direction
108
     * @return array
109
     */
110
    public static function get_message_data(
111
        $from,
112
        $number_of_items,
113
        $column,
114
        $direction,
115
        $userId = 0
116
    ) {
117
        $from = (int)$from;
118
        $number_of_items = (int)$number_of_items;
119
        $userId = empty($userId) ? api_get_user_id() : (int)$userId;
120
121
        //forcing this order
122
        if (!isset($direction)) {
123
            $column = 2;
124
            $direction = 'DESC';
125
        } else {
126
            $column = intval($column);
127
            if (!in_array($direction, ['ASC', 'DESC'])) {
128
                $direction = 'ASC';
129
            }
130
        }
131
132
        if (!in_array($column, [0, 1, 2])) {
133
            $column = 2;
134
        }
135
136
        $keyword = Session::read('message_search_keyword');
137
        $keywordCondition = '';
138
        if (!empty($keyword)) {
139
            $keyword = Database::escape_string($keyword);
140
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
141
        }
142
143
        $table = Database::get_main_table(TABLE_MESSAGE);
144
        $sql = "SELECT 
145
                    id as col0, 
146
                    title as col1, 
147
                    send_date as col2, 
148
                    msg_status as col3,
149
                    user_sender_id
150
                FROM $table
151
                WHERE
152
                    user_receiver_id=".$userId." AND
153
                    msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
154
                    $keywordCondition
155
                ORDER BY col$column $direction
156
                LIMIT $from, $number_of_items";
157
158
        $result = Database::query($sql);
159
        $message_list = [];
160
        $newMessageLink = api_get_path(WEB_CODE_PATH).'messages/new_message.php';
161
        while ($row = Database::fetch_array($result, 'ASSOC')) {
162
            $messageId = $row['col0'];
163
            $title = $row['col1'];
164
            $sendDate = $row['col2'];
165
            $status = $row['col3'];
166
            $senderId = $row['user_sender_id'];
167
168
            $title = Security::remove_XSS($title, STUDENT, true);
169
            $title = cut($title, 80, true);
170
171
            if ($status == 1) {
172
                $class = 'class = "unread"';
173
            } else {
174
                $class = 'class = "read"';
175
            }
176
177
            $userInfo = api_get_user_info($senderId);
178
            if (!empty($senderId) && !empty($userInfo)) {
179
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
180
                $message[1] .= $userInfo['complete_name_with_username'];
181
                $message[3] =
182
                    Display::url(
183
                        Display::returnFontAwesomeIcon('reply', 2),
184
                        $newMessageLink.'?re_id='.$messageId,
185
                        ['title' => get_lang('ReplyToMessage')]
186
                    );
187
            } else {
188
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
189
                $message[1] .= get_lang('UnknownUser');
190
                $message[3] =
191
                    Display::url(
192
                        Display::returnFontAwesomeIcon('reply', 2),
193
                        '#',
194
                        ['title' => get_lang('ReplyToMessage')]
195
                    );
196
            }
197
198
            $message[0] = $messageId;
199
            $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
200
            $message[3] .=
201
                '&nbsp;&nbsp;'.
202
                Display::url(
203
                    Display::returnFontAwesomeIcon('share', 2),
204
                    $newMessageLink.'?forward_id='.$messageId,
205
                    ['title' => get_lang('ForwardMessage')]
206
                ).
207
                '&nbsp;&nbsp;<a title="'.addslashes(
208
                    get_lang('DeleteMessage')
209
                ).'" onclick="javascript:if(!confirm('."'".addslashes(
210
                    api_htmlentities(get_lang('ConfirmDeleteMessage'))
211
                )."'".')) return false;" href="inbox.php?action=deleteone&id='.$messageId.'">'.
212
                Display::returnFontAwesomeIcon('trash', 2).'</a>';
213
            foreach ($message as $key => $value) {
214
                $message[$key] = api_xml_http_response_encode($value);
215
            }
216
            $message_list[] = $message;
217
        }
218
219
        return $message_list;
220
    }
221
222
    /**
223
     * @param array $aboutUserInfo
224
     * @param array $fromUserInfo
225
     * @param string $subject
226
     * @param string $content
227
     * @return bool
228
     */
229
    public static function sendMessageAboutUser(
230
        $aboutUserInfo,
231
        $fromUserInfo,
232
        $subject,
233
        $content
234
    ) {
235
        if (empty($aboutUserInfo) || empty($fromUserInfo)) {
236
            return false;
237
        }
238
239
        if (empty($fromUserInfo['id']) || empty($aboutUserInfo['id'])) {
240
            return false;
241
        }
242
243
        $table = Database::get_main_table(TABLE_MESSAGE);
244
        $now = api_get_utc_datetime();
245
        $params = [
246
            'user_sender_id' => $fromUserInfo['id'],
247
            'user_receiver_id' => $aboutUserInfo['id'],
248
            'msg_status' => MESSAGE_STATUS_CONVERSATION,
249
            'send_date' => $now,
250
            'title' => $subject,
251
            'content' => $content,
252
            'group_id' => 0,
253
            'parent_id' => 0,
254
            'update_date' => $now
255
        ];
256
        $id = Database::insert($table, $params);
257
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
258
            return true;
259
        }
260
261
        return false;
262
    }
263
264
    /**
265
     * @param array $aboutUserInfo
266
     * @return array
267
     */
268
    public static function getMessagesAboutUser($aboutUserInfo)
269
    {
270
        if (!empty($aboutUserInfo)) {
271
            $criteria = [
272
                'userReceiverId' => $aboutUserInfo['id'],
273
                'msgStatus' => MESSAGE_STATUS_CONVERSATION
274
            ];
275
            $repo = Database::getManager()->getRepository('ChamiloCoreBundle:Message');
276
            $messages = $repo->findBy($criteria, ['sendDate' => 'DESC']);
277
278
            return $messages;
279
        }
280
281
        return [];
282
    }
283
284
    /**
285
     * Sends a message to a user/group
286
     *
287
     * @param int $receiver_user_id
288
     * @param string $subject
289
     * @param string $content
290
     * @param array $file_attachments files array($_FILES) (optional)
291
     * @param array $file_comments about attachment files (optional)
292
     * @param int $group_id (optional)
293
     * @param int $parent_id (optional)
294
     * @param int $editMessageId id for updating the message (optional)
295
     * @param int $topic_id (optional) the default value is the current user_id
296
     * @param int $sender_id
297
     * @param bool $directMessage
298
     * @param int $forwardId
299
     * @param array $smsParameters
300
     *
301
     * @return bool
302
     */
303
    public static function send_message(
304
        $receiver_user_id,
305
        $subject,
306
        $content,
307
        array $file_attachments = [],
308
        array $file_comments = [],
309
        $group_id = 0,
310
        $parent_id = 0,
311
        $editMessageId = 0,
312
        $topic_id = 0,
313
        $sender_id = 0,
314
        $directMessage = false,
315
        $forwardId = 0,
0 ignored issues
show
Unused Code introduced by
The parameter $forwardId is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

315
        /** @scrutinizer ignore-unused */ $forwardId = 0,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
316
        $smsParameters = []
317
    ) {
318
        $table = Database::get_main_table(TABLE_MESSAGE);
319
        $group_id = (int) $group_id;
320
        $receiver_user_id = (int) $receiver_user_id;
321
        $parent_id = (int) $parent_id;
322
        $editMessageId = (int) $editMessageId;
323
        $topic_id = (int) $topic_id;
324
325
        if (!empty($receiver_user_id)) {
326
            $receiverUserInfo = api_get_user_info($receiver_user_id);
327
328
            // Disabling messages for inactive users.
329
            if ($receiverUserInfo['active'] == 0) {
330
                return false;
331
            }
332
        }
333
334
        $user_sender_id = empty($sender_id) ? api_get_user_id() : (int) $sender_id;
335
        if (empty($user_sender_id)) {
336
            Display::addFlash(Display::return_message(get_lang('UserDoesNotExist'), 'warning'));
337
            return false;
338
        }
339
340
        $totalFileSize = 0;
341
        if (is_array($file_attachments)) {
342
            foreach ($file_attachments as $file_attach) {
343
                $fileSize = isset($file_attach['size']) ? $file_attach['size'] : 0;
344
                if (is_array($fileSize)) {
345
                    foreach ($fileSize as $size) {
346
                        $totalFileSize += $size;
347
                    }
348
                } else {
349
                    $totalFileSize += $fileSize;
350
                }
351
            }
352
        }
353
354
        // Validating fields
355
        if (empty($subject) && empty($group_id)) {
356
            Display::addFlash(
357
                Display::return_message(
358
                    get_lang('YouShouldWriteASubject'),
359
                    'warning'
360
                )
361
            );
362
            return false;
363
        } elseif ($totalFileSize > intval(api_get_setting('message_max_upload_filesize'))) {
364
            $warning = sprintf(
365
                get_lang("FilesSizeExceedsX"),
366
                format_file_size(api_get_setting('message_max_upload_filesize'))
367
            );
368
369
            Display::addFlash(Display::return_message($warning, 'warning'));
370
371
            return false;
372
        }
373
374
        // Just in case we replace the and \n and \n\r while saving in the DB
375
        // $content = str_replace(array("\n", "\n\r"), '<br />', $content);
376
        $now = api_get_utc_datetime();
377
        if (!empty($receiver_user_id) || !empty($group_id)) {
378
            // message for user friend
379
            //@todo it's possible to edit a message? yes, only for groups
380
            if (!empty($editMessageId)) {
381
                $query = " UPDATE $table SET
382
                                update_date = '".$now."',
383
                                content = '".Database::escape_string($content)."'
384
                           WHERE id = '$editMessageId' ";
385
                Database::query($query);
386
                $messageId = $editMessageId;
387
            } else {
388
                $params = [
389
                    'user_sender_id' => $user_sender_id,
390
                    'user_receiver_id' => $receiver_user_id,
391
                    'msg_status' => MESSAGE_STATUS_UNREAD,
392
                    'send_date' => $now,
393
                    'title' => $subject,
394
                    'content' => $content,
395
                    'group_id' => $group_id,
396
                    'parent_id' => $parent_id,
397
                    'update_date' => $now
398
                ];
399
                $messageId = Database::insert($table, $params);
400
            }
401
402
            // Save attachment file for inbox messages
403
            if (is_array($file_attachments)) {
404
                $i = 0;
405
                foreach ($file_attachments as $file_attach) {
406
                    if ($file_attach['error'] == 0) {
407
                        self::saveMessageAttachmentFile(
408
                            $file_attach,
409
                            isset($file_comments[$i]) ? $file_comments[$i] : null,
410
                            $messageId,
411
                            null,
412
                            $receiver_user_id,
413
                            $group_id
414
                        );
415
                    }
416
                    $i++;
417
                }
418
            }
419
420
            if (empty($group_id)) {
421
                // message in outbox for user friend or group
422
                $params = [
423
                    'user_sender_id' => $user_sender_id,
424
                    'user_receiver_id' => $receiver_user_id,
425
                    'msg_status' => MESSAGE_STATUS_OUTBOX,
426
                    'send_date' => $now,
427
                    'title' => $subject,
428
                    'content' => $content,
429
                    'group_id' => $group_id,
430
                    'parent_id' => $parent_id,
431
                    'update_date' => $now
432
                ];
433
                $outbox_last_id = Database::insert($table, $params);
434
435
                // save attachment file for outbox messages
436
                if (is_array($file_attachments)) {
437
                    $o = 0;
438
                    foreach ($file_attachments as $file_attach) {
439
                        if ($file_attach['error'] == 0) {
440
                            $comment = isset($file_comments[$o]) ? $file_comments[$o] : '';
441
                            self::saveMessageAttachmentFile(
442
                                $file_attach,
443
                                $comment,
444
                                $outbox_last_id,
445
                                $user_sender_id
446
                            );
447
                        }
448
                        $o++;
449
                    }
450
                }
451
            }
452
453
            // Load user settings.
454
            $notification = new Notification();
455
            $sender_info = api_get_user_info($user_sender_id);
456
457
            // add file attachment additional attributes
458
            foreach ($file_attachments as $index => $file_attach) {
459
                $file_attachments[$index]['path'] = $file_attach['tmp_name'];
460
                $file_attachments[$index]['filename'] = $file_attach['name'];
461
            }
462
463
            if (empty($group_id)) {
464
                $type = Notification::NOTIFICATION_TYPE_MESSAGE;
465
                if ($directMessage) {
466
                    $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
467
                }
468
                $notification->saveNotification(
469
                    $messageId,
0 ignored issues
show
Bug introduced by
It seems like $messageId can also be of type false; however, parameter $messageId of Notification::saveNotification() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

469
                    /** @scrutinizer ignore-type */ $messageId,
Loading history...
470
                    $type,
471
                    [$receiver_user_id],
472
                    $subject,
473
                    $content,
474
                    $sender_info,
475
                    $file_attachments,
476
                    $smsParameters
477
                );
478
            } else {
479
                $usergroup = new UserGroup();
480
                $group_info = $usergroup->get($group_id);
481
                $group_info['topic_id'] = $topic_id;
482
                $group_info['msg_id'] = $messageId;
483
484
                $user_list = $usergroup->get_users_by_group(
485
                    $group_id,
486
                    false,
487
                    [],
488
                    0,
489
                    1000
490
                );
491
492
                // Adding more sense to the message group
493
                $subject = sprintf(get_lang('ThereIsANewMessageInTheGroupX'), $group_info['name']);
494
                $new_user_list = [];
495
                foreach ($user_list as $user_data) {
496
                    $new_user_list[] = $user_data['id'];
497
                }
498
                $group_info = [
499
                    'group_info' => $group_info,
500
                    'user_info' => $sender_info,
501
                ];
502
                $notification->saveNotification(
503
                    $messageId,
504
                    Notification::NOTIFICATION_TYPE_GROUP,
505
                    $new_user_list,
506
                    $subject,
507
                    $content,
508
                    $group_info,
509
                    $file_attachments,
510
                    $smsParameters
511
                );
512
            }
513
514
            return $messageId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $messageId also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
515
        }
516
517
        return false;
518
    }
519
520
    /**
521
     * @param int $receiver_user_id
522
     * @param int $subject
523
     * @param string $message
524
     * @param int $sender_id
525
     * @param bool $sendCopyToDrhUsers send copy to related DRH users
526
     * @param bool $directMessage
527
     * @param array $smsParameters
528
     * @param bool $uploadFiles Do not upload files using the MessageManager class
529
     * @param bool $attachmentList
530
     *
531
     * @return bool
532
     */
533
    public static function send_message_simple(
534
        $receiver_user_id,
535
        $subject,
536
        $message,
537
        $sender_id = 0,
538
        $sendCopyToDrhUsers = false,
539
        $directMessage = false,
540
        $smsParameters = [],
541
        $uploadFiles = true,
542
        $attachmentList = []
543
    ) {
544
        $files = $_FILES ? $_FILES : [];
545
        if ($uploadFiles === false) {
546
            $files = [];
547
        }
548
        // $attachmentList must have: tmp_name, name, size keys
549
        if (!empty($attachmentList)) {
550
            $files = $attachmentList;
551
        }
552
        $result = self::send_message(
553
            $receiver_user_id,
554
            $subject,
555
            $message,
556
            $files,
557
            [],
558
            null,
559
            null,
560
            null,
561
            null,
562
            $sender_id,
563
            $directMessage,
564
            0,
565
            $smsParameters
566
        );
567
568
        if ($sendCopyToDrhUsers) {
569
            $userInfo = api_get_user_info($receiver_user_id);
570
            $drhList = UserManager::getDrhListFromUser($receiver_user_id);
571
            if (!empty($drhList)) {
572
                foreach ($drhList as $drhInfo) {
573
                    $message = sprintf(
574
                        get_lang('CopyOfMessageSentToXUser'),
575
                        $userInfo['complete_name']
576
                    ).' <br />'.$message;
577
578
                    self::send_message_simple(
579
                        $drhInfo['user_id'],
580
                        $subject,
581
                        $message,
582
                        $sender_id,
583
                        false,
584
                        $directMessage
585
                    );
586
                }
587
            }
588
        }
589
590
        return $result;
591
    }
592
593
    /**
594
     * Update parent ids for other receiver user from current message in groups
595
     * @author Christian Fasanando Flores
596
     * @param  int $parent_id
597
     * @param  int $receiver_user_id
598
     * @param  int $messageId
599
     * @return void
600
     */
601
    public static function update_parent_ids_from_reply(
602
        $parent_id,
603
        $receiver_user_id,
604
        $messageId
605
    ) {
606
        $table = Database::get_main_table(TABLE_MESSAGE);
607
        $parent_id = intval($parent_id);
608
        $receiver_user_id = intval($receiver_user_id);
609
        $messageId = intval($messageId);
610
611
        // first get data from message id (parent)
612
        $sql = "SELECT * FROM $table WHERE id = '$parent_id'";
613
        $rs_message = Database::query($sql);
614
        $row_message = Database::fetch_array($rs_message);
615
616
        // get message id from data found early for other receiver user
617
        $sql = "SELECT id FROM $table
618
                WHERE
619
                    user_sender_id ='{$row_message['user_sender_id']}' AND
620
                    title='{$row_message['title']}' AND
621
                    content='{$row_message['content']}' AND
622
                    group_id='{$row_message['group_id']}' AND
623
                    user_receiver_id='$receiver_user_id'";
624
        $result = Database::query($sql);
625
        $row = Database::fetch_array($result);
626
627
        // update parent_id for other user receiver
628
        $sql = "UPDATE $table SET parent_id = ".$row['id']."
629
                WHERE id = $messageId";
630
        Database::query($sql);
631
    }
632
633
    /**
634
     * @param int $user_receiver_id
635
     * @param int $id
636
     * @return bool
637
     */
638
    public static function delete_message_by_user_receiver($user_receiver_id, $id)
639
    {
640
        $table = Database::get_main_table(TABLE_MESSAGE);
641
        if ($id != strval(intval($id))) {
642
            return false;
643
        }
644
        $user_receiver_id = intval($user_receiver_id);
645
        $id = intval($id);
646
        $sql = "SELECT * FROM $table
647
                WHERE id = ".$id." AND msg_status <>".MESSAGE_STATUS_OUTBOX;
648
        $rs = Database::query($sql);
649
650
        if (Database::num_rows($rs) > 0) {
651
            // delete attachment file
652
            self::delete_message_attachment_file($id, $user_receiver_id);
653
            // delete message
654
            $query = "UPDATE $table 
655
                      SET msg_status = ".MESSAGE_STATUS_DELETED."
656
                      WHERE 
657
                        user_receiver_id=".$user_receiver_id." AND 
658
                        id = ".$id;
659
            Database::query($query);
660
661
            return true;
662
        } else {
663
            return false;
664
        }
665
    }
666
667
    /**
668
     * Set status deleted
669
     * @author Isaac FLores Paz <[email protected]>
670
     * @param  int
671
     * @param  int
672
     * @return bool
673
     */
674
    public static function delete_message_by_user_sender($user_sender_id, $id)
675
    {
676
        if ($id != strval(intval($id))) {
677
            return false;
678
        }
679
680
        $table = Database::get_main_table(TABLE_MESSAGE);
681
682
        $id = intval($id);
683
        $user_sender_id = intval($user_sender_id);
684
685
        $sql = "SELECT * FROM $table WHERE id='$id'";
686
        $rs = Database::query($sql);
687
688
        if (Database::num_rows($rs) > 0) {
689
            // delete attachment file
690
            self::delete_message_attachment_file($id, $user_sender_id);
691
            // delete message
692
            $sql = "UPDATE $table 
693
                    SET msg_status = ".MESSAGE_STATUS_DELETED."
694
                    WHERE user_sender_id='$user_sender_id' AND id='$id'";
695
            Database::query($sql);
696
697
            return true;
698
        }
699
700
        return false;
701
    }
702
703
    /**
704
     * Saves a message attachment files
705
     * @param  array $file_attach $_FILES['name']
706
     * @param  string    a comment about the uploaded file
707
     * @param  int        message id
708
     * @param  int        receiver user id (optional)
709
     * @param  int        sender user id (optional)
710
     * @param  int        group id (optional)
711
     */
712
    public static function saveMessageAttachmentFile(
713
        $file_attach,
714
        $file_comment,
715
        $message_id,
716
        $receiver_user_id = 0,
717
        $sender_user_id = 0,
718
        $group_id = 0
719
    ) {
720
        $tbl_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
721
722
        // Try to add an extension to the file if it hasn't one
723
        $type = isset($file_attach['type']) ? $file_attach['type'] : '';
724
        if (empty($type)) {
725
            $type = DocumentManager::file_get_mime_type($file_attach['name']);
726
        }
727
        $new_file_name = add_ext_on_mime(stripslashes($file_attach['name']), $type);
728
729
        // user's file name
730
        $file_name = $file_attach['name'];
731
        if (!filter_extension($new_file_name)) {
732
            Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
733
        } else {
734
            $new_file_name = uniqid('');
735
            if (!empty($receiver_user_id)) {
736
                $message_user_id = $receiver_user_id;
737
            } else {
738
                $message_user_id = $sender_user_id;
739
            }
740
741
            // User-reserved directory where photos have to be placed.*
742
            $userGroup = new UserGroup();
743
            if (!empty($group_id)) {
744
                $path_user_info = $userGroup->get_group_picture_path_by_id(
745
                    $group_id,
746
                    'system',
747
                    true
748
                );
749
            } else {
750
                $path_user_info['dir'] = UserManager::getUserPathById($message_user_id, 'system');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$path_user_info was never initialized. Although not strictly required by PHP, it is generally a good practice to add $path_user_info = array(); before regardless.
Loading history...
751
            }
752
753
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
754
            // If this directory does not exist - we create it.
755
            if (!file_exists($path_message_attach)) {
756
                @mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

756
                /** @scrutinizer ignore-unhandled */ @mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
757
            }
758
759
            $new_path = $path_message_attach.$new_file_name;
760
761
            if (is_uploaded_file($file_attach['tmp_name'])) {
762
                @copy($file_attach['tmp_name'], $new_path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for copy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

762
                /** @scrutinizer ignore-unhandled */ @copy($file_attach['tmp_name'], $new_path);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
763
            } else {
764
                // 'tmp_name' can be set by the ticket
765
                if (file_exists($file_attach['tmp_name'])) {
766
                    @copy($file_attach['tmp_name'], $new_path);
767
                }
768
            }
769
770
            // Storing the attachments if any
771
            $params = [
772
                'filename' => $file_name,
773
                'comment' => $file_comment,
774
                'path' => $new_file_name,
775
                'message_id' => $message_id,
776
                'size' => $file_attach['size']
777
            ];
778
            Database::insert($tbl_message_attach, $params);
779
        }
780
    }
781
782
    /**
783
     * Delete message attachment files (logically updating the row with a suffix _DELETE_id)
784
     * @param  int    message id
785
     * @param  int    message user id (receiver user id or sender user id)
786
     * @param  int    group id (optional)
787
     */
788
    public static function delete_message_attachment_file(
789
        $message_id,
790
        $message_uid,
791
        $group_id = 0
792
    ) {
793
        $message_id = intval($message_id);
794
        $message_uid = intval($message_uid);
795
        $table_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
796
797
        $sql = "SELECT * FROM $table_message_attach 
798
                WHERE message_id = '$message_id'";
799
        $rs = Database::query($sql);
800
        while ($row = Database::fetch_array($rs)) {
801
            $path = $row['path'];
802
            $attach_id = $row['id'];
803
            $new_path = $path.'_DELETED_'.$attach_id;
804
805
            if (!empty($group_id)) {
806
                $userGroup = new UserGroup();
807
                $path_user_info = $userGroup->get_group_picture_path_by_id(
808
                    $group_id,
809
                    'system',
810
                    true
811
                );
812
            } else {
813
                $path_user_info['dir'] = UserManager::getUserPathById(
814
                    $message_uid,
815
                    'system'
816
                );
817
            }
818
819
            $path_message_attach = $path_user_info['dir'].'message_attachments/';
820
            if (is_file($path_message_attach.$path)) {
821
                if (rename($path_message_attach.$path, $path_message_attach.$new_path)) {
822
                    $sql = "UPDATE $table_message_attach set path='$new_path'
823
                            WHERE id ='$attach_id'";
824
                    Database::query($sql);
825
                }
826
            }
827
        }
828
    }
829
830
    /**
831
     * update messages by user id and message id
832
     * @param  int $user_id
833
     * @param  int $message_id
834
     * @return bool
835
     */
836
    public static function update_message($user_id, $message_id)
837
    {
838
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
839
            return false;
840
        }
841
842
        $table = Database::get_main_table(TABLE_MESSAGE);
843
        $sql = "UPDATE $table SET 
844
                    msg_status = '".MESSAGE_STATUS_NEW."'
845
                WHERE
846
                    msg_status <> ".MESSAGE_STATUS_OUTBOX." AND
847
                    user_receiver_id = ".intval($user_id)." AND
848
                    id = '".intval($message_id)."'";
849
        Database::query($sql);
850
        return true;
851
    }
852
853
    /**
854
     * @param int $user_id
855
     * @param int $message_id
856
     * @param string $type
857
     * @return bool
858
     */
859
    public static function update_message_status($user_id, $message_id, $type)
860
    {
861
        $type = intval($type);
862
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
863
            return false;
864
        }
865
        $table_message = Database::get_main_table(TABLE_MESSAGE);
866
        $sql = "UPDATE $table_message SET
867
                    msg_status = '$type'
868
                WHERE
869
                    user_receiver_id = ".intval($user_id)." AND
870
                    id = '".intval($message_id)."'";
871
        Database::query($sql);
872
    }
873
874
    /**
875
     * get messages by user id and message id
876
     * @param  int $user_id
877
     * @param  int $message_id
878
     * @return array
879
     */
880
    public static function get_message_by_user($user_id, $message_id)
881
    {
882
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
883
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
884
        }
885
        $table = Database::get_main_table(TABLE_MESSAGE);
886
        $query = "SELECT * FROM $table
887
                  WHERE user_receiver_id=".intval($user_id)." AND id='".intval($message_id)."'";
888
        $result = Database::query($query);
889
890
        return $row = Database::fetch_array($result);
891
    }
892
893
    /**
894
     * get messages by group id
895
     * @param  int $group_id group id
896
     * @return array
897
     */
898
    public static function get_messages_by_group($group_id)
899
    {
900
        if ($group_id != strval(intval($group_id))) {
901
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
902
        }
903
904
        $table = Database::get_main_table(TABLE_MESSAGE);
905
        $group_id = intval($group_id);
906
        $sql = "SELECT * FROM $table
907
                WHERE
908
                    group_id= $group_id AND
909
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
910
                ORDER BY id";
911
        $rs = Database::query($sql);
912
        $data = [];
913
        if (Database::num_rows($rs) > 0) {
914
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
915
                $data[] = $row;
916
            }
917
        }
918
        return $data;
919
    }
920
921
    /**
922
     * get messages by group id
923
     * @param  int $group_id
924
     * @param int $message_id
925
     * @return array
926
     */
927
    public static function get_messages_by_group_by_message($group_id, $message_id)
928
    {
929
        if ($group_id != strval(intval($group_id))) {
930
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
931
        }
932
        $table = Database::get_main_table(TABLE_MESSAGE);
933
        $group_id = intval($group_id);
934
        $sql = "SELECT * FROM $table
935
                WHERE
936
                    group_id = $group_id AND
937
                    msg_status NOT IN ('".MESSAGE_STATUS_OUTBOX."', '".MESSAGE_STATUS_DELETED."')
938
                ORDER BY id ";
939
940
        $rs = Database::query($sql);
941
        $data = [];
942
        $parents = [];
943
        if (Database::num_rows($rs) > 0) {
944
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
945
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
946
                    $parents[] = $row['id'];
947
                    $data[] = $row;
948
                }
949
            }
950
        }
951
952
        return $data;
953
    }
954
955
    /**
956
     * Get messages by parent id optionally with limit
957
     * @param  int        parent id
958
     * @param  int        group id (optional)
959
     * @param  int        offset (optional)
960
     * @param  int        limit (optional)
961
     * @return array
962
     */
963
    public static function get_messages_by_parent($parent_id, $group_id = 0, $offset = 0, $limit = 0)
964
    {
965
        if ($parent_id != strval(intval($parent_id))) {
966
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
967
        }
968
        $table = Database::get_main_table(TABLE_MESSAGE);
969
        $parent_id = intval($parent_id);
970
        $condition_group_id = '';
971
        if (!empty($group_id)) {
972
            $group_id = intval($group_id);
973
            $condition_group_id = " AND group_id = '$group_id' ";
974
        }
975
976
        $condition_limit = '';
977
        if ($offset && $limit) {
978
            $offset = ($offset - 1) * $limit;
979
            $condition_limit = " LIMIT $offset,$limit ";
980
        }
981
982
        $sql = "SELECT * FROM $table
983
                WHERE
984
                    parent_id='$parent_id' AND
985
                    msg_status <> ".MESSAGE_STATUS_OUTBOX."
986
                    $condition_group_id
987
                ORDER BY send_date DESC $condition_limit ";
988
        $rs = Database::query($sql);
989
        $data = [];
990
        if (Database::num_rows($rs) > 0) {
991
            while ($row = Database::fetch_array($rs)) {
992
                $data[$row['id']] = $row;
993
            }
994
        }
995
996
        return $data;
997
    }
998
999
    /**
1000
     * Gets information about messages sent
1001
     * @param  integer
1002
     * @param  integer
1003
     * @param  string
1004
     * @return array
1005
     */
1006
    public static function get_message_data_sent(
1007
        $from,
1008
        $number_of_items,
1009
        $column,
1010
        $direction
1011
    ) {
1012
        $from = intval($from);
1013
        $number_of_items = intval($number_of_items);
1014
        if (!isset($direction)) {
1015
            $column = 2;
1016
            $direction = 'DESC';
1017
        } else {
1018
            $column = intval($column);
1019
            if (!in_array($direction, ['ASC', 'DESC'])) {
1020
                $direction = 'ASC';
1021
            }
1022
        }
1023
1024
        if (!in_array($column, [0, 1, 2])) {
1025
            $column = 2;
1026
        }
1027
        $table = Database::get_main_table(TABLE_MESSAGE);
1028
        $request = api_is_xml_http_request();
1029
        $keyword = Session::read('message_sent_search_keyword');
1030
        $keywordCondition = '';
1031
        if (!empty($keyword)) {
1032
            $keyword = Database::escape_string($keyword);
1033
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1034
        }
1035
1036
        $sql = "SELECT
1037
                    id as col0, 
1038
                    title as col1, 
1039
                    send_date as col2, 
1040
                    user_receiver_id, 
1041
                    msg_status,
1042
                    user_sender_id
1043
                FROM $table
1044
                WHERE
1045
                    user_sender_id = ".api_get_user_id()." AND
1046
                    msg_status = ".MESSAGE_STATUS_OUTBOX."
1047
                    $keywordCondition
1048
                ORDER BY col$column $direction
1049
                LIMIT $from, $number_of_items";
1050
        $result = Database::query($sql);
1051
        $i = 0;
1052
        $message_list = [];
1053
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1054
            $messageId = $row['col0'];
1055
            $title = $row['col1'];
1056
            $sendDate = $row['col2'];
1057
            $status = $row['msg_status'];
1058
            $senderId = $row['user_sender_id'];
1059
1060
            if ($request === true) {
1061
                $message[0] = '<input type="checkbox" value='.$messageId.' name="out[]">';
1062
            } else {
1063
                $message[0] = $messageId;
1064
            }
1065
1066
            $class = 'class = "read"';
1067
            $title = Security::remove_XSS($title);
1068
            $userInfo = api_get_user_info($senderId);
1069
            if ($request === true) {
1070
                $message[1] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.$userInfo['complete_name_with_username'].'</a>';
1071
                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace("\\", "", $title).'</a>';
1072
                //date stays the same
1073
                $message[3] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1074
                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(get_lang('DeleteMessage')).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
1075
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1076
            } else {
1077
                $message[1] = '<a '.$class.' onclick="show_sent_message('.$messageId.')" href="../messages/view_message.php?id_send='.$messageId.'">'.$title.'</a><br />'.$userInfo['complete_name_with_username'];
1078
                $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
1079
                $message[3] = '<a title="'.addslashes(get_lang('DeleteMessage')).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage')))."'".')) return false;" >'.
1080
                    Display::returnFontAwesomeIcon('trash', 2).'</a>';
1081
            }
1082
1083
            $message_list[] = $message;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
1084
            $i++;
1085
        }
1086
1087
        return $message_list;
1088
    }
1089
1090
    /**
1091
     * Gets information about number messages sent
1092
     * @author Isaac FLores Paz <[email protected]>
1093
     * @param void
1094
     * @return integer
1095
     */
1096
    public static function getNumberOfMessagesSent()
1097
    {
1098
        $table = Database::get_main_table(TABLE_MESSAGE);
1099
        $keyword = Session::read('message_sent_search_keyword');
1100
        $keywordCondition = '';
1101
        if (!empty($keyword)) {
1102
            $keyword = Database::escape_string($keyword);
1103
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
1104
        }
1105
1106
        $sql = "SELECT COUNT(id) as number_messages 
1107
                FROM $table
1108
                WHERE
1109
                  msg_status = ".MESSAGE_STATUS_OUTBOX." AND
1110
                  user_sender_id = ".api_get_user_id()."
1111
                  $keywordCondition
1112
                ";
1113
        $result = Database::query($sql);
1114
        $result = Database::fetch_array($result);
1115
1116
        return $result['number_messages'];
1117
    }
1118
1119
    /**
1120
     * display message box in the inbox
1121
     * @param int the message id
1122
     * @param string inbox or outbox strings are available
1123
     * @todo replace numbers with letters in the $row array pff...
1124
     * @return string html with the message content
1125
     */
1126
    public static function showMessageBox($messageId, $source = 'inbox')
1127
    {
1128
        $table = Database::get_main_table(TABLE_MESSAGE);
1129
        $messageId = intval($messageId);
1130
1131
        if ($source == 'outbox') {
1132
            if (isset($messageId) && is_numeric($messageId)) {
1133
                $query = "SELECT * FROM $table
1134
                          WHERE
1135
                            user_sender_id = ".api_get_user_id()." AND
1136
                            id = ".$messageId." AND
1137
                            msg_status = ".MESSAGE_STATUS_OUTBOX;
1138
                $result = Database::query($query);
1139
            }
1140
        } else {
1141
            if (is_numeric($messageId) && !empty($messageId)) {
1142
                $query = "UPDATE $table SET
1143
                          msg_status = '".MESSAGE_STATUS_NEW."'
1144
                          WHERE
1145
                            user_receiver_id=".api_get_user_id()." AND
1146
                            id='".$messageId."'";
1147
                Database::query($query);
1148
1149
                $query = "SELECT * FROM $table
1150
                          WHERE
1151
                            msg_status<> ".MESSAGE_STATUS_OUTBOX." AND
1152
                            user_receiver_id=".api_get_user_id()." AND
1153
                            id='".$messageId."'";
1154
                $result = Database::query($query);
1155
            }
1156
        }
1157
        $row = Database::fetch_array($result, 'ASSOC');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
1158
        $user_sender_id = $row['user_sender_id'];
1159
1160
        // get file attachments by message id
1161
        $files_attachments = self::get_links_message_attachment_files(
1162
            $messageId,
1163
            $source
1164
        );
1165
1166
        $row['content'] = str_replace('</br>', '<br />', $row['content']);
1167
        $title = Security::remove_XSS($row['title'], STUDENT, true);
1168
        $content = Security::remove_XSS($row['content'], STUDENT, true);
1169
1170
        $name = get_lang('UnknownUser');
1171
        $fromUser = api_get_user_info($user_sender_id);
1172
        $userImage = '';
1173
        if (!empty($user_sender_id) && !empty($fromUser)) {
1174
            $name = $fromUser['complete_name_with_username'];
1175
            $userImage = Display::img(
1176
                $fromUser['avatar_small'],
1177
                $name,
1178
                ['title' => $name, 'class' => 'img-responsive img-circle', 'style' => 'max-width:35px'],
1179
                false
1180
            );
1181
        }
1182
1183
        $message_content = Display::page_subheader(str_replace("\\", "", $title));
1184
1185
        $receiverUserInfo = [];
1186
        if (!empty($row['user_receiver_id'])) {
1187
            $receiverUserInfo = api_get_user_info($row['user_receiver_id']);
1188
        }
1189
1190
        $message_content .= '<tr>';
1191
        if (api_get_setting('allow_social_tool') == 'true') {
1192
            $message_content .= '<div class="row">';
1193
            if ($source == 'outbox') {
1194
                $message_content .= '<div class="col-md-12">';
1195
                $message_content .= '<ul class="list-message">';
1196
                $message_content .= '<li>'.$userImage.'</li>';
1197
                $message_content .= '<li>'.$name.'&nbsp;';
1198
                if (!empty($receiverUserInfo)) {
1199
                    $message_content .= api_strtolower(
1200
                            get_lang('To')
1201
                        ).'&nbsp;<b>'.$receiverUserInfo['complete_name_with_username'].'</b></li>';
1202
                } else {
1203
                    $message_content .= api_strtolower(get_lang('To')).'&nbsp;<b>-</b></li>';
1204
                }
1205
1206
                $message_content .= '<li>'.Display::dateToStringAgoAndLongDate($row['send_date']).'</li>';
1207
                $message_content .= '</ul>';
1208
                $message_content .= '</div>';
1209
            } else {
1210
                $message_content .= '<div class="col-md-12">';
1211
                $message_content .= '<ul class="list-message">';
1212
                if (!empty($user_sender_id)) {
1213
                    $message_content .= '<li>'.$userImage.'</li>';
1214
                    $message_content .= '<li><a href="'.api_get_path(
1215
                            WEB_PATH
1216
                        ).'main/social/profile.php?u='.$user_sender_id.'">'.$name.'</a>';
1217
                } else {
1218
                    $message_content .= '<li>'.$name;
1219
                }
1220
1221
                $message_content .= '&nbsp;'.api_strtolower(get_lang('To')).'&nbsp;'.get_lang('Me');
1222
                $message_content .= '<li>'.Display::dateToStringAgoAndLongDate($row['send_date']).'</li>';
1223
                $message_content .= '</ul>';
1224
                $message_content .= '</div>';
1225
            }
1226
            $message_content .= '</div>';
1227
        } else {
1228
            if ($source == 'outbox') {
1229
                $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1230
                    $receiverUserInfo['complete_name_with_username'].'</b>';
1231
            } else {
1232
                $message_content .= get_lang('From').':&nbsp;'.$name.'</b> '.api_strtolower(get_lang('To')).' <b>'.
1233
                    get_lang('Me').'</b>';
1234
            }
1235
        }
1236
1237
        $message_content .= '		        
1238
		        <hr style="color:#ddd" />
1239
		        <table width="100%">
1240
		            <tr>
1241
		              <td valign=top class="view-message-content">'.str_replace("\\", "", $content).'</td>
1242
		            </tr>
1243
		        </table>
1244
		        <div id="message-attach">'.(!empty($files_attachments) ? implode('<br />', $files_attachments) : '').'</div>
1245
		        <div style="padding: 15px 0px 5px 0px">';
1246
        $social_link = '';
1247
        if (isset($_GET['f']) && $_GET['f'] == 'social') {
1248
            $social_link = 'f=social';
1249
        }
1250
        if ($source == 'outbox') {
1251
            $message_content .= '<a href="outbox.php?'.$social_link.'">'.
1252
                Display::return_icon('back.png', get_lang('ReturnToOutbox')).'</a> &nbsp';
1253
        } else {
1254
            $message_content .= '<a href="inbox.php?'.$social_link.'">'.
1255
                Display::return_icon('back.png', get_lang('ReturnToInbox')).'</a> &nbsp';
1256
            $message_content .= '<a href="new_message.php?re_id='.$messageId.'&'.$social_link.'">'.
1257
                Display::return_icon('message_reply.png', get_lang('ReplyToMessage')).'</a> &nbsp';
1258
        }
1259
        $message_content .= '<a href="inbox.php?action=deleteone&id='.$messageId.'&'.$social_link.'" >'.
1260
            Display::return_icon('delete.png', get_lang('DeleteMessage')).'</a>&nbsp';
1261
1262
        $message_content .= '</div></td>
1263
		      <td width=10></td>
1264
		    </tr>
1265
		</table>';
1266
1267
        return $message_content;
1268
    }
1269
1270
    /**
1271
     * get user id by user email
1272
     * @param string $user_email
1273
     * @return int user id
1274
     */
1275
    public static function get_user_id_by_email($user_email)
1276
    {
1277
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1278
        $sql = 'SELECT user_id FROM '.$tbl_user.'
1279
                WHERE email="'.Database::escape_string($user_email).'";';
1280
        $rs = Database::query($sql);
1281
        $row = Database::fetch_array($rs, 'ASSOC');
1282
        if (isset($row['user_id'])) {
1283
            return $row['user_id'];
1284
        } else {
1285
            return null;
1286
        }
1287
    }
1288
1289
    /**
1290
     * Displays messages of a group with nested view
1291
     *
1292
     * @param int $group_id
1293
     * @return string
1294
     */
1295
    public static function display_messages_for_group($group_id)
1296
    {
1297
        global $my_group_role;
1298
1299
        $rows = self::get_messages_by_group($group_id);
1300
        $topics_per_page = 10;
1301
        $html_messages = '';
1302
        $query_vars = ['id' => $group_id, 'topics_page_nr' => 0];
1303
1304
        if (is_array($rows) && count($rows) > 0) {
1305
            // prepare array for topics with its items
1306
            $topics = [];
1307
            $x = 0;
1308
            foreach ($rows as $index => $value) {
1309
                if (empty($value['parent_id'])) {
1310
                    $topics[$value['id']] = $value;
1311
                }
1312
            }
1313
1314
            $new_topics = [];
1315
1316
            foreach ($topics as $id => $value) {
1317
                $rows = null;
1318
                $rows = self::get_messages_by_group_by_message($group_id, $value['id']);
1319
                if (!empty($rows)) {
1320
                    $count = count(self::calculate_children($rows, $value['id']));
1321
                } else {
1322
                    $count = 0;
1323
                }
1324
                $value['count'] = $count;
1325
                $new_topics[$id] = $value;
1326
            }
1327
1328
            $array_html = [];
1329
            foreach ($new_topics as $index => $topic) {
1330
                $html = '';
1331
                // topics
1332
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1333
                $name = $user_sender_info['complete_name'];
1334
                $html .= '<div class="groups-messages">';
1335
                $html .= '<div class="row">';
1336
1337
                $items = $topic['count'];
1338
                $reply_label = ($items == 1) ? get_lang('GroupReply') : get_lang('GroupReplies');
1339
                $label = '<i class="fa fa-envelope"></i> '.$items.' '.$reply_label;
1340
                $topic['title'] = trim($topic['title']);
1341
1342
                if (empty($topic['title'])) {
1343
                    $topic['title'] = get_lang('Untitled');
1344
                }
1345
1346
                $html .= '<div class="col-xs-8 col-md-10">';
1347
                $html .= Display::tag(
1348
                    'h4',
1349
                    Display::url(
1350
                        Security::remove_XSS($topic['title'], STUDENT, true),
1351
                        api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$group_id.'&topic_id='.$topic['id']
1352
                    ),
1353
                    ['class' => 'title']
1354
                );
1355
                $actions = '';
1356
                if ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1357
                    $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1358
                ) {
1359
                    $actions = '<br />'.Display::url(
1360
                            get_lang('Delete'),
1361
                            api_get_path(
1362
                                WEB_CODE_PATH
1363
                            ).'social/group_topics.php?action=delete&id='.$group_id.'&topic_id='.$topic['id'],
1364
                            ['class' => 'btn btn-default']
1365
                        );
1366
                }
1367
1368
                $date = '';
1369
                if ($topic['send_date'] != $topic['update_date']) {
1370
                    if (!empty($topic['update_date'])) {
1371
                        $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1372
                                'LastUpdate'
1373
                            ).' '.Display::dateToStringAgoAndLongDate($topic['update_date']);
1374
                    }
1375
                } else {
1376
                    $date .= '<i class="fa fa-calendar"></i> '.get_lang(
1377
                            'Created'
1378
                        ).' '.Display::dateToStringAgoAndLongDate($topic['send_date']);
1379
                }
1380
                $html .= '<div class="date">'.$label.' - '.$date.$actions.'</div>';
1381
                $html .= '</div>';
1382
1383
                $image = $user_sender_info['avatar'];
1384
1385
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="'.$image.'" alt="'.$name.'"  width="64" height="64" title="'.$name.'" /></div>';
1386
                $user_info .= '<div class="name"><a href="'.api_get_path(
1387
                        WEB_PATH
1388
                    ).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp;</a></div>';
1389
1390
                $html .= '<div class="col-xs-4 col-md-2">';
1391
                $html .= $user_info;
1392
                $html .= '</div>';
1393
                $html .= '</div>';
1394
                $html .= '</div>';
1395
1396
                $array_html[] = [$html];
1397
            }
1398
1399
            // grids for items and topics  with paginations
1400
            $html_messages .= Display::return_sortable_grid(
1401
                'topics',
1402
                [],
1403
                $array_html,
1404
                [
1405
                    'hide_navigation' => false,
1406
                    'per_page' => $topics_per_page
1407
                ],
1408
                $query_vars,
1409
                false,
1410
                [true, true, true, false],
1411
                false
1412
            );
1413
        }
1414
1415
        return $html_messages;
1416
    }
1417
1418
    /**
1419
     * Displays messages of a group with nested view
1420
     * @param $group_id
1421
     * @param $topic_id
1422
     * @param $is_member
1423
     * @param $messageId
1424
     * @return string
1425
     */
1426
    public static function display_message_for_group($group_id, $topic_id, $is_member, $messageId)
0 ignored issues
show
Unused Code introduced by
The parameter $is_member is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1426
    public static function display_message_for_group($group_id, $topic_id, /** @scrutinizer ignore-unused */ $is_member, $messageId)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $messageId is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1426
    public static function display_message_for_group($group_id, $topic_id, $is_member, /** @scrutinizer ignore-unused */ $messageId)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1427
    {
1428
        global $my_group_role;
1429
        $main_message = self::get_message_by_id($topic_id);
1430
        if (empty($main_message)) {
1431
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
1432
        }
1433
        $rows = self::get_messages_by_group_by_message($group_id, $topic_id);
1434
        $rows = self::calculate_children($rows, $topic_id);
1435
        $current_user_id = api_get_user_id();
1436
1437
        $items_per_page = 50;
1438
        $query_vars = ['id' => $group_id, 'topic_id' => $topic_id, 'topics_page_nr' => 0];
1439
1440
        // Main message
1441
        $links = '';
1442
        $main_content = '';
1443
        $html = '';
1444
        $items_page_nr = null;
1445
1446
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1447
        $files_attachments = self::get_links_message_attachment_files($main_message['id']);
1448
        $name = $user_sender_info['complete_name'];
1449
1450
        $topic_page_nr = isset($_GET['topics_page_nr']) ? intval($_GET['topics_page_nr']) : null;
1451
1452
        $links .= '<div class="pull-right">';
1453
        $links .= '<div class="btn-group btn-group-sm">';
1454
1455
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1456
                $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1457
            $main_message['user_sender_id'] == $current_user_id
1458
        ) {
1459
            $urlEdit = api_get_path(WEB_CODE_PATH);
1460
            $urlEdit .= 'social/message_for_group_form.inc.php?';
1461
            $urlEdit .= http_build_query(
1462
                [
1463
                    'user_friend' => $current_user_id,
1464
                    'group_id' => $group_id,
1465
                    'message_id' => $main_message['id'],
1466
                    'action' => 'edit_message_group',
1467
                    'anchor_topic' => 'topic_'.$main_message['id'],
1468
                    'topics_page_nr' => $topic_page_nr,
1469
                    'items_page_nr' => $items_page_nr,
1470
                    'topic_id' => $main_message['id']
1471
                ]
1472
            );
1473
1474
            $links .= Display::url(
1475
                Display::returnFontAwesomeIcon('pencil'),
1476
                $urlEdit,
1477
                [
1478
                    'class' => 'btn btn-default ajax',
1479
                    'title' => get_lang('Edit'),
1480
                    'data-title' => get_lang('Edit'),
1481
                    'data-size' => 'lg'
1482
                ]
1483
            );
1484
        }
1485
1486
        $urlReply = api_get_path(WEB_CODE_PATH);
1487
        $urlReply .= 'social/message_for_group_form.inc.php?';
1488
        $urlReply .= http_build_query(
1489
            [
1490
                'user_friend' => api_get_user_id(),
1491
                'group_id' => $group_id,
1492
                'message_id' => $main_message['id'],
1493
                'action' => 'reply_message_group',
1494
                'anchor_topic' => 'topic_'.$main_message['id'],
1495
                'topics_page_nr' => $topic_page_nr,
1496
                'topic_id' => $main_message['id']
1497
            ]
1498
        );
1499
1500
        $links .= Display::url(
1501
            Display::returnFontAwesomeIcon('commenting'),
1502
            $urlReply,
1503
            [
1504
                'class' => 'btn btn-default ajax',
1505
                'title' => get_lang('Reply'),
1506
                'data-title' => get_lang('Reply'),
1507
                'data-size' => 'lg'
1508
            ]
1509
        );
1510
1511
        if (api_is_platform_admin()) {
1512
            $links .= Display::url(
1513
                Display::returnFontAwesomeIcon('trash'),
1514
                'group_topics.php?action=delete&id='.$group_id.'&topic_id='.$topic_id,
1515
                [
1516
                    'class' => 'btn btn-default'
1517
                ]
1518
            );
1519
        }
1520
1521
        $links .= '</div>';
1522
        $links .= '</div>';
1523
1524
        $title = '<h4>'.Security::remove_XSS($main_message['title'], STUDENT, true).$links.'</h4>';
1525
1526
        $userPicture = $user_sender_info['avatar'];
1527
        $main_content .= '<div class="row">';
1528
        $main_content .= '<div class="col-md-2">';
1529
        $main_content .= '<div class="avatar-author">';
1530
        $main_content .= '<img width="60px" src="'.$userPicture.'" alt="'.$name.'" class="img-responsive img-circle" title="'.$name.'" />';
1531
        $main_content .= '</div>';
1532
        $main_content .= '</div>';
1533
1534
        $date = '';
1535
        if ($main_message['send_date'] != $main_message['update_date']) {
1536
            if (!empty($main_message['update_date'])) {
1537
                $date = '<div class="date"> '.
1538
                    Display::returnFontAwesomeIcon('calendar').' '.get_lang('LastUpdate').' '.
1539
                    Display::dateToStringAgoAndLongDate($main_message['update_date']).
1540
                    '</div>';
1541
            }
1542
        } else {
1543
            $date = '<div class="date"> '.
1544
                Display::returnFontAwesomeIcon('calendar').' '.get_lang('Created').' '.
1545
                Display::dateToStringAgoAndLongDate($main_message['send_date']).
1546
                '</div>';
1547
        }
1548
        $attachment = '<div class="message-attach">'.(!empty($files_attachments) ? implode(
1549
                '<br />',
1550
                $files_attachments
1551
            ) : '').'</div>';
1552
        $main_content .= '<div class="col-md-10">';
1553
        $user_link = '<a href="'.api_get_path(
1554
                WEB_PATH
1555
            ).'main/social/profile.php?u='.$main_message['user_sender_id'].'">'.$name.'</a>';
1556
        $main_content .= '<div class="message-content"> ';
1557
        $main_content .= '<div class="username">'.$user_link.'</div>';
1558
        $main_content .= $date;
1559
        $main_content .= '<div class="message">'.$main_message['content'].$attachment.'</div></div>';
1560
        $main_content .= '</div>';
1561
        $main_content .= '</div>';
1562
1563
        $html .= Display::div(
1564
            Display::div(
1565
                $title.$main_content,
1566
                ['class' => 'message-topic']
1567
            ),
1568
            ['class' => 'sm-groups-message']
1569
        );
1570
1571
        $topic_id = $main_message['id'];
1572
1573
        if (is_array($rows) && count($rows) > 0) {
1574
            $topics = $rows;
1575
            $array_html_items = [];
1576
            foreach ($topics as $index => $topic) {
1577
                if (empty($topic['id'])) {
1578
                    continue;
1579
                }
1580
                $items_page_nr = isset($_GET['items_'.$topic['id'].'_page_nr']) ? intval($_GET['items_'.$topic['id'].'_page_nr']) : null;
1581
                $links = '';
1582
                $links .= '<div class="pull-right">';
1583
                $html_items = '';
1584
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1585
                $files_attachments = self::get_links_message_attachment_files($topic['id']);
1586
                $name = $user_sender_info['complete_name'];
1587
1588
                $links .= '<div class="btn-group btn-group-sm">';
1589
                if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1590
                    $topic['user_sender_id'] == $current_user_id
1591
                ) {
1592
                    $links .= '<a href="'.api_get_path(WEB_CODE_PATH).'social/message_for_group_form.inc.php?height=400&width=800&&user_friend='.$current_user_id.'&group_id='.$group_id.'&message_id='.$topic['id'].'&action=edit_message_group&anchor_topic=topic_'.$topic_id.'&topics_page_nr='.$topic_page_nr.'&items_page_nr='.$items_page_nr.'&topic_id='.$topic_id.'" class="ajax btn btn-default" data-size="lg" data-title="'.get_lang('Edit').'" title="'.get_lang('Edit').'">'.
1593
                        Display::returnFontAwesomeIcon('pencil').'</a>';
1594
                }
1595
                $links .= '<a href="'.api_get_path(WEB_CODE_PATH).'social/message_for_group_form.inc.php?height=400&width=800&&user_friend='.api_get_user_id().'&group_id='.$group_id.'&message_id='.$topic['id'].'&action=reply_message_group&anchor_topic=topic_'.$topic_id.'&topics_page_nr='.$topic_page_nr.'&items_page_nr='.$items_page_nr.'&topic_id='.$topic_id.'" class="ajax btn btn-default" data-size="lg" data-title="'.get_lang('Reply').'" title="'.get_lang('Reply').'">';
1596
                $links .= Display::returnFontAwesomeIcon('commenting').'</a>';
1597
                $links .= '</div>';
1598
                $links .= '</div>';
1599
1600
                $userPicture = $user_sender_info['avatar'];
1601
                $user_link = '<a href="'.api_get_path(WEB_PATH).'main/social/profile.php?u='.$topic['user_sender_id'].'">'.$name.'&nbsp</a>';
1602
                $html_items .= '<div class="row">';
1603
                $html_items .= '<div class="col-md-2">';
1604
                $html_items .= '<div class="avatar-author">';
1605
                $html_items .= '<img width="60px" src="'.$userPicture.'" alt="'.$name.'" class="img-responsive img-circle" title="'.$name.'" /></div>';
1606
                $html_items .= '</div>';
1607
1608
                $date = '';
1609
                if ($topic['send_date'] != $topic['update_date']) {
1610
                    if (!empty($topic['update_date'])) {
1611
                        $date = '<div class="date"> '.
1612
                            Display::returnFontAwesomeIcon('calendar').' '.
1613
                            get_lang('LastUpdate').' '.Display::dateToStringAgoAndLongDate($topic['update_date']).
1614
                        '</div>';
1615
                    }
1616
                } else {
1617
                    $date = '<div class="date"> '.
1618
                        Display::returnFontAwesomeIcon('calendar').
1619
                        get_lang('Created').' '.Display::dateToStringAgoAndLongDate($topic['send_date']).
1620
                    '</div>';
1621
                }
1622
                $attachment = '<div class="message-attach">'.(!empty($files_attachments) ? implode('<br />', $files_attachments) : '').'</div>';
1623
                $html_items .= '<div class="col-md-10">';
1624
                $html_items .= '<div class="message-content">';
1625
                $html_items .= $links;
1626
                $html_items .= '<div class="username">'.$user_link.'</div>';
1627
                $html_items .= $date;
1628
                $html_items .= '<div class="message">'.
1629
                    Security::remove_XSS($topic['content'], STUDENT, true).
1630
                    '</div>'.$attachment.'</div>';
1631
                $html_items .= '</div>';
1632
                $html_items .= '</div>';
1633
1634
                $base_padding = 20;
1635
1636
                if ($topic['indent_cnt'] == 0) {
1637
                    $indent = $base_padding;
1638
                } else {
1639
                    $indent = intval($topic['indent_cnt']) * $base_padding + $base_padding;
1640
                }
1641
1642
                $html_items = Display::div($html_items, ['class' => 'message-post', 'id' => 'msg_'.$topic['id']]);
1643
                $html_items = Display::div($html_items, ['class' => '', 'style' => 'margin-left:'.$indent.'px']);
1644
                $array_html_items[] = [$html_items];
1645
            }
1646
1647
            // grids for items with paginations
1648
            $options = ['hide_navigation' => false, 'per_page' => $items_per_page];
1649
            $visibility = [true, true, true, false];
1650
1651
            $style_class = [
1652
                'item' => ['class' => 'user-post'],
1653
                'main' => ['class' => 'user-list'],
1654
            ];
1655
            if (!empty($array_html_items)) {
1656
                $html .= Display::return_sortable_grid(
1657
                    'items_'.$topic['id'],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $topic seems to be defined by a foreach iteration on line 1576. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1658
                    [],
1659
                    $array_html_items,
1660
                    $options,
1661
                    $query_vars,
1662
                    null,
1663
                    $visibility,
1664
                    false,
1665
                    $style_class
1666
                );
1667
            }
1668
        }
1669
1670
        return $html;
1671
    }
1672
1673
    /**
1674
     * Add children to messages by id is used for nested view messages
1675
     * @param array $rows rows of messages
1676
     * @return array $first_seed new list adding the item children
1677
     */
1678
    public static function calculate_children($rows, $first_seed)
1679
    {
1680
        $rows_with_children = [];
1681
        foreach ($rows as $row) {
1682
            $rows_with_children[$row["id"]] = $row;
1683
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
1684
        }
1685
        $rows = $rows_with_children;
1686
        $sorted_rows = [0 => []];
1687
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
1688
        unset($sorted_rows[0]);
1689
1690
        return $sorted_rows;
1691
    }
1692
1693
    /**
1694
     * Sort recursively the messages, is used for for nested view messages
1695
     * @param array  original rows of messages
1696
     * @param array  list recursive of messages
1697
     * @param int   seed for calculate the indent
1698
     * @param int   indent for nested view
1699
     * @return void
1700
     */
1701
    public static function message_recursive_sort(
1702
        $rows,
1703
        &$messages,
1704
        $seed = 0,
1705
        $indent = 0
1706
    ) {
1707
        if ($seed > 0 && isset($rows[$seed]["id"])) {
1708
            $messages[$rows[$seed]["id"]] = $rows[$seed];
1709
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
1710
            $indent++;
1711
        }
1712
1713
        if (isset($rows[$seed]["children"])) {
1714
            foreach ($rows[$seed]["children"] as $child) {
1715
                self::message_recursive_sort($rows, $messages, $child, $indent);
1716
            }
1717
        }
1718
    }
1719
1720
    /**
1721
     * Sort date by desc from a multi-dimensional array
1722
     * @param array $array1 first array to compare
1723
     * @param array $array2 second array to compare
1724
     * @return bool
1725
     */
1726
    public function order_desc_date($array1, $array2)
1727
    {
1728
        return strcmp($array2['send_date'], $array1['send_date']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return strcmp($array2['s..., $array1['send_date']) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
1729
    }
1730
1731
    /**
1732
     * Get array of links (download) for message attachment files
1733
     * @param int $messageId
1734
     * @param string $type message list (inbox/outbox)
1735
     * @return array
1736
     */
1737
    public static function get_links_message_attachment_files($messageId, $type = '')
1738
    {
1739
        $table = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1740
        $messageId = intval($messageId);
1741
1742
        // get file attachments by message id
1743
        $links_attach_file = [];
1744
        if (!empty($messageId)) {
1745
            $sql = "SELECT * FROM $table
1746
                    WHERE message_id = '$messageId'";
1747
1748
            $rs_file = Database::query($sql);
1749
            if (Database::num_rows($rs_file) > 0) {
1750
                $attach_icon = Display::return_icon('attachment.gif', '');
1751
                $archiveURL = api_get_path(WEB_CODE_PATH).'messages/download.php?type='.$type.'&file=';
1752
                while ($row_file = Database::fetch_array($rs_file)) {
1753
                    $archiveFile = $row_file['path'];
1754
                    $filename = $row_file['filename'];
1755
                    $filesize = format_file_size($row_file['size']);
1756
                    $filecomment = Security::remove_XSS($row_file['comment']);
1757
                    $filename = Security::remove_XSS($filename);
1758
                    $links_attach_file[] = $attach_icon.'&nbsp;<a href="'.$archiveURL.$archiveFile.'">'.$filename.'</a>
1759
                        &nbsp;('.$filesize.')'.(!empty($filecomment) ? '&nbsp;-&nbsp;<i>'.$filecomment.'</i>' : '');
1760
                }
1761
            }
1762
        }
1763
        return $links_attach_file;
1764
    }
1765
1766
    /**
1767
     * Get message list by id
1768
     * @param int $messageId
1769
     * @return array
1770
     */
1771
    public static function get_message_by_id($messageId)
1772
    {
1773
        $table = Database::get_main_table(TABLE_MESSAGE);
1774
        $messageId = intval($messageId);
1775
        $sql = "SELECT * FROM $table
1776
                WHERE 
1777
                    id = '$messageId' AND 
1778
                    msg_status <> '".MESSAGE_STATUS_DELETED."' ";
1779
        $res = Database::query($sql);
1780
        $item = [];
1781
        if (Database::num_rows($res) > 0) {
1782
            $item = Database::fetch_array($res, 'ASSOC');
1783
        }
1784
        return $item;
1785
    }
1786
1787
    /**
1788
     *
1789
     * @return string
1790
     */
1791
    public static function generate_message_form()
1792
    {
1793
        $form = new FormValidator('send_message');
1794
        $form->addText(
1795
            'subject',
1796
            get_lang('Subject'),
1797
            false,
1798
            ['id' => 'subject_id']
1799
        );
1800
        $form->addTextarea(
1801
            'content',
1802
            get_lang('Message'),
1803
            ['id' => 'content_id', 'rows' => '5']
1804
        );
1805
1806
        return $form->returnForm();
1807
    }
1808
1809
    /**
1810
     * @param $id
1811
     * @param array $params
1812
     * @return string
1813
     */
1814
    public static function generate_invitation_form($id, $params = [])
0 ignored issues
show
Unused Code introduced by
The parameter $params is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1814
    public static function generate_invitation_form($id, /** @scrutinizer ignore-unused */ $params = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1814
    public static function generate_invitation_form(/** @scrutinizer ignore-unused */ $id, $params = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1815
    {
1816
        $form = new FormValidator('send_invitation');
1817
        $form->addTextarea(
1818
            'content',
1819
            get_lang('AddPersonalMessage'),
1820
            ['id' => 'content_invitation_id', 'rows' => 5]
1821
        );
1822
        return $form->returnForm();
1823
    }
1824
1825
    //@todo this functions should be in the message class
1826
1827
    /**
1828
     * @param string $keyword
1829
     * @return string
1830
     */
1831
    public static function inbox_display($keyword = '')
1832
    {
1833
        $success = get_lang('SelectedMessagesDeleted');
1834
        $success_read = get_lang('SelectedMessagesRead');
1835
        $success_unread = get_lang('SelectedMessagesUnRead');
1836
        $html = '';
1837
1838
        Session::write('message_search_keyword', $keyword);
1839
1840
        if (isset($_REQUEST['action'])) {
1841
            switch ($_REQUEST['action']) {
1842
                case 'mark_as_unread':
1843
                    if (is_array($_POST['id'])) {
1844
                        foreach ($_POST['id'] as $index => $message_id) {
1845
                            self::update_message_status(
1846
                                api_get_user_id(),
1847
                                $message_id,
1848
                                MESSAGE_STATUS_UNREAD
1849
                            );
1850
                        }
1851
                    }
1852
                    $html .= Display::return_message(
1853
                        api_xml_http_response_encode($success_unread),
1854
                        'normal',
1855
                        false
1856
                    );
1857
                    break;
1858
                case 'mark_as_read':
1859
                    if (is_array($_POST['id'])) {
1860
                        foreach ($_POST['id'] as $index => $message_id) {
1861
                            self::update_message_status(
1862
                                api_get_user_id(),
1863
                                $message_id,
1864
                                MESSAGE_STATUS_NEW
1865
                            );
1866
                        }
1867
                    }
1868
                    $html .= Display::return_message(
1869
                        api_xml_http_response_encode($success_read),
1870
                        'normal',
1871
                        false
1872
                    );
1873
                    break;
1874
                case 'delete':
1875
                    foreach ($_POST['id'] as $index => $message_id) {
1876
                        self::delete_message_by_user_receiver(api_get_user_id(), $message_id);
1877
                    }
1878
                    $html .= Display::return_message(
1879
                        api_xml_http_response_encode($success),
1880
                        'normal',
1881
                        false
1882
                    );
1883
                    break;
1884
                case 'deleteone':
1885
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
1886
                    $html .= Display::return_message(
1887
                        api_xml_http_response_encode($success),
1888
                        'confirmation',
1889
                        false
1890
                    );
1891
                    break;
1892
            }
1893
        }
1894
1895
        // display sortable table with messages of the current user
1896
        $table = new SortableTable(
1897
            'message_inbox',
1898
            ['MessageManager', 'getNumberOfMessages'],
1899
            ['MessageManager', 'get_message_data'],
1900
            2,
1901
            20,
1902
            'DESC'
1903
        );
1904
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
1905
        $table->set_header(1, get_lang('Messages'), false);
1906
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
1907
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:120px;']);
1908
1909
        if (isset($_REQUEST['f']) && $_REQUEST['f'] == 'social') {
1910
            $parameters['f'] = 'social';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$parameters was never initialized. Although not strictly required by PHP, it is generally a good practice to add $parameters = array(); before regardless.
Loading history...
1911
            $table->set_additional_parameters($parameters);
1912
        }
1913
        $table->set_form_actions(
1914
            [
1915
                'delete' => get_lang('DeleteSelectedMessages'),
1916
                'mark_as_unread' => get_lang('MailMarkSelectedAsUnread'),
1917
                'mark_as_read' => get_lang('MailMarkSelectedAsRead'),
1918
            ]
1919
        );
1920
        $html .= $table->return_table();
1921
1922
        Session::erase('message_search_keyword');
1923
1924
        return $html;
1925
    }
1926
1927
    /**
1928
     * @param string $keyword
1929
     * @return string
1930
     */
1931
    public static function outbox_display($keyword = '')
1932
    {
1933
        Session::write('message_sent_search_keyword', $keyword);
1934
        $success = get_lang('SelectedMessagesDeleted').'&nbsp</b><br />
1935
                    <a href="outbox.php">'.get_lang('BackToOutbox').'</a>';
1936
1937
        $html = '';
1938
        if (isset($_REQUEST['action'])) {
1939
            switch ($_REQUEST['action']) {
1940
                case 'delete':
1941
                    $number_of_selected_messages = count($_POST['id']);
1942
                    if ($number_of_selected_messages != 0) {
1943
                        foreach ($_POST['id'] as $index => $message_id) {
1944
                            self::delete_message_by_user_receiver(
1945
                                api_get_user_id(),
1946
                                $message_id
1947
                            );
1948
                        }
1949
                    }
1950
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
1951
                    break;
1952
                case 'deleteone':
1953
                    self::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
1954
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
1955
                    $html .= '<br/>';
1956
                    break;
1957
            }
1958
        }
1959
1960
        // display sortable table with messages of the current user
1961
        $table = new SortableTable(
1962
            'message_outbox',
1963
            ['MessageManager', 'getNumberOfMessagesSent'],
1964
            ['MessageManager', 'get_message_data_sent'],
1965
            2,
1966
            20,
1967
            'DESC'
1968
        );
1969
1970
        $table->set_header(0, '', false, ['style' => 'width:15px;']);
1971
        $table->set_header(1, get_lang('Messages'), false);
1972
        $table->set_header(2, get_lang('Date'), true, ['style' => 'width:180px;']);
1973
        $table->set_header(3, get_lang('Modify'), false, ['style' => 'width:70px;']);
1974
1975
        $table->set_form_actions(['delete' => get_lang('DeleteSelectedMessages')]);
1976
        $html .= $table->return_table();
1977
1978
        Session::erase('message_sent_search_keyword');
1979
1980
        return $html;
1981
    }
1982
1983
    /**
1984
     * Get the count of the last received messages for a user
1985
     * @param int $userId The user id
1986
     * @param int $lastId The id of the last received message
1987
     * @return int The count of new messages
1988
     */
1989
    public static function countMessagesFromLastReceivedMessage($userId, $lastId = 0)
1990
    {
1991
        $userId = intval($userId);
1992
        $lastId = intval($lastId);
1993
1994
        if (empty($userId)) {
1995
            return 0;
1996
        }
1997
1998
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
1999
2000
        $conditions = [
2001
            'where' => [
2002
                'user_receiver_id = ?' => $userId,
2003
                'AND msg_status = ?' => MESSAGE_STATUS_UNREAD,
2004
                'AND id > ?' => $lastId
2005
            ]
2006
        ];
2007
2008
        $result = Database::select('COUNT(1) AS qty', $messagesTable, $conditions);
2009
2010
        if (!empty($result)) {
2011
            $row = current($result);
2012
2013
            return $row['qty'];
2014
        }
2015
2016
        return 0;
2017
    }
2018
2019
    /**
2020
     * Get the data of the last received messages for a user
2021
     * @param int $userId The user id
2022
     * @param int $lastId The id of the last received message
2023
     * @return array
2024
     */
2025
    public static function getMessagesFromLastReceivedMessage($userId, $lastId = 0)
2026
    {
2027
        $userId = intval($userId);
2028
        $lastId = intval($lastId);
2029
2030
        if (empty($userId)) {
2031
            return [];
2032
        }
2033
2034
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2035
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
2036
2037
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname
2038
                FROM $messagesTable as m
2039
                INNER JOIN $userTable as u
2040
                ON m.user_sender_id = u.user_id
2041
                WHERE
2042
                    m.user_receiver_id = $userId AND
2043
                    m.msg_status = ".MESSAGE_STATUS_UNREAD."
2044
                    AND m.id > $lastId
2045
                ORDER BY m.send_date DESC";
2046
2047
        $result = Database::query($sql);
2048
2049
        $messages = [];
2050
        if ($result !== false) {
2051
            while ($row = Database::fetch_assoc($result)) {
2052
                $messages[] = $row;
2053
            }
2054
        }
2055
2056
        return $messages;
2057
    }
2058
2059
    /**
2060
     * Check whether a message has attachments
2061
     * @param int $messageId The message id
2062
     * @return boolean Whether the message has attachments return true. Otherwise return false
2063
     */
2064
    public static function hasAttachments($messageId)
2065
    {
2066
        $messageId = intval($messageId);
2067
2068
        if (empty($messageId)) {
2069
            return false;
2070
        }
2071
2072
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
2073
2074
        $conditions = [
2075
            'where' => [
2076
                'message_id = ?' => $messageId
2077
            ]
2078
        ];
2079
2080
        $result = Database::select(
2081
            'COUNT(1) AS qty',
2082
            $messageAttachmentTable,
2083
            $conditions,
2084
            'first'
2085
        );
2086
2087
        if (!empty($result)) {
2088
            if ($result['qty'] > 0) {
2089
                return true;
2090
            }
2091
        }
2092
2093
        return false;
2094
    }
2095
2096
    /**
2097
     * @param string $url
2098
     *
2099
     * @return FormValidator
2100
     */
2101
    public static function getSearchForm($url)
2102
    {
2103
        $form = new FormValidator(
2104
            'search',
2105
            'post',
2106
            $url,
2107
            null,
2108
            [],
2109
            FormValidator::LAYOUT_INLINE
2110
        );
2111
2112
        $form->addElement(
2113
            'text',
2114
            'keyword',
2115
            false,
2116
            [
2117
                'aria-label' => get_lang('Search'),
2118
            ]
2119
        );
2120
        $form->addButtonSearch(get_lang('Search'));
2121
2122
        return $form;
2123
    }
2124
2125
    /**
2126
     * Send a notification to all admins when a new user is registered
2127
     * @param User $user
2128
     */
2129
    public static function sendNotificationByRegisteredUser(User $user)
2130
    {
2131
        $tplMailBody = new Template(
2132
            null,
2133
            false,
2134
            false,
2135
            false,
2136
            false,
2137
            false,
2138
            false
2139
        );
2140
        $tplMailBody->assign('user', $user);
2141
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
2142
        $tplMailBody->assign(
2143
            'manageUrl',
2144
            api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user->getId()
2145
        );
2146
2147
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
2148
2149
        $emailsubject = '['.get_lang('UserRegistered').'] '.$user->getUsername();
2150
        $emailbody = $tplMailBody->fetch($layoutContent);
2151
2152
        $admins = UserManager::get_all_administrators();
2153
2154
        foreach ($admins as $admin_info) {
2155
            self::send_message(
2156
                $admin_info['user_id'],
2157
                $emailsubject,
2158
                $emailbody,
2159
                [],
2160
                [],
2161
                null,
2162
                null,
2163
                null,
2164
                null,
2165
                $user->getId()
2166
            );
2167
        }
2168
    }
2169
2170
    /**
2171
     * Get the error log from failed mailing
2172
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
2173
     * into app/cache/mail/mailq.
2174
     * This can be done with a cron command like (check the location of your mail log file first):
2175
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
2176
     * @return array|bool
2177
     */
2178
    public static function failedSentMailErrors()
2179
    {
2180
        $base = api_get_path(SYS_ARCHIVE_PATH).'mail/';
2181
        $mailq = $base.'mailq';
2182
2183
        if (!file_exists($mailq) || !is_readable($mailq)) {
2184
            return false;
2185
        }
2186
2187
        $file = fopen($mailq, 'r');
2188
        $i = 1;
2189
        while (!feof($file)) {
0 ignored issues
show
Bug introduced by
It seems like $file can also be of type false; however, parameter $handle of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2189
        while (!feof(/** @scrutinizer ignore-type */ $file)) {
Loading history...
2190
            $line = fgets($file);
0 ignored issues
show
Bug introduced by
It seems like $file can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2190
            $line = fgets(/** @scrutinizer ignore-type */ $file);
Loading history...
2191
            //$line = trim($line);
2192
2193
            if (trim($line) == '') {
2194
                continue;
2195
            }
2196
2197
            //Get the mail code, something like 1WBumL-0002xg-FF
2198
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
2199
                $mail_queue[$i]['code'] = $codeMatches[2];
2200
            }
2201
2202
            $fullMail = $base.$mail_queue[$i]['code'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mail_queue does not seem to be defined for all execution paths leading up to this point.
Loading history...
2203
            $mailFile = fopen($fullMail, 'r');
2204
2205
            //Get the reason of mail fail
2206
            $iX = 1;
2207
2208
            while (!feof($mailFile)) {
2209
                $mailLine = fgets($mailFile);
2210
                #if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2211
                if (
2212
                    $iX == 2 &&
2213
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2214
                ) {
2215
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2216
                }
2217
2218
                $iX++;
2219
            }
2220
2221
            fclose($mailFile);
0 ignored issues
show
Bug introduced by
It seems like $mailFile can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2221
            fclose(/** @scrutinizer ignore-type */ $mailFile);
Loading history...
2222
2223
            //Get the time of mail fail
2224
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
2225
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
2226
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
2227
                $mail_queue[$i]['mail'] = $emailMatches[2];
2228
                $i++;
2229
            }
2230
        }
2231
2232
        fclose($file);
2233
2234
        return array_reverse($mail_queue);
2235
    }
2236
2237
    /**
2238
     * @param int $userId
2239
     * @return array
2240
     * @throws \Doctrine\DBAL\DBALException
2241
     */
2242
    public static function getUsersThatHadConversationWithUser($userId)
2243
    {
2244
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2245
        $userId = (int) $userId;
2246
2247
        $sql = "SELECT DISTINCT
2248
                    user_sender_id
2249
                FROM $messagesTable
2250
                WHERE
2251
                    user_receiver_id = ".$userId;
2252
        $result = Database::query($sql);
2253
        $users = Database::store_result($result);
2254
        $userList = [];
2255
        foreach ($users as $userData) {
2256
            $userId = $userData['user_sender_id'];
2257
            if (empty($userId)) {
2258
                continue;
2259
            }
2260
            $userInfo = api_get_user_info($userId);
2261
            if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2262
                $userList[$userId] = $userInfo;
2263
            }
2264
        }
2265
2266
        return $userList;
2267
    }
2268
2269
    /**
2270
     * @param int $userId
2271
     * @param int $otherUserId
2272
     * @return array
2273
     * @throws \Doctrine\DBAL\DBALException
2274
     */
2275
    public static function getAllMessagesBetweenStudents($userId, $otherUserId)
2276
    {
2277
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
2278
        $userId = (int) $userId;
2279
        $otherUserId = (int) $otherUserId;
2280
2281
        if (empty($otherUserId) || empty($userId)) {
2282
            return [];
2283
        }
2284
2285
        $sql = "SELECT DISTINCT * 
2286
                FROM $messagesTable
2287
                WHERE
2288
                    (user_receiver_id = $userId AND user_sender_id = $otherUserId) OR
2289
                    (user_receiver_id = $otherUserId AND user_sender_id = $userId)
2290
                ORDER BY send_date DESC
2291
            ";
2292
        $result = Database::query($sql);
2293
        $messages = Database::store_result($result);
2294
        $list = [];
2295
        foreach ($messages as $message) {
2296
            $list[] = $message;
2297
        }
2298
2299
        return $list;
2300
    }
2301
}
2302