Completed
Push — master ( d9c5eb...f66491 )
by Yannick
95:38 queued 65:24
created

MessageManager::getCountNewMessagesFromDB()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 11

Duplication

Lines 16
Ratio 100 %

Importance

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

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
        if (!api_get_user_id()) {
24
            return false;
25
        }
26
        static $count;
27
        if (!isset($count)) {
28
            $cacheEnabled = function_exists('apcu_exists');
29
            if ($cacheEnabled) {
30
                $var = 'social_messages_unread_u_'.$userId;
0 ignored issues
show
Bug introduced by
The variable $userId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
31
                if (apcu_exists($var)) {
32
                    $count = apcu_fetch($var);
33
                } else {
34
                    $count = self::getCountNewMessagesFromDB($userId);
35
                    apcu_store($var, $count, 60);
36
                }
37
            } else {
38
                $count = self::getCountNewMessagesFromDB($userId);
39
            }
40
        }
41
42
        return $count;
43
    }
44
    /**
45
     * Execute the SQL necessary to know the number of messages in the database
46
     * @param   int $userId The user for which we need the unread messages count
47
     * @return  int The number of unread messages in the database for the given user
48
     */
49 View Code Duplication
    private static function getCountNewMessagesFromDB($userId)
50
    {
51
        if (empty($userId)) {
52
            return 0;
53
        }
54
        $table = Database::get_main_table(TABLE_MESSAGE);
55
        $sql = "SELECT COUNT(id) as count 
56
                        FROM $table
57
                        WHERE
58
                            user_receiver_id=" . api_get_user_id() . " AND
59
                            msg_status = " . MESSAGE_STATUS_UNREAD;
60
        $result = Database::query($sql);
61
        $row = Database::fetch_assoc($result);
62
63
        return $row['count'];
64
    }
65
66
    /**
67
     * Get the list of user_ids of users who are online.
68
     */
69
    public static function users_connected_by_id()
70
    {
71
        $count = who_is_online_count();
72
        $user_connect = who_is_online(0, $count, null, null, 30, true);
73
        $user_id_list = array();
74
        for ($i = 0; $i < count($user_connect); $i++) {
75
            $user_id_list[$i] = $user_connect[$i][0];
76
        }
77
78
        return $user_id_list;
79
    }
80
81
    /**
82
     * Gets the total number of messages, used for the inbox sortable table
83
     */
84
    public static function get_number_of_messages($unread = false)
85
    {
86
        $table_message = Database::get_main_table(TABLE_MESSAGE);
87
        if ($unread) {
88
            $condition_msg_status = ' msg_status = ' . MESSAGE_STATUS_UNREAD . ' ';
89
        } else {
90
            $condition_msg_status = ' msg_status IN(' . MESSAGE_STATUS_NEW . ',' . MESSAGE_STATUS_UNREAD . ') ';
91
        }
92
93
        $keyword = Session::read('message_search_keyword');
94
        $keywordCondition = '';
95
        if (!empty($keyword)) {
96
            $keyword = Database::escape_string($keyword);
97
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
98
        }
99
100
        $sql = "SELECT COUNT(id) as number_messages
101
                FROM $table_message
102
                WHERE $condition_msg_status AND
103
                    user_receiver_id=" . api_get_user_id() . "
104
                    $keywordCondition
105
                ";
106
        $result = Database::query($sql);
107
        $result = Database::fetch_array($result);
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
108
109
        return $result['number_messages'];
110
    }
111
112
    /**
113
     * Gets information about some messages, used for the inbox sortable table
114
     * @param int $from
115
     * @param int $number_of_items
116
     * @param string $direction
117
     */
118
    public static function get_message_data($from, $number_of_items, $column, $direction)
119
    {
120
        $from = intval($from);
121
        $number_of_items = intval($number_of_items);
122
123
        //forcing this order
124 View Code Duplication
        if (!isset($direction)) {
125
            $column = 3;
126
            $direction = 'DESC';
127
        } else {
128
            $column = intval($column);
129
            if (!in_array($direction, array('ASC', 'DESC'))) {
130
                $direction = 'ASC';
131
            }
132
        }
133
134
        $keyword = Session::read('message_search_keyword');
135
        $keywordCondition = '';
136
        if (!empty($keyword)) {
137
            $keyword = Database::escape_string($keyword);
138
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
139
        }
140
141
        $table_message = Database::get_main_table(TABLE_MESSAGE);
142
143
        $sql = "SELECT 
144
                    id as col0, 
145
                    user_sender_id as col1, 
146
                    title as col2, 
147
                    send_date as col3, 
148
                    msg_status as col4
149
                FROM $table_message
150
                WHERE
151
                  user_receiver_id=" . api_get_user_id() . " AND
152
                  msg_status IN (0,1)
153
                  $keywordCondition
154
                ORDER BY col$column $direction
155
                LIMIT $from, $number_of_items";
156
157
        $sql_result = Database::query($sql);
158
        $i = 0;
159
        $message_list = array();
160
161
        while ($result = Database::fetch_row($sql_result)) {
162
            $message[0] = $result[0];
163
            $result[2] = Security::remove_XSS($result[2], STUDENT, true);
164
            $result[2] = cut($result[2], 80, true);
165
166
            if ($result[4] == 1) {
167
                $class = 'class = "unread"';
168
            } else {
169
                $class = 'class = "read"';
170
            }
171
            $link = '';
172
            if (isset($_GET['f']) && $_GET['f'] == 'social') {
173
                $link = '&f=social';
174
            }
175
            $userInfo = api_get_user_info($result[1]);
176
            $message[1] = '<a ' . $class . ' href="view_message.php?id=' . $result[0] . $link . '">' . $result[2] . '</a><br />' . $userInfo['complete_name'];
177
            $message[3] = '<a href="new_message.php?re_id=' . $result[0] . $link . '">' .
178
                Display::return_icon('message_reply.png', get_lang('ReplyToMessage')) . '</a>' .
179
                '&nbsp;&nbsp;<a onclick="javascript:if(!confirm(' . "'" . addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage'))) . "'" . ')) return false;" href="inbox.php?action=deleteone&id=' . $result[0] . $link . '">' . Display::return_icon('delete.png', get_lang('DeleteMessage')) . '</a>';
180
181
            $message[2] = api_convert_and_format_date($result[3], DATE_TIME_FORMAT_LONG); //date stays the same
182
            foreach ($message as $key => $value) {
183
                $message[$key] = api_xml_http_response_encode($value);
184
            }
185
            $message_list[] = $message;
186
            $i++;
187
        }
188
189
        return $message_list;
190
    }
191
192
    /**
193
     * Sends a message to a user/group
194
     *
195
     * @param int $receiver_user_id
196
     * @param string $subject
197
     * @param string $content
198
     * @param array $file_attachments files array($_FILES) (optional)
199
     * @param array $file_comments about attachment files (optional)
200
     * @param int $group_id (optional)
201
     * @param int $parent_id (optional)
202
     * @param int $edit_message_id id for updating the message (optional)
203
     * @param int $topic_id (optional) the default value is the current user_id
204
     * @param int $sender_id
205
     * @param bool $directMessage
206
     *
207
     * @return bool
208
     */
