Test Setup Failed
Push — master ( f71949...6c6bd7 )
by Julito
55:21
created

forumfunction.inc.php ➔ updateThread()   D

Complexity

Conditions 12
Paths 121

Size

Total Lines 91
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 67
nc 121
nop 1
dl 0
loc 91
rs 4.6933
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Doctrine\Common\Collections\Criteria;
6
use Chamilo\CourseBundle\Entity\CForumPost;
7
use Chamilo\CourseBundle\Entity\CForumThread;
8
9
/**
10
 * These files are a complete rework of the forum. The database structure is
11
 * based on phpBB but all the code is rewritten. A lot of new functionalities
12
 * are added:
13
 * - forum categories and forums can be sorted up or down, locked or made invisible
14
 * - consistent and integrated forum administration
15
 * - forum options:     are students allowed to edit their post?
16
 *                         moderation of posts (approval)
17
 *                         reply only forums (students cannot create new threads)
18
 *                         multiple forums per group
19
 * - sticky messages
20
 * - new view option: nested view
21
 * - quoting a message
22
 *
23
 * @package chamilo.forum
24
 *
25
 * @todo several functions have to be moved to the itemmanager library
26
 * @todo displaying icons => display library
27
 * @todo complete the missing phpdoc the correct order should be
28
 * @todo convert into a class
29
 */
30
31
get_notifications_of_user();
32
33
$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui', 'jquery-upload'));
34
$htmlHeadXtra[] = '<script>
35
36
function check_unzip() {
37
    if (document.upload.unzip.checked){
38
        document.upload.if_exists[0].disabled=true;
39
        document.upload.if_exists[1].checked=true;
40
        document.upload.if_exists[2].disabled=true;
41
    } else {
42
        document.upload.if_exists[0].checked=true;
43
        document.upload.if_exists[0].disabled=false;
44
        document.upload.if_exists[2].disabled=false;
45
    }
46
}
47
function setFocus() {
48
    $("#title_file").focus();
49
}
50
</script>';
51
// The next javascript script is to manage ajax upload file
52
$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui', 'jquery-upload'));
53
54
// Recover Thread ID, will be used to generate delete attachment URL to do ajax
55
$threadId = isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : 0;
56
$forumId = isset($_REQUEST['forum']) ? intval($_REQUEST['forum']) : 0;
57
58
// The next javascript script is to delete file by ajax
59
$htmlHeadXtra[] = '<script>
60
$(function () {
61
    $(document).on("click", ".deleteLink", function(e) {
62
        e.preventDefault();
63
        e.stopPropagation();
64
        var l = $(this);
65
        var id = l.closest("tr").attr("id");
66
        var filename = l.closest("tr").find(".attachFilename").html();
67
        if (confirm("' . get_lang('AreYouSureToDeleteJS') . '", filename)) {
68
            $.ajax({
69
                type: "POST",
70
                url: "'.api_get_path(WEB_AJAX_PATH) . 'forum.ajax.php?'.api_get_cidreq().'&a=delete_file&attachId=" + id +"&thread='.$threadId .'&forum='.$forumId .'",
71
                dataType: "json",
72
                success: function(data) {
73
                    if (data.error == false) {
74
                        l.closest("tr").remove();
75
                        if ($(".files td").length < 1) {
76
                            $(".files").closest(".control-group").hide();
77
                        }
78
                    }
79
                }
80
            })
81
        }
82
    });
83
});
84
</script>';
85
86
/**
87
 * This function handles all the forum and forum categories actions. This is a wrapper for the
88
 * forum and forum categories. All this code code could go into the section where this function is
89
 * called but this make the code there cleaner.
90
 * @param int $lp_id Learning path Id
91
 *
92
 * @return void
93
 * @author Patrick Cool <[email protected]>, Ghent University
94
 * @author Juan Carlos Raña Trabado (return to lp_id)
95
 * @version may 2011, Chamilo 1.8.8
96
 */
97
function handle_forum_and_forumcategories($lp_id = null)
98
{
99
    $action_forum_cat = isset($_GET['action']) ? $_GET['action'] : '';
100
    $get_content = isset($_GET['content']) ? $_GET['content'] : '';
101
    $post_submit_cat = isset($_POST['SubmitForumCategory']) ? true : false;
102
    $post_submit_forum = isset($_POST['SubmitForum']) ? true : false;
103
    $get_id = isset($_GET['id']) ? intval($_GET['id']) : '';
104
    $forum_categories_list = get_forum_categories();
105
106
    //Verify if forum category exists
107
    if (empty($forum_categories_list)) {
108
        $get_content = 'forumcategory';
109
    }
110
111
    // Adding a forum category
112
    if (($action_forum_cat == 'add' && $get_content == 'forumcategory') || $post_submit_cat) {
113
        show_add_forumcategory_form(array(), $lp_id); //$lp_id when is called from learning path
114
    }
115
116
    // Adding a forum
117
    if ((($action_forum_cat == 'add' || $action_forum_cat == 'edit') && $get_content == 'forum') || $post_submit_forum) {
118
        if ($action_forum_cat == 'edit' && $get_id || $post_submit_forum) {
119
            $inputvalues = get_forums($get_id);
120
        } else {
121
            $inputvalues = array();
122
        }
123
        show_add_forum_form($inputvalues, $lp_id);
124
    }
125
126
    // Edit a forum category
127
    if (($action_forum_cat == 'edit' && $get_content == 'forumcategory') || (isset($_POST['SubmitEditForumCategory'])) ? true : false) {
128
        $forum_category = get_forum_categories($get_id);
129
        show_edit_forumcategory_form($forum_category);
130
    }
131
132
    // Delete a forum category
133
    if ($action_forum_cat == 'delete') {
134
        $id_forum = intval($get_id);
135
        $list_threads = get_threads($id_forum);
136
137
        for ($i = 0; $i < count($list_threads); $i++) {
138
            deleteForumCategoryThread('thread', $list_threads[$i]['thread_id']);
139
            $link_info = GradebookUtils::isResourceInCourseGradebook(
140
                api_get_course_int_id(),
141
                5,
142
                $list_threads[$i]['thread_id'],
143
                api_get_session_id()
144
            );
145
            if ($link_info !== false) {
146
                GradebookUtils::remove_resource_from_course_gradebook($link_info['id']);
147
            }
148
        }
149
        $return_message = deleteForumCategoryThread($get_content, $get_id);
150
        echo Display::return_message($return_message, 'confirmation', false);
151
    }
152
153
    // Change visibility of a forum or a forum category.
154
    if ($action_forum_cat == 'invisible' || $action_forum_cat == 'visible') {
155
        $return_message = change_visibility($get_content, $get_id, $action_forum_cat);
156
        echo Display::return_message($return_message, 'confirmation', false);
157
    }
158
    // Change lock status of a forum or a forum category.
159
    if ($action_forum_cat == 'lock' || $action_forum_cat == 'unlock') {
160
        $return_message = change_lock_status($get_content, $get_id, $action_forum_cat);
161
        echo Display::return_message($return_message, 'confirmation', false);
162
    }
163
    // Move a forum or a forum category.
164
    if ($action_forum_cat == 'move' && isset($_GET['direction'])) {
165
        $return_message = move_up_down($get_content, $_GET['direction'], $get_id);
166
        echo Display::return_message($return_message, 'confirmation', false);
167
    }
168
}
169
170
/**
171
 * This function displays the form that is used to add a forum category.
172
 *
173
 * @param  array $inputvalues (deprecated, set to null when calling)
174
 * @param  int $lp_id Learning path ID
175
 *
176
 * @author Patrick Cool <[email protected]>, Ghent University
177
 * @author Juan Carlos Raña Trabado (return to lp_id)
178
 * @version may 2011, Chamilo 1.8.8
179
 */
180
function show_add_forumcategory_form($inputvalues = array(), $lp_id)
181
{
182
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq());
183
    // hidden field if from learning path
184
    $form->addElement('hidden', 'lp_id', $lp_id);
185
    // Setting the form elements.
186
    $form->addElement('header', get_lang('AddForumCategory'));
187
    $form->addElement('text', 'forum_category_title', get_lang('Title'), array('autofocus'));
188
    $form->addElement(
189
        'html_editor',
190
        'forum_category_comment',
191
        get_lang('Description'),
192
        null,
193
        array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
194
    );
195
    $form->addButtonCreate(get_lang('CreateCategory'), 'SubmitForumCategory');
196
197
    // Setting the rules.
198
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
199
200
    // The validation or display
201 View Code Duplication
    if ($form->validate()) {
202
        $check = Security::check_token('post');
203
        if ($check) {
204
            $values = $form->exportValues();
205
            store_forumcategory($values);
206
        }
207
        Security::clear_token();
208
    } else {
209
        $token = Security::get_token();
210
        $form->addElement('hidden', 'sec_token');
211
        $form->setConstants(array('sec_token' => $token));
212
        $form->display();
213
    }
214
}
215
216
/**
217
 * This function displays the form that is used to add a forum category.
218
 *
219
 * @param array $inputvalues
220
 * @param int $lp_id
221
 * @return void HTML
222
 *
223
 * @author Patrick Cool <[email protected]>, Ghent University
224
 * @author Juan Carlos Raña Trabado (return to lp_id)
225
 *
226
 * @version may 2011, Chamilo 1.8.8
227
 */
228
function show_add_forum_form($inputvalues = array(), $lp_id)
229
{
230
    $_course = api_get_course_info();
231
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq());
232
233
    // The header for the form
234
    if (!empty($inputvalues)) {
235
        $form_title = get_lang('EditForum');
236
    } else {
237
        $form_title = get_lang('AddForum');
238
    }
239
240
    $form->addElement('header', $form_title);
241
242
    // We have a hidden field if we are editing.
243
    if (!empty($inputvalues) && is_array($inputvalues)) {
244
        $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
245
        $form->addElement('hidden', 'forum_id', $my_forum_id);
246
    }
247
    $lp_id = intval($lp_id);
248
249
    // hidden field if from learning path
250
    $form->addElement('hidden', 'lp_id', $lp_id);
251
252
    // The title of the forum
253
    $form->addElement('text', 'forum_title', get_lang('Title'), array('autofocus'));
254
255
    // The comment of the forum.
256
    $form->addElement(
257
        'html_editor',
258
        'forum_comment',
259
        get_lang('Description'),
260
        null,
261
        array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
262
    );
263
264
    // Dropdown list: Forum categories
265
    $forum_categories = get_forum_categories();
266
    foreach ($forum_categories as $key => $value) {
267
        $forum_categories_titles[$value['cat_id']] = $value['cat_title'];
268
    }
269
    $form->addElement('select', 'forum_category', get_lang('InForumCategory'), $forum_categories_titles);
270
    $form->applyFilter('forum_category', 'html_filter');
271
272
    if ($_course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) {
273
        // This is for horizontal
274
        $group = array();
275
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
276
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
277
        $form->addGroup($group, 'allow_anonymous_group', get_lang('AllowAnonymousPosts'));
278
    }
279
280
    $form->addButtonAdvancedSettings('advanced_params');
281
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
282
283
    $form->addDateTimePicker(
284
        'start_time',
285
        array(get_lang('ForumStartDate'), get_lang('ForumStartDateComment')),
286
        array('id' => 'start_time')
287
    );
288
289
    $form->addDateTimePicker(
290
        'end_time',
291
        array(get_lang('ForumEndDate'), get_lang('ForumEndDateComment')),
292
        array('id' => 'end_time')
293
    );
294
295
    $form->addRule(
296
        array('start_time', 'end_time'),
297
        get_lang('StartDateMustBeBeforeTheEndDate'),
298
        'compare_datetime_text',
299
        '< allow_empty'
300
    );
301
302
    $group = array();
303
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('Yes'), 1);
304
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('No'), 0);
305
    $form->addGroup($group, 'moderated', get_lang('ModeratedForum'));
306
307
    $group = array();
308
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
309
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
310
    $form->addGroup($group, 'students_can_edit_group', get_lang('StudentsCanEdit'));
311
312
    $group = array();
313
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
314
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
315
316
    $group = array();
317
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
318
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
319
320
    $group = array();
321
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
322
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
323
    $form->addGroup($group, 'allow_new_threads_group', get_lang('AllowNewThreads'));
324
325
    $group = array();
326
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
327
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
328
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
329
    $form->addGroup($group, 'default_view_type_group', get_lang('DefaultViewType'));
330
331
    // Drop down list: Groups
332
    $groups = GroupManager::get_group_list();
333
    $groups_titles[0] = get_lang('NotAGroupForum');
334
    foreach ($groups as $key => $value) {
335
        $groups_titles[$value['id']] = $value['name'];
336
    }
337
    $form->addElement('select', 'group_forum', get_lang('ForGroup'), $groups_titles);
338
339
    // Public or private group forum
340
    $group = array();
341
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public'), 'public');
342
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private'), 'private');
343
    $form->addGroup($group, 'public_private_group_forum_group', get_lang('PublicPrivateGroupForum'));
344
345
    // Forum image
346
    $form->addProgress();
347
    if (!empty($inputvalues['forum_image'])) {
348
        $baseImagePath = api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
349
        $image_path = api_get_path(WEB_COURSE_PATH).$baseImagePath;
350
        $sysImagePath = api_get_path(SYS_COURSE_PATH).$baseImagePath;
351
352
        if (file_exists($sysImagePath)) {
353
            $show_preview_image = Display::img($image_path, null, ['class' => 'img-responsive']);
354
            $form->addElement('label', get_lang('PreviewImage'), $show_preview_image);
355
            $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
356
        }
357
    }
358
    $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
359
    $form->addElement('file', 'picture', ($forum_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
360
    $form->addRule('picture', get_lang('OnlyImagesAllowed'), 'filetype', array('jpg', 'jpeg', 'png', 'gif'));
361
    $form->addElement('html', '</div>');
362
363
    // The OK button
364
    if (isset($_GET['id']) && $_GET['action'] == 'edit') {
365
        $form->addButtonUpdate(get_lang('ModifyForum'), 'SubmitForum');
366
    } else {
367
        $form->addButtonCreate(get_lang('CreateForum'), 'SubmitForum');
368
    }
369
370
    // setting the rules
371
    $form->addRule('forum_title', get_lang('ThisFieldIsRequired'), 'required');
372
    $form->addRule('forum_category', get_lang('ThisFieldIsRequired'), 'required');
373
374
    $defaultSettingAllowNewThreads = api_get_default_tool_setting('forum', 'allow_new_threads', 0);
375
376
    // Settings the defaults
377
    if (empty($inputvalues) || !is_array($inputvalues)) {
378
        $defaults['moderated']['moderated'] = 0;
379
        $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
380
        $defaults['students_can_edit_group']['students_can_edit'] = 0;
381
        $defaults['approval_direct_group']['approval_direct'] = 0;
382
        $defaults['allow_attachments_group']['allow_attachments'] = 1;
383
        $defaults['allow_new_threads_group']['allow_new_threads'] = $defaultSettingAllowNewThreads;
384
        $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
385
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
386
        if (isset($_GET['forumcategory'])) {
387
            $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
388
        }
389
    } else {
390
        // the default values when editing = the data in the table
391
        $defaults['forum_id'] = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
392
        $defaults['forum_title'] = prepare4display(isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null);
393
        $defaults['forum_comment'] = prepare4display(isset($inputvalues['forum_comment']) ? $inputvalues['forum_comment'] : null);
394
        $defaults['start_time'] = isset($inputvalues['start_time']) ? api_get_local_time($inputvalues['start_time']) : null;
395
        $defaults['end_time'] = isset($inputvalues['end_time']) ? api_get_local_time($inputvalues['end_time']) : null;
396
        $defaults['moderated']['moderated'] = isset($inputvalues['moderated']) ? $inputvalues['moderated'] : 0;
397
        $defaults['forum_category'] = isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
398
        $defaults['allow_anonymous_group']['allow_anonymous'] = isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] : null;
399
        $defaults['students_can_edit_group']['students_can_edit'] = isset($inputvalues['allow_edit']) ? $inputvalues['allow_edit'] : null;
400
        $defaults['approval_direct_group']['approval_direct'] = isset($inputvalues['approval_direct_post']) ? $inputvalues['approval_direct_post'] : null;
401
        $defaults['allow_attachments_group']['allow_attachments'] = isset($inputvalues['allow_attachments']) ? $inputvalues['allow_attachments'] : null;
402
        $defaults['allow_new_threads_group']['allow_new_threads'] = isset($inputvalues['allow_new_threads']) ? $inputvalues['allow_new_threads'] : $defaultSettingAllowNewThreads;
403
        $defaults['default_view_type_group']['default_view_type'] = isset($inputvalues['default_view']) ? $inputvalues['default_view'] : null;
404
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = isset($inputvalues['forum_group_public_private']) ? $inputvalues['forum_group_public_private'] : null;
405
        $defaults['group_forum'] = isset($inputvalues['forum_of_group']) ? $inputvalues['forum_of_group'] : null;
406
    }
407
    $form->setDefaults($defaults);
408
    // Validation or display
409 View Code Duplication
    if ($form->validate()) {
410
        $check = Security::check_token('post');
411
        if ($check) {
412
            $values = $form->getSubmitValues();
413
            $return_message = store_forum($values);
414
            echo Display::return_message($return_message, 'confirmation');
0 ignored issues
show
Security Bug introduced by
It seems like $return_message defined by store_forum($values) on line 413 can also be of type false; however, Display::return_message() does only seem to accept string, 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...
415
        }
416
        Security::clear_token();
417
    } else {
418
        $token = Security::get_token();
419
        $form->addElement('hidden', 'sec_token');
420
        $form->setConstants(array('sec_token' => $token));
421
        $form->display();
422
    }
423
}
424
425
/**
426
 * This function deletes the forum image if exists
427
 *
428
 * @param int forum id
429
 * @return boolean true if success
430
 * @author Julio Montoya <[email protected]>
431
 * @version february 2006, dokeos 1.8
432
 */
433
function delete_forum_image($forum_id)
434
{
435
    $table_forums = Database::get_course_table(TABLE_FORUM);
436
    $course_id = api_get_course_int_id();
437
    $forum_id = intval($forum_id);
438
439
    $sql = "SELECT forum_image FROM $table_forums
440
            WHERE forum_id = $forum_id AND c_id = $course_id";
441
    $result = Database::query($sql);
442
    $row = Database::fetch_array($result);
443
    if ($row['forum_image'] != '') {
444
        $file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
445
        if (file_exists($file)) {
446
            unlink($file);
447
        }
448
449
        return true;
450
    } else {
451
        return false;
452
    }
453
}
454
455
/**
456
 * This function displays the form that is used to edit a forum category.
457
 * This is more or less a copy from the show_add_forumcategory_form function with the only difference that is uses
458
 * some default values. I tried to have both in one function but this gave problems with the handle_forum_and_forumcategories function
459
 * (storing was done twice)
460
 *
461
 * @param array
462
 * @return void HTML
463
 *
464
 * @author Patrick Cool <[email protected]>, Ghent University
465
 * @version february 2006, dokeos 1.8
466
 */
467
function show_edit_forumcategory_form($inputvalues = array())
468
{
469
    $categoryId = $inputvalues['cat_id'];
470
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq().'&id='.$categoryId);
471
472
    // Setting the form elements.
473
    $form->addElement('header', '', get_lang('EditForumCategory'));
474
    $form->addElement('hidden', 'forum_category_id');
475
    $form->addElement('text', 'forum_category_title', get_lang('Title'));
476
477
    $form->addElement(
478
        'html_editor',
479
        'forum_category_comment',
480
        get_lang('Comment'),
481
        null,
482
        array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
483
    );
484
485
    $form->addButtonUpdate(get_lang('ModifyCategory'), 'SubmitEditForumCategory');
486
487
    // Setting the default values.
488
    $defaultvalues['forum_category_id'] = $inputvalues['cat_id'];
489
    $defaultvalues['forum_category_title'] = $inputvalues['cat_title'];
490
    $defaultvalues['forum_category_comment'] = $inputvalues['cat_comment'];
491
    $form->setDefaults($defaultvalues);
492
493
    // Setting the rules.
494
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
495
496
    // Validation or display
497 View Code Duplication
    if ($form->validate()) {
498
        $check = Security::check_token('post');
499
        if ($check) {
500
            $values = $form->exportValues();
501
            store_forumcategory($values);
502
        }
503
        Security::clear_token();
504
    } else {
505
        $token = Security::get_token();
506
        $form->addElement('hidden', 'sec_token');
507
        $form->setConstants(array('sec_token' => $token));
508
        $form->display();
509
    }
510
}
511
512
/**
513
 * This function stores the forum category in the database.
514
 * The new category is added to the end.
515
 *
516
 * @param array $values
517
 * @param array $courseInfo
518
 * @param bool $showMessage
519
 * @return void HMTL language variable
520
 *
521
 * @author Patrick Cool <[email protected]>, Ghent University
522
 * @version february 2006, dokeos 1.8
523
 */
524
function store_forumcategory($values, $courseInfo = array(), $showMessage = true)
525
{
526
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
527
    $course_id = $courseInfo['real_id'];
528
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
529
530
    // Find the max cat_order. The new forum category is added at the end => max cat_order + &
531
    $sql = "SELECT MAX(cat_order) as sort_max
532
            FROM $table_categories
533
            WHERE c_id = $course_id";
534
    $result = Database::query($sql);
535
    $row = Database::fetch_array($result);
536
    $new_max = $row['sort_max'] + 1;
537
    $session_id = api_get_session_id();
538
    $clean_cat_title = $values['forum_category_title'];
539
    $last_id = null;
540
541
    if (isset($values['forum_category_id'])) {
542
        // Storing after edition.
543
        $params = [
544
            'cat_title' => $clean_cat_title,
545
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
546
        ];
547
548
        Database::update(
549
            $table_categories,
550
            $params,
551
            [
552
                'c_id = ? AND cat_id = ?' => [
553
                    $course_id,
554
                    $values['forum_category_id'],
555
                ],
556
            ]
557
        );
558
559
        api_item_property_update(
560
            $courseInfo,
561
            TOOL_FORUM_CATEGORY,
562
            $values['forum_category_id'],
563
            'ForumCategoryUpdated',
564
            api_get_user_id()
565
        );
566
        $return_message = get_lang('ForumCategoryEdited');
567
    } else {
568
        $params = [
569
            'c_id' => $course_id,
570
            'cat_title' => $clean_cat_title,
571
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
572
            'cat_order' => $new_max,
573
            'session_id' => $session_id,
574
            'locked' => 0,
575
            'cat_id' => 0
576
        ];
577
        $last_id = Database::insert($table_categories, $params);
578
579
        if ($last_id > 0) {
580
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
581
            Database::query($sql);
582
583
            api_item_property_update(
584
                $courseInfo,
585
                TOOL_FORUM_CATEGORY,
586
                $last_id,
587
                'ForumCategoryAdded',
588
                api_get_user_id()
589
            );
590
            api_set_default_visibility(
591
                $last_id,
592
                TOOL_FORUM_CATEGORY,
593
                0,
594
                $courseInfo
595
            );
596
        }
597
        $return_message = get_lang('ForumCategoryAdded');
598
    }
599
600
    if ($showMessage) {
601
        echo Display::return_message($return_message, 'confirmation');
602
    }
603
604
    return $last_id;
605
}
606
607
/**
608
 * This function stores the forum in the database. The new forum is added to the end.
609
 *
610
 * @param array $values
611
 * @param array $courseInfo
612
 * @param bool  $returnId
613
 * @return string language variable
614
 *
615
 * @author Patrick Cool <[email protected]>, Ghent University
616
 * @version february 2006, dokeos 1.8
617
 */
