Passed
Push — master ( 2f567c...15378b )
by Julito
12:45
created

set_notification()   B

Complexity

Conditions 10
Paths 28

Size

Total Lines 54
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 34
nc 28
nop 5
dl 0
loc 54
rs 7.6666
c 1
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 Chamilo\CourseBundle\Entity\CForumPost;
5
use Chamilo\CourseBundle\Entity\CForumThread;
6
use Chamilo\UserBundle\Entity\User;
7
use ChamiloSession as Session;
8
use Doctrine\Common\Collections\Criteria;
9
10
/**
11
 * These files are a complete rework of the forum. The database structure is
12
 * based on phpBB but all the code is rewritten. A lot of new functionalities
13
 * are added:
14
 * - forum categories and forums can be sorted up or down, locked or made invisible
15
 * - consistent and integrated forum administration
16
 * - forum options:     are students allowed to edit their post?
17
 *                         moderation of posts (approval)
18
 *                         reply only forums (students cannot create new threads)
19
 *                         multiple forums per group
20
 * - sticky messages
21
 * - new view option: nested view
22
 * - quoting a message.
23
 *
24
 * @package chamilo.forum
25
 *
26
 * @todo convert into a class
27
 */
28
define('FORUM_NEW_POST', 0);
29
getNotificationsPerUser();
30
31
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
32
$htmlHeadXtra[] = '<script>
33
34
function check_unzip() {
35
    if (document.upload.unzip.checked){
36
        document.upload.if_exists[0].disabled=true;
37
        document.upload.if_exists[1].checked=true;
38
        document.upload.if_exists[2].disabled=true;
39
    } else {
40
        document.upload.if_exists[0].checked=true;
41
        document.upload.if_exists[0].disabled=false;
42
        document.upload.if_exists[2].disabled=false;
43
    }
44
}
45
function setFocus() {
46
    $("#title_file").focus();
47
}
48
</script>';
49
// The next javascript script is to manage ajax upload file
50
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
51
52
// Recover Thread ID, will be used to generate delete attachment URL to do ajax
53
$threadId = isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : 0;
54
$forumId = isset($_REQUEST['forum']) ? intval($_REQUEST['forum']) : 0;
55
56
$ajaxUrl = api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq();
57
// The next javascript script is to delete file by ajax
58
$htmlHeadXtra[] = '<script>
59
$(function () {
60
    $(document).on("click", ".deleteLink", function(e) {
61
        e.preventDefault();
62
        e.stopPropagation();
63
        var l = $(this);
64
        var id = l.closest("tr").attr("id");
65
        var filename = l.closest("tr").find(".attachFilename").html();
66
        if (confirm("'.get_lang('AreYouSureToDeleteJS').'", filename)) {
67
            $.ajax({
68
                type: "POST",
69
                url: "'.$ajaxUrl.'&a=delete_file&attachId=" + id +"&thread='.$threadId.'&forum='.$forumId.'",
70
                dataType: "json",
71
                success: function(data) {
72
                    if (data.error == false) {
73
                        l.closest("tr").remove();
74
                        if ($(".files td").length < 1) {
75
                            $(".files").closest(".control-group").hide();
76
                        }
77
                    }
78
                }
79
            })
80
        }
81
    });
82
});
83
</script>';
84
85
/**
86
 * This function handles all the forum and forum categories actions. This is a wrapper for the
87
 * forum and forum categories. All this code code could go into the section where this function is
88
 * called but this make the code there cleaner.
89
 *
90
 * @param int $lp_id Learning path Id
91
 *
92
 * @author Patrick Cool <[email protected]>, Ghent University
93
 * @author Juan Carlos Raña Trabado (return to lp_id)
94
 *
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']) ? (int) $_GET['id'] : 0;
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
    $content = '';
112
113
    // Adding a forum category
114
    if (($action_forum_cat === 'add' && $get_content === 'forumcategory') || $post_submit_cat) {
115
        $content = show_add_forumcategory_form([], $lp_id); //$lp_id when is called from learning path
116
    }
117
118
    // Adding a forum
119
    if ((($action_forum_cat === 'add' || $action_forum_cat === 'edit') && $get_content === 'forum') ||
120
        $post_submit_forum
121
    ) {
122
        $inputvalues = [];
123
        if ($action_forum_cat === 'edit' && $get_id || $post_submit_forum) {
124
            $inputvalues = get_forums($get_id);
125
        }
126
        $content = show_add_forum_form($inputvalues, $lp_id);
127
    }
128
129
    // Edit a forum category
130
    if (($action_forum_cat === 'edit' && $get_content === 'forumcategory') ||
131
    (isset($_POST['SubmitEditForumCategory'])) ? true : false
132
    ) {
133
        $forum_category = get_forum_categories($get_id);
134
        $content = show_edit_forumcategory_form($forum_category);
135
    }
136
137
    // Delete a forum category
138
    if ($action_forum_cat === 'delete') {
139
        $list_threads = get_threads($get_id);
140
        for ($i = 0; $i < count($list_threads); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
141
            deleteForumCategoryThread('thread', $list_threads[$i]['thread_id']);
142
            $link_info = GradebookUtils::isResourceInCourseGradebook(
143
                api_get_course_id(),
144
                5,
145
                $list_threads[$i]['thread_id'],
146
                api_get_session_id()
147
            );
148
            if ($link_info !== false) {
149
                GradebookUtils::remove_resource_from_course_gradebook($link_info['id']);
150
            }
151
        }
152
        deleteForumCategoryThread($get_content, $get_id);
153
    }
154
155
    // Change visibility of a forum or a forum category.
156
    if ($action_forum_cat === 'invisible' || $action_forum_cat === 'visible') {
157
        $return_message = change_visibility($get_content, $get_id, $action_forum_cat);
158
        Display::addFlash(
159
            Display::return_message($return_message, 'confirmation', false)
160
        );
161
    }
162
    // Change lock status of a forum or a forum category.
163
    if ($action_forum_cat === 'lock' || $action_forum_cat === 'unlock') {
164
        $return_message = change_lock_status($get_content, $get_id, $action_forum_cat);
165
        Display::addFlash(
166
            Display::return_message($return_message, 'confirmation', false)
167
        );
168
    }
169
    // Move a forum or a forum category.
170
    if ($action_forum_cat === 'move' && isset($_GET['direction'])) {
171
        $return_message = move_up_down($get_content, $_GET['direction'], $get_id);
172
        Display::addFlash(
173
            Display::return_message($return_message, 'confirmation', false)
174
        );
175
    }
176
177
    return $content;
178
}
179
180
/**
181
 * This function displays the form that is used to add a forum category.
182
 *
183
 * @param array $inputvalues (deprecated, set to null when calling)
184
 * @param int   $lp_id       Learning path ID
185
 *
186
 * @return string
187
 *
188
 * @author Patrick Cool <[email protected]>, Ghent University
189
 * @author Juan Carlos Raña Trabado (return to lp_id)
190
 *
191
 * @version may 2011, Chamilo 1.8.8
192
 */
193
function show_add_forumcategory_form($inputvalues = [], $lp_id)
194
{
195
    $form = new FormValidator(
196
        'forumcategory',
197
        'post',
198
        'index.php?'.api_get_cidreq()
199
    );
200
    // hidden field if from learning path
201
    $form->addElement('hidden', 'lp_id', $lp_id);
202
    // Setting the form elements.
203
    $form->addElement('header', get_lang('AddForumCategory'));
204
    $form->addElement('text', 'forum_category_title', get_lang('Title'), ['autofocus']);
205
    $form->addElement(
206
        'html_editor',
207
        'forum_category_comment',
208
        get_lang('Description'),
209
        null,
210
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
211
    );
212
213
    $extraField = new ExtraField('forum_category');
214
    $returnParams = $extraField->addElements(
215
        $form,
216
        null,
217
        [], //exclude
218
        false, // filter
219
        false, // tag as select
220
        [], //show only fields
221
        [], // order fields
222
        [] // extra data
223
    );
224
225
    $form->addButtonCreate(get_lang('CreateCategory'), 'SubmitForumCategory');
226
227
    // Setting the rules.
228
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
229
230
    // The validation or display
231
    if ($form->validate()) {
232
        $check = Security::check_token('post');
233
        if ($check) {
234
            $values = $form->exportValues();
235
            store_forumcategory($values);
236
        }
237
        Security::clear_token();
238
    } else {
239
        $token = Security::get_token();
240
        $form->addElement('hidden', 'sec_token');
241
        $form->setConstants(['sec_token' => $token]);
242
243
        return $form->returnForm();
244
    }
245
}
246
247
/**
248
 * This function displays the form that is used to add a forum category.
249
 *
250
 * @param array $inputvalues
251
 * @param int   $lp_id
252
 *
253
 * @author Patrick Cool <[email protected]>, Ghent University
254
 * @author Juan Carlos Raña Trabado (return to lp_id)
255
 *
256
 * @version may 2011, Chamilo 1.8.8
257
 */
258
function show_add_forum_form($inputvalues = [], $lp_id)
259
{
260
    $_course = api_get_course_info();
261
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq());
262
263
    // The header for the form
264
    $form_title = get_lang('AddForum');
265
    if (!empty($inputvalues)) {
266
        $form_title = get_lang('EditForum');
267
    }
268
269
    $form->addHeader($form_title);
270
271
    // We have a hidden field if we are editing.
272
    if (!empty($inputvalues) && is_array($inputvalues)) {
273
        $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
274
        $form->addElement('hidden', 'forum_id', $my_forum_id);
275
    }
276
    $lp_id = (int) $lp_id;
277
278
    // hidden field if from learning path
279
    $form->addElement('hidden', 'lp_id', $lp_id);
280
281
    // The title of the forum
282
    $form->addElement('text', 'forum_title', get_lang('Title'), ['autofocus']);
283
284
    // The comment of the forum.
285
    $form->addElement(
286
        'html_editor',
287
        'forum_comment',
288
        get_lang('Description'),
289
        null,
290
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
291
    );
292
293
    // Dropdown list: Forum categories
294
    $forum_categories = get_forum_categories();
295
    foreach ($forum_categories as $key => $value) {
296
        $forum_categories_titles[$value['cat_id']] = $value['cat_title'];
297
    }
298
    $form->addElement(
299
        'select',
300
        'forum_category',
301
        get_lang('InForumCategory'),
302
        $forum_categories_titles
303
    );
304
    $form->applyFilter('forum_category', 'html_filter');
305
306
    if ($_course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) {
307
        // This is for horizontal
308
        $group = [];
309
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
310
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
311
        $form->addGroup($group, 'allow_anonymous_group', get_lang('AllowAnonymousPosts'));
312
    }
313
314
    $form->addButtonAdvancedSettings('advanced_params');
315
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
316
317
    $form->addDateTimePicker(
318
        'start_time',
319
        [get_lang('ForumStartDate'), get_lang('ForumStartDateComment')],
320
        ['id' => 'start_time']
321
    );
322
323
    $form->addDateTimePicker(
324
        'end_time',
325
        [get_lang('ForumEndDate'), get_lang('ForumEndDateComment')],
326
        ['id' => 'end_time']
327
    );
328
329
    $form->addRule(
330
        ['start_time', 'end_time'],
331
        get_lang('StartDateMustBeBeforeTheEndDate'),
332
        'compare_datetime_text',
333
        '< allow_empty'
334
    );
335
336
    $group = [];
337
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('Yes'), 1);
338
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('No'), 0);
339
    $form->addGroup($group, 'moderated', get_lang('ModeratedForum'));
340
341
    $group = [];
342
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
343
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
344
    $form->addGroup($group, 'students_can_edit_group', get_lang('StudentsCanEdit'));
345
346
    $group = [];
347
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
348
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
349
350
    $group = [];
351
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
352
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
353
354
    $group = [];
355
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
356
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
357
    $form->addGroup($group, 'allow_new_threads_group', get_lang('AllowNewThreads'));
358
359
    $group = [];
360
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
361
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
362
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
363
    $form->addGroup($group, 'default_view_type_group', get_lang('DefaultViewType'));
364
365
    // Drop down list: Groups
366
    $groups = GroupManager::get_group_list();
367
    $groups_titles[0] = get_lang('NotAGroupForum');
368
    foreach ($groups as $key => $value) {
369
        $groups_titles[$value['id']] = $value['name'];
370
    }
371
    $form->addElement('select', 'group_forum', get_lang('ForGroup'), $groups_titles);
372
373
    // Public or private group forum
374
    $group = [];
375
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public'), 'public');
376
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private'), 'private');
377
    $form->addGroup($group, 'public_private_group_forum_group', get_lang('PublicPrivateGroupForum'));
378
379
    // Forum image
380
    $form->addProgress();
381
    if (!empty($inputvalues['forum_image'])) {
382
        $baseImagePath = api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
383
        $image_path = api_get_path(WEB_COURSE_PATH).$baseImagePath;
384
        $sysImagePath = api_get_path(SYS_COURSE_PATH).$baseImagePath;
385
386
        if (file_exists($sysImagePath)) {
387
            $show_preview_image = Display::img(
388
                $image_path,
389
                null,
390
                ['class' => 'img-responsive']
391
            );
392
            $form->addElement('label', get_lang('PreviewImage'), $show_preview_image);
393
            $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
394
        }
395
    }
396
    $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
397
    $form->addElement('file', 'picture', ($forum_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
398
    $form->addRule(
399
        'picture',
400
        get_lang('OnlyImagesAllowed'),
401
        'filetype',
402
        ['jpg', 'jpeg', 'png', 'gif']
403
    );
404
405
    //$forumId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
406
    //$skillList = Skill::addSkillsToForm($form, ITEM_TYPE_FORUM, $forumId);
407
408
    $form->addElement('html', '</div>');
409
410
    // The OK button
411
    if (isset($_GET['id']) && $_GET['action'] == 'edit') {
412
        $form->addButtonUpdate(get_lang('ModifyForum'), 'SubmitForum');
413
    } else {
414
        $form->addButtonCreate(get_lang('CreateForum'), 'SubmitForum');
415
    }
416
417
    // setting the rules
418
    $form->addRule('forum_title', get_lang('ThisFieldIsRequired'), 'required');
419
    $form->addRule('forum_category', get_lang('ThisFieldIsRequired'), 'required');
420
421
    $defaultSettingAllowNewThreads = api_get_default_tool_setting('forum', 'allow_new_threads', 0);
422
423
    // Settings the defaults
424
    if (empty($inputvalues) || !is_array($inputvalues)) {
425
        $defaults['moderated']['moderated'] = 0;
426
        $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
427
        $defaults['students_can_edit_group']['students_can_edit'] = 0;
428
        $defaults['approval_direct_group']['approval_direct'] = 0;
429
        $defaults['allow_attachments_group']['allow_attachments'] = 1;
430
        $defaults['allow_new_threads_group']['allow_new_threads'] = $defaultSettingAllowNewThreads;
431
        $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
432
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
433
        if (isset($_GET['forumcategory'])) {
434
            $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
435
        }
436
    } else {
437
        // the default values when editing = the data in the table
438
        $defaults['forum_id'] = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
439
        $defaults['forum_title'] = prepare4display(isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null);
440
        $defaults['forum_comment'] = prepare4display(isset($inputvalues['forum_comment']) ? $inputvalues['forum_comment'] : null);
441
        $defaults['start_time'] = isset($inputvalues['start_time']) ? api_get_local_time($inputvalues['start_time']) : null;
442
        $defaults['end_time'] = isset($inputvalues['end_time']) ? api_get_local_time($inputvalues['end_time']) : null;
443
        $defaults['moderated']['moderated'] = isset($inputvalues['moderated']) ? $inputvalues['moderated'] : 0;
444
        $defaults['forum_category'] = isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
445
        $defaults['allow_anonymous_group']['allow_anonymous'] = isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] : null;
446
        $defaults['students_can_edit_group']['students_can_edit'] = isset($inputvalues['allow_edit']) ? $inputvalues['allow_edit'] : null;
447
        $defaults['approval_direct_group']['approval_direct'] = isset($inputvalues['approval_direct_post']) ? $inputvalues['approval_direct_post'] : null;
448
        $defaults['allow_attachments_group']['allow_attachments'] = isset($inputvalues['allow_attachments']) ? $inputvalues['allow_attachments'] : null;
449
        $defaults['allow_new_threads_group']['allow_new_threads'] = isset($inputvalues['allow_new_threads']) ? $inputvalues['allow_new_threads'] : $defaultSettingAllowNewThreads;
450
        $defaults['default_view_type_group']['default_view_type'] = isset($inputvalues['default_view']) ? $inputvalues['default_view'] : null;
451
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = isset($inputvalues['forum_group_public_private']) ? $inputvalues['forum_group_public_private'] : null;
452
        $defaults['group_forum'] = isset($inputvalues['forum_of_group']) ? $inputvalues['forum_of_group'] : null;
453
    }
454
455
    $form->setDefaults($defaults);
456
    // Validation or display
457
    if ($form->validate()) {
458
        $check = Security::check_token('post');
459
        if ($check) {
460
            $values = $form->getSubmitValues();
461
            $forumId = store_forum($values, '', true);
462
            if ($forumId) {
463
                // Skill::saveSkills($form, ITEM_TYPE_FORUM, $forumId);
464
                if (isset($values['forum_id'])) {
465
                    Display::addFlash(Display::return_message(get_lang('ForumEdited'), 'confirmation'));
466
                } else {
467
                    Display::addFlash(Display::return_message(get_lang('ForumAdded'), 'confirmation'));
468
                }
469
            }
470
        }
471
        Security::clear_token();
472
    } else {
473
        $token = Security::get_token();
474
        $form->addElement('hidden', 'sec_token');
475
        $form->setConstants(['sec_token' => $token]);
476
477
        return $form->returnForm();
478
    }
479
}
480
481
/**
482
 * This function deletes the forum image if exists.
483
 *
484
 * @param int forum id
485
 *
486
 * @return bool true if success
487
 *
488
 * @author Julio Montoya <[email protected]>
489
 *
490
 * @version february 2006, dokeos 1.8
491
 */
492
function delete_forum_image($forum_id)
493
{
494
    $table_forums = Database::get_course_table(TABLE_FORUM);
495
    $course_id = api_get_course_int_id();
496
    $forum_id = intval($forum_id);
497
498
    $sql = "SELECT forum_image FROM $table_forums
499
            WHERE forum_id = $forum_id AND c_id = $course_id";
500
    $result = Database::query($sql);
501
    $row = Database::fetch_array($result);
502
    if ($row['forum_image'] != '') {
503
        $file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
504
        if (file_exists($file)) {
505
            unlink($file);
506
        }
507
508
        return true;
509
    } else {
510
        return false;
511
    }
512
}
513
514
/**
515
 * This function displays the form that is used to edit a forum category.
516
 *
517
 * @param array
518
 *
519
 * @return string
520
 *
521
 * @author Patrick Cool <[email protected]>, Ghent University
522
 *
523
 * @version february 2006, dokeos 1.8
524
 */
525
function show_edit_forumcategory_form($inputvalues = [])
526
{
527
    $categoryId = $inputvalues['cat_id'];
528
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq().'&id='.$categoryId);
529
530
    // Setting the form elements.
531
    $form->addElement('header', '', get_lang('EditForumCategory'));
532
    $form->addElement('hidden', 'forum_category_id');
533
    $form->addElement('text', 'forum_category_title', get_lang('Title'));
534
535
    $form->addElement(
536
        'html_editor',
537
        'forum_category_comment',
538
        get_lang('Comment'),
539
        null,
540
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
541
    );
542
543
    $extraField = new ExtraField('forum_category');
544
    $returnParams = $extraField->addElements(
545
        $form,
546
        $categoryId,
547
        [], //exclude
548
        false, // filter
549
        false, // tag as select
550
        [], //show only fields
551
        [], // order fields
552
        [] // extra data
553
    );
554
555
    $form->addButtonUpdate(get_lang('ModifyCategory'), 'SubmitEditForumCategory');
556
557
    // Setting the default values.
558
    $defaultvalues['forum_category_id'] = $inputvalues['cat_id'];
559
    $defaultvalues['forum_category_title'] = $inputvalues['cat_title'];
560
    $defaultvalues['forum_category_comment'] = $inputvalues['cat_comment'];
561
    $form->setDefaults($defaultvalues);
562
563
    // Setting the rules.
564
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
565
566
    // Validation or display
567
    if ($form->validate()) {
568
        $check = Security::check_token('post');
569
        if ($check) {
570
            $values = $form->exportValues();
571
            store_forumcategory($values);
572
        }
573
        Security::clear_token();
574
    } else {
575
        $token = Security::get_token();
576
        $form->addElement('hidden', 'sec_token');
577
        $form->setConstants(['sec_token' => $token]);
578
579
        return $form->returnForm();
580
    }
581
}
582
583
/**
584
 * This function stores the forum category in the database.
585
 * The new category is added to the end.
586
 *
587
 * @param array $values
588
 * @param array $courseInfo
589
 * @param bool  $showMessage
590
 *
591
 * @author Patrick Cool <[email protected]>, Ghent University
592
 *
593
 * @version february 2006, dokeos 1.8
594
 */
595
function store_forumcategory($values, $courseInfo = [], $showMessage = true)
596
{
597
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
598
    $course_id = $courseInfo['real_id'];
599
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
600
601
    // Find the max cat_order. The new forum category is added at the end => max cat_order + &
602
    $sql = "SELECT MAX(cat_order) as sort_max
603
            FROM $table_categories
604
            WHERE c_id = $course_id";
605
    $result = Database::query($sql);
606
    $row = Database::fetch_array($result);
607
    $new_max = $row['sort_max'] + 1;
608
    $session_id = api_get_session_id();
609
    $clean_cat_title = $values['forum_category_title'];
610
    $last_id = null;
611
612
    if (isset($values['forum_category_id'])) {
613
        // Storing after edition.
614
        $params = [
615
            'cat_title' => $clean_cat_title,
616
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
617
        ];
618
619
        Database::update(
620
            $table_categories,
621
            $params,
622
            [
623
                'c_id = ? AND cat_id = ?' => [
624
                    $course_id,
625
                    $values['forum_category_id'],
626
                ],
627
            ]
628
        );
629
630
        api_item_property_update(
631
            $courseInfo,
632
            TOOL_FORUM_CATEGORY,
633
            $values['forum_category_id'],
634
            'ForumCategoryUpdated',
635
            api_get_user_id()
636
        );
637
        $return_message = get_lang('ForumCategoryEdited');
638
639
        $logInfo = [
640
            'tool' => TOOL_FORUM,
641
            'tool_id' => 0,
642
            'tool_id_detail' => 0,
643
            'action' => 'update-forumcategory',
644
            'action_details' => 'forumcategory',
645
            'info' => $clean_cat_title,
646
        ];
647
        Event::registerLog($logInfo);
648
649
        $values['item_id'] = $values['forum_category_id'];
650
    } else {
651
        $params = [
652
            'c_id' => $course_id,
653
            'cat_title' => $clean_cat_title,
654
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
655
            'cat_order' => $new_max,
656
            'session_id' => $session_id,
657
            'locked' => 0,
658
            'cat_id' => 0,
659
        ];
660
        $last_id = Database::insert($table_categories, $params);
661
662
        if ($last_id > 0) {
663
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
664
            Database::query($sql);
665
666
            api_item_property_update(
667
                $courseInfo,
668
                TOOL_FORUM_CATEGORY,
669
                $last_id,
670
                'ForumCategoryAdded',
671
                api_get_user_id()
672
            );
673
            api_set_default_visibility(
674
                $last_id,
675
                TOOL_FORUM_CATEGORY,
676
                0,
677
                $courseInfo
678
            );
679
        }
680
        $return_message = get_lang('ForumCategoryAdded');
681
682
        $logInfo = [
683
            'tool' => TOOL_FORUM,
684
            'tool_id' => 0,
685
            'tool_id_detail' => 0,
686
            'action' => 'new-forumcategory',
687
            'action_details' => 'forumcategory',
688
            'info' => $clean_cat_title,
689
        ];
690
        Event::registerLog($logInfo);
691
692
        $values['item_id'] = $last_id;
693
    }
694
695
    $extraFieldValue = new ExtraFieldValue('forum_category');
696
    $extraFieldValue->saveFieldValues($values);
697
698
    if ($showMessage) {
699
        Display::addFlash(Display::return_message($return_message, 'confirmation'));
700
    }
701
702
    return $last_id;
703
}
704
705
/**
706
 * This function stores the forum in the database. The new forum is added to the end.
707
 *
708
 * @param array $values
709
 * @param array $courseInfo
710
 * @param bool  $returnId
711
 *
712
 * @return string language variable
713
 *
714
 * @author Patrick Cool <[email protected]>, Ghent University
715
 *
716
 * @version february 2006, dokeos 1.8
717
 */