209
    public static function send_message(
210
        $receiver_user_id,
211
        $subject,
212
        $content,
213
        array $file_attachments = [],
214
        array $file_comments = [],
215
        $group_id = 0,
216
        $parent_id = 0,
217
        $edit_message_id = 0,
218
        $topic_id = 0,
219
        $sender_id = null,
220
        $directMessage = false
221
    ) {
222
        $table_message = Database::get_main_table(TABLE_MESSAGE);
223
        $group_id = intval($group_id);
224
        $receiver_user_id = intval($receiver_user_id);
225
        $parent_id = intval($parent_id);
226
        $edit_message_id = intval($edit_message_id);
227
        $topic_id = intval($topic_id);
228
229
        if (!empty($receiver_user_id)) {
230
            $receiverUserInfo = api_get_user_info($receiver_user_id);
231
232
            // Disabling messages for inactive users.
233
            if ($receiverUserInfo['active'] == 0) {
234
                return false;
235
            }
236
        }
237
238
        if (empty($sender_id)) {
239
            $user_sender_id = api_get_user_id();
240
        } else {
241
            $user_sender_id = intval($sender_id);
242
        }
243
244
        $total_filesize = 0;
245
        if (is_array($file_attachments)) {
246
            foreach ($file_attachments as $file_attach) {
247
                $fileSize = isset($file_attach['size']) ? $file_attach['size'] : 0;
248
                if (is_array($fileSize)) {
249
                    foreach ($fileSize as $size) {
250
                        $total_filesize += $size;
251
                    }
252
                } else {
253
                    $total_filesize += $fileSize;
254
                }
255
            }
256
        }
257
258
        // Validating fields
259
        if (empty($subject) && empty($group_id)) {
260
            Display::addFlash(Display::return_message(get_lang('YouShouldWriteASubject'), 'warning'));
261
            return false;
262
        } else if ($total_filesize > intval(api_get_setting('message_max_upload_filesize'))) {
263
            $warning = sprintf(
264
                get_lang("FilesSizeExceedsX"),
265
                format_file_size(api_get_setting('message_max_upload_filesize'))
266
            );
267
268
            Display::addFlash(Display::return_message($warning, 'warning'));
269
270
            return false;
271
        }
272
273
        $inbox_last_id = null;
274
275
        //Just in case we replace the and \n and \n\r while saving in the DB
276
        //$content = str_replace(array("\n", "\n\r"), '<br />', $content);
277
278
        $now = api_get_utc_datetime();
279
        if (!empty($receiver_user_id) || !empty($group_id)) {
280
            // message for user friend
281
            //@todo it's possible to edit a message? yes, only for groups
282
            if ($edit_message_id) {
283
                $query = " UPDATE $table_message SET
284
                                update_date = '" . $now . "',
285
                                content = '".Database::escape_string($content)."'
286
                           WHERE id = '$edit_message_id' ";
287
                Database::query($query);
288
                $inbox_last_id = $edit_message_id;
289
            } else {
290
                $params = [
291
                    'user_sender_id' => $user_sender_id,
292
                    'user_receiver_id' => $receiver_user_id,
293
                    'msg_status' => '1',
294
                    'send_date' => $now,
295
                    'title' => $subject,
296
                    'content' => $content,
297
                    'group_id' => $group_id,
298
                    'parent_id' => $parent_id,
299
                    'update_date' => $now
300
                ];
301
                $inbox_last_id = Database::insert($table_message, $params);
302
            }
303
304
            // Save attachment file for inbox messages
305
            if (is_array($file_attachments)) {
306
                $i = 0;
307
                foreach ($file_attachments as $file_attach) {
308
                    if ($file_attach['error'] == 0) {
309
                        self::save_message_attachment_file(
310
                            $file_attach,
311
                            isset($file_comments[$i]) ? $file_comments[$i] : null,
312
                            $inbox_last_id,
313
                            null,
314
                            $receiver_user_id,
315
                            $group_id
316
                        );
317
                    }
318
                    $i++;
319
                }
320
            }
321
322
            if (empty($group_id)) {
323
                // message in outbox for user friend or group
324
                $params = [
325
                    'user_sender_id' => $user_sender_id,
326
                    'user_receiver_id' => $receiver_user_id,
327
                    'msg_status' => '4',
328
                    'send_date' => $now,
329
                    'title' => $subject,
330
                    'content' => $content,
331
                    'group_id' => $group_id,
332
                    'parent_id' => $parent_id,
333
                    'update_date' => $now
334
                ];
335
                $outbox_last_id = Database::insert($table_message, $params);
336
337
                // save attachment file for outbox messages
338
                if (is_array($file_attachments)) {
339
                    $o = 0;
340
                    foreach ($file_attachments as $file_attach) {
341
                        if ($file_attach['error'] == 0) {
342
                            $comment = isset($file_comments[$o]) ? $file_comments[$o] : '';
343
                            self::save_message_attachment_file(
344
                                $file_attach,
345
                                $comment,
346
                                $outbox_last_id,
347
                                $user_sender_id
348
                            );
349
                        }
350
                        $o++;
351
                    }
352
                }
353
            }
354
355
            // Load user settings.
356
            $notification = new Notification();
357
            $sender_info = api_get_user_info($user_sender_id);
358
359
            // add file attachment additional attributes
360
            foreach ($file_attachments as $index => $file_attach) {
361
                $file_attachments[$index]['path'] = $file_attach['tmp_name'];
362
                $file_attachments[$index]['filename'] = $file_attach['name'];
363
            }
364
365
            if (empty($group_id)) {
366
                $type = Notification::NOTIFICATION_TYPE_MESSAGE;
367
                if ($directMessage) {
368
                    $type = Notification::NOTIFICATION_TYPE_DIRECT_MESSAGE;
369
                }
370
                $notification->save_notification(
371
                    $type,
372
                    array($receiver_user_id),
373
                    $subject,
374
                    $content,
375
                    $sender_info,
0 ignored issues
show
Security Bug introduced by
It seems like $sender_info defined by api_get_user_info($user_sender_id) on line 357 can also be of type false; however, Notification::save_notification() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
376
                    $file_attachments
377
                );
378
            } else {
379
                $usergroup = new UserGroup();
380
                $group_info = $usergroup->get($group_id);
381
                $group_info['topic_id'] = $topic_id;
382
                $group_info['msg_id'] = $inbox_last_id;
383
384
                $user_list = $usergroup->get_users_by_group($group_id, false, array(), 0, 1000);
385
386
                // Adding more sense to the message group
387
                $subject = sprintf(get_lang('ThereIsANewMessageInTheGroupX'), $group_info['name']);
388
389
                $new_user_list = array();
390
                foreach ($user_list as $user_data) {
391
                    $new_user_list[] = $user_data['id'];
392
                }
393
                $group_info = array(
394
                    'group_info' => $group_info,
395
                    'user_info' => $sender_info,
396
                );
397
                $notification->save_notification(
398
                    Notification::NOTIFICATION_TYPE_GROUP,
399
                    $new_user_list,
400
                    $subject,
401
                    $content,
402
                    $group_info,
403
                    $file_attachments
404
                );
405
            }
406
407
            return $inbox_last_id;
408
        }
409
410
        return false;
411
    }
412
413
    /**
414
     * @param int $receiver_user_id
415
     * @param int $subject
416
     * @param string $message
417
     * @param int $sender_id
418
     * @param bool $sendCopyToDrhUsers send copy to related DRH users
419
     * @param bool $directMessage
420
     *
421
     * @return bool
422
     */
423
    public static function send_message_simple(
424
        $receiver_user_id,
425
        $subject,
426
        $message,
427
        $sender_id = null,
428
        $sendCopyToDrhUsers = false,
429
        $directMessage = false
430
    ) {
431
        $result = MessageManager::send_message(
432
            $receiver_user_id,
433
            $subject,
434
            $message,
435
            $_FILES ? $_FILES : [],
436
            [],
437
            null,
438
            null,
439
            null,
440
            null,
441
            $sender_id,
442
            $directMessage
443
        );
444
445
        if ($sendCopyToDrhUsers) {
446
            $userInfo = api_get_user_info($receiver_user_id);
447
            $drhList = UserManager::getDrhListFromUser($receiver_user_id);
448
            if (!empty($drhList)) {
449
                foreach ($drhList as $drhInfo) {
450
                    $message = sprintf(
451
                            get_lang('CopyOfMessageSentToXUser'),
452
                            $userInfo['complete_name']
453
                        ) . ' <br />' . $message;
454
455
                    MessageManager::send_message_simple(
456
                        $drhInfo['user_id'],
457
                        $subject,
458
                        $message,
459
                        $sender_id,
460
                        false,
461
                        $directMessage
462
                    );
463
                }
464
            }
465
        }
466
467
        return $result;
468
    }
469
470
    /**
471
     * Update parent ids for other receiver user from current message in groups
472
     * @author Christian Fasanando Flores
473
     * @param  int $parent_id
474
     * @param  int $receiver_user_id
475
     * @param  int $message_id
476
     * @return void
477
     */
478
    public static function update_parent_ids_from_reply($parent_id, $receiver_user_id, $message_id)
479
    {
480
        $table_message = Database::get_main_table(TABLE_MESSAGE);
481
        $parent_id = intval($parent_id);
482
        $receiver_user_id = intval($receiver_user_id);
483
        $message_id = intval($message_id);
484
        // first get data from message id (parent)
485
        $sql_message = "SELECT * FROM $table_message WHERE id = '$parent_id'";
486
        $rs_message = Database::query($sql_message);
487
        $row_message = Database::fetch_array($rs_message);
488
489
        // get message id from data found early for other receiver user
490
        $sql = "SELECT id FROM $table_message
491
                WHERE
492
                    user_sender_id ='{$row_message['user_sender_id']}' AND
493
                    title='{$row_message['title']}' AND
494
                    content='{$row_message['content']}' AND
495
                    group_id='{$row_message['group_id']}' AND
496
                    user_receiver_id='$receiver_user_id'";
497
        $rs_msg_id = Database::query($sql);
498
        $row = Database::fetch_array($rs_msg_id);
499
500
        // update parent_id for other user receiver
501
        $sql = "UPDATE $table_message SET parent_id = " . $row['id'] . "
502
                WHERE id = $message_id";
503
        Database::query($sql);
504
    }
505
506
    /**
507
     * @param int $user_receiver_id
508
     * @param int $id
509
     * @return bool
510
     */
511
    public static function delete_message_by_user_receiver($user_receiver_id, $id)
512
    {
513
        $table_message = Database::get_main_table(TABLE_MESSAGE);
514
        if ($id != strval(intval($id))) {
515
            return false;
516
        }
517
        $user_receiver_id = intval($user_receiver_id);
518
        $id = intval($id);
519
        $sql = "SELECT * FROM $table_message
520
                WHERE id=" . $id . " AND msg_status<>4";
521
        $rs = Database::query($sql);
522
523
        if (Database::num_rows($rs) > 0) {
524
            // delete attachment file
525
            self::delete_message_attachment_file($id, $user_receiver_id);
526
            // delete message
527
            $query = "UPDATE $table_message SET msg_status=3
528
                      WHERE user_receiver_id=" . $user_receiver_id . " AND id=" . $id;
529
            Database::query($query);
530
531
            return true;
532
        } else {
533
            return false;
534
        }
535
    }
536
537
    /**
538
     * Set status deleted
539
     * @author Isaac FLores Paz <[email protected]>
540
     * @param  int
541
     * @param  int
542
     * @return bool
543
     */
544
    public static function delete_message_by_user_sender($user_sender_id, $id)
545
    {
546
        if ($id != strval(intval($id))) {
547
            return false;
548
        }
549
550
        $table_message = Database::get_main_table(TABLE_MESSAGE);
551
552
        $id = intval($id);
553
        $user_sender_id = intval($user_sender_id);
554
555
        $sql = "SELECT * FROM $table_message WHERE id='$id'";
556
        $rs = Database::query($sql);
557
558
        if (Database::num_rows($rs) > 0) {
559
            // delete attachment file
560
            self::delete_message_attachment_file($id, $user_sender_id);
561
            // delete message
562
            $sql = "UPDATE $table_message 
563
                    SET msg_status=3
564
                    WHERE user_sender_id='$user_sender_id' AND id='$id'";
565
            Database::query($sql);
566
567
            return true;
568
        }
569
570
        return false;
571
    }