618
function store_forum($values, $courseInfo = array(), $returnId = false)
619
{
620
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
621
    $course_id = $courseInfo['real_id'];
622
    $session_id = api_get_session_id();
623
624
    if (isset($values['group_id']) && !empty($values['group_id'])) {
625
        $group_id = $values['group_id'];
626
    } else {
627
        $group_id = api_get_group_id();
628
    }
629
    $groupInfo = [];
630
    if (!empty($group_id)) {
631
        $groupInfo = GroupManager::get_group_properties($group_id);
632
    }
633
634
    $table_forums = Database::get_course_table(TABLE_FORUM);
635
636
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
637
    if (is_null($values['forum_category'])) {
638
        $new_max = null;
639
    } else {
640
        $sql = "SELECT MAX(forum_order) as sort_max
641
                FROM $table_forums
642
                WHERE
643
                    c_id = $course_id AND
644
                    forum_category='".Database::escape_string($values['forum_category'])."'";
645
        $result = Database::query($sql);
646
        $row = Database::fetch_array($result);
647
        $new_max = $row['sort_max'] + 1;
648
    }
649
650
    // Forum images
651
    $image_moved = false;
652
    $has_attachment = false;
653
    if (!empty($_FILES['picture']['name'])) {
654
        $upload_ok = process_uploaded_file($_FILES['picture']);
655
        $has_attachment = true;
656
    } else {
657
        $image_moved = true;
658
    }
659
660
    // Remove existing picture if it was requested.
661
    if (!empty($_POST['remove_picture'])) {
662
        delete_forum_image($values['forum_id']);
663
    }
664
665
    $new_file_name = '';
666
    if (isset($upload_ok)) {
667
        if ($has_attachment) {
668
            $course_dir = $courseInfo['path'].'/upload/forum/images';
669
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
670
            $updir = $sys_course_path.$course_dir;
671
            // Try to add an extension to the file if it hasn't one.
672
            $new_file_name = add_ext_on_mime(
673
                Database::escape_string($_FILES['picture']['name']),
674
                $_FILES['picture']['type']
675
            );
676
            if (!filter_extension($new_file_name)) {
677
                //Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
678
                $image_moved = false;
679
            } else {
680
                $file_extension = explode('.', $_FILES['picture']['name']);
681
                $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
682
                $new_file_name = uniqid('').'.'.$file_extension;
683
                $new_path = $updir.'/'.$new_file_name;
684
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
685
                // Storing the attachments if any
686
                if ($result) {
687
                    $image_moved = true;
688
                }
689
            }
690
        }
691
    }
692
693
    if (isset($values['forum_id'])) {
694
        // Storing after edition.
695
        $params = [
696
            'forum_title'=> $values['forum_title'],
697
            'forum_comment'=> isset($values['forum_comment']) ? $values['forum_comment'] : null,
698
            'forum_category'=> isset($values['forum_category']) ? $values['forum_category'] : null,
699
            'allow_anonymous'=> isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
700
            'allow_edit'=> isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
701
            'approval_direct_post'=> isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
702
            'allow_attachments'=> isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
703
            'allow_new_threads'=> isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
704
            'default_view'=> isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
705
            'forum_of_group'=> isset($values['group_forum']) ? $values['group_forum'] : null,
706
            'forum_group_public_private'=> isset($values['public_private_group_forum_group']['public_private_group_forum']) ? $values['public_private_group_forum_group']['public_private_group_forum'] : null,
707
            'moderated'=> $values['moderated']['moderated'],
708
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
709
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
710
            'session_id'=> $session_id,
711
            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0
712
        ];
713
714
        if (isset($upload_ok)) {
715
            if ($has_attachment) {
716
                $params['forum_image'] = $new_file_name;
717
            }
718
        }
719
720
        if (isset($values['remove_picture']) && $values['remove_picture'] == 1) {
721
            $params['forum_image'] = '';
722
            delete_forum_image($values['forum_id']);
723
        }
724
725
        Database::update(
726
            $table_forums,
727
            $params,
728
            ['c_id = ? AND forum_id = ?' => [$course_id, $values['forum_id']]]
729
        );
730
731
        api_item_property_update(
732
            $courseInfo,
733
            TOOL_FORUM,
734
            Database::escape_string($values['forum_id']),
735
            'ForumUpdated',
736
            api_get_user_id(),
737
            $groupInfo
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($group_id) on line 631 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
738
        );
739
740
        $return_message = get_lang('ForumEdited');
741
    } else {
742
        if ($image_moved) {
743
            $new_file_name = isset($new_file_name) ? $new_file_name : '';
744
        }
745
        $params = [
746
            'c_id' => $course_id,
747
            'forum_title'=> $values['forum_title'],
748
            'forum_image'=> $new_file_name,
749
            'forum_comment'=> isset($values['forum_comment']) ? $values['forum_comment'] : null,
750
            'forum_category'=> isset($values['forum_category']) ? $values['forum_category'] : null,
751
            'allow_anonymous'=> isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
752
            'allow_edit'=> isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
753
            'approval_direct_post'=> isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
754
            'allow_attachments'=> isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
755
            'allow_new_threads'=> isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
756
            'default_view'=> isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
757
            'forum_of_group'=> isset($values['group_forum']) ? $values['group_forum'] : null,
758
            'forum_group_public_private'=> isset($values['public_private_group_forum_group']['public_private_group_forum']) ? $values['public_private_group_forum_group']['public_private_group_forum'] : null,
759
            'moderated'=> isset($values['moderated']['moderated']) ? (int) $values['moderated']['moderated'] : 0,
760
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
761
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
762
            'forum_order'=> isset($new_max) ? $new_max : null,
763
            'session_id'=> $session_id,
764
            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0,
765
            'locked' => 0,
766
            'forum_id' => 0
767
        ];
768
769
        $last_id = Database::insert($table_forums, $params);
770 View Code Duplication
        if ($last_id > 0) {
771
            $sql = "UPDATE $table_forums SET forum_id = iid WHERE iid = $last_id";
772
            Database::query($sql);
773
774
            api_item_property_update(
775
                $courseInfo,
776
                TOOL_FORUM,
777
                $last_id,
778
                'ForumAdded',
779
                api_get_user_id(),
780
                $groupInfo
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($group_id) on line 631 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
781
            );
782
783
            api_set_default_visibility(
784
                $last_id,
785
                TOOL_FORUM,
786
                $group_id,
787
                $courseInfo
788
            );
789
        }
790
        $return_message = get_lang('ForumAdded');
791
        if ($returnId) {
792
            return $last_id;
793
        }
794
    }
795
796
    return $return_message;
797
}
798
799
/**
800
 * This function deletes a forum or a forum category
801
 * This function currently does not delete the forums inside the category,
802
 * nor the threads and replies inside these forums.
803
 * For the moment this is the easiest method and it has the advantage that it
804
 * allows to recover fora that were acidently deleted
805
 * when the forum category got deleted.
806
 *
807
 * @param $content = what we are deleting (a forum or a forum category)
808
 * @param $id The id of the forum category that has to be deleted.
809
 *
810
 * @todo write the code for the cascading deletion of the forums inside a
811
 * forum category and also the threads and replies inside these forums
812
 * @todo config setting for recovery or not
813
 * (see also the documents tool: real delete or not).
814
 * @return string
815
 * @author Patrick Cool <[email protected]>, Ghent University
816
 * @version february 2006, dokeos 1.8
817
 */
818
function deleteForumCategoryThread($content, $id)
819
{
820
    $_course = api_get_course_info();
821
    $table_forums = Database::get_course_table(TABLE_FORUM);
822
    $table_forums_post = Database::get_course_table(TABLE_FORUM_POST);
823
    $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
824
    $course_id = api_get_course_int_id();
825
    $groupId = api_get_group_id();
826
    $groupInfo = GroupManager::get_group_properties($groupId);
827
    $userId = api_get_user_id();
828
    $id = intval($id);
829
830
    // Delete all attachment file about this tread id.
831
    $sql = "SELECT post_id FROM $table_forums_post
832
            WHERE c_id = $course_id AND thread_id = '".$id."' ";
833
    $res = Database::query($sql);
834
    while ($poster_id = Database::fetch_row($res)) {
835
        delete_attachment($poster_id[0]);
836
    }
837
838
    $tool_constant = null;
839
    $return_message = '';
840
841 View Code Duplication
    if ($content == 'forumcategory') {
842
        $tool_constant = TOOL_FORUM_CATEGORY;
843
        $return_message = get_lang('ForumCategoryDeleted');
844
845
        if (!empty($forum_list)) {
0 ignored issues
show
Bug introduced by
The variable $forum_list seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
846
            $sql = "SELECT forum_id FROM $table_forums
847
                    WHERE c_id = $course_id AND forum_category='".$id."'";
848
            $result = Database::query($sql);
849
            $row = Database::fetch_array($result);
850
            foreach ($row as $arr_forum) {
851
                $forum_id = $arr_forum['forum_id'];
852
                api_item_property_update(
853
                    $_course,
854
                    'forum',
855
                    $forum_id,
856
                    'delete',
857
                    api_get_user_id()
858
                );
859
            }
860
        }
861
    }
862
863 View Code Duplication
    if ($content == 'forum') {
864
        $tool_constant = TOOL_FORUM;
865
        $return_message = get_lang('ForumDeleted');
866
867
        if (!empty($number_threads)) {
0 ignored issues
show
Bug introduced by
The variable $number_threads seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
868
            $sql = "SELECT thread_id FROM $table_forum_thread
869
                    WHERE c_id = $course_id AND forum_id = $id ";
870
            $result = Database::query($sql);
871
            $row = Database::fetch_array($result);
872
            foreach ($row as $arr_forum) {
873
                $forum_id = $arr_forum['thread_id'];
874
                api_item_property_update(
875
                    $_course,
876
                    'forum_thread',
877
                    $forum_id,
878
                    'delete',
879
                    api_get_user_id()
880
                );
881
            }
882
        }
883
    }
884
885
    if ($content == 'thread') {
886
        $tool_constant = TOOL_FORUM_THREAD;
887
        $return_message = get_lang('ThreadDeleted');
888
    }
889
890
    api_item_property_update(
891
        $_course,
892
        $tool_constant,
893
        $id,
894
        'delete',
895
        $userId,
896
        $groupInfo
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($groupId) on line 826 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
897
    );
898
899
    // Check if this returns a true and if so => return $return_message, if not => return false;
900
    return $return_message;
901
}
902
903
/**
904
 * This function deletes a forum post. This separate function is needed because forum posts do not appear in the item_property table (yet)
905
 * and because deleting a post also has consequence on the posts that have this post as parent_id (they are also deleted).
906
 * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
907
 * We also have to decrease the number of replies in the thread table
908
 *
909
 * @param $post_id the id of the post that will be deleted
910
 * @todo write recursive function that deletes all the posts that have this message as parent
911
 * @return string language variable
912
 * @author Patrick Cool <[email protected]>, Ghent University
913
 * @author Hubert Borderiou Function cleanead and fixed
914
 * @version february 2006
915
 */
916
function delete_post($post_id)
917
{
918
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
919
    $post_id = intval($post_id);
920
    $course_id = api_get_course_int_id();
921
    $em = Database::getManager();
922
923
    $post = $em
924
        ->getRepository('ChamiloCourseBundle:CForumPost')
925
        ->findOneBy(['cId' => $course_id, 'postId' => $post_id]);
926
927
    if ($post) {
928
        $em
929
            ->createQuery('
930
                UPDATE ChamiloCourseBundle:CForumPost p
931
                SET p.postParentId = :parent_of_deleted_post
932
                WHERE
933
                    p.cId = :course AND
934
                    p.postParentId = :post AND
935
                    p.threadId = :thread_of_deleted_post AND
936
                    p.forumId = :forum_of_deleted_post
937
            ')
938
            ->execute([
939
                'parent_of_deleted_post' => $post->getPostParentId(),
940
                'course' => $course_id,
941
                'post' => $post->getPostId(),
942
                'thread_of_deleted_post' => $post->getThreadId(),
943
                'forum_of_deleted_post' => $post->getForumId()
944
            ]);
945
946
        $em->remove($post);
947
        $em->flush();
948
949
        // Delete attachment file about this post id.
950
        delete_attachment($post_id);
951
    }
952
953
    $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
954
955
    if (is_array($last_post_of_thread)) {
956
        // Decreasing the number of replies for this thread and also changing the last post information.
957
        $sql = "UPDATE $table_threads
958
                SET
959
                    thread_replies = thread_replies - 1,
960
                    thread_last_post = ".intval($last_post_of_thread['post_id']).",
961
                    thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
962
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
963
        Database::query($sql);
964
965
        return 'PostDeleted';
966
    }
967
    if (!$last_post_of_thread) {
968
        // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
969
        $sql = "DELETE FROM $table_threads
970
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
971
        Database::query($sql);
972
973
        return 'PostDeletedSpecial';
974
    }
975
}
976
977
/**
978
 * This function gets the all information of the last (=most recent) post of the thread
979
 * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date
980
 *
981
 * @param $thread_id the id of the thread we want to know the last post of.
982
 * @return an array or bool if there is a last post found, false if there is
983
 * no post entry linked to that thread => thread will be deleted
984
 *
985
 * @author Patrick Cool <[email protected]>, Ghent University
986
 * @version february 2006, dokeos 1.8
987
 */
988 View Code Duplication
function check_if_last_post_of_thread($thread_id)
989
{
990
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
991
    $course_id = api_get_course_int_id();
992
    $sql = "SELECT * FROM $table_posts
993
            WHERE c_id = $course_id AND thread_id = ".intval($thread_id)."
994
            ORDER BY post_date DESC";
995
    $result = Database::query($sql);
996
    if (Database::num_rows($result) > 0) {
997
        $row = Database::fetch_array($result);
998
999
        return $row;
1000
    } else {
1001
        return false;
1002
    }
1003
}
1004
1005
/**
1006
 * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
1007
 * @param $id the id of the content we want to make invisible
1008
 * @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
1009
 * @param array $additional_url_parameters
1010
 *
1011
 * @return string HTML
1012
 */
1013
function return_visible_invisible_icon($content, $id, $current_visibility_status, $additional_url_parameters = '')
1014
{
1015
    $html = '';
1016
    $id = Security::remove_XSS($id);
1017 View Code Duplication
    if ($current_visibility_status == '1') {
1018
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1019
        if (is_array($additional_url_parameters)) {
1020
            foreach ($additional_url_parameters as $key => $value) {
1021
                $html .= $key.'='.$value.'&';
1022
            }
1023
        }
1024
        $html .= 'action=invisible&content='.$content.'&id='.$id.'">'.
1025
            Display::return_icon('visible.png', get_lang('MakeInvisible'), array(), ICON_SIZE_SMALL).'</a>';
1026
    }
1027 View Code Duplication
    if ($current_visibility_status == '0') {
1028
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1029
        if (is_array($additional_url_parameters)) {
1030
            foreach ($additional_url_parameters as $key => $value) {
1031
                $html .= $key.'='.$value.'&';
1032
            }
1033
        }
1034
        $html .= 'action=visible&content='.$content.'&id='.$id.'">'.
1035
            Display::return_icon('invisible.png', get_lang('MakeVisible'), array(), ICON_SIZE_SMALL).'</a>';
1036
    }
1037
    return $html;
1038
}
1039
1040
/**
1041
 * @param $content
1042
 * @param $id
1043
 * @param $current_lock_status
1044
 * @param string $additional_url_parameters
1045
 * @return string
1046
 */
1047
function return_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
1048
{
1049
    $html = '';
1050
    $id = intval($id);
1051
    //check if the forum is blocked due
1052
    if ($content == 'thread') {
1053
        if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
1054
            $html .= Display::return_icon('lock_na.png', get_lang('ResourceLockedByGradebook'), array(), ICON_SIZE_SMALL);
1055
1056
            return $html;
1057
        }
1058
    }
1059 View Code Duplication
    if ($current_lock_status == '1') {
1060
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1061
        if (is_array($additional_url_parameters)) {
1062
            foreach ($additional_url_parameters as $key => $value) {
1063
                $html .= $key.'='.$value.'&';
1064
            }
1065
        }
1066
        $html .= 'action=unlock&content='.$content.'&id='.$id.'">'.
1067
            Display::return_icon('lock.png', get_lang('Unlock'), array(), ICON_SIZE_SMALL).'</a>';
1068
    }
1069 View Code Duplication
    if ($current_lock_status == '0') {
1070
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1071
        if (is_array($additional_url_parameters)) {
1072
            foreach ($additional_url_parameters as $key => $value) {
1073
                $html .= $key.'='.$value.'&';
1074
            }
1075
        }
1076
        $html .= 'action=lock&content='.$content.'&id='.$id.'">'.
1077
            Display::return_icon('unlock.png', get_lang('Lock'), array(), ICON_SIZE_SMALL).'</a>';
1078
    }
1079
1080
    return $html;
1081
}
1082
1083
/**
1084
 * This function takes care of the display of the up and down icon
1085
 *
1086
 * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
1087
 * @param $id is the id of the item we want to display the icons for
1088
 * @param $list is an array of all the items. All items in this list should have
1089
 * an up and down icon except for the first (no up icon) and the last (no down icon)
1090
 *          The key of this $list array is the id of the item.
1091
 *
1092
 * @return string HTML
1093
 **/
1094
function return_up_down_icon($content, $id, $list)
1095
{
1096
    $id = strval(intval($id));
1097
    $total_items = count($list);
1098
    $position = 0;
1099
    $internal_counter = 0;
1100
    $forumCategory = isset($_GET['forumcategory']) ? Security::remove_XSS($_GET['forumcategory']) : null;
1101
1102
    if (is_array($list)) {
1103
        foreach ($list as $key => $listitem) {
1104
            $internal_counter++;
1105
            if ($id == $key) {
1106
                $position = $internal_counter;
1107
            }
1108
        }
1109
    }
1110
1111
    if ($position > 1) {
1112
        $return_value = '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=up&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveUp').'">'.
1113
            Display::return_icon('up.png', get_lang('MoveUp'), array(), ICON_SIZE_SMALL).'</a>';
1114
    } else {
1115
        $return_value = Display::return_icon('up_na.png', '-', array(), ICON_SIZE_SMALL);
1116
    }
1117
1118
    if ($position < $total_items) {
1119
        $return_value .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=down&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveDown').'" >'.
1120
            Display::return_icon('down.png', get_lang('MoveDown'), array(), ICON_SIZE_SMALL).'</a>';
1121
    } else {
1122
        $return_value .= Display::return_icon('down_na.png', '-', array(), ICON_SIZE_SMALL);
1123
    }
1124
    return $return_value;
1125
}
1126
1127
/**
1128
 * This function changes the visibility in the database (item_property)
1129
 *
1130
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1131
 * @param int $id the id of the content we want to make invisible
1132
 * @param string $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
1133
 *
1134
 * @todo change the get parameter so that it matches the tool constants.
1135
 * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
1136
 * @todo move to itemmanager
1137
 *
1138
 * @return string language variable
1139
 *
1140
 * @author Patrick Cool <[email protected]>, Ghent University
1141
 * @version february 2006, dokeos 1.8
1142
 */
1143
function change_visibility($content, $id, $target_visibility)
1144
{
1145
    $_course = api_get_course_info();
1146
    $constants = array(
1147
        'forumcategory' => TOOL_FORUM_CATEGORY,
1148
        'forum' => TOOL_FORUM,
1149
        'thread' => TOOL_FORUM_THREAD,
1150
    );
1151
    api_item_property_update(
1152
        $_course,
1153
        $constants[$content],
1154
        $id,
1155
        $target_visibility,
1156
        api_get_user_id()
1157
    );
1158
1159
    if ($target_visibility == 'visible') {
1160
        handle_mail_cue($content, $id);
1161
    }
1162
    return get_lang('VisibilityChanged');
1163
}
1164
1165
/**
1166
 * This function changes the lock status in the database
1167
 *
1168
 * @param string $content what is it that we want to (un)lock: forum category, forum, thread, post
1169
 * @param int $id the id of the content we want to (un)lock
1170
 * @param string $action do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
1171
 * @return string language variable
1172
 *
1173
 * @todo move to item manager
1174
 *
1175
 * @author Patrick Cool <[email protected]>, Ghent University
1176
 * @version february 2006, dokeos 1.8
1177
 */
1178
function change_lock_status($content, $id, $action)
1179
{
1180
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1181
    $table_forums = Database::get_course_table(TABLE_FORUM);
1182
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1183
1184
    // Determine the relevant table.
1185
    if ($content == 'forumcategory') {
1186
        $table = $table_categories;
1187
        $id_field = 'cat_id';
1188
    } elseif ($content == 'forum') {
1189
        $table = $table_forums;
1190
        $id_field = 'forum_id';
1191
    } elseif ($content == 'thread') {
1192
        $table = $table_threads;
1193
        $id_field = 'thread_id';
1194
    } else {
1195
        return get_lang('Error');
1196
    }
1197
1198
    // Determine what we are doing => defines the value for the database and the return message.
1199
    if ($action == 'lock') {
1200
        $db_locked = 1;
1201
        $return_message = get_lang('Locked');
1202
    } elseif ($action == 'unlock') {
1203
        $db_locked = 0;
1204
        $return_message = get_lang('Unlocked');
1205
    } else {
1206
        return get_lang('Error');
1207
    }
1208
1209
    $course_id = api_get_course_int_id();
1210
1211
    // Doing the change in the database
1212
    $sql = "UPDATE $table SET locked='".Database::escape_string($db_locked)."'
1213
            WHERE c_id = $course_id AND $id_field='".Database::escape_string($id)."'";
1214
    if (Database::query($sql)) {
1215
        return $return_message;
1216
    } else {
1217
        return get_lang('Error');
1218
    }
1219
}
1220
1221
/**
1222
 * This function moves a forum or a forum category up or down
1223
 *
1224
 * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
1225
 * @param $direction do we want to move it up or down.
1226
 * @param $id the id of the content we want to make invisible
1227
 * @todo consider removing the table_item_property calls here but this can
1228
 * prevent unwanted side effects when a forum does not have an entry in
1229
 * the item_property table but does have one in the forum table.
1230
 * @return string language variable
1231
 *
1232
 * @author Patrick Cool <[email protected]>, Ghent University
1233
 * @version february 2006, dokeos 1.8
1234
 */
1235
function move_up_down($content, $direction, $id)
1236
{
1237
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1238
    $table_forums = Database::get_course_table(TABLE_FORUM);
1239
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1240
    $course_id = api_get_course_int_id();
1241
    $id = intval($id);
1242
1243
    // Determine which field holds the sort order.
1244
    if ($content == 'forumcategory') {
1245
        $table = $table_categories;
1246
        $sort_column = 'cat_order';
1247
        $id_column = 'cat_id';
1248
        $sort_column = 'cat_order';
1249
    } elseif ($content == 'forum') {
1250
        $table = $table_forums;
1251
        $sort_column = 'forum_order';
1252
        $id_column = 'forum_id';
1253
        $sort_column = 'forum_order';
1254
        // We also need the forum_category of this forum.
1255
        $sql = "SELECT forum_category FROM $table_forums
1256
                WHERE c_id = $course_id AND forum_id = ".intval($id);
1257
        $result = Database::query($sql);
1258
        $row = Database::fetch_array($result);
1259
        $forum_category = $row['forum_category'];
1260
    } else {
1261
        return get_lang('Error');
1262
    }
1263
1264
    // Determine the need for sorting ascending or descending order.
1265
    if ($direction == 'down') {
1266
        $sort_direction = 'ASC';
1267
    } elseif ($direction == 'up') {
1268
        $sort_direction = 'DESC';
1269
    } else {
1270
        return get_lang('Error');
1271
    }
1272
1273
    // The SQL statement
1274
    if ($content == 'forumcategory') {
1275
        $sql = "SELECT *
1276
                FROM $table_categories forum_categories, $table_item_property item_properties
1277
                WHERE
1278
                    forum_categories.c_id = $course_id AND
1279
                    item_properties.c_id = $course_id AND
1280
                    forum_categories.cat_id=item_properties.ref AND
1281
                    item_properties.tool='".TOOL_FORUM_CATEGORY."'
1282
                ORDER BY forum_categories.cat_order $sort_direction";
1283
    }
1284
    if ($content == 'forum') {
1285
        $sql = "SELECT *
1286
            FROM $table
1287
            WHERE
1288
                c_id = $course_id AND
1289
                forum_category='".Database::escape_string($forum_category)."'
1290
            ORDER BY forum_order $sort_direction";
1291
    }
1292
    // Finding the items that need to be switched.
1293
    $result = Database::query($sql);
1294
    $found = false;
1295
    while ($row = Database::fetch_array($result)) {
1296
        //echo $row[$id_column].'-';
1297
        if ($found) {
1298
            $next_id = $row[$id_column];
1299
            $next_sort = $row[$sort_column];
1300
            $found = false;
1301
        }
1302
        if ($id == $row[$id_column]) {
1303
            $this_id = $id;
1304
            $this_sort = $row[$sort_column];
1305
            $found = true;
1306
        }
1307
    }
1308
1309
    // Committing the switch.
1310
    // We do an extra check if we do not have illegal values. If your remove this if statment you will
1311
    // be able to mess with the sorting by refreshing the page over and over again.
1312
    if ($this_sort != '' && $next_sort != '' && $next_id != '' && $this_id != '') {
1313
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."'
1314
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($next_id)."'";
1315
        Database::query($sql);
1316
1317
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."'
1318
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($this_id)."'";
1319
        Database::query($sql);
1320
    }
1321
1322
    return get_lang(ucfirst($content).'Moved');
1323
}
1324
1325
/**
1326
 * Retrieve all the information off the forum categories (or one specific) for the current course.
1327
 * The categories are sorted according to their sorting order (cat_order
1328
 *
1329
 * @param int|string $id default ''. When an id is passed we only find the information
1330
 * about that specific forum category. If no id is passed we get all the forum categories.
1331
 * @param int $courseId Optional. The course ID
1332
 * @param int $sessionId Optional. The session ID
1333
 * @return array containing all the information about all the forum categories
1334
 *
1335
 * @author Patrick Cool <[email protected]>, Ghent University
1336
 * @version february 2006, dokeos 1.8
1337
 */
1338
function get_forum_categories($id = '', $courseId = 0, $sessionId = 0)
1339
{
1340
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1341
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1342
1343
    // Condition for the session
1344
    $session_id = $sessionId ?: api_get_session_id();
1345
    $course_id = $courseId ?: api_get_course_int_id();
1346
1347
    $condition_session = api_get_session_condition($session_id, true, true, 'forum_categories.session_id');
1348
    $condition_session .= " AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
1349
1350
    if (empty($id)) {
1351
        $sql = "SELECT *
1352
                FROM $table_item_property item_properties 
1353
                INNER JOIN $table_categories forum_categories
1354
                ON (
1355
                    forum_categories.cat_id = item_properties.ref AND 
1356
                    item_properties.c_id = forum_categories.c_id
1357
                )
1358
                WHERE                    
1359
                    item_properties.visibility = 1 AND
1360
                    item_properties.tool = '".TOOL_FORUM_CATEGORY."'
1361
                    $condition_session
1362
                ORDER BY forum_categories.cat_order ASC";
1363
        if (api_is_allowed_to_edit()) {
1364
            $sql = "SELECT *
1365
                    FROM $table_item_property item_properties  
1366
                    INNER JOIN $table_categories forum_categories
1367
                    ON (
1368
                        forum_categories.cat_id = item_properties.ref AND 
1369
                        item_properties.c_id = forum_categories.c_id
1370
                    )
1371
                    WHERE                        
1372
                        item_properties.visibility<>2 AND
1373
                        item_properties.tool='".TOOL_FORUM_CATEGORY."'
1374
                        $condition_session
1375
                    ORDER BY forum_categories.cat_order ASC";
1376
        }
1377
    } else {
1378
        $sql = "SELECT *
1379
                FROM $table_item_property item_properties 
1380
                INNER JOIN $table_categories forum_categories
1381
                ON (
1382
                    forum_categories.cat_id = item_properties.ref AND 
1383
                    item_properties.c_id = forum_categories.c_id
1384
                )
1385
                WHERE                    
1386
                    item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
1387
                    forum_categories.cat_id = ".intval($id)."
1388
                    $condition_session
1389
                ORDER BY forum_categories.cat_order ASC";
1390
    }
1391
    $result = Database::query($sql);
1392
    $forum_categories_list = array();
1393
    while ($row = Database::fetch_assoc($result)) {
1394
        if (empty($id)) {
1395
            $forum_categories_list[$row['cat_id']] = $row;
1396
        } else {
1397
            $forum_categories_list = $row;
1398
        }
1399
    }
1400
1401
    return $forum_categories_list;
1402
}
1403
1404
/**
1405
 * This function retrieves all the fora in a given forum category
1406
 *
1407
 * @param int $cat_id the id of the forum category
1408
 * @param int $courseId Optional. The course ID
1409
 * @return array containing all the information about the forums (regardless of their category)
1410
 *
1411
 * @author Patrick Cool <[email protected]>, Ghent University
1412
 * @version february 2006, dokeos 1.8
1413
 */