718
function store_forum($values, $courseInfo = [], $returnId = false)
719
{
720
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
721
    $courseId = $courseInfo['real_id'];
722
    $session_id = api_get_session_id();
723
    $group_id = api_get_group_id();
724
    if (isset($values['group_id']) && !empty($values['group_id'])) {
725
        $group_id = $values['group_id'];
726
    }
727
    $groupInfo = [];
728
    if (!empty($group_id)) {
729
        $groupInfo = GroupManager::get_group_properties($group_id);
730
    }
731
732
    $table_forums = Database::get_course_table(TABLE_FORUM);
733
734
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
735
    if (is_null($values['forum_category'])) {
736
        $new_max = null;
737
    } else {
738
        $sql = "SELECT MAX(forum_order) as sort_max
739
                FROM $table_forums
740
                WHERE
741
                    c_id = $courseId AND
742
                    forum_category='".Database::escape_string($values['forum_category'])."'";
743
        $result = Database::query($sql);
744
        $row = Database::fetch_array($result);
745
        $new_max = $row['sort_max'] + 1;
746
    }
747
748
    // Forum images
749
    $has_attachment = false;
750
    $image_moved = true;
751
    if (!empty($_FILES['picture']['name'])) {
752
        $upload_ok = process_uploaded_file($_FILES['picture']);
753
        $has_attachment = true;
754
    }
755
756
    // Remove existing picture if it was requested.
757
    if (!empty($_POST['remove_picture'])) {
758
        delete_forum_image($values['forum_id']);
759
    }
760
761
    $new_file_name = '';
762
    if (isset($upload_ok)) {
763
        if ($has_attachment) {
764
            $course_dir = $courseInfo['path'].'/upload/forum/images';
765
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
766
            $updir = $sys_course_path.$course_dir;
767
            // Try to add an extension to the file if it hasn't one.
768
            $new_file_name = add_ext_on_mime(
769
                Database::escape_string($_FILES['picture']['name']),
770
                $_FILES['picture']['type']
771
            );
772
            if (!filter_extension($new_file_name)) {
773
                //Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
774
                $image_moved = false;
775
            } else {
776
                $file_extension = explode('.', $_FILES['picture']['name']);
777
                $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
778
                $new_file_name = uniqid('').'.'.$file_extension;
779
                $new_path = $updir.'/'.$new_file_name;
780
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
781
                // Storing the attachments if any
782
                if ($result) {
783
                    $image_moved = true;
784
                }
785
            }
786
        }
787
    }
788
789
    if (isset($values['forum_id'])) {
790
        // Storing after edition.
791
        $params = [
792
            'forum_title' => $values['forum_title'],
793
            'forum_comment' => isset($values['forum_comment']) ? $values['forum_comment'] : null,
794
            'forum_category' => isset($values['forum_category']) ? $values['forum_category'] : null,
795
            'allow_anonymous' => isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
796
            'allow_edit' => isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
797
            'approval_direct_post' => isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
798
            'allow_attachments' => isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
799
            'allow_new_threads' => isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
800
            'default_view' => isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
801
            'forum_of_group' => isset($values['group_forum']) ? $values['group_forum'] : null,
802
            '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,
803
            'moderated' => $values['moderated']['moderated'],
804
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
805
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
806
            'session_id' => $session_id,
807
            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0,
808
        ];
809
810
        if (isset($upload_ok)) {
811
            if ($has_attachment) {
812
                $params['forum_image'] = $new_file_name;
813
            }
814
        }
815
816
        if (isset($values['remove_picture']) && $values['remove_picture'] == 1) {
817
            $params['forum_image'] = '';
818
            delete_forum_image($values['forum_id']);
819
        }
820
821
        // Move groups from one group to another
822
        if (isset($values['group_forum'])) {
823
            $forumData = get_forums($values['forum_id']);
824
            $currentGroupId = $forumData['forum_of_group'];
825
            if ($currentGroupId != $values['group_forum']) {
826
                $threads = get_threads($values['forum_id']);
827
                $toGroupId = 'NULL';
828
                if (!empty($values['group_forum'])) {
829
                    $toGroupId = $values['group_forum'];
830
                }
831
                $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
832
                foreach ($threads as $thread) {
833
                    $sql = "UPDATE $tableItemProperty 
834
                            SET to_group_id = $toGroupId
835
                            WHERE 
836
                                tool = '".TOOL_FORUM_THREAD."' AND
837
                                ref = ".$thread['thread_id']." AND
838
                                c_id = ".$courseId;
839
                    Database::query($sql);
840
841
                    $posts = getPosts(
842
                        $forumData,
843
                        $thread['thread_id']
844
                    );
845
846
                    foreach ($posts as $post) {
847
                        $postId = $post['post_id'];
848
                        $attachMentList = getAllAttachment($postId);
849
                        if (!empty($attachMentList)) {
850
                            foreach ($attachMentList as $attachMent) {
851
                                $sql = "UPDATE $tableItemProperty 
852
                                        SET to_group_id = $toGroupId
853
                                        WHERE 
854
                                            tool = '".TOOL_FORUM_ATTACH."' AND 
855
                                            ref = ".$attachMent['iid']." AND
856
                                            c_id = ".$courseId;
857
                                Database::query($sql);
858
                            }
859
                        }
860
861
                        $sql = "UPDATE $tableItemProperty 
862
                                SET to_group_id = $toGroupId
863
                                WHERE 
864
                                    tool = '".TOOL_FORUM_POST."' AND
865
                                    ref = $postId AND
866
                                    c_id = $courseId";
867
                        Database::query($sql);
868
                    }
869
                }
870
            }
871
        }
872
873
        Database::update(
874
            $table_forums,
875
            $params,
876
            ['c_id = ? AND forum_id = ?' => [$courseId, $values['forum_id']]]
877
        );
878
879
        api_item_property_update(
880
            $courseInfo,
881
            TOOL_FORUM,
882
            Database::escape_string($values['forum_id']),
883
            'ForumUpdated',
884
            api_get_user_id(),
885
            $groupInfo
886
        );
887
888
        $return_message = get_lang('ForumEdited');
889
        $forumId = $values['forum_id'];
890
891
        $logInfo = [
892
            'tool' => TOOL_FORUM,
893
            'tool_id' => $values['forum_id'],
894
            'action' => 'update-forum',
895
            'action_details' => 'forum',
896
            'info' => $values['forum_title'],
897
        ];
898
        Event::registerLog($logInfo);
899
    } else {
900
        if ($image_moved) {
901
            $new_file_name = isset($new_file_name) ? $new_file_name : '';
902
        }
903
        $params = [
904
            'c_id' => $courseId,
905
            'forum_title' => $values['forum_title'],
906
            'forum_image' => $new_file_name,
907
            'forum_comment' => isset($values['forum_comment']) ? $values['forum_comment'] : null,
908
            'forum_category' => isset($values['forum_category']) ? $values['forum_category'] : null,
909
            'allow_anonymous' => isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
910
            'allow_edit' => isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
911
            'approval_direct_post' => isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
912
            'allow_attachments' => isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
913
            'allow_new_threads' => isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
914
            'default_view' => isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
915
            'forum_of_group' => isset($values['group_forum']) ? $values['group_forum'] : null,
916
            '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,
917
            'moderated' => isset($values['moderated']['moderated']) ? (int) $values['moderated']['moderated'] : 0,
918
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
919
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
920
            'forum_order' => isset($new_max) ? $new_max : null,
921
            'session_id' => $session_id,
922
            'lp_id' => isset($values['lp_id']) ? (int) $values['lp_id'] : 0,
923
            'locked' => 0,
924
            'forum_id' => 0,
925
        ];
926
927
        $forumId = Database::insert($table_forums, $params);
928
        if ($forumId > 0) {
929
            $sql = "UPDATE $table_forums SET forum_id = iid WHERE iid = $forumId";
930
            Database::query($sql);
931
            $courseCode = $courseInfo['code'];
932
            $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseCode);
933
934
            $status = STUDENT;
935
            if (!empty($session_id)) {
936
                $status = 0;
937
            }
938
            if ($subscribe === 1) {
939
                $userList = CourseManager::get_user_list_from_course_code(
940
                    $courseCode,
941
                    $session_id,
942
                    null,
943
                    null,
944
                    $status
945
                );
946
                foreach ($userList as $userInfo) {
947
                    set_notification('forum', $forumId, false, $userInfo, $courseInfo);
948
                }
949
            }
950
951
            api_item_property_update(
952
                $courseInfo,
953
                TOOL_FORUM,
954
                $forumId,
955
                'ForumAdded',
956
                api_get_user_id(),
957
                $groupInfo
958
            );
959
960
            api_set_default_visibility(
961
                $forumId,
962
                TOOL_FORUM,
963
                $group_id,
964
                $courseInfo
965
            );
966
967
            $logInfo = [
968
                'tool' => TOOL_FORUM,
969
                'tool_id' => $forumId,
970
                'action' => 'new-forum',
971
                'action_details' => 'forum',
972
                'info' => $values['forum_title'],
973
            ];
974
            Event::registerLog($logInfo);
975
        }
976
        $return_message = get_lang('ForumAdded');
977
    }
978
979
    if ($returnId) {
980
        return $forumId;
981
    }
982
983
    return $return_message;
984
}
985
986
/**
987
 * This function deletes a forum or a forum category
988
 * This function currently does not delete the forums inside the category,
989
 * nor the threads and replies inside these forums.
990
 * For the moment this is the easiest method and it has the advantage that it
991
 * allows to recover fora that were acidently deleted
992
 * when the forum category got deleted.
993
 *
994
 * @param $content = what we are deleting (a forum or a forum category)
0 ignored issues
show
Documentation Bug introduced by
The doc comment = at position 0 could not be parsed: Unknown type name '=' at position 0 in =.
Loading history...
995
 * @param $id the id of the forum category that has to be deleted
996
 *
997
 * @todo write the code for the cascading deletion of the forums inside a
998
 * forum category and also the threads and replies inside these forums
999
 * @todo config setting for recovery or not
1000
 * (see also the documents tool: real delete or not).
1001
 *
1002
 * @return string
1003
 *
1004
 * @author Patrick Cool <[email protected]>, Ghent University
1005
 *
1006
 * @version february 2006, dokeos 1.8
1007
 */
1008
function deleteForumCategoryThread($content, $id)
1009
{
1010
    $_course = api_get_course_info();
1011
    $table_forums = Database::get_course_table(TABLE_FORUM);
1012
    $table_forums_post = Database::get_course_table(TABLE_FORUM_POST);
1013
    $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
1014
    $course_id = api_get_course_int_id();
1015
    $groupId = api_get_group_id();
1016
    $groupInfo = GroupManager::get_group_properties($groupId);
1017
    $userId = api_get_user_id();
1018
    $id = (int) $id;
1019
1020
    // Delete all attachment file about this tread id.
1021
    $sql = "SELECT post_id FROM $table_forums_post
1022
            WHERE c_id = $course_id AND thread_id = '".$id."' ";
1023
    $res = Database::query($sql);
1024
    while ($poster_id = Database::fetch_row($res)) {
1025
        delete_attachment($poster_id[0]);
1026
    }
1027
1028
    $tool_constant = null;
1029
    $return_message = '';
1030
    if ($content === 'forumcategory') {
1031
        $tool_constant = TOOL_FORUM_CATEGORY;
1032
        $return_message = get_lang('ForumCategoryDeleted');
1033
1034
        if (!empty($forum_list)) {
1035
            $sql = "SELECT forum_id FROM $table_forums
1036
                    WHERE c_id = $course_id AND forum_category='".$id."'";
1037
            $result = Database::query($sql);
1038
            $row = Database::fetch_array($result);
1039
            foreach ($row as $arr_forum) {
1040
                $forum_id = $arr_forum['forum_id'];
1041
                api_item_property_update(
1042
                    $_course,
1043
                    'forum',
1044
                    $forum_id,
1045
                    'delete',
1046
                    api_get_user_id()
1047
                );
1048
            }
1049
        }
1050
    }
1051
1052
    if ($content === 'forum') {
1053
        $tool_constant = TOOL_FORUM;
1054
        $return_message = get_lang('ForumDeleted');
1055
1056
        if (!empty($number_threads)) {
1057
            $sql = "SELECT thread_id FROM $table_forum_thread 
1058
                    WHERE c_id = $course_id AND forum_id = $id ";
1059
            $result = Database::query($sql);
1060
            $row = Database::fetch_array($result);
1061
            foreach ($row as $arr_forum) {
1062
                $forum_id = $arr_forum['thread_id'];
1063
                api_item_property_update(
1064
                    $_course,
1065
                    'forum_thread',
1066
                    $forum_id,
1067
                    'delete',
1068
                    api_get_user_id()
1069
                );
1070
            }
1071
        }
1072
    }
1073
1074
    if ($content === 'thread') {
1075
        $tool_constant = TOOL_FORUM_THREAD;
1076
        $return_message = get_lang('ThreadDeleted');
1077
        Skill::deleteSkillsFromItem($id, ITEM_TYPE_FORUM_THREAD);
1078
    }
1079
1080
    api_item_property_update(
1081
        $_course,
1082
        $tool_constant,
1083
        $id,
1084
        'delete',
1085
        $userId,
1086
        $groupInfo
1087
    );
1088
1089
    // Check if this returns a true and if so => return $return_message, if not => return false;
1090
    if (!empty($return_message)) {
1091
        Display::addFlash(Display::return_message($return_message, 'confirmation', false));
1092
    }
1093
1094
    return $return_message;
1095
}
1096
1097
/**
1098
 * This function deletes a forum post. This separate function is needed because forum posts do not appear
1099
 * in the item_property table (yet)
1100
 * and because deleting a post also has consequence on the posts that have this post as parent_id
1101
 * (they are also deleted).
1102
 * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
1103
 * We also have to decrease the number of replies in the thread table.
1104
 *
1105
 * @param $post_id the id of the post that will be deleted
1106
 *
1107
 * @todo write recursive function that deletes all the posts that have this message as parent
1108
 *
1109
 * @return string language variable
1110
 *
1111
 * @author Patrick Cool <[email protected]>, Ghent University
1112
 * @author Hubert Borderiou Function cleanead and fixed
1113
 *
1114
 * @version february 2006
1115
 */
1116
function delete_post($post_id)
1117
{
1118
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1119
    $post_id = intval($post_id);
1120
    $course_id = api_get_course_int_id();
1121
    $em = Database::getManager();
1122
1123
    $post = $em
1124
        ->getRepository('ChamiloCourseBundle:CForumPost')
1125
        ->findOneBy(['cId' => $course_id, 'postId' => $post_id]);
1126
1127
    if ($post) {
1128
        $em
1129
            ->createQuery('
1130
                UPDATE ChamiloCourseBundle:CForumPost p
1131
                SET p.postParentId = :parent_of_deleted_post
1132
                WHERE
1133
                    p.cId = :course AND
1134
                    p.postParentId = :post AND
1135
                    p.threadId = :thread_of_deleted_post AND
1136
                    p.forumId = :forum_of_deleted_post
1137
            ')
1138
            ->execute([
1139
                'parent_of_deleted_post' => $post->getPostParentId(),
1140
                'course' => $course_id,
1141
                'post' => $post->getPostId(),
1142
                'thread_of_deleted_post' => $post->getThread() ? $post->getThread()->getIid() : 0,
1143
                'forum_of_deleted_post' => $post->getForumId(),
1144
            ]);
1145
1146
        $em->remove($post);
1147
        $em->flush();
1148
1149
        // Delete attachment file about this post id.
1150
        delete_attachment($post_id);
1151
    }
1152
1153
    $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
1154
1155
    if (is_array($last_post_of_thread)) {
1156
        // Decreasing the number of replies for this thread and also changing the last post information.
1157
        $sql = "UPDATE $table_threads
1158
                SET
1159
                    thread_replies = thread_replies - 1,
1160
                    thread_last_post = ".intval($last_post_of_thread['post_id']).",
1161
                    thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
1162
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
1163
        Database::query($sql);
1164
1165
        return 'PostDeleted';
1166
    }
1167
    if (!$last_post_of_thread) {
1168
        // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
1169
        $sql = "DELETE FROM $table_threads
1170
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
1171
        Database::query($sql);
1172
1173
        return 'PostDeletedSpecial';
1174
    }
1175
}
1176
1177
/**
1178
 * This function gets the all information of the last (=most recent) post of the thread
1179
 * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date.
1180
 *
1181
 * @param $thread_id the id of the thread we want to know the last post of
1182
 *
1183
 * @return an array or bool if there is a last post found, false if there is
1184
 *            no post entry linked to that thread => thread will be deleted
1185
 *
1186
 * @author Patrick Cool <[email protected]>, Ghent University
1187
 *
1188
 * @version february 2006, dokeos 1.8
1189
 */
1190
function check_if_last_post_of_thread($thread_id)
1191
{
1192
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1193
    $course_id = api_get_course_int_id();
1194
    $sql = "SELECT * FROM $table_posts
1195
            WHERE c_id = $course_id AND thread_id = ".intval($thread_id)."
1196
            ORDER BY post_date DESC";
1197
    $result = Database::query($sql);
1198
    if (Database::num_rows($result) > 0) {
1199
        $row = Database::fetch_array($result);
1200
1201
        return $row;
1202
    } else {
1203
        return false;
1204
    }
1205
}
1206
1207
/**
1208
 * @param string $content                   Type of content forum category, forum, thread, post
1209
 * @param int    $id                        the id of the content we want to make invisible
1210
 * @param int    $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
1211
 * @param array  $additional_url_parameters
1212
 *
1213
 * @return string HTML
1214
 */
1215
function return_visible_invisible_icon(
1216
    $content,
1217
    $id,
1218
    $current_visibility_status,
1219
    $additional_url_parameters = ''
1220
) {
1221
    $html = '';
1222
    $id = (int) $id;
1223
    $current_visibility_status = (int) $current_visibility_status;
1224
1225
    if ($current_visibility_status == 1) {
1226
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1227
        if (is_array($additional_url_parameters)) {
1228
            foreach ($additional_url_parameters as $key => $value) {
1229
                $html .= $key.'='.$value.'&';
1230
            }
1231
        }
1232
        $html .= 'action=invisible&content='.$content.'&id='.$id.'">'.
1233
            Display::return_icon('visible.png', get_lang('MakeInvisible'), [], ICON_SIZE_SMALL).'</a>';
1234
    }
1235
    if ($current_visibility_status == 0) {
1236
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1237
        if (is_array($additional_url_parameters)) {
1238
            foreach ($additional_url_parameters as $key => $value) {
1239
                $html .= $key.'='.$value.'&';
1240
            }
1241
        }
1242
        $html .= 'action=visible&content='.$content.'&id='.$id.'">'.
1243
            Display::return_icon('invisible.png', get_lang('MakeVisible'), [], ICON_SIZE_SMALL).'</a>';
1244
    }
1245
1246
    return $html;
1247
}
1248
1249
/**
1250
 * @param $content
1251
 * @param $id
1252
 * @param $current_lock_status
1253
 * @param string $additional_url_parameters
1254
 *
1255
 * @return string
1256
 */
1257
function return_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
1258
{
1259
    $html = '';
1260
    $id = intval($id);
1261
    //check if the forum is blocked due
1262
    if ($content == 'thread') {
1263
        if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
1264
            $html .= Display::return_icon(
1265
                'lock_na.png',
1266
                get_lang('ResourceLockedByGradebook'),
1267
                [],
1268
                ICON_SIZE_SMALL
1269
            );
1270
1271
            return $html;
1272
        }
1273
    }
1274
    if ($current_lock_status == '1') {
1275
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1276
        if (is_array($additional_url_parameters)) {
1277
            foreach ($additional_url_parameters as $key => $value) {
1278
                $html .= $key.'='.$value.'&';
1279
            }
1280
        }
1281
        $html .= 'action=unlock&content='.$content.'&id='.$id.'">'.
1282
            Display::return_icon('lock.png', get_lang('Unlock'), [], ICON_SIZE_SMALL).'</a>';
1283
    }
1284
    if ($current_lock_status == '0') {
1285
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1286
        if (is_array($additional_url_parameters)) {
1287
            foreach ($additional_url_parameters as $key => $value) {
1288
                $html .= $key.'='.$value.'&';
1289
            }
1290
        }
1291
        $html .= 'action=lock&content='.$content.'&id='.$id.'">'.
1292
            Display::return_icon('unlock.png', get_lang('Lock'), [], ICON_SIZE_SMALL).'</a>';
1293
    }
1294
1295
    return $html;
1296
}
1297
1298
/**
1299
 * This function takes care of the display of the up and down icon.
1300
 *
1301
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1302
 * @param int    $id      is the id of the item we want to display the icons for
1303
 * @param array  $list    is an array of all the items. All items in this list should have
1304
 *                        an up and down icon except for the first (no up icon) and the last (no down icon)
1305
 *                        The key of this $list array is the id of the item.
1306
 *
1307
 * @return string HTML
1308
 */
1309
function return_up_down_icon($content, $id, $list)
1310
{
1311
    $id = (int) $id;
1312
    $total_items = count($list);
1313
    $position = 0;
1314
    $internal_counter = 0;
1315
    $forumCategory = isset($_GET['forumcategory']) ? Security::remove_XSS($_GET['forumcategory']) : null;
1316
1317
    if (is_array($list)) {
1318
        foreach ($list as $key => $listitem) {
1319
            $internal_counter++;
1320
            if ($id == $key) {
1321
                $position = $internal_counter;
1322
            }
1323
        }
1324
    }
1325
1326
    if ($position > 1) {
1327
        $return_value = '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=up&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveUp').'">'.
1328
            Display::return_icon('up.png', get_lang('MoveUp'), [], ICON_SIZE_SMALL).'</a>';
1329
    } else {
1330
        $return_value = Display::return_icon('up_na.png', '-', [], ICON_SIZE_SMALL);
1331
    }
1332
1333
    if ($position < $total_items) {
1334
        $return_value .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=down&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveDown').'" >'.
1335
            Display::return_icon('down.png', get_lang('MoveDown'), [], ICON_SIZE_SMALL).'</a>';
1336
    } else {
1337
        $return_value .= Display::return_icon('down_na.png', '-', [], ICON_SIZE_SMALL);
1338
    }
1339
1340
    return $return_value;
1341
}
1342
1343
/**
1344
 * This function changes the visibility in the database (item_property).
1345
 *
1346
 * @param string $content           what is it that we want to make (in)visible: forum category, forum, thread, post
1347
 * @param int    $id                the id of the content we want to make invisible
1348
 * @param string $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
1349
 *
1350
 * @todo change the get parameter so that it matches the tool constants.
1351
 * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
1352
 * @todo move to itemmanager
1353
 *
1354
 * @return string language variable
1355
 *
1356
 * @author Patrick Cool <[email protected]>, Ghent University
1357
 *
1358
 * @version february 2006, dokeos 1.8
1359
 */
1360
function change_visibility($content, $id, $target_visibility)
1361
{
1362
    $_course = api_get_course_info();
1363
    $constants = [
1364
        'forumcategory' => TOOL_FORUM_CATEGORY,
1365
        'forum' => TOOL_FORUM,
1366
        'thread' => TOOL_FORUM_THREAD,
1367
    ];
1368
    api_item_property_update(
1369
        $_course,
1370
        $constants[$content],
1371
        $id,
1372
        $target_visibility,
1373
        api_get_user_id()
1374
    );
1375
1376
    if ($target_visibility == 'visible') {
1377
        handle_mail_cue($content, $id);
1378
    }
1379
1380
    return get_lang('VisibilityChanged');
1381
}
1382
1383
/**
1384
 * This function changes the lock status in the database.
1385
 *
1386
 * @param string $content what is it that we want to (un)lock: forum category, forum, thread, post
1387
 * @param int    $id      the id of the content we want to (un)lock
1388
 * @param string $action  do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
1389
 *
1390
 * @return string language variable
1391
 *
1392
 * @todo move to item manager
1393
 *
1394
 * @author Patrick Cool <[email protected]>, Ghent University
1395
 *
1396
 * @version february 2006, dokeos 1.8
1397
 */
1398
function change_lock_status($content, $id, $action)
1399
{
1400
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1401
    $table_forums = Database::get_course_table(TABLE_FORUM);
1402
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1403
1404
    // Determine the relevant table.
1405
    if ($content == 'forumcategory') {
1406
        $table = $table_categories;
1407
        $id_field = 'cat_id';
1408
    } elseif ($content == 'forum') {
1409
        $table = $table_forums;
1410
        $id_field = 'forum_id';
1411
    } elseif ($content == 'thread') {
1412
        $table = $table_threads;
1413
        $id_field = 'thread_id';
1414
    } else {
1415
        return get_lang('Error');
1416
    }
1417
1418
    // Determine what we are doing => defines the value for the database and the return message.
1419
    if ($action == 'lock') {
1420
        $db_locked = 1;
1421
        $return_message = get_lang('Locked');
1422
    } elseif ($action == 'unlock') {
1423
        $db_locked = 0;
1424
        $return_message = get_lang('Unlocked');
1425
    } else {
1426
        return get_lang('Error');
1427
    }
1428
1429
    $course_id = api_get_course_int_id();
1430
1431
    // Doing the change in the database
1432
    $sql = "UPDATE $table SET locked='".Database::escape_string($db_locked)."'
1433
            WHERE c_id = $course_id AND $id_field='".Database::escape_string($id)."'";
1434
    if (Database::query($sql)) {
1435
        return $return_message;
1436
    } else {
1437
        return get_lang('Error');
1438
    }
1439
}
1440
1441
/**
1442
 * This function moves a forum or a forum category up or down.
1443
 *
1444
 * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
1445
 * @param $direction do we want to move it up or down
1446
 * @param $id the id of the content we want to make invisible
1447
 *
1448
 * @todo consider removing the table_item_property calls here but this can
1449
 * prevent unwanted side effects when a forum does not have an entry in
1450
 * the item_property table but does have one in the forum table.
1451
 *
1452
 * @return string language variable
1453
 *
1454
 * @author Patrick Cool <[email protected]>, Ghent University
1455
 *
1456
 * @version february 2006, dokeos 1.8
1457
 */
1458
function move_up_down($content, $direction, $id)
1459
{
1460
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1461
    $table_forums = Database::get_course_table(TABLE_FORUM);
1462
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1463
    $course_id = api_get_course_int_id();
1464
    $id = intval($id);
1465
1466
    // Determine which field holds the sort order.
1467
    if ($content == 'forumcategory') {
1468
        $table = $table_categories;
1469
        $sort_column = 'cat_order';
1470
        $id_column = 'cat_id';
1471
        $sort_column = 'cat_order';
1472
    } elseif ($content == 'forum') {
1473
        $table = $table_forums;
1474
        $sort_column = 'forum_order';
1475
        $id_column = 'forum_id';
1476
        $sort_column = 'forum_order';
1477
        // We also need the forum_category of this forum.
1478
        $sql = "SELECT forum_category FROM $table_forums
1479
                WHERE c_id = $course_id AND forum_id = ".intval($id);
1480
        $result = Database::query($sql);
1481
        $row = Database::fetch_array($result);
1482
        $forum_category = $row['forum_category'];
1483
    } else {
1484
        return get_lang('Error');
1485
    }
1486
1487
    // Determine the need for sorting ascending or descending order.
1488
    if ($direction == 'down') {
1489
        $sort_direction = 'ASC';
1490
    } elseif ($direction == 'up') {
1491
        $sort_direction = 'DESC';
1492
    } else {
1493
        return get_lang('Error');
1494
    }
1495
1496
    // The SQL statement
1497
    if ($content == 'forumcategory') {
1498
        $sql = "SELECT *
1499
                FROM $table_categories forum_categories, $table_item_property item_properties
1500
                WHERE
1501
                    forum_categories.c_id = $course_id AND
1502
                    item_properties.c_id = $course_id AND
1503
                    forum_categories.cat_id=item_properties.ref AND
1504
                    item_properties.tool='".TOOL_FORUM_CATEGORY."'
1505
                ORDER BY forum_categories.cat_order $sort_direction";
1506
    }
1507
    if ($content == 'forum') {
1508
        $sql = "SELECT *
1509
            FROM $table
1510
            WHERE
1511
                c_id = $course_id AND
1512
                forum_category='".Database::escape_string($forum_category)."'
1513
            ORDER BY forum_order $sort_direction";
1514
    }
1515
    // Finding the items that need to be switched.
1516
    $result = Database::query($sql);
1517
    $found = false;
1518
    while ($row = Database::fetch_array($result)) {
1519
        if ($found) {
1520
            $next_id = $row[$id_column];
1521
            $next_sort = $row[$sort_column];
1522
            $found = false;
1523
        }
1524
        if ($id == $row[$id_column]) {
1525
            $this_id = $id;
1526
            $this_sort = $row[$sort_column];
1527
            $found = true;
1528
        }
1529
    }
1530
1531
    // Committing the switch.
1532
    // We do an extra check if we do not have illegal values. If your remove this if statement you will
1533
    // be able to mess with the sorting by refreshing the page over and over again.
1534
    if ($this_sort != '' && $next_sort != '' && $next_id != '' && $this_id != '') {
1535
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."'
1536
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($next_id)."'";
1537
        Database::query($sql);
1538
1539
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."'
1540
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($this_id)."'";
1541
        Database::query($sql);
1542
    }
1543
1544
    return get_lang(ucfirst($content).'Moved');
1545
}
1546
1547
/**
1548
 * Retrieve all the information off the forum categories (or one specific) for the current course.
1549
 * The categories are sorted according to their sorting order (cat_order.
1550
 *
1551
 * @param int|string $id        default ''. When an id is passed we only find the information
1552
 *                              about that specific forum category. If no id is passed we get all the forum categories.
1553
 * @param int        $courseId  Optional. The course ID
1554
 * @param int        $sessionId Optional. The session ID
1555
 *
1556
 * @return array containing all the information about all the forum categories
1557
 *
1558
 * @author Patrick Cool <[email protected]>, Ghent University
1559
 *
1560
 * @version february 2006, dokeos 1.8
1561
 */
1562
function get_forum_categories($id = '', $courseId = 0, $sessionId = 0)
1563
{
1564
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1565
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1566
1567
    // Condition for the session
1568
    $session_id = $sessionId ?: api_get_session_id();
1569
    $course_id = $courseId ?: api_get_course_int_id();
1570
1571
    $condition_session = api_get_session_condition(
1572
        $session_id,
1573
        true,
1574
        true,
1575
        'forum_categories.session_id'
1576
    );
1577
    $condition_session .= " AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
1578
1579
    if (empty($id)) {
1580
        $sql = "SELECT *
1581
                FROM $table_item_property item_properties 
1582
                INNER JOIN $table_categories forum_categories
1583
                ON (
1584
                    forum_categories.cat_id = item_properties.ref AND 
1585
                    item_properties.c_id = forum_categories.c_id
1586
                )
1587
                WHERE                    
1588
                    item_properties.visibility = 1 AND
1589
                    item_properties.tool = '".TOOL_FORUM_CATEGORY."'
1590
                    $condition_session
1591
                ORDER BY forum_categories.cat_order ASC";
1592
        if (api_is_allowed_to_edit()) {
1593
            $sql = "SELECT *
1594
                    FROM $table_item_property item_properties  
1595
                    INNER JOIN $table_categories forum_categories
1596
                    ON (
1597
                        forum_categories.cat_id = item_properties.ref AND 
1598
                        item_properties.c_id = forum_categories.c_id
1599
                    )
1600
                    WHERE                        
1601
                        item_properties.visibility<>2 AND
1602
                        item_properties.tool='".TOOL_FORUM_CATEGORY."'
1603
                        $condition_session
1604
                    ORDER BY forum_categories.cat_order ASC";
1605
        }
1606
    } else {
1607
        $sql = "SELECT *
1608
                FROM $table_item_property item_properties 
1609
                INNER JOIN $table_categories forum_categories
1610
                ON (
1611
                    forum_categories.cat_id = item_properties.ref AND 
1612
                    item_properties.c_id = forum_categories.c_id
1613
                )
1614
                WHERE                    
1615
                    item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
1616
                    forum_categories.cat_id = ".intval($id)."
1617
                    $condition_session
1618
                ORDER BY forum_categories.cat_order ASC";
1619
    }
1620
1621
    $result = Database::query($sql);
1622
    $forum_categories_list = [];
1623
    $extraFieldValue = new ExtraFieldValue('forum_category');
1624
    while ($row = Database::fetch_assoc($result)) {
1625
        $row['extra_fields'] = $extraFieldValue->getAllValuesByItem($row['cat_id']);
1626
1627
        if (empty($id)) {
1628
            $forum_categories_list[$row['cat_id']] = $row;
1629
        } else {
1630
            $forum_categories_list = $row;
1631
        }
1632
    }
1633
1634
    return $forum_categories_list;
1635
}
1636
1637
/**
1638
 * This function retrieves all the fora in a given forum category.
1639
 *
1640
 * @param int $cat_id   the id of the forum category
1641
 * @param int $courseId Optional. The course ID
1642
 *
1643
 * @return array containing all the information about the forums (regardless of their category)
1644
 *
1645
 * @author Patrick Cool <[email protected]>, Ghent University
1646
 *
1647
 * @version february 2006, dokeos 1.8
1648
 */