572
573
    /**
574
     * Saves a message attachment files
575
     * @param  array $file_attach $_FILES['name']
576
     * @param  string    a comment about the uploaded file
577
     * @param  int        message id
578
     * @param  int        receiver user id (optional)
579
     * @param  int        sender user id (optional)
580
     * @param  int        group id (optional)
581
     * @return void
582
     */
583
    public static function save_message_attachment_file(
584
        $file_attach,
585
        $file_comment,
586
        $message_id,
587
        $receiver_user_id = 0,
588
        $sender_user_id = 0,
589
        $group_id = 0
590
    ) {
591
        $tbl_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
592
593
        // Try to add an extension to the file if it hasn't one
594
        $new_file_name = add_ext_on_mime(stripslashes($file_attach['name']), $file_attach['type']);
595
596
        // user's file name
597
        $file_name = $file_attach['name'];
598
        if (!filter_extension($new_file_name)) {
599
            Display:: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
0 ignored issues
show
Deprecated Code introduced by
The method Display::display_error_message() has been deprecated with message: use Display::addFlash with Display::return_message

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
600
        } else {
601
            $new_file_name = uniqid('');
602
            if (!empty($receiver_user_id)) {
603
                $message_user_id = $receiver_user_id;
604
            } else {
605
                $message_user_id = $sender_user_id;
606
            }
607
608
            // User-reserved directory where photos have to be placed.*
609
            $userGroup = new UserGroup();
610
611 View Code Duplication
            if (!empty($group_id)) {
612
                $path_user_info = $userGroup->get_group_picture_path_by_id($group_id, 'system', true);
613
            } else {
614
                $path_user_info['dir'] = UserManager::getUserPathById($message_user_id, 'system');
615
            }
616
617
            $path_message_attach = $path_user_info['dir'] . 'message_attachments/';
618
619
            // If this directory does not exist - we create it.
620
            if (!file_exists($path_message_attach)) {
621
                @mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);
622
            }
623
            $new_path = $path_message_attach . $new_file_name;
624
            if (is_uploaded_file($file_attach['tmp_name'])) {
625
                @copy($file_attach['tmp_name'], $new_path);
626
            }
627
628
            // Storing the attachments if any
629
            $params = [
630
                'filename' => $file_name,
631
                'comment' => $file_comment,
632
                'path' => $new_file_name,
633
                'message_id' => $message_id,
634
                'size' => $file_attach['size']
635
            ];
636
            Database::insert($tbl_message_attach, $params);
637
        }
638
    }
639
640
    /**
641
     * Delete message attachment files (logically updating the row with a suffix _DELETE_id)
642
     * @param  int    message id
643
     * @param  int    message user id (receiver user id or sender user id)
644
     * @param  int    group id (optional)
645
     * @return void
646
     */
647
    public static function delete_message_attachment_file($message_id, $message_uid, $group_id = 0)
648
    {
649
        $message_id = intval($message_id);
650
        $message_uid = intval($message_uid);
651
        $table_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
652
653
        $sql = "SELECT * FROM $table_message_attach WHERE message_id = '$message_id'";
654
        $rs = Database::query($sql);
655
        while ($row = Database::fetch_array($rs)) {
656
            $path = $row['path'];
657
            $attach_id = $row['id'];
658
            $new_path = $path . '_DELETED_' . $attach_id;
659
660 View Code Duplication
            if (!empty($group_id)) {
661
                $userGroup = new UserGroup();
662
                $path_user_info = $userGroup->get_group_picture_path_by_id(
663
                    $group_id,
664
                    'system',
665
                    true
666
                );
667
            } else {
668
                $path_user_info['dir'] = UserManager::getUserPathById(
669
                    $message_uid,
670
                    'system'
671
                );
672
            }
673
674
            $path_message_attach = $path_user_info['dir'] . 'message_attachments/';
675
            if (is_file($path_message_attach . $path)) {
676
                if (rename($path_message_attach . $path, $path_message_attach . $new_path)) {
677
                    $sql = "UPDATE $table_message_attach set path='$new_path'
678
                            WHERE id ='$attach_id'";
679
                    Database::query($sql);
680
                }
681
            }
682
        }
683
    }
684
685
    /**
686
     * update messages by user id and message id
687
     * @param  int $user_id
688
     * @param  int $message_id
689
     * @return resource
690
     */
691
    public static function update_message($user_id, $message_id)
692
    {
693
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id)))
694
            return false;
695
696
        $table_message = Database::get_main_table(TABLE_MESSAGE);
697
        $sql = "UPDATE $table_message SET msg_status = '0'
698
                WHERE
699
                    msg_status<>4 AND
700
                    user_receiver_id=" . intval($user_id) . " AND
701
                    id='" . intval($message_id) . "'";
702
        Database::query($sql);
703
    }
704
705
    /**
706
     * @param int $user_id
707
     * @param int $message_id
708
     * @param string $type
709
     * @return bool
710
     */
711 View Code Duplication
    public static function update_message_status($user_id, $message_id, $type)
712
    {
713
        $type = intval($type);
714
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id))) {
715
            return false;
716
        }
717
        $table_message = Database::get_main_table(TABLE_MESSAGE);
718
        $sql = "UPDATE $table_message SET
719
                    msg_status = '$type'
720
                WHERE
721
                    user_receiver_id=" . intval($user_id) . " AND
722
                    id='" . intval($message_id) . "'";
723
        Database::query($sql);
724
    }
725
726
    /**
727
     * get messages by user id and message id
728
     * @param  int $user_id
729
     * @param  int $message_id
730
     * @return array
731
     */
732 View Code Duplication
    public static function get_message_by_user($user_id, $message_id)
733
    {
734
        if ($message_id != strval(intval($message_id)) || $user_id != strval(intval($user_id)))
735
            return false;
736
        $table_message = Database::get_main_table(TABLE_MESSAGE);
737
        $query = "SELECT * FROM $table_message
738
                  WHERE user_receiver_id=" . intval($user_id) . " AND id='" . intval($message_id) . "'";
739
        $result = Database::query($query);
740
741
        return $row = Database::fetch_array($result);
742
    }
743
744
    /**
745
     * get messages by group id
746
     * @param  int        group id
747
     * @return array
748
     */
749
    public static function get_messages_by_group($group_id)
750
    {
751
        if ($group_id != strval(intval($group_id))) {
752
            return false;
753
        }
754
755
        $table_message = Database::get_main_table(TABLE_MESSAGE);
756
        $group_id = intval($group_id);
757
        $sql = "SELECT * FROM $table_message
758
                WHERE
759
                    group_id= $group_id AND
760
                    msg_status NOT IN ('" . MESSAGE_STATUS_OUTBOX . "', '" . MESSAGE_STATUS_DELETED . "')
761
                ORDER BY id";
762
        $rs = Database::query($sql);
763
        $data = array();
764
        if (Database::num_rows($rs) > 0) {
765
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
766
                $data[] = $row;
767
            }
768
        }
769
        return $data;
770
    }
771
772
    /**
773
     * get messages by group id
774
     * @param  int $group_id
775
     * @param int $message_id
776
     * @return array
777
     */
778
    public static function get_messages_by_group_by_message($group_id, $message_id)
779
    {
780
        if ($group_id != strval(intval($group_id))) {
781
            return false;
782
        }
783
        $table_message = Database::get_main_table(TABLE_MESSAGE);
784
        $group_id = intval($group_id);
785
        $sql = "SELECT * FROM $table_message
786
                WHERE
787
                    group_id = $group_id AND
788
                    msg_status NOT IN ('" . MESSAGE_STATUS_OUTBOX . "', '" . MESSAGE_STATUS_DELETED . "')
789
                ORDER BY id ";
790
791
        $rs = Database::query($sql);
792
        $data = array();
793
        $parents = array();
794 View Code Duplication
        if (Database::num_rows($rs) > 0) {
795
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
796
                if ($message_id == $row['parent_id'] || in_array($row['parent_id'], $parents)) {
797
                    $parents[] = $row['id'];
798
                    $data[] = $row;
799
                }
800
            }
801
        }
802
803
        return $data;
804
    }
805
806
    /**
807
     * get messages by parent id optionally with limit
808
     * @param  int        parent id
809
     * @param  int        group id (optional)
810
     * @param  int        offset (optional)
811
     * @param  int        limit (optional)
812
     * @return array
813
     */
814
    public static function get_messages_by_parent($parent_id, $group_id = '', $offset = 0, $limit = 0)
815
    {
816
        if ($parent_id != strval(intval($parent_id))) {
817
            return false;
818
        }
819
        $table_message = Database::get_main_table(TABLE_MESSAGE);
820
        $parent_id = intval($parent_id);
821
822
        $condition_group_id = "";
823
        if ($group_id !== '') {
824
            $group_id = intval($group_id);
825
            $condition_group_id = " AND group_id = '$group_id' ";
826
        }
827
828
        $condition_limit = "";
829
        if ($offset && $limit) {
830
            $offset = ($offset - 1) * $limit;
831
            $condition_limit = " LIMIT $offset,$limit ";
832
        }
833
834
        $sql = "SELECT * FROM $table_message
835
                WHERE
836
                    parent_id='$parent_id' AND
837
                    msg_status <> " . MESSAGE_STATUS_OUTBOX . "
838
                    $condition_group_id
839
                ORDER BY send_date DESC $condition_limit ";
840
        $rs = Database::query($sql);
841
        $data = array();
842
        if (Database::num_rows($rs) > 0) {
843
            while ($row = Database::fetch_array($rs)) {
844
                $data[$row['id']] = $row;
845
            }
846
        }
847
848
        return $data;
849
    }