1414
function get_forums_in_category($cat_id, $courseId = 0)
1415
{
1416
    $table_forums = Database::get_course_table(TABLE_FORUM);
1417
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1418
1419
    $forum_list = array();
1420
    $course_id = $courseId ?: api_get_course_int_id();
1421
    $cat_id = (int) $cat_id;
1422
1423
    $sql = "SELECT * FROM $table_forums forum 
1424
            INNER JOIN $table_item_property item_properties
1425
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1426
            WHERE
1427
                forum.forum_category = '".$cat_id."' AND                
1428
                item_properties.visibility = 1 AND
1429
                forum.c_id = $course_id AND
1430
                item_properties.c_id = $course_id AND
1431
                item_properties.tool = '".TOOL_FORUM."'                 
1432
            ORDER BY forum.forum_order ASC";
1433
    if (api_is_allowed_to_edit()) {
1434
        $sql = "SELECT * FROM $table_forums forum  
1435
                INNER JOIN $table_item_property item_properties
1436
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1437
                WHERE
1438
                    forum.forum_category = '".$cat_id."' AND                    
1439
                    item_properties.visibility <> 2 AND
1440
                    item_properties.tool = '".TOOL_FORUM."' AND
1441
                    item_properties.c_id = $course_id AND
1442
                    forum.c_id = $course_id
1443
                ORDER BY forum_order ASC";
1444
    }
1445
    $result = Database::query($sql);
1446
    while ($row = Database::fetch_array($result)) {
1447
        $forum_list[$row['forum_id']] = $row;
1448
    }
1449
1450
    return $forum_list;
1451
}
1452
1453
/**
1454
 * Retrieve all the forums (regardless of their category) or of only one.
1455
 * The forums are sorted according to the forum_order.
1456
 * Since it does not take the forum category into account there probably
1457
 * will be two or more forums that have forum_order=1, ...
1458
 * @param int $id forum id
1459
 * @param string $course_code
1460
 * @param bool $includeGroupsForum
1461
 * @param int $sessionId
1462
 * @return array an array containing all the information about the forums (regardless of their category)
1463
 * @todo check $sql4 because this one really looks fishy.
1464
 *
1465
 * @author Patrick Cool <[email protected]>, Ghent University
1466
 * @version february 2006, dokeos 1.8
1467
 */
1468
function get_forums(
1469
    $id = '',
1470
    $course_code = '',
1471
    $includeGroupsForum = true,
1472
    $sessionId = 0
1473
) {
1474
    $course_info = api_get_course_info($course_code);
1475
1476
    $table_forums = Database::get_course_table(TABLE_FORUM);
1477
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1478
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1479
1480
    // Condition for the session
1481
    $session_id = intval($sessionId) ?: api_get_session_id();
1482
    $sessionIdLink = $session_id === 0 ? '' : ' AND threads.session_id = item_properties.session_id';
1483
1484
    $condition_session = api_get_session_condition(
1485
        $session_id,
1486
        true,
1487
        false,
1488
        'item_properties.session_id'
1489
    );
1490
1491
    $course_id = $course_info['real_id'];
1492
1493
    $forum_list = array();
1494
    $includeGroupsForumSelect = '';
1495
    if (!$includeGroupsForum) {
1496
        $includeGroupsForumSelect = " AND forum_of_group = 0 ";
1497
    }
1498
1499
    if ($id == '') {
1500
        // Student
1501
        // Select all the forum information of all forums (that are visible to students).
1502
        $sql = "SELECT item_properties.*, forum.* 
1503
                FROM $table_forums forum
1504
                INNER JOIN $table_item_property item_properties
1505
                ON (
1506
                    forum.forum_id = item_properties.ref AND
1507
                    forum.c_id = item_properties.c_id
1508
                )
1509
                WHERE
1510
                    item_properties.visibility = 1 AND
1511
                    item_properties.tool = '".TOOL_FORUM."'
1512
                    $condition_session AND
1513
                    forum.c_id = $course_id AND
1514
                    item_properties.c_id = $course_id
1515
                    $includeGroupsForumSelect
1516
                ORDER BY forum.forum_order ASC";
1517
1518
        // Select the number of threads of the forums (only the threads that are visible).
1519
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1520
                FROM $table_threads threads
1521
                INNER JOIN $table_item_property item_properties
1522
                ON (
1523
                    threads.thread_id = item_properties.ref AND
1524
                    threads.c_id = item_properties.c_id
1525
                    $sessionIdLink
1526
                )
1527
                WHERE
1528
                    item_properties.visibility=1 AND
1529
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1530
                    threads.c_id = $course_id AND
1531
                    item_properties.c_id = $course_id
1532
                GROUP BY threads.forum_id";
1533
1534
        // Course Admin
1535 View Code Duplication
        if (api_is_allowed_to_edit()) {
1536
            // Select all the forum information of all forums (that are not deleted).
1537
            $sql = "SELECT item_properties.*, forum.* 
1538
                    FROM $table_forums forum
1539
                    INNER JOIN $table_item_property item_properties
1540
                    ON (
1541
                        forum.forum_id = item_properties.ref AND
1542
                        forum.c_id = item_properties.c_id
1543
                    )
1544
                    WHERE
1545
                        item_properties.visibility <> 2 AND
1546
                        item_properties.tool = '".TOOL_FORUM."'
1547
                        $condition_session AND
1548
                        forum.c_id = $course_id AND
1549
                        item_properties.c_id = $course_id
1550
                        $includeGroupsForumSelect
1551
                    ORDER BY forum_order ASC";
1552
1553
            // Select the number of threads of the forums (only the threads that are not deleted).
1554
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1555
                    FROM $table_threads threads
1556
                    INNER JOIN $table_item_property item_properties
1557
                    ON (
1558
                        threads.thread_id = item_properties.ref AND
1559
                        threads.c_id = item_properties.c_id
1560
                        $sessionIdLink
1561
                    )
1562
                    WHERE
1563
                        item_properties.visibility<>2 AND
1564
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1565
                        threads.c_id = $course_id AND
1566
                        item_properties.c_id = $course_id
1567
                    GROUP BY threads.forum_id";
1568
        }
1569
    } else {
1570
        // GETTING ONE SPECIFIC FORUM
1571
        /* We could do the splitup into student and course admin also but we want
1572
        to have as much as information about a certain forum as possible
1573
        so we do not take too much information into account. This function
1574
         (or this section of the function) is namely used to fill the forms
1575
        when editing a forum (and for the moment it is the only place where
1576
        we use this part of the function) */
1577
1578
        // Select all the forum information of the given forum (that is not deleted).
1579
        $sql = "SELECT * FROM $table_item_property item_properties 
1580
                INNER JOIN $table_forums forum
1581
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1582
                WHERE
1583
                    forum.forum_id = ".intval($id)." AND
1584
                    forum.c_id = $course_id AND
1585
                    item_properties.visibility != 2 AND
1586
                    item_properties.tool = '".TOOL_FORUM."'
1587
                ORDER BY forum_order ASC";
1588
1589
        // Select the number of threads of the forum.
1590
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1591
                FROM $table_threads
1592
                WHERE
1593
                    forum_id = ".intval($id)."
1594
                GROUP BY forum_id";
1595
    }
1596
1597
    // Handling all the forum information.
1598
    $result = Database::query($sql);
1599
    while ($row = Database::fetch_assoc($result)) {
1600
        if ($id == '') {
1601
            $forum_list[$row['forum_id']] = $row;
1602
        } else {
1603
            $forum_list = $row;
1604
        }
1605
    }
1606
1607
    // Handling the thread count information.
1608
    $result2 = Database::query($sql2);
1609
    while ($row2 = Database::fetch_array($result2)) {
1610
        if ($id == '') {
1611
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1612
        } else {
1613
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1614
        }
1615
    }
1616
1617
    /* Finding the last post information
1618
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1619
    if ($id == '') {
1620
        if (is_array($forum_list)) {
1621 View Code Duplication
            foreach ($forum_list as $key => $value) {
1622
                $last_post_info_of_forum = get_last_post_information(
1623
                    $key,
1624
                    api_is_allowed_to_edit(),
1625
                    $course_id
1626
                );
1627
1628
                if ($last_post_info_of_forum) {
1629
                    $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
1630
                    $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
1631
                    $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
1632
                    $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
1633
                    $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
1634
                    $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
1635
                }
1636
            }
1637
        } else {
1638
            $forum_list = array();
1639
        }
1640
    } else {
1641
        $last_post_info_of_forum = get_last_post_information(
1642
            $id,
1643
            api_is_allowed_to_edit(),
1644
            $course_id
1645
        );
1646
        if ($last_post_info_of_forum) {
1647
            $forum_list['last_post_id'] = $last_post_info_of_forum['last_post_id'];
1648
            $forum_list['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
1649
            $forum_list['last_post_date'] = $last_post_info_of_forum['last_post_date'];
1650
            $forum_list['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
1651
            $forum_list['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
1652
            $forum_list['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
1653
        }
1654
    }
1655
1656
    return $forum_list;
1657
}
1658
1659
/**
1660
 * @param int $course_id
1661
 * @param int $thread_id
1662
 * @param int $forum_id
1663
 * @param bool $show_visible
1664
 * @return array|bool
1665
 */
1666
function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
1667
{
1668
    if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
1669
        return false;
1670
    }
1671
1672
    $thread_id = intval($thread_id);
1673
    $forum_id = intval($forum_id);
1674
    $course_id = intval($course_id);
1675
1676
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1677
    $sql = "SELECT * FROM $table_posts
1678
            WHERE 
1679
                c_id = $course_id AND 
1680
                thread_id = $thread_id AND 
1681
                forum_id = $forum_id";
1682
1683
    if ($show_visible == false) {
1684
        $sql .= " AND visible = 1 ";
1685
    }
1686
1687
    $sql .= " ORDER BY post_id DESC LIMIT 1";
1688
    $result = Database::query($sql);
1689
    if (Database::num_rows($result)) {
1690
        return Database::fetch_array($result, 'ASSOC');
1691
    } else {
1692
        return false;
1693
    }
1694
}
1695
1696
/**
1697
 * This function gets all the last post information of a certain forum
1698
 *
1699
 * @param int $forum_id the id of the forum we want to know the last post information of.
1700
 * @param bool $show_invisibles
1701
 * @param string course db name
1702
 * @param int $sessionId Optional. The session id
1703
 * @return array containing all the information about the last post
1704
 * (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
1705
 *
1706
 * @author Patrick Cool <[email protected]>, Ghent University
1707
 * @version february 2006, dokeos 1.8
1708
 */
1709
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1710
{
1711
    if (!isset($course_id)) {
1712
        $course_id = api_get_course_int_id();
1713
    } else {
1714
        $course_id = intval($course_id);
1715
    }
1716
    $sessionId = $sessionId ? intval($sessionId) : api_get_session_id();
1717
1718
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1719
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1720
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1721
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1722
1723
    $forum_id = intval($forum_id);
1724
    $return_array = array();
1725
1726
    // First get the threads to make sure there is no inconsistency in the
1727
    // database between forum and thread
1728
    $sql = "SELECT thread_id FROM $table_threads 
1729
            WHERE 
1730
                forum_id = $forum_id AND 
1731
                c_id = $course_id AND 
1732
                session_id = $sessionId";
1733
    $result = Database::query($sql);
1734
    if (Database::num_rows($result) == 0) {
1735
        // If there are no threads in this forum, then there are no posts
1736
        return [];
1737
    }
1738
    $threads = array();
1739
    while ($row = Database::fetch_row($result)) {
1740
        $threads[] = $row[0];
1741
    }
1742
    $threadsList = implode(',', $threads);
1743
    // Now get the posts that are linked to these threads
1744
    $sql = "SELECT
1745
                post.post_id,
1746
                post.forum_id,
1747
                post.poster_id,
1748
                post.poster_name,
1749
                post.post_date,
1750
                users.lastname,
1751
                users.firstname,
1752
                post.visible,
1753
                thread_properties.visibility AS thread_visibility,
1754
                forum_properties.visibility AS forum_visibility
1755
            FROM
1756
                $table_posts post,
1757
                $table_users users,
1758
                $table_item_property thread_properties,
1759
                $table_item_property forum_properties
1760
            WHERE
1761
                post.forum_id = $forum_id
1762
                AND post.thread_id IN ($threadsList)
1763
                AND post.poster_id = users.user_id
1764
                AND post.thread_id = thread_properties.ref
1765
                AND thread_properties.tool='".TOOL_FORUM_THREAD."'
1766
                AND post.forum_id=forum_properties.ref
1767
                AND forum_properties.tool='".TOOL_FORUM."'
1768
                AND post.c_id = $course_id AND
1769
                thread_properties.c_id = $course_id AND
1770
                forum_properties.c_id = $course_id
1771
            ORDER BY post.post_id DESC";
1772
    $result = Database::query($sql);
1773
1774
    if ($show_invisibles) {
1775
        $row = Database::fetch_array($result);
1776
        $return_array['last_post_id'] = $row['post_id'];
1777
        $return_array['last_poster_id'] = $row['poster_id'];
1778
        $return_array['last_post_date'] = $row['post_date'];
1779
        $return_array['last_poster_name'] = $row['poster_name'];
1780
        $return_array['last_poster_lastname'] = $row['lastname'];
1781
        $return_array['last_poster_firstname'] = $row['firstname'];
1782
1783
        return $return_array;
1784
    } else {
1785
        // We have to loop through the results to find the first one that is
1786
        // actually visible to students (forum_category, forum, thread AND post are visible).
1787
        while ($row = Database::fetch_array($result)) {
1788
            if ($row['visible'] == '1' && $row['thread_visibility'] == '1' && $row['forum_visibility'] == '1') {
1789
                $return_array['last_post_id'] = $row['post_id'];
1790
                $return_array['last_poster_id'] = $row['poster_id'];
1791
                $return_array['last_post_date'] = $row['post_date'];
1792
                $return_array['last_poster_name'] = $row['poster_name'];
1793
                $return_array['last_poster_lastname'] = $row['lastname'];
1794
                $return_array['last_poster_firstname'] = $row['firstname'];
1795
1796
                return $return_array;
1797
            }
1798
        }
1799
    }
1800
}
1801
1802
/**
1803
 * Retrieve all the threads of a given forum
1804
 *
1805
 * @param int $forum_id
1806
 * @param int|null $courseId Optional If is null then it is considered the current course
1807
 * @param int|null $sessionId Optional. If is null then it is considered the current session
1808
 * @return array containing all the information about the threads
1809
 *
1810
 * @author Patrick Cool <[email protected]>, Ghent University
1811
 * @version february 2006, dokeos 1.8
1812
 */
1813
function get_threads($forum_id, $courseId = null, $sessionId = null)
1814
{
1815
    $groupId = api_get_group_id();
1816
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
1817
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1818
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1819
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1820
1821
    $courseId = $courseId !== null ? intval($courseId) : api_get_course_int_id();
1822
    $groupInfo = GroupManager::get_group_properties($groupId);
1823
    $groupCondition = '';
1824
1825
    if (!empty($groupInfo)) {
1826
        $groupIid = $groupInfo['iid'];
1827
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
1828
    }
1829
1830
    $sessionCondition = api_get_session_condition(
1831
        $sessionId,
1832
        true,
1833
        false,
1834
        'item_properties.session_id'
1835
    );
1836
1837
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
1838
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
1839
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
1840
    // This is why it is added to the end of the field selection
1841
    $sql = "SELECT DISTINCT
1842
                item_properties.*,
1843
                users.firstname,
1844
                users.lastname,
1845
                users.user_id,
1846
                thread.locked as locked,
1847
                thread.*
1848
            FROM $table_threads thread
1849
            INNER JOIN $table_item_property item_properties
1850
            ON
1851
                thread.thread_id = item_properties.ref AND
1852
                item_properties.c_id = thread.c_id AND
1853
                item_properties.tool = '".TABLE_FORUM_THREAD."' 
1854
                $groupCondition
1855
                $sessionCondition
1856
            LEFT JOIN $table_users users
1857
                ON thread.thread_poster_id = users.user_id
1858
            WHERE
1859
                item_properties.visibility='1' AND
1860
                thread.forum_id = ".intval($forum_id)." AND
1861
                thread.c_id = $courseId 
1862
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1863
1864
    if (api_is_allowed_to_edit()) {
1865
        $sql = "SELECT DISTINCT
1866
                    item_properties.*,
1867
                    users.firstname,
1868
                    users.lastname,
1869
                    users.user_id,
1870
                    thread.locked as locked,
1871
                    thread.*
1872
                FROM $table_threads thread
1873
                INNER JOIN $table_item_property item_properties
1874
                ON
1875
                    thread.thread_id = item_properties.ref AND
1876
                    item_properties.c_id = thread.c_id AND
1877
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
1878
                    $groupCondition
1879
                    $sessionCondition
1880
                LEFT JOIN $table_users users
1881
                    ON thread.thread_poster_id=users.user_id
1882
                WHERE
1883
                    item_properties.visibility<>2 AND
1884
                    thread.forum_id = ".intval($forum_id)." AND
1885
                    thread.c_id = $courseId 
1886
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1887
1888
    }
1889
    $result = Database::query($sql);
1890
    $list = array();
1891
    $alreadyAdded = array();
1892 View Code Duplication
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1893
        if (in_array($row['thread_id'], $alreadyAdded)) {
1894
            continue;
1895
        }
1896
        $list[] = $row;
1897
        $alreadyAdded[] = $row['thread_id'];
1898
    }
1899
1900
    return $list;
1901
}
1902
1903
/**
1904
 * Get a thread by Id and course id
1905
 *
1906
 * @param int $threadId the thread Id
1907
 * @param int $cId the course id
1908
 * @return array containing all the information about the thread
1909
 */
1910
function getThreadInfo($threadId, $cId)
1911
{
1912
    $em = Database::getManager();
1913
    $forumThread = $em->getRepository('ChamiloCourseBundle:CForumThread')->findOneBy(['threadId' => $threadId, 'cId' => $cId]);
1914
1915
    $thread = [];
1916
1917
    if ($forumThread) {
1918
        $thread['threadId'] = $forumThread->getThreadId();
1919
        $thread['threadTitle'] = $forumThread->getThreadTitle();
1920
        $thread['forumId'] = $forumThread->getForumId();
1921
        $thread['sessionId'] = $forumThread->getSessionId();
1922
        $thread['threadSticky'] = $forumThread->getThreadSticky();
1923
        $thread['locked'] = $forumThread->getLocked();
1924
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
1925
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
1926
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
1927
        $thread['threadWeight'] = $forumThread->getThreadWeight();
1928
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
1929
    }
1930
1931
    return $thread;
1932
}
1933
1934
/**
1935
 * Retrieve all posts of a given thread
1936
 * @param array $forumInfo
1937
 * @param int $threadId The thread ID
1938
 * @param string $orderDirection Optional. The direction for sort the posts
1939
 * @param boolean $recursive Optional. If the list is recursive
1940
 * @param int $postId Optional. The post ID for recursive list
1941
 * @param int $depth Optional. The depth to indicate the indent
1942
 * @todo move to a repository
1943
 *
1944
 * @return array containing all the information about the posts of a given thread
1945
 */
1946
function getPosts(
1947
    $forumInfo,
1948
    $threadId,
1949
    $orderDirection = 'ASC',
1950
    $recursive = false,
1951
    $postId = null,
1952
    $depth = -1
1953
) {
1954
    $em = Database::getManager();
1955
1956
    if (api_is_allowed_to_edit(false, true)) {
1957
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
1958
    } else {
1959
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
1960
    }
1961
1962
    $criteria = Criteria::create();
1963
    $criteria
1964
        ->where(Criteria::expr()->eq('threadId', $threadId))
1965
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
1966
        ->andWhere($visibleCriteria)
1967
    ;
1968
1969
    $groupId = api_get_group_id();
1970
    $groupInfo = GroupManager::get_group_properties($groupId);
1971
    $filterModerated = true;
1972
1973
    if (empty($groupId)) {
1974
        if (api_is_allowed_to_edit()) {
1975
            $filterModerated = false;
1976
        }
1977
    } else {
1978
        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo) || api_is_allowed_to_edit(false, true)) {
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($groupId) on line 1970 can also be of type null; however, GroupManager::is_tutor_of_group() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1979
            $filterModerated = false;
1980
        }
1981
    }
1982
1983
    if ($recursive) {
1984
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
1985
    }
1986
1987
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
1988
    $qb->select('p')
1989
        ->addCriteria($criteria)
1990
        ->addOrderBy('p.postId', $orderDirection);
1991
1992
    if ($filterModerated && $forumInfo['moderated'] == 1) {
1993
        if (!api_is_allowed_to_edit(false, true)) {
1994
            $userId = api_get_user_id();
1995
            $qb->andWhere(
1996
                "p.status = 1 OR 
1997
                    (p.status = ".CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
1998
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
1999
                    (p.status IS NULL AND p.posterId = $userId) 
2000
                    "
2001
            );
2002
        }
2003
    }
2004
2005
    $posts = $qb->getQuery()->getResult();
2006
    $depth++;
2007
2008
    $list = [];
2009
    /** @var CForumPost $post */
2010
    foreach ($posts as $post) {
2011
        $postInfo = [
2012
            'iid' => $post->getIid(),
2013
            'c_id' => $post->getCId(),
2014
            'post_id' => $post->getPostId(),
2015
            'post_title' => $post->getPostTitle(),
2016
            'post_text' => $post->getPostText(),
2017
            'thread_id' => $post->getThreadId(),
2018
            'forum_id' => $post->getForumId(),
2019
            'poster_id' => $post->getPosterId(),
2020
            'poster_name' => $post->getPosterName(),
2021
            'post_date' => $post->getPostDate(),
2022
            'post_notification' => $post->getPostNotification(),
2023
            'post_parent_id' => $post->getPostParentId(),
2024
            'visible' => $post->getVisible(),
2025
            'status' => $post->getStatus(),
2026
            'indent_cnt' => $depth
2027
        ];
2028
2029
        $posterId = $post->getPosterId();
2030
        if (!empty($posterId)) {
2031
            $user = $em->find('ChamiloUserBundle:User', $posterId);
2032
2033
            if ($user) {
2034
                $postInfo['user_id'] = $user->getUserId();
2035
                $postInfo['username'] = $user->getUsername();
2036
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
2037
                $postInfo['lastname'] = $user->getLastname();
2038
                $postInfo['firstname'] = $user->getFirstname();
2039
            }
2040
        }
2041
2042
        $list[] = $postInfo;
2043
2044
        if (!$recursive) {
2045
            continue;
2046
        }
2047
        $list = array_merge(
2048
            $list,
2049
            getPosts(
2050
                $forumInfo,
2051
                $threadId,
2052
                $orderDirection,
2053
                $recursive,
2054
                $post->getPostId(),
2055
                $depth
2056
            )
2057
        );
2058
    }
2059
2060
    return $list;
2061
}
2062
2063
/**
2064
 * This function retrieves all the information of a post
2065
 *
2066
 * @param int $post_id integer that indicates the forum
2067
 *
2068
 * @return array returns
2069
 *
2070
 * @author Patrick Cool <[email protected]>, Ghent University
2071
 * @version february 2006, dokeos 1.8
2072
 */
2073 View Code Duplication
function get_post_information($post_id)
2074
{
2075
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
2076
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2077
    $course_id = api_get_course_int_id();
2078
2079
    $sql = "SELECT posts.*, email FROM ".$table_posts." posts, ".$table_users." users
2080
            WHERE
2081
                c_id = $course_id AND
2082
                posts.poster_id=users.user_id AND
2083
                posts.post_id = ".intval($post_id);
2084
    $result = Database::query($sql);
2085
    $row = Database::fetch_array($result, 'ASSOC');
2086
2087
    return $row;
2088
}
2089
2090
/**
2091
 * This function retrieves all the information of a thread
2092
 *
2093
 * @param int $forumId
2094
 * @param $thread_id integer that indicates the forum
2095
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2096
 * @return array returns
2097
 *
2098
 * @author Patrick Cool <[email protected]>, Ghent University
2099
 * @version february 2006, dokeos 1.8
2100
 */
2101
function get_thread_information($forumId, $thread_id, $sessionId = null)
2102
{
2103
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2104
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2105
    $thread_id = intval($thread_id);
2106
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
2107
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'threads.session_id');
2108
    $forumCondition = '';
2109
    if (!empty($forumId)) {
2110
        $forumId = (int) $forumId;
2111
        $forumCondition = " threads.forum_id = $forumId AND ";
2112
    }
2113
    $sql = "SELECT * FROM $table_item_property item_properties
2114
            INNER JOIN
2115
            $table_threads threads
2116
            ON (item_properties.ref = threads.thread_id AND threads.c_id = item_properties.c_id)
2117
            WHERE
2118
                $forumCondition
2119
                item_properties.tool= '".TOOL_FORUM_THREAD."' AND                
2120
                threads.thread_id = $thread_id 
2121
                $sessionCondition
2122
            ";
2123
2124
    $result = Database::query($sql);
2125
    $row = Database::fetch_assoc($result);
2126
2127
    return $row;
2128
}
2129
2130
/**
2131
 * This function retrieves forum thread users details
2132
 * @param   int Thread ID
2133
 * @param   string  Course DB name (optional)
2134
 * @return  Doctrine\DBAL\Driver\Statement|null array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2135
 * @author Christian Fasanando <[email protected]>,
2136
 * @todo     this function need to be improved
2137
 * @version octubre 2008, dokeos 1.8
2138
 */