1649
function get_forums_in_category($cat_id, $courseId = 0)
1650
{
1651
    $table_forums = Database::get_course_table(TABLE_FORUM);
1652
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1653
1654
    $forum_list = [];
1655
    $course_id = $courseId ?: api_get_course_int_id();
1656
    $cat_id = (int) $cat_id;
1657
1658
    $sql = "SELECT * FROM $table_forums forum 
1659
            INNER JOIN $table_item_property item_properties
1660
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1661
            WHERE
1662
                forum.forum_category = '".$cat_id."' AND                
1663
                item_properties.visibility = 1 AND
1664
                forum.c_id = $course_id AND
1665
                item_properties.c_id = $course_id AND
1666
                item_properties.tool = '".TOOL_FORUM."'                 
1667
            ORDER BY forum.forum_order ASC";
1668
    if (api_is_allowed_to_edit()) {
1669
        $sql = "SELECT * FROM $table_forums forum  
1670
                INNER JOIN $table_item_property item_properties
1671
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1672
                WHERE
1673
                    forum.forum_category = '".$cat_id."' AND                    
1674
                    item_properties.visibility <> 2 AND
1675
                    item_properties.tool = '".TOOL_FORUM."' AND
1676
                    item_properties.c_id = $course_id AND
1677
                    forum.c_id = $course_id
1678
                ORDER BY forum_order ASC";
1679
    }
1680
    $result = Database::query($sql);
1681
    while ($row = Database::fetch_array($result)) {
1682
        $forum_list[$row['forum_id']] = $row;
1683
    }
1684
1685
    return $forum_list;
1686
}
1687
1688
/**
1689
 * Retrieve all the forums (regardless of their category) or of only one.
1690
 * The forums are sorted according to the forum_order.
1691
 * Since it does not take the forum category into account there probably
1692
 * will be two or more forums that have forum_order=1, ...
1693
 *
1694
 * @param int    $id                 forum id
1695
 * @param string $course_code
1696
 * @param bool   $includeGroupsForum
1697
 * @param int    $sessionId
1698
 *
1699
 * @return array an array containing all the information about the forums (regardless of their category)
1700
 *
1701
 * @todo check $sql4 because this one really looks fishy.
1702
 *
1703
 * @author Patrick Cool <[email protected]>, Ghent University
1704
 *
1705
 * @version february 2006, dokeos 1.8
1706
 */
1707
function get_forums(
1708
    $id = 0,
1709
    $course_code = '',
1710
    $includeGroupsForum = true,
1711
    $sessionId = 0
1712
) {
1713
    $id = (int) $id;
1714
    $course_info = api_get_course_info($course_code);
1715
1716
    $table_forums = Database::get_course_table(TABLE_FORUM);
1717
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1718
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1719
1720
    // Condition for the session
1721
    $session_id = intval($sessionId) ?: api_get_session_id();
1722
    $sessionIdLink = $session_id === 0 ? '' : ' AND threads.session_id = item_properties.session_id';
1723
1724
    $condition_session = api_get_session_condition(
1725
        $session_id,
1726
        true,
1727
        false,
1728
        'item_properties.session_id'
1729
    );
1730
1731
    $course_id = $course_info['real_id'];
1732
1733
    $forum_list = [];
1734
    $includeGroupsForumSelect = '';
1735
    if (!$includeGroupsForum) {
1736
        $includeGroupsForumSelect = " AND (forum_of_group = 0 OR forum_of_group IS NULL) ";
1737
    }
1738
1739
    $allowToEdit = api_is_allowed_to_edit();
1740
1741
    if (empty($id)) {
1742
        // Student
1743
        // Select all the forum information of all forums (that are visible to students).
1744
        $sql = "SELECT item_properties.*, forum.* 
1745
                FROM $table_forums forum
1746
                INNER JOIN $table_item_property item_properties
1747
                ON (
1748
                    forum.forum_id = item_properties.ref AND
1749
                    forum.c_id = item_properties.c_id
1750
                )
1751
                WHERE
1752
                    item_properties.visibility = 1 AND
1753
                    item_properties.tool = '".TOOL_FORUM."'
1754
                    $condition_session AND
1755
                    forum.c_id = $course_id AND
1756
                    item_properties.c_id = $course_id
1757
                    $includeGroupsForumSelect
1758
                ORDER BY forum.forum_order ASC";
1759
1760
        // Select the number of threads of the forums (only the threads that are visible).
1761
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1762
                FROM $table_threads threads
1763
                INNER JOIN $table_item_property item_properties
1764
                ON (
1765
                    threads.thread_id = item_properties.ref AND
1766
                    threads.c_id = item_properties.c_id
1767
                    $sessionIdLink
1768
                )
1769
                WHERE
1770
                    item_properties.visibility=1 AND
1771
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1772
                    threads.c_id = $course_id AND
1773
                    item_properties.c_id = $course_id
1774
                GROUP BY threads.forum_id";
1775
1776
        // Course Admin
1777
        if ($allowToEdit) {
1778
            // Select all the forum information of all forums (that are not deleted).
1779
            $sql = "SELECT item_properties.*, forum.* 
1780
                    FROM $table_forums forum
1781
                    INNER JOIN $table_item_property item_properties
1782
                    ON (
1783
                        forum.forum_id = item_properties.ref AND
1784
                        forum.c_id = item_properties.c_id
1785
                    )
1786
                    WHERE
1787
                        item_properties.visibility <> 2 AND
1788
                        item_properties.tool = '".TOOL_FORUM."'
1789
                        $condition_session AND
1790
                        forum.c_id = $course_id AND
1791
                        item_properties.c_id = $course_id
1792
                        $includeGroupsForumSelect
1793
                    ORDER BY forum_order ASC";
1794
1795
            // Select the number of threads of the forums (only the threads that are not deleted).
1796
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1797
                    FROM $table_threads threads
1798
                    INNER JOIN $table_item_property item_properties
1799
                    ON (
1800
                        threads.thread_id = item_properties.ref AND
1801
                        threads.c_id = item_properties.c_id
1802
                        $sessionIdLink
1803
                    )
1804
                    WHERE
1805
                        item_properties.visibility<>2 AND
1806
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1807
                        threads.c_id = $course_id AND
1808
                        item_properties.c_id = $course_id
1809
                    GROUP BY threads.forum_id";
1810
        }
1811
    } else {
1812
        // GETTING ONE SPECIFIC FORUM
1813
        /* We could do the splitup into student and course admin also but we want
1814
        to have as much as information about a certain forum as possible
1815
        so we do not take too much information into account. This function
1816
         (or this section of the function) is namely used to fill the forms
1817
        when editing a forum (and for the moment it is the only place where
1818
        we use this part of the function) */
1819
1820
        // Select all the forum information of the given forum (that is not deleted).
1821
        $sql = "SELECT * FROM $table_item_property item_properties 
1822
                INNER JOIN $table_forums forum
1823
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1824
                WHERE
1825
                    forum.forum_id = $id AND
1826
                    forum.c_id = $course_id AND
1827
                    item_properties.visibility != 2 AND
1828
                    item_properties.tool = '".TOOL_FORUM."'
1829
                ORDER BY forum_order ASC";
1830
1831
        // Select the number of threads of the forum.
1832
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1833
                FROM $table_threads
1834
                WHERE
1835
                    forum_id = $id
1836
                GROUP BY forum_id";
1837
    }
1838
1839
    // Handling all the forum information.
1840
    $result = Database::query($sql);
1841
    while ($row = Database::fetch_assoc($result)) {
1842
        if (empty($id)) {
1843
            $forum_list[$row['forum_id']] = $row;
1844
        } else {
1845
            $forum_list = $row;
1846
        }
1847
    }
1848
1849
    // Handling the thread count information.
1850
    $result2 = Database::query($sql2);
1851
    while ($row2 = Database::fetch_array($result2)) {
1852
        if (empty($id)) {
1853
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1854
        } else {
1855
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1856
        }
1857
    }
1858
1859
    /* Finding the last post information
1860
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1861
    if (empty($id)) {
1862
        if (is_array($forum_list)) {
1863
            foreach ($forum_list as $key => $value) {
1864
                $lastPost = get_last_post_information(
1865
                    $key,
1866
                    $allowToEdit,
1867
                    $course_id
1868
                );
1869
1870
                if ($lastPost) {
1871
                    $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
1872
                    $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
1873
                    $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
1874
                    $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
1875
                    $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1876
                    $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1877
                    $forum_list[$key]['last_post_title'] = $lastPost['last_post_title'];
1878
                    $forum_list[$key]['last_post_text'] = $lastPost['last_post_text'];
1879
                }
1880
            }
1881
        } else {
1882
            $forum_list = [];
1883
        }
1884
    } else {
1885
        $lastPost = get_last_post_information(
1886
            $id,
1887
            $allowToEdit,
1888
            $course_id
1889
        );
1890
        if ($lastPost) {
1891
            $forum_list['last_post_id'] = $lastPost['last_post_id'];
1892
            $forum_list['last_poster_id'] = $lastPost['last_poster_id'];
1893
            $forum_list['last_post_date'] = $lastPost['last_post_date'];
1894
            $forum_list['last_poster_name'] = $lastPost['last_poster_name'];
1895
            $forum_list['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1896
            $forum_list['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1897
            $forum_list['last_post_title'] = $lastPost['last_post_title'];
1898
            $forum_list['last_post_text'] = $lastPost['last_post_text'];
1899
        }
1900
    }
1901
1902
    return $forum_list;
1903
}
1904
1905
/**
1906
 * @param int  $course_id
1907
 * @param int  $thread_id
1908
 * @param int  $forum_id
1909
 * @param bool $show_visible
1910
 *
1911
 * @return array|bool
1912
 */
1913
function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
1914
{
1915
    if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
1916
        return false;
1917
    }
1918
1919
    $thread_id = intval($thread_id);
1920
    $forum_id = intval($forum_id);
1921
    $course_id = intval($course_id);
1922
1923
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1924
    $sql = "SELECT * FROM $table_posts
1925
            WHERE 
1926
                c_id = $course_id AND 
1927
                thread_id = $thread_id AND 
1928
                forum_id = $forum_id";
1929
1930
    if ($show_visible == false) {
1931
        $sql .= " AND visible = 1 ";
1932
    }
1933
1934
    $sql .= " ORDER BY post_id DESC LIMIT 1";
1935
    $result = Database::query($sql);
1936
    if (Database::num_rows($result)) {
1937
        return Database::fetch_array($result, 'ASSOC');
1938
    } else {
1939
        return false;
1940
    }
1941
}
1942
1943
/**
1944
 * This function gets all the last post information of a certain forum.
1945
 *
1946
 * @param int  $forum_id        the id of the forum we want to know the last post information of
1947
 * @param bool $show_invisibles
1948
 * @param string course db name
1949
 * @param int $sessionId Optional. The session id
1950
 *
1951
 * @return array containing all the information about the last post
1952
 *               (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
1953
 *
1954
 * @author Patrick Cool <[email protected]>, Ghent University
1955
 *
1956
 * @version february 2006, dokeos 1.8
1957
 */
1958
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1959
{
1960
    if (!isset($course_id)) {
1961
        $course_id = api_get_course_int_id();
1962
    } else {
1963
        $course_id = intval($course_id);
1964
    }
1965
    $sessionId = $sessionId ? intval($sessionId) : api_get_session_id();
1966
1967
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1968
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1969
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1970
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1971
1972
    $forum_id = intval($forum_id);
1973
    $return_array = [];
1974
1975
    // First get the threads to make sure there is no inconsistency in the
1976
    // database between forum and thread
1977
    $sql = "SELECT thread_id FROM $table_threads 
1978
            WHERE 
1979
                forum_id = $forum_id AND 
1980
                c_id = $course_id AND 
1981
                session_id = $sessionId";
1982
    $result = Database::query($sql);
1983
    if (Database::num_rows($result) == 0) {
1984
        // If there are no threads in this forum, then there are no posts
1985
        return [];
1986
    }
1987
    $threads = [];
1988
    while ($row = Database::fetch_row($result)) {
1989
        $threads[] = $row[0];
1990
    }
1991
    $threadsList = implode(',', $threads);
1992
    // Now get the posts that are linked to these threads
1993
    $sql = "SELECT
1994
                post.post_id,
1995
                post.forum_id,
1996
                post.poster_id,
1997
                post.poster_name,
1998
                post.post_date,
1999
                users.lastname,
2000
                users.firstname,
2001
                post.visible,
2002
                thread_properties.visibility AS thread_visibility,
2003
                forum_properties.visibility AS forum_visibility,
2004
                post.post_title,
2005
                post.post_text
2006
            FROM
2007
                $table_posts post,
2008
                $table_users users,
2009
                $table_item_property thread_properties,
2010
                $table_item_property forum_properties
2011
            WHERE
2012
                post.forum_id = $forum_id
2013
                AND post.thread_id IN ($threadsList)
2014
                AND post.poster_id = users.user_id
2015
                AND post.thread_id = thread_properties.ref
2016
                AND thread_properties.tool='".TOOL_FORUM_THREAD."'
2017
                AND post.forum_id=forum_properties.ref
2018
                AND forum_properties.tool='".TOOL_FORUM."'
2019
                AND post.c_id = $course_id AND
2020
                thread_properties.c_id = $course_id AND
2021
                forum_properties.c_id = $course_id
2022
            ORDER BY post.post_id DESC";
2023
    $result = Database::query($sql);
2024
2025
    if ($show_invisibles) {
2026
        $row = Database::fetch_array($result);
2027
        $return_array['last_post_id'] = $row['post_id'];
2028
        $return_array['last_poster_id'] = $row['poster_id'];
2029
        $return_array['last_post_date'] = $row['post_date'];
2030
        $return_array['last_poster_name'] = $row['poster_name'];
2031
        $return_array['last_poster_lastname'] = $row['lastname'];
2032
        $return_array['last_poster_firstname'] = $row['firstname'];
2033
        $return_array['last_post_title'] = $row['post_title'];
2034
        $return_array['last_post_text'] = $row['post_text'];
2035
2036
        return $return_array;
2037
    } else {
2038
        // We have to loop through the results to find the first one that is
2039
        // actually visible to students (forum_category, forum, thread AND post are visible).
2040
        while ($row = Database::fetch_array($result)) {
2041
            if ($row['visible'] == '1' && $row['thread_visibility'] == '1' && $row['forum_visibility'] == '1') {
2042
                $return_array['last_post_id'] = $row['post_id'];
2043
                $return_array['last_poster_id'] = $row['poster_id'];
2044
                $return_array['last_post_date'] = $row['post_date'];
2045
                $return_array['last_poster_name'] = $row['poster_name'];
2046
                $return_array['last_poster_lastname'] = $row['lastname'];
2047
                $return_array['last_poster_firstname'] = $row['firstname'];
2048
                $return_array['last_post_title'] = $row['post_title'];
2049
                $return_array['last_post_text'] = $row['post_text'];
2050
2051
                return $return_array;
2052
            }
2053
        }
2054
    }
2055
}
2056
2057
/**
2058
 * Retrieve all the threads of a given forum.
2059
 *
2060
 * @param int      $forum_id
2061
 * @param int|null $courseId  Optional If is null then it is considered the current course
2062
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2063
 *
2064
 * @return array containing all the information about the threads
2065
 *
2066
 * @author Patrick Cool <[email protected]>, Ghent University
2067
 *
2068
 * @version february 2006, dokeos 1.8
2069
 */
2070
function get_threads($forum_id, $courseId = null, $sessionId = null)
2071
{
2072
    $groupId = api_get_group_id();
2073
    $sessionId = $sessionId !== null ? (int) $sessionId : api_get_session_id();
2074
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2075
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2076
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2077
2078
    $courseId = $courseId !== null ? (int) $courseId : api_get_course_int_id();
2079
    $groupInfo = GroupManager::get_group_properties($groupId);
2080
    $groupCondition = '';
2081
2082
    if (!empty($groupInfo)) {
2083
        $groupIid = $groupInfo['iid'];
2084
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
2085
    }
2086
2087
    $sessionCondition = api_get_session_condition(
2088
        $sessionId,
2089
        true,
2090
        false,
2091
        'item_properties.session_id'
2092
    );
2093
2094
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
2095
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
2096
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
2097
    // This is why it is added to the end of the field selection
2098
    $sql = "SELECT DISTINCT
2099
                item_properties.*,
2100
                users.firstname,
2101
                users.lastname,
2102
                users.user_id,
2103
                thread.locked as locked,
2104
                thread.*
2105
            FROM $table_threads thread
2106
            INNER JOIN $table_item_property item_properties
2107
            ON
2108
                thread.thread_id = item_properties.ref AND
2109
                item_properties.c_id = thread.c_id AND
2110
                item_properties.tool = '".TABLE_FORUM_THREAD."' 
2111
                $groupCondition
2112
                $sessionCondition
2113
            LEFT JOIN $table_users users
2114
                ON thread.thread_poster_id = users.user_id
2115
            WHERE
2116
                item_properties.visibility='1' AND
2117
                thread.forum_id = ".intval($forum_id)." AND
2118
                thread.c_id = $courseId 
2119
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2120
2121
    if (api_is_allowed_to_edit()) {
2122
        $sql = "SELECT DISTINCT
2123
                    item_properties.*,
2124
                    users.firstname,
2125
                    users.lastname,
2126
                    users.user_id,
2127
                    thread.locked as locked,
2128
                    thread.*
2129
                FROM $table_threads thread
2130
                INNER JOIN $table_item_property item_properties
2131
                ON
2132
                    thread.thread_id = item_properties.ref AND
2133
                    item_properties.c_id = thread.c_id AND
2134
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
2135
                    $groupCondition
2136
                    $sessionCondition
2137
                LEFT JOIN $table_users users
2138
                    ON thread.thread_poster_id=users.user_id
2139
                WHERE
2140
                    item_properties.visibility<>2 AND
2141
                    thread.forum_id = ".intval($forum_id)." AND
2142
                    thread.c_id = $courseId 
2143
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2144
    }
2145
    $result = Database::query($sql);
2146
    $list = [];
2147
    $alreadyAdded = [];
2148
    while ($row = Database::fetch_array($result, 'ASSOC')) {
2149
        if (in_array($row['thread_id'], $alreadyAdded)) {
2150
            continue;
2151
        }
2152
        $list[] = $row;
2153
        $alreadyAdded[] = $row['thread_id'];
2154
    }
2155
2156
    return $list;
2157
}
2158
2159
/**
2160
 * Get a thread by Id and course id.
2161
 *
2162
 * @param int $threadId the thread Id
2163
 * @param int $cId      the course id
2164
 *
2165
 * @return array containing all the information about the thread
2166
 */
2167
function getThreadInfo($threadId, $cId)
2168
{
2169
    $repo = Database::getManager()->getRepository('ChamiloCourseBundle:CForumThread');
2170
    $forumThread = $repo->findOneBy(['threadId' => $threadId, 'cId' => $cId]);
2171
2172
    $thread = [];
2173
    if ($forumThread) {
2174
        $thread['threadId'] = $forumThread->getThreadId();
2175
        $thread['threadTitle'] = $forumThread->getThreadTitle();
2176
        $thread['forumId'] = $forumThread->getForum() ? $forumThread->getForum()->getIid() : 0;
2177
        $thread['sessionId'] = $forumThread->getSessionId();
2178
        $thread['threadSticky'] = $forumThread->getThreadSticky();
2179
        $thread['locked'] = $forumThread->getLocked();
2180
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
2181
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
2182
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
2183
        $thread['threadWeight'] = $forumThread->getThreadWeight();
2184
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
2185
    }
2186
2187
    return $thread;
2188
}
2189
2190
/**
2191
 * Retrieve all posts of a given thread.
2192
 *
2193
 * @param array  $forumInfo
2194
 * @param int    $threadId       The thread ID
2195
 * @param string $orderDirection Optional. The direction for sort the posts
2196
 * @param bool   $recursive      Optional. If the list is recursive
2197
 * @param int    $postId         Optional. The post ID for recursive list
2198
 * @param int    $depth          Optional. The depth to indicate the indent
2199
 *
2200
 * @todo move to a repository
2201
 *
2202
 * @return array containing all the information about the posts of a given thread
2203
 */
2204
function getPosts(
2205
    $forumInfo,
2206
    $threadId,
2207
    $orderDirection = 'ASC',
2208
    $recursive = false,
2209
    $postId = null,
2210
    $depth = -1
2211
) {
2212
    $em = Database::getManager();
2213
2214
    if (api_is_allowed_to_edit(false, true)) {
2215
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
2216
    } else {
2217
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
2218
    }
2219
2220
    $criteria = Criteria::create();
2221
    $criteria
2222
        ->where(Criteria::expr()->eq('thread', $threadId))
2223
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
2224
        ->andWhere($visibleCriteria)
2225
    ;
2226
2227
    $groupId = api_get_group_id();
2228
    $groupInfo = GroupManager::get_group_properties($groupId);
2229
    $filterModerated = true;
2230
2231
    if (empty($groupId)) {
2232
        if (api_is_allowed_to_edit()) {
2233
            $filterModerated = false;
2234
        }
2235
    } else {
2236
        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo) ||
2237
            api_is_allowed_to_edit(false, true)
2238
        ) {
2239
            $filterModerated = false;
2240
        }
2241
    }
2242
2243
    if ($recursive) {
2244
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
2245
    }
2246
2247
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
2248
    $qb->select('p')
2249
        ->addCriteria($criteria)
2250
        ->addOrderBy('p.postId', $orderDirection);
2251
2252
    if ($filterModerated && $forumInfo['moderated'] == 1) {
2253
        if (!api_is_allowed_to_edit(false, true)) {
2254
            $userId = api_get_user_id();
2255
            $qb->andWhere(
2256
                "p.status = 1 OR 
2257
                    (p.status = ".CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
2258
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
2259
                    (p.status IS NULL AND p.posterId = $userId) 
2260
                    "
2261
            );
2262
        }
2263
    }
2264
2265
    $posts = $qb->getQuery()->getResult();
2266
    $depth++;
2267
2268
    $list = [];
2269
    /** @var CForumPost $post */
2270
    foreach ($posts as $post) {
2271
        $postInfo = [
2272
            'iid' => $post->getIid(),
2273
            'c_id' => $post->getCId(),
2274
            'post_id' => $post->getPostId(),
2275
            'post_title' => $post->getPostTitle(),
2276
            'post_text' => $post->getPostText(),
2277
            'thread_id' => $post->getThread() ? $post->getThread()->getIid() : 0,
2278
            'forum_id' => $post->getForumId(),
2279
            'poster_id' => $post->getPosterId(),
2280
            'poster_name' => $post->getPosterName(),
2281
            'post_date' => $post->getPostDate(),
2282
            'post_notification' => $post->getPostNotification(),
2283
            'post_parent_id' => $post->getPostParentId(),
2284
            'visible' => $post->getVisible(),
2285
            'status' => $post->getStatus(),
2286
            'indent_cnt' => $depth,
2287
        ];
2288
2289
        $posterId = $post->getPosterId();
2290
        if (!empty($posterId)) {
2291
            $user = api_get_user_entity($posterId);
2292
            if ($user) {
2293
                $postInfo['user_id'] = $user->getUserId();
2294
                $postInfo['username'] = $user->getUsername();
2295
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
2296
                $postInfo['lastname'] = $user->getLastname();
2297
                $postInfo['firstname'] = $user->getFirstname();
2298
                $postInfo['complete_name'] = UserManager::formatUserFullName($user);
2299
            }
2300
        }
2301
2302
        $list[] = $postInfo;
2303
2304
        if (!$recursive) {
2305
            continue;
2306
        }
2307
        $list = array_merge(
2308
            $list,
2309
            getPosts(
2310
                $forumInfo,
2311
                $threadId,
2312
                $orderDirection,
2313
                $recursive,
2314
                $post->getPostId(),
2315
                $depth
2316
            )
2317
        );
2318
    }
2319
2320
    return $list;
2321
}
2322
2323
/**
2324
 * This function retrieves all the information of a post.
2325
 *
2326
 * @param int $post_id integer that indicates the forum
2327
 *
2328
 * @return array returns
2329
 *
2330
 * @author Patrick Cool <[email protected]>, Ghent University
2331
 *
2332
 * @version february 2006, dokeos 1.8
2333
 */
2334
function get_post_information($post_id)
2335
{
2336
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
2337
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2338
    $course_id = api_get_course_int_id();
2339
    $post_id = (int) $post_id;
2340
2341
    if (empty($post_id)) {
2342
        return [];
2343
    }
2344
2345
    $sql = "SELECT posts.*, email FROM ".$table_posts." posts, ".$table_users." users
2346
            WHERE
2347
                c_id = $course_id AND
2348
                posts.poster_id=users.user_id AND
2349
                posts.post_id = ".$post_id;
2350
    $result = Database::query($sql);
2351
    $row = Database::fetch_array($result, 'ASSOC');
2352
2353
    return $row;
2354
}
2355
2356
/**
2357
 * This function retrieves all the information of a thread.
2358
 *
2359
 * @param int $forumId
2360
 * @param $thread_id integer that indicates the forum
2361
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2362
 *
2363
 * @return array returns
2364
 *
2365
 * @author Patrick Cool <[email protected]>, Ghent University
2366
 *
2367
 * @version february 2006, dokeos 1.8
2368
 */
2369
function get_thread_information($forumId, $thread_id, $sessionId = null)
2370
{
2371
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2372
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2373
    $thread_id = intval($thread_id);
2374
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
2375
    $sessionCondition = api_get_session_condition(
2376
        $sessionId,
2377
        true,
2378
        false,
2379
        'threads.session_id'
2380
    );
2381
    $forumCondition = '';
2382
    if (!empty($forumId)) {
2383
        $forumId = (int) $forumId;
2384
        $forumCondition = " threads.forum_id = $forumId AND ";
2385
    }
2386
    $sql = "SELECT * FROM $table_item_property item_properties
2387
            INNER JOIN
2388
            $table_threads threads
2389
            ON (item_properties.ref = threads.thread_id AND threads.c_id = item_properties.c_id)
2390
            WHERE
2391
                $forumCondition
2392
                item_properties.tool= '".TOOL_FORUM_THREAD."' AND                
2393
                threads.thread_id = $thread_id 
2394
                $sessionCondition
2395
            ";
2396
2397
    $result = Database::query($sql);
2398
    $row = Database::fetch_assoc($result);
2399
2400
    return $row;
2401
}
2402
2403
/**
2404
 * This function retrieves forum thread users details.
2405
 *
2406
 * @param   int Thread ID
2407
 * @param   string  Course DB name (optional)
2408
 *
2409
 * @return Doctrine\DBAL\Driver\Statement|null array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2410
 *
2411
 * @author Christian Fasanando <[email protected]>,
2412
 *
2413
 * @todo     this function need to be improved
2414
 *
2415
 * @version octubre 2008, dokeos 1.8
2416
 */
2417
function get_thread_users_details($thread_id)
2418
{
2419
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2420
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2421
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2422
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2423
2424
    $course_id = api_get_course_int_id();
2425
2426
    $is_western_name_order = api_is_western_name_order();
2427
    if ($is_western_name_order) {
2428
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2429
    } else {
2430
        $orderby = 'ORDER BY user.lastname, user.firstname';
2431
    }
2432
2433
    if (api_get_session_id()) {
2434
        $session_info = api_get_session_info(api_get_session_id());
2435
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2436
        //not showing coaches
2437
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2438
                FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2439
                WHERE 
2440
                    p.poster_id = user.id AND
2441
                    user.id = session_rel_user_rel_course.user_id AND
2442
                    session_rel_user_rel_course.status<>'2' AND
2443
                    session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2444
                    p.thread_id = ".intval($thread_id)." AND
2445
                    session_id = ".api_get_session_id()." AND
2446
                    p.c_id = $course_id AND
2447
                    session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2448
    } else {
2449
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2450
                FROM $t_posts p, $t_users user, $t_course_user course_user
2451
                WHERE 
2452
                    p.poster_id = user.id
2453
                    AND user.id = course_user.user_id
2454
                    AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2455
                    AND p.thread_id = ".intval($thread_id)."
2456
                    AND course_user.status NOT IN('1') AND
2457
                    p.c_id = $course_id AND
2458
                    course_user.c_id = ".$course_id." $orderby";
2459
    }
2460
    $result = Database::query($sql);
2461
2462
    return $result;
2463
}
2464
2465
/**
2466
 * This function retrieves forum thread users qualify.
2467
 *
2468
 * @param   int Thread ID
2469
 * @param   string  Course DB name (optional)
2470
 *
2471
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2472
 *
2473
 * @author Jhon Hinojosa
2474
 *
2475
 * @todo     this function need to be improved
2476
 */