850
851
    /**
852
     * Gets information about if exist messages
853
     * @author Isaac FLores Paz <[email protected]>
854
     * @param  integer
855
     * @param  integer
856
     * @return boolean
857
     */
858
    public static function exist_message($user_id, $id)
859
    {
860
        if ($id != strval(intval($id)) || $user_id != strval(intval($user_id)))
861
            return false;
862
        $table_message = Database::get_main_table(TABLE_MESSAGE);
863
        $query = "SELECT id FROM $table_message
864
                  WHERE
865
                    user_receiver_id = " . intval($user_id) . " AND
866
                    id = '" . intval($id) . "'";
867
        $result = Database::query($query);
868
        $num = Database::num_rows($result);
869
        if ($num > 0) {
870
            return true;
871
        } else {
872
            return false;
873
        }
874
    }
875
876
    /**
877
     * Gets information about messages sent
878
     * @param  integer
879
     * @param  integer
880
     * @param  string
881
     * @return array
882
     */
883
    public static function get_message_data_sent($from, $number_of_items, $column, $direction)
884
    {
885
        $from = intval($from);
886
        $number_of_items = intval($number_of_items);
887 View Code Duplication
        if (!isset($direction)) {
888
            $column = 3;
889
            $direction = 'DESC';
890
        } else {
891
            $column = intval($column);
892
            if (!in_array($direction, array('ASC', 'DESC')))
893
                $direction = 'ASC';
894
        }
895
        $table_message = Database::get_main_table(TABLE_MESSAGE);
896
        $request = api_is_xml_http_request();
897
898
        $keyword = Session::read('message_sent_search_keyword');
899
        $keywordCondition = '';
900
        if (!empty($keyword)) {
901
            $keyword = Database::escape_string($keyword);
902
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
903
        }
904
905
        $sql = "SELECT
906
                    id as col0, 
907
                    user_sender_id as col1, 
908
                    title as col2, 
909
                    send_date as col3, 
910
                    user_receiver_id as col4, 
911
                    msg_status as col5
912
                FROM $table_message
913
                WHERE
914
                    user_sender_id=" . api_get_user_id() . " AND
915
                    msg_status=" . MESSAGE_STATUS_OUTBOX . "
916
                    $keywordCondition
917
                ORDER BY col$column $direction
918
                LIMIT $from, $number_of_items";
919
        $sql_result = Database::query($sql);
920
        $i = 0;
921
        $message_list = array();
922
        while ($result = Database::fetch_row($sql_result)) {
923
            if ($request === true) {
924
                $message[0] = '<input type="checkbox" value=' . $result[0] . ' name="out[]">';
925
            } else {
926
                $message[0] = ($result[0]);
927
            }
928
            $class = 'class = "read"';
929
            $result[2] = Security::remove_XSS($result[2]);
930
            $userInfo = api_get_user_info($result[4]);
931
            if ($request === true) {
932
                $message[1] = '<a onclick="show_sent_message(' . $result[0] . ')" href="javascript:void(0)">' . $userInfo['complete_name'] . '</a>';
933
                $message[2] = '<a onclick="show_sent_message(' . $result[0] . ')" href="javascript:void(0)">' . str_replace("\\", "", $result[2]) . '</a>';
934
                $message[3] = api_convert_and_format_date($result[3], DATE_TIME_FORMAT_LONG); //date stays the same
935
                $message[4] = '&nbsp;&nbsp;<a onclick="delete_one_message_outbox(' . $result[0] . ')" href="javascript:void(0)"  >' .
936
                    Display::return_icon('delete.png', get_lang('DeleteMessage')) . '</a>';
937
            } else {
938
                $link = '';
939
                if (isset($_GET['f']) && $_GET['f'] == 'social') {
940
                    $link = '&f=social';
941
                }
942
                $message[1] = '<a ' . $class . ' onclick="show_sent_message (' . $result[0] . ')" href="../messages/view_message.php?id_send=' . $result[0] . $link . '">' . $result[2] . '</a><br />' . $userInfo['complete_name'];
943
                $message[2] = api_convert_and_format_date($result[3], DATE_TIME_FORMAT_LONG); //date stays the same
944
                $message[3] = '<a href="outbox.php?action=deleteone&id=' . $result[0] . '&' . $link . '"  onclick="javascript:if(!confirm(' . "'" . addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage'))) . "'" . ')) return false;" >' .
945
                    Display::return_icon('delete.png', get_lang('DeleteMessage')) . '</a>';
946
            }
947
948
            foreach ($message as $key => $value) {
949
                $message[$key] = $value;
950
            }
951
            $message_list[] = $message;
952
            $i++;
953
        }
954
955
        return $message_list;
956
    }
957
958
    /**
959
     * Gets information about number messages sent
960
     * @author Isaac FLores Paz <[email protected]>
961
     * @param void
962
     * @return integer
963
     */
964
    public static function get_number_of_messages_sent()
965
    {
966
        $table_message = Database::get_main_table(TABLE_MESSAGE);
967
968
        $keyword = Session::read('message_sent_search_keyword');
969
        $keywordCondition = '';
970
        if (!empty($keyword)) {
971
            $keyword = Database::escape_string($keyword);
972
            $keywordCondition = " AND (title like '%$keyword%' OR content LIKE '%$keyword%') ";
973
        }
974
975
        $sql = "SELECT COUNT(id) as number_messages 
976
                FROM $table_message
977
                WHERE
978
                  msg_status=" . MESSAGE_STATUS_OUTBOX . " AND
979
                  user_sender_id=" . api_get_user_id() . "
980
                  $keywordCondition
981
                ";
982
        $result = Database::query($sql);
983
        $result = Database::fetch_array($result);
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
984
985
        return $result['number_messages'];
986
    }
987
988
    /**
989
     * display message box in the inbox
990
     * @param int the message id
991
     * @param string inbox or outbox strings are available
992
     * @todo replace numbers with letters in the $row array pff...
993
     * @return string html with the message content
994
     */
995
    public static function show_message_box($message_id, $source = 'inbox')
