Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

MessageManager::send_message_simple()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 53
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 32
nc 12
nop 8
dl 0
loc 53
rs 8.7155
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* 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
     * Execute the SQL necessary to know the number of messages in the database
48
     * @param   int $userId The user for which we need the unread messages count
49
     * @return  int The number of unread messages in the database for the given user
50
     */
51
    private static function getCountNewMessagesFromDB($userId)
52
    {
53
        if (empty($userId)) {
54
            return 0;
55
        }
56
        $table = Database::get_main_table(TABLE_MESSAGE);
57
        $sql = "SELECT COUNT(id) as count 
58
                FROM $table
59
                WHERE
60
                    user_receiver_id=".api_get_user_id()." AND
61
                    msg_status = ".MESSAGE_STATUS_UNREAD;
62
        $result = Database::query($sql);
63
        $row = Database::fetch_assoc($result);
64
65
        return $row['count'];
66
    }
67
68
    /**
69
     * Gets the total number of messages, used for the inbox sortable table
70
     * @param bool $unread
71
     * @return int
72
     */
73
    public static function getNumberOfMessages($unread = false)
74
    {
75
        $table = Database::get_main_table(TABLE_MESSAGE);
76
        if ($unread) {
77
            $condition_msg_status = ' msg_status = '.MESSAGE_STATUS_UNREAD.' ';
78
        } else {
79
            $condition_msg_status = ' msg_status IN('.MESSAGE_STATUS_NEW.','.MESSAGE_STATUS_UNREAD.') ';
80
        }
81
82
        $keyword = Session::read('message_search_keyword');
83
        $keywordCondition = '';
84
        if (!empty($keyword)) {
85
            $keyword = Database::escape_string($keyword);
86
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
87
        }
88
89
        $sql = "SELECT COUNT(id) as number_messages
90
                FROM $table
91
                WHERE $condition_msg_status AND
92
                    user_receiver_id=".api_get_user_id()."
93
                    $keywordCondition
94
                ";
95
        $result = Database::query($sql);
96
        $result = Database::fetch_array($result);
97
98
        return $result['number_messages'];
99
    }
100
101
    /**
102
     * Gets information about some messages, used for the inbox sortable table
103
     * @param int $from
104
     * @param int $number_of_items
105
     * @param string $column
106
     * @param string $direction
107
     * @return array
108
     */
109
    public static function get_message_data(
110
        $from,
111
        $number_of_items,
112
        $column,
113
        $direction
114
    ) {
115
        $from = (int) $from;
116
        $number_of_items = (int) $number_of_items;
117
118
        //forcing this order
119
        if (!isset($direction)) {
120
            $column = 2;
121
            $direction = 'DESC';
122
        } else {
123
            $column = intval($column);
124
            if (!in_array($direction, ['ASC', 'DESC'])) {
125
                $direction = 'ASC';
126
            }
127
        }
128
129
        if (!in_array($column, [0, 1, 2])) {
130
            $column = 2;
131
        }
132
133
        $keyword = Session::read('message_search_keyword');
134
        $keywordCondition = '';
135
        if (!empty($keyword)) {
136
            $keyword = Database::escape_string($keyword);
137
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
138
        }
139
140
        $table = Database::get_main_table(TABLE_MESSAGE);
141
        $sql = "SELECT 
142
                    id as col0, 
143
                    title as col1, 
144
                    send_date as col2, 
145
                    msg_status as col3,
146
                    user_sender_id
147
                FROM $table
148
                WHERE
149
                    user_receiver_id=".api_get_user_id()." AND
150
                    msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
151
                    $keywordCondition
152
                ORDER BY col$column $direction
153
                LIMIT $from, $number_of_items";
154
155
        $result = Database::query($sql);
156
        $message_list = [];
157
        $newMessageLink = api_get_path(WEB_CODE_PATH).'messages/new_message.php';
158
        while ($row = Database::fetch_array($result, 'ASSOC')) {
159
            $messageId = $row['col0'];
160
            $title = $row['col1'];
161
            $sendDate = $row['col2'];
162
            $status = $row['col3'];
163
            $senderId = $row['user_sender_id'];
164
165
            $title = Security::remove_XSS($title, STUDENT, true);
166
            $title = cut($title, 80, true);
167
168
            if ($status == 1) {
169
                $class = 'class = "unread"';
170
            } else {
171
                $class = 'class = "read"';
172
            }
173
174
            $userInfo = api_get_user_info($senderId);
175
            if (!empty($senderId) && !empty($userInfo)) {
176
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
177
                $message[1] .= $userInfo['complete_name_with_username'];
178
                $message[3] =
179
                    Display::url(
180
                        Display::returnFontAwesomeIcon('reply', 2),
181
                        $newMessageLink.'?re_id='.$messageId,
182
                        ['title' => get_lang('ReplyToMessage') ]
183
                    );
184
            } else {
185
                $message[1] = '<a '.$class.' href="view_message.php?id='.$messageId.'">'.$title.'</a><br />';
186
                $message[1] .= get_lang('UnknownUser');
187
                $message[3] =
188
                    Display::url(
189
                        Display::returnFontAwesomeIcon('reply', 2),
190
                        '#',
191
                        ['title' => get_lang('ReplyToMessage')]
192
                    );
193
            }
194
195
            $message[0] = $messageId;
196
            $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
197
            $message[3] .=
198
                '&nbsp;&nbsp;'.
199
                Display::url(
200
                    Display::returnFontAwesomeIcon('share', 2),
201
                    $newMessageLink.'?forward_id='.$messageId,
202
                    ['title' => get_lang('ForwardMessage') ]
203
                ).
204
                '&nbsp;&nbsp;<a title="'.addslashes(get_lang('DeleteMessage')).'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage')))."'".')) return false;" href="inbox.php?action=deleteone&id='.$messageId.'">'.