2477
function get_thread_users_qualify($thread_id)
2478
{
2479
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2480
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2481
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2482
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2483
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2484
2485
    $course_id = api_get_course_int_id();
2486
    $sessionId = api_get_session_id();
2487
2488
    $is_western_name_order = api_is_western_name_order();
2489
    if ($is_western_name_order) {
2490
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2491
    } else {
2492
        $orderby = 'ORDER BY user.lastname, user.firstname';
2493
    }
2494
2495
    if ($sessionId) {
2496
        $session_info = api_get_session_info($sessionId);
2497
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2498
        //not showing coaches
2499
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2500
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2501
                WHERE poster_id = user.id
2502
                    AND post.poster_id = qualify.user_id
2503
                    AND user.id = scu.user_id
2504
                    AND scu.status<>'2'
2505
                    AND scu.user_id NOT IN ($user_to_avoid)
2506
                    AND qualify.thread_id = ".intval($thread_id)."
2507
                    AND post.thread_id = ".intval($thread_id)."
2508
                    AND scu.session_id = $sessionId
2509
                    AND scu.c_id = ".$course_id." AND
2510
                    qualify.c_id = $course_id AND
2511
                    post.c_id = $course_id
2512
                $orderby ";
2513
    } else {
2514
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2515
                FROM $t_posts post,
2516
                     $t_qualify qualify,
2517
                     $t_users user,
2518
                     $t_course_user course_user
2519
                WHERE
2520
                     post.poster_id = user.id
2521
                     AND post.poster_id = qualify.user_id
2522
                     AND user.id = course_user.user_id
2523
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2524
                     AND qualify.thread_id = ".intval($thread_id)."
2525
                     AND post.thread_id = ".intval($thread_id)."
2526
                     AND course_user.status not in('1')
2527
                     AND course_user.c_id = $course_id
2528
                     AND qualify.c_id = $course_id
2529
                     AND post.c_id = $course_id
2530
                 $orderby ";
2531
    }
2532
    $result = Database::query($sql);
2533
2534
    return $result;
2535
}
2536
2537
/**
2538
 * This function retrieves forum thread users not qualify.
2539
 *
2540
 * @param   int Thread ID
2541
 * @param   string  Course DB name (optional)
2542
 *
2543
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2544
 *
2545
 * @author   Jhon Hinojosa<[email protected]>,
2546
 *
2547
 * @version oct 2008, dokeos 1.8
2548
 */
2549
function get_thread_users_not_qualify($thread_id)
2550
{
2551
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2552
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2553
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2554
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2555
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2556
2557
    $is_western_name_order = api_is_western_name_order();
2558
    if ($is_western_name_order) {
2559
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2560
    } else {
2561
        $orderby = 'ORDER BY user.lastname, user.firstname';
2562
    }
2563
2564
    $course_id = api_get_course_int_id();
2565
2566
    $sql1 = "SELECT user_id FROM  $t_qualify
2567
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2568
    $result1 = Database::query($sql1);
2569
    $cad = '';
2570
    while ($row = Database::fetch_array($result1)) {
2571
        $cad .= $row['user_id'].',';
2572
    }
2573
    if ($cad == '') {
2574
        $cad = '0';
2575
    } else {
2576
        $cad = substr($cad, 0, strlen($cad) - 1);
2577
    }
2578
2579
    if (api_get_session_id()) {
2580
        $session_info = api_get_session_info(api_get_session_id());
2581
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2582
        //not showing coaches
2583
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2584
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2585
                WHERE poster_id = user.id
2586
                    AND user.id NOT IN (".$cad.")
2587
                    AND user.id = session_rel_user_rel_course.user_id
2588
                    AND session_rel_user_rel_course.status<>'2'
2589
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2590
                    AND post.thread_id = ".intval($thread_id)."
2591
                    AND session_id = ".api_get_session_id()."
2592
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2593
    } else {
2594
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2595
                FROM $t_posts post, $t_users user,$t_course_user course_user
2596
                WHERE post.poster_id = user.id
2597
                AND user.id NOT IN (".$cad.")
2598
                AND user.id = course_user.user_id
2599
                AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2600
                AND post.thread_id = ".intval($thread_id)."
2601
                AND course_user.status not in('1')
2602
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2603
    }
2604
    $result = Database::query($sql);
2605
2606
    return $result;
2607
}
2608
2609
/**
2610
 * This function retrieves all the information of a given forum_id.
2611
 *
2612
 * @param $forum_id integer that indicates the forum
2613
 *
2614
 * @return array returns
2615
 *
2616
 * @author Patrick Cool <[email protected]>, Ghent University
2617
 *
2618
 * @version february 2006, dokeos 1.8
2619
 *
2620
 * @deprecated this functionality is now moved to get_forums($forum_id)
2621
 */
2622
function get_forum_information($forum_id, $courseId = 0)
2623
{
2624
    $table_forums = Database::get_course_table(TABLE_FORUM);
2625
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2626
    $courseId = empty($courseId) ? api_get_course_int_id() : intval($courseId);
2627
    $forum_id = intval($forum_id);
2628
2629
    $sql = "SELECT *
2630
            FROM $table_forums forums
2631
            INNER JOIN $table_item_property item_properties
2632
            ON (forums.c_id = item_properties.c_id)
2633
            WHERE
2634
                item_properties.tool = '".TOOL_FORUM."' AND
2635
                item_properties.ref = '".$forum_id."' AND
2636
                forums.forum_id = '".$forum_id."' AND
2637
                forums.c_id = ".$courseId."
2638
            ";
2639
2640
    $result = Database::query($sql);
2641
    $row = Database::fetch_array($result, 'ASSOC');
2642
    $row['approval_direct_post'] = 0;
2643
    // We can't anymore change this option, so it should always be activated.
2644
2645
    return $row;
2646
}
2647
2648
/**
2649
 * This function retrieves all the information of a given forumcategory id.
2650
 *
2651
 * @param $cat_id integer that indicates the forum
2652
 *
2653
 * @return array returns if there are category or bool returns if there aren't category
2654
 *
2655
 * @author Patrick Cool <[email protected]>, Ghent University
2656
 *
2657
 * @version february 2006, dokeos 1.8
2658
 */
2659
function get_forumcategory_information($cat_id)
2660
{
2661
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2662
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2663
2664
    $course_id = api_get_course_int_id();
2665
    $sql = "SELECT *
2666
            FROM $table_categories forumcategories 
2667
            INNER JOIN $table_item_property item_properties
2668
            ON (forumcategories.c_id = item_properties.c_id)
2669
            WHERE
2670
                forumcategories.c_id = $course_id AND
2671
                item_properties.c_id = $course_id AND
2672
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2673
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2674
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2675
    $result = Database::query($sql);
2676
    $row = Database::fetch_array($result);
2677
2678
    return $row;
2679
}
2680
2681
/**
2682
 * This function counts the number of forums inside a given category.
2683
 *
2684
 * @param int $cat_id the id of the forum category
2685
 *
2686
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
2687
 *      of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2688
 *
2689
 * @return int the number of forums inside the given category
2690
 *
2691
 * @author Patrick Cool <[email protected]>, Ghent University
2692
 *
2693
 * @version february 2006, dokeos 1.8
2694
 */
2695
function count_number_of_forums_in_category($cat_id)
2696
{
2697
    $table_forums = Database::get_course_table(TABLE_FORUM);
2698
    $course_id = api_get_course_int_id();
2699
    $cat_id = (int) $cat_id;
2700
    $sql = "SELECT count(*) AS number_of_forums
2701
            FROM $table_forums
2702
            WHERE c_id = $course_id AND forum_category = $cat_id";
2703
    $result = Database::query($sql);
2704
    $row = Database::fetch_array($result);
2705
2706
    return $row['number_of_forums'];
2707
}
2708
2709
/**
2710
 * This function update a thread.
2711
 *
2712
 * @param array $values - The form Values
2713
 */
2714
function updateThread($values)
2715
{
2716
    if (!api_is_allowed_to_edit()) {
2717
        return '';
2718
    }
2719
2720
    $logInfo = [
2721
        'tool' => TOOL_FORUM,
2722
        'tool_id' => $values['forum_id'],
2723
        'tool_id_detail' => $values['thread_id'],
2724
        'action' => 'edit-thread',
2725
        'action_details' => 'thread',
2726
        'info' => $values['thread_title'],
2727
    ];
2728
    Event::registerLog($logInfo);
2729
2730
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2731
    $courseId = api_get_course_int_id();
2732
    $courseCode = api_get_course_id();
2733
    $sessionId = api_get_session_id();
2734
2735
    // Simple update + set gradebook values to null
2736
    $params = [
2737
        'thread_title' => $values['thread_title'],
2738
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
2739
    ];
2740
    $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2741
    Database::update($threadTable, $params, $where);
2742
2743
    $id = $values['thread_id'];
2744
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2745
        $courseCode,
2746
        LINK_FORUM_THREAD,
2747
        $id,
2748
        $sessionId
2749
    );
2750
    $linkId = $linkInfo['id'];
2751
    $em = Database::getManager();
2752
    $gradebookLink = null;
2753
    if (!empty($linkId)) {
2754
        $gradebookLink = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($linkId);
2755
    }
2756
2757
    // values 1 or 0
2758
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2759
    if ($check) {
2760
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2761
        $value = isset($values['numeric_calification']) ? intval($values['numeric_calification']) : 0;
2762
        $weight = isset($values['weight_calification']) ? floatval($values['weight_calification']) : 0;
2763
        $description = '';
2764
        // Update title
2765
        $params = [
2766
            'thread_title_qualify' => $values['calification_notebook_title'],
2767
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2768
            'thread_weight' => api_float_val($values['weight_calification']),
2769
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2770
        ];
2771
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2772
        Database::update($threadTable, $params, $where);
2773
2774
        if (!$linkInfo) {
2775
            GradebookUtils::add_resource_to_course_gradebook(
2776
                $values['category_id'],
2777
                $courseCode,
2778
                LINK_FORUM_THREAD,
2779
                $id,
2780
                $title,
2781
                $weight,
2782
                $value,
2783
                $description,
2784
                1,
2785
                $sessionId
2786
            );
2787
        } else {
2788
            if ($gradebookLink) {
2789
                $gradebookLink->setWeight($weight);
2790
                $em->persist($gradebookLink);
2791
                $em->flush();
2792
            }
2793
        }
2794
    } else {
2795
        $params = [
2796
            'thread_title_qualify' => '',
2797
            'thread_qualify_max' => 0,
2798
            'thread_weight' => 0,
2799
            'thread_peer_qualify' => 0,
2800
        ];
2801
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2802
        Database::update($threadTable, $params, $where);
2803
2804
        if (!empty($linkInfo)) {
2805
            if ($gradebookLink) {
2806
                $em->remove($gradebookLink);
2807
                $em->flush();
2808
            }
2809
        }
2810
    }
2811
2812
    $message = get_lang('EditPostStored').'<br />';
2813
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2814
}
2815
2816
/**
2817
 * This function stores a new thread. This is done through an entry in the forum_thread table AND
2818
 * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet)).
2819
 *
2820
 * @param array $current_forum
2821
 * @param array $values
2822
 * @param array $courseInfo
2823
 * @param bool  $showMessage
2824
 * @param int   $userId        Optional. The user ID
2825
 * @param int   $sessionId
2826
 *
2827
 * @return CForumThread
2828
 *
2829
 * @author Patrick Cool <[email protected]>, Ghent University
2830
 *
2831
 * @version february 2006, dokeos 1.8
2832
 */
2833
function store_thread(
2834
    $current_forum,
2835
    $values,
2836
    $courseInfo = [],
2837
    $showMessage = true,
2838
    $userId = 0,
2839
    $sessionId = 0
2840
) {
2841
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2842
    $userId = $userId ?: api_get_user_id();
2843
    $course_id = $courseInfo['real_id'];
2844
    $courseCode = $courseInfo['code'];
2845
    $groupId = api_get_group_id();
2846
    $groupInfo = GroupManager::get_group_properties($groupId);
2847
    $sessionId = $sessionId ?: api_get_session_id();
2848
2849
    $em = Database::getManager();
2850
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2851
    $upload_ok = 1;
2852
    $has_attachment = false;
2853
2854
    if (!empty($_FILES['user_upload']['name'])) {
2855
        $upload_ok = process_uploaded_file($_FILES['user_upload']);
2856
        $has_attachment = true;
2857
    }
2858
2859
    if (!$upload_ok) {
2860
        if ($showMessage) {
2861
            Display::addFlash(
2862
                Display::return_message(
2863
                    get_lang('UplNoFileUploaded'),
2864
                    'error',
2865
                    false
2866
                )
2867
            );
2868
        }
2869
2870
        return null;
2871
    }
2872
2873
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2874
    $visible = 1;
2875
    if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
2876
        $visible = 0; // The post has not been approved yet.
2877
    }
2878
    $clean_post_title = $values['post_title'];
2879
2880
    $forum = $em->find('ChamiloCourseBundle:CForumForum', $values['forum_id']);
2881
2882
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2883
    $lastThread = new CForumThread();
2884
    $lastThread
2885
        ->setCId($course_id)
2886
        ->setThreadTitle($clean_post_title)
2887
        ->setForum($forum)
2888
        ->setThreadPosterId($userId)
2889
        ->setThreadPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2890
        ->setThreadDate($post_date)
2891
        ->setThreadSticky(isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
2892
        ->setThreadTitleQualify(
2893
            isset($values['calification_notebook_title']) ? $values['calification_notebook_title'] : null
2894
        )
2895
        ->setThreadQualifyMax(isset($values['numeric_calification']) ? (int) $values['numeric_calification'] : 0)
2896
        ->setThreadWeight(isset($values['weight_calification']) ? (int) $values['weight_calification'] : 0)
2897
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2898
        ->setSessionId($sessionId)
2899
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2900
        ->setThreadId(0)
2901
        ->setLocked(0)
2902
    ;
2903
2904
    $em->persist($lastThread);
2905
    $em->flush();
2906
2907
    // Add option gradebook qualify.
2908
    if (isset($values['thread_qualify_gradebook']) &&
2909
        1 == $values['thread_qualify_gradebook']
2910
    ) {
2911
        // Add function gradebook.
2912
        $resourcename = stripslashes($values['calification_notebook_title']);
2913
        GradebookUtils::add_resource_to_course_gradebook(
2914
            $values['category_id'],
2915
            $courseCode,
2916
            5,
2917
            $lastThread->getIid(),
2918
            $resourcename,
2919
            $values['weight_calification'],
2920
            $values['numeric_calification'],
2921
            '',
2922
            0,
2923
            $sessionId
2924
        );
2925
    }
2926
2927
    if ($lastThread->getIid()) {
2928
        $lastThread->setThreadId($lastThread->getIid());
2929
2930
        $em->merge($lastThread);
2931
        $em->flush();
2932
2933
        api_item_property_update(
2934
            $courseInfo,
2935
            TOOL_FORUM_THREAD,
2936
            $lastThread->getIid(),
2937
            'ForumThreadAdded',
2938
            $userId,
2939
            $groupInfo,
2940
            null,
2941
            null,
2942
            null,
2943
            $sessionId
2944
        );
2945
2946
        // If the forum properties tell that the posts have to be approved
2947
        // we have to put the whole thread invisible,
2948
        // because otherwise the students will see the thread and not the post
2949
        // in the thread.
2950
        // We also have to change $visible because the post itself has to be
2951
        // visible in this case (otherwise the teacher would have
2952
        // to make the thread visible AND the post.
2953
        // Default behaviour
2954
        api_set_default_visibility(
2955
            $lastThread->getIid(),
2956
            TOOL_FORUM_THREAD,
2957
            $groupId,
2958
            $courseInfo,
2959
            $sessionId,
2960
            $userId
2961
        );
2962
2963
        if ($visible == 0) {
2964
            api_item_property_update(
2965
                $courseInfo,
2966
                TOOL_FORUM_THREAD,
2967
                $lastThread->getIid(),
2968
                'invisible',
2969
                $userId,
2970
                $groupInfo
2971
            );
2972
            $visible = 1;
2973
        }
2974
2975
        $logInfo = [
2976
            'tool' => TOOL_FORUM,
2977
            'tool_id' => $values['forum_id'],
2978
            'tool_id_detail' => $lastThread->getIid(),
2979
            'action' => 'new-thread',
2980
            'action_details' => '',
2981
            'info' => $clean_post_title,
2982
        ];
2983
        Event::registerLog($logInfo);
2984
    }
2985
2986
    // We now store the content in the table_post table.
2987
    $lastPost = new CForumPost();
2988
    $lastPost
2989
        ->setCId($course_id)
2990
        ->setPostTitle($clean_post_title)
2991
        ->setPostText($values['post_text'])
2992
        ->setThread($lastThread)
2993
        ->setForumId($values['forum_id'])
2994
        ->setPosterId($userId)
2995
        ->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2996
        ->setPostDate($post_date)
2997
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
2998
        ->setPostParentId(null)
2999
        ->setVisible($visible)
3000
        ->setPostId(0)
3001
        ->setStatus(CForumPost::STATUS_VALIDATED);
3002
3003
    if ($current_forum['moderated']) {
3004
        $lastPost->setStatus(
3005
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
3006
        );
3007
    }
3008
3009
    $em->persist($lastPost);
3010
    $em->flush();
3011
3012
    $lastPostId = $lastPost->getIid();
3013
3014
    $lastThread->setThreadLastPost($lastPostId);
3015
3016
    $em->merge($lastThread);
3017
    $em->flush();
3018
3019
    $logInfo = [
3020
        'tool' => TOOL_FORUM,
3021
        'tool_id' => $values['forum_id'],
3022
        'tool_id_detail' => $lastThread->getIid(),
3023
        'action' => 'new-post',
3024
        'info' => $clean_post_title,
3025
    ];
3026
    Event::registerLog($logInfo);
3027
3028
    if ($lastPostId) {
3029
        $lastPost->setPostId($lastPostId);
3030
        $em->merge($lastPost);
3031
        $em->flush();
3032
    }
3033
3034
    // Update attached files
3035
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3036
        foreach ($_POST['file_ids'] as $key => $id) {
3037
            editAttachedFile(
3038
                [
3039
                    'comment' => $_POST['file_comments'][$key],
3040
                    'post_id' => $lastPostId,
3041
                ],
3042
                $id
3043
            );
3044
        }
3045
    }
3046
3047
    // Now we have to update the thread table to fill the thread_last_post
3048
    // field (so that we know when the thread has been updated for the last time).
3049
    $sql = "UPDATE $table_threads
3050
            SET thread_last_post = '".Database::escape_string($lastPostId)."'
3051
            WHERE
3052
                c_id = $course_id AND
3053
                thread_id='".Database::escape_string($lastThread->getIid())."'";
3054
    $result = Database::query($sql);
3055
    $message = get_lang('NewThreadStored');
3056
3057
    // Overwrite default message.
3058
    if ($current_forum['moderated'] &&
3059
        !api_is_allowed_to_edit(null, true)
3060
    ) {
3061
        $message = get_lang('MessageHasToBeApproved');
3062
    }
3063
3064
    // Storing the attachments if any.
3065
    if ($has_attachment) {
3066
        // Try to add an extension to the file if it hasn't one.
3067
        $new_file_name = add_ext_on_mime(
3068
            stripslashes($_FILES['user_upload']['name']),
3069
            $_FILES['user_upload']['type']
3070
        );
3071
3072
        if (!filter_extension($new_file_name)) {
3073
            if ($showMessage) {
3074
                Display::addFlash(Display::return_message(
3075
                    get_lang('UplUnableToSaveFileFilteredExtension'),
3076
                    'error'
3077
                ));
3078
            }
3079
        } else {
3080
            if ($result) {
3081
                add_forum_attachment_file(
3082
                    isset($values['file_comment']) ? $values['file_comment'] : null,
3083
                    $lastPostId
3084
                );
3085
            }
3086
        }
3087
    } else {
3088
        $message .= '<br />';
3089
    }
3090
3091
    if ($current_forum['approval_direct_post'] == '1' &&
3092
        !api_is_allowed_to_edit(null, true)
3093
    ) {
3094
        $message .= get_lang('MessageHasToBeApproved').'<br />';
3095
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3096
            get_lang('Forum').'</a><br />';
3097
    } else {
3098
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3099
            get_lang('Forum').'</a><br />';
3100
        $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&thread='.$lastThread->getIid().'">'.
3101
            get_lang('Message').'</a>';
3102
    }
3103
    $reply_info['new_post_id'] = $lastPostId;
3104
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3105
3106
    if ($my_post_notification == 1) {
3107
        set_notification('thread', $lastThread->getIid(), true);
3108
    }
3109
3110
    send_notification_mails(
3111
        $current_forum['forum_id'],
3112
        $lastThread->getIid(),
3113
        $reply_info,
3114
        $courseInfo['code']
3115
    );
3116
3117
    Session::erase('formelements');
3118
    Session::erase('origin');
3119
    Session::erase('breadcrumbs');
3120
    Session::erase('addedresource');
3121
    Session::erase('addedresourceid');
3122
3123
    if ($showMessage) {
3124
        Display::addFlash(Display::return_message($message, 'success', false));
3125
    }
3126
3127
    return $lastThread;
3128
}
3129
3130
/**
3131
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
3132
 *
3133
 * @param array  $current_forum
3134
 * @param string $action        is the parameter that determines if we are
3135
 *                              1. newthread: adding a new thread (both empty) => No I-frame
3136
 *                              2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
3137
 *                              3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled)
3138
 *                              (I first thought to put and I-frame with the message only)
3139
 *                              4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled).
3140
 *                              The message will be in the reply. (I first thought not to put an I-frame here)
3141
 * @param array  $form_values
3142
 * @param bool   $showPreview
3143
 *
3144
 * @return FormValidator
3145
 *
3146
 * @author Patrick Cool <[email protected]>, Ghent University
3147
 *
3148
 * @version february 2006, dokeos 1.8
3149
 */
3150
function show_add_post_form($current_forum, $action, $form_values = '', $showPreview = true)
3151
{
3152
    $_user = api_get_user_info();
3153
    $action = isset($action) ? Security::remove_XSS($action) : '';
3154
    $myThread = isset($_GET['thread']) ? (int) $_GET['thread'] : '';
3155
    $forumId = isset($_GET['forum']) ? (int) $_GET['forum'] : '';
3156
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
3157
    $giveRevision = isset($_GET['give_revision']) && $_GET['give_revision'] == 1;
3158
3159
    $url = api_get_self().'?'.http_build_query(
3160
        [
3161
            'action' => $action,
3162
            'forum' => $forumId,
3163
            'thread' => $myThread,
3164
            'post' => $my_post,
3165
        ]
3166
    ).'&'.api_get_cidreq();
3167
3168
    $form = new FormValidator(
3169
        'thread',
3170
        'post',
3171
        $url
3172
    );
3173
3174
    $form->setConstants(['forum' => '5']);
3175
3176
    // Setting the form elements.
3177
    $form->addElement('hidden', 'forum_id', $forumId);
3178
    $form->addElement('hidden', 'thread_id', $myThread);
3179
    $form->addElement('hidden', 'action', $action);
3180
3181
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
3182
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
3183
        $form->addElement('text', 'poster_name', get_lang('Name'));
3184
        $form->applyFilter('poster_name', 'html_filter');
3185
    }
3186
3187
    $form->addElement('text', 'post_title', get_lang('Title'));
3188
    $form->addHtmlEditor(
3189
        'post_text',
3190
        get_lang('Text'),
3191
        true,
3192
        false,
3193
        api_is_allowed_to_edit(null, true) ? [
3194
            'ToolbarSet' => 'Forum',
3195
            'Width' => '100%',
3196
            'Height' => '300',
3197
        ] : [
3198
            'ToolbarSet' => 'ForumStudent',
3199
            'Width' => '100%',
3200
            'Height' => '300',
3201
            'UserStatus' => 'student',
3202
        ]
3203
    );
3204
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
3205
3206
    if (in_array($action, ['newthread', 'replythread', 'replymessage', 'quote'])) {
3207
        $extraFields = new ExtraField('forum_post');
3208
        $extraFields->addElements(
3209
            $form,
3210
            null,
3211
            [], //exclude
3212
            false, // filter
3213
            false, // tag as select
3214
            ['ask_for_revision'], //show only fields
3215
            [], // order fields
3216
            [] // extra data);
3217
        );
3218
    }
3219
3220
    $iframe = null;
3221
    if ($showPreview) {
3222
        $myThread = Security::remove_XSS($myThread);
3223
        if ($action != 'newthread' && !empty($myThread)) {
3224
            $iframe = "<iframe style=\"border: 1px solid black\" src=\"iframe_thread.php?".api_get_cidreq(
3225
                )."&forum=".$forumId."&thread=".$myThread."#".$my_post."\" width=\"100%\"></iframe>";
3226
        }
3227
        if (!empty($iframe)) {
3228
            $form->addElement('label', get_lang('Thread'), $iframe);
3229
        }
3230
    }
3231
3232
    if (Gradebook::is_active() &&
3233
        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor()) && !($myThread)
3234
    ) {
3235
        $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
3236
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3237
3238
        // Thread qualify
3239
        if (Gradebook::is_active()) {
3240
            //Loading gradebook select
3241
            GradebookUtils::load_gradebook_select_in_tool($form);
3242
            $form->addElement(
3243
                'checkbox',
3244
                'thread_qualify_gradebook',
3245
                '',
3246
                get_lang('QualifyThreadGradebook'),
3247
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
3248
            );
3249
        } else {
3250
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
3251
        }
3252
3253
        $form->addElement('html', '<div id="options_field" style="display:none">');
3254
        $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
3255
        $form->applyFilter('numeric_calification', 'html_filter');
3256
        $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
3257
        $form->applyFilter('calification_notebook_title', 'html_filter');
3258
3259
        $form->addElement(
3260
            'text',
3261
            'weight_calification',
3262
            get_lang('QualifyWeight'),
3263
            ['value' => '0.00', 'onfocus' => "javascript: this.select();"]
3264
        );
3265
        $form->applyFilter('weight_calification', 'html_filter');
3266
3267
        $group = [];
3268
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
3269
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
3270
        $form->addGroup(
3271
            $group,
3272
            '',
3273
            [
3274
                get_lang('ForumThreadPeerScoring'),
3275
                get_lang('ForumThreadPeerScoringComment'),
3276
            ]
3277
        );
3278
        $form->addElement('html', '</div>');
3279
        $form->addElement('html', '</div>');
3280
    }
3281
3282
    if ($action === 'newthread') {
3283
        Skill::addSkillsToForm($form, ITEM_TYPE_FORUM_THREAD, 0);
3284
    }
3285
3286
    if (api_is_allowed_to_edit(null, true) && $action == 'newthread') {
3287
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
3288
    }
3289
3290
    if (in_array($action, ['quote', 'replymessage'])) {
3291
        $form->addFile('user_upload[]', get_lang('Attachment'));
3292
        $form->addButton(
3293
            'add_attachment',
3294
            get_lang('AddAttachment'),
3295
            'paperclip',
3296
            'default',
3297
            'default',
3298
            null,
3299
            ['id' => 'reply-add-attachment']
3300
        );
3301
    } else {
3302
        $form->addFile('user_upload', get_lang('Attachment'));
3303
    }
3304
3305
    if ($giveRevision) {
3306
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
3307
        $form->addHidden('give_revision', 1);
3308
        if ($hide === false) {
3309
            $extraField = new ExtraField('forum_post');
3310
            $extraField->addElements(
3311
                $form,
3312
                null,
3313
                [], //exclude
3314
                false, // filter
3315
                false, // tag as select
3316
                ['revision_language'], //show only fields
3317
                [], // order fields
3318
                [] // extra data
3319
            );
3320
        } else {
3321
            $form->addHidden('extra_revision_language', 1);
3322
        }
3323
    }
3324
3325
    // Setting the class and text of the form title and submit button.