996
    {
997
        $table_message = Database::get_main_table(TABLE_MESSAGE);
998
        $message_id = intval($message_id);
999
1000
        if ($source == 'outbox') {
1001 View Code Duplication
            if (isset($message_id) && is_numeric($message_id)) {
1002
                $query = "SELECT * FROM $table_message
1003
                          WHERE
1004
                            user_sender_id = " . api_get_user_id() . " AND
1005
                            id = " . $message_id . " AND
1006
                            msg_status = 4;";
1007
                $result = Database::query($query);
1008
            }
1009
        } else {
1010
            if (is_numeric($message_id) && !empty($message_id)) {
1011
                $query = "UPDATE $table_message SET
1012
                          msg_status = '" . MESSAGE_STATUS_NEW . "'
1013
                          WHERE
1014
                            user_receiver_id=" . api_get_user_id() . " AND
1015
                            id='" . $message_id . "'";
1016
                Database::query($query);
1017
1018
                $query = "SELECT * FROM $table_message
1019
                          WHERE
1020
                            msg_status<>4 AND
1021
                            user_receiver_id=" . api_get_user_id() . " AND
1022
                            id='" . $message_id . "'";
1023
                $result = Database::query($query);
1024
            }
1025
        }
1026
        $row = Database::fetch_array($result, 'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1027
        $user_sender_id = $row['user_sender_id'];
1028
1029
        // get file attachments by message id
1030
        $files_attachments = self::get_links_message_attachment_files($message_id, $source);
1031
1032
        $title = Security::remove_XSS($row['title'], STUDENT, true);
1033
        $content = Security::remove_XSS($row['content'], STUDENT, true);
1034
1035
        $from_user = api_get_user_info($user_sender_id);
1036
        $name = $from_user['complete_name'];
1037
        $message_content = Display::page_subheader(str_replace("\\", "", $title));
1038
        $user_image = '';
1039
        if (api_get_setting('allow_social_tool') == 'true') {
1040
            $user_image = Display::img(
1041
                $from_user['avatar_no_query'],
1042
                $name,
1043
                array('title' => $name, 'class' => 'img-responsive img-circle', 'style' => 'max-width:35px')
1044
            );
1045
        }
1046
1047
        $receiverUserInfo = api_get_user_info($row['user_receiver_id']);
1048
1049
        $message_content .= '<tr>';
1050
        if (api_get_setting('allow_social_tool') == 'true') {
1051
            $message_content .= '<div class="row">';
1052
1053
            if ($source == 'outbox') {
1054
                $message_content .= '<div class="col-md-1">';
1055
                $message_content .= $user_image;
1056
                $message_content .= '</div>';
1057
1058
                $message_content .= '<div class="col-md-4">';
1059
                $message_content .= '<a href="' . api_get_path(WEB_PATH) . 'main/social/profile.php?u=' . $user_sender_id . '">' . $name . '</a> ';
1060
                $message_content .= api_strtolower(get_lang('To')) . '&nbsp;<b>' . $receiverUserInfo['complete_name'];
1061
                $message_content .= '</div>';
1062
1063
                $message_content .= '<div class="col-md-2 col-md-offset-5">';
1064
                $message_content .= Display::dateToStringAgoAndLongDate($row['send_date']);
1065
                $message_content .= '</div>';
1066
1067
            } else {
1068
                $message_content .= '<div class="col-md-1">';
1069
                $message_content .= $user_image;
1070
                $message_content .= '</div>';
1071
1072
                $message_content .= '<div class="col-md-4">';
1073
                $message_content .= '<a href="' . api_get_path(WEB_PATH) . 'main/social/profile.php?u=' . $user_sender_id . '">' . $name . '</a> ';
1074
                $message_content .= '</div>';
1075
1076
                $message_content .= '<div class="col-md-2 col-md-offset-5">';
1077
                $message_content .= Display::dateToStringAgoAndLongDate($row['send_date']);
1078
                $message_content .= '</div>';
1079
            }
1080
            $message_content .= '</div>';
1081
        } else {
1082
            if ($source == 'outbox') {
1083
                $message_content .= get_lang('From') . ':&nbsp;' . $name . '</b> ' . api_strtolower(get_lang('To')) . ' <b>' . $receiverUserInfo['complete_name'] . '</b>';
1084
            } else {
1085
                $message_content .= get_lang('From') . ':&nbsp;' . $name . '</b> ' . api_strtolower(get_lang('To')) . ' <b>' . get_lang('Me') . '</b>';
1086
            }
1087
        }
1088
        $message_content .= '
1089
		        <br />
1090
		        <hr style="color:#ddd" />
1091
		        <table width="100%">
1092
		            <tr>
1093
		              <td valign=top class="view-message-content">' . str_replace("\\", "", $content) . '</td>
1094
		            </tr>
1095
		        </table>
1096
		        <div id="message-attach">' . (!empty($files_attachments) ? implode('<br />', $files_attachments) : '') . '</div>
1097
		        <div style="padding: 15px 0px 5px 0px">';
1098
        $social_link = '';
1099
        if (isset($_GET['f']) && $_GET['f'] == 'social') {
1100
            $social_link = 'f=social';
1101
        }
1102
        if ($source == 'outbox') {
1103
            $message_content .= '<a href="outbox.php?' . $social_link . '">' .
1104
                Display::return_icon('back.png', get_lang('ReturnToOutbox')) . '</a> &nbsp';
1105
        } else {
1106
            $message_content .= '<a href="inbox.php?' . $social_link . '">' .
1107
                Display::return_icon('back.png', get_lang('ReturnToInbox')) . '</a> &nbsp';
1108
            $message_content .= '<a href="new_message.php?re_id=' . $message_id . '&' . $social_link . '">' .
1109
                Display::return_icon('message_reply.png', get_lang('ReplyToMessage')) . '</a> &nbsp';
1110
        }
1111
        $message_content .= '<a href="inbox.php?action=deleteone&id=' . $message_id . '&' . $social_link . '" >' .
1112
            Display::return_icon('delete.png', get_lang('DeleteMessage')) . '</a>&nbsp';
1113
1114
        $message_content .= '</div></td>
1115
		      <td width=10></td>
1116
		    </tr>
1117
		</table>';
1118
1119
        return $message_content;
1120
    }
1121
1122
    /**
1123
     * get user id by user email
1124
     * @param string $user_email
1125
     * @return int user id
1126
     */
1127
    public static function get_user_id_by_email($user_email)
1128
    {
1129
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1130
        $sql = 'SELECT user_id FROM ' . $tbl_user . '
1131
                WHERE email="' . Database::escape_string($user_email) . '";';
1132
        $rs = Database::query($sql);
1133
        $row = Database::fetch_array($rs, 'ASSOC');
1134
        if (isset($row['user_id'])) {
1135
            return $row['user_id'];
1136
        } else {
1137
            return null;
1138
        }
1139
    }
1140
1141
    /**
1142
     * Displays messages of a group with nested view
1143
     *
1144
     * @param int $group_id
1145
     */
1146
    public static function display_messages_for_group($group_id)
1147
    {
1148
        global $my_group_role;
1149
1150
        $rows = self::get_messages_by_group($group_id);
1151
        $topics_per_page = 10;
1152
        $html_messages = '';
1153
        $query_vars = array('id' => $group_id, 'topics_page_nr' => 0);
1154
1155
        if (is_array($rows) && count($rows) > 0) {
1156
            // prepare array for topics with its items
1157
            $topics = array();
1158
            $x = 0;
1159
            foreach ($rows as $index => $value) {
1160
                if (empty($value['parent_id'])) {
1161
                    $topics[$value['id']] = $value;
1162
                }
1163
            }
1164
1165
            $new_topics = array();
1166
1167
            foreach ($topics as $id => $value) {
1168
                $rows = null;
1169
                $rows = self::get_messages_by_group_by_message($group_id, $value['id']);
1170
                if (!empty($rows)) {
1171
                    $count = count(self::calculate_children($rows, $value['id']));
1172
                } else {
1173
                    $count = 0;
1174
                }
1175
                $value['count'] = $count;
1176
                $new_topics[$id] = $value;
1177
            }
1178
1179
            $array_html = array();
1180
1181
            foreach ($new_topics as $index => $topic) {
1182
                $html = '';
1183
                // topics
1184
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1185
                $name = $user_sender_info['complete_name'];
1186
                $html .= '<div class="groups-messages">';
1187
                $html .= '<div class="row">';
1188
1189
                $items = $topic['count'];
1190
                $reply_label = ($items == 1) ? get_lang('GroupReply') : get_lang('GroupReplies');
1191
                $label = '<i class="fa fa-envelope"></i> ' . $items . ' ' . $reply_label;
1192
                $topic['title'] = trim($topic['title']);
1193
1194
                if (empty($topic['title'])) {
1195
                    $topic['title'] = get_lang('Untitled');
1196
                }
1197
1198
                $html .= '<div class="col-xs-8 col-md-10">';
1199
                $html .= Display::tag(
1200
                    'h4',
1201
                    Display::url(
1202
                        Security::remove_XSS($topic['title'], STUDENT, true),
1203
                        api_get_path(WEB_CODE_PATH) . 'social/group_topics.php?id=' . $group_id . '&topic_id=' . $topic['id']
1204
                    ), array('class' => 'title')
1205
                );
1206
                $actions = '';
1207
                if ($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1208
                    $my_group_role == GROUP_USER_PERMISSION_MODERATOR
1209
                ) {
1210
                    $actions = '<br />' . Display::url(get_lang('Delete'), api_get_path(WEB_CODE_PATH) . 'social/group_topics.php?action=delete&id=' . $group_id . '&topic_id=' . $topic['id'], array('class' => 'btn btn-default'));
1211
                }
1212
1213
                $date = '';
1214
                if ($topic['send_date'] != $topic['update_date']) {
1215
                    if (!empty($topic['update_date'])) {
1216
                        $date .= '<i class="fa fa-calendar"></i> ' . get_lang('LastUpdate') . ' ' . date_to_str_ago($topic['update_date']);
1217
                    }
1218
                } else {
1219
                    $date .= '<i class="fa fa-calendar"></i> ' . get_lang('Created') . ' ' . date_to_str_ago($topic['send_date']);
1220
                }
1221
                $html .= '<div class="date">' . $label . ' - ' . $date . $actions . '</div>';
1222
                $html .= '</div>';
1223
1224
                $image = $user_sender_info['avatar'];
1225
1226
                $user_info = '<div class="author"><img class="img-responsive img-circle" src="' . $image . '" alt="' . $name . '"  width="64" height="64" title="' . $name . '" /></div>';
1227
                $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>';
1228
1229
                $html .= '<div class="col-xs-4 col-md-2">';
1230
                $html .= $user_info;
1231
                $html .= '</div>';
1232
                $html .= '</div>';
1233
                $html .= '</div>';
1234
1235
                $array_html[] = array($html);
1236
            }
1237
1238
            // grids for items and topics  with paginations
1239
            $html_messages .= Display::return_sortable_grid(
1240
                'topics',
1241
                array(),
1242
                $array_html,
1243
                array(
1244
                    'hide_navigation' => false,
1245
                    'per_page' => $topics_per_page
1246
                ),
1247
                $query_vars,
1248
                false,
1249
                array(true, true, true, false),
1250
                false
1251
            );
1252
        }
1253
1254
        return $html_messages;
1255
    }
1256
1257
    /**
1258
     * Displays messages of a group with nested view
1259
     * @param $group_id
1260
     * @param $topic_id
1261
     * @param $is_member
1262
     * @param $message_id
1263
     * @return string
1264
     */
1265
    public static function display_message_for_group($group_id, $topic_id, $is_member, $message_id)
1266
    {
1267
        global $my_group_role;
1268
        $main_message = self::get_message_by_id($topic_id);
1269
        if (empty($main_message)) {
1270
            return false;
1271
        }
1272
        $rows = self::get_messages_by_group_by_message($group_id, $topic_id);
1273
        $rows = self::calculate_children($rows, $topic_id);
0 ignored issues
show
Security Bug introduced by
It seems like $rows can also be of type false; however, MessageManager::calculate_children() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
1274
        $current_user_id = api_get_user_id();
1275
1276
        $items_per_page = 50;
1277
        $query_vars = array('id' => $group_id, 'topic_id' => $topic_id, 'topics_page_nr' => 0);
1278
1279
        // Main message
1280
        $links = '';
1281
        $main_content = '';
1282
        $html = '';
1283
        $items_page_nr = null;
1284
1285
        $user_sender_info = api_get_user_info($main_message['user_sender_id']);
1286
        $files_attachments = self::get_links_message_attachment_files($main_message['id']);
1287
        $name = $user_sender_info['complete_name'];
1288
1289
        $topic_page_nr = isset($_GET['topics_page_nr']) ? intval($_GET['topics_page_nr']) : null;
1290
1291
        $links .= '<div class="pull-right">';
1292
        $links .= '<div class="btn-group btn-group-sm">';
1293
1294
        if (($my_group_role == GROUP_USER_PERMISSION_ADMIN ||
1295
                $my_group_role == GROUP_USER_PERMISSION_MODERATOR) ||
1296
            $main_message['user_sender_id'] == $current_user_id
1297
        ) {
1298
            $urlEdit = api_get_path(WEB_CODE_PATH);
1299
            $urlEdit .= 'social/message_for_group_form.inc.php?';
1300
            $urlEdit .= http_build_query([
1301
                'user_friend' => $current_user_id,
1302
                'group_id' => $group_id,
1303
                'message_id' => $main_message['id'],
1304
                'action' => 'edit_message_group',
1305
                'anchor_topic' => 'topic_' . $main_message['id'],
1306
                'topics_page_nr' => $topic_page_nr,
1307
                'items_page_nr' => $items_page_nr,
1308
                'topic_id' => $main_message['id']
1309
            ]);
1310
            if (api_is_platform_admin()) {
1311
                $links .= Display::url(
1312
                    Display::returnFontAwesomeIcon('trash'),
1313
                    'group_topics.php?action=delete&id=' . $group_id . '&topic_id=' . $topic_id,
1314
                    [
1315
                        'class' => 'btn btn-default'
1316
                    ]
1317
                );
1318
            }
1319
            $links .= Display::url(
1320
                Display::returnFontAwesomeIcon('pencil'),
1321
                $urlEdit,
1322
                [
1323
                    'class' => 'btn btn-default ajax',
1324
                    'title' => get_lang('Edit'),
1325
                    'data-title' => get_lang('Edit'),
1326
                    'data-size' => 'lg'
1327
                ]
1328
            );
1329
        }
1330
1331
        $urlReply = api_get_path(WEB_CODE_PATH);
1332
        $urlReply .= 'social/message_for_group_form.inc.php?';
1333
        $urlReply .= http_build_query([
1334
            'user_friend' => api_get_user_id(),
1335
            'group_id' => $group_id,
1336
            'message_id' => $main_message['id'],
1337
            'action' => 'reply_message_group',
1338
            'anchor_topic' => 'topic_' . $main_message['id'],
1339
            'topics_page_nr' => $topic_page_nr,
1340
            'topic_id' => $main_message['id']
1341
        ]);
1342
1343
        $links .= Display::url(
1344
            Display::returnFontAwesomeIcon('commenting'),
1345
            $urlReply,
1346
            [
1347
                'class' => 'btn btn-default ajax',
1348
                'title' => get_lang('Reply'),
1349
                'data-title' => get_lang('Reply'),
1350
                'data-size' => 'lg'
1351
            ]
1352
        );
1353
        $links .= '</div>';
1354
        $links .= '</div>';
1355
1356
        $title = '<h4>' . Security::remove_XSS($main_message['title'], STUDENT, true) . $links . '</h4>';
1357
1358
        $userPicture = $user_sender_info['avatar'];
1359
        $main_content .= '<div class="row">';
1360
        $main_content .= '<div class="col-md-2">';
1361
        $main_content .= '<div class="avatar-author">';
1362
        $main_content .= '<img width="60px" src="' . $userPicture . '" alt="' . $name . '" class="img-responsive img-circle" title="' . $name . '" />';
1363
        $main_content .= '</div>';
1364
        $main_content .= '</div>';
1365
1366
        $date = '';
1367 View Code Duplication
        if ($main_message['send_date'] != $main_message['update_date']) {
1368
            if (!empty($main_message['update_date'])) {
1369
                $date = '<div class="date"> '. Display::returnFontAwesomeIcon('calendar') .' ' . get_lang('LastUpdate') . ' ' . date_to_str_ago($main_message['update_date']) . '</div>';
1370
            }
1371
        } else {
1372
            $date = '<div class="date"> ' . Display::returnFontAwesomeIcon('calendar') .' ' . get_lang('Created') . ' ' . date_to_str_ago($main_message['send_date']) . '</div>';
1373
        }
1374
        $attachment = '<div class="message-attach">' . (!empty($files_attachments) ? implode('<br />', $files_attachments) : '') . '</div>';
1375
        $main_content .= '<div class="col-md-10">';
1376
        $user_link = '<a href="' . api_get_path(WEB_PATH) . 'main/social/profile.php?u=' . $main_message['user_sender_id'] . '">' . $name . '</a>';
1377
        $main_content .= '<div class="message-content"> ';
1378
        $main_content .= '<div class="username">' . $user_link . '</div>';
1379
        $main_content .= $date ;
1380
        $main_content .= '<div class="message">'. $main_message['content'] . $attachment . '</div></div>';
1381
        $main_content .= '</div>';
1382
        $main_content .= '</div>';
1383
1384
        $html .= Display::div(
1385
            Display::div(
1386
                $title.$main_content,
1387
                array('class' => 'message-topic')
1388
            ),
1389
            array('class' => 'sm-groups-message')
1390
        );
1391
1392
        $topic_id = $main_message['id'];
1393
1394
        if (is_array($rows) && count($rows) > 0) {
1395
            $topics = $rows;
1396
            $array_html_items = array();
1397
            foreach ($topics as $index => $topic) {
1398
                if (empty($topic['id'])) {
1399
                    continue;
1400
                }
1401
                $items_page_nr = isset($_GET['items_' . $topic['id'] . '_page_nr']) ? intval($_GET['items_' . $topic['id'] . '_page_nr']) : null;
1402
                $links = '';
1403
                $links .= '<div class="pull-right">';
1404
                $html_items = '';
1405
                $user_sender_info = api_get_user_info($topic['user_sender_id']);
1406
                $files_attachments = self::get_links_message_attachment_files($topic['id']);
1407
                $name = $user_sender_info['complete_name'];
1408
1409
                $links .= '<div class="btn-group btn-group-sm">';
1410
                if (($my_group_role == GROUP_USER_PERMISSION_ADMIN || $my_group_role == GROUP_USER_PERMISSION_MODERATOR) || $topic['user_sender_id'] == $current_user_id) {
1411
                    $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') . '">' .
1412
                        Display::returnFontAwesomeIcon('pencil') . '</a>';
1413
                }
1414
                $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') . '">';
1415
                $links .= Display::returnFontAwesomeIcon('commenting') . '</a>';
1416
                $links .= '</div>';
1417
                $links .= '</div>';
1418
1419
                $userPicture = $user_sender_info['avatar'];
1420
                $user_link = '<a href="' . api_get_path(WEB_PATH) . 'main/social/profile.php?u=' . $topic['user_sender_id'] . '">' . $name . '&nbsp</a>';
1421
                $html_items .= '<div class="row">';
1422
                $html_items .= '<div class="col-md-2">';
1423
                $html_items .= '<div class="avatar-author"><img width="60px" src="' . $userPicture . '" alt="' . $name . '" class="img-responsive img-circle" title="' . $name . '" /></div>';
1424
                $html_items .= '</div>';
1425
1426
                $date = '';
1427 View Code Duplication
                if ($topic['send_date'] != $topic['update_date']) {
1428
                    if (!empty($topic['update_date'])) {
1429
                        $date = '<div class="date"> ' . Display::returnFontAwesomeIcon('calendar') .' '. get_lang('LastUpdate') . ' ' . date_to_str_ago($topic['update_date']) . '</div>';
1430
                    }
1431
                } else {
1432
                    $date = '<div class="date"> ' . Display::returnFontAwesomeIcon('calendar') . get_lang('Created') . ' ' . date_to_str_ago($topic['send_date']) . '</div>';
1433
                }
1434
                $attachment = '<div class="message-attach">' . (!empty($files_attachments) ? implode('<br />', $files_attachments) : '') . '</div>';
1435
                $html_items .= '<div class="col-md-10">';
1436
                $html_items .= '<div class="message-content">';
1437
                $html_items .= $links;
1438
                $html_items .= '<div class="username">' . $user_link . '</div>';
1439
                $html_items .= $date;
1440
                $html_items .=  '<div class="message">' . Security::remove_XSS($topic['content'], STUDENT, true) . '</div>' . $attachment . '</div>';
1441
                $html_items .= '</div>';
1442
                $html_items .= '</div>';
1443
1444
                $base_padding = 20;
1445
1446
                if ($topic['indent_cnt'] == 0) {
1447
                    $indent = $base_padding;
1448
                } else {
1449
                    $indent = intval($topic['indent_cnt']) * $base_padding + $base_padding;
1450
                }
1451
1452
                $html_items = Display::div($html_items, array('class' => 'message-post', 'id' => 'msg_' . $topic['id']));
1453
                $html_items = Display::div($html_items, array('class' => '', 'style' => 'margin-left:' . $indent . 'px'));
1454
                $array_html_items[] = array($html_items);
1455
            }
1456
            // grids for items with paginations
1457
            $options = array('hide_navigation' => false, 'per_page' => $items_per_page);
1458
            $visibility = array(true, true, true, false);
1459
1460
            $style_class = array(
1461
                'item' => array('class' => 'user-post'),
1462
                'main' => array('class' => 'user-list'),
1463
            );
1464
            if (!empty($array_html_items)) {
1465
                $html .= Display::return_sortable_grid(
1466
                    'items_' . $topic['id'],
0 ignored issues
show
Bug introduced by
The variable $topic seems to be defined by a foreach iteration on line 1397. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
1467
                    array(),
1468
                    $array_html_items,
1469
                    $options,
1470
                    $query_vars,
1471
                    null,
1472
                    $visibility,
1473
                    false,
1474
                    $style_class
1475
                );
1476
            }
1477
        }
1478
1479
        return $html;
1480
    }
1481
1482
    /**
1483
     * Add children to messages by id is used for nested view messages
1484
     * @param array $rows rows of messages
1485
     * @return array $first_seed new list adding the item children
1486
     */
1487
    public static function calculate_children($rows, $first_seed)
1488
    {
1489
        $rows_with_children = array();
1490
        foreach ($rows as $row) {
1491
            $rows_with_children[$row["id"]] = $row;
1492
            $rows_with_children[$row["parent_id"]]["children"][] = $row["id"];
1493
        }
1494
        $rows = $rows_with_children;
1495
        $sorted_rows = array(0 => array());
1496
        self::message_recursive_sort($rows, $sorted_rows, $first_seed);
1497
        unset($sorted_rows[0]);
1498
1499
        return $sorted_rows;
1500
    }
1501
1502
    /**
1503
     * Sort recursively the messages, is used for for nested view messages
1504
     * @param array  original rows of messages
1505
     * @param array  list recursive of messages
1506
     * @param int   seed for calculate the indent
1507
     * @param int   indent for nested view
1508
     * @return void
1509
     */
1510
    public static function message_recursive_sort($rows, &$messages, $seed = 0, $indent = 0)
1511
    {
1512
        if ($seed > 0 && isset($rows[$seed]["id"])) {
1513
            $messages[$rows[$seed]["id"]] = $rows[$seed];
1514
            $messages[$rows[$seed]["id"]]["indent_cnt"] = $indent;
1515
            $indent++;
1516
        }
1517
1518
        if (isset($rows[$seed]["children"])) {
1519
            foreach ($rows[$seed]["children"] as $child) {
1520
                self::message_recursive_sort($rows, $messages, $child, $indent);
1521
            }
1522
        }
1523
    }
1524
1525
    /**
1526
     * Sort date by desc from a multi-dimensional array
1527
     * @param array $array1 first array to compare
1528
     * @param array $array2 second array to compare
1529
     * @return bool
1530
     */
1531
    public function order_desc_date($array1, $array2)
1532
    {
1533
        return strcmp($array2['send_date'], $array1['send_date']);
1534
    }
1535
1536
    /**
1537
     * Get array of links (download) for message attachment files
1538
     * @param int $message_id
1539
     * @param string $type message list (inbox/outbox)
1540
     * @return array
1541
     */
1542
    public static function get_links_message_attachment_files($message_id, $type = '')
1543
    {
1544
        $tbl_message_attach = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1545
        $message_id = intval($message_id);
1546
1547
        // get file attachments by message id
1548
        $links_attach_file = array();
1549
        if (!empty($message_id)) {
1550
1551
            $sql = "SELECT * FROM $tbl_message_attach
1552
                    WHERE message_id = '$message_id'";
1553
1554
            $rs_file = Database::query($sql);
1555
            if (Database::num_rows($rs_file) > 0) {
1556
                $attach_icon = Display::return_icon('attachment.gif', '');
1557
                $archiveURL = api_get_path(WEB_CODE_PATH) . 'messages/download.php?type=' . $type . '&file=';
1558
                while ($row_file = Database::fetch_array($rs_file)) {
1559
                    $archiveFile = $row_file['path'];
1560
                    $filename = $row_file['filename'];
1561
                    $filesize = format_file_size($row_file['size']);
1562
                    $filecomment = Security::remove_XSS($row_file['comment']);
1563
                    $filename = Security::remove_XSS($filename);
1564
                    $links_attach_file[] = $attach_icon . '&nbsp;<a href="' . $archiveURL . $archiveFile . '">' . $filename . '</a>&nbsp;(' . $filesize . ')' . (!empty($filecomment) ? '&nbsp;-&nbsp;<i>' . $filecomment . '</i>' : '');
1565
                }
1566
            }
1567
        }
1568
        return $links_attach_file;
1569
    }
1570
1571
    /**
1572
     * Get message list by id
1573
     * @param int $message_id
1574
     * @return array
1575
     */
1576
    public static function get_message_by_id($message_id)
1577
    {
1578
        $tbl_message = Database::get_main_table(TABLE_MESSAGE);
1579
        $message_id = intval($message_id);
1580
        $sql = "SELECT * FROM $tbl_message
1581
                WHERE 
1582
                    id = '$message_id' AND 
1583
                    msg_status <> '" . MESSAGE_STATUS_DELETED . "' ";
1584
        $res = Database::query($sql);
1585
        $item = array();
1586
        if (Database::num_rows($res) > 0) {
1587
            $item = Database::fetch_array($res, 'ASSOC');
1588
        }
1589
        return $item;
1590
    }
1591
1592
    /**
1593
     * @param $id
1594
     * @param array $params
1595
     * @return string
1596
     */
1597
    public static function generate_message_form($id, $params = array())
1598
    {
1599
        $form = new FormValidator('send_message');
1600
        $form->addText('subject', get_lang('Subject'), false, ['id' => 'subject_id']);
1601
        $form->addTextarea('content', get_lang('Message'), ['id' => 'content_id', 'rows' => '5']);
1602
1603
        return $form->returnForm();
1604
    }
1605
1606
    /**
1607
     * @param $id
1608
     * @param array $params
1609
     * @return string
1610
     */
1611
    public static function generate_invitation_form($id, $params = array())
1612
    {
1613
        $form = new FormValidator('send_invitation');
1614
        $form->addTextarea('content', get_lang('AddPersonalMessage'), ['id' => 'content_invitation_id', 'rows' => 5]);
1615
        return $form->returnForm();
1616
    }
1617
1618
    //@todo this functions should be in the message class
1619
    /**
1620
     * @param string $keyword
1621
     * @return string
1622
     */
1623
    public static function inbox_display($keyword = '')
1624
    {
1625
        $success = get_lang('SelectedMessagesDeleted');
1626
        $success_read = get_lang('SelectedMessagesRead');
1627
        $success_unread = get_lang('SelectedMessagesUnRead');
1628
        $html = '';
1629
1630
        Session::write('message_search_keyword', $keyword);
1631
1632
        if (isset($_REQUEST['action'])) {
1633
            switch ($_REQUEST['action']) {
1634
                case 'mark_as_unread' :
1635
                    $number_of_selected_messages = count($_POST['id']);
1636
                    if (is_array($_POST['id'])) {
1637
                        foreach ($_POST['id'] as $index => $message_id) {
1638
                            MessageManager::update_message_status(api_get_user_id(), $message_id, MESSAGE_STATUS_UNREAD);
1639
                        }
1640
                    }
1641
                    $html .= Display::return_message(api_xml_http_response_encode($success_unread), 'normal', false);
1642
                    break;
1643
                case 'mark_as_read' :
1644
                    $number_of_selected_messages = count($_POST['id']);
1645
                    if (is_array($_POST['id'])) {
1646
                        foreach ($_POST['id'] as $index => $message_id) {
1647
                            MessageManager::update_message_status(api_get_user_id(), $message_id, MESSAGE_STATUS_NEW);
1648
                        }
1649
                    }
1650
                    $html .= Display::return_message(api_xml_http_response_encode($success_read), 'normal', false);
1651
                    break;
1652 View Code Duplication
                case 'delete' :
1653
                    $number_of_selected_messages = count($_POST['id']);
1654
                    foreach ($_POST['id'] as $index => $message_id) {
1655
                        MessageManager::delete_message_by_user_receiver(api_get_user_id(), $message_id);
1656
                    }
1657
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
1658
                    break;
1659 View Code Duplication
                case 'deleteone' :
1660
                    MessageManager::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
1661
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'confirmation', false);
1662
                    break;
1663
            }
1664
        }
1665
1666
        // display sortable table with messages of the current user
1667
        $table = new SortableTable(
1668
            'message_inbox',
1669
            array('MessageManager', 'get_number_of_messages'),
1670
            array('MessageManager', 'get_message_data'),
1671
            3,
1672
            20,
1673
            'DESC'
1674
        );
1675
        $table->set_header(0, '', false, array('style' => 'width:15px;'));
1676
        $table->set_header(1, get_lang('Messages'), false);
1677
        $table->set_header(2, get_lang('Date'), true, array('style' => 'width:180px;'));
1678
        $table->set_header(3, get_lang('Modify'), false, array('style' => 'width:70px;'));
1679
1680
        if (isset($_REQUEST['f']) && $_REQUEST['f'] == 'social') {
1681
            $parameters['f'] = 'social';
1682
            $table->set_additional_parameters($parameters);
1683
        }
1684
        $table->set_form_actions(
1685
            array(
1686
                'delete' => get_lang('DeleteSelectedMessages'),
1687
                'mark_as_unread' => get_lang('MailMarkSelectedAsUnread'),
1688
                'mark_as_read' => get_lang('MailMarkSelectedAsRead'),
1689
            )
1690
        );
1691
        $html .= $table->return_table();
1692
1693
        Session::erase('message_search_keyword');
1694
1695
        return $html;
1696
    }