2139
function get_thread_users_details($thread_id)
2140
{
2141
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2142
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2143
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2144
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2145
2146
    $course_id = api_get_course_int_id();
2147
2148
    $is_western_name_order = api_is_western_name_order();
2149
    if ($is_western_name_order) {
2150
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2151
    } else {
2152
        $orderby = 'ORDER BY user.lastname, user.firstname';
2153
    }
2154
2155 View Code Duplication
    if (api_get_session_id()) {
2156
        $session_info = api_get_session_info(api_get_session_id());
2157
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2158
        //not showing coaches
2159
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2160
                  FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2161
                  WHERE p.poster_id = user.id AND
2162
                  user.id = session_rel_user_rel_course.user_id AND
2163
                  session_rel_user_rel_course.status<>'2' AND
2164
                  session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2165
                  p.thread_id = ".intval($thread_id)." AND
2166
                  session_id = ".api_get_session_id()." AND
2167
                  p.c_id = $course_id AND
2168
                  session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2169
    } else {
2170
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2171
                  FROM $t_posts p, $t_users user, $t_course_user course_user
2172
                  WHERE p.poster_id = user.id
2173
                  AND user.id = course_user.user_id
2174
                  AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2175
                  AND p.thread_id = ".intval($thread_id)."
2176
                  AND course_user.status NOT IN('1') AND
2177
                  p.c_id = $course_id AND
2178
                  course_user.c_id = ".$course_id." $orderby";
2179
    }
2180
    $result = Database::query($sql);
2181
2182
    return $result;
2183
}
2184
2185
/**
2186
 * This function retrieves forum thread users qualify
2187
 * @param   int Thread ID
2188
 * @param   string  Course DB name (optional)
2189
 * @return  Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2190
 * @author Jhon Hinojosa
2191
 * @todo     this function need to be improved
2192
 */
2193
function get_thread_users_qualify($thread_id)
2194
{
2195
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2196
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2197
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2198
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2199
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2200
2201
    $course_id = api_get_course_int_id();
2202
    $sessionId = api_get_session_id();
2203
2204
    $is_western_name_order = api_is_western_name_order();
2205
    if ($is_western_name_order) {
2206
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2207
    } else {
2208
        $orderby = 'ORDER BY user.lastname, user.firstname';
2209
    }
2210
2211
    if ($sessionId) {
2212
        $session_info = api_get_session_info($sessionId);
2213
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2214
        //not showing coaches
2215
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2216
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2217
                WHERE poster_id = user.id
2218
                    AND post.poster_id = qualify.user_id
2219
                    AND user.id = scu.user_id
2220
                    AND scu.status<>'2'
2221
                    AND scu.user_id NOT IN ($user_to_avoid)
2222
                    AND qualify.thread_id = ".intval($thread_id)."
2223
                    AND post.thread_id = ".intval($thread_id)."
2224
                    AND scu.session_id = $sessionId
2225
                    AND scu.c_id = ".$course_id." AND
2226
                    qualify.c_id = $course_id AND
2227
                    post.c_id = $course_id
2228
                $orderby ";
2229
    } else {
2230
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2231
                FROM $t_posts post,
2232
                     $t_qualify qualify,
2233
                     $t_users user,
2234
                     $t_course_user course_user
2235
                WHERE
2236
                     post.poster_id = user.id
2237
                     AND post.poster_id = qualify.user_id
2238
                     AND user.id = course_user.user_id
2239
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2240
                     AND qualify.thread_id = ".intval($thread_id)."
2241
                     AND post.thread_id = ".intval($thread_id)."
2242
                     AND course_user.status not in('1')
2243
                     AND course_user.c_id = $course_id
2244
                     AND qualify.c_id = $course_id
2245
                     AND post.c_id = $course_id
2246
                 $orderby ";
2247
    }
2248
    $result = Database::query($sql);
2249
2250
    return $result;
2251
}
2252
2253
/**
2254
 * This function retrieves forum thread users not qualify
2255
 * @param   int Thread ID
2256
 * @param   string  Course DB name (optional)
2257
 * @return  Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2258
 * @author   Jhon Hinojosa<[email protected]>,
2259
 * @version oct 2008, dokeos 1.8
2260
 */
2261
function get_thread_users_not_qualify($thread_id)
2262
{
2263
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2264
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2265
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2266
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2267
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2268
2269
    $is_western_name_order = api_is_western_name_order();
2270
    if ($is_western_name_order) {
2271
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2272
    } else {
2273
        $orderby = 'ORDER BY user.lastname, user.firstname';
2274
    }
2275
2276
    $course_id = api_get_course_int_id();
2277
2278
    $sql1 = "SELECT user_id FROM  $t_qualify
2279
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2280
    $result1 = Database::query($sql1);
2281
    $cad = '';
2282
    while ($row = Database::fetch_array($result1)) {
2283
        $cad .= $row['user_id'].',';
2284
    }
2285
    if ($cad == '') {
2286
        $cad = '0';
2287
    } else {
2288
        $cad = substr($cad, 0, strlen($cad) - 1);
2289
    }
2290
2291 View Code Duplication
    if (api_get_session_id()) {
2292
        $session_info = api_get_session_info(api_get_session_id());
2293
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2294
        //not showing coaches
2295
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2296
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2297
                WHERE poster_id = user.id
2298
                    AND user.id NOT IN (".$cad.")
2299
                    AND user.id = session_rel_user_rel_course.user_id
2300
                    AND session_rel_user_rel_course.status<>'2'
2301
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2302
                    AND post.thread_id = ".intval($thread_id)."
2303
                    AND session_id = ".api_get_session_id()."
2304
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2305
    } else {
2306
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2307
                FROM $t_posts post, $t_users user,$t_course_user course_user
2308
                WHERE post.poster_id = user.id
2309
                AND user.id NOT IN (".$cad.")
2310
                AND user.id = course_user.user_id
2311
                AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2312
                AND post.thread_id = ".intval($thread_id)."
2313
                AND course_user.status not in('1')
2314
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2315
    }
2316
    $result = Database::query($sql);
2317
2318
    return $result;
2319
}
2320
2321
/**
2322
 * This function retrieves all the information of a given forum_id
2323
 *
2324
 * @param $forum_id integer that indicates the forum
2325
 * @return array returns
2326
 *
2327
 * @author Patrick Cool <[email protected]>, Ghent University
2328
 * @version february 2006, dokeos 1.8
2329
 *
2330
 * @deprecated this functionality is now moved to get_forums($forum_id)
2331
 */
2332
function get_forum_information($forum_id, $courseId = 0)
2333
{
2334
    $table_forums = Database::get_course_table(TABLE_FORUM);
2335
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2336
    $courseId = empty($courseId) ? api_get_course_int_id() : intval($courseId);
2337
    $forum_id = intval($forum_id);
2338
2339
    $sql = "SELECT *
2340
            FROM $table_forums forums
2341
            INNER JOIN $table_item_property item_properties
2342
            ON (forums.c_id = item_properties.c_id)
2343
            WHERE
2344
                item_properties.tool = '".TOOL_FORUM."' AND
2345
                item_properties.ref = '".$forum_id."' AND
2346
                forums.forum_id = '".$forum_id."' AND
2347
                forums.c_id = ".$courseId."
2348
            ";
2349
2350
    $result = Database::query($sql);
2351
    $row = Database::fetch_array($result, 'ASSOC');
2352
    $row['approval_direct_post'] = 0;
2353
    // We can't anymore change this option, so it should always be activated.
2354
2355
    return $row;
2356
}
2357
2358
/**
2359
 * This function retrieves all the information of a given forumcategory id
2360
 *
2361
 * @param $cat_id integer that indicates the forum
2362
 *
2363
 * @return array returns if there are category or bool returns if there aren't category
2364
 * @author Patrick Cool <[email protected]>, Ghent University
2365
 * @version february 2006, dokeos 1.8
2366
 */
2367
function get_forumcategory_information($cat_id)
2368
{
2369
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2370
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2371
2372
    $course_id = api_get_course_int_id();
2373
    $sql = "SELECT *
2374
            FROM ".$table_categories." forumcategories, ".$table_item_property." item_properties
2375
            WHERE
2376
                forumcategories.c_id = $course_id AND
2377
                item_properties.c_id = $course_id AND
2378
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2379
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2380
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2381
    $result = Database::query($sql);
2382
    $row = Database::fetch_array($result);
2383
2384
    return $row;
2385
}
2386
2387
/**
2388
 * This function counts the number of forums inside a given category
2389
 *
2390
 * @param int $cat_id the id of the forum category
2391
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
2392
 *      of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2393
 * @return int the number of forums inside the given category
2394
 *
2395
 * @author Patrick Cool <[email protected]>, Ghent University
2396
 * @version february 2006, dokeos 1.8
2397
 */
2398 View Code Duplication
function count_number_of_forums_in_category($cat_id)
2399
{
2400
    $table_forums = Database::get_course_table(TABLE_FORUM);
2401
    $course_id = api_get_course_int_id();
2402
    $sql = "SELECT count(*) AS number_of_forums
2403
            FROM ".$table_forums."
2404
            WHERE c_id = $course_id AND forum_category='".Database::escape_string($cat_id)."'";
2405
    $result = Database::query($sql);
2406
    $row = Database::fetch_array($result);
2407
2408
    return $row['number_of_forums'];
2409
}
2410
2411
/**
2412
 * This function update a thread
2413
 *
2414
 * @param array $values - The form Values
2415
 * @return void HTML
2416
 *
2417
 */
2418
function updateThread($values)
2419
{
2420
    if (!api_is_allowed_to_edit()) {
2421
        return '';
2422
    }
2423
2424
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2425
    $courseId = api_get_course_int_id();
2426
    $courseCode = api_get_course_id();
2427
    $sessionId = api_get_session_id();
2428
2429
    // Simple update + set gradebook values to null
2430
    $params = [
2431
        'thread_title' => $values['thread_title'],
2432
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : null
2433
    ];
2434
    $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2435
    Database::update($threadTable, $params, $where);
2436
2437
    $id = $values['thread_id'];
2438
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2439
        $courseCode,
2440
        LINK_FORUM_THREAD,
2441
        $id,
2442
        $sessionId
2443
    );
2444
    $linkId = $linkInfo['id'];
2445
    $em = Database::getManager();
2446
    $gradebookLink = null;
2447
    if (!empty($linkId)) {
2448
        $gradebookLink = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($linkId);
2449
    }
2450
2451
    // values 1 or 0
2452
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2453
    if ($check) {
2454
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2455
        $value = isset($values['numeric_calification']) ? intval($values['numeric_calification']) : 0;
2456
        $weight = isset($values['weight_calification']) ? floatval($values['weight_calification']) : 0;
2457
        $description = '';
2458
        // Update title
2459
        $params = [
2460
            'thread_title_qualify' => $values['calification_notebook_title'],
2461
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2462
            'thread_weight' => api_float_val($values['weight_calification']),
2463
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2464
        ];
2465
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2466
        Database::update($threadTable, $params, $where);
2467
2468
        if (!$linkInfo) {
2469
            GradebookUtils::add_resource_to_course_gradebook(
2470
                $values['category_id'],
2471
                $courseCode,
2472
                LINK_FORUM_THREAD,
2473
                $id,
2474
                $title,
2475
                $weight,
2476
                $value,
2477
                $description,
2478
                1,
2479
                $sessionId
2480
            );
2481
        } else {
2482
            if ($gradebookLink) {
2483
                $gradebookLink->setWeight($weight);
2484
                $em->persist($gradebookLink);
2485
                $em->flush();
2486
            }
2487
        }
2488
    } else {
2489
        $params = [
2490
            'thread_title_qualify' => '',
2491
            'thread_qualify_max' => '',
2492
            'thread_weight' => '',
2493
            'thread_peer_qualify' => '',
2494
        ];
2495
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2496
        Database::update($threadTable, $params, $where);
2497
2498
        if (!empty($linkInfo)) {
2499
            if ($gradebookLink) {
2500
                $em->remove($gradebookLink);
2501
                $em->flush();
2502
            }
2503
        }
2504
    }
2505
2506
    $message = get_lang('EditPostStored').'<br />';
2507
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2508
}
2509
2510
/**
2511
 * This function stores a new thread. This is done through an entry in the forum_thread table AND
2512
 * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet))
2513
 *
2514
 * @param array $current_forum
2515
 * @param array $values
2516
 * @param array $courseInfo
2517
 * @param bool $showMessage
2518
 * @param int $userId Optional. The user ID
2519
 * @param int $sessionId
2520
 * @return int
2521
 * @author Patrick Cool <[email protected]>, Ghent University
2522
 * @version february 2006, dokeos 1.8
2523
 */
2524
function store_thread(
2525
    $current_forum,
2526
    $values,
2527
    $courseInfo = array(),
2528
    $showMessage = true,
2529
    $userId = 0,
2530
    $sessionId = 0
2531
) {
2532
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2533
    $userId = $userId ?: api_get_user_id();
2534
    $course_id = $courseInfo['real_id'];
2535
    $courseCode = $courseInfo['code'];
2536
    $groupId = api_get_group_id();
2537
    $groupInfo = GroupManager::get_group_properties($groupId);
2538
    $sessionId = $sessionId ?: api_get_session_id();
2539
2540
    $em = Database::getManager();
2541
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2542
2543
    $gradebook = isset($_GET['gradebook']) ? Security::remove_XSS($_GET['gradebook']) : '';
2544
    $upload_ok = 1;
2545
    $has_attachment = false;
2546
2547 View Code Duplication
    if (!empty($_FILES['user_upload']['name'])) {
2548
        $upload_ok = process_uploaded_file($_FILES['user_upload']);
2549
        $has_attachment = true;
2550
    }
2551
2552
    if (!$upload_ok) {
2553
        if ($showMessage) {
2554
            Display::addFlash(
2555
                Display::return_message(
2556
                    get_lang('UplNoFileUploaded'),
2557
                    'error',
2558
                    false
2559
                )
2560
            );
2561
        }
2562
2563
        return null;
2564
    }
2565
2566
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2567
2568 View Code Duplication
    if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
2569
        $visible = 0; // The post has not been approved yet.
2570
    } else {
2571
        $visible = 1;
2572
    }
2573
    $clean_post_title = $values['post_title'];
2574
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2575
2576
    $lastThread = new CForumThread();
2577
    $lastThread
2578
        ->setCId($course_id)
2579
        ->setThreadTitle($clean_post_title)
2580
        ->setForumId($values['forum_id'])
2581
        ->setThreadPosterId($userId)
2582
        ->setThreadPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2583
        ->setThreadDate($post_date)
2584
        ->setThreadSticky(isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
2585
        ->setThreadTitleQualify(
2586
            isset($values['calification_notebook_title']) ? $values['calification_notebook_title'] : null
2587
        )
2588
        ->setThreadQualifyMax(isset($values['numeric_calification']) ? (int) $values['numeric_calification'] : 0)
2589
        ->setThreadWeight(isset($values['weight_calification']) ? (int) $values['weight_calification'] : 0)
2590
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2591
        ->setSessionId($sessionId)
2592
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2593
        ->setThreadId(0)
2594
        ->setLocked(0)
2595
    ;
2596
2597
    $em->persist($lastThread);
2598
    $em->flush();
2599
2600
    // Add option gradebook qualify.
2601
    if (isset($values['thread_qualify_gradebook']) &&
2602
        1 == $values['thread_qualify_gradebook']
2603
    ) {
2604
        // Add function gradebook.
2605
        $resourcetype = 5;
2606
        $resourceid = $lastThread->getIid();
2607
        $resourcename = stripslashes($values['calification_notebook_title']);
2608
        $maxqualify = $values['numeric_calification'];
2609
        $weigthqualify = $values['weight_calification'];
2610
        GradebookUtils::add_resource_to_course_gradebook(
2611
            $values['category_id'],
2612
            $courseCode,
2613
            $resourcetype,
2614
            $resourceid,
2615
            $resourcename,
2616
            $weigthqualify,
2617
            $maxqualify,
2618
            '',
2619
            0,
2620
            $sessionId
2621
        );
2622
    }
2623
2624
    if ($lastThread->getIid()) {
2625
        $lastThread->setThreadId($lastThread->getIid());
2626
2627
        $em->merge($lastThread);
2628
        $em->flush();
2629
2630
        api_item_property_update(
2631
            $courseInfo,
2632
            TOOL_FORUM_THREAD,
2633
            $lastThread->getIid(),
2634
            'ForumThreadAdded',
2635
            $userId,
2636
            $groupInfo,
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($groupId) on line 2537 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2637
            null,
2638
            null,
2639
            null,
2640
            $sessionId
2641
        );
2642
2643
        // If the forum properties tell that the posts have to be approved
2644
        // we have to put the whole thread invisible,
2645
        // because otherwise the students will see the thread and not the post
2646
        // in the thread.
2647
        // We also have to change $visible because the post itself has to be
2648
        // visible in this case (otherwise the teacher would have
2649
        // to make the thread visible AND the post.
2650
        // Default behaviour
2651
        api_set_default_visibility(
2652
            $lastThread->getIid(),
2653
            TOOL_FORUM_THREAD,
2654
            $groupId,
2655
            $courseInfo,
2656
            $sessionId,
2657
            $userId
2658
        );
2659
2660
        if ($visible == 0) {
2661
            api_item_property_update(
2662
                $courseInfo,
2663
                TOOL_FORUM_THREAD,
2664
                $lastThread->getIid(),
2665
                'invisible',
2666
                $userId,
2667
                $groupInfo
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($groupId) on line 2537 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2668
            );
2669
            $visible = 1;
2670
        }
2671
    }
2672
2673
    // We now store the content in the table_post table.
2674
    $lastPost = new CForumPost();
2675
    $lastPost
2676
        ->setCId($course_id)
2677
        ->setPostTitle($clean_post_title)
2678
        ->setPostText($values['post_text'])
2679
        ->setThreadId($lastThread->getIid())
2680
        ->setForumId($values['forum_id'])
2681
        ->setPosterId($userId)
2682
        ->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2683
        ->setPostDate($post_date)
2684
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
2685
        ->setPostParentId(null)
2686
        ->setVisible($visible)
2687
        ->setPostId(0)
2688
        ->setStatus(CForumPost::STATUS_VALIDATED);
2689
2690
    if ($current_forum['moderated']) {
2691
        $lastPost->setStatus(
2692
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
2693
        );
2694
    }
2695
2696
    $em->persist($lastPost);
2697
    $em->flush();
2698
2699
    $lastPostId = $lastPost->getIid();
2700
2701
    if ($lastPostId) {
2702
        $lastPost->setPostId($lastPostId);
2703
        $em->merge($lastPost);
2704
        $em->flush();
2705
    }
2706
2707
    // Update attached files
2708 View Code Duplication
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
2709
        foreach ($_POST['file_ids'] as $key => $id) {
2710
            editAttachedFile(
2711
                array(
2712
                    'comment' => $_POST['file_comments'][$key],
2713
                    'post_id' => $lastPostId
2714
                ),
2715
                $id
2716
            );
2717
        }
2718
    }
2719
2720
    // Now we have to update the thread table to fill the thread_last_post
2721
    // field (so that we know when the thread has been updated for the last time).
2722
    $sql = "UPDATE $table_threads
2723
            SET thread_last_post = '".Database::escape_string($lastPostId)."'
2724
            WHERE
2725
                c_id = $course_id AND
2726
                thread_id='".Database::escape_string($lastThread->getIid())."'";
2727
    $result = Database::query($sql);
2728
    $message = get_lang('NewThreadStored');
2729
2730
    // Overwrite default message.
2731
    if ($current_forum['moderated'] &&
2732
        !api_is_allowed_to_edit(null, true)
2733
    ) {
2734
        $message = get_lang('MessageHasToBeApproved');
2735
    }
2736
2737
    // Storing the attachments if any.
2738
    if ($has_attachment) {
2739
        // Try to add an extension to the file if it hasn't one.
2740
        $new_file_name = add_ext_on_mime(
2741
            stripslashes($_FILES['user_upload']['name']),
2742
            $_FILES['user_upload']['type']
2743
        );
2744
2745
        if (!filter_extension($new_file_name)) {
2746
            if ($showMessage) {
2747
                Display::addFlash(Display::return_message(
2748
                    get_lang('UplUnableToSaveFileFilteredExtension'),
2749
                    'error'
2750
                ));
2751
            }
2752
        } else {
2753
            if ($result) {
2754
                add_forum_attachment_file(
2755
                    isset($values['file_comment']) ? $values['file_comment'] : null,
2756
                    $lastPostId
2757
                );
2758
            }
2759
        }
2760
    } else {
2761
        $message .= '<br />';
2762
    }
2763
2764
    if ($current_forum['approval_direct_post'] == '1' &&
2765
        !api_is_allowed_to_edit(null, true)
2766
    ) {
2767
        $message .= get_lang('MessageHasToBeApproved').'<br />';
2768
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2769
            get_lang('Forum').'</a><br />';
2770
    } else {
2771
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2772
            get_lang('Forum').'</a><br />';
2773
        $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&gradebook='.$gradebook.'&thread='.$lastThread->getIid().'">'.
2774
            get_lang('Message').'</a>';
2775
    }
2776
    $reply_info['new_post_id'] = $lastPostId;
2777
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
2778
2779
    if ($my_post_notification == 1) {
2780
        set_notification('thread', $lastThread->getIid(), true);
2781
    }
2782
2783
    send_notification_mails(
2784
        $current_forum['forum_id'],
2785
        $lastThread->getIid(),
2786
        $reply_info,
2787
        $courseInfo['code']
2788
    );
2789
2790
    Session::erase('formelements');
2791
    Session::erase('origin');
2792
    Session::erase('breadcrumbs');
2793
    Session::erase('addedresource');
2794
    Session::erase('addedresourceid');
2795
2796
    if ($showMessage) {
2797
        Display::addFlash(Display::return_message($message, 'success', false));
2798
    }
2799
    return $lastThread->getIid();
2800
}
2801
2802
/**
2803
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
2804
 * @param array $current_forum
2805
 * @param array $forum_setting
2806
 * @param string $action is the parameter that determines if we are
2807
 *  1. newthread: adding a new thread (both empty) => No I-frame
2808
 *  2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
2809
 *  3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled) (I first thought to put and I-frame with the message only)
2810
 *  4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled). The message will be in the reply. (I first thought not to put an I-frame here)
2811
 * @return FormValidator
2812
 * @author Patrick Cool <[email protected]>, Ghent University
2813
 * @version february 2006, dokeos 1.8
2814
 */
2815
function show_add_post_form($current_forum, $forum_setting, $action, $id = '', $form_values = '')
2816
{
2817
    $_user = api_get_user_info();
2818
    $action = isset($action) ? Security::remove_XSS($action) : '';
2819
    $myThread = isset($_GET['thread']) ? (int) $_GET['thread'] : '';
2820
    $forumId = isset($_GET['forum']) ? (int) $_GET['forum'] : '';
2821
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
2822
    $my_gradebook = isset($_GET['gradebook']) ? Security::remove_XSS($_GET['gradebook']) : '';
2823
2824
    $url = api_get_self().'?'.http_build_query([
2825
        'action' => $action,
2826
        'forum' => $forumId,
2827
        'gradebook' => $my_gradebook,
2828
        'thread' => $myThread,
2829
        'post' => $my_post
2830
    ]).'&'.api_get_cidreq();
2831
2832
    $form = new FormValidator(
2833
        'thread',
2834
        'post',
2835
        $url
2836
    );
2837
2838
    $form->setConstants(array('forum' => '5'));
2839
2840
    // Setting the form elements.
2841
    $form->addElement('hidden', 'forum_id', $forumId);
2842
    $form->addElement('hidden', 'thread_id', $myThread);
2843
    $form->addElement('hidden', 'gradebook', $my_gradebook);
2844
    $form->addElement('hidden', 'action', $action);
2845
2846
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
2847
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
2848
        $form->addElement('text', 'poster_name', get_lang('Name'));
2849
        $form->applyFilter('poster_name', 'html_filter');
2850
    }
2851
2852
    $form->addElement('text', 'post_title', get_lang('Title'));
2853
    $form->addHtmlEditor(
2854
        'post_text',
2855
        get_lang('Text'),
2856
        true,
2857
        false,
2858
        api_is_allowed_to_edit(null, true) ? array(
2859
            'ToolbarSet' => 'Forum',
2860
            'Width' => '100%',
2861
            'Height' => '300',
2862
        ) : array(
2863
            'ToolbarSet' => 'ForumStudent',
2864
            'Width' => '100%',
2865
            'Height' => '300',
2866
            'UserStatus' => 'student'
2867
        )
2868
    );
2869
2870
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
2871
    $iframe = null;
2872
    $myThread = Security::remove_XSS($myThread);
2873
    if ($forum_setting['show_thread_iframe_on_reply'] && $action != 'newthread' && !empty($myThread)) {
2874
        $iframe = "<iframe style=\"border: 1px solid black\" src=\"iframe_thread.php?".api_get_cidreq()."&forum=".intval($forumId)."&thread=".$myThread."#".Security::remove_XSS($my_post)."\" width=\"100%\"></iframe>";
2875
    }
2876
    if (!empty($iframe)) {
2877
        $form->addElement('label', get_lang('Thread'), $iframe);
2878
    }