3326
    if ($action == 'quote') {
3327
        $form->addButtonCreate(get_lang('QuoteMessage'), 'SubmitPost');
3328
    } elseif ($action == 'replythread') {
3329
        $form->addButtonCreate(get_lang('ReplyToThread'), 'SubmitPost');
3330
    } elseif ($action == 'replymessage') {
3331
        $form->addButtonCreate(get_lang('ReplyToMessage'), 'SubmitPost');
3332
    } else {
3333
        $form->addButtonCreate(get_lang('CreateThread'), 'SubmitPost');
3334
    }
3335
3336
    $defaults['thread_peer_qualify'] = 0;
3337
    if (!empty($form_values)) {
3338
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3339
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3340
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3341
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3342
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3343
    }
3344
3345
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
3346
    // we can add this as default to the textarea.
3347
    // We also need to put the parent_id of the post in a hidden form when
3348
    if (($action == 'quote' || $action == 'replymessage' || $giveRevision) && !empty($my_post)) {
3349
        // we are quoting or replying to a message (<> reply to a thread !!!)
3350
        $form->addHidden('post_parent_id', $my_post);
3351
3352
        // If we are replying or are quoting then we display a default title.
3353
        $values = get_post_information($my_post);
3354
        $posterInfo = api_get_user_info($values['poster_id']);
3355
        $posterName = '';
3356
        if ($posterInfo) {
3357
            $posterName = $posterInfo['complete_name'];
3358
        }
3359
        $defaults['post_title'] = get_lang('ReplyShort').api_html_entity_decode($values['post_title'], ENT_QUOTES);
3360
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
3361
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
3362
        if ($action == 'quote') {
3363
            $defaults['post_text'] = '<div>&nbsp;</div>
3364
                <div style="margin: 5px;">
3365
                    <div style="font-size: 90%; font-style: italic;">'.
3366
                get_lang('Quoting').' '.$posterName.':</div>
3367
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
3368
                prepare4display($values['post_text']).'
3369
                        </div>
3370
                    </div>
3371
                <div>&nbsp;</div>
3372
                <div>&nbsp;</div>
3373
            ';
3374
        }
3375
        if ($giveRevision) {
3376
            $defaults['post_text'] = prepare4display($values['post_text']);
3377
        }
3378
    }
3379
3380
    $form->setDefaults(isset($defaults) ? $defaults : []);
3381
3382
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3383
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
3384
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
3385
        $form->addRule(
3386
            'poster_name',
3387
            get_lang('ThisFieldIsRequired'),
3388
            'required'
3389
        );
3390
    }
3391
3392
    // Validation or display
3393
    if ($form->validate()) {
3394
        $check = Security::check_token('post');
3395
        if ($check) {
3396
            $values = $form->getSubmitValues();
3397
            if (isset($values['thread_qualify_gradebook']) &&
3398
                $values['thread_qualify_gradebook'] == '1' &&
3399
                empty($values['weight_calification'])
3400
            ) {
3401
                Display::addFlash(
3402
                    Display::return_message(
3403
                        get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3404
                        'error',
3405
                        false
3406
                    )
3407
                );
3408
3409
                return false;
3410
            }
3411
3412
            $postId = 0;
3413
            $threadId = 0;
3414
3415
            switch ($action) {
3416
                case 'newthread':
3417
                    $myThread = store_thread($current_forum, $values);
3418
                    if ($myThread) {
3419
                        $threadId = $myThread->getIid();
3420
                        Skill::saveSkills($form, ITEM_TYPE_FORUM_THREAD, $threadId);
3421
                        $postId = $myThread->getThreadLastPost();
3422
                    }
3423
                    break;
3424
                case 'quote':
3425
                case 'replythread':
3426
                case 'replymessage':
3427
                    $postId = store_reply($current_forum, $values);
3428
                    break;
3429
            }
3430
3431
            if ($postId) {
3432
                $postInfo = get_post_information($postId);
3433
                if ($postInfo) {
3434
                    $threadId = $postInfo['thread_id'];
3435
                }
3436
3437
                if (isset($values['give_revision']) && $values['give_revision'] == 1) {
3438
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3439
                    $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3440
3441
                    $params = [
3442
                        'item_id' => $postId,
3443
                        'extra_revision_language' => $revisionLanguage,
3444
                    ];
3445
3446
                    $extraFieldValues->saveFieldValues(
3447
                        $params,
3448
                        false,
3449
                        false,
3450
                        ['revision_language']
3451
                    );
3452
                }
3453
3454
                if (in_array($action, ['newthread', 'replythread', 'replymessage', 'quote'])) {
3455
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3456
                    $params = [
3457
                        'item_id' => $postId,
3458
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3459
                    ];
3460
                    $extraFieldValues->saveFieldValues(
3461
                        $params,
3462
                        false,
3463
                        false,
3464
                        ['ask_for_revision']
3465
                    );
3466
                }
3467
            }
3468
3469
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3470
                [
3471
                    'forum' => $forumId,
3472
                    'thread' => $threadId,
3473
                ]
3474
            );
3475
3476
            Security::clear_token();
3477
            header('Location: '.$url);
3478
            exit;
3479
        }
3480
    } else {
3481
        $token = Security::get_token();
3482
        $form->addElement('hidden', 'sec_token');
3483
        $form->setConstants(['sec_token' => $token]);
3484
3485
        // Delete from $_SESSION forum attachment from other posts
3486
        // and keep only attachments for new post
3487
        clearAttachedFiles(FORUM_NEW_POST);
3488
        // Get forum attachment ajax table to add it to form
3489
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $current_forum['forum_id']);
3490
        $ajaxHtml = $attachmentAjaxTable;
3491
        $form->addElement('html', $ajaxHtml);
3492
3493
        return $form;
3494
    }
3495
}
3496
3497
/**
3498
 * @param array $threadInfo
3499
 * @param int   $user_id
3500
 * @param int   $thread_id
3501
 * @param int   $thread_qualify
3502
 * @param int   $qualify_time
3503
 * @param int   $session_id
3504
 *
3505
 * @return array optional
3506
 *
3507
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3508
 *
3509
 * @version October 2008, dokeos  1.8.6
3510
 */
3511
function saveThreadScore(
3512
    $threadInfo,
3513
    $user_id,
3514
    $thread_id,
3515
    $thread_qualify = 0,
3516
    $qualify_time,
3517
    $session_id = 0
3518
) {
3519
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3520
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3521
3522
    $course_id = api_get_course_int_id();
3523
    $session_id = intval($session_id);
3524
    $currentUserId = api_get_user_id();
3525
3526
    if ($user_id == strval(intval($user_id)) &&
3527
        $thread_id == strval(intval($thread_id)) &&
3528
        $thread_qualify == strval(floatval($thread_qualify))
3529
    ) {
3530
        // Testing
3531
        $sql = "SELECT thread_qualify_max FROM $table_threads
3532
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3533
        $res_string = Database::query($sql);
3534
        $row_string = Database::fetch_array($res_string);
3535
        if ($thread_qualify <= $row_string[0]) {
3536
            if ($threadInfo['thread_peer_qualify'] == 0) {
3537
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3538
                        WHERE
3539
                            c_id = $course_id AND
3540
                            user_id = $user_id AND
3541
                            thread_id = ".$thread_id;
3542
            } else {
3543
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3544
                        WHERE
3545
                            c_id = $course_id AND
3546
                            user_id = $user_id AND
3547
                            qualify_user_id = $currentUserId AND
3548
                            thread_id = ".$thread_id;
3549
            }
3550
3551
            $result = Database::query($sql);
3552
            $row = Database::fetch_array($result);
3553
3554
            if ($row[0] == 0) {
3555
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3556
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3557
                Database::query($sql);
3558
                $insertId = Database::insert_id();
3559
                if ($insertId) {
3560
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3561
                            WHERE iid = $insertId";
3562
                    Database::query($sql);
3563
                }
3564
3565
                return 'insert';
3566
            } else {
3567
                saveThreadScoreHistory(
3568
                    '1',
3569
                    $course_id,
3570
                    $user_id,
3571
                    $thread_id
3572
                );
3573
3574
                // Update
3575
                $sql = "UPDATE $table_threads_qualify
3576
                        SET
3577
                            qualify = '".$thread_qualify."',
3578
                            qualify_time = '".$qualify_time."'
3579
                        WHERE
3580
                            c_id = $course_id AND
3581
                            user_id=".$user_id." AND
3582
                            thread_id=".$thread_id." AND
3583
                            qualify_user_id = $currentUserId
3584
                        ";
3585
                Database::query($sql);
3586
3587
                return 'update';
3588
            }
3589
        } else {
3590
            return null;
3591
        }
3592
    }
3593
}
3594
3595
/**
3596
 * This function shows qualify.
3597
 *
3598
 * @param string $option    contains the information of option to run
3599
 * @param int    $user_id   contains the information the current user id
3600
 * @param int    $thread_id contains the information the current thread id
3601
 *
3602
 * @return int qualify
3603
 *             <code> $option=1 obtained the qualification of the current thread</code>
3604
 *
3605
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3606
 *
3607
 * @version October 2008, dokeos  1.8.6
3608
 */
3609
function showQualify($option, $user_id, $thread_id)
3610
{
3611
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3612
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3613
3614
    $course_id = api_get_course_int_id();
3615
    $user_id = (int) $user_id;
3616
    $thread_id = (int) $thread_id;
3617
3618
    if (empty($user_id) || empty($thread_id)) {
3619
        return false;
3620
    }
3621
3622
    $sql = '';
3623
    switch ($option) {
3624
        case 1:
3625
            $sql = "SELECT qualify FROM $table_threads_qualify
3626
                    WHERE
3627
                        c_id = $course_id AND
3628
                        user_id=".$user_id." AND
3629
                        thread_id=".$thread_id;
3630
            break;
3631
        case 2:
3632
            $sql = "SELECT thread_qualify_max FROM $table_threads
3633
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3634
            break;
3635
    }
3636
3637
    if (!empty($sql)) {
3638
        $rs = Database::query($sql);
3639
        $row = Database::fetch_array($rs);
3640
3641
        return $row[0];
3642
    }
3643
3644
    return [];
3645
}
3646
3647
/**
3648
 * This function gets qualify historical.
3649
 *
3650
 * @param int  $user_id   contains the information the current user id
3651
 * @param int  $thread_id contains the information the current thread id
3652
 * @param bool $opt       contains the information of option to run
3653
 *
3654
 * @return array
3655
 *
3656
 * @author Christian Fasanando <[email protected]>,
3657
 * @author Isaac Flores <[email protected]>,
3658
 *
3659
 * @version October 2008, dokeos  1.8.6
3660
 */
3661
function getThreadScoreHistory($user_id, $thread_id, $opt)
3662
{
3663
    $user_id = (int) $user_id;
3664
    $thread_id = (int) $thread_id;
3665
3666
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3667
    $course_id = api_get_course_int_id();
3668
3669
    if ($opt == 'false') {
3670
        $sql = "SELECT * FROM $table_threads_qualify_log
3671
                WHERE
3672
                    c_id = $course_id AND
3673
                    thread_id='".$thread_id."' AND
3674
                    user_id='".$user_id."'
3675
                ORDER BY qualify_time";
3676
    } else {
3677
        $sql = "SELECT * FROM $table_threads_qualify_log
3678
                WHERE
3679
                    c_id = $course_id AND
3680
                    thread_id='".$thread_id."' AND
3681
                    user_id='".$user_id."'
3682
                ORDER BY qualify_time DESC";
3683
    }
3684
    $rs = Database::query($sql);
3685
    $log = [];
3686
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3687
        $log[] = $row;
3688
    }
3689
3690
    return $log;
3691
}
3692
3693
/**
3694
 * This function stores qualify historical.
3695
 *
3696
 * @param bool contains the information of option to run
3697
 * @param string contains the information the current course id
3698
 * @param int contains the information the current forum id
3699
 * @param int contains the information the current user id
3700
 * @param int contains the information the current thread id
3701
 * @param int contains the information the current qualify
3702
 * @param string $option
3703
 * @param int    $course_id
3704
 * @param int    $user_id
3705
 * @param int    $thread_id
3706
 *
3707
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3708
 *
3709
 * @version October 2008, dokeos  1.8.6
3710
 */
3711
function saveThreadScoreHistory(
3712
    $option,
3713
    $course_id,
3714
    $user_id,
3715
    $thread_id
3716
) {
3717
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3718
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3719
3720
    $course_id = intval($course_id);
3721
    $qualify_user_id = api_get_user_id();
3722
3723
    if ($user_id == strval(intval($user_id)) &&
3724
        $thread_id == strval(intval($thread_id)) && $option == 1
3725
    ) {
3726
        // Extract information of thread_qualify.
3727
        $sql = "SELECT qualify, qualify_time
3728
                FROM $table_threads_qualify
3729
                WHERE
3730
                    c_id = $course_id AND
3731
                    user_id = ".$user_id." AND
3732
                    thread_id = ".$thread_id." AND
3733
                    qualify_user_id = $qualify_user_id
3734
                ";
3735
        $rs = Database::query($sql);
3736
        $row = Database::fetch_array($rs);
3737
3738
        // Insert thread_historical.
3739
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3740
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3741
        Database::query($sql);
3742
3743
        $insertId = Database::insert_id();
3744
        if ($insertId) {
3745
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3746
                    WHERE iid = $insertId";
3747
            Database::query($sql);
3748
        }
3749
    }
3750
}
3751
3752
/**
3753
 * This function shows current thread qualify .
3754
 *
3755
 * @param int $threadId
3756
 * @param int $sessionId
3757
 * @param int $userId
3758
 *
3759
 * @return array or null if is empty
3760
 *
3761
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3762
 *
3763
 * @version December 2008, dokeos  1.8.6
3764
 */
3765
function current_qualify_of_thread($threadId, $sessionId, $userId)
3766
{
3767
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3768
3769
    $course_id = api_get_course_int_id();
3770
    $currentUserId = api_get_user_id();
3771
    $sessionId = intval($sessionId);
3772
    $threadId = intval($threadId);
3773
3774
    $sql = "SELECT qualify FROM $table_threads_qualify
3775
            WHERE
3776
                c_id = $course_id AND
3777
                thread_id = $threadId AND
3778
                session_id = $sessionId AND
3779
                qualify_user_id = $currentUserId AND
3780
                user_id = $userId
3781
            ";
3782
    $res = Database::query($sql);
3783
    $row = Database::fetch_array($res, 'ASSOC');
3784
3785
    return $row['qualify'];
3786
}
3787
3788
/**
3789
 * This function stores a reply in the forum_post table.
3790
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date).
3791
 *
3792
 * @param array $current_forum
3793
 * @param array $values
3794
 * @param int   $courseId      Optional
3795
 * @param int   $userId        Optional
3796
 *
3797
 * @return int post id
3798
 *
3799
 * @author Patrick Cool <[email protected]>, Ghent University
3800
 *
3801
 * @version february 2006, dokeos 1.8
3802
 */
3803
function store_reply($current_forum, $values, $courseId = 0, $userId = 0)
3804
{
3805
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3806
    $_course = api_get_course_info_by_id($courseId);
3807
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3808
    $post_date = api_get_utc_datetime();
3809
    $userId = $userId ?: api_get_user_id();
3810
3811
    if ($current_forum['allow_anonymous'] == 1) {
3812
        if (api_is_anonymous() && empty($userId)) {
3813
            $userId = api_get_anonymous_id();
3814
        }
3815
    }
3816
3817
    if (empty($userId)) {
3818
        return false;
3819
    }
3820
3821
    $visible = 1;
3822
    if ($current_forum['approval_direct_post'] == '1' &&
3823
        !api_is_allowed_to_edit(null, true)
3824
    ) {
3825
        $visible = 0;
3826
    }
3827
3828
    $upload_ok = 1;
3829
    $new_post_id = 0;
3830
3831
    if ($upload_ok) {
3832
        // We first store an entry in the forum_post table.
3833
        $new_post_id = Database::insert(
3834
            $table_posts,
3835
            [
3836
                'c_id' => $courseId,
3837
                'post_title' => $values['post_title'],
3838
                'post_text' => isset($values['post_text']) ? ($values['post_text']) : null,
3839
                'thread_id' => $values['thread_id'],
3840
                'forum_id' => $values['forum_id'],
3841
                'poster_id' => $userId,
3842
                'post_id' => 0,
3843
                'post_date' => $post_date,
3844
                'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : null,
3845
                'post_parent_id' => isset($values['post_parent_id']) ? $values['post_parent_id'] : null,
3846
                'visible' => $visible,
3847
            ]
3848
        );
3849
3850
        if ($new_post_id) {
3851
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
3852
            Database::query($sql);
3853
3854
            $values['new_post_id'] = $new_post_id;
3855
            $message = get_lang('ReplyAdded');
3856
3857
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3858
                foreach ($_POST['file_ids'] as $key => $id) {
3859
                    editAttachedFile(
3860
                        [
3861
                            'comment' => $_POST['file_comments'][$key],
3862
                            'post_id' => $new_post_id,
3863
                        ],
3864
                        $id
3865
                    );
3866
                }
3867
            }
3868
3869
            // Update the thread.
3870
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
3871
3872
            // Update the forum.
3873
            api_item_property_update(
3874
                $_course,
3875
                TOOL_FORUM,
3876
                $values['forum_id'],
3877
                'NewMessageInForum',
3878
                $userId
3879
            );
3880
3881
            // Insert post
3882
            api_item_property_update(
3883
                $_course,
3884
                TOOL_FORUM_POST,
3885
                $new_post_id,
3886
                'NewPost',
3887
                $userId
3888
            );
3889
3890
            if ($current_forum['approval_direct_post'] == '1' &&
3891
                !api_is_allowed_to_edit(null, true)
3892
            ) {
3893
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3894
            }
3895
3896
            if ($current_forum['moderated'] &&
3897
                !api_is_allowed_to_edit(null, true)
3898
            ) {
3899
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3900
            }
3901
3902
            // Setting the notification correctly.
3903
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3904
            if ($my_post_notification == 1) {
3905
                set_notification('thread', $values['thread_id'], true);
3906
            }
3907
3908
            send_notification_mails(
3909
                $values['forum_id'],
3910
                $values['thread_id'],
3911
                $values
3912
            );
3913
            add_forum_attachment_file('', $new_post_id);
3914
3915
            $logInfo = [
3916
                'tool' => TOOL_FORUM,
3917
                'tool_id' => $values['forum_id'],
3918
                'tool_id_detail' => $values['thread_id'],
3919
                'action' => 'new-post',
3920
                'action_details' => $values['action'],
3921
                'info' => $values['post_title'],
3922
            ];
3923
            Event::registerLog($logInfo);
3924
        }
3925
3926
        Session::erase('formelements');
3927
        Session::erase('origin');
3928
        Session::erase('breadcrumbs');
3929
        Session::erase('addedresource');
3930
        Session::erase('addedresourceid');
3931
3932
        Display::addFlash(Display::return_message($message, 'confirmation', false));
3933
    } else {
3934
        Display::addFlash(
3935
            Display::return_message(
3936
                get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
3937
                'error'
3938
            )
3939
        );
3940
    }
3941
3942
    return $new_post_id;
3943
}
3944
3945
/**
3946
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
3947
 *
3948
 * @param array contains all the information about the current post
3949
 * @param array contains all the information about the current thread
3950
 * @param array contains all info about the current forum (to check if attachments are allowed)
3951
 * @param array contains the default values to fill the form
3952
 *
3953
 * @author Patrick Cool <[email protected]>, Ghent University
3954
 *
3955
 * @version february 2006, dokeos 1.8
3956
 */
3957
function show_edit_post_form(
3958
    $current_post,
3959
    $current_thread,
3960
    $current_forum,
3961
    $form_values = '',
3962
    $id_attach = 0
3963
) {
3964
    // Initialize the object.
3965
    $form = new FormValidator(
3966
        'edit_post',
3967
        'post',
3968
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.intval($_GET['post'])
3969
    );
3970
    $form->addElement('header', get_lang('EditPost'));
3971
    // Setting the form elements.
3972
    $form->addElement('hidden', 'post_id', $current_post['post_id']);
3973
    $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
3974
    $form->addElement('hidden', 'id_attach', $id_attach);
3975
3976
    if (empty($current_post['post_parent_id'])) {
3977
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
3978
    }
3979
3980
    $form->addElement('text', 'post_title', get_lang('Title'));
3981
    $form->applyFilter('post_title', 'html_filter');
3982
    $form->addElement(
3983
        'html_editor',
3984
        'post_text',
3985
        get_lang('Text'),
3986
        null,
3987
        api_is_allowed_to_edit(null, true) ? [
3988
            'ToolbarSet' => 'Forum',
3989
            'Width' => '100%',
3990
            'Height' => '400',
3991
        ] : [
3992
            'ToolbarSet' => 'ForumStudent',
3993
            'Width' => '100%',
3994
            'Height' => '400',
3995
            'UserStatus' => 'student',
3996
        ]
3997
    );
3998
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
3999
4000
    $extraFields = new ExtraField('forum_post');
4001
    $extraFields->addElements($form, $current_post['post_id']);
4002
4003
    $form->addButtonAdvancedSettings('advanced_params');
4004
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
4005
4006
    if ($current_forum['moderated'] && api_is_allowed_to_edit(null, true)) {
4007
        $group = [];
4008
        $group[] = $form->createElement(
4009
            'radio',
4010
            'status',
4011
            null,
4012
            get_lang('Validated'),
4013
            1
4014
        );
4015
        $group[] = $form->createElement(
4016
            'radio',
4017
            'status',
4018
            null,
4019
            get_lang('WaitingModeration'),
4020
            2
4021
        );
4022
        $group[] = $form->createElement(
4023
            'radio',
4024
            'status',
4025
            null,
4026
            get_lang('Rejected'),
4027
            3
4028
        );
4029
        $form->addGroup($group, 'status', get_lang('Status'));
4030
    }
4031
4032
    $defaults['status']['status'] = isset($current_post['status']) && !empty($current_post['status']) ? $current_post['status'] : 2;
4033
    $form->addElement(
4034
        'checkbox',
4035
        'post_notification',
4036
        '',
4037
        get_lang('NotifyByEmail').' ('.$current_post['email'].')'
4038
    );
4039
4040
    if (api_is_allowed_to_edit(null, true) &&
4041
        empty($current_post['post_parent_id'])
4042
    ) {
4043
        // The sticky checkbox only appears when it is the first post of a thread.
4044
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
4045
        if ($current_thread['thread_sticky'] == 1) {
4046
            $defaults['thread_sticky'] = true;
4047
        }
4048
    }
4049
4050
    $form->addElement('html', '</div>');
4051
4052
    $form->addFile('user_upload[]', get_lang('Attachment'));
4053
    $form->addButton(
4054
        'add_attachment',
4055
        get_lang('AddAttachment'),
4056
        'paperclip',
4057
        'default',
4058
        'default',
4059
        null,
4060
        ['id' => 'reply-add-attachment']
4061
    );
4062
4063
    $form->addButtonUpdate(get_lang('Modify'), 'SubmitPost');
4064
4065
    // Setting the default values for the form elements.
4066
    $defaults['post_title'] = $current_post['post_title'];
4067
    $defaults['post_text'] = $current_post['post_text'];
4068
4069
    if ($current_post['post_notification'] == 1) {
4070
        $defaults['post_notification'] = true;
4071
    }
4072
4073
    if (!empty($form_values)) {
4074
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
4075
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
4076
    }
4077
4078
    $form->setDefaults($defaults);
4079
4080
    // The course admin can make a thread sticky (=appears with special icon and always on top).
4081
4082
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
4083
4084
    // Validation or display
4085
    if ($form->validate()) {
4086
        $values = $form->exportValues();
4087
4088
        $values['item_id'] = $current_post['post_id'];
4089
        $extraFieldValues = new ExtraFieldValue('forum_post');
4090
        $extraFieldValues->saveFieldValues($values);
4091
4092
        store_edit_post($current_forum, $values);
4093
    } else {
4094
        // Delete from $_SESSION forum attachment from other posts
4095
        clearAttachedFiles($current_post['post_id']);
4096
        // Get forum attachment ajax table to add it to form
4097
        $fileData = getAttachmentsAjaxTable($current_post['post_id'], $current_forum['forum_id']);
4098
        $form->addElement('html', $fileData);
4099
        $form->display();
4100
    }
4101
}
4102
4103
/**
4104
 * This function stores the edit of a post in the forum_post table.
4105
 *
4106
 * @param array
4107
 *
4108
 * @author Patrick Cool <[email protected]>, Ghent University
4109
 *
4110
 * @version february 2006, dokeos 1.8
4111
 */
4112
function store_edit_post($forumInfo, $values)
4113
{
4114
    $logInfo = [
4115
        'tool' => TOOL_FORUM,
4116
        'tool_id' => $_GET['forum'],
4117
        'tool_id_detail' => $values['thread_id'],
4118
        'action' => 'edit-post',
4119
        'action_details' => 'post',
4120
        'info' => $values['post_title'],
4121
    ];
4122
    Event::registerLog($logInfo);
4123
4124
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
4125
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4126
    $course_id = api_get_course_int_id();
4127
4128
    //check if this post is the first of the thread
4129
    // First we check if the change affects the thread and if so we commit
4130
    // the changes (sticky and post_title=thread_title are relevant).
4131
4132
    $posts = getPosts($forumInfo, $values['thread_id']);
4133
    $first_post = null;
4134
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
4135
        $first_post = $posts[0];
4136
    }
4137
4138
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
4139
        // Simple edit
4140
        $params = [
4141
            'thread_title' => $values['post_title'],
4142
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
4143
        ];
4144
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
4145
        Database::update($threadTable, $params, $where);
4146
    }
4147
4148
    $status = '';
4149
    $updateStatus = false;
4150
    if ($forumInfo['moderated']) {
4151
        if (api_is_allowed_to_edit(null, true)) {
4152
            $status = $values['status']['status'];
4153
            $updateStatus = true;
4154
        } else {
4155
            $status = CForumPost::STATUS_WAITING_MODERATION;
4156
            $updateStatus = true;
4157
        }
4158
    }
4159
4160
    // Update the post_title and the post_text.
4161
    $params = [
4162
        'post_title' => $values['post_title'],
4163
        'post_text' => $values['post_text'],
4164
        'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : '',
4165
    ];
4166
4167
    if ($updateStatus) {
4168
        $params['status'] = $status;
4169
    }
4170
4171
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
4172
    Database::update($table_posts, $params, $where);
4173
4174
    // Update attached files
4175
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
4176
        foreach ($_POST['file_ids'] as $key => $id) {
4177
            editAttachedFile(
4178
                [
4179
                    'comment' => $_POST['file_comments'][$key],
4180
                    'post_id' => $values['post_id'],
4181
                ],
4182
                $id
4183
            );
4184
        }
4185
    }
4186
4187
    if (!empty($values['remove_attach'])) {
4188
        delete_attachment($values['post_id']);
4189
    }
4190
4191
    if (empty($values['id_attach'])) {
4192
        add_forum_attachment_file(
4193
            isset($values['file_comment']) ? $values['file_comment'] : null,
4194
            $values['post_id']
4195
        );
4196
    } else {
4197
        edit_forum_attachment_file(
4198
            isset($values['file_comment']) ? $values['file_comment'] : null,
4199
            $values['post_id'],
4200
            $values['id_attach']
4201
        );
4202
    }
4203
4204
    $message = get_lang('EditPostStored').'<br />';
4205
    $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&">'.get_lang('Forum').'</a><br />';
4206
    $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.$values['thread_id'].'&post='.Security::remove_XSS($_GET['post']).'">'.get_lang('Message').'</a>';
4207
4208
    Session::erase('formelements');
4209
    Session::erase('origin');
4210
    Session::erase('breadcrumbs');
4211
    Session::erase('addedresource');
4212
    Session::erase('addedresourceid');
4213
4214
    echo Display::return_message($message, 'confirmation', false);
4215
}
4216
4217
/**
4218
 * This function displays the firstname and lastname of the user as a link to the user tool.
4219
 *
4220
 * @param string names
4221
 * @ in_title : title tootip
4222
 *
4223
 * @return string HTML
4224
 *
4225
 * @author Patrick Cool <[email protected]>, Ghent University
4226
 *
4227
 * @version february 2006, dokeos 1.8
4228
 */