1697
1698
    /**
1699
     * @param string $keyword
1700
     * @return null|string
1701
     */
1702
    public static function outbox_display($keyword = '')
1703
    {
1704
        $social_link = false;
1705
        if (isset($_REQUEST['f']) && $_REQUEST['f'] == 'social') {
1706
            $social_link = 'f=social';
1707
        }
1708
1709
        Session::write('message_sent_search_keyword', $keyword);
1710
1711
        $success = get_lang('SelectedMessagesDeleted') . '&nbsp</b><br /><a href="outbox.php?' . $social_link . '">' . get_lang('BackToOutbox') . '</a>';
1712
1713
        $html = null;
1714
        if (isset($_REQUEST['action'])) {
1715
            switch ($_REQUEST['action']) {
1716 View Code Duplication
                case 'delete':
1717
                    $number_of_selected_messages = count($_POST['id']);
1718
                    if ($number_of_selected_messages != 0) {
1719
                        foreach ($_POST['id'] as $index => $message_id) {
1720
                            MessageManager::delete_message_by_user_receiver(api_get_user_id(), $message_id);
1721
                        }
1722
                    }
1723
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
1724
                    break;
1725 View Code Duplication
                case 'deleteone':
1726
                    MessageManager::delete_message_by_user_receiver(api_get_user_id(), $_GET['id']);
1727
                    $html .= Display::return_message(api_xml_http_response_encode($success), 'normal', false);
1728
                    $html .= '<br/>';
1729
                    break;
1730
            }
1731
        }
1732
1733
        // display sortable table with messages of the current user
1734
        $table = new SortableTable(
1735
            'message_outbox',
1736
            array('MessageManager', 'get_number_of_messages_sent'),
1737
            array('MessageManager', 'get_message_data_sent'),
1738
            3,
1739
            20,
1740
            'DESC'
1741
        );
1742
1743
        $parameters['f'] = isset($_GET['f']) && $_GET['f'] == 'social' ? 'social' : null;
1744
        $table->set_additional_parameters($parameters);
1745
        $table->set_header(0, '', false, array('style' => 'width:15px;'));
1746
1747
        $table->set_header(1, get_lang('Messages'), false);
1748
        $table->set_header(2, get_lang('Date'), true, array('style' => 'width:160px;'));
1749
        $table->set_header(3, get_lang('Modify'), false, array('style' => 'width:70px;'));
1750
1751
        $table->set_form_actions(array('delete' => get_lang('DeleteSelectedMessages')));
1752
        $html .= $table->return_table();
1753
1754
        Session::erase('message_sent_search_keyword');
1755
1756
        return $html;
1757
    }
