Passed
Push — webservicelpcreate ( d8cb35 )
by
unknown
13:48
created

send_mail()   C

Complexity

Conditions 13
Paths 49

Size

Total Lines 54
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 36
nc 49
nop 4
dl 0
loc 54
rs 6.6166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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