4229
function display_user_link($user_id, $name, $origin = '', $in_title = '')
4230
{
4231
    if ($user_id != 0) {
4232
        $userInfo = api_get_user_info($user_id);
4233
4234
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
4235
    } else {
4236
        return $name.' ('.get_lang('Anonymous').')';
4237
    }
4238
}
4239
4240
/**
4241
 * This function displays the user image from the profile, with a link to the user's details.
4242
 *
4243
 * @param   int     User's database ID
0 ignored issues
show
Documentation Bug introduced by
The doc comment User's at position 0 could not be parsed: Unknown type name 'User's' at position 0 in User's.
Loading history...
4244
 * @param   string  User's name
4245
 * @param   string  the origin where the forum is called (example : learnpath)
4246
 *
4247
 * @return string An HTML with the anchor and the image of the user
4248
 *
4249
 * @author Julio Montoya <[email protected]>
4250
 */
4251
function display_user_image($user_id, $name, $origin = '')
4252
{
4253
    $userInfo = api_get_user_info($user_id);
4254
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
4255
4256
    if ($user_id != 0) {
4257
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
4258
    } else {
4259
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
4260
    }
4261
}
4262
4263
/**
4264
 * The thread view counter gets increased every time someone looks at the thread.
4265
 *
4266
 * @param int
4267
 *
4268
 * @author Patrick Cool <[email protected]>, Ghent University
4269
 *
4270
 * @version february 2006, dokeos 1.8
4271
 */
4272
function increase_thread_view($thread_id)
4273
{
4274
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4275
    $course_id = api_get_course_int_id();
4276
4277
    $sql = "UPDATE $table_threads 
4278
            SET thread_views = thread_views + 1
4279
            WHERE 
4280
                c_id = $course_id AND  
4281
                thread_id = '".intval($thread_id)."'";
4282
    Database::query($sql);
4283
}
4284
4285
/**
4286
 * The relies counter gets increased every time somebody replies to the thread.
4287
 *
4288
 * @author Patrick Cool <[email protected]>, Ghent University
4289
 *
4290
 * @version february 2006, dokeos 1.8
4291
 *
4292
 * @param int    $threadId
4293
 * @param string $lastPostId
4294
 * @param string $post_date
4295
 */
4296
function updateThreadInfo($threadId, $lastPostId, $post_date)
4297
{
4298
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4299
    $course_id = api_get_course_int_id();
4300
    $sql = "UPDATE $table_threads SET 
4301
            thread_replies = thread_replies+1,
4302
            thread_last_post = '".Database::escape_string($lastPostId)."',
4303
            thread_date = '".Database::escape_string($post_date)."'
4304
            WHERE 
4305
                c_id = $course_id AND  
4306
                thread_id='".Database::escape_string($threadId)."'"; // this needs to be cleaned first
4307
    Database::query($sql);
4308
}
4309
4310
/**
4311
 * This function is used to find all the information about what's new in the forum tool.
4312
 *
4313
 * @author Patrick Cool <[email protected]>, Ghent University
4314
 *
4315
 * @version february 2006, dokeos 1.8
4316
 */
4317
function get_whats_new()
4318
{
4319
    $userId = api_get_user_id();
4320
    $course_id = api_get_course_int_id();
4321
4322
    if (empty($course_id) || empty($userId)) {
4323
        return false;
4324
    }
4325
4326
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4327
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
4328
4329
    $tool = TOOL_FORUM;
4330
    $lastForumAccess = Session::read('last_forum_access');
4331
4332
    if (!$lastForumAccess) {
4333
        $sql = "SELECT * FROM $tracking_last_tool_access
4334
                WHERE
4335
                    access_user_id = $userId AND
4336
                    c_id = $course_id AND
4337
                    access_tool = '".Database::escape_string($tool)."'";
4338
        $result = Database::query($sql);
4339
        $row = Database::fetch_array($result);
4340
        Session::write('last_forum_access', $row['access_date']);
4341
        $lastForumAccess = $row['access_date'];
4342
    }
4343
4344
    $whatsNew = Session::read('whatsnew_post_info');
4345
4346
    if (!$whatsNew) {
4347
        if ($lastForumAccess != '') {
4348
            $postInfo = [];
4349
            $sql = "SELECT * FROM $table_posts
4350
                    WHERE
4351
                        c_id = $course_id AND
4352
                        visible = 1 AND                        
4353
                        post_date > '".Database::escape_string($lastForumAccess)."'";
4354
            $result = Database::query($sql);
4355
            while ($row = Database::fetch_array($result)) {
4356
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
4357
            }
4358
            Session::write('whatsnew_post_info', $postInfo);
4359
        }
4360
    }
4361
}
4362
4363
/**
4364
 * This function approves a post = change.
4365
 *
4366
 * @param int    $post_id the id of the post that will be deleted
4367
 * @param string $action  make the post visible or invisible
4368
 *
4369
 * @return string language variable
4370
 *
4371
 * @author Patrick Cool <[email protected]>, Ghent University
4372
 *
4373
 * @version february 2006, dokeos 1.8
4374
 */
4375
function approve_post($post_id, $action)
4376
{
4377
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4378
    $course_id = api_get_course_int_id();
4379
4380
    if ($action == 'invisible') {
4381
        $visibility_value = 0;
4382
    }
4383
4384
    if ($action == 'visible') {
4385
        $visibility_value = 1;
4386
        handle_mail_cue('post', $post_id);
4387
    }
4388
4389
    $sql = "UPDATE $table_posts SET
4390
            visible='".Database::escape_string($visibility_value)."'
4391
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
4392
    $return = Database::query($sql);
4393
4394
    if ($return) {
4395
        return 'PostVisibilityChanged';
4396
    }
4397
}
4398
4399
/**
4400
 * This function retrieves all the unapproved messages for a given forum
4401
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this).
4402
 *
4403
 * @param $forum_id the forum where we want to know the unapproved messages of
4404
 *
4405
 * @return array returns
4406
 *
4407
 * @author Patrick Cool <[email protected]>, Ghent University
4408
 *
4409
 * @version february 2006, dokeos 1.8
4410
 */
4411
function get_unaproved_messages($forum_id)
4412
{
4413
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4414
    $course_id = api_get_course_int_id();
4415
4416
    $return_array = [];
4417
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
4418
            WHERE 
4419
                c_id = $course_id AND 
4420
                forum_id='".Database::escape_string($forum_id)."' AND 
4421
                visible='0' ";
4422
    $result = Database::query($sql);
4423
    while ($row = Database::fetch_array($result)) {
4424
        $return_array[] = $row['thread_id'];
4425
    }
4426
4427
    return $return_array;
4428
}
4429
4430
/**
4431
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
4432
 * was added to a given thread.
4433
 *
4434
 * @param array reply information
4435
 *
4436
 * @author Patrick Cool <[email protected]>, Ghent University
4437
 *
4438
 * @version february 2006, dokeos 1.8
4439
 */
4440
function send_notification_mails($forumId, $thread_id, $reply_info)
4441
{
4442
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4443
4444
    // First we need to check if
4445
    // 1. the forum category is visible
4446
    // 2. the forum is visible
4447
    // 3. the thread is visible
4448
    // 4. the reply is visible (=when there is)
4449
    $current_thread = get_thread_information($forumId, $thread_id);
4450
    $current_forum = get_forum_information($current_thread['forum_id'], $current_thread['c_id']);
4451
4452
    $current_forum_category = null;
4453
    if (isset($current_forum['forum_category'])) {
4454
        $current_forum_category = get_forumcategory_information($current_forum['forum_category']);
4455
    }
4456
4457
    $send_mails = false;
4458
    if ($current_thread['visibility'] == '1' &&
4459
        $current_forum['visibility'] == '1' &&
4460
        ($current_forum_category && $current_forum_category['visibility'] == '1') &&
4461
        $current_forum['approval_direct_post'] != '1'
4462
    ) {
4463
        $send_mails = true;
4464
    }
4465
4466
    // The forum category, the forum, the thread and the reply are visible to the user
4467
    if ($send_mails && !empty($forumId)) {
4468
        $postId = isset($reply_info['new_post_id']) ? $reply_info['new_post_id'] : 0;
4469
        send_notifications($forumId, $thread_id, $postId);
4470
    } else {
4471
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4472
        if (isset($current_forum['forum_id'])) {
4473
            $sql = "SELECT * FROM $table_notification
4474
                    WHERE
4475
                        c_id = ".api_get_course_int_id()." AND
4476
                        (
4477
                            forum_id = '".intval($current_forum['forum_id'])."' OR
4478
                            thread_id = '".intval($thread_id)."'
4479
                        ) ";
4480
4481
            $result = Database::query($sql);
4482
            $user_id = api_get_user_id();
4483
            while ($row = Database::fetch_array($result)) {
4484
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4485
                        VALUES (".api_get_course_int_id().", '".intval($thread_id)."', '".intval($reply_info['new_post_id'])."', '$user_id' )";
4486
                Database::query($sql);
4487
            }
4488
        }
4489
    }
4490
}
4491
4492
/**
4493
 * This function is called whenever something is made visible because there might
4494
 * be new posts and the user might have indicated that (s)he wanted to be
4495
 * informed about the new posts by mail.
4496
 *
4497
 * @param string $content Content type (post, thread, forum, forum_category)
4498
 * @param int    $id      Item DB ID of the corresponding content type
4499
 *
4500
 * @return string language variable
4501
 *
4502
 * @author Patrick Cool <[email protected]>, Ghent University
4503
 *
4504
 * @version february 2006, dokeos 1.8
4505
 */
4506
function handle_mail_cue($content, $id)
4507
{
4508
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4509
    $table_forums = Database::get_course_table(TABLE_FORUM);
4510
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4511
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4512
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4513
4514
    $course_id = api_get_course_int_id();
4515
    $id = (int) $id;
4516
4517
    /* If the post is made visible we only have to send mails to the people
4518
     who indicated that they wanted to be informed for that thread.*/
4519
    if ($content == 'post') {
4520
        // Getting the information about the post (need the thread_id).
4521
        $post_info = get_post_information($id);
4522
        $thread_id = (int) $post_info['thread_id'];
4523
4524
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4525
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4526
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4527
                WHERE
4528
                    posts.c_id = $course_id AND
4529
                    mailcue.c_id = $course_id AND
4530
                    posts.thread_id = $thread_id AND
4531
                    posts.post_notification = '1' AND
4532
                    mailcue.thread_id = $thread_id AND
4533
                    users.user_id = posts.poster_id AND
4534
                    users.active = 1
4535
                GROUP BY users.email";
4536
4537
        $result = Database::query($sql);
4538
        while ($row = Database::fetch_array($result)) {
4539
            $forumInfo = get_forum_information($post_info['forum_id']);
4540
            send_mail($row, $forumInfo, get_thread_information($post_info['forum_id'], $post_info['thread_id']), $post_info);
4541
        }
4542
    } elseif ($content == 'thread') {
4543
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4544
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4545
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4546
                WHERE
4547
                    posts.c_id = $course_id AND
4548
                    mailcue.c_id = $course_id AND
4549
                    posts.thread_id = $id AND
4550
                    posts.post_notification = '1' AND
4551
                    mailcue.thread_id = $id AND
4552
                    users.user_id = posts.poster_id AND
4553
                    users.active = 1
4554
                GROUP BY users.email";
4555
        $result = Database::query($sql);
4556
        while ($row = Database::fetch_array($result)) {
4557
            $forumInfo = get_forum_information($row['forum_id']);
4558
            send_mail($row, $forumInfo, get_thread_information($row['forum_id'], $id));
4559
        }
4560
4561
        // Deleting the relevant entries from the mailcue.
4562
        $sql = "DELETE FROM $table_mailcue
4563
                WHERE c_id = $course_id AND thread_id = $id";
4564
        Database::query($sql);
4565
    } elseif ($content == 'forum') {
4566
        $sql = "SELECT thread_id FROM $table_threads
4567
                WHERE c_id = $course_id AND forum_id = $id";
4568
        $result = Database::query($sql);
4569
        while ($row = Database::fetch_array($result)) {
4570
            handle_mail_cue('thread', $row['thread_id']);
4571
        }
4572
    } elseif ($content == 'forum_category') {
4573
        $sql = "SELECT forum_id FROM $table_forums
4574
                WHERE c_id = $course_id AND forum_category = $id";
4575
        $result = Database::query($sql);
4576
        while ($row = Database::fetch_array($result)) {
4577
            handle_mail_cue('forum', $row['forum_id']);
4578
        }
4579
    } else {
4580
        return get_lang('Error');
4581
    }
4582
}
4583
4584
/**
4585
 * This function sends the mails for the mail notification.
4586
 *
4587
 * @param array
4588
 * @param array
4589
 * @param array
4590
 * @param array
4591
 *
4592
 * @author Patrick Cool <[email protected]>, Ghent University
4593
 *
4594
 * @version february 2006, dokeos 1.8
4595
 */
4596
function send_mail($userInfo, $forumInfo, $thread_information, $postInfo = [])
4597
{
4598
    if (empty($userInfo) || empty($forumInfo) || empty($thread_information)) {
4599
        return false;
4600
    }
4601
4602
    $_course = api_get_course_info();
4603
    $user_id = api_get_user_id();
4604
4605
    $thread_link = '';
4606
    if (isset($thread_information) && is_array($thread_information)) {
4607
        $thread_link = api_get_path(WEB_CODE_PATH).
4608
            'forum/viewthread.php?'.api_get_cidreq().'&forum='.$thread_information['forum_id'].'&thread='.$thread_information['thread_id'];
4609
    }
4610
    $email_body = get_lang('Dear').' '.api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4611
    $email_body .= get_lang('NewForumPost').': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4612
4613
    $courseId = api_get_configuration_value('global_forums_course_id');
4614
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'].': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4615
4616
    $courseInfoTitle = get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4617
    if (!empty($courseId) && $_course['real_id'] == $courseId) {
4618
        $subject = get_lang('NewForumPost').': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4619
        $courseInfoTitle = " <br />\n";
4620
    }
4621
    $email_body .= $courseInfoTitle;
4622
4623
    if (!empty($postInfo) && isset($postInfo['post_text'])) {
4624
        $text = cut(strip_tags($postInfo['post_text']), 100);
4625
        if (!empty($text)) {
4626
            $email_body .= get_lang('Message').": <br />\n ";
4627
            $email_body .= $text;
4628
            $email_body .= "<br /><br />\n";
4629
        }
4630
    }
4631
4632
    $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
4633
4634
    if (!empty($thread_link)) {
4635
        $email_body .= get_lang('ThreadCanBeFoundHere')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
4636
    }
4637
4638
    if ($userInfo['user_id'] != $user_id) {
4639
        MessageManager::send_message(
4640
            $userInfo['user_id'],
4641
            $subject,
4642
            $email_body,
4643
            [],
4644
            [],
4645
            null,
4646
            null,
4647
            null,
4648
            null,
4649
            $user_id
4650
        );
4651
    }
4652
}
4653
4654
/**
4655
 * This function displays the form for moving a thread to a different (already existing) forum.
4656
 *
4657
 * @author Patrick Cool <[email protected]>, Ghent University
4658
 *
4659
 * @version february 2006, dokeos 1.8
4660
 */
4661
function move_thread_form()
4662
{
4663
    $form = new FormValidator(
4664
        'movepost',
4665
        'post',
4666
        api_get_self().'?forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4667
    );
4668
    // The header for the form
4669
    $form->addElement('header', get_lang('MoveThread'));
4670
    // Invisible form: the thread_id
4671
    $form->addElement('hidden', 'thread_id', intval($_GET['thread']));
4672
    // the fora
4673
    $forum_categories = get_forum_categories();
4674
    $forums = get_forums();
4675
4676
    $htmlcontent = '<div class="row">
4677
        <div class="label">
4678
            <span class="form_required">*</span>'.get_lang('MoveTo').'
4679
        </div>
4680
        <div class="formw">';
4681
    $htmlcontent .= '<select name="forum">';
4682
    foreach ($forum_categories as $key => $category) {
4683
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4684
        foreach ($forums as $key => $forum) {
4685
            if (isset($forum['forum_category'])) {
4686
                if ($forum['forum_category'] == $category['cat_id']) {
4687
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4688
                }
4689
            }
4690
        }
4691
        $htmlcontent .= '</optgroup>';
4692
    }
4693
    $htmlcontent .= "</select>";
4694
    $htmlcontent .= '   </div>
4695
                    </div>';
4696
4697
    $form->addElement('html', $htmlcontent);
4698
4699
    // The OK button
4700
    $form->addButtonSave(get_lang('MoveThread'), 'SubmitForum');
4701
4702
    // Validation or display
4703
    if ($form->validate()) {
4704
        $values = $form->exportValues();
4705
        if (isset($_POST['forum'])) {
4706
            store_move_thread($values);
4707
        }
4708
    } else {
4709
        $form->display();
4710
    }
4711
}
4712
4713
/**
4714
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4715
 *
4716
 * @author Patrick Cool <[email protected]>, Ghent University
4717
 *
4718
 * @version february 2006, dokeos 1.8
4719
 */
4720
function move_post_form()
4721
{
4722
    $form = new FormValidator(
4723
        'movepost',
4724
        'post',
4725
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post'])
4726
    );
4727
    // The header for the form
4728
    $form->addElement('header', '', get_lang('MovePost'));
4729
4730
    // Invisible form: the post_id
4731
    $form->addElement('hidden', 'post_id', intval($_GET['post']));
4732
4733
    // Dropdown list: Threads of this forum
4734
    $threads = get_threads($_GET['forum']);
4735
    //my_print_r($threads);
4736
    $threads_list[0] = get_lang('ANewThread');
4737
    foreach ($threads as $key => $value) {
4738
        $threads_list[$value['thread_id']] = $value['thread_title'];
4739
    }
4740
    $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
4741
    $form->applyFilter('thread', 'html_filter');
4742
4743
    // The OK button
4744
    $form->addButtonSave(get_lang('MovePost'), 'submit');
4745
4746
    // Setting the rules
4747
    $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
4748
4749
    // Validation or display
4750
    if ($form->validate()) {
4751
        $values = $form->exportValues();
4752
        store_move_post($values);
4753
    } else {
4754
        $form->display();
4755
    }
4756
}
4757
4758
/**
4759
 * @param array
4760
 *
4761
 * @return string HTML language variable
4762
 *
4763
 * @author Patrick Cool <[email protected]>, Ghent University
4764
 *
4765
 * @version february 2006, dokeos 1.8
4766
 */
4767
function store_move_post($values)
4768
{
4769
    $_course = api_get_course_info();
4770
    $course_id = api_get_course_int_id();
4771
4772
    $table_forums = Database::get_course_table(TABLE_FORUM);
4773
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4774
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4775
4776
    if ($values['thread'] == '0') {
4777
        $current_post = get_post_information($values['post_id']);
4778
4779
        // Storing a new thread.
4780
        $params = [
4781
            'c_id' => $course_id,
4782
            'thread_title' => $current_post['post_title'],
4783
            'forum_id' => $current_post['forum_id'],
4784
            'thread_poster_id' => $current_post['poster_id'],
4785
            'thread_poster_name' => $current_post['poster_name'],
4786
            'thread_last_post' => $values['post_id'],
4787
            'thread_date' => $current_post['post_date'],
4788
        ];
4789
4790
        $new_thread_id = Database::insert($table_threads, $params);
4791
4792
        api_item_property_update(
4793
            $_course,
4794
            TOOL_FORUM_THREAD,
4795
            $new_thread_id,
4796
            'visible',
4797
            $current_post['poster_id']
4798
        );
4799
4800
        // Moving the post to the newly created thread.
4801
        $sql = "UPDATE $table_posts SET thread_id='".intval($new_thread_id)."', post_parent_id = NULL
4802
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4803
        Database::query($sql);
4804
4805
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4806
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4807
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4808
        Database::query($sql);
4809
4810
        // Updating updating the number of threads in the forum.
4811
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4812
                WHERE c_id = $course_id AND forum_id='".intval($current_post['forum_id'])."'";
4813
        Database::query($sql);
4814
4815
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4816
        $sql = "SELECT * FROM $table_posts
4817
                WHERE c_id = $course_id AND thread_id='".intval($current_post['thread_id'])."'
4818
                ORDER BY post_id DESC";
4819
        $result = Database::query($sql);
4820
        $row = Database::fetch_array($result);
4821
        $sql = "UPDATE $table_threads SET
4822
                    thread_last_post='".$row['post_id']."',
4823
                    thread_replies=thread_replies-1
4824
                WHERE
4825
                    c_id = $course_id AND
4826
                    thread_id='".intval($current_post['thread_id'])."'";
4827
        Database::query($sql);
4828
    } else {
4829
        // Moving to the chosen thread.
4830
        $sql = "SELECT thread_id FROM ".$table_posts."
4831
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
4832
        $result = Database::query($sql);
4833
        $row = Database::fetch_array($result);
4834
4835
        $original_thread_id = $row['thread_id'];
4836
4837
        $sql = "SELECT thread_last_post FROM ".$table_threads."
4838
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4839
4840
        $result = Database::query($sql);
4841
        $row = Database::fetch_array($result);
4842
        $thread_is_last_post = $row['thread_last_post'];
4843
        // If is this thread, update the thread_last_post with the last one.
4844
4845
        if ($thread_is_last_post == $values['post_id']) {
4846
            $sql = "SELECT post_id FROM ".$table_posts."
4847
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
4848
                    ORDER BY post_date DESC LIMIT 1";
4849
            $result = Database::query($sql);
4850
4851
            $row = Database::fetch_array($result);
4852
            $thread_new_last_post = $row['post_id'];
4853
4854
            $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."'
4855
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4856
            Database::query($sql);
4857
        }
4858
4859
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4860
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
4861
        Database::query($sql);
4862
4863
        // moving to the chosen thread
4864
        $sql = "UPDATE $table_posts SET thread_id='".intval($_POST['thread'])."', post_parent_id = NULL
4865
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4866
        Database::query($sql);
4867
4868
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4869
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4870
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4871
        Database::query($sql);
4872
4873
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4874
                WHERE c_id = $course_id AND thread_id='".intval($_POST['thread'])."'";
4875
        Database::query($sql);
4876
    }
4877
4878
    return get_lang('ThreadMoved');
4879
}
4880
4881
/**
4882
 * @param array
4883
 *
4884
 * @return string HTML language variable
4885
 *
4886
 * @author Patrick Cool <[email protected]>, Ghent University
4887
 *
4888
 * @version february 2006, dokeos 1.8
4889
 */
4890
function store_move_thread($values)
4891
{
4892
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4893
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4894
4895
    $courseId = api_get_course_int_id();
4896
    $sessionId = api_get_session_id();
4897
4898
    $forumId = intval($_POST['forum']);
4899
    $threadId = intval($_POST['thread_id']);
4900
    $forumInfo = get_forums($forumId);
4901
4902
    // Change the thread table: Setting the forum_id to the new forum.
4903
    $sql = "UPDATE $table_threads SET forum_id = $forumId
4904
            WHERE c_id = $courseId AND thread_id = $threadId";
4905
    Database::query($sql);
4906
4907
    // Changing all the posts of the thread: setting the forum_id to the new forum.
4908
    $sql = "UPDATE $table_posts SET forum_id = $forumId
4909
            WHERE c_id = $courseId AND thread_id= $threadId";
4910
    Database::query($sql);
4911
    // Fix group id, if forum is moved to a different group
4912
    if (!empty($forumInfo['to_group_id'])) {
4913
        $groupId = $forumInfo['to_group_id'];
4914
        $item = api_get_item_property_info(
4915
            $courseId,
4916
            TABLE_FORUM_THREAD,
4917
            $threadId,
4918
            $sessionId,
4919
            $groupId
4920
        );
4921
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4922
        $sessionCondition = api_get_session_condition($sessionId);
4923
4924
        if (!empty($item)) {
4925
            if ($item['to_group_id'] != $groupId) {
4926
                $sql = "UPDATE $table
4927
                    SET to_group_id = $groupId
4928
                    WHERE
4929
                      tool = '".TABLE_FORUM_THREAD."' AND
4930
                      c_id = $courseId AND
4931
                      ref = ".$item['ref']."
4932
                      $sessionCondition
4933
                ";
4934
                Database::query($sql);
4935
            }
4936
        } else {
4937
            $sql = "UPDATE $table
4938
                    SET to_group_id = $groupId
4939
                    WHERE
4940
                      tool = '".TABLE_FORUM_THREAD."' AND
4941
                      c_id = $courseId AND
4942
                      ref = ".$threadId."
4943
                      $sessionCondition
4944
            ";
4945
            Database::query($sql);
4946
        }
4947
    }
4948
4949
    return get_lang('ThreadMoved');
4950
}
4951
4952
/**
4953
 * Prepares a string for displaying by highlighting the search results inside, if any.
4954
 *
4955
 * @param string $input the input string
4956
 *
4957
 * @return string the same string with highlighted hits inside
4958
 *
4959
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
4960
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
4961
 */
4962
function prepare4display($input)
4963
{
4964
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
4965
    static $search;
4966
4967
    if (!isset($search)) {
4968
        if (isset($_POST['search_term'])) {
4969
            $search = $_POST['search_term']; // No html at all.
4970
        } elseif (isset($_GET['search'])) {
4971
            $search = $_GET['search'];
4972
        } else {
4973
            $search = '';
4974
        }
4975
    }
4976
4977
    if (!empty($search)) {
4978
        if (strstr($search, '+')) {
4979
            $search_terms = explode('+', $search);
4980
        } else {
4981
            $search_terms[] = trim($search);
4982
        }
4983
        $counter = 0;
4984
        foreach ($search_terms as $key => $search_term) {
4985
            $input = api_preg_replace(
4986
                '/'.preg_quote(trim($search_term), '/').'/i',
4987
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
4988
                $input
4989
            );
4990
            $counter++;
4991
        }
4992
    }
4993
4994
    // TODO: Security should be implemented outside this function.
4995
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
4996
    // (see comments of Security::remove_XSS() method to learn about other levels).
4997
4998
    return Security::remove_XSS($input, STUDENT, true);
4999
}
5000
5001
/**
5002
 * Display the search form for the forum and display the search results.
5003
 *
5004
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5005
 *
5006
 * @version march 2008, dokeos 1.8.5
5007
 */
5008
function forum_search()
5009
{
5010
    $form = new FormValidator(
5011
        'forumsearch',
5012
        'post',
5013
        'forumsearch.php?'.api_get_cidreq()
5014
    );
5015
5016
    // Setting the form elements.
5017
    $form->addElement('header', '', get_lang('ForumSearch'));
5018
    $form->addElement('text', 'search_term', get_lang('SearchTerm'), ['autofocus']);
5019
    $form->applyFilter('search_term', 'html_filter');
5020
    $form->addElement('static', 'search_information', '', get_lang('ForumSearchInformation'));
5021
    $form->addButtonSearch(get_lang('Search'));
5022
5023
    // Setting the rules.
5024
    $form->addRule('search_term', get_lang('ThisFieldIsRequired'), 'required');
5025
    $form->addRule('search_term', get_lang('TooShort'), 'minlength', 3);
5026
5027
    // Validation or display.
5028
    if ($form->validate()) {
5029
        $values = $form->exportValues();
5030
        $form->setDefaults($values);
5031
        $form->display();
5032
        // Display the search results.
5033
        display_forum_search_results(stripslashes($values['search_term']));
5034
    } else {
5035
        $form->display();
5036
    }
5037
}
5038
5039
/**
5040
 * Display the search results.
5041
 *
5042
 * @param string
5043
 * @param string $search_term
5044
 *
5045
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5046
 *
5047
 * @version march 2008, dokeos 1.8.5
5048
 */