1758
1759
    /**
1760
     * Get the count of the last received messages for a user
1761
     * @param int $userId The user id
1762
     * @param int $lastId The id of the last received message
1763
     * @return int The count of new messages
1764
     */
1765
    public static function countMessagesFromLastReceivedMessage($userId, $lastId = 0)
1766
    {
1767
        $userId = intval($userId);
1768
        $lastId = intval($lastId);
1769
1770
        if (empty($userId)) {
1771
            return 0;
1772
        }
1773
1774
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
1775
1776
        $conditions = array(
1777
            'where' => array(
1778
                'user_receiver_id = ?' => $userId,
1779
                'AND msg_status = ?' => MESSAGE_STATUS_UNREAD,
1780
                'AND id > ?' => $lastId
1781
            )
1782
        );
1783
1784
        $result = Database::select('COUNT(1) AS qty', $messagesTable, $conditions);
1785
1786
        if (!empty($result)) {
1787
            $row = current($result);
1788
1789
            return $row['qty'];
1790
        }
1791
1792
        return 0;
1793
    }
1794
1795
    /**
1796
     * Get the data of the last received messages for a user
1797
     * @param int $userId The user id
1798
     * @param int $lastId The id of the last received message
1799
     * @return array
1800
     */
1801
    public static function getMessagesFromLastReceivedMessage($userId, $lastId = 0)