205
                Display::returnFontAwesomeIcon('trash', 2).'</a>';
206
            foreach ($message as $key => $value) {
207
                $message[$key] = api_xml_http_response_encode($value);
208
            }
209
            $message_list[] = $message;
210
        }
211
212
        return $message_list;
213
    }
214
215
    /**
216
     * @param array $aboutUserInfo
217
     * @param array $fromUserInfo
218
     * @param string $subject
219
     * @param string $content
220
     * @return bool
221
     */
222
    public static function sendMessageAboutUser(
223
        $aboutUserInfo,
224
        $fromUserInfo,
225
        $subject,
226
        $content
227
    ) {
228
        if (empty($aboutUserInfo) || empty($fromUserInfo)) {
229
            return false;
230
        }
231
232
        if (empty($fromUserInfo['id']) || empty($aboutUserInfo['id'])) {
233
            return false;
234
        }
235
236
        $table = Database::get_main_table(TABLE_MESSAGE);
237
        $now = api_get_utc_datetime();
238
        $params = [
239
            'user_sender_id' => $fromUserInfo['id'],
240
            'user_receiver_id' => $aboutUserInfo['id'],
241
            'msg_status' => MESSAGE_STATUS_CONVERSATION,
242
            'send_date' => $now,
243
            'title' => $subject,
244
            'content' => $content,
245
            'group_id' => 0,
246
            'parent_id' => 0,
247
            'update_date' => $now
248
        ];
249
        $id = Database::insert($table, $params);
250
        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...
251
            return true;
252
        }
253
254
        return false;
255
    }
256
257
    /**
258
     * @param array $aboutUserInfo
259
     * @return array
260
     */
261
    public static function getMessagesAboutUser($aboutUserInfo)
262
    {
263
        if (!empty($aboutUserInfo)) {
264
            $criteria = [
265
              'userReceiverId' => $aboutUserInfo['id'],
266
              'msgStatus' => MESSAGE_STATUS_CONVERSATION
267
            ];
268
            $repo = Database::getManager()->getRepository('ChamiloCoreBundle:Message');
269
            $messages = $repo->findBy($criteria, ['sendDate' => 'DESC']);
270
271
            return $messages;
272
        }
273
274
        return [];
275
    }
276
277
    /**
278
     * Sends a message to a user/group
279
     *
280
     * @param int $receiver_user_id
281
     * @param string $subject
282
     * @param string $content
283
     * @param array $file_attachments files array($_FILES) (optional)
284
     * @param array $file_comments about attachment files (optional)
285
     * @param int $group_id (optional)
286
     * @param int $parent_id (optional)
287
     * @param int $editMessageId id for updating the message (optional)
288
     * @param int $topic_id (optional) the default value is the current user_id
289
     * @param int $sender_id
290
     * @param bool $directMessage
291
     * @param int $forwardId
292
     * @param array $smsParameters
293
     *
294
     * @return bool
295
     */
296
    public static function send_message(
297
        $receiver_user_id,
298
        $subject,
299
        $content,
300
        array $file_attachments = [],
301
        array $file_comments = [],
302
        $group_id = 0,
303
        $parent_id = 0,
304
        $editMessageId = 0,
305
        $topic_id = 0,
306
        $sender_id = 0,
307
        $directMessage = false,
308
        $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

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

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

739
                /** @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...
740
            }
741
742
            $new_path = $path_message_attach.$new_file_name;
743
            if (is_uploaded_file($file_attach['tmp_name'])) {
744
                @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

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

1390
    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...
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

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

1769
    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

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

2143
        while (!feof(/** @scrutinizer ignore-type */ $file)) {
Loading history...
2144
            $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

2144
            $line = fgets(/** @scrutinizer ignore-type */ $file);
Loading history...
2145
            //$line = trim($line);
2146
2147
            if (trim($line) == '') {
2148
                continue;
2149
            }
2150
2151
            //Get the mail code, something like 1WBumL-0002xg-FF
2152
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
2153
                $mail_queue[$i]['code'] = $codeMatches[2];
2154
            }
2155
2156
            $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...
2157
            $mailFile = fopen($fullMail, 'r');
2158
2159
            //Get the reason of mail fail
2160
            $iX = 1;
2161
2162
            while (!feof($mailFile)) {
2163
                $mailLine = fgets($mailFile);
2164
                #if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
2165
                if (
2166
                    $iX == 2 &&
2167
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
2168
                ) {
2169
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
2170
                }
2171
2172
                $iX++;
2173
            }
2174
2175
            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

2175
            fclose(/** @scrutinizer ignore-type */ $mailFile);
Loading history...
2176
2177
            //Get the time of mail fail
2178
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
2179
                $mail_queue[$i]['time'] = $timeMatches[1].$timeMatches[2];
2180
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
2181
                $mail_queue[$i]['mail'] = $emailMatches[2];
2182
                $i++;
2183
            }
2184
        }
2185
2186
        fclose($file);
2187
2188
        return array_reverse($mail_queue);
2189
    }
2190
}
2191