5049
function display_forum_search_results($search_term)
5050
{
5051
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5052
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5053
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5054
    $session_id = api_get_session_id();
5055
    $course_id = api_get_course_int_id();
5056
5057
    // Defining the search strings as an array.
5058
    if (strstr($search_term, '+')) {
5059
        $search_terms = explode('+', $search_term);
5060
    } else {
5061
        $search_terms[] = $search_term;
5062
    }
5063
5064
    // Search restriction.
5065
    foreach ($search_terms as $value) {
5066
        $search_restriction[] = "
5067
        (
5068
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR 
5069
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%' 
5070
        )";
5071
    }
5072
5073
    $sessionCondition = api_get_session_condition(
5074
        $session_id,
5075
        true,
5076
        false,
5077
        'item_property.session_id'
5078
    );
5079
5080
    $sql = "SELECT posts.*
5081
            FROM $table_posts posts 
5082
            INNER JOIN $table_threads threads
5083
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5084
            INNER JOIN $table_item_property item_property
5085
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
5086
            WHERE
5087
                posts.c_id = $course_id AND 
5088
                item_property.c_id = $course_id AND 
5089
                item_property.visibility = 1  
5090
                $sessionCondition AND
5091
                posts.visible = 1 AND 
5092
                item_property.tool = '".TOOL_FORUM_THREAD."' AND 
5093
                ".implode(' AND ', $search_restriction)."
5094
            GROUP BY posts.post_id";
5095
5096
    // Getting all the information of the forum categories.
5097
    $forum_categories_list = get_forum_categories();
5098
5099
    // Getting all the information of the forums.
5100
    $forum_list = get_forums();
5101
5102
    $result = Database::query($sql);
5103
    $search_results = [];
5104
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5105
        $forumId = $row['forum_id'];
5106
        $forumData = get_forums($forumId);
5107
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
5108
        $display_result = false;
5109
        /*
5110
          We only show it when
5111
          1. forum category is visible
5112
          2. forum is visible
5113
          3. thread is visible (to do)
5114
          4. post is visible
5115
         */
5116
        if (!api_is_allowed_to_edit(null, true)) {
5117
            if (!empty($category)) {
5118
                if ($category['visibility'] == '1' && $forumData['visibility'] == '1') {
5119
                    $display_result = true;
5120
                }
5121
            } else {
5122
                if ($forumData['visible'] == '1') {
5123
                    $display_result = true;
5124
                }
5125
            }
5126
        } else {
5127
            $display_result = true;
5128
        }
5129
5130
        if ($display_result) {
5131
            $categoryName = !empty($category) ? $category['cat_title'] : '';
5132
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
5133
                prepare4display($categoryName).'</a> &gt; ';
5134
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
5135
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
5136
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
5137
                prepare4display($row['post_title']).'</a>';
5138
            $search_results_item .= '<br />';
5139
            if (api_strlen($row['post_title']) > 200) {
5140
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
5141
            } else {
5142
                $search_results_item .= prepare4display($row['post_title']);
5143
            }
5144
            $search_results_item .= '</li>';
5145
            $search_results[] = $search_results_item;
5146
        }
5147
    }
5148
    echo '<legend>'.count($search_results).' '.get_lang('ForumSearchResults').'</legend>';
5149
    echo '<ol>';
5150
    if ($search_results) {
5151
        echo implode($search_results);
5152
    }
5153
    echo '</ol>';
5154
}
5155
5156
/**
5157
 * Return the link to the forum search page.
5158
 *
5159
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5160
 *
5161
 * @version April 2008, dokeos 1.8.5
5162
 */
5163
function search_link()
5164
{
5165
    $return = '';
5166
    $origin = api_get_origin();
5167
    if ($origin != 'learnpath') {
5168
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
5169
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
5170
5171
        if (!empty($_GET['search'])) {
5172
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
5173
            $url = api_get_self().'?';
5174
            $url_parameter = [];
5175
            foreach ($_GET as $key => $value) {
5176
                if ($key != 'search') {
5177
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
5178
                }
5179
            }
5180
            $url = $url.implode('&', $url_parameter);
5181
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
5182
        }
5183
    }
5184
5185
    return $return;
5186
}
5187
5188
/**
5189
 * This function adds an attachment file into a forum.
5190
 *
5191
 * @param string $file_comment a comment about file
5192
 * @param int    $last_id      from forum_post table
5193
 *
5194
 * @return false|null
5195
 */
5196
function add_forum_attachment_file($file_comment, $last_id)
5197
{
5198
    $_course = api_get_course_info();
5199
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5200
5201
    if (empty($_FILES['user_upload'])) {
5202
        return false;
5203
    }
5204
5205
    $filesData = [];
5206
5207
    if (!is_array($_FILES['user_upload']['name'])) {
5208
        $filesData[] = $_FILES['user_upload'];
5209
    } else {
5210
        $fileCount = count($_FILES['user_upload']['name']);
5211
        $fileKeys = array_keys($_FILES['user_upload']);
5212
        for ($i = 0; $i < $fileCount; $i++) {
5213
            foreach ($fileKeys as $key) {
5214
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5215
            }
5216
        }
5217
    }
5218
5219
    foreach ($filesData as $attachment) {
5220
        if (empty($attachment['name'])) {
5221
            continue;
5222
        }
5223
5224
        $upload_ok = process_uploaded_file($attachment);
5225
5226
        if (!$upload_ok) {
5227
            continue;
5228
        }
5229
5230
        $course_dir = $_course['path'].'/upload/forum';
5231
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5232
        $updir = $sys_course_path.$course_dir;
5233
5234
        // Try to add an extension to the file if it hasn't one.
5235
        $new_file_name = add_ext_on_mime(
5236
            stripslashes($attachment['name']),
5237
            $attachment['type']
5238
        );
5239
        // User's file name
5240
        $file_name = $attachment['name'];
5241
5242
        if (!filter_extension($new_file_name)) {
5243
            Display::addFlash(
5244
                Display::return_message(
5245
                    get_lang('UplUnableToSaveFileFilteredExtension'),
5246
                    'error'
5247
                )
5248
            );
5249
5250
            return;
5251
        }
5252
5253
        $new_file_name = uniqid('');
5254
        $new_path = $updir.'/'.$new_file_name;
5255
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5256
        $safe_file_comment = Database::escape_string($file_comment);
5257
        $safe_file_name = Database::escape_string($file_name);
5258
        $safe_new_file_name = Database::escape_string($new_file_name);
5259
        $last_id = intval($last_id);
5260
        // Storing the attachments if any.
5261
        if (!$result) {
5262
            return;
5263
        }
5264
5265
        $last_id_file = Database::insert(
5266
            $agenda_forum_attachment,
5267
            [
5268
                'c_id' => api_get_course_int_id(),
5269
                'filename' => $safe_file_name,
5270
                'comment' => $safe_file_comment,
5271
                'path' => $safe_new_file_name,
5272
                'post_id' => $last_id,
5273
                'size' => intval($attachment['size']),
5274
            ]
5275
        );
5276
5277
        api_item_property_update(
5278
            $_course,
5279
            TOOL_FORUM_ATTACH,
5280
            $last_id_file,
5281
            'ForumAttachmentAdded',
5282
            api_get_user_id()
5283
        );
5284
    }
5285
}
5286
5287
/**
5288
 * This function edits an attachment file into a forum.
5289
 *
5290
 * @param string $file_comment a comment about file
5291
 * @param int    $post_id
5292
 * @param int    $id_attach    attachment file Id
5293
 */
5294
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
5295
{
5296
    $_course = api_get_course_info();
5297
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5298
    $course_id = api_get_course_int_id();
5299
5300
    $filesData = [];
5301
5302
    if (!is_array($_FILES['user_upload']['name'])) {
5303
        $filesData[] = $_FILES['user_upload'];
5304
    } else {
5305
        $fileCount = count($_FILES['user_upload']['name']);
5306
        $fileKeys = array_keys($_FILES['user_upload']);
5307
5308
        for ($i = 0; $i < $fileCount; $i++) {
5309
            foreach ($fileKeys as $key) {
5310
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5311
            }
5312
        }
5313
    }
5314
5315
    foreach ($filesData as $attachment) {
5316
        if (empty($attachment['name'])) {
5317
            continue;
5318
        }
5319
5320
        $upload_ok = process_uploaded_file($attachment);
5321
5322
        if (!$upload_ok) {
5323
            continue;
5324
        }
5325
5326
        $course_dir = $_course['path'].'/upload/forum';
5327
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5328
        $updir = $sys_course_path.$course_dir;
5329
5330
        // Try to add an extension to the file if it hasn't one.
5331
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
5332
        // User's file name
5333
        $file_name = $attachment['name'];
5334
5335
        if (!filter_extension($new_file_name)) {
5336
            Display::addFlash(
5337
                Display::return_message(
5338
                    get_lang('UplUnableToSaveFileFilteredExtension'),
5339
                    'error'
5340
                )
5341
            );
5342
        } else {
5343
            $new_file_name = uniqid('');
5344
            $new_path = $updir.'/'.$new_file_name;
5345
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5346
            $safe_file_comment = Database::escape_string($file_comment);
5347
            $safe_file_name = Database::escape_string($file_name);
5348
            $safe_new_file_name = Database::escape_string($new_file_name);
5349
            $safe_post_id = (int) $post_id;
5350
            $safe_id_attach = (int) $id_attach;
5351
            // Storing the attachments if any.
5352
            if ($result) {
5353
                $sql = "UPDATE $table_forum_attachment 
5354
                        SET 
5355
                            filename = '$safe_file_name', 
5356
                            comment = '$safe_file_comment', 
5357
                            path = '$safe_new_file_name', 
5358
                            post_id = '$safe_post_id', 
5359
                            size ='".$attachment['size']."'
5360
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
5361
                Database::query($sql);
5362
                api_item_property_update(
5363
                    $_course,
5364
                    TOOL_FORUM_ATTACH,
5365
                    $safe_id_attach,
5366
                    'ForumAttachmentUpdated',
5367
                    api_get_user_id()
5368
                );
5369
            }
5370
        }
5371
    }
5372
}
5373
5374
/**
5375
 * Show a list with all the attachments according to the post's id.
5376
 *
5377
 * @param int $postId
5378
 *
5379
 * @return array with the post info
5380
 *
5381
 * @author Julio Montoya
5382
 *
5383
 * @version avril 2008, dokeos 1.8.5
5384
 */
5385
function get_attachment($postId)
5386
{
5387
    $table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5388
    $course_id = api_get_course_int_id();
5389
    $row = [];
5390
    $postId = (int) $postId;
5391
5392
    if (empty($postId)) {
5393
        return [];
5394
    }
5395
5396
    $sql = "SELECT iid, path, filename, comment 
5397
            FROM $table
5398
            WHERE c_id = $course_id AND post_id = $postId";
5399
    $result = Database::query($sql);
5400
    if (Database::num_rows($result) != 0) {
5401
        $row = Database::fetch_array($result);
5402
    }
5403
5404
    return $row;
5405
}
5406
5407
/**
5408
 * @param int $postId
5409
 *
5410
 * @return array
5411
 */
5412
function getAllAttachment($postId)
5413
{
5414
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5415
    $courseId = api_get_course_int_id();
5416
    $postId = (int) $postId;
5417
5418
    if (empty($postId)) {
5419
        return [];
5420
    }
5421
5422
    $columns = ['iid', 'path', 'filename', 'comment'];
5423
    $conditions = [
5424
        'where' => [
5425
            'c_id = ? AND post_id = ?' => [$courseId, $postId],
5426
        ],
5427
    ];
5428
    $array = Database::select(
5429
        $columns,
5430
        $forumAttachmentTable,
5431
        $conditions,
5432
        'all',
5433
        'ASSOC'
5434
    );
5435
5436
    return $array;
5437
}
5438
5439
/**
5440
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional).
5441
 *
5442
 * @param int $post_id
5443
 * @param int $id_attach
5444
 *
5445
 * @return int
5446
 *
5447
 * @author Julio Montoya
5448
 *
5449
 * @version october 2014, chamilo 1.9.8
5450
 */
5451
function delete_attachment($post_id, $id_attach = 0)
5452
{
5453
    $_course = api_get_course_info();
5454
5455
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5456
    $course_id = api_get_course_int_id();
5457
5458
    $cond = (!empty($id_attach)) ? " iid = ".(int) $id_attach."" : " post_id = ".(int) $post_id."";
5459
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
5460
    $res = Database::query($sql);
5461
    $row = Database::fetch_array($res);
5462
5463
    $course_dir = $_course['path'].'/upload/forum';
5464
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
5465
    $updir = $sys_course_path.$course_dir;
5466
    $my_path = isset($row['path']) ? $row['path'] : null;
5467
    $file = $updir.'/'.$my_path;
5468
    if (Security::check_abs_path($file, $updir)) {
5469
        @unlink($file);
5470
    }
5471
5472
    // Delete from forum_attachment table.
5473
    $sql = "DELETE FROM $forum_table_attachment 
5474
            WHERE c_id = $course_id AND $cond ";
5475
    $result = Database::query($sql);
5476
    if ($result !== false) {
5477
        $affectedRows = Database::affected_rows($result);
5478
    } else {
5479
        $affectedRows = 0;
5480
    }
5481
5482
    // Update item_property.
5483
    api_item_property_update(
5484
        $_course,
5485
        TOOL_FORUM_ATTACH,
5486
        $id_attach,
5487
        'ForumAttachmentDelete',
5488
        api_get_user_id()
5489
    );
5490
5491
    if (!empty($result) && !empty($id_attach)) {
5492
        Display::addFlash(Display::return_message(get_lang('AttachmentFileDeleteSuccess'), 'confirmation'));
5493
    }
5494
5495
    return $affectedRows;
5496
}
5497
5498
/**
5499
 * This function gets all the forum information of the all the forum of the group.
5500
 *
5501
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5502
 *
5503
 * @return array
5504
 *
5505
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5506
 */
5507
function get_forums_of_group($groupInfo)
5508
{
5509
    $table_forums = Database::get_course_table(TABLE_FORUM);
5510
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5511
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5512
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5513
    $course_id = api_get_course_int_id();
5514
    $groupId = (int) $groupInfo['id'];
5515
5516
    // Student
5517
    // Select all the forum information of all forums (that are visible to students).
5518
    $sql = "SELECT * FROM $table_forums forum 
5519
            INNER JOIN $table_item_property item_properties
5520
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5521
            WHERE
5522
                forum.forum_of_group = $groupId AND
5523
                forum.c_id = $course_id AND
5524
                item_properties.c_id = $course_id AND                
5525
                item_properties.visibility = 1 AND
5526
                item_properties.tool = '".TOOL_FORUM."'
5527
            ORDER BY forum.forum_order ASC";
5528
5529
    // Select the number of threads of the forums (only the threads that are visible).
5530
    $sql2 = "SELECT 
5531
                count(thread_id) AS number_of_threads, 
5532
                threads.forum_id
5533
            FROM $table_threads threads 
5534
            INNER JOIN $table_item_property item_properties
5535
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5536
            WHERE                
5537
                threads.c_id = $course_id AND
5538
                item_properties.c_id = $course_id AND
5539
                item_properties.visibility = 1 AND
5540
                item_properties.tool='".TOOL_FORUM_THREAD."'
5541
            GROUP BY threads.forum_id";
5542
5543
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5544
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5545
            FROM $table_posts posts 
5546
            INNER JOIN $table_threads threads 
5547
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5548
            INNER JOIN $table_item_property item_properties
5549
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5550
            WHERE 
5551
                posts.visible=1 AND
5552
                posts.c_id = $course_id AND
5553
                item_properties.c_id = $course_id AND
5554
                threads.c_id = $course_id AND 
5555
                item_properties.visibility = 1 AND 
5556
                item_properties.tool='".TOOL_FORUM_THREAD."'
5557
            GROUP BY threads.forum_id";
5558
5559
    // Course Admin
5560
    if (api_is_allowed_to_edit()) {
5561
        // Select all the forum information of all forums (that are not deleted).
5562
        $sql = "SELECT *
5563
                FROM $table_forums forum 
5564
                INNER JOIN $table_item_property item_properties
5565
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5566
                WHERE
5567
                    forum.forum_of_group = $groupId AND
5568
                    forum.c_id = $course_id AND
5569
                    item_properties.c_id = $course_id AND                    
5570
                    item_properties.visibility <> 2 AND
5571
                    item_properties.tool = '".TOOL_FORUM."'
5572
                ORDER BY forum_order ASC";
5573
5574
        // Select the number of threads of the forums (only the threads that are not deleted).
5575
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5576
                 FROM $table_threads threads 
5577
                 INNER JOIN $table_item_property item_properties
5578
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5579
                 WHERE
5580
                    threads.c_id = $course_id AND
5581
                    item_properties.c_id = $course_id AND
5582
                    item_properties.visibility <> 2 AND
5583
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5584
                GROUP BY threads.forum_id";
5585
        // Select the number of posts of the forum.
5586
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5587
                FROM $table_posts
5588
                WHERE c_id = $course_id 
5589
                GROUP BY forum_id";
5590
    }
5591
5592
    // Handling all the forum information.
5593
    $result = Database::query($sql);
5594
    $forum_list = [];
5595
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5596
        $forum_list[$row['forum_id']] = $row;
5597
    }
5598
5599
    // Handling the thread count information.
5600
    $result2 = Database::query($sql2);
5601
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5602
        if (is_array($forum_list)) {
5603
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5604
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5605
            }
5606
        }
5607
    }
5608
5609
    // Handling the post count information.
5610
    $result3 = Database::query($sql3);
5611
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5612
        if (is_array($forum_list)) {
5613
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5614
                // This is needed because sql3 takes also the deleted forums into account.
5615
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5616
            }
5617
        }
5618
    }
5619
5620
    // Finding the last post information
5621
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5622
    if (!empty($forum_list)) {
5623
        foreach ($forum_list as $key => $value) {
5624
            $lastPost = get_last_post_information($key, api_is_allowed_to_edit());
5625
            if ($lastPost) {
5626
                $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
5627
                $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
5628
                $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
5629
                $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
5630
                $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
5631
                $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
5632
            }
5633
        }
5634
    }
5635
5636
    return $forum_list;
5637
}
5638
5639
/**
5640
 * This function stores which users have to be notified of which forums or threads.
5641
 *
5642
 * @param string $content    does the user want to be notified about a forum or about a thread
5643
 * @param int    $id         the id of the forum or thread
5644
 * @param bool   $addOnly
5645
 * @param array  $userInfo
5646
 * @param array  $courseInfo
5647
 *
5648
 * @return string language variable
5649
 *
5650
 * @author  Patrick Cool <[email protected]>, Ghent University, Belgium
5651
 * @author  Julio Montoya
5652
 *
5653
 * @since   May 2008 v1.8.5
5654
 */
5655
function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
5656
{
5657
    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
5658
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
5659
    $id = (int) $id;
5660
5661
    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
5662
        return false;
5663
    }
5664
5665
    // Database table definition
5666
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5667
5668
    $course_id = $courseInfo['real_id'];
5669
5670
    // Which database field do we have to store the id in?
5671
    $field = 'thread_id';
5672
    if ($content === 'forum') {
5673
        $field = 'forum_id';
5674
    }
5675
5676
    $userId = $userInfo['user_id'];
5677
5678
    // First we check if the notification is already set for this.
5679
    $sql = "SELECT * FROM $table_notification
5680
            WHERE
5681
                c_id = $course_id AND
5682
                $field = $id AND
5683
                user_id = $userId ";
5684
    $result = Database::query($sql);
5685
    $total = Database::num_rows($result);
5686
5687
    // If the user did not indicate that (s)he wanted to be notified already
5688
    // then we store the notification request (to prevent double notification requests).
5689
    if ($total <= 0) {
5690
        $sql = "INSERT INTO $table_notification (c_id, $field, user_id)
5691
                VALUES ($course_id, '$id','$userId')";
5692
        Database::query($sql);
5693
        Session::erase('forum_notification');
5694
        getNotificationsPerUser(0, true);
5695
5696
        return get_lang('YouWillBeNotifiedOfNewPosts');
5697
    } else {
5698
        if (!$addOnly) {
5699
            $sql = "DELETE FROM $table_notification
5700
                    WHERE
5701
                        c_id = $course_id AND
5702
                        $field = $id AND
5703
                        user_id = $userId ";
5704
            Database::query($sql);
5705
            Session::erase('forum_notification');
5706
            getNotificationsPerUser(0, true);
5707
5708
            return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
5709
        }
5710
    }
5711
}
5712
5713
/**
5714
 * This function retrieves all the email adresses of the users who wanted to be notified
5715
 * about a new post in a certain forum or thread.
5716
 *
5717
 * @param string $content does the user want to be notified about a forum or about a thread
5718
 * @param int    $id      the id of the forum or thread
5719
 *
5720
 * @return array returns
5721
 *
5722
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5723
 * @author Julio Montoya
5724
 *
5725
 * @version May 2008, dokeos 1.8.5
5726
 *
5727
 * @since May 2008, dokeos 1.8.5
5728
 */
5729
function get_notifications($content, $id)
5730
{
5731
    // Database table definition
5732
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5733
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5734
    $course_id = api_get_course_int_id();
5735
5736
    // Which database field contains the notification?
5737
    $field = 'thread_id';
5738
    if ($content === 'forum') {
5739
        $field = 'forum_id';
5740
    }
5741
5742
    $id = (int) $id;
5743
5744
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
5745
            FROM $table_users user, $table_notification notification
5746
            WHERE 
5747
                notification.c_id = $course_id AND user.active = 1 AND
5748
                user.user_id = notification.user_id AND
5749
                notification.$field = $id ";
5750
5751
    $result = Database::query($sql);
5752
    $return = [];
5753
5754
    while ($row = Database::fetch_array($result)) {
5755
        $return['user'.$row['user_id']] = ['email' => $row['email'], 'user_id' => $row['user_id']];
5756
    }
5757
5758
    return $return;
5759
}
5760
5761
/**
5762
 * Get all the users who need to receive a notification of a new post (those subscribed to
5763
 * the forum or the thread).
5764
 *
5765
 * @param int $forum_id  the id of the forum
5766
 * @param int $thread_id the id of the thread
5767
 * @param int $post_id   the id of the post
5768
 *
5769
 * @return false|null
5770
 *
5771
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5772
 *
5773
 * @version May 2008, dokeos 1.8.5
5774
 *
5775
 * @since May 2008, dokeos 1.8.5
5776
 */
5777
function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
5778
{
5779
    $forum_id = (int) $forum_id;
5780
    // Users who subscribed to the forum
5781
    if ($forum_id != 0) {
5782
        $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
5783
    } else {
5784
        return false;
5785
    }
5786
5787
    $current_thread = get_thread_information($forum_id, $thread_id);
5788
5789
    // User who subscribed to the thread
5790
    if ($thread_id != 0) {
5791
        $users_to_be_notified_by_thread = get_notifications('thread', $thread_id);
5792
    }
5793
5794
    $postInfo = [];
5795
    if (!empty($post_id)) {
5796
        $postInfo = get_post_information($post_id);
5797
    }
5798
5799
    // Merging the two
5800
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
5801
    $forumInfo = get_forum_information($forum_id);
5802
5803
    if (is_array($users_to_be_notified)) {
5804
        foreach ($users_to_be_notified as $value) {
5805
            $userInfo = api_get_user_info($value['user_id']);
5806
            send_mail($userInfo, $forumInfo, $current_thread, $postInfo);
5807
        }
5808
    }
5809
}
5810
5811
/**
5812
 * Get all the notification subscriptions of the user
5813
 * = which forums and which threads does the user wants to be informed of when a new
5814
 * post is added to this thread.
5815
 *
5816
 * @param int  $user_id the user_id of a user (default = 0 => the current user)
5817
 * @param bool $force   force get the notification subscriptions (even if the information is already in the session
5818
 *
5819
 * @return array
5820
 *
5821
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5822
 *
5823
 * @version May 2008, dokeos 1.8.5
5824
 *
5825
 * @since May 2008, dokeos 1.8.5
5826
 */
5827
function getNotificationsPerUser($user_id = 0, $force = false, $course_id = 0)
5828
{
5829
    // Database table definition
5830
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5831
    $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
5832
    if (empty($course_id) || $course_id == -1) {
5833
        return null;
5834
    }
5835
5836
    $user_id = empty($user_id) ? api_get_user_id() : (int) $user_id;
5837
5838
    if (!isset($_SESSION['forum_notification']) ||
5839
        $_SESSION['forum_notification']['course'] != $course_id ||
5840
        $force == true
5841
    ) {
5842
        $_SESSION['forum_notification']['course'] = $course_id;
5843
        $sql = "SELECT * FROM $table_notification
5844
                WHERE c_id = $course_id AND user_id='".$user_id."'";
5845
5846
        $result = Database::query($sql);
5847
        while ($row = Database::fetch_array($result)) {
5848
            if (!is_null($row['forum_id'])) {
5849
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5850
            }
5851
            if (!is_null($row['thread_id'])) {
5852
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5853
            }
5854
        }
5855
    }
5856
}
5857
5858
/**
5859
 * This function counts the number of post inside a thread.
5860
 *
5861
 * @param int $thread_id
5862
 *
5863
 * @return int the number of post inside a thread
5864
 *
5865
 * @author Jhon Hinojosa <[email protected]>,
5866
 *
5867
 * @version octubre 2008, dokeos 1.8
5868
 */
5869
function count_number_of_post_in_thread($thread_id)
5870
{
5871
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5872
    $course_id = api_get_course_int_id();
5873
    if (empty($course_id)) {
5874
        return 0;
5875
    }
5876
    $sql = "SELECT count(*) count FROM $table_posts
5877
            WHERE 
5878
                c_id = $course_id AND 
5879
                thread_id='".intval($thread_id)."' ";
5880
    $result = Database::query($sql);
5881
5882
    $count = 0;
5883
    if (Database::num_rows($result) > 0) {
5884
        $row = Database::fetch_array($result);
5885
        $count = $row['count'];
5886
    }
5887
5888
    return $count;
5889
}
5890
5891
/**
5892
 * This function counts the number of post inside a thread user.
5893
 *
5894
 * @param int $thread_id
5895
 * @param int $user_id
5896
 *
5897
 * @return int the number of post inside a thread user
5898
 */
5899
function count_number_of_post_for_user_thread($thread_id, $user_id)
5900
{
5901
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5902
    $course_id = api_get_course_int_id();
5903
    $sql = "SELECT count(iid) as count 
5904
            FROM $table_posts
5905
            WHERE c_id = $course_id AND
5906
                  thread_id=".intval($thread_id)." AND
5907
                  poster_id = ".intval($user_id)." AND visible = 1 ";
5908
    $result = Database::query($sql);
5909
    $count = 0;
5910
    if (Database::num_rows($result) > 0) {
5911
        $count = Database::fetch_array($result);
5912
        $count = $count['count'];
5913
    }
5914
5915
    return $count;
5916
}
5917
5918
/**
5919
 * This function retrieves information of statistical.
5920
 *
5921
 * @param int $thread_id
5922
 * @param int $user_id
5923
 * @param int $course_id
5924
 *
5925
 * @return array the information of statistical
5926
 *
5927
 * @author Jhon Hinojosa <[email protected]>,
5928
 *
5929
 * @version oct 2008, dokeos 1.8
5930
 */
5931
function get_statistical_information($thread_id, $user_id, $course_id)
5932
{
5933
    $result = [];
5934
    $courseInfo = api_get_course_info_by_id($course_id);
5935
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
5936
    $result['post'] = count_number_of_post_in_thread($thread_id);
5937
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
5938
5939
    return $result;
5940
}
5941
5942
/**
5943
 * This function return the posts inside a thread from a given user.
5944
 *
5945
 * @param string $course_code
5946
 * @param int    $thread_id
5947
 * @param int    $user_id
5948
 *
5949
 * @return array posts inside a thread
5950
 *
5951
 * @author Jhon Hinojosa <[email protected]>,
5952
 *
5953
 * @version oct 2008, dokeos 1.8
5954
 */
5955
function get_thread_user_post($course_code, $thread_id, $user_id)
5956
{
5957
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5958
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5959
    $thread_id = intval($thread_id);
5960
    $user_id = intval($user_id);
5961
    $course_info = api_get_user_info($course_code);
5962
    $course_id = $course_info['real_id'];
5963
5964
    if (empty($course_id)) {
5965
        $course_id = api_get_course_int_id();
5966
    }
5967
    $sql = "SELECT * FROM $table_posts posts
5968
            LEFT JOIN  $table_users users
5969
                ON posts.poster_id=users.user_id
5970
            WHERE
5971
                posts.c_id = $course_id AND
5972
                posts.thread_id='$thread_id'
5973
                AND posts.poster_id='$user_id'
5974
            ORDER BY posts.post_id ASC";
5975
5976
    $result = Database::query($sql);
5977
    $post_list = [];
5978
    while ($row = Database::fetch_array($result)) {
5979
        $row['status'] = '1';
5980
        $post_list[] = $row;
5981
        $sql = "SELECT * FROM $table_posts posts
5982
                LEFT JOIN $table_users users
5983
                ON (posts.poster_id=users.user_id)
5984
                WHERE
5985
                    posts.c_id = $course_id AND
5986
                    posts.thread_id='$thread_id'
5987
                    AND posts.post_parent_id='".$row['post_id']."'
5988
                ORDER BY posts.post_id ASC";
5989
        $result2 = Database::query($sql);
5990
        while ($row2 = Database::fetch_array($result2)) {
5991
            $row2['status'] = '0';
5992
            $post_list[] = $row2;
5993
        }
5994
    }
5995
5996
    return $post_list;
5997
}
5998
5999
/**
6000
 * This function get the name of an thread by id.
6001
 *
6002
 * @param int thread_id
6003
 *
6004
 * @return string
6005
 *
6006
 * @author Christian Fasanando
6007
 * @author Julio Montoya <[email protected]> Adding security
6008
 */