2879
2880
    if ((api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && !($myThread)) {
2881
        $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
2882
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
2883
2884
        // Thread qualify
2885
        if (Gradebook::is_active()) {
2886
            //Loading gradebook select
2887
            GradebookUtils::load_gradebook_select_in_tool($form);
2888
            $form->addElement(
2889
                'checkbox',
2890
                'thread_qualify_gradebook',
2891
                '',
2892
                get_lang('QualifyThreadGradebook'),
2893
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
2894
            );
2895
        } else {
2896
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
2897
        }
2898
2899
        $form->addElement('html', '<div id="options_field" style="display:none">');
2900
        $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
2901
        $form->applyFilter('numeric_calification', 'html_filter');
2902
        $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
2903
        $form->applyFilter('calification_notebook_title', 'html_filter');
2904
2905
        $form->addElement(
2906
            'text',
2907
            'weight_calification',
2908
            get_lang('QualifyWeight'),
2909
            array('value' => '0.00', 'onfocus' => "javascript: this.select();")
2910
        );
2911
        $form->applyFilter('weight_calification', 'html_filter');
2912
2913
        $group = array();
2914
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
2915
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
2916
        $form->addGroup(
2917
            $group,
2918
            '',
2919
            [
2920
                get_lang('ForumThreadPeerScoring'),
2921
                get_lang('ForumThreadPeerScoringComment'),
2922
            ]
2923
        );
2924
        $form->addElement('html', '</div>');
2925
        $form->addElement('html', '</div>');
2926
    }
2927
2928 View Code Duplication
    if ($forum_setting['allow_sticky'] && api_is_allowed_to_edit(null, true) && $action == 'newthread') {
2929
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
2930
    }
2931
2932
    if (in_array($action, ['quote', 'replymessage'])) {
2933
        $form->addFile('user_upload[]', get_lang('Attachment'));
2934
        $form->addButton(
2935
            'add_attachment',
2936
            get_lang('AddAttachment'),
2937
            'paperclip',
2938
            'default',
2939
            'default',
2940
            null,
2941
            ['id' => 'reply-add-attachment']
2942
        );
2943
    } else {
2944
        $form->addFile('user_upload', get_lang('Attachment'));
2945
    }
2946
2947
    // Setting the class and text of the form title and submit button.
2948
    if ($action == 'quote') {
2949
        $form->addButtonCreate(get_lang('QuoteMessage'), 'SubmitPost');
2950
    } elseif ($action == 'replythread') {
2951
        $form->addButtonCreate(get_lang('ReplyToThread'), 'SubmitPost');
2952
    } elseif ($action == 'replymessage') {
2953
        $form->addButtonCreate(get_lang('ReplyToMessage'), 'SubmitPost');
2954
    } else {
2955
        $form->addButtonCreate(get_lang('CreateThread'), 'SubmitPost');
2956
    }
2957
2958
    if (!empty($form_values)) {
2959
        $defaults['post_title'] = prepare4display($form_values['post_title']);
2960
        $defaults['post_text'] = prepare4display($form_values['post_text']);
2961
        $defaults['post_notification'] = strval(intval($form_values['post_notification']));
2962
        $defaults['thread_sticky'] = strval(intval($form_values['thread_sticky']));
2963
        $defaults['thread_peer_qualify'] = intval($form_values['thread_peer_qualify']);
2964
    } else {
2965
        $defaults['thread_peer_qualify'] = 0;
2966
    }
2967
2968
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
2969
    // we can add this as default to the textarea.
2970
    if (($action == 'quote' || $action == 'replymessage') && isset($my_post)) {
2971
        // We also need to put the parent_id of the post in a hidden form when
2972
        // we are quoting or replying to a message (<> reply to a thread !!!)
2973
        $form->addHidden('post_parent_id', intval($my_post));
2974
2975
        // If we are replying or are quoting then we display a default title.
2976
        $values = get_post_information($my_post);
2977
        $posterInfo = api_get_user_info($values['poster_id']);
2978
        $posterName = '';
2979
        if ($posterInfo) {
2980
            $posterName = $posterInfo['complete_name'];
2981
        }
2982
        $defaults['post_title'] = get_lang('ReplyShort').api_html_entity_decode($values['post_title'], ENT_QUOTES);
2983
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
2984
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
2985
        if ($action == 'quote') {
2986
            $defaults['post_text'] = '<div>&nbsp;</div>
2987
                <div style="margin: 5px;">
2988
                    <div style="font-size: 90%; font-style: italic;">'.
2989
                        get_lang('Quoting').' '.$posterName.':</div>
2990
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
2991
                            prepare4display($values['post_text']).'
2992
                        </div>
2993
                    </div>
2994
                <div>&nbsp;</div>
2995
                <div>&nbsp;</div>
2996
            ';
2997
        }
2998
    }
2999
3000
    $form->setDefaults(isset($defaults) ? $defaults : []);
3001
3002
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3003
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
3004
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
3005
        $form->addRule('poster_name', get_lang('ThisFieldIsRequired'), 'required');
3006
    }
3007
3008
    // Validation or display
3009
    if ($form->validate()) {
3010
        $check = Security::check_token('post');
3011
        if ($check) {
3012
            $values = $form->exportValues();
3013
            if (isset($values['thread_qualify_gradebook']) &&
3014
                $values['thread_qualify_gradebook'] == '1' &&
3015
                empty($values['weight_calification'])
3016
            ) {
3017
                Display::addFlash(
3018
                    Display::return_message(
3019
                        get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3020
                        'error',
3021
                        false
3022
                    )
3023
                );
3024
3025
                return false;
3026
            }
3027
3028
            switch ($action) {
3029
                case 'newthread':
3030
                    $myThread = store_thread($current_forum, $values);
3031
                    break;
3032
                case 'quote':
3033
                case 'replythread':
3034
                case 'replymessage':
3035
                    store_reply($current_forum, $values);
3036
3037
                    break;
3038
            }
3039
3040
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3041
                [
3042
                    'forum' => $forumId,
3043
                    'thread' => $myThread
3044
                ]
3045
            );
3046
3047
            Security::clear_token();
3048
            header('Location: '.$url);
3049
            exit;
3050
        }
3051
    } else {
3052
        $token = Security::get_token();
3053
        $form->addElement('hidden', 'sec_token');
3054
        $form->setConstants(array('sec_token' => $token));
3055
3056
        // Delete from $_SESSION forum attachment from other posts
3057
        // and keep only attachments for new post
3058
        clearAttachedFiles(FORUM_NEW_POST);
3059
        // Get forum attachment ajax table to add it to form
3060
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $current_forum['forum_id']);
3061
        $ajaxHtml = $attachmentAjaxTable;
3062
        $form->addElement('html', $ajaxHtml);
3063
3064
        return $form;
3065
    }
3066
}
3067
3068
/**
3069
 * @param array $threadInfo
3070
 * @param integer $user_id
3071
 * @param integer $thread_id
3072
 * @param integer $thread_qualify
3073
 * @param integer $qualify_time
3074
 * @param integer $session_id
3075
 * @return array optional
3076
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3077
 * @version October 2008, dokeos  1.8.6
3078
 */
3079
function saveThreadScore(
3080
    $threadInfo,
3081
    $user_id,
3082
    $thread_id,
3083
    $thread_qualify = 0,
3084
    $qualify_time,
3085
    $session_id = 0
3086
) {
3087
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3088
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3089
3090
    $course_id = api_get_course_int_id();
3091
    $session_id = intval($session_id);
3092
    $currentUserId = api_get_user_id();
3093
3094
    if ($user_id == strval(intval($user_id)) &&
3095
        $thread_id == strval(intval($thread_id)) &&
3096
        $thread_qualify == strval(floatval($thread_qualify))
3097
    ) {
3098
        // Testing
3099
        $sql = "SELECT thread_qualify_max FROM $table_threads
3100
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3101
        $res_string = Database::query($sql);
3102
        $row_string = Database::fetch_array($res_string);
3103
        if ($thread_qualify <= $row_string[0]) {
3104
            if ($threadInfo['thread_peer_qualify'] == 0) {
3105
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3106
                        WHERE
3107
                            c_id = $course_id AND
3108
                            user_id = $user_id AND
3109
                            thread_id = ".$thread_id;
3110
            } else {
3111
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3112
                        WHERE
3113
                            c_id = $course_id AND
3114
                            user_id = $user_id AND
3115
                            qualify_user_id = $currentUserId AND
3116
                            thread_id = ".$thread_id;
3117
            }
3118
3119
            $result = Database::query($sql);
3120
            $row = Database::fetch_array($result);
3121
3122
            if ($row[0] == 0) {
3123
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3124
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3125
                Database::query($sql);
3126
3127
                $insertId = Database::insert_id();
3128
                if ($insertId) {
3129
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3130
                            WHERE iid = $insertId";
3131
                    Database::query($sql);
3132
                }
3133
3134
                return 'insert';
3135
            } else {
3136
3137
                saveThreadScoreHistory(
3138
                    '1',
3139
                    $course_id,
3140
                    $user_id,
3141
                    $thread_id
3142
                );
3143
3144
3145
                // Update
3146
                $sql = "UPDATE $table_threads_qualify
3147
                        SET
3148
                            qualify = '".$thread_qualify."',
3149
                            qualify_time = '".$qualify_time."'
3150
                        WHERE
3151
                            c_id = $course_id AND
3152
                            user_id=".$user_id." AND
3153
                            thread_id=".$thread_id." AND
3154
                            qualify_user_id = $currentUserId
3155
                        ";
3156
                Database::query($sql);
3157
3158
                return 'update';
3159
            }
3160
3161
        } else {
3162
            return null;
3163
        }
3164
    }
3165
}
3166
3167
/**
3168
 * This function shows qualify.
3169
 * @param string $option contains the information of option to run
3170
 * @param integer $user_id contains the information the current user id
3171
 * @param integer $thread_id contains the information the current thread id
3172
 * @return integer qualify
3173
 * <code> $option=1 obtained the qualification of the current thread</code>
3174
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3175
 * @version October 2008, dokeos  1.8.6
3176
 */
3177
function showQualify($option, $user_id, $thread_id)
3178
{
3179
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3180
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3181
3182
    $course_id = api_get_course_int_id();
3183
    $user_id = intval($user_id);
3184
    $thread_id = intval($thread_id);
3185
3186
    if (empty($user_id) || empty($thread_id)) {
3187
        return false;
3188
    }
3189
3190
    $sql = '';
3191
    switch ($option) {
3192
        case 1:
3193
            $sql = "SELECT qualify FROM $table_threads_qualify
3194
                    WHERE
3195
                        c_id = $course_id AND
3196
                        user_id=".$user_id." AND
3197
                        thread_id=".$thread_id;
3198
            break;
3199
        case 2:
3200
            $sql = "SELECT thread_qualify_max FROM $table_threads
3201
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3202
            break;
3203
    }
3204
3205
    if (!empty($sql)) {
3206
        $rs = Database::query($sql);
3207
        $row = Database::fetch_array($rs);
3208
3209
        return $row[0];
3210
    }
3211
3212
    return array();
3213
}
3214
3215
/**
3216
 * This function gets qualify historical.
3217
 * @param integer $user_id contains the information the current user id
3218
 * @param integer $thread_id contains the information the current thread id
3219
 * @param boolean $opt contains the information of option to run
3220
 * @return array
3221
 * @author Christian Fasanando <[email protected]>,
3222
 * @author Isaac Flores <[email protected]>,
3223
 * @version October 2008, dokeos  1.8.6
3224
 */
3225
function getThreadScoreHistory($user_id, $thread_id, $opt)
3226
{
3227
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3228
    $course_id = api_get_course_int_id();
3229
3230
    if ($opt == 'false') {
3231
        $sql = "SELECT * FROM $table_threads_qualify_log
3232
                WHERE
3233
                    c_id = $course_id AND
3234
                    thread_id='".Database::escape_string($thread_id)."' AND
3235
                    user_id='".Database::escape_string($user_id)."'
3236
                ORDER BY qualify_time";
3237
    } else {
3238
        $sql = "SELECT * FROM $table_threads_qualify_log
3239
                WHERE
3240
                    c_id = $course_id AND
3241
                    thread_id='".Database::escape_string($thread_id)."' AND
3242
                    user_id='".Database::escape_string($user_id)."'
3243
                ORDER BY qualify_time DESC";
3244
    }
3245
    $rs = Database::query($sql);
3246
    $log = array();
3247
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3248
        $log[] = $row;
3249
    }
3250
3251
    return $log;
3252
}
3253
3254
/**
3255
 * This function stores qualify historical.
3256
 * @param boolean contains the information of option to run
3257
 * @param string contains the information the current course id
3258
 * @param integer contains the information the current forum id
3259
 * @param integer contains the information the current user id
3260
 * @param integer contains the information the current thread id
3261
 * @param integer contains the information the current qualify
3262
 * @param string $option
3263
 * @param integer $course_id
3264
 * @param integer $user_id
3265
 * @param integer $thread_id
3266
 * @return void
3267
 * <code>$option=1 obtained the qualification of the current thread</code>
3268
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3269
 * @version October 2008, dokeos  1.8.6
3270
 */
3271
function saveThreadScoreHistory(
3272
    $option,
3273
    $course_id,
3274
    $user_id,
3275
    $thread_id
3276
) {
3277
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3278
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3279
3280
    $course_id = intval($course_id);
3281
    $qualify_user_id = api_get_user_id();
3282
3283
    if ($user_id == strval(intval($user_id)) &&
3284
        $thread_id == strval(intval($thread_id)) && $option == 1
3285
    ) {
3286
3287
        // Extract information of thread_qualify.
3288
        $sql = "SELECT qualify, qualify_time
3289
                FROM $table_threads_qualify
3290
                WHERE
3291
                    c_id = $course_id AND
3292
                    user_id = ".$user_id." AND
3293
                    thread_id = ".$thread_id." AND
3294
                    qualify_user_id = $qualify_user_id
3295
                ";
3296
        $rs = Database::query($sql);
3297
        $row = Database::fetch_array($rs);
3298
3299
        // Insert thread_historical.
3300
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3301
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3302
        Database::query($sql);
3303
3304
        $insertId = Database::insert_id();
3305
        if ($insertId) {
3306
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3307
                    WHERE iid = $insertId";
3308
            Database::query($sql);
3309
        }
3310
    }
3311
}
3312
3313
/**
3314
 * This function shows current thread qualify .
3315
 * @param integer $threadId
3316
 * @param integer $sessionId
3317
 * @param integer $userId
3318
 *
3319
 * @return array or null if is empty
3320
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3321
 * @version December 2008, dokeos  1.8.6
3322
 */
3323 View Code Duplication
function current_qualify_of_thread($threadId, $sessionId, $userId)
3324
{
3325
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3326
3327
    $course_id = api_get_course_int_id();
3328
    $currentUserId = api_get_user_id();
3329
    $sessionId = intval($sessionId);
3330
    $threadId = intval($threadId);
3331
3332
    $sql = "SELECT qualify FROM $table_threads_qualify
3333
            WHERE
3334
                c_id = $course_id AND
3335
                thread_id = $threadId AND
3336
                session_id = $sessionId AND
3337
                qualify_user_id = $currentUserId AND
3338
                user_id = $userId
3339
            ";
3340
    $res = Database::query($sql);
3341
    $row = Database::fetch_array($res, 'ASSOC');
3342
3343
    return $row['qualify'];
3344
}
3345
3346
/**
3347
 * This function stores a reply in the forum_post table.
3348
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date)
3349
 * @param array $current_forum
3350
 * @param array $values
3351
 * @param int $courseId Optional
3352
 * @param int $userId Optional
3353
 * @return array
3354
 * @author Patrick Cool <[email protected]>, Ghent University
3355
 * @version february 2006, dokeos 1.8
3356
 */
3357
function store_reply($current_forum, $values, $courseId = 0, $userId = 0)
3358
{
3359
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3360
    $_course = api_get_course_info_by_id($courseId);
3361
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3362
    $post_date = api_get_utc_datetime();
3363
    $userId = $userId ?: api_get_user_id();
3364
3365 View Code Duplication
    if ($current_forum['approval_direct_post'] == '1' &&
3366
        !api_is_allowed_to_edit(null, true)
3367
    ) {
3368
        $visible = 0;
3369
    } else {
3370
        $visible = 1;
3371
    }
3372
3373
    $upload_ok = 1;
3374
    $return = array();
3375
3376
    if ($upload_ok) {
3377
        // We first store an entry in the forum_post table.
3378
        $new_post_id = Database::insert(
3379
            $table_posts,
3380
            [
3381
                'c_id' => $courseId,
3382
                'post_title' => $values['post_title'],
3383
                'post_text' => isset($values['post_text']) ? ($values['post_text']) : null,
3384
                'thread_id' => $values['thread_id'],
3385
                'forum_id' => $values['forum_id'],
3386
                'poster_id' => $userId,
3387
                'post_id' => 0,
3388
                'post_date' => $post_date,
3389
                'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : null,
3390
                'post_parent_id' => isset($values['post_parent_id']) ? $values['post_parent_id'] : null,
3391
                'visible' => $visible,
3392
            ]
3393
        );
3394
3395
        if ($new_post_id) {
3396
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
3397
            Database::query($sql);
3398
3399
            $values['new_post_id'] = $new_post_id;
3400
            $message = get_lang('ReplyAdded');
3401
3402 View Code Duplication
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3403
                foreach ($_POST['file_ids'] as $key => $id) {
3404
                    editAttachedFile(
3405
                        array(
3406
                            'comment' => $_POST['file_comments'][$key],
3407
                            'post_id' => $new_post_id,
3408
                        ),
3409
                        $id
3410
                    );
3411
                }
3412
            }
3413
3414
            // Update the thread.
3415
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
0 ignored issues
show
Bug introduced by
It seems like $post_date defined by api_get_utc_datetime() on line 3362 can also be of type null or object<DateTime>; however, updateThreadInfo() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
3416
3417
            // Update the forum.
3418
            api_item_property_update(
3419
                $_course,
3420
                TOOL_FORUM,
3421
                $values['forum_id'],
3422
                'NewMessageInForum',
3423
                $userId
3424
            );
3425
3426
            // Insert post
3427
            api_item_property_update(
3428
                $_course,
3429
                TOOL_FORUM_POST,
3430
                $new_post_id,
3431
                'NewPost',
3432
                $userId
3433
            );
3434
3435
            if ($current_forum['approval_direct_post'] == '1' &&
3436
                !api_is_allowed_to_edit(null, true)
3437
            ) {
3438
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3439
            }
3440
3441
            if ($current_forum['moderated'] &&
3442
                !api_is_allowed_to_edit(null, true)
3443
            ) {
3444
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3445
            }
3446
3447
            // Setting the notification correctly.
3448
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3449
            if ($my_post_notification == 1) {
3450
                set_notification('thread', $values['thread_id'], true);
3451
            }
3452
3453
            send_notification_mails(
3454
                $values['forum_id'],
3455
                $values['thread_id'],
3456
                $values
3457
            );
3458
            add_forum_attachment_file('', $new_post_id);
3459
        }
3460
3461
        Session::erase('formelements');
3462
        Session::erase('origin');
3463
        Session::erase('breadcrumbs');
3464
        Session::erase('addedresource');
3465
        Session::erase('addedresourceid');
3466
3467
        Display::addFlash(Display::return_message($message, 'confirmation', false));
3468
    } else {
3469
        Display::addFlash(
3470
            Display::return_message(
3471
                get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
3472
                'error'
3473
            )
3474
        );
3475
    }
3476
3477
    return $return;
3478
}
3479
3480
/**
3481
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
3482
 * @param array contains all the information about the current post
3483
 * @param array contains all the information about the current thread
3484
 * @param array contains all info about the current forum (to check if attachments are allowed)
3485
 * @param array contains the default values to fill the form
3486
 * @return void
3487
 *
3488
 * @author Patrick Cool <[email protected]>, Ghent University
3489
 * @version february 2006, dokeos 1.8
3490
 */
3491
function show_edit_post_form(
3492
    $forum_setting,
3493
    $current_post,
3494
    $current_thread,
3495
    $current_forum,
3496
    $form_values = '',
3497
    $id_attach = 0
3498
) {
3499
    // Initialize the object.
3500
    $form = new FormValidator(
3501
        'edit_post',
3502
        'post',
3503
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.intval($_GET['post'])
3504
    );
3505
    $form->addElement('header', get_lang('EditPost'));
3506
    // Setting the form elements.
3507
    $form->addElement('hidden', 'post_id', $current_post['post_id']);
3508
    $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
3509
    $form->addElement('hidden', 'id_attach', $id_attach);
3510
3511
    if (empty($current_post['post_parent_id'])) {
3512
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
3513
    }
3514
3515
    $form->addElement('text', 'post_title', get_lang('Title'));
3516
    $form->applyFilter('post_title', 'html_filter');
3517
    $form->addElement(
3518
        'html_editor',
3519
        'post_text',
3520
        get_lang('Text'),
3521
        null,
3522
        api_is_allowed_to_edit(null, true) ? array(
3523
            'ToolbarSet' => 'Forum',
3524
            'Width' => '100%',
3525
            'Height' => '400',
3526
        ) : array(
3527
            'ToolbarSet' => 'ForumStudent',
3528
            'Width' => '100%',
3529
            'Height' => '400',
3530
            'UserStatus' => 'student',
3531
        )
3532
    );
3533
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
3534
3535
    $form->addButtonAdvancedSettings('advanced_params');
3536
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3537
3538
    if ($current_forum['moderated'] && api_is_allowed_to_edit(null, true)) {
3539
        $group = array();
3540
        $group[] = $form->createElement(
3541
            'radio',
3542
            'status',
3543
            null,
3544
            get_lang('Validated'),
3545
            1
3546
        );
3547
        $group[] = $form->createElement(
3548
            'radio',
3549
            'status',
3550
            null,
3551
            get_lang('WaitingModeration'),
3552
            2
3553
        );
3554
        $group[] = $form->createElement(
3555
            'radio',
3556
            'status',
3557
            null,
3558
            get_lang('Rejected'),
3559
            3
3560
        );
3561
        $form->addGroup($group, 'status', get_lang('Status'));
3562
    }
3563
3564
    $defaults['status']['status'] = isset($current_post['status']) && !empty($current_post['status']) ? $current_post['status'] : 2;
3565
3566
    if ($forum_setting['allow_post_notification']) {
3567
        $form->addElement('checkbox', 'post_notification', '', get_lang('NotifyByEmail').' ('.$current_post['email'].')');
3568
    }
3569
3570
    if ($forum_setting['allow_sticky'] &&
3571
        api_is_allowed_to_edit(null, true) &&
3572
        empty($current_post['post_parent_id'])
3573
    ) {
3574
        // The sticky checkbox only appears when it is the first post of a thread.
3575
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
3576
        if ($current_thread['thread_sticky'] == 1) {
3577
            $defaults['thread_sticky'] = true;
3578
        }
3579
    }
3580
3581
    $form->addElement('html', '</div>');
3582
3583
    $form->addFile('user_upload[]', get_lang('Attachment'));
3584
    $form->addButton(
3585
        'add_attachment',
3586
        get_lang('AddAttachment'),
3587
        'paperclip',
3588
        'default',
3589
        'default',
3590
        null,
3591
        ['id' => 'reply-add-attachment']
3592
    );
3593
3594
    $form->addButtonUpdate(get_lang('Modify'), 'SubmitPost');
3595
3596
    // Setting the default values for the form elements.
3597
    $defaults['post_title'] = $current_post['post_title'];
3598
    $defaults['post_text'] = $current_post['post_text'];
3599
3600
    if ($current_post['post_notification'] == 1) {
3601
        $defaults['post_notification'] = true;
3602
    }
3603
3604
    if (!empty($form_values)) {
3605
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
3606
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
3607
    }
3608
3609
    $form->setDefaults($defaults);
3610
3611
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3612
3613
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
3614
3615
    // Validation or display
3616
    if ($form->validate()) {
3617
        $values = $form->exportValues();
3618
        store_edit_post($current_forum, $values);
3619
    } else {
3620
        // Delete from $_SESSION forum attachment from other posts
3621
        clearAttachedFiles($current_post['post_id']);
3622
        // Get forum attachment ajax table to add it to form
3623
        $fileData = getAttachmentsAjaxTable($current_post['post_id'], $current_forum['forum_id']);
3624
        $form->addElement('html', $fileData);
3625
        $form->display();
3626
    }
3627
}
3628
3629
/**
3630
 * This function stores the edit of a post in the forum_post table.
3631
 *
3632
 * @param array
3633
 * @return void HTML
3634
 *
3635
 * @author Patrick Cool <[email protected]>, Ghent University
3636
 * @version february 2006, dokeos 1.8
3637
 */
3638
function store_edit_post($forumInfo, $values)
3639
{
3640
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
3641
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3642
    $gradebook = Security::remove_XSS($_GET['gradebook']);
3643
    $course_id = api_get_course_int_id();
3644
3645
    //check if this post is the first of the thread
3646
    // First we check if the change affects the thread and if so we commit
3647
    // the changes (sticky and post_title=thread_title are relevant).
3648
3649
    $posts = getPosts($forumInfo, $values['thread_id']);
3650
    $first_post = null;
3651
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
3652
        $first_post = $posts[0];
3653
    }
3654
3655
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
3656
        // Simple edit
3657
        $params = [
3658
            'thread_title' => $values['post_title'],
3659
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : null,
3660
        ];
3661
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
3662
        Database::update($threadTable, $params, $where);
3663
    }
3664
3665
    $status = '';
3666
    $updateStatus = false;
3667
    if ($forumInfo['moderated']) {
3668
        if (api_is_allowed_to_edit(null, true)) {
3669
            $status = $values['status']['status'];
3670
            $updateStatus = true;
3671
        } else {
3672
            $status = CForumPost::STATUS_WAITING_MODERATION;
3673
            $updateStatus = true;
3674
        }
3675
    }
3676
3677
    // Update the post_title and the post_text.
3678
    $params = [
3679
        'post_title' => $values['post_title'],
3680
        'post_text' => $values['post_text'],
3681
        'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : '',
3682
    ];
3683
3684
    if ($updateStatus) {
3685
        $params['status'] = $status;
3686
    }
3687
3688
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
3689
    Database::update($table_posts, $params, $where);
3690
3691
    // Update attached files
3692 View Code Duplication
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3693
        foreach ($_POST['file_ids'] as $key => $id) {
3694
            editAttachedFile(
3695
                array(
3696
                    'comment' => $_POST['file_comments'][$key],
3697
                    'post_id' => $values['post_id'],
3698
                ),
3699
                $id
3700
            );
3701
        }
3702
    }
3703
3704
    if (!empty($values['remove_attach'])) {
3705
        delete_attachment($values['post_id']);
3706
    }
3707
3708
    if (empty($values['id_attach'])) {
3709
        add_forum_attachment_file(
3710
            isset($values['file_comment']) ? $values['file_comment'] : null,
3711
            $values['post_id']
3712
        );
3713
    } else {
3714
        edit_forum_attachment_file(
3715
            isset($values['file_comment']) ? $values['file_comment'] : null,
3716
            $values['post_id'],
3717
            $values['id_attach']
3718
        );
3719
    }
3720
3721
    $message = get_lang('EditPostStored').'<br />';
3722
    $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&">'.get_lang('Forum').'</a><br />';