1802
    {
1803
        $userId = intval($userId);
1804
        $lastId = intval($lastId);
1805
1806
        if (empty($userId)) {
1807
            return 0;
1808
        }
1809
1810
        $messagesTable = Database::get_main_table(TABLE_MESSAGE);
1811
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1812
1813
        $sql = "SELECT m.*, u.user_id, u.lastname, u.firstname
1814
                FROM $messagesTable as m
1815
                INNER JOIN $userTable as u
1816
                ON m.user_sender_id = u.user_id
1817
                WHERE
1818
                    m.user_receiver_id = $userId AND
1819
                    m.msg_status = " . MESSAGE_STATUS_UNREAD . "
1820
                    AND m.id > $lastId
1821
                ORDER BY m.send_date DESC";
1822
1823
        $result = Database::query($sql);
1824
1825
        $messages = [];
1826
        if ($result !== false) {
1827
            while ($row = Database::fetch_assoc($result)) {
1828
                $messages[] = $row;
1829
            }
1830
        }
1831
1832
        return $messages;
1833
    }
1834
1835
    /**
1836
     * Check whether a message has attachments
1837
     * @param int $messageId The message id
1838
     * @return boolean Whether the message has attachments return true. Otherwise return false
1839
     */
1840
    public static function hasAttachments($messageId)
1841
    {
1842
        $messageId = intval($messageId);
1843
1844
        if (empty($messageId)) {
1845
            return false;
1846
        }
1847
1848
        $messageAttachmentTable = Database::get_main_table(TABLE_MESSAGE_ATTACHMENT);
1849
1850
        $conditions = array(
1851
            'where' => array(
1852
                'message_id = ?' => $messageId
1853
            )
1854
        );
1855
1856
        $result = Database::select('COUNT(1) AS qty', $messageAttachmentTable, $conditions, 'first');
1857
1858
        if (!empty($result)) {
1859
            if ($result['qty'] > 0) {
1860
                return true;
1861
            }
1862
        }
1863
1864
        return false;
1865
    }
1866
1867
    /**
1868
     * @param string $url
1869
     *
1870
     * @return FormValidator
1871
     */
1872
    public static function getSearchForm($url)
1873
    {
1874
        $form = new FormValidator('search', 'post', $url, null, [], FormValidator::LAYOUT_INLINE);
1875
1876
        $form->addElement('text', 'keyword');
1877
        $form->addButtonSearch(get_lang('Search'));
1878
1879
        return $form;
1880
    }
1881
1882
    /**
1883
     * Send a notification to all admins when a new user is registered
1884
     * @param User $user
1885
     */
1886
    public static function sendNotificationByRegisteredUser(User $user)
1887
    {
1888
        $tplMailBody = new Template(null, false, false, false, false, false, false);
1889
        $tplMailBody->assign('user', $user);
1890
        $tplMailBody->assign('is_western_name_order', api_is_western_name_order());
1891
        $tplMailBody->assign('manageUrl', api_get_path(WEB_CODE_PATH) . 'admin/user_edit.php?user_id=' . $user->getId());
1892
1893
        $layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin.tpl');
1894
1895
        $emailsubject = '[' . get_lang('UserRegistered') . '] ' . $user->getUsername();
1896
        $emailbody = $tplMailBody->fetch($layoutContent);
1897
1898
        $admins = UserManager::get_all_administrators();
1899
1900 View Code Duplication
        foreach ($admins as $admin_info) {
1901
            MessageManager::send_message(
1902
                $admin_info['user_id'],
1903
                $emailsubject,
1904
                $emailbody,
1905
                [],
1906
                [],
1907
                null,
1908
                null,
1909
                null,
1910
                null,
1911
                $user->getId()
1912
            );
1913
        }
1914
    }
1915
1916
    /**
1917
     * Get the error log from failed mailing
1918
     * This assumes a complex setup where you have a cron script regularly copying the mail queue log
1919
     * into app/cache/mail/mailq.
1920
     * This can be done with a cron command like (check the location of your mail log file first):
1921
     * @example 0,30 * * * * root cp /var/log/exim4/mainlog /var/www/chamilo/app/cache/mail/mailq
1922
     * @return array|bool
1923
     */
1924
    public static function failedSentMailErrors()
1925
    {
1926
        $base = api_get_path(SYS_ARCHIVE_PATH) . 'mail/';
1927
        $mailq = $base . 'mailq';
1928
1929
        if (!file_exists($mailq) || !is_readable($mailq)) {
1930
            return false;
1931
        }
1932
1933
        $file = fopen($mailq, 'r');
1934
        $i = 1;
1935
        while (!feof($file)) {
1936
            $line = fgets($file);
1937
            //$line = trim($line);
1938
1939
            if (trim($line) == '') {
1940
                continue;
1941
            }
1942
1943
            //Get the mail code, something like 1WBumL-0002xg-FF
1944
            if (preg_match('/(.*)\s((.*)-(.*)-(.*))\s<(.*)$/', $line, $codeMatches)) {
1945
                $mail_queue[$i]['code'] = $codeMatches[2];
1946
            }
1947
1948
            $fullMail = $base . $mail_queue[$i]['code'];
1949
            $mailFile = fopen($fullMail, 'r');
1950
1951
            //Get the reason of mail fail
1952
            $iX = 1;
1953
1954
            while (!feof($mailFile)) {
1955
                $mailLine = fgets($mailFile);
1956
                #if ($iX == 4 && preg_match('/(.*):\s(.*)$/', $mailLine, $matches)) {
1957
                if (
1958
                    $iX == 2 &&
1959
                    preg_match('/(.*)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s(.*)/', $mailLine, $detailsMatches)
1960
                ) {
1961
                    $mail_queue[$i]['reason'] = $detailsMatches[3];
1962
                }
1963
1964
                $iX++;
1965
            }
1966
1967
            fclose($mailFile);
1968
1969
            //Get the time of mail fail
1970
            if (preg_match('/^\s?(\d+)(\D+)\s+(.*)$/', $line, $timeMatches)) {
1971
                $mail_queue[$i]['time'] = $timeMatches[1] . $timeMatches[2];
1972
            } elseif (preg_match('/^(\s+)((.*)@(.*))\s+(.*)$/', $line, $emailMatches)) {
1973
                $mail_queue[$i]['mail'] = $emailMatches[2];
1974
                $i++;
1975
            }
1976
        }
1977
1978
        fclose($file);
1979
1980
        return array_reverse($mail_queue);
1981
    }
1982
}
1983