6009
function get_name_thread_by_id($thread_id)
6010
{
6011
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
6012
    $course_id = api_get_course_int_id();
6013
    $sql = "SELECT thread_title 
6014
            FROM $t_forum_thread
6015
            WHERE c_id = $course_id AND thread_id = '".intval($thread_id)."' ";
6016
    $result = Database::query($sql);
6017
    $row = Database::fetch_array($result);
6018
6019
    return $row[0];
6020
}
6021
6022
/**
6023
 * This function gets all the post written by an user.
6024
 *
6025
 * @param int    $user_id
6026
 * @param string $course_code
6027
 *
6028
 * @return string
6029
 */
6030
function get_all_post_from_user($user_id, $course_code)
6031
{
6032
    $j = 0;
6033
    $forums = get_forums('', $course_code);
6034
    krsort($forums);
6035
    $forum_results = '';
6036
6037
    foreach ($forums as $forum) {
6038
        if ($forum['visibility'] == 0) {
6039
            continue;
6040
        }
6041
        if ($j <= 4) {
6042
            $threads = get_threads($forum['forum_id']);
6043
6044
            if (is_array($threads)) {
6045
                $i = 0;
6046
                $hand_forums = '';
6047
                $post_counter = 0;
6048
                foreach ($threads as $thread) {
6049
                    if ($thread['visibility'] == 0) {
6050
                        continue;
6051
                    }
6052
                    if ($i <= 4) {
6053
                        $post_list = get_thread_user_post_limit(
6054
                            $course_code,
6055
                            $thread['thread_id'],
6056
                            $user_id,
6057
                            1
6058
                        );
6059
                        $post_counter = count($post_list);
6060
                        if (is_array($post_list) && count($post_list) > 0) {
6061
                            $hand_forums .= '<div id="social-thread">';
6062
                            $hand_forums .= Display::return_icon(
6063
                                'thread.png',
6064
                                get_lang('Thread'),
6065
                                '',
6066
                                ICON_SIZE_MEDIUM
6067
                            );
6068
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
6069
                            $hand_forums .= '</div>';
6070
6071
                            foreach ($post_list as $posts) {
6072
                                $hand_forums .= '<div id="social-post">';
6073
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
6074
                                $hand_forums .= '<br / >';
6075
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
6076
                                $hand_forums .= '</div>';
6077
                                $hand_forums .= '<br / >';
6078
                            }
6079
                        }
6080
                    }
6081
                    $i++;
6082
                }
6083
                $forum_results .= '<div id="social-forum">';
6084
                $forum_results .= '<div class="clear"></div><br />';
6085
                $forum_results .= '<div id="social-forum-title">'.
6086
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
6087
                    '<div style="float:right;margin-top:-35px">
6088
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
6089
                    get_lang('SeeForum').'    
6090
                        </a>
6091
                     </div></div>';
6092
                $forum_results .= '<br / >';
6093
                if ($post_counter > 0) {
6094
                    $forum_results .= $hand_forums;
6095
                }
6096
                $forum_results .= '</div>';
6097
            }
6098
            $j++;
6099
        }
6100
    }
6101
6102
    return $forum_results;
6103
}
6104
6105
/**
6106
 * @param string $course_code
6107
 * @param int    $thread_id
6108
 * @param int    $user_id
6109
 * @param int    $limit
6110
 *
6111
 * @return array
6112
 */
6113
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
6114
{
6115
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6116
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6117
6118
    $course_info = api_get_course_info($course_code);
6119
    $course_id = $course_info['real_id'];
6120
6121
    $sql = "SELECT * FROM $table_posts posts
6122
            LEFT JOIN  $table_users users
6123
                ON posts.poster_id=users.user_id
6124
            WHERE
6125
                posts.c_id = $course_id AND
6126
                posts.thread_id='".Database::escape_string($thread_id)."' AND 
6127
                posts.poster_id='".Database::escape_string($user_id)."'
6128
            ORDER BY posts.post_id DESC LIMIT $limit ";
6129
    $result = Database::query($sql);
6130
    $post_list = [];
6131
    while ($row = Database::fetch_array($result)) {
6132
        $row['status'] = '1';
6133
        $post_list[] = $row;
6134
    }
6135
6136
    return $post_list;
6137
}
6138
6139
/**
6140
 * @param string $userId
6141
 * @param array  $courseInfo
6142
 * @param int    $sessionId
6143
 *
6144
 * @return array
6145
 */
6146
function getForumCreatedByUser($userId, $courseInfo, $sessionId)
6147
{
6148
    if (empty($userId) || empty($courseInfo)) {
6149
        return [];
6150
    }
6151
6152
    $courseId = $courseInfo['real_id'];
6153
    $items = api_get_item_property_list_by_tool_by_user(
6154
        $userId,
6155
        'forum',
6156
        $courseId,
6157
        $sessionId
6158
    );
6159
6160
    $forumList = [];
6161
    if (!empty($items)) {
6162
        foreach ($items as $forum) {
6163
            $forumInfo = get_forums(
6164
                $forum['ref'],
6165
                $courseInfo['code'],
6166
                true,
6167
                $sessionId
6168
            );
6169
            if (!empty($forumInfo) && isset($forumInfo['forum_title'])) {
6170
                $forumList[] = [
6171
                    $forumInfo['forum_title'],
6172
                    api_get_local_time($forum['insert_date']),
6173
                    api_get_local_time($forum['lastedit_date']),
6174
                ];
6175
            }
6176
        }
6177
    }
6178
6179
    return $forumList;
6180
}
6181
6182
/**
6183
 * This function builds an array of all the posts in a given thread
6184
 * where the key of the array is the post_id
6185
 * It also adds an element children to the array which itself is an array
6186
 * that contains all the id's of the first-level children.
6187
 *
6188
 * @return array $rows containing all the information on the posts of a thread
6189
 *
6190
 * @author Patrick Cool <[email protected]>, Ghent University
6191
 */
6192
function calculate_children($rows)
6193
{
6194
    $sorted_rows = [0 => []];
6195
    if (!empty($rows)) {
6196
        foreach ($rows as $row) {
6197
            $rows_with_children[$row['post_id']] = $row;
6198
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
6199
        }
6200
6201
        $rows = $rows_with_children;
6202
        forumRecursiveSort($rows, $sorted_rows);
6203
        unset($sorted_rows[0]);
6204
    }
6205
6206
    return $sorted_rows;
6207
}
6208
6209
/**
6210
 * @param $rows
6211
 * @param $threads
6212
 * @param int $seed
6213
 * @param int $indent
6214
 */
6215
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
6216
{
6217
    if ($seed > 0) {
6218
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
6219
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
6220
        $indent++;
6221
    }
6222
6223
    if (isset($rows[$seed]['children'])) {
6224
        foreach ($rows[$seed]['children'] as $child) {
6225
            forumRecursiveSort($rows, $threads, $child, $indent);
6226
        }
6227
    }
6228
}
6229
6230
/**
6231
 * Update forum attachment data, used to update comment and post ID.
6232
 *
6233
 * @param $array array (field => value) to update forum attachment row
6234
 * @param $id attach ID to find row to update
6235
 * @param null $courseId course ID to find row to update
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $courseId is correct as it would always require null to be passed?
Loading history...
6236
 *
6237
 * @return int number of affected rows
6238
 */
6239
function editAttachedFile($array, $id, $courseId = null)
6240
{
6241
    // Init variables
6242
    $setString = '';
6243
    $id = (int) $id;
6244
    $courseId = (int) $courseId;
6245
    if (empty($courseId)) {
6246
        // $courseId can be null, use api method
6247
        $courseId = api_get_course_int_id();
6248
    }
6249
    /*
6250
     * Check if Attachment ID and Course ID are greater than zero
6251
     * and array of field values is not empty
6252
     */
6253
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
6254
        foreach ($array as $key => &$item) {
6255
            $item = Database::escape_string($item);
6256
            $setString .= $key.' = "'.$item.'", ';
6257
        }
6258
        // Delete last comma
6259
        $setString = substr($setString, 0, strlen($setString) - 2);
6260
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6261
        $sql = "UPDATE $forumAttachmentTable 
6262
                SET $setString WHERE c_id = $courseId AND id = $id";
6263
        $result = Database::query($sql);
6264
        if ($result !== false) {
6265
            $affectedRows = Database::affected_rows($result);
6266
            if ($affectedRows > 0) {
6267
                /*
6268
                 * If exist in $_SESSION variable, then delete them from it
6269
                 * because they would be deprecated
6270
                 */
6271
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
6272
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
6273
                }
6274
            }
6275
6276
            return $affectedRows;
6277
        }
6278
    }
6279
6280
    return 0;
6281
}
6282
6283
/**
6284
 * Return a table where the attachments will be set.
6285
 *
6286
 * @param int $postId Forum Post ID
6287
 *
6288
 * @return string The Forum Attachments Ajax Table
6289
 */
6290
function getAttachmentsAjaxTable($postId = 0)
6291
{
6292
    $postId = (int) $postId;
6293
    $courseId = api_get_course_int_id();
6294
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6295
    $fileDataContent = '';
6296
    // Update comment to show if form did not pass validation
6297
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
6298
        // 'file_ids is the name from forum attachment ajax form
6299
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
6300
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
6301
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
6302
            ) {
6303
                // If exist forum attachment then update into $_SESSION data
6304
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
6305
            }
6306
        }
6307
    }
6308
6309
    // Get data to fill into attachment files table
6310
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6311
        is_array($_SESSION['forum']['upload_file'][$courseId])
6312
    ) {
6313
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
6314
        foreach ($uploadedFiles as $k => $uploadedFile) {
6315
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
6316
                // Buil html table including an input with attachmentID
6317
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
6318
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
6319
                    $uploadedFile['delete'].'</td>'.
6320
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
6321
            } else {
6322
                /*
6323
                 * If attachment data is empty, then delete it from $_SESSION
6324
                 * because could generate and empty row into html table
6325
                 */
6326
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
6327
            }
6328
        }
6329
    }
6330
    $style = empty($fileDataContent) ? 'display: none;' : '';
6331
    // Forum attachment Ajax table
6332
    $fileData = '
6333
    <div class="control-group " style="'.$style.'">
6334
        <label class="control-label">'.get_lang('AttachmentList').'</label>
6335
        <div class="controls">
6336
            <table id="attachmentFileList" class="files data_table span10">
6337
                <tr>
6338
                    <th>'.get_lang('FileName').'</th>
6339
                    <th>'.get_lang('Size').'</th>
6340
                    <th>'.get_lang('Status').'</th>
6341
                    <th>'.get_lang('Comment').'</th>
6342
                    <th>'.get_lang('Delete').'</th>
6343
                </tr>
6344
                '.$fileDataContent.'
6345
            </table>
6346
        </div>
6347
    </div>';
6348
6349
    return $fileData;
6350
}
6351
6352
/**
6353
 * Return an array of prepared attachment data to build forum attachment table
6354
 * Also, save this array into $_SESSION to do available the attachment data.
6355
 *
6356
 * @param int $forumId
6357
 * @param int $threadId
6358
 * @param int $postId
6359
 * @param int $attachId
6360
 * @param int $courseId
6361
 *
6362
 * @return array
6363
 */
6364
function getAttachedFiles(
6365
    $forumId,
6366
    $threadId,
6367
    $postId = 0,
6368
    $attachId = 0,
6369
    $courseId = 0
6370
) {
6371
    $forumId = (int) $forumId;
6372
    $courseId = (int) $courseId;
6373
    $attachId = (int) $attachId;
6374
    $postId = (int) $postId;
6375
    $threadId = !empty($threadId) ? intval($threadId) : isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : '';
6376
    if (empty($courseId)) {
6377
        // $courseId can be null, use api method
6378
        $courseId = api_get_course_int_id();
6379
    }
6380
    if (empty($forumId)) {
6381
        if (!empty($_REQUEST['forum'])) {
6382
            $forumId = (int) $_REQUEST['forum'];
6383
        } else {
6384
            // if forum ID is empty, cannot generate delete url
6385
6386
            return [];
6387
        }
6388
    }
6389
    // Check if exist at least one of them to filter forum attachment select query
6390
    if (empty($postId) && empty($attachId)) {
6391
        return [];
6392
    } elseif (empty($postId)) {
6393
        $filter = "AND iid = $attachId";
6394
    } elseif (empty($attachId)) {
6395
        $filter = "AND post_id = $postId";
6396
    } else {
6397
        $filter = "AND post_id = $postId AND iid = $attachId";
6398
    }
6399
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6400
    $sql = "SELECT iid, comment, filename, path, size
6401
            FROM $forumAttachmentTable
6402
            WHERE c_id = $courseId $filter";
6403
    $result = Database::query($sql);
6404
    $json = [];
6405
    if ($result !== false && Database::num_rows($result) > 0) {
6406
        while ($row = Database::fetch_array($result, 'ASSOC')) {
6407
            // name contains an URL to download attachment file and its filename
6408
            $json['name'] = Display::url(
6409
                api_htmlentities($row['filename']),
6410
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
6411
                ['target' => '_blank', 'class' => 'attachFilename']
6412
            );
6413
            $json['id'] = $row['iid'];
6414
            $json['comment'] = $row['comment'];
6415
            // Format file size
6416
            $json['size'] = format_file_size($row['size']);
6417
            // Check if $row is consistent
6418
            if (!empty($row) && is_array($row)) {
6419
                // Set result as success and bring delete URL
6420
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded'));
6421
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
6422
                $json['delete'] = Display::url(
6423
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
6424
                    $url,
6425
                    ['class' => 'deleteLink']
6426
                );
6427
            } else {
6428
                // If not, set an exclamation result
6429
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
6430
            }
6431
            // Store array data into $_SESSION
6432
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
6433
        }
6434
    }
6435
6436
    return $json;
6437
}
6438
6439
/**
6440
 * Clear forum attachment data stored in $_SESSION,
6441
 * If is not defined post, it will clear all forum attachment data from course.
6442
 *
6443
 * @param int $postId   -1 : Clear all attachments from course stored in $_SESSION
6444
 *                      0 : Clear attachments from course, except from temporal post "0"
6445
 *                      but without delete them from file system and database
6446
 *                      Other values : Clear attachments from course except specified post
6447
 *                      and delete them from file system and database
6448
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
6449
 *
6450
 * @return array
6451
 */
6452
function clearAttachedFiles($postId = 0, $courseId = 0)
6453
{
6454
    // Init variables
6455
    $courseId = (int) $courseId;
6456
    $postId = (int) $postId;
6457
    $array = [];
6458
    if (empty($courseId)) {
6459
        // $courseId can be null, use api method
6460
        $courseId = api_get_course_int_id();
6461
    }
6462
    if ($postId === -1) {
6463
        // If post ID is -1 then delete course's attachment data from $_SESSION
6464
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
6465
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
6466
            unset($_SESSION['forum']['upload_file'][$courseId]);
6467
        }
6468
    } else {
6469
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6470
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6471
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
6472
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
6473
                if (!in_array($attachId, $attachIds)) {
6474
                    // If attach ID is not into specified post, delete attachment
6475
                    // Save deleted attachment ID
6476
                    $array[] = $attachId;
6477
                    if ($postId !== 0) {
6478
                        // Post 0 is temporal, delete them from file system and DB
6479
                        delete_attachment(0, $attachId);
6480
                    }
6481
                    // Delete attachment data from $_SESSION
6482
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
6483
                }
6484
            }
6485
        }
6486
    }
6487
6488
    return $array;
6489
}
6490
6491
/**
6492
 * Returns an array of forum attachment ids into a course and forum post.
6493
 *
6494
 * @param int $postId
6495
 * @param int $courseId
6496
 *
6497
 * @return array
6498
 */
6499
function getAttachmentIdsByPostId($postId, $courseId = 0)
6500
{
6501
    $array = [];
6502
    $courseId = (int) $courseId;
6503
    $postId = (int) $postId;
6504
    if (empty($courseId)) {
6505
        // $courseId can be null, use api method
6506
        $courseId = api_get_course_int_id();
6507
    }
6508
    if ($courseId > 0) {
6509
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6510
        $sql = "SELECT id FROM $forumAttachmentTable
6511
                WHERE c_id = $courseId AND post_id = $postId";
6512
        $result = Database::query($sql);
6513
        if ($result !== false && Database::num_rows($result) > 0) {
6514
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6515
                $array[] = $row['id'];
6516
            }
6517
        }
6518
    }
6519
6520
    return $array;
6521
}
6522
6523
/**
6524
 * Check if the forum category exists looking for its title.
6525
 *
6526
 * @param string $title     The forum category title
6527
 * @param int    $courseId  The course ID
6528
 * @param int    $sessionId Optional. The session ID
6529
 *
6530
 * @return bool
6531
 */
6532
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6533
{
6534
    $sessionId = (int) $sessionId;
6535
    $courseId = (int) $courseId;
6536
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6537
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6538
6539
    $fakeFrom = "$forumCategoryTable fc
6540
        INNER JOIN $itemProperty ip ";
6541
6542
    if ($sessionId === 0) {
6543
        $fakeFrom .= "
6544
            ON (
6545
                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)
6546
            )
6547
        ";
6548
    } else {
6549
        $fakeFrom .= "
6550
            ON (
6551
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6552
            )
6553
        ";
6554
    }
6555
6556
    $resultData = Database::select(
6557
        'fc.*',
6558
        $fakeFrom,
6559
        [
6560
            'where' => [
6561
                'ip.visibility != ? AND ' => 2,
6562
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6563
                'fc.session_id = ? AND ' => $sessionId,
6564
                'fc.cat_title = ? AND ' => $title,
6565
                'fc.c_id = ?' => $courseId,
6566
            ],
6567
        ],
6568
        'first'
6569
    );
6570
6571
    if (empty($resultData)) {
6572
        return false;
6573
    }
6574
6575
    return $resultData;
6576
}
6577
6578
/**
6579
 * @param array $current_forum
6580
 * @param array $row
6581
 * @param bool  $addWrapper
6582
 *
6583
 * @return string
6584
 */
6585
function getPostStatus($current_forum, $row, $addWrapper = true)
6586
{
6587
    $statusIcon = '';
6588
    if ($current_forum['moderated']) {
6589
        if ($addWrapper) {
6590
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6591
        }
6592
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6593
6594
        $addUrl = false;
6595
        $showStatus = false;
6596
        if (api_is_allowed_to_edit(false, true)) {
6597
            $addUrl = true;
6598
        } else {
6599
            if ($row['user_id'] == api_get_user_id()) {
6600
                $showStatus = true;
6601
            }
6602
        }
6603
6604
        $label = '';
6605
        $icon = '';
6606
        $buttonType = '';
6607
        switch ($row['status']) {
6608
            case CForumPost::STATUS_VALIDATED:
6609
                $label = get_lang('Validated');
6610
                $icon = 'check-circle';
6611
                $buttonType = 'success';
6612
                break;
6613
            case CForumPost::STATUS_WAITING_MODERATION:
6614
                $label = get_lang('WaitingModeration');
6615
                $icon = 'warning';
6616
                $buttonType = 'warning';
6617
                break;
6618
            case CForumPost::STATUS_REJECTED:
6619
                $label = get_lang('Rejected');
6620
                $icon = 'minus-circle';
6621
                $buttonType = 'danger';
6622
                break;
6623
        }
6624
6625
        if ($addUrl) {
6626
            $statusIcon .= Display::toolbarButton(
6627
                $label.'&nbsp;',
6628
                'javascript:void(0)',
6629
                $icon,
6630
                $buttonType,
6631
                ['class' => 'change_post_status']
6632
            );
6633
        } else {
6634
            if ($showStatus) {
6635
                $statusIcon .= Display::label(
6636
                    Display::returnFontAwesomeIcon($icon).$label,
6637
                    $buttonType
6638
                );
6639
            }
6640
        }
6641
6642
        if ($addWrapper) {
6643
            $statusIcon .= '</span>';
6644
        }
6645
    }
6646
6647
    return $statusIcon;
6648
}
6649
6650
/**
6651
 * @param array $forumInfo
6652
 * @param int   $threadId
6653
 * @param int   $status
6654
 *
6655
 * @return mixed
6656
 */
6657
function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
6658
{
6659
    $em = Database::getManager();
6660
    $criteria = Criteria::create();
6661
    $criteria
6662
        ->where(Criteria::expr()->eq('status', $status))
6663
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
6664
        ->andWhere(Criteria::expr()->eq('visible', 1))
6665
    ;
6666
6667
    if (!empty($threadId)) {
6668
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6669
    }
6670
6671
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6672
    $qb->select('count(p.iid)')
6673
        ->addCriteria($criteria);
6674
6675
    return $qb->getQuery()->getSingleScalarResult();
6676
}
6677
6678
/**
6679
 * @param array $forum
6680
 * @param array $post
6681
 *
6682
 * @return bool
6683
 */
6684
function postIsEditableByStudent($forum, $post)
6685
{
6686
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6687
        return true;
6688
    }
6689
6690
    if ($forum['moderated'] == 1) {
6691
        if (is_null($post['status'])) {
6692
            return true;
6693
        } else {
6694
            return in_array(
6695
                $post['status'],
6696
                [
6697
                    CForumPost::STATUS_WAITING_MODERATION,
6698
                    CForumPost::STATUS_REJECTED,
6699
                ]
6700
            );
6701
        }
6702
    } else {
6703
        return true;
6704
    }
6705
}
6706
6707
/**
6708
 * @param int $postId
6709
 *
6710
 * @return bool
6711
 */
6712
function savePostRevision($postId)
6713
{
6714
    $postData = get_post_information($postId);
6715
6716
    if (empty($postData)) {
6717
        return false;
6718
    }
6719
6720
    $userId = api_get_user_id();
6721
6722
    if ($postData['poster_id'] != $userId) {
6723
        return false;
6724
    }
6725
6726
    $status = (int) !postNeedsRevision($postId);
6727
    $extraFieldValue = new ExtraFieldValue('forum_post');
6728
    $params = [
6729
        'item_id' => $postId,
6730
        'extra_ask_for_revision' => ['extra_ask_for_revision' => $status],
6731
    ];
6732
    if (empty($status)) {
6733
        unset($params['extra_ask_for_revision']);
6734
    }
6735
    $extraFieldValue->saveFieldValues(
6736
        $params,
6737
        true,
6738
        false,
6739
        ['ask_for_revision']
6740
    );
6741
}
6742
6743
/**
6744
 * @param int $postId
6745
 *
6746
 * @return string
6747
 */
6748
function getPostRevision($postId)
6749
{
6750
    $extraFieldValue = new ExtraFieldValue('forum_post');
6751
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6752
        $postId,
6753
        'revision_language'
6754
    );
6755
    $revision = '';
6756
    if ($value && isset($value['value'])) {
6757
        $revision = $value['value'];
6758
    }
6759
6760
    return $revision;
6761
}
6762
6763
/**
6764
 * @param int $postId
6765
 *
6766
 * @return bool
6767
 */
6768
function postNeedsRevision($postId)
6769
{
6770
    $extraFieldValue = new ExtraFieldValue('forum_post');
6771
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6772
        $postId,
6773
        'ask_for_revision'
6774
    );
6775
    $hasRevision = false;
6776
    if ($value && isset($value['value'])) {
6777
        return $value['value'] == 1;
6778
    }
6779
6780
    return $hasRevision;
6781
}
6782
6783
/**
6784
 * @param int   $postId
6785
 * @param array $threadInfo
6786
 *
6787
 * @return string
6788
 */
6789
function getAskRevisionButton($postId, $threadInfo)
6790
{
6791
    if (api_get_configuration_value('allow_forum_post_revisions') === false) {
6792
        return '';
6793
    }
6794
6795
    $postId = (int) $postId;
6796
6797
    $status = 'btn-default';
6798
    if (postNeedsRevision($postId)) {
6799
        $status = 'btn-success';
6800
    }
6801
6802
    return Display::url(
6803
        get_lang('AskRevision'),
6804
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6805
        api_get_cidreq().'&action=ask_revision&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6806
        ['class' => "btn $status", 'title' => get_lang('AskRevision')]
6807
    );
6808
}
6809
6810
/**
6811
 * @param int   $postId
6812
 * @param array $threadInfo
6813
 *
6814
 * @return string
6815
 */
6816
function giveRevisionButton($postId, $threadInfo)
6817
{
6818
    $postId = (int) $postId;
6819
6820
    return Display::toolbarButton(
6821
        get_lang('GiveRevision'),
6822
        api_get_path(WEB_CODE_PATH).'forum/reply.php?'.api_get_cidreq().'&'.http_build_query(
6823
            [
6824
                'forum' => $threadInfo['forum_id'],
6825
                'thread' => $threadInfo['thread_id'],
6826
                'post' => $postId = (int) $postId,
6827
                'action' => 'replymessage',
6828
                'give_revision' => 1,
6829
            ]
6830
        ),
6831
        'reply',
6832
        'primary',
6833
        ['id' => "reply-to-post-{$postId}"]
6834
    );
6835
}
6836
6837
/**
6838
 * @param int   $postId
6839
 * @param array $threadInfo
6840
 *
6841
 * @return string
6842
 */
6843
function getReportButton($postId, $threadInfo)
6844
{
6845
    $postId = (int) $postId;
6846
6847
    return Display::url(
6848
        Display::returnFontAwesomeIcon('flag'),
6849
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6850
        api_get_cidreq().'&action=report&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6851
        ['class' => 'btn btn-danger', 'title' => get_lang('Report')]
6852
    );
6853
}
6854
6855
/**
6856
 * @return bool
6857
 */
6858
function reportAvailable()
6859
{
6860
    $extraFieldValue = new ExtraFieldValue('course');
6861
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6862
        api_get_course_int_id(),
6863
        'allow_forum_report_button'
6864
    );
6865
    $allowReport = false;
6866
    if ($value && isset($value['value']) && $value['value'] == 1) {
6867
        $allowReport = true;
6868
    }
6869
6870
    return $allowReport;
6871
}
6872
6873
/**
6874
 * @return array
6875
 */
6876
function getReportRecipients()
6877
{
6878
    $extraFieldValue = new ExtraFieldValue('course');
6879
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6880
        api_get_course_int_id(),
6881
        'forum_report_recipients'
6882
    );
6883
    $users = [];
6884
    if ($value && isset($value['value'])) {
6885
        $usersType = explode(';', $value['value']);
6886
6887
        foreach ($usersType as $type) {
6888
            switch ($type) {
6889
                case 'teachers':
6890
                    $teachers = CourseManager::get_teacher_list_from_course_code(api_get_course_id());
6891
                    if (!empty($teachers)) {
6892
                        $users = array_merge($users, array_column($teachers, 'user_id'));
6893
                    }
6894
                break;
6895
                case 'admins':
6896
                    $admins = UserManager::get_all_administrators();
6897
                    if (!empty($admins)) {
6898
                        $users = array_merge($users, array_column($admins, 'user_id'));
6899
                    }
6900
                    break;
6901
                case 'community_managers':
6902
                    $managers = api_get_configuration_value('community_managers_user_list');
6903
                    if (!empty($managers) && isset($managers['users'])) {
6904
                        $users = array_merge($users, $managers['users']);
6905
                    }
6906
                    break;
6907
            }
6908
        }
6909
6910
        $users = array_unique(array_filter($users));
6911
    }
6912
6913
    return $users;
6914
}
6915
6916
/**
6917
 * @param int   $postId
6918
 * @param array $forumInfo
6919
 * @param array $threadInfo
6920
 *
6921
 * @return bool
6922
 */
6923
function reportPost($postId, $forumInfo, $threadInfo)
6924
{
6925
    if (!reportAvailable()) {
6926
        return false;
6927
    }
6928
6929
    if (empty($forumInfo) || empty($threadInfo)) {
6930
        return false;
6931
    }
6932
6933
    $postId = (int) $postId;
6934
6935
    $postData = get_post_information($postId);
6936
    $currentUser = api_get_user_info();
6937
6938
    if (!empty($postData)) {
6939
        $users = getReportRecipients();
6940
        if (!empty($users)) {
6941
            $url = api_get_path(WEB_CODE_PATH).
6942
                'forum/viewthread.php?forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'].'&'.api_get_cidreq().'&post_id='.$postId.'#post_id_'.$postId;
6943
            $postLink = Display::url(
6944
                $postData['post_title'],
6945
                $url
6946
            );
6947
            $subject = get_lang('ForumPostReported');
6948
            $content = sprintf(
6949
                get_lang('UserXReportedPostXInForumX'),
6950
                $currentUser['complete_name'],
6951
                $postLink,
6952
                $forumInfo['forum_title']
6953
            );
6954
            foreach ($users as $userId) {
6955
                MessageManager::send_message_simple($userId, $subject, $content);
6956
            }
6957
        }
6958
    }
6959
}
6960