3723
    $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&gradebook='.$gradebook.'&thread='.$values['thread_id'].'&post='.Security::remove_XSS($_GET['post']).'">'.get_lang('Message').'</a>';
3724
3725
    Session::erase('formelements');
3726
    Session::erase('origin');
3727
    Session::erase('breadcrumbs');
3728
    Session::erase('addedresource');
3729
    Session::erase('addedresourceid');
3730
3731
    echo Display::return_message($message, 'confirmation', false);
3732
}
3733
3734
/**
3735
 * This function displays the firstname and lastname of the user as a link to the user tool.
3736
 *
3737
 * @param string names
3738
 * @ in_title : title tootip
3739
 * @return string HTML
3740
 *
3741
 * @author Patrick Cool <[email protected]>, Ghent University
3742
 * @version february 2006, dokeos 1.8
3743
 */
3744
function display_user_link($user_id, $name, $origin = '', $in_title = '')
3745
{
3746
    if ($user_id != 0) {
3747
        $userInfo = api_get_user_info($user_id);
3748
3749
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
3750
    } else {
3751
        return $name.' ('.get_lang('Anonymous').')';
3752
    }
3753
}
3754
3755
/**
3756
 * This function displays the user image from the profile, with a link to the user's details.
3757
 * @param   int     User's database ID
3758
 * @param   string  User's name
3759
 * @param   string  the origin where the forum is called (example : learnpath)
3760
 * @return  string  An HTML with the anchor and the image of the user
3761
 * @author Julio Montoya <[email protected]>
3762
 */
3763
function display_user_image($user_id, $name, $origin = '')
3764
{
3765
    $userInfo = api_get_user_info($user_id);
3766
3767
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
3768
3769
    if ($user_id != 0) {
3770
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
3771
    } else {
3772
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
3773
    }
3774
}
3775
3776
/**
3777
 * The thread view counter gets increased every time someone looks at the thread
3778
 *
3779
 * @param int
3780
 * @return void
3781
 *
3782
 * @author Patrick Cool <[email protected]>, Ghent University
3783
 * @version february 2006, dokeos 1.8
3784
 */
3785 View Code Duplication
function increase_thread_view($thread_id)
3786
{
3787
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3788
    $course_id = api_get_course_int_id();
3789
3790
    $sql = "UPDATE $table_threads 
3791
            SET thread_views = thread_views + 1
3792
            WHERE 
3793
                c_id = $course_id AND  
3794
                thread_id = '".intval($thread_id)."'";
3795
    Database::query($sql);
3796
}
3797
3798
/**
3799
 * The relies counter gets increased every time somebody replies to the thread
3800
 *
3801
 * @author Patrick Cool <[email protected]>, Ghent University
3802
 * @version february 2006, dokeos 1.8
3803
 * @param string $lastPostId
3804
 * @param string $post_date
3805
 */
3806
function updateThreadInfo($thread_id, $lastPostId, $post_date)
3807
{
3808
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3809
    $course_id = api_get_course_int_id();
3810
    $sql = "UPDATE $table_threads SET 
3811
            thread_replies = thread_replies+1,
3812
            thread_last_post = '".Database::escape_string($lastPostId)."',
3813
            thread_date = '".Database::escape_string($post_date)."'
3814
            WHERE 
3815
                c_id = $course_id AND  
3816
                thread_id='".Database::escape_string($thread_id)."'"; // this needs to be cleaned first
3817
    Database::query($sql);
3818
}
3819
3820
/**
3821
 * This function is used to find all the information about what's new in the forum tool
3822
 * @return void
3823
 *
3824
 * @author Patrick Cool <[email protected]>, Ghent University
3825
 * @version february 2006, dokeos 1.8
3826
 */
3827
function get_whats_new()
3828
{
3829
    $userId = api_get_user_id();
3830
    $course_id = api_get_course_int_id();
3831
3832
    if (empty($course_id) || empty($userId)) {
3833
        return false;
3834
    }
3835
3836
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3837
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
3838
3839
    $tool = TOOL_FORUM;
3840
    $lastForumAccess = Session::read('last_forum_access');
3841
3842
    if (!$lastForumAccess) {
3843
        $sql = "SELECT * FROM $tracking_last_tool_access
3844
                WHERE
3845
                    access_user_id = $userId AND
3846
                    c_id = $course_id AND
3847
                    access_tool = '".Database::escape_string($tool)."'";
3848
        $result = Database::query($sql);
3849
        $row = Database::fetch_array($result);
3850
        Session::write('last_forum_access', $row['access_date']);
3851
        $lastForumAccess = $row['access_date'];
3852
    }
3853
3854
    $whatsNew = Session::read('whatsnew_post_info');
3855
3856
    if (!$whatsNew) {
3857
        if ($lastForumAccess != '') {
3858
            $postInfo = array();
3859
            $sql = "SELECT * FROM $table_posts
3860
                    WHERE
3861
                        c_id = $course_id AND
3862
                        visible = 1 AND                        
3863
                        post_date > '".Database::escape_string($lastForumAccess)."'";
3864
            $result = Database::query($sql);
3865
            while ($row = Database::fetch_array($result)) {
3866
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
3867
            }
3868
            Session::write('whatsnew_post_info', $postInfo);
3869
        }
3870
    }
3871
}
3872
3873
/**
3874
 * This function approves a post = change
3875
 *
3876
 * @param int $post_id the id of the post that will be deleted
3877
 * @param string $action make the post visible or invisible
3878
 * @return string language variable
3879
 *
3880
 * @author Patrick Cool <[email protected]>, Ghent University
3881
 * @version february 2006, dokeos 1.8
3882
 */
3883
function approve_post($post_id, $action)
3884
{
3885
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3886
    $course_id = api_get_course_int_id();
3887
3888
    if ($action == 'invisible') {
3889
        $visibility_value = 0;
3890
    }
3891
3892
    if ($action == 'visible') {
3893
        $visibility_value = 1;
3894
        handle_mail_cue('post', $post_id);
3895
    }
3896
3897
    $sql = "UPDATE $table_posts SET
3898
            visible='".Database::escape_string($visibility_value)."'
3899
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
3900
    $return = Database::query($sql);
3901
3902
    if ($return) {
3903
        return 'PostVisibilityChanged';
3904
    }
3905
}
3906
3907
/**
3908
 * This function retrieves all the unapproved messages for a given forum
3909
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this)
3910
 *
3911
 * @param $forum_id the forum where we want to know the unapproved messages of
3912
 * @return array returns
3913
 *
3914
 * @author Patrick Cool <[email protected]>, Ghent University
3915
 * @version february 2006, dokeos 1.8
3916
 */
3917
function get_unaproved_messages($forum_id)
3918
{
3919
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3920
    $course_id = api_get_course_int_id();
3921
3922
    $return_array = array();
3923
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
3924
            WHERE 
3925
                c_id = $course_id AND 
3926
                forum_id='".Database::escape_string($forum_id)."' AND 
3927
                visible='0' ";
3928
    $result = Database::query($sql);
3929
    while ($row = Database::fetch_array($result)) {
3930
        $return_array[] = $row['thread_id'];
3931
    }
3932
3933
    return $return_array;
3934
}
3935
3936
/**
3937
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
3938
 * was added to a given thread.
3939
 *
3940
 * @param array reply information
3941
 * @return void
3942
 *
3943
 * @author Patrick Cool <[email protected]>, Ghent University
3944
 * @version february 2006, dokeos 1.8
3945
 */
3946
function send_notification_mails($forumId, $thread_id, $reply_info)
3947
{
3948
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
3949
3950
    // First we need to check if
3951
    // 1. the forum category is visible
3952
    // 2. the forum is visible
3953
    // 3. the thread is visible
3954
    // 4. the reply is visible (=when there is)
3955
    $current_thread = get_thread_information($forumId, $thread_id);
3956
    $current_forum = get_forum_information($current_thread['forum_id'], $current_thread['c_id']);
3957
3958
    $current_forum_category = null;
3959
    if (isset($current_forum['forum_category'])) {
3960
        $current_forum_category = get_forumcategory_information(
3961
            $current_forum['forum_category']
3962
        );
3963
    }
3964
3965
    if ($current_thread['visibility'] == '1' &&
3966
        $current_forum['visibility'] == '1' &&
3967
        ($current_forum_category && $current_forum_category['visibility'] == '1') &&
3968
        $current_forum['approval_direct_post'] != '1'
3969
    ) {
3970
        $send_mails = true;
3971
    } else {
3972
        $send_mails = false;
3973
    }
3974
3975
    // The forum category, the forum, the thread and the reply are visible to the user
3976
    if ($send_mails) {
3977
        if (!empty($forumId)) {
3978
            send_notifications($forumId, $thread_id);
3979
        }
3980
    } else {
3981
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
3982
        if (isset($current_forum['forum_id'])) {
3983
            $sql = "SELECT * FROM $table_notification
3984
                    WHERE
3985
                        c_id = ".api_get_course_int_id()." AND
3986
                        (
3987
                            forum_id = '".intval($current_forum['forum_id'])."' OR
3988
                            thread_id = '".intval($thread_id)."'
3989
                        ) ";
3990
3991
            $result = Database::query($sql);
3992
            $user_id = api_get_user_id();
3993
            while ($row = Database::fetch_array($result)) {
3994
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
3995
                        VALUES (".api_get_course_int_id().", '".intval($thread_id)."', '".intval($reply_info['new_post_id'])."', '$user_id' )";
3996
                Database::query($sql);
3997
            }
3998
        }
3999
    }
4000
}
4001
4002
/**
4003
 * This function is called whenever something is made visible because there might
4004
 * be new posts and the user might have indicated that (s)he wanted to be
4005
 * informed about the new posts by mail.
4006
 *
4007
 * @param string  Content type (post, thread, forum, forum_category)
4008
 * @param int     Item DB ID
4009
 * @param string $content
4010
 * @param integer $id
4011
 * @return string language variable
4012
 * @author Patrick Cool <[email protected]>, Ghent University
4013
 * @version february 2006, dokeos 1.8
4014
 */
4015
function handle_mail_cue($content, $id)
4016
{
4017
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4018
    $table_forums = Database::get_course_table(TABLE_FORUM);
4019
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4020
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4021
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4022
4023
    $course_id = api_get_course_int_id();
4024
4025
    /* If the post is made visible we only have to send mails to the people
4026
     who indicated that they wanted to be informed for that thread.*/
4027
    if ($content == 'post') {
4028
        // Getting the information about the post (need the thread_id).
4029
        $post_info = get_post_information($id);
4030
        $thread_id = intval($post_info['thread_id']);
4031
4032
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4033
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4034
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4035
                WHERE
4036
                    posts.c_id = $course_id AND
4037
                    mailcue.c_id = $course_id AND
4038
                    posts.thread_id='$thread_id'
4039
                    AND posts.post_notification='1'
4040
                    AND mailcue.thread_id='$thread_id'
4041
                    AND users.user_id=posts.poster_id
4042
                    AND users.active=1
4043
                GROUP BY users.email";
4044
4045
        $result = Database::query($sql);
4046
        while ($row = Database::fetch_array($result)) {
4047
            send_mail($row, get_thread_information($post_info['forum_id'], $post_info['thread_id']));
4048
        }
4049
    } elseif ($content == 'thread') {
4050
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4051
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4052
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4053
                WHERE
4054
                    posts.c_id = $course_id AND
4055
                    mailcue.c_id = $course_id AND
4056
                    posts.thread_id = ".intval($id)."
4057
                    AND posts.post_notification='1'
4058
                    AND mailcue.thread_id = ".intval($id)."
4059
                    AND users.user_id=posts.poster_id
4060
                    AND users.active=1
4061
                GROUP BY users.email";
4062
        $result = Database::query($sql);
4063
        while ($row = Database::fetch_array($result)) {
4064
            send_mail($row, get_thread_information($row['forum_id'], $id));
4065
        }
4066
4067
        // Deleting the relevant entries from the mailcue.
4068
        $sql = "DELETE FROM $table_mailcue
4069
                WHERE c_id = $course_id AND thread_id='".Database::escape_string($id)."'";
4070
        Database::query($sql);
4071
    } elseif ($content == 'forum') {
4072
        $sql = "SELECT thread_id FROM $table_threads
4073
                WHERE c_id = $course_id AND forum_id='".Database::escape_string($id)."'";
4074
        $result = Database::query($sql);
4075
        while ($row = Database::fetch_array($result)) {
4076
            handle_mail_cue('thread', $row['thread_id']);
4077
        }
4078
    } elseif ($content == 'forum_category') {
4079
        $sql = "SELECT forum_id FROM $table_forums
4080
                WHERE c_id = $course_id AND forum_category ='".Database::escape_string($id)."'";
4081
        $result = Database::query($sql);
4082
        while ($row = Database::fetch_array($result)) {
4083
            handle_mail_cue('forum', $row['forum_id']);
4084
        }
4085
    } else {
4086
        return get_lang('Error');
4087
    }
4088
}
4089
4090
/**
4091
 * This function sends the mails for the mail notification
4092
 *
4093
 * @param array
4094
 * @param array
4095
 * @return void
4096
 *
4097
 * @author Patrick Cool <[email protected]>, Ghent University
4098
 * @version february 2006, dokeos 1.8
4099
 */
4100
function send_mail($user_info = array(), $thread_information = array())
4101
{
4102
    $_course = api_get_course_info();
4103
    $user_id = api_get_user_id();
4104
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'];
4105 View Code Duplication
    if (isset($thread_information) && is_array($thread_information)) {
4106
        $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&forum='.$thread_information['forum_id'].'&thread='.$thread_information['thread_id'];
4107
    }
4108
    $email_body = get_lang('Dear').' '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4109
    $email_body .= get_lang('NewForumPost')."\n";
4110
    $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4111
    $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
4112
    $email_body .= get_lang('ThreadCanBeFoundHere')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
4113
4114
    if ($user_info['user_id'] <> $user_id) {
4115
        MessageManager::send_message($user_info['user_id'], $subject, $email_body, [], [], null, null, null, null, $user_id);
4116
    }
4117
}
4118
4119
/**
4120
 * This function displays the form for moving a thread to a different (already existing) forum
4121
 * @return void HTML
4122
 *
4123
 * @author Patrick Cool <[email protected]>, Ghent University
4124
 * @version february 2006, dokeos 1.8
4125
 */
4126
function move_thread_form()
4127
{
4128
    $gradebook = Security::remove_XSS($_GET['gradebook']);
4129
    $form = new FormValidator(
4130
        'movepost',
4131
        'post',
4132
        api_get_self().'?forum='.intval($_GET['forum']).'&gradebook='.$gradebook.'&thread='.intval($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4133
    );
4134
    // The header for the form
4135
    $form->addElement('header', get_lang('MoveThread'));
4136
    // Invisible form: the thread_id
4137
    $form->addElement('hidden', 'thread_id', intval($_GET['thread']));
4138
    // the fora
4139
    $forum_categories = get_forum_categories();
4140
    $forums = get_forums();
4141
4142
    $htmlcontent = '<div class="row">
4143
        <div class="label">
4144
            <span class="form_required">*</span>'.get_lang('MoveTo').'
4145
        </div>
4146
        <div class="formw">';
4147
    $htmlcontent .= '<select name="forum">';
4148
    foreach ($forum_categories as $key => $category) {
4149
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4150
        foreach ($forums as $key => $forum) {
4151
            if (isset($forum['forum_category'])) {
4152
                if ($forum['forum_category'] == $category['cat_id']) {
4153
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4154
                }
4155
            }
4156
        }
4157
        $htmlcontent .= '</optgroup>';
4158
    }
4159
    $htmlcontent .= "</select>";
4160
    $htmlcontent .= '   </div>
4161
                    </div>';
4162
4163
    $form->addElement('html', $htmlcontent);
4164
4165
    // The OK button
4166
    $form->addButtonSave(get_lang('MoveThread'), 'SubmitForum');
4167
4168
    // Validation or display
4169
    if ($form->validate()) {
4170
        $values = $form->exportValues();
4171
        if (isset($_POST['forum'])) {
4172
            store_move_thread($values);
4173
        }
4174
    } else {
4175
        $form->display();
4176
    }
4177
}
4178
4179
/**
4180
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4181
 * @return void HTML
4182
 *
4183
 * @author Patrick Cool <[email protected]>, Ghent University
4184
 * @version february 2006, dokeos 1.8
4185
 */
4186
function move_post_form()
4187
{
4188
    $gradebook = Security::remove_XSS($_GET['gradebook']);
4189
    // initiate the object
4190
    $form = new FormValidator('movepost', 'post', api_get_self().'?'.api_get_cidreq().'&forum='.Security::remove_XSS($_GET['forum']).'&thread='.Security::remove_XSS($_GET['thread']).'&gradebook='.$gradebook.'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post']));
4191
    // The header for the form
4192
    $form->addElement('header', '', get_lang('MovePost'));
4193
4194
    // Invisible form: the post_id
4195
    $form->addElement('hidden', 'post_id', intval($_GET['post']));
4196
4197
    // Dropdown list: Threads of this forum
4198
    $threads = get_threads($_GET['forum']);
4199
    //my_print_r($threads);
4200
    $threads_list[0] = get_lang('ANewThread');
4201
    foreach ($threads as $key => $value) {
4202
        $threads_list[$value['thread_id']] = $value['thread_title'];
4203
    }
4204
    $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
4205
    $form->applyFilter('thread', 'html_filter');
4206
4207
    // The OK button
4208
    $form->addButtonSave(get_lang('MovePost'), 'submit');
4209
4210
    // Setting the rules
4211
    $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
4212
4213
    // Validation or display
4214
    if ($form->validate()) {
4215
        $values = $form->exportValues();
4216
        store_move_post($values);
4217
    } else {
4218
        $form->display();
4219
    }
4220
}
4221
4222
/**
4223
 *
4224
 * @param array
4225
 * @return string HTML language variable
4226
 *
4227
 * @author Patrick Cool <[email protected]>, Ghent University
4228
 * @version february 2006, dokeos 1.8
4229
 */
4230
function store_move_post($values)
4231
{
4232
    $_course = api_get_course_info();
4233
    $course_id = api_get_course_int_id();
4234
4235
    $table_forums = Database::get_course_table(TABLE_FORUM);
4236
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4237
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4238
4239
    if ($values['thread'] == '0') {
4240
        $current_post = get_post_information($values['post_id']);
4241
4242
        // Storing a new thread.
4243
        $params = [
4244
            'c_id' => $course_id,
4245
            'thread_title' => $current_post['post_title'],
4246
            'forum_id' => $current_post['forum_id'],
4247
            'thread_poster_id' => $current_post['poster_id'],
4248
            'thread_poster_name' => $current_post['poster_name'],
4249
            'thread_last_post' => $values['post_id'],
4250
            'thread_date' => $current_post['post_date'],
4251
        ];
4252
4253
        $new_thread_id = Database::insert($table_threads, $params);
4254
4255
        api_item_property_update(
4256
            $_course,
4257
            TOOL_FORUM_THREAD,
4258
            $new_thread_id,
4259
            'visible',
4260
            $current_post['poster_id']
4261
        );
4262
4263
        // Moving the post to the newly created thread.
4264
        $sql = "UPDATE $table_posts SET thread_id='".intval($new_thread_id)."', post_parent_id = NULL
4265
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4266
        Database::query($sql);
4267
4268
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4269
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4270
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4271
        Database::query($sql);
4272
4273
        // Updating updating the number of threads in the forum.
4274
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4275
                WHERE c_id = $course_id AND forum_id='".intval($current_post['forum_id'])."'";
4276
        Database::query($sql);
4277
4278
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4279
        $sql = "SELECT * FROM $table_posts
4280
                WHERE c_id = $course_id AND thread_id='".intval($current_post['thread_id'])."'
4281
                ORDER BY post_id DESC";
4282
        $result = Database::query($sql);
4283
        $row = Database::fetch_array($result);
4284
        $sql = "UPDATE $table_threads SET
4285
                    thread_last_post='".$row['post_id']."',
4286
                    thread_replies=thread_replies-1
4287
                WHERE
4288
                    c_id = $course_id AND
4289
                    thread_id='".intval($current_post['thread_id'])."'";
4290
        Database::query($sql);
4291
    } else {
4292
        // Moving to the chosen thread.
4293
        $sql = "SELECT thread_id FROM ".$table_posts."
4294
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
4295
        $result = Database::query($sql);
4296
        $row = Database::fetch_array($result);
4297
4298
        $original_thread_id = $row['thread_id'];
4299
4300
        $sql = "SELECT thread_last_post FROM ".$table_threads."
4301
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4302
4303
        $result = Database::query($sql);
4304
        $row = Database::fetch_array($result);
4305
        $thread_is_last_post = $row['thread_last_post'];
4306
        // If is this thread, update the thread_last_post with the last one.
4307
4308
        if ($thread_is_last_post == $values['post_id']) {
4309
            $sql = "SELECT post_id FROM ".$table_posts."
4310
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
4311
                    ORDER BY post_date DESC LIMIT 1";
4312
            $result = Database::query($sql);
4313
4314
            $row = Database::fetch_array($result);
4315
            $thread_new_last_post = $row['post_id'];
4316
4317
            $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."'
4318
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4319
            Database::query($sql);
4320
        }
4321
4322
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4323
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
4324
        Database::query($sql);
4325
4326
        // moving to the chosen thread
4327
        $sql = "UPDATE $table_posts SET thread_id='".intval($_POST['thread'])."', post_parent_id = NULL
4328
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4329
        Database::query($sql);
4330
4331
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4332
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4333
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4334
        Database::query($sql);
4335
4336
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4337
                WHERE c_id = $course_id AND thread_id='".intval($_POST['thread'])."'";
4338
        Database::query($sql);
4339
    }
4340
4341
    return get_lang('ThreadMoved');
4342
}
4343
4344
/**
4345
 *
4346
 * @param array
4347
 * @return string HTML language variable
4348
 *
4349
 * @author Patrick Cool <[email protected]>, Ghent University
4350
 * @version february 2006, dokeos 1.8
4351
 */
4352
function store_move_thread($values)
4353
{
4354
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4355
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4356
4357
    $courseId = api_get_course_int_id();
4358
    $sessionId = api_get_session_id();
4359
4360
    $forumId = intval($_POST['forum']);
4361
    $threadId = intval($_POST['thread_id']);
4362
    $forumInfo = get_forums($forumId);
4363
4364
    // Change the thread table: Setting the forum_id to the new forum.
4365
    $sql = "UPDATE $table_threads SET forum_id = $forumId
4366
            WHERE c_id = $courseId AND thread_id = $threadId";
4367
    Database::query($sql);
4368
4369
    // Changing all the posts of the thread: setting the forum_id to the new forum.
4370
    $sql = "UPDATE $table_posts SET forum_id = $forumId
4371
            WHERE c_id = $courseId AND thread_id= $threadId";
4372
    Database::query($sql);
4373
    // Fix group id, if forum is moved to a different group
4374
    if (!empty($forumInfo['to_group_id'])) {
4375
        $groupId = $forumInfo['to_group_id'];
4376
        $item = api_get_item_property_info($courseId, TABLE_FORUM_THREAD, $threadId, $sessionId, $groupId);
4377
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4378
        $sessionCondition = api_get_session_condition($sessionId);
4379
4380
        if (!empty($item)) {
4381
            if ($item['to_group_id'] != $groupId) {
4382
                $sql = "UPDATE $table
4383
                    SET to_group_id = $groupId
4384
                    WHERE
4385
                      tool = '".TABLE_FORUM_THREAD."' AND
4386
                      c_id = $courseId AND
4387
                      ref = ".$item['ref']."
4388
                      $sessionCondition
4389
                ";
4390
                Database::query($sql);
4391
            }
4392
        } else {
4393
            $sql = "UPDATE $table
4394
                    SET to_group_id = $groupId
4395
                    WHERE
4396
                      tool = '".TABLE_FORUM_THREAD."' AND
4397
                      c_id = $courseId AND
4398
                      ref = ".$threadId."
4399
                      $sessionCondition
4400
            ";
4401
            Database::query($sql);
4402
        }
4403
    }
4404
4405
    return get_lang('ThreadMoved');
4406
}
4407
4408
/**
4409
 * Prepares a string for displaying by highlighting the search results inside, if any.
4410
 * @param string $input    The input string.
4411
 * @return string          The same string with highlighted hits inside.
4412
 *
4413
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
4414
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
4415
 */
4416
function prepare4display($input)
4417
{
4418
    static $highlightcolors = array('yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33');
4419
    static $search;
4420
4421
    if (!isset($search)) {
4422
        if (isset($_POST['search_term'])) {
4423
            $search = $_POST['search_term']; // No html at all.
4424
        } elseif (isset($_GET['search'])) {
4425
            $search = $_GET['search'];
4426
        } else {
4427
            $search = '';
4428
        }
4429
    }
4430
4431
    if (!empty($search)) {
4432
        if (strstr($search, '+')) {
4433
            $search_terms = explode('+', $search);
4434
        } else {
4435
            $search_terms[] = trim($search);
4436
        }
4437
        $counter = 0;
4438
        foreach ($search_terms as $key => $search_term) {
4439
            $input = api_preg_replace('/'.preg_quote(trim($search_term), '/').'/i', '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>', $input);
4440
            $counter++;
4441
        }
4442
    }
4443
4444
    // TODO: Security should be implemented outside this function.
4445
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles (see comments of Security::remove_XSS() method to learn about other levels).
4446
4447
    return Security::remove_XSS($input, STUDENT, true);
4448
}
4449
4450
/**
4451
 * Display the search form for the forum and display the search results
4452
 * @return void display an HTML search results
4453
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4454
 * @version march 2008, dokeos 1.8.5
4455
 */
4456
function forum_search()
4457
{
4458
    $form = new FormValidator('forumsearch', 'post', 'forumsearch.php?'.api_get_cidreq());
4459
4460
    // Setting the form elements.
4461
    $form->addElement('header', '', get_lang('ForumSearch'));
4462
    $form->addElement('text', 'search_term', get_lang('SearchTerm'), array('autofocus'));
4463
    $form->applyFilter('search_term', 'html_filter');
4464
    $form->addElement('static', 'search_information', '', get_lang('ForumSearchInformation'));
4465
    $form->addButtonSearch(get_lang('Search'));
4466
4467
    // Setting the rules.
4468
    $form->addRule('search_term', get_lang('ThisFieldIsRequired'), 'required');
4469
    $form->addRule('search_term', get_lang('TooShort'), 'minlength', 3);
4470
4471
    // Validation or display.
4472
    if ($form->validate()) {
4473
        $values = $form->exportValues();
4474
        $form->setDefaults($values);
4475
        $form->display();
4476
        // Display the search results.
4477
        display_forum_search_results(stripslashes($values['search_term']));
4478
    } else {
4479
        $form->display();
4480
    }
4481
}
4482
4483
/**
4484
 * Display the search results
4485
 * @param string
4486
 * @param string $search_term
4487
 * @return void display the results
4488
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4489
 * @version march 2008, dokeos 1.8.5
4490
 */
4491
function display_forum_search_results($search_term)
4492
{
4493
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4494
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4495
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
4496
    $session_id = api_get_session_id();
4497
    $gradebook = Security::remove_XSS($_GET['gradebook']);
4498
    $course_id = api_get_course_int_id();
4499
4500
    // Defining the search strings as an array.
4501
    if (strstr($search_term, '+')) {
4502
        $search_terms = explode('+', $search_term);
4503
    } else {
4504
        $search_terms[] = $search_term;
4505
    }
4506
4507
    // Search restriction.
4508
    foreach ($search_terms as $value) {
4509
        $search_restriction[] = "
4510
        (
4511
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR 
4512
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%' 
4513
        )";
4514
    }
4515
4516
    $sessionCondition = api_get_session_condition($session_id, true, false, 'item_property.session_id');
4517
4518
    $sql = "SELECT posts.*
4519
            FROM $table_posts posts INNER JOIN $table_threads threads
4520
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
4521
            INNER JOIN $table_item_property item_property
4522
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
4523
            WHERE
4524
                posts.c_id = $course_id AND 
4525
                item_property.c_id = $course_id AND 
4526
                item_property.visibility = 1  
4527
                $sessionCondition AND
4528
                posts.visible = 1 AND 
4529
                item_property.tool = '".TOOL_FORUM_THREAD."' AND 
4530
                ".implode(' AND ', $search_restriction)."
4531
            GROUP BY posts.post_id";
4532
4533
    // Getting all the information of the forum categories.
4534
    $forum_categories_list = get_forum_categories();
4535
4536
    // Getting all the information of the forums.
4537
    $forum_list = get_forums();
4538
4539
    $result = Database::query($sql);
4540
    $search_results = [];
4541
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4542
        $forumId = $row['forum_id'];
4543
        $forumData = get_forums($forumId);
4544
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
4545
        $display_result = false;
4546
        /*
4547
          We only show it when
4548
          1. forum category is visible
4549
          2. forum is visible
4550
          3. thread is visible (to do)
4551
          4. post is visible
4552
         */
4553
        if (!api_is_allowed_to_edit(null, true)) {
4554
            if (!empty($category)) {
4555
                if ($category['visibility'] == '1' && $forumData['visibility'] == '1') {
4556
                    $display_result = true;
4557
                }
4558
            } else {
4559
                if ($forumData['visible'] == '1') {
4560
                    $display_result = true;
4561
                }
4562
            }
4563
        } else {
4564
            $display_result = true;
4565
        }
4566
4567
        if ($display_result) {
4568
            $categoryName = !empty($category) ? $category['cat_title'] : '';
4569
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
4570
                prepare4display($categoryName).'</a> &gt; ';
4571
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
4572
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
4573
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&gradebook='.$gradebook.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
4574
                prepare4display($row['post_title']).'</a>';
4575
            $search_results_item .= '<br />';
4576
            if (api_strlen($row['post_title']) > 200) {
4577
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
0 ignored issues
show
Security Bug introduced by
It seems like api_substr(strip_tags($r...'post_title']), 0, 200) targeting api_substr() can also be of type false; however, prepare4display() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
4578
            } else {
4579
                $search_results_item .= prepare4display($row['post_title']);
4580
            }
4581
            $search_results_item .= '</li>';
4582
            $search_results[] = $search_results_item;
4583
        }
4584
    }
4585
    echo '<legend>'.count($search_results).' '.get_lang('ForumSearchResults').'</legend>';
4586
    echo '<ol>';
4587
    if ($search_results) {
4588
        echo implode($search_results);
4589
    }
4590
    echo '</ol>';
4591
}
4592
4593
/**
4594
 * Return the link to the forum search page
4595
 *
4596
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4597
 * @version April 2008, dokeos 1.8.5
4598
 */
4599
function search_link()
4600
{
4601
    $return = '';
4602
    $origin = api_get_origin();
4603
    if ($origin != 'learnpath') {
4604
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
4605
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
4606
4607
        if (!empty($_GET['search'])) {
4608
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
4609
            $url = api_get_self().'?';
4610
            $url_parameter = array();
4611
            foreach ($_GET as $key => $value) {
4612
                if ($key != 'search') {
4613
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
4614
                }
4615
            }
4616
            $url = $url.implode('&', $url_parameter);
4617
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
4618
        }
4619
    }
4620
4621
    return $return;
4622
}
4623
4624
/**
4625
 * This function adds an attachment file into a forum
4626
 * @param string $file_comment  a comment about file
4627
 * @param int $last_id from forum_post table
4628
 * @return false|null
4629
 */
4630
function add_forum_attachment_file($file_comment, $last_id)
4631
{
4632
    $_course = api_get_course_info();
4633
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4634
4635
    if (!isset($_FILES['user_upload'])) {
4636
        return false;
4637
    }
4638
4639
    $fileCount = count($_FILES['user_upload']['name']);
4640
    $filesData = [];
4641
4642 View Code Duplication
    if (!is_array($_FILES['user_upload']['name'])) {
4643
        $filesData[] = $_FILES['user_upload'];
4644
    } else {
4645
        $fileKeys = array_keys($_FILES['user_upload']);
4646
        for ($i = 0; $i < $fileCount; $i++) {
4647
            foreach ($fileKeys as $key) {
4648
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
4649
            }
4650
        }
4651
    }
4652
4653
    foreach ($filesData as $attachment) {
4654
        if (empty($attachment['name'])) {
4655
            continue;
4656
        }
4657
4658
        $upload_ok = process_uploaded_file($attachment);
4659
4660
        if (!$upload_ok) {
4661
            continue;
4662
        }
4663
4664
        $course_dir = $_course['path'].'/upload/forum';
4665
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
4666
        $updir = $sys_course_path.$course_dir;
4667
4668
        // Try to add an extension to the file if it hasn't one.
4669
        $new_file_name = add_ext_on_mime(
4670
            stripslashes($attachment['name']),
4671
            $attachment['type']
4672
        );
4673
        // User's file name
4674
        $file_name = $attachment['name'];
4675
4676
        if (!filter_extension($new_file_name)) {
4677
            Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
4678
4679
            return;
4680
        }
4681
4682
        $new_file_name = uniqid('');
4683
        $new_path = $updir.'/'.$new_file_name;
4684
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
4685
        $safe_file_comment = Database::escape_string($file_comment);
4686
        $safe_file_name = Database::escape_string($file_name);
4687
        $safe_new_file_name = Database::escape_string($new_file_name);
4688
        $last_id = intval($last_id);
4689
        // Storing the attachments if any.
4690
        if (!$result) {
4691
            return;
4692
        }
4693
4694
        $last_id_file = Database::insert(
4695
            $agenda_forum_attachment,
4696
            [
4697
                'c_id' => api_get_course_int_id(),
4698
                'filename' => $safe_file_name,
4699
                'comment' => $safe_file_comment,
4700
                'path' => $safe_new_file_name,
4701
                'post_id' => $last_id,
4702
                'size' => intval($attachment['size']),
4703
            ]
4704
        );
4705
4706
        api_item_property_update(
4707
            $_course,
4708
            TOOL_FORUM_ATTACH,
4709
            $last_id_file,
4710
            'ForumAttachmentAdded',
4711
            api_get_user_id()
4712
        );
4713
    }
4714
}
4715
4716
/**
4717
 * This function edits an attachment file into a forum
4718
 * @param string $file_comment  a comment about file
4719
 * @param int $post_id
4720
 * @param int $id_attach attachment file Id
4721
 * @return void
4722
 */
4723
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
4724
{
4725
    $_course = api_get_course_info();
4726
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4727
    $course_id = api_get_course_int_id();
4728
4729
    $fileCount = count($_FILES['user_upload']['name']);
4730
    $filesData = [];
4731
4732 View Code Duplication
    if (!is_array($_FILES['user_upload']['name'])) {
4733
        $filesData[] = $_FILES['user_upload'];
4734
    } else {
4735
        $fileKeys = array_keys($_FILES['user_upload']);
4736
4737
        for ($i = 0; $i < $fileCount; $i++) {
4738
            foreach ($fileKeys as $key) {
4739
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
4740
            }
4741
        }
4742
    }
4743
4744
    foreach ($filesData as $attachment) {
4745
        if (empty($attachment['name'])) {
4746
            continue;
4747
        }
4748
4749
        $upload_ok = process_uploaded_file($attachment);
4750
4751
        if (!$upload_ok) {
4752
            continue;
4753
        }
4754
4755
        $course_dir = $_course['path'].'/upload/forum';
4756
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
4757
        $updir = $sys_course_path.$course_dir;
4758
4759
        // Try to add an extension to the file if it hasn't one.
4760
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
4761
        // User's file name
4762
        $file_name = $attachment['name'];
4763
4764
        if (!filter_extension($new_file_name)) {
4765
            Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
4766
        } else {
4767
            $new_file_name = uniqid('');
4768
            $new_path = $updir.'/'.$new_file_name;
4769
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
4770
            $safe_file_comment = Database::escape_string($file_comment);
4771
            $safe_file_name = Database::escape_string($file_name);
4772
            $safe_new_file_name = Database::escape_string($new_file_name);
4773
            $safe_post_id = (int) $post_id;
4774
            $safe_id_attach = (int) $id_attach;
4775
            // Storing the attachments if any.
4776 View Code Duplication
            if ($result) {
4777
                $sql = "UPDATE $table_forum_attachment SET filename = '$safe_file_name', comment = '$safe_file_comment', path = '$safe_new_file_name', post_id = '$safe_post_id', size ='".$attachment['size']."'
4778
                       WHERE c_id = $course_id AND id = '$safe_id_attach'";
4779
                Database::query($sql);
4780
                api_item_property_update(
4781
                    $_course,
4782
                    TOOL_FORUM_ATTACH,
4783
                    $safe_id_attach,
4784
                    'ForumAttachmentUpdated',
4785
                    api_get_user_id()
4786
                );
4787
            }
4788
        }
4789
    }
4790
}
4791
4792
/**
4793
 * Show a list with all the attachments according to the post's id
4794
 * @param int $post_id
4795
 * @return array with the post info
4796
 * @author Julio Montoya
4797
 * @version avril 2008, dokeos 1.8.5
4798
 */
4799
function get_attachment($post_id)
4800
{
4801
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4802
    $course_id = api_get_course_int_id();
4803
    $row = array();
4804
    $post_id = intval($post_id);
4805
    $sql = "SELECT iid, path, filename, comment 
4806
            FROM $forum_table_attachment
4807
            WHERE c_id = $course_id AND post_id = $post_id";
4808
    $result = Database::query($sql);
4809
    if (Database::num_rows($result) != 0) {
4810
        $row = Database::fetch_array($result);
4811
    }
4812
4813
    return $row;
4814
}
4815
4816
/**
4817
 * @param int $postId
4818
 *
4819
 * @return array
4820
 */
4821
function getAllAttachment($postId)
4822
{
4823
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4824
    $courseId = api_get_course_int_id();
4825
    $postId = intval($postId);
4826
    $columns = array('iid', 'path', 'filename', 'comment');
4827
    $conditions = array(
4828
        'where' => array(
4829
            'c_id = ? AND post_id = ?' => array($courseId, $postId),
4830
        ),
4831
    );
4832
    $array = Database::select(
4833
        $columns,
4834
        $forumAttachmentTable,
4835
        $conditions,
4836
        'all',
4837
        'ASSOC'
4838
    );
4839
4840
    return $array;
4841
}
4842
4843
/**
4844
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional)
4845
 * @param int $post_id
4846
 * @param int $id_attach
4847
 * @param bool $display to show or not result message
4848
 * @return integer
4849
 * @author Julio Montoya
4850
 * @version october 2014, chamilo 1.9.8
4851
 */
4852
function delete_attachment($post_id, $id_attach = 0, $display = true)
4853
{
4854
    $_course = api_get_course_info();
4855
4856
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4857
    $course_id = api_get_course_int_id();
4858
4859
    $cond = (!empty($id_attach)) ? " iid = ".(int) $id_attach."" : " post_id = ".(int) $post_id."";
4860
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
4861
    $res = Database::query($sql);
4862
    $row = Database::fetch_array($res);
4863
4864
    $course_dir = $_course['path'].'/upload/forum';
4865
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
4866
    $updir = $sys_course_path.$course_dir;
4867
    $my_path = isset($row['path']) ? $row['path'] : null;
4868
    $file = $updir.'/'.$my_path;
4869
    if (Security::check_abs_path($file, $updir)) {
4870
        @unlink($file);
4871
    }
4872
4873
    // Delete from forum_attachment table.
4874
    $sql = "DELETE FROM $forum_table_attachment WHERE c_id = $course_id AND $cond ";
4875
    $result = Database::query($sql);
4876
    if ($result !== false) {
4877
        $affectedRows = Database::affected_rows($result);
4878
    } else {
4879
        $affectedRows = 0;
4880
    }
4881
4882
    // Update item_property.
4883
    api_item_property_update(
4884
        $_course,
4885
        TOOL_FORUM_ATTACH,
4886
        $id_attach,
4887
        'ForumAttachmentDelete',
4888
        api_get_user_id()
4889
    );
4890
4891
    if (!empty($result) && !empty($id_attach) && $display) {
4892
        $message = get_lang('AttachmentFileDeleteSuccess');
4893
        echo Display::return_message($message, 'confirmation');
4894
    }
4895
4896
    return $affectedRows;
4897
}
4898
4899
/**
4900
 * This function gets all the forum information of the all the forum of the group
4901
 *
4902
 * @param integer $groupId the id of the group we need the fora of (see forum.forum_of_group)
0 ignored issues
show
Bug introduced by
There is no parameter named $groupId. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
4903
 * @return array
4904
 *
4905
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
4906
 */
4907
function get_forums_of_group($groupInfo)
4908
{
4909
    $table_forums = Database::get_course_table(TABLE_FORUM);
4910
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4911
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4912
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
4913
    $course_id = api_get_course_int_id();
4914
    $groupId = (int) $groupInfo['id'];
4915
4916
    // Student
4917
    // Select all the forum information of all forums (that are visible to students).
4918
4919
    $sql = "SELECT * FROM $table_forums forum 
4920
            INNER JOIN $table_item_property item_properties
4921
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
4922
            WHERE
4923
                forum.forum_of_group = $groupId AND
4924
                forum.c_id = $course_id AND
4925
                item_properties.c_id = $course_id AND                
4926
                item_properties.visibility = 1 AND
4927
                item_properties.tool = '".TOOL_FORUM."'
4928
            ORDER BY forum.forum_order ASC";
4929
4930
    // Select the number of threads of the forums (only the threads that are visible).
4931
    $sql2 = "SELECT 
4932
                count(thread_id) AS number_of_threads, 
4933
                threads.forum_id
4934
            FROM $table_threads threads 
4935
            INNER JOIN $table_item_property item_properties
4936
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
4937
            WHERE                
4938
                threads.c_id = $course_id AND
4939
                item_properties.c_id = $course_id AND
4940
                item_properties.visibility = 1 AND
4941
                item_properties.tool='".TOOL_FORUM_THREAD."'
4942
            GROUP BY threads.forum_id";
4943
4944
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
4945
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
4946
            FROM $table_posts posts 
4947
            INNER JOIN $table_threads threads 
4948
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
4949
            INNER JOIN $table_item_property item_properties
4950
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
4951
            WHERE 
4952
                posts.visible=1 AND
4953
                posts.c_id = $course_id AND
4954
                item_properties.c_id = $course_id AND
4955
                threads.c_id = $course_id AND 
4956
                item_properties.visibility = 1 AND 
4957
                item_properties.tool='".TOOL_FORUM_THREAD."'
4958
            GROUP BY threads.forum_id";
4959
4960
    // Course Admin
4961 View Code Duplication
    if (api_is_allowed_to_edit()) {
4962
        // Select all the forum information of all forums (that are not deleted).
4963
        $sql = "SELECT *
4964
                FROM $table_forums forum INNER JOIN $table_item_property item_properties
4965
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
4966
                WHERE
4967
                    forum.forum_of_group = $groupId AND
4968
                    forum.c_id = $course_id AND
4969
                    item_properties.c_id = $course_id AND                    
4970
                    item_properties.visibility <> 2 AND
4971
                    item_properties.tool = '".TOOL_FORUM."'
4972
                ORDER BY forum_order ASC";
4973
4974
        // Select the number of threads of the forums (only the threads that are not deleted).
4975
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
4976
                 FROM $table_threads threads INNER JOIN $table_item_property item_properties
4977
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
4978
                 WHERE
4979
                    threads.c_id = $course_id AND
4980
                    item_properties.c_id = $course_id AND
4981
                    item_properties.visibility <> 2 AND
4982
                    item_properties.tool='".TOOL_FORUM_THREAD."'
4983
                GROUP BY threads.forum_id";
4984
        // Select the number of posts of the forum.
4985
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
4986
                FROM $table_posts
4987
                WHERE c_id = $course_id 
4988
                GROUP BY forum_id";
4989
    }
4990
4991
    // Handling all the forum information.
4992
    $result = Database::query($sql);
4993
    $forum_list = array();
4994
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4995
        $forum_list[$row['forum_id']] = $row;
4996
    }
4997
4998
    // Handling the thread count information.
4999
    $result2 = Database::query($sql2);
5000 View Code Duplication
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5001
        if (is_array($forum_list)) {
5002
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5003
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5004
            }
5005
        }
5006
    }
5007
5008
    // Handling the post count information.
5009
    $result3 = Database::query($sql3);
5010 View Code Duplication
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5011
        if (is_array($forum_list)) {
5012
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5013
                // This is needed because sql3 takes also the deleted forums into account.
5014
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5015
            }
5016
        }
5017
    }
5018
5019
    // Finding the last post information
5020
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5021
    if (!empty($forum_list)) {
5022 View Code Duplication
        foreach ($forum_list as $key => $value) {
5023
            $last_post_info_of_forum = get_last_post_information($key, api_is_allowed_to_edit());
5024
            if ($last_post_info_of_forum) {
5025
                $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
5026
                $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
5027
                $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
5028
                $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
5029
                $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
5030
                $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
5031
            }
5032
        }
5033
    }
5034
5035
    return $forum_list;
5036
}
5037
5038
/**
5039
 * This function stores which users have to be notified of which forums or threads
5040
 *
5041
 * @param string $content does the user want to be notified about a forum or about a thread
5042
 * @param integer $id the id of the forum or thread
5043
 * @return string language variable
5044
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5045
 * @version May 2008, dokeos 1.8.5
5046
 * @since May 2008, dokeos 1.8.5
5047
 */
5048
function set_notification($content, $id, $add_only = false)
5049
{
5050
    $_user = api_get_user_info();
5051
5052
    // Database table definition
5053
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5054
5055
    $course_id = api_get_course_int_id();
5056
5057
    // Which database field do we have to store the id in?
5058
    if ($content == 'forum') {
5059
        $database_field = 'forum_id';
5060
    } else {
5061
        $database_field = 'thread_id';
5062
    }
5063
5064
    // First we check if the notification is already set for this.
5065
    $sql = "SELECT * FROM $table_notification
5066
            WHERE
5067
                c_id = $course_id AND
5068
                $database_field = '".Database::escape_string($id)."' AND
5069
                user_id = '".intval($_user['user_id'])."'";
5070
    $result = Database::query($sql);
5071
    $total = Database::num_rows($result);
5072
5073
    // If the user did not indicate that (s)he wanted to be notified already
5074
    // then we store the notification request (to prevent double notification requests).
5075
    if ($total <= 0) {
5076
        $sql = "INSERT INTO $table_notification (c_id, $database_field, user_id)
5077
                VALUES (".$course_id.", '".Database::escape_string($id)."','".intval($_user['user_id'])."')";
5078
        Database::query($sql);
5079
        Session::erase('forum_notification');
5080
        get_notifications_of_user(0, true);
5081
5082
        return get_lang('YouWillBeNotifiedOfNewPosts');
5083
    } else {
5084
        if (!$add_only) {
5085
            $sql = "DELETE FROM $table_notification
5086
                    WHERE
5087
                        c_id = $course_id AND
5088
                        $database_field = '".Database::escape_string($id)."' AND
5089
                        user_id = '".intval($_user['user_id'])."'";
5090
            Database::query($sql);
5091
            Session::erase('forum_notification');
5092
            get_notifications_of_user(0, true);
5093
5094
            return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
5095
        }
5096
    }
5097
}
5098
5099
/**
5100
 * This function retrieves all the email adresses of the users who wanted to be notified
5101
 * about a new post in a certain forum or thread
5102
 *
5103
 * @param string $content does the user want to be notified about a forum or about a thread
5104
 * @param integer $id the id of the forum or thread
5105
 * @return array returns
5106
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5107
 * @version May 2008, dokeos 1.8.5
5108
 * @since May 2008, dokeos 1.8.5
5109
 */
5110
function get_notifications($content, $id)
5111
{
5112
    // Database table definition
5113
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5114
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5115
5116
    $course_id = api_get_course_int_id();
5117
5118
    // Which database field contains the notification?
5119
    if ($content == 'forum') {
5120
        $database_field = 'forum_id';
5121
    } else {
5122
        $database_field = 'thread_id';
5123
    }
5124
5125
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
5126
            FROM $table_users user, $table_notification notification
5127
            WHERE notification.c_id = $course_id AND user.active = 1 AND
5128
            user.user_id = notification.user_id AND
5129
            notification.$database_field= '".Database::escape_string($id)."'";
5130
5131
    $result = Database::query($sql);
5132
    $return = array();
5133
5134
    while ($row = Database::fetch_array($result)) {
5135
        $return['user'.$row['user_id']] = array('email' => $row['email'], 'user_id' => $row['user_id']);
5136
    }
5137
5138
    return $return;
5139
}
5140
5141
/**
5142
 * Get all the users who need to receive a notification of a new post (those subscribed to
5143
 * the forum or the thread)
5144
 *
5145
 * @param integer $forum_id the id of the forum
5146
 * @param integer $thread_id the id of the thread
5147
 * @param integer $post_id the id of the post
5148
 * @return false|null
5149
 *
5150
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5151
 * @version May 2008, dokeos 1.8.5
5152
 * @since May 2008, dokeos 1.8.5
5153
 */
5154
function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
5155
{
5156
    $_course = api_get_course_info();
5157
    $forum_id = (int) $forum_id;
5158
5159
    // The content of the mail
5160
    $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forum_id.'&thread='.$thread_id;
5161
5162
    // Users who subscribed to the forum
5163
    if ($forum_id != 0) {
5164
        $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
5165
    } else {
5166
        return false;
5167
    }
5168
5169
    $current_thread = get_thread_information($forum_id, $thread_id);
5170
    $current_forum = get_forum_information($current_thread['forum_id']);
5171
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'].' - '.$current_forum['forum_title'].' - '.$current_thread['thread_title'];
5172
5173
    // User who subscribed to the thread
5174
    if ($thread_id != 0) {
5175
        $users_to_be_notified_by_thread = get_notifications('thread', $thread_id);
5176
    }
5177
5178
    // Merging the two
5179
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
5180
    $sender_id = api_get_user_id();
5181
5182
    if (is_array($users_to_be_notified)) {
5183
        foreach ($users_to_be_notified as $value) {
5184
5185
            $user_info = api_get_user_info($value['user_id']);
5186
            $email_body = get_lang('Dear').' '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
5187
            $email_body .= get_lang('NewForumPost').": ".$current_forum['forum_title'].' - '.$current_thread['thread_title']." <br />\n";
5188
            $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."]  <br />\n";
5189
            $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
5190
            $email_body .= get_lang('ThreadCanBeFoundHere').': <br /> <a href="'.$thread_link.'">'.$thread_link."</a>\n";
5191
5192
            MessageManager::send_message_simple(
5193
                $value['user_id'], $subject, $email_body, $sender_id
5194
            );
5195
        }
5196
    }
5197
}
5198
5199
/**
5200
 * Get all the notification subscriptions of the user
5201
 * = which forums and which threads does the user wants to be informed of when a new
5202
 * post is added to this thread
5203
 *
5204
 * @param integer $user_id the user_id of a user (default = 0 => the current user)
5205
 * @param boolean $force force get the notification subscriptions (even if the information is already in the session
5206
 * @return array returns
5207
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5208
 * @version May 2008, dokeos 1.8.5
5209
 * @since May 2008, dokeos 1.8.5
5210
 */
5211
function get_notifications_of_user($user_id = 0, $force = false)
5212
{
5213
    // Database table definition
5214
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5215
    $course_id = api_get_course_int_id();
5216
    if (empty($course_id) || $course_id == -1) {
5217
        return null;
5218
    }
5219
    if ($user_id == 0) {
5220
        $user_id = api_get_user_id();
5221
    }
5222
5223
    if (!isset($_SESSION['forum_notification']) ||
5224
        $_SESSION['forum_notification']['course'] != $course_id ||
5225
        $force = true
5226
    ) {
5227
        $_SESSION['forum_notification']['course'] = $course_id;
5228
5229
        $sql = "SELECT * FROM $table_notification
5230
                WHERE c_id = $course_id AND user_id='".intval($user_id)."'";
5231
        $result = Database::query($sql);
5232
        while ($row = Database::fetch_array($result)) {
5233
            if (!is_null($row['forum_id'])) {
5234
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5235
            }
5236
            if (!is_null($row['thread_id'])) {
5237
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5238
            }
5239
        }
5240
    }
5241
}
5242
5243
/**
5244
 * This function counts the number of post inside a thread
5245
 * @param   int $thread_id
5246
 * @return  int the number of post inside a thread
5247
 * @author Jhon Hinojosa <[email protected]>,
5248
 * @version octubre 2008, dokeos 1.8
5249
 */
5250 View Code Duplication
function count_number_of_post_in_thread($thread_id)
5251
{
5252
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5253
    $course_id = api_get_course_int_id();
5254
    if (empty($course_id)) {
5255
        return 0;
5256
    }
5257
    $sql = "SELECT count(*) count FROM $table_posts
5258
            WHERE 
5259
                c_id = $course_id AND 
5260
                thread_id='".intval($thread_id)."' ";
5261
    $result = Database::query($sql);
5262
5263
    $count = 0;
5264
    if (Database::num_rows($result) > 0) {
5265
        $row = Database::fetch_array($result);
5266
        $count = $row['count'];
5267
    }
5268
5269
    return $count;
5270
}
5271
5272
/**
5273
 * This function counts the number of post inside a thread user
5274
 * @param   int $thread_id
5275
 * @param   int $user_id
5276
 *
5277
 * @return  int the number of post inside a thread user
5278
 */
5279 View Code Duplication
function count_number_of_post_for_user_thread($thread_id, $user_id)
5280
{
5281
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5282
    $course_id = api_get_course_int_id();
5283
    $sql = "SELECT count(iid) as count 
5284
            FROM $table_posts
5285
            WHERE c_id = $course_id AND
5286
                  thread_id=".intval($thread_id)." AND
5287
                  poster_id = ".intval($user_id)." AND visible = 1 ";
5288
    $result = Database::query($sql);
5289
    $count = 0;
5290
    if (Database::num_rows($result) > 0) {
5291
        $count = Database::fetch_array($result);
5292
        $count = $count['count'];
5293
    }
5294
5295
    return $count;
5296
}
5297
5298
/**
5299
 * This function counts the number of user register in course
5300
 * @param   int $course_id Course ID
5301
 * @deprecated use CourseManager::get_users_count_in_course
5302
 * @return  int the number of user register in course
5303
 * @author Jhon Hinojosa <[email protected]>,
5304
 * @version octubre 2008, dokeos 1.8
5305
 */
5306
function count_number_of_user_in_course($course_id)
5307
{
5308
    $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5309
5310
    $sql = "SELECT * FROM $table
5311
            WHERE c_id ='".intval($course_id)."' ";
5312
    $result = Database::query($sql);
5313
5314
    return count(Database::store_result($result));
5315
}
5316
5317
/**
5318
 * This function retrieves information of statistical
5319
 * @param   int $thread_id
5320
 * @param   int $user_id
5321
 * @param   int $course_id
5322
 *
5323
 * @return  array the information of statistical
5324
 * @author Jhon Hinojosa <[email protected]>,
5325
 * @version oct 2008, dokeos 1.8
5326
 */
5327
function get_statistical_information($thread_id, $user_id, $course_id)
5328
{
5329
    $result = array();
5330
    $courseInfo = api_get_course_info_by_id($course_id);
5331
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
5332
    $result['post'] = count_number_of_post_in_thread($thread_id);
5333
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
5334
5335
    return $result;
5336
}
5337
5338
/**
5339
 * This function return the posts inside a thread from a given user
5340
 * @param   string $course_code
5341
 * @param   int $thread_id
5342
 * @param   int $user_id
5343
 *
5344
 * @return  array posts inside a thread
5345
 * @author Jhon Hinojosa <[email protected]>,
5346
 * @version oct 2008, dokeos 1.8
5347
 */
5348
function get_thread_user_post($course_code, $thread_id, $user_id)
5349
{
5350
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5351
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5352
    $thread_id = intval($thread_id);
5353
    $user_id = intval($user_id);
5354
    $course_info = api_get_user_info($course_code);
5355
    $course_id = $course_info['real_id'];
5356
5357
    if (empty($course_id)) {
5358
        $course_id = api_get_course_int_id();
5359
    }
5360
    $sql = "SELECT * FROM $table_posts posts
5361
            LEFT JOIN  $table_users users
5362
                ON posts.poster_id=users.user_id
5363
            WHERE
5364
                posts.c_id = $course_id AND
5365
                posts.thread_id='$thread_id'
5366
                AND posts.poster_id='$user_id'
5367
            ORDER BY posts.post_id ASC";
5368
5369
    $result = Database::query($sql);
5370
    $post_list = array();
5371 View Code Duplication
    while ($row = Database::fetch_array($result)) {
5372
        $row['status'] = '1';
5373
        $post_list[] = $row;
5374
        $sql = "SELECT * FROM $table_posts posts
5375
                LEFT JOIN $table_users users
5376
                ON (posts.poster_id=users.user_id)
5377
                WHERE
5378
                    posts.c_id = $course_id AND
5379
                    posts.thread_id='$thread_id'
5380
                    AND posts.post_parent_id='".$row['post_id']."'
5381
                ORDER BY posts.post_id ASC";
5382
        $result2 = Database::query($sql);
5383
        while ($row2 = Database::fetch_array($result2)) {
5384
            $row2['status'] = '0';
5385
            $post_list[] = $row2;
5386
        }
5387
    }
5388
5389
    return $post_list;
5390
}
5391
5392
/**
5393
 * This function get the name of an thread by id
5394
 * @param int thread_id
5395
 * @return String
5396
 * @author Christian Fasanando
5397
 * @author Julio Montoya <[email protected]> Adding security
5398
 */
5399
function get_name_thread_by_id($thread_id)
5400
{
5401
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
5402
    $course_id = api_get_course_int_id();
5403
    $sql = "SELECT thread_title 
5404
            FROM $t_forum_thread
5405
            WHERE c_id = $course_id AND thread_id = '".intval($thread_id)."' ";
5406
    $result = Database::query($sql);
5407
    $row = Database::fetch_array($result);
5408
5409
    return $row[0];
5410
}
5411
5412
/**
5413
 * This function gets all the post written by an user
5414
 * @param int $user_id
5415
 * @param string $course_code
5416
 *
5417
 * @return string
5418
 */
5419
function get_all_post_from_user($user_id, $course_code)
5420
{
5421
    $j = 0;
5422
    $forums = get_forums('', $course_code);
5423
    krsort($forums);
5424
    $forum_results = '';
5425
5426
    foreach ($forums as $forum) {
5427
        if ($forum['visibility'] == 0) {
5428
            continue;
5429
        }
5430
        if ($j <= 4) {
5431
            $threads = get_threads($forum['forum_id']);
5432
5433
            if (is_array($threads)) {
5434
                $i = 0;
5435
                $hand_forums = '';
5436
                $post_counter = 0;
5437
5438
                foreach ($threads as $thread) {
5439
                    if ($thread['visibility'] == 0) {
5440
                        continue;
5441
                    }
5442
                    if ($i <= 4) {
5443
                        $post_list = get_thread_user_post_limit($course_code, $thread['thread_id'], $user_id, 1);
5444
                        $post_counter = count($post_list);
5445
                        if (is_array($post_list) && count($post_list) > 0) {
5446
                            $hand_forums .= '<div id="social-thread">';
5447
                            $hand_forums .= Display::return_icon('thread.png', get_lang('Thread'), '', ICON_SIZE_MEDIUM);
5448
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
5449
                            $hand_forums .= '</div>';
5450
5451
                            foreach ($post_list as $posts) {
5452
                                $hand_forums .= '<div id="social-post">';
5453
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
5454
                                $hand_forums .= '<br / >';
5455
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
5456
                                $hand_forums .= '</div>';
5457
                                $hand_forums .= '<br / >';
5458
                            }
5459
                        }
5460
                    }
5461
                    $i++;
5462
                }
5463
                $forum_results .= '<div id="social-forum">';
5464
                $forum_results .= '<div class="clear"></div><br />';
5465
                $forum_results .= '<div id="social-forum-title">'.
5466
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
5467
                    '<div style="float:right;margin-top:-35px">
5468
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
5469
                            get_lang('SeeForum').'    
5470
                        </a>
5471
                     </div></div>';
5472
                $forum_results .= '<br / >';
5473
                if ($post_counter > 0) {
5474
                    $forum_results .= $hand_forums;
5475
                }
5476
                $forum_results .= '</div>';
5477
            }$j++;
5478
        }
5479
    }
5480
5481
    return $forum_results;
5482
}
5483
5484
/**
5485
 * @param string $course_code
5486
 * @param int $thread_id
5487
 * @param int $user_id
5488
 * @param int $limit
5489
 *
5490
 * @return array
5491
 */
5492
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
5493
{
5494
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5495
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5496
5497
    $course_info = api_get_course_info($course_code);
5498
    $course_id = $course_info['real_id'];
5499
5500
    $sql = "SELECT * FROM $table_posts posts
5501
            LEFT JOIN  $table_users users
5502
                ON posts.poster_id=users.user_id
5503
            WHERE
5504
                posts.c_id = $course_id AND
5505
                posts.thread_id='".Database::escape_string($thread_id)."'
5506
                AND posts.poster_id='".Database::escape_string($user_id)."'
5507
            ORDER BY posts.post_id DESC LIMIT $limit ";
5508
    $result = Database::query($sql);
5509
    $post_list = array();
5510
    while ($row = Database::fetch_array($result)) {
5511
        $row['status'] = '1';
5512
        $post_list[] = $row;
5513
    }
5514
5515
    return $post_list;
5516
}
5517
5518
/**
5519
 * @param string $user_id
5520
 * @param int $courseId
5521
 * @param int $sessionId
5522
 *
5523
 * @return array
5524
 */
5525
function getForumCreatedByUser($user_id, $courseId, $sessionId)
5526
{
5527
    $items = api_get_item_property_list_by_tool_by_user(
5528
        $user_id,
5529
        'forum',
5530
        $courseId,
5531
        $sessionId
5532
    );
5533
5534
    $courseInfo = api_get_course_info_by_id($courseId);
5535
5536
    $forumList = array();
5537 View Code Duplication
    if (!empty($items)) {
5538
        foreach ($items as $forum) {
5539
            $forumInfo = get_forums(
5540
                $forum['ref'],
5541
                $courseInfo['code'],
5542
                true,
5543
                $sessionId
5544
            );
5545
5546
            $forumList[] = array(
5547
                $forumInfo['forum_title'],
5548
                api_get_local_time($forum['insert_date']),
5549
                api_get_local_time($forum['lastedit_date']),
5550
            );
5551
        }
5552
    }
5553
5554
    return $forumList;
5555
}
5556
5557
/**
5558
 * This function builds an array of all the posts in a given thread
5559
 * where the key of the array is the post_id
5560
 * It also adds an element children to the array which itself is an array
5561
 * that contains all the id's of the first-level children
5562
 * @return array $rows containing all the information on the posts of a thread
5563
 * @author Patrick Cool <[email protected]>, Ghent University
5564
 */
5565
function calculate_children($rows)
5566
{
5567
    $sorted_rows = array(0 => array());
5568
    if (!empty($rows)) {
5569
        foreach ($rows as $row) {
5570
            $rows_with_children[$row['post_id']] = $row;
5571
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
5572
        }
5573
5574
        $rows = $rows_with_children;
5575
        forumRecursiveSort($rows, $sorted_rows);
5576
        unset($sorted_rows[0]);
5577
    }
5578
5579
    return $sorted_rows;
5580
}
5581
5582
/**
5583
 * @param $rows
5584
 * @param $threads
5585
 * @param int $seed
5586
 * @param int $indent
5587
 */
5588
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
5589
{
5590
    if ($seed > 0) {
5591
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
5592
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
5593
        $indent++;
5594
    }
5595
5596
    if (isset($rows[$seed]['children'])) {
5597
        foreach ($rows[$seed]['children'] as $child) {
5598
            forumRecursiveSort($rows, $threads, $child, $indent);
5599
        }
5600
    }
5601
}
5602
5603
/**
5604
 * Update forum attachment data, used to update comment and post ID.
5605
 * @param $array Array (field => value) to update forum attachment row.
5606
 * @param $id Attach ID to find row to update.
5607
 * @param null $courseId Course ID to find row to update.
5608
 * @return int Number of affected rows.
5609
 */
5610
function editAttachedFile($array, $id, $courseId = null) {
5611
    // Init variables
5612
    $setString = '';
5613
    $id = intval($id);
5614
    $courseId = intval($courseId);
5615
    if (empty($courseId)) {
5616
        // $courseId can be null, use api method
5617
        $courseId = api_get_course_int_id();
5618
    }
5619
    /*
5620
     * Check if Attachment ID and Course ID are greater than zero
5621
     * and array of field values is not empty
5622
     */
5623
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
5624
        foreach ($array as $key => &$item) {
5625
            $item = Database::escape_string($item);
5626
            $setString .= $key.' = "'.$item.'", ';
5627
        }
5628
        // Delete last comma
5629
        $setString = substr($setString, 0, strlen($setString) - 2);
5630
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5631
        $sql = "UPDATE $forumAttachmentTable SET $setString WHERE c_id = $courseId AND id = $id";
5632
        $result = Database::query($sql);
5633
        if ($result !== false) {
5634
            $affectedRows = Database::affected_rows($result);
5635 View Code Duplication
            if ($affectedRows > 0) {
5636
                /*
5637
                 * If exist in $_SESSION variable, then delete them from it
5638
                 * because they would be deprecated
5639
                 */
5640
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
5641
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
5642
                }
5643
            }
5644
5645
            return $affectedRows;
5646
        }
5647
    }
5648
5649
    return 0;
5650
}
5651
5652
/**
5653
 * Return a table where the attachments will be set
5654
 * @param int $postId Forum Post ID
5655
 *
5656
 * @return string The Forum Attachments Ajax Table
5657
 */
5658
function getAttachmentsAjaxTable($postId = 0)
5659
{
5660
    // Init variables
5661
    $postId = intval($postId);
5662
    $courseId = api_get_course_int_id();
5663
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
5664
    $fileDataContent = '';
5665
    // Update comment to show if form did not pass validation
5666
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
5667
        // 'file_ids is the name from forum attachment ajax form
5668
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
5669
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
5670
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
5671
            ) {
5672
                // If exist forum attachment then update into $_SESSION data
5673
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
5674
            }
5675
        }
5676
    }
5677
5678
    // Get data to fill into attachment files table
5679
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
5680
        is_array($_SESSION['forum']['upload_file'][$courseId])
5681
    ) {
5682
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
5683
        foreach ($uploadedFiles as $k => $uploadedFile) {
5684
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
5685
                // Buil html table including an input with attachmentID
5686
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
5687
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
5688
                    $uploadedFile['delete'].'</td>'.
5689
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
5690
            } else {
5691
                /*
5692
                 * If attachment data is empty, then delete it from $_SESSION
5693
                 * because could generate and empty row into html table
5694
                 */
5695
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
5696
            }
5697
        }
5698
    }
5699
    $style = empty($fileDataContent) ? 'display: none;' : '';
5700
    // Forum attachment Ajax table
5701
    $fileData = '
5702
    <div class="control-group " style="'. $style.'">
5703
        <label class="control-label">'.get_lang('AttachmentList').'</label>
5704
        <div class="controls">
5705
            <table id="attachmentFileList" class="files data_table span10">
5706
                <tr>
5707
                    <th>'.get_lang('FileName').'</th>
5708
                    <th>'.get_lang('Size').'</th>
5709
                    <th>'.get_lang('Status').'</th>
5710
                    <th>'.get_lang('Comment').'</th>
5711
                    <th>'.get_lang('Delete').'</th>
5712
                </tr>
5713
                '.$fileDataContent.'
5714
            </table>
5715
        </div>
5716
    </div>';
5717
5718
    return $fileData;
5719
}
5720
5721
/**
5722
 * Return an array of prepared attachment data to build forum attachment table
5723
 * Also, save this array into $_SESSION to do available the attachment data
5724
 * @param int $forumId
5725
 * @param int $threadId
5726
 * @param int $postId
5727
 * @param int $attachId
5728
 * @param int $courseId
5729
 *
5730
 * @return array
5731
 */
5732
function getAttachedFiles($forumId, $threadId, $postId = 0, $attachId = 0, $courseId = 0)
5733
{
5734
    $forumId = intval($forumId);
5735
    $courseId = intval($courseId);
5736
    $attachId = intval($attachId);
5737
    $postId = intval($postId);
5738
    $threadId = !empty($threadId) ? intval($threadId) : isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : '';
5739
    if (empty($courseId)) {
5740
        // $courseId can be null, use api method
5741
        $courseId = api_get_course_int_id();
5742
    }
5743
    if (empty($forumId)) {
5744
        if (!empty($_REQUEST['forum'])) {
5745
            $forumId = intval($_REQUEST['forum']);
5746
        } else {
5747
            // if forum ID is empty, cannot generate delete url
5748
5749
            return array();
5750
        }
5751
    }
5752
    // Check if exist at least one of them to filter forum attachment select query
5753
    if (empty($postId) && empty($attachId)) {
5754
5755
        return array();
5756
    } elseif (empty($postId)) {
5757
        $filter = "AND iid = $attachId";
5758
    } elseif (empty($attachId)) {
5759
        $filter = "AND post_id = $postId";
5760
    } else {
5761
        $filter = "AND post_id = $postId AND iid = $attachId";
5762
    }
5763
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5764
    $sql = "SELECT iid, comment, filename, path, size
5765
            FROM $forumAttachmentTable
5766
            WHERE c_id = $courseId $filter";
5767
    $result = Database::query($sql);
5768
    $json = array();
5769
    if ($result !== false && Database::num_rows($result) > 0) {
5770
        while ($row = Database::fetch_array($result, 'ASSOC')) {
5771
            // name contains an URL to download attachment file and its filename
5772
            $json['name'] = Display::url(
5773
                api_htmlentities($row['filename']),
5774
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
5775
                array('target'=>'_blank', 'class' => 'attachFilename')
5776
            );
5777
            $json['id'] = $row['iid'];
5778
            $json['comment'] = $row['comment'];
5779
            // Format file size
5780
            $json['size'] = format_file_size($row['size']);
5781
            // Check if $row is consistent
5782
            if (!empty($row) && is_array($row)) {
5783
                // Set result as success and bring delete URL
5784
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded'));
5785
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
5786
                $json['delete'] = Display::url(
5787
                    Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL),
5788
                    $url,
5789
                    array('class' => 'deleteLink')
5790
                );
5791
            } else {
5792
                // If not, set an exclamation result
5793
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
5794
            }
5795
            // Store array data into $_SESSION
5796
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
5797
        }
5798
    }
5799
5800
    return $json;
5801
}
5802
5803
/**
5804
 * Clear forum attachment data stored in $_SESSION,
5805
 * If is not defined post, it will clear all forum attachment data from course
5806
 * @param int $postId -1 : Clear all attachments from course stored in $_SESSION
5807
 *                      0 : Clear attachments from course, except from temporal post "0"
5808
 *                          but without delete them from file system and database
5809
 *                     Other values : Clear attachments from course except specified post
5810
 *                          and delete them from file system and database
5811
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
5812
 *
5813
 * @return array
5814
 */
5815
function clearAttachedFiles($postId = null, $courseId = null) {
5816
    // Init variables
5817
    $courseId = intval($courseId);
5818
    $postId = intval($postId);
5819
    $array = array();
5820
    if (empty($courseId)) {
5821
        // $courseId can be null, use api method
5822
        $courseId = api_get_course_int_id();
5823
    }
5824
    if ($postId === -1) {
5825
        // If post ID is -1 then delete course's attachment data from $_SESSION
5826 View Code Duplication
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
5827
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
5828
            unset($_SESSION['forum']['upload_file'][$courseId]);
5829
        }
5830
    } else {
5831
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
5832
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
5833
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
5834
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
5835
                if (!in_array($attachId, $attachIds)) {
5836
                    // If attach ID is not into specified post, delete attachment
5837
                    // Save deleted attachment ID
5838
                    $array[] = $attachId;
5839
                    if ($postId !== 0) {
5840
                        // Post 0 is temporal, delete them from file system and DB
5841
                        delete_attachment(0, $attachId, false);
5842
                    }
5843
                    // Delete attachment data from $_SESSION
5844
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
5845
                }
5846
            }
5847
        }
5848
    }
5849
5850
    return $array;
5851
}
5852
5853
/**
5854
 * Returns an array of forum attachment ids into a course and forum post
5855
 * @param int $postId
5856
 * @param int $courseId
5857
 *
5858
 * @return array
5859
 */
5860
function getAttachmentIdsByPostId($postId, $courseId = null)
5861
{
5862
5863
    $array = array();
5864
    $courseId = intval($courseId);
5865
    $postId = intval($postId);
5866
    if (empty($courseId)) {
5867
        // $courseId can be null, use api method
5868
        $courseId = api_get_course_int_id();
5869
    }
5870
    if ($courseId > 0) {
5871
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5872
        $sql = "SELECT id FROM $forumAttachmentTable
5873
                WHERE c_id = $courseId AND post_id = $postId";
5874
        $result = Database::query($sql);
5875
        if ($result !== false && Database::num_rows($result) > 0) {
5876
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5877
                $array[] = $row['id'];
5878
            }
5879
        }
5880
    }
5881
    return $array;
5882
}
5883
5884
/**
5885
 * Check if the forum category exists looking for its title
5886
 * @param string $title The forum category title
5887
 * @param int $courseId The course ID
5888
 * @param int $sessionId Optional. The session ID
5889
 * @return boolean
5890
 */
5891
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
5892
{
5893
    $sessionId = intval($sessionId);
5894
5895
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
5896
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
5897
5898
    $fakeFrom = "$forumCategoryTable fc
5899
        INNER JOIN $itemProperty ip ";
5900
5901
    if ($sessionId === 0) {
5902
        $fakeFrom .= "
5903
            ON (
5904
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND (fc.session_id = ip.session_id OR ip.session_id IS NULL)
5905
            )
5906
        ";
5907
    } else {
5908
        $fakeFrom .= "
5909
            ON (
5910
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
5911
            )
5912
        ";
5913
    }
5914
5915
    $resultData = Database::select(
5916
        'fc.*',
5917
        $fakeFrom,
5918
        [
5919
            'where' => [
5920
                'ip.visibility != ? AND ' => 2,
5921
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
5922
                'fc.session_id = ? AND ' => $sessionId,
5923
                'fc.cat_title = ? AND ' => $title,
5924
                'fc.c_id = ?' => intval($courseId)
5925
            ]
5926
        ],
5927
        'first'
5928
    );
5929
5930
    if (empty($resultData)) {
5931
        return false;
5932
    }
5933
5934
    return $resultData;
5935
}
5936
5937
/**
5938
 * @param array $current_forum
5939
 * @param array $row
5940
 *
5941
 * @return string
5942
 */
5943
function getPostStatus($current_forum, $row, $addWrapper = true)
5944
{
5945
    $statusIcon = '';
5946
    if ($current_forum['moderated']) {
5947
        if ($addWrapper) {
5948
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
5949
        }
5950
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
5951
5952
        $addUrl = false;
5953
        $showStatus = false;
5954
        if (api_is_allowed_to_edit(false, true)) {
5955
            $addUrl = true;
5956
        } else {
5957
            if ($row['user_id'] == api_get_user_id()) {
5958
                $showStatus = true;
5959
            }
5960
        }
5961
5962
        $label = '';
5963
        $icon = '';
5964
        $buttonType = '';
5965
        switch ($row['status']) {
5966
            case CForumPost::STATUS_VALIDATED:
5967
                $label = get_lang('Validated');
5968
                $icon = 'check-circle';
5969
                $buttonType = 'success';
5970
                break;
5971
            case CForumPost::STATUS_WAITING_MODERATION:
5972
                $label = get_lang('WaitingModeration');
5973
                $icon = 'warning';
5974
                $buttonType = 'warning';
5975
                break;
5976
            case CForumPost::STATUS_REJECTED:
5977
                $label = get_lang('Rejected');
5978
                $icon = 'minus-circle';
5979
                $buttonType = 'danger';
5980
                break;
5981
        }
5982
5983
        if ($addUrl) {
5984
            $statusIcon .= Display::toolbarButton(
5985
                $label.'&nbsp;',
5986
                'javascript:void(0)',
5987
                $icon,
5988
                $buttonType,
5989
                ['class' => 'change_post_status']
5990
            );
5991
        } else {
5992
            if ($showStatus) {
5993
                $statusIcon .= Display::label(
5994
                    Display::returnFontAwesomeIcon($icon).$label,
5995
                    $buttonType
5996
                );
5997
            }
5998
        }
5999
6000
        if ($addWrapper) {
6001
            $statusIcon .= '</span>';
6002
        }
6003
    }
6004
6005
    return $statusIcon;
6006
}
6007
6008
/**
6009
 * @param array $forumInfo
6010
 * @param int $threadId
6011
 * @param int $status
6012
 * @return mixed
6013
 */
6014
function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
6015
{
6016
    $em = Database::getManager();
6017
    $criteria = Criteria::create();
6018
    $criteria
6019
        ->where(Criteria::expr()->eq('status', $status))
6020
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
6021
        ->andWhere(Criteria::expr()->eq('visible', 1))
6022
    ;
6023
6024
    if (!empty($threadId)) {
6025
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6026
    }
6027
6028
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6029
    $qb->select('count(p.iid)')
6030
        ->addCriteria($criteria);
6031
6032
    return $qb->getQuery()->getSingleScalarResult();
6033
}
6034
6035
/**
6036
 * @param array $forum
6037
 * @param array $post
6038
 *
6039
 * @return bool
6040
 */
6041
function postIsEditableByStudent($forum, $post)
6042
{
6043
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6044
        return true;
6045
    }
6046
6047
    if ($forum['moderated'] == 1) {
6048
        if (is_null($post['status'])) {
6049
            return true;
6050
        } else {
6051
            return in_array($post['status'],
6052
                [
6053
                    CForumPost::STATUS_WAITING_MODERATION,
6054
                    CForumPost::STATUS_REJECTED,
6055
                ]
6056
            );
6057
        }
6058
    } else {
6059
        return true;
6060
    }
6061
}
6062
6063